home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 531.lha / Less_v1.4Z / src.LZH / src / signal.c < prev    next >
C/C++ Source or Header  |  1991-07-03  |  6KB  |  258 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. #ifdef AMIGA
  15. /*
  16.  * This all works on the Amiga under SAS-C.  The SIGINT stuff only
  17.  * responds to ^C from the window that started Less, not the Less window
  18.  * itself.  ^C from the Less window is polled by chk_sigs(), and
  19.  * eventually does the same thing.
  20.  */
  21.  
  22. #define SIGWINCH
  23. #define S_WINCH 04
  24. #endif
  25.  
  26. #ifdef AMIGA
  27. /* Compile with -HPreHeader.q to get "less.h"! */
  28. #else
  29. #include "less.h"
  30. #endif
  31.  
  32. #include <signal.h>
  33. #include <setjmp.h>
  34.  
  35. /*
  36.  * The type of signal handler functions.
  37.  * Usually int, although it should be void.
  38.  */
  39. #ifdef AMIGA
  40. typedef void            HANDLER;
  41. #else
  42. typedef int             HANDLER;
  43. #endif
  44.  
  45. /* Prototypes for functions defined in signal.c */
  46.  
  47. static HANDLER interrupt __PROTO((void));
  48.  
  49.  
  50. /*
  51.  * "sigs" contains bits indicating signals which need to be processed.
  52.  */
  53. public int sigs;
  54. #define S_INTERRUPT     01
  55. #ifdef SIGTSTP
  56. #define S_STOP          02
  57. #endif
  58.  
  59.  
  60. extern int reading;
  61. extern int sc_width, sc_height;
  62. extern char *first_cmd;
  63. extern jmp_buf main_loop;
  64.  
  65. /*
  66.  * Interrupt signal handler.
  67.  */
  68. #ifdef __STDC__
  69. static HANDLER interrupt (void)
  70. #else
  71.         static HANDLER
  72. interrupt()
  73. #endif
  74. {
  75. #ifdef AMIGA
  76.         /* This gets entered upon ^C from the CLI window.  ^C in the
  77.          * Less window is handled in io.c.  A ^C in the CLI window is
  78.          * taken as a real sign of distress, we quit.
  79.          * (Sending less a break from another process gets here, too.
  80.          */
  81.         quit();
  82. #else
  83.         SIGNAL(SIGINT, interrupt);
  84.         sigs |= S_INTERRUPT;
  85.         if (reading)
  86.                 psignals();
  87. #endif
  88. }
  89.  
  90. #ifdef SIGTSTP
  91. /*
  92.  * "Stop" (^Z) signal handler.
  93.  */
  94.         static HANDLER
  95. stop()
  96. {
  97.         SIGNAL(SIGTSTP, stop);
  98.         sigs |= S_STOP;
  99.         if (reading)
  100.                 psignals();
  101. }
  102. #endif
  103.  
  104. #ifdef SIGWINCH
  105. /*
  106.  * "Window" change handler
  107.  */
  108. #ifdef __STDC__
  109. void winch (void)
  110. #else
  111. winch()
  112. #endif
  113. {
  114. #ifndef AMIGA
  115.         SIGNAL(SIGWINCH, winch);
  116. #endif
  117.         sigs |= S_WINCH;
  118.         if (reading)
  119.                 psignals();
  120. #ifdef AMIGA
  121.         else
  122.                 sigs |= S_INTERRUPT;
  123. #endif
  124. }
  125. #else
  126. #ifdef SIGWIND
  127. /*
  128.  * "Window" change handler
  129.  */
  130. winch()
  131. {
  132.         SIGNAL(SIGWIND, winch);
  133.         sigs |= S_WINCH;
  134.         if (reading)
  135.                 psignals();
  136. }
  137. #endif
  138. #endif
  139.  
  140. /*
  141.  * Set up the signal handlers.
  142.  */
  143. #ifdef __STDC__
  144. void init_signals (void)
  145. #else
  146.         public void
  147. init_signals()
  148. #endif
  149. {
  150.         (void) SIGNAL(SIGINT, interrupt);
  151. #ifdef SIGTSTP
  152.         (void) SIGNAL(SIGTSTP, stop);
  153. #endif
  154. #ifdef SIGWINCH
  155. #ifndef AMIGA
  156.         (void) SIGNAL(SIGWINCH, winch);
  157. #endif
  158. #else
  159. #ifdef SIGWIND
  160.         (void) SIGNAL(SIGWIND, winch);
  161. #endif
  162. #endif
  163. }
  164.  
  165. /*
  166.  * Process any signals we have recieved.
  167.  * A received signal cause a bit to be set in "sigs".
  168.  */
  169. #ifdef __STDC__
  170. void psignals (void)
  171. #else
  172.         public void
  173. psignals()
  174. #endif
  175. {
  176.         register int tsignals;
  177.  
  178.         tsignals = sigs;
  179.         sigs = 0;
  180.         if (tsignals == 0)
  181.                 return;
  182.  
  183.         dropout();              /* Discard any buffered output */
  184.  
  185. #ifdef S_WINCH
  186.         if (tsignals & S_WINCH)
  187.         {
  188.                 int old_width, old_height;
  189.                 /*
  190.                  * Re-execute get_term() to read the new window size.
  191.                  */
  192.                 old_width = sc_width;
  193.                 old_height = sc_height;
  194.                 get_term();
  195.                 if (sc_width != old_width || sc_height != old_height)
  196.                         first_cmd = "r";
  197. #ifndef AMIGA
  198.                 longjmp(main_loop, 1);
  199. #endif
  200.         }
  201. #endif
  202. #ifdef SIGTSTP
  203.         if (tsignals & S_STOP)
  204.         {
  205.                 /*
  206.                  * Clean up the terminal.
  207.                  */
  208. #ifdef SIGTTOU
  209.                 SIGNAL(SIGTTOU, SIG_IGN);
  210. #endif
  211.                 lower_left();
  212.                 clear_eol();
  213.                 flush();
  214.                 raw_mode(0);
  215. #ifdef SIGTTOU
  216.                 SIGNAL(SIGTTOU, SIG_DFL);
  217. #endif
  218.                 SIGNAL(SIGTSTP, SIG_DFL);
  219. #if SIGSETMASK
  220.                 /*
  221.                  * This system will not allow us to send a
  222.                  * stop signal (SIGTSTP) to ourself
  223.                  * while we are in the signal handler, like maybe now.
  224.                  * (This can be the case if we are reading; see comment above.)
  225.                  * So we ask the silly system for permission to do so.
  226.                  */
  227.                 sigsetmask(0);
  228. #endif
  229.                 kill(getpid(), SIGTSTP);
  230.                 /*
  231.                  * ... Bye bye. ...
  232.                  * Hopefully we'll be back later and resume here...
  233.                  * Reset the terminal and arrange to repaint the
  234.                  * screen when we get back to the main command loop.
  235.                  */
  236.                 SIGNAL(SIGTSTP, stop);
  237.                 raw_mode(1);
  238.                 first_cmd = "r";
  239.                 longjmp(main_loop, 1);
  240.         }
  241. #endif
  242.         if (tsignals & S_INTERRUPT)
  243.         {
  244. #ifdef AMIGA
  245.                 error("Interrupt");
  246. #else
  247.                 bell();
  248.                 /*
  249.                  * {{ You may wish to replace the bell() with
  250.                  *    error("Interrupt"); }}
  251.                  */
  252. #endif
  253.         }
  254.  
  255.         longjmp(main_loop, 1);
  256. }
  257.  
  258.