|
|
1.1 ! root 1: /* ! 2: * Routines dealing with signals. ! 3: * ! 4: * A signal usually merely causes a bit to be set in the "signals" word. ! 5: * At some convenient time, the mainline code checks to see if any ! 6: * signals need processing by calling psignal(). ! 7: * An exception is made if we are reading from the keyboard when the ! 8: * signal is received. Some operating systems will simply call the ! 9: * signal handler and NOT return from the read (with EINTR). ! 10: * To handle this case, we service the interrupt directly from ! 11: * the handler if we are reading from the keyboard. ! 12: */ ! 13: ! 14: #include "less.h" ! 15: #include <signal.h> ! 16: #include <setjmp.h> ! 17: ! 18: /* ! 19: * The type of signal handler functions. ! 20: * Usually int, although it should be void. ! 21: */ ! 22: typedef int HANDLER; ! 23: ! 24: /* ! 25: * "sigs" contains bits indicating signals which need to be processed. ! 26: */ ! 27: public int sigs; ! 28: #define S_INTERRUPT 01 ! 29: #ifdef SIGTSTP ! 30: #define S_STOP 02 ! 31: #endif ! 32: #ifdef NRTC ! 33: #define S_QUIT 04 ! 34: #endif NRTC ! 35: ! 36: extern int reading; ! 37: extern char *first_cmd; ! 38: extern jmp_buf main_loop; ! 39: ! 40: /* ! 41: * Interrupt signal handler. ! 42: */ ! 43: static HANDLER ! 44: interrupt() ! 45: { ! 46: SIGNAL(SIGINT, interrupt); ! 47: sigs |= S_INTERRUPT; ! 48: if (reading) ! 49: psignals(); ! 50: } ! 51: ! 52: #ifdef NRTC ! 53: /* ! 54: * Interrupt signal handler. ! 55: */ ! 56: static HANDLER ! 57: quitnow () ! 58: { ! 59: SIGNAL(SIGQUIT, quitnow); ! 60: sigs |= S_QUIT; ! 61: if (reading) ! 62: psignals(); ! 63: } ! 64: #endif NRTC ! 65: ! 66: #ifdef SIGTSTP ! 67: /* ! 68: * "Stop" (^Z) signal handler. ! 69: */ ! 70: static HANDLER ! 71: stop() ! 72: { ! 73: SIGNAL(SIGTSTP, stop); ! 74: sigs |= S_STOP; ! 75: if (reading) ! 76: psignals(); ! 77: } ! 78: #endif ! 79: ! 80: /* ! 81: * Set up the signal handlers. ! 82: */ ! 83: public void ! 84: init_signals() ! 85: { ! 86: (void) SIGNAL(SIGINT, interrupt); ! 87: #ifdef NRTC ! 88: (void) SIGNAL (SIGQUIT, quitnow); ! 89: #endif NRTC ! 90: #ifdef SIGTSTP ! 91: (void) SIGNAL(SIGTSTP, stop); ! 92: #endif ! 93: } ! 94: ! 95: /* ! 96: * Process any signals we have recieved. ! 97: * A received signal cause a bit to be set in "sigs". ! 98: */ ! 99: public void ! 100: psignals() ! 101: { ! 102: register int tsignals; ! 103: ! 104: tsignals = sigs; ! 105: sigs = 0; ! 106: if (tsignals == 0) ! 107: return; ! 108: ! 109: dropout(); /* Discard any buffered output */ ! 110: ! 111: #ifdef SIGTSTP ! 112: if (tsignals & S_STOP) ! 113: { ! 114: /* ! 115: * Clean up the terminal. ! 116: */ ! 117: #ifdef SIGTTOU ! 118: SIGNAL(SIGTTOU, SIG_IGN); ! 119: #endif ! 120: lower_left(); ! 121: clear_eol(); ! 122: flush(); ! 123: raw_mode(0); ! 124: #ifdef SIGTTOU ! 125: SIGNAL(SIGTTOU, SIG_DFL); ! 126: #endif ! 127: SIGNAL(SIGTSTP, SIG_DFL); ! 128: #if SIGSETMASK ! 129: /* ! 130: * This system will not allow us to send a ! 131: * stop signal (SIGTSTP) to ourself ! 132: * while we are in the signal handler, like maybe now. ! 133: * (This can be the case if we are reading; see comment above.) ! 134: * So we ask the silly system for permission to do so. ! 135: */ ! 136: sigsetmask(0); ! 137: #endif ! 138: kill(getpid(), SIGTSTP); ! 139: /* ! 140: * ... Bye bye. ... ! 141: * Hopefully we'll be back later and resume here... ! 142: * Reset the terminal and arrange to repaint the ! 143: * screen when we get back to the main command loop. ! 144: */ ! 145: SIGNAL(SIGTSTP, stop); ! 146: raw_mode(1); ! 147: first_cmd = "r"; ! 148: longjmp(main_loop, 1); ! 149: } ! 150: #endif ! 151: #ifdef NRTC ! 152: if (tsignals & S_QUIT) ! 153: quit (); ! 154: #endif NRTC ! 155: if (tsignals & S_INTERRUPT) ! 156: { ! 157: bell(); ! 158: /* ! 159: * {{ You may wish to replace the bell() with ! 160: * error("Interrupt"); }} ! 161: */ ! 162: } ! 163: ! 164: longjmp(main_loop, 1); ! 165: } ! 166: ! 167: /* ! 168: * Pass the specified command to a shell to be executed. ! 169: * Like plain "system()", but handles resetting terminal modes, etc. ! 170: */ ! 171: public void ! 172: lsystem(cmd) ! 173: char *cmd; ! 174: { ! 175: int inp; ! 176: ! 177: /* ! 178: * Print the command which is to be executed. ! 179: */ ! 180: lower_left(); ! 181: clear_eol(); ! 182: puts("!"); ! 183: puts(cmd); ! 184: puts("\n"); ! 185: ! 186: /* ! 187: * De-initialize the terminal and take out of raw mode. ! 188: */ ! 189: deinit(); ! 190: flush(); ! 191: raw_mode(0); ! 192: ! 193: /* ! 194: * Restore signals to their defaults. ! 195: */ ! 196: SIGNAL(SIGINT, SIG_DFL); ! 197: #ifdef SIGTSTP ! 198: SIGNAL(SIGTSTP, SIG_DFL); ! 199: #endif ! 200: /* ! 201: * Pass the command to the system to be executed. ! 202: */ ! 203: inp = dup(0); ! 204: close(0); ! 205: open("/dev/tty", 0); ! 206: ! 207: system(cmd); ! 208: ! 209: close(0); ! 210: dup(inp); ! 211: close(inp); ! 212: ! 213: /* ! 214: * Reset signals, raw mode, etc. ! 215: */ ! 216: init_signals(); ! 217: raw_mode(1); ! 218: init(); ! 219: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.