/*********************************Start-set_io_async***************************/ /*This Function sets up a signal call back function '(*call_back)()' to be called asynchronously when I/O is available on the file descriptor 'fd'. The siganl system is set to restart if possible any system calls that are interrupted and to send the signal information data with the call back function 'call_back_func()'. (See sigaction() in Linux manuals.) This signal is blocked until we return or use the signal masking functions to change the signals blocking state. The signal call back function is retained until specifically changed(unlike when using 'signal()'.) Real Time signals are queued to a MAX depth set by the system. There are approximtely 32 RT signals available SIGRTMIN to SIGRTMAX. Input: wait: 0 => Set I/O mode non-blocking on file descriptor 'fd'. 1 => Set I/O mode blocking on file descriptor 'fd'. rt_sig_no: Real time signal number to use. If 'rt_sig_no' is less than SIGRTMIM or greater than SIGRTMAX the then signal queue depth reverts to '1' and the signal info structure may or may not apply. Specifically CYGWIN does not seem to offer a 'fcntl()' 'F_SETSIG' signal option, but does support signal information at least via 'sigqueue()'. Return: 0 => Success. -1 => Failure, global variable "errno" has error code. */ int set_io_async(int fd,void (*call_back)(int signum, siginfo_t *siginfo, void *ucontext),int rt_sig_no,u_char wait) { int flags; struct sigaction new_signal_handler; struct sigaction org_signal_handler; DBPRINTF(2,"set_io_async(fd=%d,call_back=%ul,rt_sig_no=%d,wait=%d)\n", fd,call_back,rt_sig_no,wait); /*Setup new signal handler struct.*/ new_signal_handler.sa_sigaction=call_back; sigemptyset(&new_signal_handler.sa_mask); new_signal_handler.sa_flags= SA_SIGINFO|SA_RESTART; /*Setup our signal handler.*/ if(sigaction(rt_sig_no,&new_signal_handler,&org_signal_handler)<0){ DBPRINTF(2,"sigaction() failed.\n"); return(-1); } # ifndef __CYGWIN__ /*Setup to use as a real time signal(signals are queue'd.)*/ if(fcntl(fd,F_SETSIG,rt_sig_no)<0){ DBPRINTF(2,"fcntl(F_SETSIG) failed.\n"); sigaction(rt_sig_no,&org_signal_handler,NULL);/*Restore old handler.*/ return(-1); } # endif /*Setup owner for async I/O.*/ if(fcntl(fd,F_SETOWN,getpid())<0){ DBPRINTF(2,"fcntl(F_SETOWN) failed.\n"); sigaction(rt_sig_no,&org_signal_handler,NULL);/*Restore old handler.*/ return(-1); } # ifdef __CYGWIN__ if((flags=fcntl(fd,F_GETFL,0))<0){ DBPRINTF(2,"fcntl(F_GETFL) failed.\n"); sigaction(rt_sig_no,&org_signal_handler,NULL);/*Restore old handler.*/ return(-1); } flags|=(wait)?(FASYNC):(FNDELAY|FASYNC); /*Allow asynchronous I/O signals and if wait mode set non-blocking I/O.*/ if(fcntl(fd,F_SETFL,flags)<0){ DBPRINTF(2,"fcntl(F_SETFL) failed.\n"); sigaction(rt_sig_no,&org_signal_handler,NULL);/*Restore old handler.*/ return(-1); } int set_state=1; if(ioctl(fd,FIOASYNC,&set_state)<0){ DBPRINTF(2,"ioctl(FIOASYNC) failed.\n"); sigaction(rt_sig_no,&org_signal_handler,NULL);/*Restore old handler.*/ return(-1); } # else /*Get current socket flags.*/ if((flags=fcntl(fd,F_GETFL,0))<0){ DBPRINTF(2,"fcntl(F_GETFL) failed.\n"); sigaction(rt_sig_no,&org_signal_handler,NULL);/*Restore old handler.*/ return(-1); } flags|=(wait)?(FASYNC):(FNDELAY|FASYNC); /*Allow receipt of asynchronous I/O signals and set non-blocking I/O.*/ if(fcntl(fd,F_SETFL,flags)<0){ DBPRINTF(2,"fcntl(F_SETFL) failed.\n"); sigaction(rt_sig_no,&org_signal_handler,NULL);/*Restore old handler.*/ return(-1); } #endif /*Good return.*/ return(0); } /**********************************End-set_io_async****************************/