|
|
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: ! 33: extern int reading; ! 34: extern char *first_cmd; ! 35: extern jmp_buf main_loop; ! 36: ! 37: /* ! 38: * Interrupt signal handler. ! 39: */ ! 40: static HANDLER ! 41: interrupt() ! 42: { ! 43: SIGNAL(SIGINT, interrupt); ! 44: sigs |= S_INTERRUPT; ! 45: if (reading) ! 46: psignals(); ! 47: } ! 48: ! 49: #ifdef SIGTSTP ! 50: /* ! 51: * "Stop" (^Z) signal handler. ! 52: */ ! 53: static HANDLER ! 54: stop() ! 55: { ! 56: SIGNAL(SIGTSTP, stop); ! 57: sigs |= S_STOP; ! 58: if (reading) ! 59: psignals(); ! 60: } ! 61: #endif ! 62: ! 63: /* ! 64: * Set up the signal handlers. ! 65: */ ! 66: public void ! 67: init_signals() ! 68: { ! 69: (void) SIGNAL(SIGINT, interrupt); ! 70: #ifdef SIGTSTP ! 71: (void) SIGNAL(SIGTSTP, stop); ! 72: #endif ! 73: } ! 74: ! 75: /* ! 76: * Process any signals we have recieved. ! 77: * A received signal cause a bit to be set in "sigs". ! 78: */ ! 79: public void ! 80: psignals() ! 81: { ! 82: register int tsignals; ! 83: ! 84: tsignals = sigs; ! 85: sigs = 0; ! 86: if (tsignals == 0) ! 87: return; ! 88: ! 89: dropout(); /* Discard any buffered output */ ! 90: ! 91: #ifdef SIGTSTP ! 92: if (tsignals & S_STOP) ! 93: { ! 94: /* ! 95: * Clean up the terminal. ! 96: */ ! 97: #ifdef SIGTTOU ! 98: SIGNAL(SIGTTOU, SIG_IGN); ! 99: #endif ! 100: lower_left(); ! 101: clear_eol(); ! 102: flush(); ! 103: raw_mode(0); ! 104: #ifdef SIGTTOU ! 105: SIGNAL(SIGTTOU, SIG_DFL); ! 106: #endif ! 107: SIGNAL(SIGTSTP, SIG_DFL); ! 108: #if SIGSETMASK ! 109: /* ! 110: * This system will not allow us to send a ! 111: * stop signal (SIGTSTP) to ourself ! 112: * while we are in the signal handler, like maybe now. ! 113: * (This can be the case if we are reading; see comment above.) ! 114: * So we ask the silly system for permission to do so. ! 115: */ ! 116: sigsetmask(0); ! 117: #endif ! 118: kill(getpid(), SIGTSTP); ! 119: /* ! 120: * ... Bye bye. ... ! 121: * Hopefully we'll be back later and resume here... ! 122: * Reset the terminal and arrange to repaint the ! 123: * screen when we get back to the main command loop. ! 124: */ ! 125: SIGNAL(SIGTSTP, stop); ! 126: raw_mode(1); ! 127: first_cmd = "r"; ! 128: longjmp(main_loop, 1); ! 129: } ! 130: #endif ! 131: if (tsignals & S_INTERRUPT) ! 132: { ! 133: bell(); ! 134: /* ! 135: * {{ You may wish to replace the bell() with ! 136: * error("Interrupt"); }} ! 137: */ ! 138: } ! 139: ! 140: longjmp(main_loop, 1); ! 141: } ! 142: ! 143: /* ! 144: * Pass the specified command to a shell to be executed. ! 145: * Like plain "system()", but handles resetting terminal modes, etc. ! 146: */ ! 147: public void ! 148: lsystem(cmd) ! 149: char *cmd; ! 150: { ! 151: int inp; ! 152: ! 153: /* ! 154: * Print the command which is to be executed. ! 155: */ ! 156: lower_left(); ! 157: clear_eol(); ! 158: puts("!"); ! 159: puts(cmd); ! 160: puts("\n"); ! 161: ! 162: /* ! 163: * De-initialize the terminal and take out of raw mode. ! 164: */ ! 165: deinit(); ! 166: flush(); ! 167: raw_mode(0); ! 168: ! 169: /* ! 170: * Restore signals to their defaults. ! 171: */ ! 172: SIGNAL(SIGINT, SIG_DFL); ! 173: #ifdef SIGTSTP ! 174: SIGNAL(SIGTSTP, SIG_DFL); ! 175: #endif ! 176: /* ! 177: * Pass the command to the system to be executed. ! 178: */ ! 179: inp = dup(0); ! 180: close(0); ! 181: open("/dev/tty", 0); ! 182: ! 183: system(cmd); ! 184: ! 185: close(0); ! 186: dup(inp); ! 187: close(inp); ! 188: ! 189: /* ! 190: * Reset signals, raw mode, etc. ! 191: */ ! 192: init_signals(); ! 193: raw_mode(1); ! 194: init(); ! 195: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.