/* ossig.c - convert SysV signals to keycode events Copyright 1990 Business Management Systems, Inc. Author: Stuart D. Gathman Without this module, signals that occur during Kgetc() cause a keystroke of EOF (-1). We have no control over what happens to signals that occur at any other time. This module causes a signal to *always* generate a keystroke. This module also works with multiple input file descriptors. Signal keystrokes are returned on the current or next call to Kgetc() - regardless of which input file is in use. System V signals have always been a pain to use for anything useful. Even "reliable" signals don't mix with other kinds of ipc, including read(). This module sets up a signal handler that sets O_NDELAY on the keyboard so that read() will return even if the signal occurs after mykey has checked for signals but before the read begins (in the call to savekey). In any case, all this nastiness is hidden away inside the Ksignal() function. */ #include #include #include #include "keyboard.h" static volatile int sawsig[NSIG], somesig; static void (*savesig[NSIG])(/**/ int /**/); static int (*savekey)(/**/ FILE * /**/); static int mykey(fp) FILE *fp; { register int rc; sawsig[0] = fileno(fp); /* make signals set O_NDELAY */ do { if (somesig) { /* try to minimize CPU overhead */ somesig = 0; for (rc = 1; rc < NSIG; ++rc) { if (sawsig[rc]) { sawsig[0] = EOF; sawsig[rc] = 0; somesig = 1; /* make sure we check signals again */ return KEY_SIG(rc); } } } rc = (*savekey)(fp); if (rc != EOF) { sawsig[0] = EOF; return rc; /* no signal came in */ } } while (sawsig[0] == EOF); return EOF; /* not one of our signals */ } static void trap(sig) { int fd; signal(sig,trap); somesig = sawsig[sig] = 1; fd = sawsig[0]; if (fd != EOF) { sawsig[0] = EOF; fcntl(fd,F_SETFL,O_NDELAY); } } void Ksignal(sig) { if (savekey == 0) { savekey = waitkey; waitkey = mykey; } savesig[sig] = signal(sig,trap); } /* This probably isn't needed, but untraps a signal, untrap all if sig==0 */ void Ksigend(sig) { if (sig) { signal(sig,savesig[sig]); savesig[sig] = 0; return; } for (sig = 1; sig < NSIG; ++sig) if (savesig[sig]) Ksigend(sig); waitkey = savekey; savekey = 0; }