home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / utilit~1 / initsnb.zoo / init / sh / trap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-09  |  6.8 KB  |  330 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Kenneth Almquist.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)trap.c    5.2 (Berkeley) 4/12/91";
  39. #endif /* not lint */
  40.  
  41. #include "shell.h"
  42. #include "main.h"
  43. #include "nodes.h"    /* for other headers */
  44. #include "eval.h"
  45. #include "jobs.h"
  46. #include "options.h"
  47. #include "syntax.h"
  48. #include "signames.h"
  49. #include "output.h"
  50. #include "memalloc.h"
  51. #include "error.h"
  52. #include "trap.h"
  53. #include "mystring.h"
  54. #include <signal.h>
  55.  
  56.  
  57. /*
  58.  * Sigmode records the current value of the signal handlers for the various
  59.  * modes.  A value of zero means that the current handler is not known.
  60.  * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
  61.  */
  62.  
  63. #define S_DFL 1            /* default signal handling (SIG_DFL) */
  64. #define S_CATCH 2        /* signal is caught */
  65. #define S_IGN 3            /* signal is ignored (SIG_IGN) */
  66. #define S_HARD_IGN 4        /* signal is ignored permenantly */
  67.  
  68.  
  69. extern char nullstr[1];        /* null string */
  70.  
  71. char *trap[MAXSIG+1];        /* trap handler commands */
  72. MKINIT char sigmode[MAXSIG];    /* current value of signal */
  73. char gotsig[MAXSIG];        /* indicates specified signal received */
  74. int pendingsigs;            /* indicates some signal received */
  75.  
  76. /*
  77.  * The trap builtin.
  78.  */
  79.  
  80. trapcmd(argc, argv)  char **argv; {
  81.     char *action;
  82.     char **ap;
  83.     int signo;
  84.  
  85.     if (argc <= 1) {
  86.         for (signo = 0 ; signo <= MAXSIG ; signo++) {
  87.             if (trap[signo] != NULL)
  88.                 out1fmt("%d: %s\n", signo, trap[signo]);
  89.         }
  90.         return 0;
  91.     }
  92.     ap = argv + 1;
  93.     if (is_number(*ap))
  94.         action = NULL;
  95.     else
  96.         action = *ap++;
  97.     while (*ap) {
  98.         if ((signo = number(*ap)) < 0 || signo > MAXSIG)
  99.             error("%s: bad trap", *ap);
  100.         INTOFF;
  101.         if (action)
  102.             action = savestr(action);
  103.         if (trap[signo])
  104.             ckfree(trap[signo]);
  105.         trap[signo] = action;
  106.         if (signo != 0)
  107.             setsignal(signo);
  108.         INTON;
  109.         ap++;
  110.     }
  111.     return 0;
  112. }
  113.  
  114.  
  115.  
  116. /*
  117.  * Clear traps on a fork.
  118.  */
  119.  
  120. void
  121. clear_traps() {
  122.     char **tp;
  123.  
  124.     for (tp = trap ; tp <= &trap[MAXSIG] ; tp++) {
  125.         if (*tp && **tp) {    /* trap not NULL or SIG_IGN */
  126.             INTOFF;
  127.             ckfree(*tp);
  128.             *tp = NULL;
  129.             if (tp != &trap[0])
  130.                 setsignal(tp - trap);
  131.             INTON;
  132.         }
  133.     }
  134. }
  135.  
  136.  
  137.  
  138. /*
  139.  * Set the signal handler for the specified signal.  The routine figures
  140.  * out what it should be set to.
  141.  */
  142.  
  143. typedef void *sig_t;
  144.  
  145. int
  146. setsignal(signo) {
  147.     int action;
  148.     sig_t sigact;
  149.     char *t;
  150.     extern void onsig();
  151.  
  152.     if ((t = trap[signo]) == NULL)
  153.         action = S_DFL;
  154.     else if (*t != '\0')
  155.         action = S_CATCH;
  156.     else
  157.         action = S_IGN;
  158.     if (rootshell && action == S_DFL) {
  159.         switch (signo) {
  160.         case SIGINT:
  161.             if (iflag)
  162.                 action = S_CATCH;
  163.             break;
  164.         case SIGQUIT:
  165. #ifdef DEBUG
  166.             {
  167.             extern int debug;
  168.  
  169.             if (debug)
  170.                 break;
  171.             }
  172. #endif
  173.             /* FALLTHROUGH */
  174.         case SIGTERM:
  175.             if (iflag)
  176.                 action = S_IGN;
  177.             break;
  178. #if JOBS
  179.         case SIGTSTP:
  180.         case SIGTTOU:
  181.             if (jflag)
  182.                 action = S_IGN;
  183.             break;
  184. #endif
  185.         }
  186.     }
  187.     t = &sigmode[signo - 1];
  188.     if (*t == 0) {    /* current setting unknown */
  189.         /*
  190.          * There is a race condition here if action is not S_IGN.
  191.          * A signal can be ignored that shouldn't be.
  192.          */
  193.         if ((int)(sigact = signal(signo, SIG_IGN)) == -1)
  194.             error("Signal system call failed");
  195.         if (sigact == SIG_IGN) {
  196.             *t = S_HARD_IGN;
  197.         } else {
  198.             *t = S_IGN;
  199.         }
  200.     }
  201.     if (*t == S_HARD_IGN || *t == action)
  202.         return 0;
  203.     switch (action) {
  204.         case S_DFL:    sigact = SIG_DFL;    break;
  205.         case S_CATCH:      sigact = onsig;        break;
  206.         case S_IGN:    sigact = SIG_IGN;    break;
  207.     }
  208.     *t = action;
  209.     return (int)signal(signo, sigact);
  210. }
  211.  
  212.  
  213. /*
  214.  * Ignore a signal.
  215.  */
  216.  
  217. void
  218. ignoresig(signo) {
  219.     if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
  220.         signal(signo, SIG_IGN);
  221.     }
  222.     sigmode[signo - 1] = S_HARD_IGN;
  223. }
  224.  
  225.  
  226. #ifdef mkinit
  227. INCLUDE "signames.h"
  228. INCLUDE "trap.h"
  229.  
  230. SHELLPROC {
  231.     char *sm;
  232.  
  233.     clear_traps();
  234.     for (sm = sigmode ; sm < sigmode + MAXSIG ; sm++) {
  235.         if (*sm == S_IGN)
  236.             *sm = S_HARD_IGN;
  237.     }
  238. }
  239. #endif
  240.  
  241.  
  242.  
  243. /*
  244.  * Signal handler.
  245.  */
  246.  
  247. void
  248. onsig(signo) {
  249.     signal(signo, onsig);
  250.     if (signo == SIGINT && trap[SIGINT] == NULL) {
  251.         onint();
  252.         return;
  253.     }
  254.     gotsig[signo - 1] = 1;
  255.     pendingsigs++;
  256. }
  257.  
  258.  
  259.  
  260. /*
  261.  * Called to execute a trap.  Perhaps we should avoid entering new trap
  262.  * handlers while we are executing a trap handler.
  263.  */
  264.  
  265. void
  266. dotrap() {
  267.     int i;
  268.     int savestatus;
  269.  
  270.     for (;;) {
  271.         for (i = 1 ; ; i++) {
  272.             if (gotsig[i - 1])
  273.                 break;
  274.             if (i >= MAXSIG)
  275.                 goto done;
  276.         }
  277.         gotsig[i - 1] = 0;
  278.         savestatus=exitstatus;
  279.         evalstring(trap[i]);
  280.         exitstatus=savestatus;
  281.     }
  282. done:
  283.     pendingsigs = 0;
  284. }
  285.  
  286.  
  287.  
  288. /*
  289.  * Controls whether the shell is interactive or not.
  290.  */
  291.  
  292. int is_interactive;
  293.  
  294. void
  295. setinteractive(on) {
  296.     if (on == is_interactive)
  297.         return;
  298.     setsignal(SIGINT);
  299.     setsignal(SIGQUIT);
  300.     setsignal(SIGTERM);
  301.     is_interactive = on;
  302. }
  303.  
  304.  
  305.  
  306. /*
  307.  * Called to exit the shell.
  308.  */
  309.  
  310. void
  311. exitshell(status) {
  312.     struct jmploc loc1, loc2;
  313.     char *p;
  314.  
  315.     TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
  316.     if (setjmp(loc1.loc))  goto l1;
  317.     if (setjmp(loc2.loc))  goto l2;
  318.     handler = &loc1;
  319.     if ((p = trap[0]) != NULL && *p != '\0') {
  320.         trap[0] = NULL;
  321.         evalstring(p);
  322.     }
  323. l1:   handler = &loc2;            /* probably unnecessary */
  324.     flushall();
  325. #if JOBS
  326.     setjobctl(0);
  327. #endif
  328. l2:   _exit(status);
  329. }
  330.