Home | History | Annotate | Line # | Download | only in info
      1  1.1  christos /*	$NetBSD: signals.c,v 1.1.1.1 2016/01/14 00:11:29 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /* signals.c -- install and maintain signal handlers.
      4  1.1  christos    Id: signals.c,v 1.7 2004/04/11 17:56:46 karl Exp
      5  1.1  christos 
      6  1.1  christos    Copyright (C) 1993, 1994, 1995, 1998, 2002, 2003, 2004 Free Software
      7  1.1  christos    Foundation, Inc.
      8  1.1  christos 
      9  1.1  christos    This program is free software; you can redistribute it and/or modify
     10  1.1  christos    it under the terms of the GNU General Public License as published by
     11  1.1  christos    the Free Software Foundation; either version 2, or (at your option)
     12  1.1  christos    any later version.
     13  1.1  christos 
     14  1.1  christos    This program is distributed in the hope that it will be useful,
     15  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  1.1  christos    GNU General Public License for more details.
     18  1.1  christos 
     19  1.1  christos    You should have received a copy of the GNU General Public License
     20  1.1  christos    along with this program; if not, write to the Free Software
     21  1.1  christos    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     22  1.1  christos 
     23  1.1  christos    Originally written by Brian Fox (bfox (at) ai.mit.edu). */
     24  1.1  christos 
     25  1.1  christos #include "info.h"
     26  1.1  christos #include "signals.h"
     27  1.1  christos 
     28  1.1  christos void initialize_info_signal_handler (void);
     29  1.1  christos 
     30  1.1  christos /* **************************************************************** */
     31  1.1  christos /*                                                                  */
     32  1.1  christos /*              Pretending That We Have POSIX Signals               */
     33  1.1  christos /*                                                                  */
     34  1.1  christos /* **************************************************************** */
     35  1.1  christos 
     36  1.1  christos #if !defined (HAVE_SIGPROCMASK) && defined (HAVE_SIGSETMASK)
     37  1.1  christos /* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
     38  1.1  christos static void
     39  1.1  christos sigprocmask (int operation, int *newset, int *oldset)
     40  1.1  christos {
     41  1.1  christos   switch (operation)
     42  1.1  christos     {
     43  1.1  christos     case SIG_UNBLOCK:
     44  1.1  christos       sigsetmask (sigblock (0) & ~(*newset));
     45  1.1  christos       break;
     46  1.1  christos 
     47  1.1  christos     case SIG_BLOCK:
     48  1.1  christos       *oldset = sigblock (*newset);
     49  1.1  christos       break;
     50  1.1  christos 
     51  1.1  christos     case SIG_SETMASK:
     52  1.1  christos       sigsetmask (*newset);
     53  1.1  christos       break;
     54  1.1  christos 
     55  1.1  christos     default:
     56  1.1  christos       abort ();
     57  1.1  christos     }
     58  1.1  christos }
     59  1.1  christos #endif /* !HAVE_SIGPROCMASK && HAVE_SIGSETMASK */
     60  1.1  christos 
     61  1.1  christos /* **************************************************************** */
     62  1.1  christos /*                                                                  */
     63  1.1  christos /*                  Signal Handling for Info                        */
     64  1.1  christos /*                                                                  */
     65  1.1  christos /* **************************************************************** */
     66  1.1  christos 
     67  1.1  christos #if defined (HAVE_SIGACTION) || defined (HAVE_SIGPROCMASK) ||\
     68  1.1  christos   defined (HAVE_SIGSETMASK)
     69  1.1  christos static void
     70  1.1  christos mask_termsig (sigset_t *set)
     71  1.1  christos {
     72  1.1  christos # if defined (SIGTSTP)
     73  1.1  christos   sigaddset (set, SIGTSTP);
     74  1.1  christos   sigaddset (set, SIGTTOU);
     75  1.1  christos   sigaddset (set, SIGTTIN);
     76  1.1  christos # endif
     77  1.1  christos # if defined (SIGWINCH)
     78  1.1  christos   sigaddset (set, SIGWINCH);
     79  1.1  christos # endif
     80  1.1  christos #if defined (SIGQUIT)
     81  1.1  christos   sigaddset (set, SIGQUIT);
     82  1.1  christos #endif
     83  1.1  christos #if defined (SIGINT)
     84  1.1  christos   sigaddset (set, SIGINT);
     85  1.1  christos #endif
     86  1.1  christos # if defined (SIGUSR1)
     87  1.1  christos   sigaddset (set, SIGUSR1);
     88  1.1  christos # endif
     89  1.1  christos }
     90  1.1  christos #endif /* HAVE_SIGACTION || HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
     91  1.1  christos 
     92  1.1  christos static RETSIGTYPE info_signal_proc (int sig);
     93  1.1  christos #if defined (HAVE_SIGACTION)
     94  1.1  christos typedef struct sigaction signal_info;
     95  1.1  christos signal_info info_signal_handler;
     96  1.1  christos 
     97  1.1  christos static void
     98  1.1  christos set_termsig (int sig, signal_info *old)
     99  1.1  christos {
    100  1.1  christos   sigaction (sig, &info_signal_handler, old);
    101  1.1  christos }
    102  1.1  christos 
    103  1.1  christos static void
    104  1.1  christos restore_termsig (int sig, const signal_info *saved)
    105  1.1  christos {
    106  1.1  christos   sigaction (sig, saved, NULL);
    107  1.1  christos }
    108  1.1  christos #else /* !HAVE_SIGACTION */
    109  1.1  christos typedef RETSIGTYPE (*signal_info) ();
    110  1.1  christos #define set_termsig(sig, old) (void)(*(old) = signal (sig, info_signal_proc))
    111  1.1  christos #define restore_termsig(sig, saved) (void)signal (sig, *(saved))
    112  1.1  christos #define info_signal_handler info_signal_proc
    113  1.1  christos static int term_conf_busy = 0;
    114  1.1  christos #endif /* !HAVE_SIGACTION */
    115  1.1  christos 
    116  1.1  christos static signal_info old_TSTP, old_TTOU, old_TTIN;
    117  1.1  christos static signal_info old_WINCH, old_INT, old_USR1;
    118  1.1  christos static signal_info old_QUIT;
    119  1.1  christos 
    120  1.1  christos void
    121  1.1  christos initialize_info_signal_handler (void)
    122  1.1  christos {
    123  1.1  christos #ifdef SA_NOCLDSTOP
    124  1.1  christos   /* (Based on info from Paul Eggert found in coreutils.)  Don't use
    125  1.1  christos      HAVE_SIGACTION to decide whether to use the sa_handler, sa_flags,
    126  1.1  christos      sa_mask members, as some systems (Solaris 7+) don't define them.  Use
    127  1.1  christos      SA_NOCLDSTOP instead; it's been part of POSIX.1 since day 1 (in 1988).  */
    128  1.1  christos   info_signal_handler.sa_handler = info_signal_proc;
    129  1.1  christos   info_signal_handler.sa_flags = 0;
    130  1.1  christos   mask_termsig (&info_signal_handler.sa_mask);
    131  1.1  christos #endif /* SA_NOCLDSTOP */
    132  1.1  christos 
    133  1.1  christos #if defined (SIGTSTP)
    134  1.1  christos   set_termsig (SIGTSTP, &old_TSTP);
    135  1.1  christos   set_termsig (SIGTTOU, &old_TTOU);
    136  1.1  christos   set_termsig (SIGTTIN, &old_TTIN);
    137  1.1  christos #endif /* SIGTSTP */
    138  1.1  christos 
    139  1.1  christos #if defined (SIGWINCH)
    140  1.1  christos   set_termsig (SIGWINCH, &old_WINCH);
    141  1.1  christos #endif
    142  1.1  christos 
    143  1.1  christos #if defined (SIGQUIT)
    144  1.1  christos   set_termsig (SIGQUIT, &old_QUIT);
    145  1.1  christos #endif
    146  1.1  christos 
    147  1.1  christos #if defined (SIGINT)
    148  1.1  christos   set_termsig (SIGINT, &old_INT);
    149  1.1  christos #endif
    150  1.1  christos 
    151  1.1  christos #if defined (SIGUSR1)
    152  1.1  christos   /* Used by DJGPP to simulate SIGTSTP on Ctrl-Z.  */
    153  1.1  christos   set_termsig (SIGUSR1, &old_USR1);
    154  1.1  christos #endif
    155  1.1  christos }
    156  1.1  christos 
    157  1.1  christos static void
    158  1.1  christos redisplay_after_signal (void)
    159  1.1  christos {
    160  1.1  christos   terminal_clear_screen ();
    161  1.1  christos   display_clear_display (the_display);
    162  1.1  christos   window_mark_chain (windows, W_UpdateWindow);
    163  1.1  christos   display_update_display (windows);
    164  1.1  christos   display_cursor_at_point (active_window);
    165  1.1  christos   fflush (stdout);
    166  1.1  christos }
    167  1.1  christos 
    168  1.1  christos static void
    169  1.1  christos reset_info_window_sizes (void)
    170  1.1  christos {
    171  1.1  christos   terminal_goto_xy (0, 0);
    172  1.1  christos   fflush (stdout);
    173  1.1  christos   terminal_unprep_terminal ();
    174  1.1  christos   terminal_get_screen_size ();
    175  1.1  christos   terminal_prep_terminal ();
    176  1.1  christos   display_initialize_display (screenwidth, screenheight);
    177  1.1  christos   window_new_screen_size (screenwidth, screenheight);
    178  1.1  christos   redisplay_after_signal ();
    179  1.1  christos }
    180  1.1  christos 
    181  1.1  christos static RETSIGTYPE
    182  1.1  christos info_signal_proc (int sig)
    183  1.1  christos {
    184  1.1  christos   signal_info *old_signal_handler = NULL;
    185  1.1  christos 
    186  1.1  christos #if !defined (HAVE_SIGACTION)
    187  1.1  christos   /* best effort: first increment this counter and later block signals */
    188  1.1  christos   if (term_conf_busy)
    189  1.1  christos     return;
    190  1.1  christos   term_conf_busy++;
    191  1.1  christos #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
    192  1.1  christos     {
    193  1.1  christos       sigset_t nvar, ovar;
    194  1.1  christos       sigemptyset (&nvar);
    195  1.1  christos       mask_termsig (&nvar);
    196  1.1  christos       sigprocmask (SIG_BLOCK, &nvar, &ovar);
    197  1.1  christos     }
    198  1.1  christos #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
    199  1.1  christos #endif /* !HAVE_SIGACTION */
    200  1.1  christos   switch (sig)
    201  1.1  christos     {
    202  1.1  christos #if defined (SIGTSTP)
    203  1.1  christos     case SIGTSTP:
    204  1.1  christos     case SIGTTOU:
    205  1.1  christos     case SIGTTIN:
    206  1.1  christos #endif
    207  1.1  christos #if defined (SIGQUIT)
    208  1.1  christos     case SIGQUIT:
    209  1.1  christos #endif
    210  1.1  christos #if defined (SIGINT)
    211  1.1  christos     case SIGINT:
    212  1.1  christos #endif
    213  1.1  christos       {
    214  1.1  christos #if defined (SIGTSTP)
    215  1.1  christos         if (sig == SIGTSTP)
    216  1.1  christos           old_signal_handler = &old_TSTP;
    217  1.1  christos         if (sig == SIGTTOU)
    218  1.1  christos           old_signal_handler = &old_TTOU;
    219  1.1  christos         if (sig == SIGTTIN)
    220  1.1  christos           old_signal_handler = &old_TTIN;
    221  1.1  christos #endif /* SIGTSTP */
    222  1.1  christos #if defined (SIGQUIT)
    223  1.1  christos         if (sig == SIGQUIT)
    224  1.1  christos           old_signal_handler = &old_QUIT;
    225  1.1  christos #endif /* SIGQUIT */
    226  1.1  christos #if defined (SIGINT)
    227  1.1  christos         if (sig == SIGINT)
    228  1.1  christos           old_signal_handler = &old_INT;
    229  1.1  christos #endif /* SIGINT */
    230  1.1  christos 
    231  1.1  christos         /* For stop signals, restore the terminal IO, leave the cursor
    232  1.1  christos            at the bottom of the window, and stop us. */
    233  1.1  christos         terminal_goto_xy (0, screenheight - 1);
    234  1.1  christos         terminal_clear_to_eol ();
    235  1.1  christos         fflush (stdout);
    236  1.1  christos         terminal_unprep_terminal ();
    237  1.1  christos 	restore_termsig (sig, old_signal_handler);
    238  1.1  christos 	UNBLOCK_SIGNAL (sig);
    239  1.1  christos 	kill (getpid (), sig);
    240  1.1  christos 
    241  1.1  christos         /* The program is returning now.  Restore our signal handler,
    242  1.1  christos            turn on terminal handling, redraw the screen, and place the
    243  1.1  christos            cursor where it belongs. */
    244  1.1  christos         terminal_prep_terminal ();
    245  1.1  christos 	set_termsig (sig, old_signal_handler);
    246  1.1  christos 	/* window size might be changed while sleeping */
    247  1.1  christos 	reset_info_window_sizes ();
    248  1.1  christos       }
    249  1.1  christos       break;
    250  1.1  christos 
    251  1.1  christos #if defined (SIGWINCH) || defined (SIGUSR1)
    252  1.1  christos #ifdef SIGWINCH
    253  1.1  christos     case SIGWINCH:
    254  1.1  christos #endif
    255  1.1  christos #ifdef SIGUSR1
    256  1.1  christos     case SIGUSR1:
    257  1.1  christos #endif
    258  1.1  christos       {
    259  1.1  christos 	/* Turn off terminal IO, tell our parent that the window has changed,
    260  1.1  christos 	   then reinitialize the terminal and rebuild our windows. */
    261  1.1  christos #ifdef SIGWINCH
    262  1.1  christos 	if (sig == SIGWINCH)
    263  1.1  christos 	  old_signal_handler = &old_WINCH;
    264  1.1  christos #endif
    265  1.1  christos #ifdef SIGUSR1
    266  1.1  christos 	if (sig == SIGUSR1)
    267  1.1  christos 	  old_signal_handler = &old_USR1;
    268  1.1  christos #endif
    269  1.1  christos 	terminal_goto_xy (0, 0);
    270  1.1  christos 	fflush (stdout);
    271  1.1  christos 	terminal_unprep_terminal (); /* needless? */
    272  1.1  christos 	restore_termsig (sig, old_signal_handler);
    273  1.1  christos 	UNBLOCK_SIGNAL (sig);
    274  1.1  christos 	kill (getpid (), sig);
    275  1.1  christos 
    276  1.1  christos 	/* After our old signal handler returns... */
    277  1.1  christos 	set_termsig (sig, old_signal_handler); /* needless? */
    278  1.1  christos 	terminal_prep_terminal ();
    279  1.1  christos 	reset_info_window_sizes ();
    280  1.1  christos       }
    281  1.1  christos       break;
    282  1.1  christos #endif /* SIGWINCH || SIGUSR1 */
    283  1.1  christos     }
    284  1.1  christos #if !defined (HAVE_SIGACTION)
    285  1.1  christos   /* at this time it is safer to perform unblock after decrement */
    286  1.1  christos   term_conf_busy--;
    287  1.1  christos #if defined (HAVE_SIGPROCMASK) || defined (HAVE_SIGSETMASK)
    288  1.1  christos     {
    289  1.1  christos       sigset_t nvar, ovar;
    290  1.1  christos       sigemptyset (&nvar);
    291  1.1  christos       mask_termsig (&nvar);
    292  1.1  christos       sigprocmask (SIG_UNBLOCK, &nvar, &ovar);
    293  1.1  christos     }
    294  1.1  christos #endif /* HAVE_SIGPROCMASK || HAVE_SIGSETMASK */
    295  1.1  christos #endif /* !HAVE_SIGACTION */
    296  1.1  christos }
    297  1.1  christos /* vim: set sw=2 cino={1s>2sn-s^-se-s: */
    298