home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume6 / less2 / part2 / signal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-11-30  |  3.4 KB  |  196 lines

  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. }
  196.