home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / tc.sig.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  8.7 KB  |  413 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/tc.sig.c,v 3.13 1992/10/14 20:19:19 christos Exp $ */
  2. /*
  3.  * tc.sig.c: Signal routine emulations
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: tc.sig.c,v 3.13 1992/10/14 20:19:19 christos Exp $")
  40.  
  41. #include "tc.wait.h"
  42.  
  43. #ifndef BSDSIGS
  44.  
  45. /* this stack is used to queue signals
  46.  * we can handle up to MAX_CHLD outstanding children now;
  47.  */
  48. #define MAX_CHLD 50
  49. static struct mysigstack {
  50.     int     s_w;        /* wait report             */
  51.     int     s_errno;        /* errno returned;         */
  52.     pid_t   s_pid;        /* pid returned             */
  53. }       stk[MAX_CHLD];
  54. static int stk_ptr = -1;
  55.  
  56.  
  57. # ifdef UNRELSIGS
  58. /* queue child signals
  59.  */
  60. static sigret_t
  61. sig_ch_queue()
  62. {
  63. #  ifdef JOBDEBUG
  64.     xprintf("queue SIGCHLD\n");
  65.     flush();
  66. #  endif /* JOBDEBUG */
  67.     stk_ptr++;
  68.     stk[stk_ptr].s_pid = (pid_t) wait(&stk[stk_ptr].s_w);
  69.     stk[stk_ptr].s_errno = errno;
  70.     (void) signal(SIGCHLD, sig_ch_queue);
  71. #  ifndef SIGVOID
  72.     return(0);
  73. #  endif /* SIGVOID */
  74. }
  75.  
  76. /* process all awaiting child signals
  77.  */
  78. static sigret_t
  79. sig_ch_rel()
  80. {
  81.     while (stk_ptr > -1)
  82.     pchild(SIGCHLD);
  83. #  ifdef JOBDEBUG
  84.     xprintf("signal(SIGCHLD, pchild);\n");
  85. #  endif /* JOBDEBUG */
  86.     (void) signal(SIGCHLD, pchild);
  87. #  ifndef SIGVOID
  88.     return(0);
  89. #  endif /* SIGVOID */
  90. }
  91.  
  92.  
  93. /* libc.a contains these functions in SYSVREL >= 3. */
  94. sigret_t
  95. (*xsigset(a, b)) ()
  96.     int     a;
  97.     sigret_t  (*b) __P((int));
  98. {
  99.     return (signal(a, b));
  100. }
  101.  
  102. /* release signal
  103.  *    release all queued signals and
  104.  *    set the default signal handler
  105.  */
  106. void
  107. sigrelse(what)
  108.     int     what;
  109. {
  110.     if (what == SIGCHLD)
  111.     sig_ch_rel();
  112.  
  113. #  ifdef COHERENT
  114.     (void) signal(what, what == SIGINT ? pintr : SIG_DFL);
  115. #  endif /* COHERENT */
  116. }
  117.  
  118. /* hold signal
  119.  * only works with child and interrupt
  120.  */
  121. void
  122. xsighold(what)
  123.     int     what;
  124. {
  125.     if (what == SIGCHLD)
  126.     (void) signal(SIGCHLD, sig_ch_queue);
  127.  
  128. #  ifdef COHERENT
  129.     (void) signal(what, SIG_IGN);
  130. #  endif /* COHERENT */
  131. }
  132.  
  133. /* ignore signal
  134.  */
  135. void
  136. xsigignore(a)
  137.     int     a;
  138. {
  139.     (void) signal(a, SIG_IGN);
  140. }
  141.  
  142. /* atomically release one signal
  143.  */
  144. void
  145. xsigpause(what)
  146.     int     what;
  147. {
  148.     /* From: Jim Mattson <mattson%cs@ucsd.edu> */
  149.     if (what == SIGCHLD)
  150.     pchild(SIGCHLD);
  151. }
  152.  
  153.  
  154. /* return either awaiting processes or do a wait now
  155.  */
  156. pid_t
  157. ourwait(w)
  158.     int    *w;
  159. {
  160.     pid_t pid;
  161.  
  162. #  ifdef JOBDEBUG
  163.     xprintf("our wait %d\n", stk_ptr);
  164.     flush();
  165. #  endif /* JOBDEBUG */
  166.  
  167.     if (stk_ptr == -1) {
  168.     /* stack empty return signal from stack */
  169.     pid = (pid_t) wait(w);
  170. #  ifdef JOBDEBUG
  171.     xprintf("signal(SIGCHLD, pchild);\n");
  172. #  endif /* JOBDEBUG */
  173.     (void) signal(SIGCHLD, pchild);
  174.     return (pid);
  175.     }
  176.     else {
  177.     /* return signal from stack */
  178.     errno = stk[stk_ptr].s_errno;
  179.     *w = stk[stk_ptr].s_w;
  180.     stk_ptr--;
  181.     return (stk[stk_ptr + 1].s_pid);
  182.     }
  183. } /* end ourwait */
  184.  
  185. #  ifdef COHERENT
  186. #   undef signal
  187. sigret_t
  188. (*xsignal(a, b)) ()
  189.     int     a;
  190.     sigret_t  (*b) __P((int));
  191. {
  192.     if (a == SIGCHLD)
  193.     return SIG_DFL;
  194.     else
  195.     return (signal(a, b));
  196. }
  197. #  endif /* COHERENT */
  198.  
  199. # endif /* UNRELSIGS */
  200.  
  201. # ifdef SXA
  202. /*
  203.  * SX/A is SYSVREL3 but does not have sys5-sigpause().
  204.  * I've heard that sigpause() is not defined in SYSVREL3.
  205.  */
  206. /* This is not need if you make tcsh by BSD option's cc. */
  207. void
  208. sigpause(what)
  209. {
  210.     if (what == SIGCHLD) {
  211.     bsd_sigpause(bsd_sigblock((sigmask_t) 0) & ~sigmask(SIGBSDCHLD));
  212.     }
  213.     else if (what == 0) {
  214.     pause();
  215.     }
  216.     else {
  217.     xprintf("sigpause(%d)\n", what);
  218.     pause();
  219.     }
  220. }
  221. # endif /* SXA */
  222.  
  223. #endif /* !BSDSIGS */
  224.  
  225. #ifdef NEEDsignal
  226. /* turn into bsd signals */
  227. sigret_t(*
  228.      xsignal(s, a)) ()
  229.     int     s;
  230.     sigret_t (*a) __P((int));
  231. {
  232.     sigvec_t osv, sv;
  233.  
  234.     (void) mysigvec(s, NULL, &osv);
  235.     sv = osv;
  236.     sv.sv_handler = a;
  237. #ifdef SIG_STK
  238.     sv.sv_onstack = SIG_STK;
  239. #endif /* SIG_STK */
  240. #ifdef SV_BSDSIG
  241.     sv.sv_flags = SV_BSDSIG;
  242. #endif /* SV_BSDSIG */
  243.  
  244.     if (mysigvec(s, &sv, NULL) < 0)
  245.     return (BADSIG);
  246.     return (osv.sv_handler);
  247. }
  248.  
  249. #endif /* NEEDsignal */
  250.  
  251. #ifdef POSIXSIGS
  252. /*
  253.  * Support for signals.
  254.  */
  255.  
  256. extern int errno;
  257.  
  258. /* Set and test a bit.  Bits numbered 1 to 32 */
  259.  
  260. #define SETBIT(x, y)    x |= sigmask(y)
  261. #define ISSET(x, y)    ((x & sigmask(y)) != 0)
  262.  
  263. #ifdef DEBUG
  264. # define SHOW_SIGNALS    1    /* to assist in debugging signals */
  265. #endif /* DEBUG */
  266.  
  267. #ifdef SHOW_SIGNALS
  268. char   *show_sig_mask();
  269. #endif /* SHOW_SIGNALS */
  270.  
  271. int     debug_signals = 0;
  272.  
  273. /*
  274.  * sigsetmask(mask)
  275.  *
  276.  * Set a new signal mask.  Return old mask.
  277.  */
  278. sigmask_t
  279. sigsetmask(mask)
  280.     sigmask_t     mask;
  281. {
  282.     sigset_t set, oset;
  283.     int     m;
  284.     register int i;
  285.  
  286.     sigemptyset(&set);
  287.     sigemptyset(&oset);
  288.  
  289.     for (i = 1; i <= MAXSIG; i++)
  290.     if (ISSET(mask, i))
  291.         sigaddset(&set, i);
  292.  
  293.     if (sigprocmask(SIG_SETMASK, &set, &oset))
  294.     xprintf("sigsetmask(0x%x) - sigprocmask failed, errno %d",
  295.         mask, errno);
  296.  
  297.     m = 0;
  298.     for (i = 1; i <= MAXSIG; i++)
  299.     if (sigismember(&oset, i))
  300.         SETBIT(m, i);
  301.  
  302.     return (m);
  303. }
  304.  
  305. /*
  306.  * sigblock(mask)
  307.  *
  308.  * Add "mask" set of signals to the present signal mask.
  309.  * Return old mask.
  310.  */
  311. sigmask_t
  312. sigblock(mask)
  313.     sigmask_t     mask;
  314. {
  315.     sigset_t set, oset;
  316.     int     m;
  317.     register int i;
  318.  
  319.     sigemptyset(&set);
  320.     sigemptyset(&oset);
  321.  
  322.     /* Get present set of signals. */
  323.     if (sigprocmask(SIG_SETMASK, NULL, &set))
  324.     xprintf("sigblock(0x%x) - sigprocmask failed, errno %d",
  325.         mask, errno);
  326.  
  327.     /* Add in signals from mask. */
  328.     for (i = 1; i <= MAXSIG; i++)
  329.     if (ISSET(mask, i))
  330.         sigaddset(&set, i);
  331.  
  332.     sigprocmask(SIG_SETMASK, &set, &oset);
  333.  
  334.     /* Return old mask to user. */
  335.     m = 0;
  336.     for (i = 1; i <= MAXSIG; i++)
  337.     if (sigismember(&oset, i))
  338.         SETBIT(m, i);
  339.  
  340.     return (m);
  341. }
  342.  
  343.  
  344. /*
  345.  * bsd_sigpause(mask)
  346.  *
  347.  * Set new signal mask and wait for signal;
  348.  * Old mask is restored on signal.
  349.  */
  350. void
  351. bsd_sigpause(mask)
  352.     sigmask_t     mask;
  353. {
  354.     sigset_t set;
  355.     register int i;
  356.  
  357.     sigemptyset(&set);
  358.  
  359.     for (i = 1; i <= MAXSIG; i++)
  360.     if (ISSET(mask, i))
  361.         sigaddset(&set, i);
  362.     sigsuspend(&set);
  363. }
  364.  
  365. /*
  366.  * bsd_signal(sig, func)
  367.  *
  368.  * Emulate bsd style signal()
  369.  */
  370. sigret_t (*bsd_signal(sig, func))()
  371.         int sig;
  372.         sigret_t (*func)();
  373. {
  374.         struct sigaction act, oact;
  375.         sigset_t set;
  376.         sigret_t (*r_func)();
  377.  
  378.         if (sig < 0 || sig > MAXSIG) {
  379.                 xprintf("error: bsd_signal(%d) signal out of range\n", sig);
  380.                 return((sigret_t(*)()) SIG_IGN);
  381.         }
  382.  
  383.         sigemptyset(&set);
  384.  
  385.         act.sa_handler = (sigret_t(*)()) func;      /* user function */
  386.         act.sa_mask = set;                      /* signal mask */
  387.         act.sa_flags = 0;                       /* no special actions */
  388.  
  389.         if (sigaction(sig, &act, &oact)) {
  390.                 xprintf("error: bsd_signal(%d) - sigaction failed, errno %d\n",
  391.                     sig, errno);
  392.                 return((sigret_t(*)()) SIG_IGN);
  393.         }
  394.  
  395.         r_func = (sigret_t(*)()) oact.sa_handler;
  396.         return(r_func);
  397. }
  398. #endif /* POSIXSIG */
  399.  
  400.  
  401. #ifdef SIGSYNCH
  402. static long Synch_Cnt = 0;
  403.  
  404. sigret_t
  405. synch_handler(sno)
  406. int sno;
  407. {
  408.     if (sno != SIGSYNCH)
  409.     abort();
  410.     Synch_Cnt++;
  411. }
  412. #endif /* SIGSYNCH */
  413.