home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21fs.zip / octave / readline / signals.c < prev    next >
C/C++ Source or Header  |  2000-01-15  |  11KB  |  392 lines

  1. /* Modified by Klaus Gebhardt, October 1996 */
  2. /* signals.c -- signal handling support for readline. */
  3.  
  4. /* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
  5.  
  6.    This file is part of the GNU Readline Library, a library for
  7.    reading lines of text with interactive input and history editing.
  8.  
  9.    The GNU Readline Library is free software; you can redistribute it
  10.    and/or modify it under the terms of the GNU General Public License
  11.    as published by the Free Software Foundation; either version 1, or
  12.    (at your option) any later version.
  13.  
  14.    The GNU Readline Library is distributed in the hope that it will be
  15.    useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  16.    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.    GNU General Public License for more details.
  18.  
  19.    The GNU General Public License is often shipped with GNU software, and
  20.    is generally kept in a file called COPYING or LICENSE.  If you do not
  21.    have a copy of the license, write to the Free Software Foundation,
  22.    675 Mass Ave, Cambridge, MA 02139, USA. */
  23. #define READLINE_LIBRARY
  24.  
  25. #if defined (HAVE_CONFIG_H)
  26. #  include <config.h>
  27. #endif
  28.  
  29. #include <stdio.h>        /* Just for NULL.  Yuck. */
  30. #include <sys/types.h>
  31. #include <signal.h>
  32.  
  33. #if defined (HAVE_UNISTD_H)
  34. #  include <unistd.h>
  35. #endif /* HAVE_UNISTD_H */
  36.  
  37. /* System-specific feature definitions and include files. */
  38. #include "rldefs.h"
  39.  
  40. #if defined (GWINSZ_IN_SYS_IOCTL)
  41. #  include <sys/ioctl.h>
  42. #endif /* GWINSZ_IN_SYS_IOCTL */
  43.  
  44. #if defined (__GO32__)
  45. #  undef HANDLE_SIGNALS
  46. #endif /* __GO32__ */
  47.  
  48. #if defined (HANDLE_SIGNALS)
  49. /* Some standard library routines. */
  50. #include "readline.h"
  51. #include "history.h"
  52.  
  53. extern int readline_echoing_p;
  54. extern int rl_pending_input;
  55. extern int _rl_meta_flag;
  56.  
  57. extern void free_undo_list ();
  58. extern void _rl_get_screen_size ();
  59. extern void _rl_redisplay_after_sigwinch ();
  60. extern void _rl_clean_up_for_exit ();
  61. extern void _rl_kill_kbd_macro ();
  62. extern void _rl_init_argument ();
  63. extern void rl_deprep_terminal (), rl_prep_terminal ();
  64.  
  65. #ifndef __EMX__
  66. #if !defined (RETSIGTYPE)
  67. #  if defined (VOID_SIGHANDLER)
  68. #    define RETSIGTYPE void
  69. #  else
  70. #    define RETSIGTYPE int
  71. #  endif /* !VOID_SIGHANDLER */
  72. #endif /* !RETSIGTYPE */
  73.  
  74. #if defined (VOID_SIGHANDLER)
  75. #  define SIGHANDLER_RETURN return
  76. #else
  77. #  define SIGHANDLER_RETURN return (0)
  78. #endif
  79. #else
  80. #define RETSIGTYPE void
  81. #define SIGHANDLER_RETURN return
  82. #endif
  83.  
  84. /* This typedef is equivalant to the one for Function; it allows us
  85.    to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
  86. typedef RETSIGTYPE SigHandler ();
  87.  
  88. static SigHandler *rl_set_sighandler ();
  89.  
  90. /* **************************************************************** */
  91. /*                                        */
  92. /*               Signal Handling                          */
  93. /*                                    */
  94. /* **************************************************************** */
  95.  
  96. /* If we're not being compiled as part of bash, initialize handlers for
  97.    and catch the job control signals (SIGTTIN, SIGTTOU, SIGTSTP) and
  98.    SIGTERM. */
  99. #if !defined (SHELL)
  100. #  define HANDLE_JOB_SIGNALS
  101. #  define HANDLE_SIGTERM
  102. #endif /* !SHELL */
  103.  
  104. #if defined (HAVE_POSIX_SIGNALS)
  105. typedef struct sigaction sighandler_cxt;
  106. #  define rl_sigaction(s, nh, oh)    sigaction(s, nh, oh)
  107. #else
  108. typedef struct { SigHandler *sa_handler; } sighandler_cxt;
  109. #  define sigemptyset(m)
  110. #endif /* !HAVE_POSIX_SIGNALS */
  111.  
  112. #ifdef __EMX__
  113. static sighandler_cxt old_int, old_break, old_alrm;
  114. #else
  115. static sighandler_cxt old_int, old_alrm;
  116. #endif
  117.  
  118. #if defined (HANDLE_JOB_SIGNALS)
  119. static sighandler_cxt old_tstp, old_ttou, old_ttin;
  120. #endif /* HANDLE_JOB_SIGNALS */
  121.  
  122. #if defined (HANDLE_SIGTERM)
  123. static sighandler_cxt old_term;
  124. #endif
  125.  
  126. #if defined (SIGWINCH)
  127. static sighandler_cxt old_winch;
  128. #endif
  129.  
  130. /* Readline signal handler functions. */
  131.  
  132. static RETSIGTYPE
  133. rl_signal_handler (sig)
  134.      int sig;
  135. {
  136. #if defined (HAVE_POSIX_SIGNALS)
  137.   sigset_t set;
  138. #else /* !HAVE_POSIX_SIGNALS */
  139. #  if defined (HAVE_BSD_SIGNALS)
  140.   long omask;
  141. #  else /* !HAVE_BSD_SIGNALS */
  142.   sighandler_cxt dummy_cxt;    /* needed for rl_set_sighandler call */
  143. #  endif /* !HAVE_BSD_SIGNALS */
  144. #endif /* !HAVE_POSIX_SIGNALS */
  145.  
  146. #if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
  147.   /* Since the signal will not be blocked while we are in the signal
  148.      handler, ignore it until rl_clear_signals resets the catcher. */
  149. #ifndef __EMX__
  150.   if (sig == SIGINT || sig == SIGALRM)
  151. #else
  152.   if (sig == SIGINT || sig == SIGBREAK || sig == SIGALRM)
  153. #endif
  154.     rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
  155. #endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
  156.  
  157.   switch (sig)
  158.     {
  159.     case SIGINT:
  160.     case SIGBREAK:
  161.       {
  162.     register HIST_ENTRY *entry;
  163.  
  164.     free_undo_list ();
  165.  
  166.     entry = current_history ();
  167.     if (entry)
  168.       entry->data = (char *)NULL;
  169.       }
  170.       _rl_kill_kbd_macro ();
  171.       rl_clear_message ();
  172.       _rl_init_argument ();
  173.  
  174. #if defined (SIGTSTP)
  175.     case SIGTSTP:
  176.     case SIGTTOU:
  177.     case SIGTTIN:
  178. #endif /* SIGTSTP */
  179.     case SIGALRM:
  180.     case SIGTERM:
  181.       _rl_clean_up_for_exit ();
  182.       (*rl_deprep_term_function) ();
  183.       rl_clear_signals ();
  184.       rl_pending_input = 0;
  185.  
  186. #if defined (__EMX__)
  187.       signal (sig, SIG_ACK);
  188. #endif
  189.  
  190. #if defined (HAVE_POSIX_SIGNALS)
  191.       sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
  192.       sigdelset (&set, sig);
  193. #else /* !HAVE_POSIX_SIGNALS */
  194. #  if defined (HAVE_BSD_SIGNALS)
  195.       omask = sigblock (0);
  196. #  endif /* HAVE_BSD_SIGNALS */
  197. #endif /* !HAVE_POSIX_SIGNALS */
  198.  
  199.       kill (getpid (), sig);
  200.  
  201.       /* Let the signal that we just sent through.  */
  202. #if defined (HAVE_POSIX_SIGNALS)
  203.       sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
  204. #else /* !HAVE_POSIX_SIGNALS */
  205. #  if defined (HAVE_BSD_SIGNALS)
  206.       sigsetmask (omask & ~(sigmask (sig)));
  207. #  endif /* HAVE_BSD_SIGNALS */
  208. #endif /* !HAVE_POSIX_SIGNALS */
  209.  
  210.       (*rl_prep_term_function) (_rl_meta_flag);
  211.       rl_set_signals ();
  212.     }
  213.  
  214.   SIGHANDLER_RETURN;
  215. }
  216.  
  217. #if defined (SIGWINCH)
  218. static RETSIGTYPE
  219. rl_handle_sigwinch (sig)
  220.      int sig;
  221. {
  222.   SigHandler *oh;
  223.  
  224. #if defined (MUST_REINSTALL_SIGHANDLERS)
  225.   sighandler_cxt dummy_winch;
  226.  
  227.   /* We don't want to change old_winch -- it holds the state of SIGWINCH
  228.      disposition set by the calling application.  We need this state
  229.      because we call the application's SIGWINCH handler after updating
  230.      our own idea of the screen size. */
  231.   rl_set_sighandler (SIGWINCH, rl_handle_sigwinch, &dummy_winch);
  232. #endif
  233.  
  234.   if (readline_echoing_p)
  235.     {
  236.       _rl_get_screen_size (fileno (rl_instream), 1);
  237.       _rl_redisplay_after_sigwinch ();
  238.     }
  239.  
  240.   /* If another sigwinch handler has been installed, call it. */
  241.   oh = (SigHandler *)old_winch.sa_handler;
  242.   if (oh &&  oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
  243.     (*oh) (sig);
  244.  
  245.   SIGHANDLER_RETURN;
  246. }
  247. #endif  /* SIGWINCH */
  248.  
  249. /* Functions to manage signal handling. */
  250.  
  251. #if !defined (HAVE_POSIX_SIGNALS)
  252. static int
  253. rl_sigaction (sig, nh, oh)
  254.      int sig;
  255.      sighandler_cxt *nh, *oh;
  256. {
  257.   oh->sa_handler = signal (sig, nh->sa_handler);
  258.   return 0;
  259. }
  260. #endif /* !HAVE_POSIX_SIGNALS */
  261.  
  262. /* Set up a readline-specific signal handler, saving the old signal
  263.    information in OHANDLER.  Return the old signal handler, like
  264.    signal(). */
  265. static SigHandler *
  266. rl_set_sighandler (sig, handler, ohandler)
  267.      int sig;
  268.      SigHandler *handler;
  269.      sighandler_cxt *ohandler;
  270. {
  271. #if defined (HAVE_POSIX_SIGNALS)
  272.   struct sigaction act;
  273.  
  274.   act.sa_handler = handler;
  275.   act.sa_flags = 0;
  276.   sigemptyset (&act.sa_mask);
  277.   sigemptyset (&ohandler->sa_mask);
  278.   sigaction (sig, &act, ohandler);
  279. #else
  280.   ohandler->sa_handler = (SigHandler *)signal (sig, handler);
  281. #endif /* !HAVE_POSIX_SIGNALS */
  282.   return (ohandler->sa_handler);
  283. }
  284.  
  285. int
  286. rl_set_signals ()
  287. {
  288.   sighandler_cxt dummy;
  289.   SigHandler *oh;
  290.  
  291. #if defined (HAVE_POSIX_SIGNALS)
  292.   sigemptyset (&dummy.sa_mask);
  293. #endif
  294.  
  295.   oh = rl_set_sighandler (SIGINT, rl_signal_handler, &old_int);
  296.   if (oh == (SigHandler *)SIG_IGN)
  297.     rl_sigaction (SIGINT, &old_int, &dummy);
  298.  
  299. #ifdef __EMX__
  300.   oh = rl_set_sighandler (SIGBREAK, rl_signal_handler, &old_break);
  301.   if (oh == (SigHandler *)SIG_IGN)
  302.     rl_sigaction (SIGBREAK, &old_break, &dummy);
  303. #endif
  304.  
  305.   oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
  306.   if (oh == (SigHandler *)SIG_IGN)
  307.     rl_sigaction (SIGALRM, &old_alrm, &dummy);
  308. #if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
  309.   /* If the application using readline has already installed a signal
  310.      handler with SA_RESTART, SIGALRM will cause reads to be restarted
  311.      automatically, so readline should just get out of the way.  Since
  312.      we tested for SIG_IGN above, we can just test for SIG_DFL here. */
  313.   if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
  314.     rl_sigaction (SIGALRM, &old_alrm, &dummy);
  315. #endif /* HAVE_POSIX_SIGNALS */
  316.  
  317. #if defined (HANDLE_JOB_SIGNALS)
  318.  
  319. #if defined (SIGTSTP)
  320.   oh = rl_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
  321.   if (oh == (SigHandler *)SIG_IGN)
  322.     rl_sigaction (SIGTSTP, &old_tstp, &dummy);
  323. #else
  324.   oh = (SigHandler *)NULL;
  325. #endif /* SIGTSTP */
  326.  
  327. #if defined (SIGTTOU)
  328.   rl_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
  329.   rl_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
  330.  
  331.   if (oh == (SigHandler *)SIG_IGN)
  332.     {
  333.       rl_set_sighandler (SIGTTOU, SIG_IGN, &dummy);
  334.       rl_set_sighandler (SIGTTIN, SIG_IGN, &dummy);
  335.     }
  336. #endif /* SIGTTOU */
  337.  
  338. #endif /* HANDLE_JOB_SIGNALS */
  339.  
  340. #if defined (HANDLE_SIGTERM)
  341.   /* Handle SIGTERM if we're not being compiled as part of bash. */
  342.   rl_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
  343. #endif /* HANDLE_SIGTERM */
  344.  
  345. #if defined (SIGWINCH)
  346.   rl_set_sighandler (SIGWINCH, rl_handle_sigwinch, &old_winch);
  347. #endif /* SIGWINCH */
  348.  
  349.   return 0;
  350. }
  351.  
  352. int
  353. rl_clear_signals ()
  354. {
  355.   sighandler_cxt dummy;
  356.  
  357. #if defined (HAVE_POSIX_SIGNALS)
  358.   sigemptyset (&dummy.sa_mask);
  359. #endif
  360.  
  361.   rl_sigaction (SIGINT, &old_int, &dummy);
  362. #ifdef __EMX__
  363.   rl_sigaction (SIGBREAK, &old_break, &dummy);
  364. #endif
  365.   rl_sigaction (SIGALRM, &old_alrm, &dummy);
  366.  
  367. #if defined (HANDLE_JOB_SIGNALS)
  368.  
  369. #if defined (SIGTSTP)
  370.   rl_sigaction (SIGTSTP, &old_tstp, &dummy);
  371. #endif
  372.  
  373. #if defined (SIGTTOU)
  374.   rl_sigaction (SIGTTOU, &old_ttou, &dummy);
  375.   rl_sigaction (SIGTTIN, &old_ttin, &dummy);
  376. #endif /* SIGTTOU */
  377.  
  378. #endif /* HANDLE_JOB_SIGNALS */
  379.  
  380. #if defined (HANDLE_SIGTERM)
  381.   rl_sigaction (SIGTERM, &old_term, &dummy);
  382. #endif /* HANDLE_SIGTERM */
  383.  
  384. #if defined (SIGWINCH)
  385.   sigemptyset (&dummy.sa_mask);
  386.   rl_sigaction (SIGWINCH, &old_winch, &dummy);
  387. #endif
  388.  
  389.   return 0;
  390. }
  391. #endif  /* HANDLE_SIGNALS */
  392.