home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Shells / zsh-3.0.5-MIHS / src / Src / signals.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-25  |  18.1 KB  |  729 lines

  1. /*
  2.  * $Id: signals.c,v 2.24 1996/10/15 20:16:35 hzoli Exp $
  3.  *
  4.  * signals.c - signals handling code
  5.  *
  6.  * This file is part of zsh, the Z shell.
  7.  *
  8.  * Copyright (c) 1992-1996 Paul Falstad
  9.  * All rights reserved.
  10.  *
  11.  * Permission is hereby granted, without written agreement and without
  12.  * license or royalty fees, to use, copy, modify, and distribute this
  13.  * software and to distribute modified versions of this software for any
  14.  * purpose, provided that the above copyright notice and the following
  15.  * two paragraphs appear in all copies of this software.
  16.  *
  17.  * In no event shall Paul Falstad or the Zsh Development Group be liable
  18.  * to any party for direct, indirect, special, incidental, or consequential
  19.  * damages arising out of the use of this software and its documentation,
  20.  * even if Paul Falstad and the Zsh Development Group have been advised of
  21.  * the possibility of such damage.
  22.  *
  23.  * Paul Falstad and the Zsh Development Group specifically disclaim any
  24.  * warranties, including, but not limited to, the implied warranties of
  25.  * merchantability and fitness for a particular purpose.  The software
  26.  * provided hereunder is on an "as is" basis, and Paul Falstad and the
  27.  * Zsh Development Group have no obligation to provide maintenance,
  28.  * support, updates, enhancements, or modifications.
  29.  *
  30.  */
  31.  
  32. #include "zsh.h"
  33.  
  34. /* This is only used on machines that don't understand signal sets.  *
  35.  * On SYSV machines this will represent the signals that are blocked *
  36.  * (held) using sighold.  On machines which can't block signals at   *
  37.  * all, we will simulate this by ignoring them and remembering them  *
  38.  * in this variable.                                                 */
  39. #if !defined(POSIX_SIGNALS) && !defined(BSD_SIGNALS)
  40. static sigset_t blocked_set;
  41. #endif
  42.  
  43. #ifdef POSIX_SIGNALS
  44. # define signal_jmp_buf       sigjmp_buf
  45. # define signal_setjmp(b)     sigsetjmp((b),1)
  46. # define signal_longjmp(b,n)  siglongjmp((b),(n))
  47. #else
  48. # define signal_jmp_buf       jmp_buf
  49. # define signal_setjmp(b)     setjmp(b)
  50. # define signal_longjmp(b,n)  longjmp((b),(n))
  51. #endif
  52.  
  53. #ifdef NO_SIGNAL_BLOCKING
  54. # define signal_process(sig)  signal_ignore(sig)
  55. # define signal_reset(sig)    install_handler(sig)
  56. #else
  57. # define signal_process(sig)  ;
  58. # define signal_reset(sig)    ;
  59. #endif
  60.  
  61. /* Install signal handler for given signal.           *
  62.  * If possible, we want to make sure that interrupted *
  63.  * system calls are not restarted.                    */
  64.  
  65. /**/
  66. void
  67. install_handler(int sig)
  68. {
  69. #ifdef POSIX_SIGNALS
  70.     struct sigaction act;
  71.  
  72.     act.sa_handler = (SIGNAL_HANDTYPE) handler;
  73.     sigemptyset(&act.sa_mask);        /* only block sig while in handler */
  74.     act.sa_flags = 0;
  75. # ifdef SA_INTERRUPT                  /* SunOS 4.x */
  76.     if (interact)
  77.         act.sa_flags |= SA_INTERRUPT; /* make sure system calls are not restarted */
  78. # endif
  79.     sigaction(sig, &act, (struct sigaction *)NULL);
  80. #else
  81. # ifdef BSD_SIGNALS
  82.     struct sigvec vec;
  83.  
  84.     vec.sv_handler = (SIGNAL_HANDTYPE) handler;
  85.     vec.sv_mask = sigmask(sig);    /* mask out this signal while in handler    */
  86. #  ifdef SV_INTERRUPT
  87.     vec.sv_flags = SV_INTERRUPT;   /* make sure system calls are not restarted */
  88. #  endif
  89.     sigvec(sig, &vec, (struct sigvec *)NULL);
  90. # else
  91. #  ifdef SYSV_SIGNALS
  92.     /* we want sigset rather than signal because it will   *
  93.      * block sig while in handler.  signal usually doesn't */
  94.     sigset(sig, handler);
  95. #  else  /* NO_SIGNAL_BLOCKING (bummer) */
  96.     signal(sig, handler);
  97.  
  98. #  endif /* SYSV_SIGNALS  */
  99. # endif  /* BSD_SIGNALS   */
  100. #endif   /* POSIX_SIGNALS */
  101. }
  102.  
  103. /* enable ^C interrupts */
  104.  
  105. /**/
  106. void
  107. intr(void)
  108. {
  109.     if (interact)
  110.         install_handler(SIGINT);
  111. }
  112.  
  113. /* disable ^C interrupts */
  114.  
  115. /**/
  116. void
  117. nointr(void)
  118. {
  119.     if (interact)
  120.         signal_ignore(SIGINT);
  121. }
  122.  
  123. /* temporarily block ^C interrupts */
  124.  
  125. /**/
  126. void
  127. holdintr(void)
  128. {
  129.     if (interact)
  130.         signal_block(signal_mask(SIGINT));
  131. }
  132.  
  133. /* release ^C interrupts */
  134.  
  135. /**/
  136. void
  137. noholdintr(void)
  138. {
  139.     if (interact)
  140.         signal_unblock(signal_mask(SIGINT));
  141. }
  142.  
  143. /* create a signal mask containing *
  144.  * only the given signal           */
  145.  
  146. /**/
  147. sigset_t
  148. signal_mask(int sig)
  149. {
  150.     sigset_t set;
  151.  
  152.     sigemptyset(&set);
  153.     if (sig)
  154.         sigaddset(&set, sig);
  155.     return set;
  156. }
  157.  
  158. /* Block the signals in the given signal *
  159.  * set. Return the old signal set.       */
  160.  
  161. /**/
  162. sigset_t
  163. signal_block(sigset_t set)
  164. {
  165.     sigset_t oset;
  166.  
  167. #ifdef POSIX_SIGNALS
  168.     sigprocmask(SIG_BLOCK, &set, &oset);
  169. #else
  170. # ifdef BSD_SIGNALS
  171.     oset = sigblock(set);
  172. # else
  173. #  ifdef SYSV_SIGNALS
  174.     int i;
  175.  
  176.     oset = blocked_set;
  177.     for (i = 1; i <= NSIG; ++i) {
  178.         if (sigismember(&set, i) && !sigismember(&blocked_set, i)) {
  179.             sigaddset(&blocked_set, i);
  180.             sighold(i);
  181.         }
  182.     }
  183. #  else  /* NO_SIGNAL_BLOCKING */
  184. /* We will just ignore signals if the system doesn't have *
  185.  * the ability to block them.                             */
  186.     int i;
  187.  
  188.     oset = blocked_set;
  189.     for (i = 1; i <= NSIG; ++i) {
  190.         if (sigismember(&set, i) && !sigismember(&blocked_set, i)) {
  191.             sigaddset(&blocked_set, i);
  192.             signal_ignore(i);
  193.         }
  194.    }
  195. #  endif /* SYSV_SIGNALS  */
  196. # endif  /* BSD_SIGNALS   */
  197. #endif   /* POSIX_SIGNALS */
  198.  
  199.     return oset;
  200. }
  201.  
  202. /* Unblock the signals in the given signal *
  203.  * set. Return the old signal set.         */
  204.  
  205. /**/
  206. sigset_t
  207. signal_unblock(sigset_t set)
  208. {
  209.     sigset_t oset;
  210.  
  211. #ifdef POSIX_SIGNALS
  212.     sigprocmask(SIG_UNBLOCK, &set, &oset);
  213. #else
  214. # ifdef BSD_SIGNALS
  215.     sigfillset(&oset);
  216.     oset = sigsetmask(oset);
  217.     sigsetmask(oset & ~set);
  218. # else
  219. #  ifdef SYSV_SIGNALS
  220.     int i;
  221.  
  222.     oset = blocked_set;
  223.     for (i = 1; i <= NSIG; ++i) {
  224.         if (sigismember(&set, i) && sigismember(&blocked_set, i)) {
  225.             sigdelset(&blocked_set, i);
  226.             sigrelse(i);
  227.         }
  228.     }
  229. #  else  /* NO_SIGNAL_BLOCKING */
  230. /* On systems that can't block signals, we are just ignoring them.  So *
  231.  * to unblock signals, we just reenable the signal handler for them.   */
  232.     int i;
  233.  
  234.     oset = blocked_set;
  235.     for (i = 1; i <= NSIG; ++i) {
  236.         if (sigismember(&set, i) && sigismember(&blocked_set, i)) {
  237.             sigdelset(&blocked_set, i);
  238.             install_handler(i);
  239.         }
  240.    }
  241. #  endif /* SYSV_SIGNALS  */
  242. # endif  /* BSD_SIGNALS   */
  243. #endif   /* POSIX_SIGNALS */
  244.  
  245.     return oset;
  246. }
  247.  
  248. /* set the process signal mask to *
  249.  * be the given signal mask       */
  250.  
  251. /**/
  252. sigset_t
  253. signal_setmask(sigset_t set)
  254. {
  255.     sigset_t oset;
  256.  
  257. #ifdef POSIX_SIGNALS
  258.     sigprocmask(SIG_SETMASK, &set, &oset);
  259. #else
  260. # ifdef BSD_SIGNALS
  261.     oset = sigsetmask(set);
  262. # else
  263. #  ifdef SYSV_SIGNALS
  264.     int i;
  265.  
  266.     oset = blocked_set;
  267.     for (i = 1; i <= NSIG; ++i) {
  268.         if (sigismember(&set, i) && !sigismember(&blocked_set, i)) {
  269.             sigaddset(&blocked_set, i);
  270.             sighold(i);
  271.         } else if (!sigismember(&set, i) && sigismember(&blocked_set, i)) {
  272.             sigdelset(&blocked_set, i);
  273.             sigrelse(i);
  274.         }
  275.     }
  276. #  else  /* NO_SIGNAL_BLOCKING */
  277.     int i;
  278.  
  279.     oset = blocked_set;
  280.     for (i = 1; i < NSIG; ++i) {
  281.         if (sigismember(&set, i) && !sigismember(&blocked_set, i)) {
  282.             sigaddset(&blocked_set, i);
  283.             signal_ignore(i);
  284.         } else if (!sigismember(&set, i) && sigismember(&blocked_set, i)) {
  285.             sigdelset(&blocked_set, i);
  286.             install_handler(i);
  287.         }
  288.     }
  289. #  endif /* SYSV_SIGNALS  */
  290. # endif  /* BSD_SIGNALS   */
  291. #endif   /* POSIX_SIGNALS */
  292.  
  293.     return oset;
  294. }
  295.  
  296. #if defined(NO_SIGNAL_BLOCKING)
  297. static int suspend_longjmp = 0;
  298. static signal_jmp_buf suspend_jmp_buf;
  299. #endif
  300.  
  301. /**/
  302. int
  303. signal_suspend(int sig, int sig2)
  304. {
  305.     int ret;
  306.  
  307. #ifdef POSIX_SIGNALS
  308.     sigset_t set;
  309.  
  310.     sigfillset(&set);
  311.     sigdelset(&set, sig);
  312.     sigdelset(&set, SIGHUP);  /* still don't know why we add this? */
  313.     if (sig2)
  314.         sigdelset(&set, sig2);
  315.     ret = sigsuspend(&set);
  316. #else
  317. # ifdef BSD_SIGNALS
  318.     sigset_t set;
  319.  
  320.     sigfillset(&set);
  321.     sigdelset(&set, sig);
  322.     if (sig2)
  323.       sigdelset(&set, sig2);
  324.     ret = sigpause(set);
  325. # else
  326. #  ifdef SYSV_SIGNALS
  327.     ret = sigpause(sig);
  328.  
  329. #  else  /* NO_SIGNAL_BLOCKING */
  330.     /* need to use signal_longjmp to make this race-free *
  331.      * between the child_unblock() and pause()           */
  332.     if (signal_setjmp(suspend_jmp_buf) == 0) {
  333.         suspend_longjmp = 1;   /* we want to signal_longjmp after catching signal */
  334.         child_unblock();       /* do we need to unblock sig2 as well?             */
  335.         ret = pause();
  336.     }
  337.     suspend_longjmp = 0;       /* turn off using signal_longjmp since we are past *
  338.                                 * the pause() function.                           */
  339. #  endif /* SYSV_SIGNALS  */
  340. # endif  /* BSD_SIGNALS   */
  341. #endif   /* POSIX_SIGNALS */
  342.  
  343.     return ret;
  344. }
  345.  
  346. /* What flavor of waitpid/wait3/wait shall we use? */
  347.  
  348. #ifdef HAVE_WAITPID
  349. # define  WAIT(pid, statusp, options) waitpid(pid, statusp, options)
  350. #else
  351. # ifdef HAVE_WAIT3
  352. #  define WAIT(pid, statusp, options) wait3((void *) statusp, options, NULL)
  353. # else
  354. #  define WAIT(pid, statusp, options) wait(statusp)
  355. # endif
  356. #endif
  357.  
  358. /* the signal handler */
  359.  
  360. /**/
  361. RETSIGTYPE
  362. handler(int sig)
  363. {
  364.     sigset_t newmask, oldmask;
  365.  
  366. #if defined(NO_SIGNAL_BLOCKING)
  367.     int do_jump;
  368.     signal_jmp_buf jump_to;
  369. #endif
  370.  
  371.     signal_process(sig);
  372.  
  373.     sigfillset(&newmask);
  374.     oldmask = signal_block(newmask);        /* Block all signals temporarily           */
  375.  
  376. #if defined(NO_SIGNAL_BLOCKING)
  377.     do_jump = suspend_longjmp;              /* do we need to longjmp to signal_suspend */
  378.     suspend_longjmp = 0;                    /* In case a SIGCHLD somehow arrives       */
  379.  
  380.     if (sig == SIGCHLD) {                   /* Traps can cause nested child_suspend()  */
  381.         if (do_jump)
  382.             jump_to = suspend_jmp_buf;      /* Copy suspend_jmp_buf                    */
  383.     }
  384. #endif
  385.  
  386.     if (queueing_enabled) {           /* Are we queueing signals now?      */
  387.         int temp_rear = ++queue_rear % MAX_QUEUE_SIZE;
  388.  
  389.     DPUTS(temp_rear == queue_front, "BUG: signal queue full");
  390.         if (temp_rear != queue_front) { /* Make sure it's not full (extremely unlikely) */
  391.             queue_rear = temp_rear;                  /* ok, not full, so add to queue   */
  392.             signal_queue[queue_rear] = sig;          /* save signal caught              */
  393.             signal_mask_queue[queue_rear] = oldmask; /* save current signal mask        */
  394.         }
  395.         signal_reset(sig);
  396.         return;
  397.     }
  398.  
  399.     signal_setmask(oldmask);          /* Reset signal mask, signal traps ok now */
  400.  
  401.     switch (sig) {
  402.     case SIGCHLD:
  403.  
  404.     /* keep WAITING until no more child processes to reap */
  405.     for (;;)
  406.       cont: {
  407.             int old_errno = errno; /* save the errno, since WAIT may change it */
  408.         int status;
  409.         Job jn;
  410.         Process pn;
  411.             pid_t pid;
  412.         pid_t *procsubpid = &cmdoutpid;
  413.         int *procsubval = &cmdoutval;
  414.         struct execstack *es = exstack;
  415.  
  416.             pid = WAIT(-1, &status, WNOHANG|WUNTRACED);  /* reap the child process */
  417.  
  418.             if (!pid)  /* no more children to reap */
  419.                 break;
  420.  
  421.         /* check if child returned was from process substitution */
  422.         for (;;) {
  423.         if (pid == *procsubpid) {
  424.             *procsubpid = 0;
  425.             if (WIFSIGNALED(status))
  426.             *procsubval = (0200 | WTERMSIG(status));
  427.             else
  428.             *procsubval = WEXITSTATUS(status);
  429.             times(&shtms);
  430.             goto cont;
  431.         }
  432.         if (!es)
  433.             break;
  434.         procsubpid = &es->cmdoutpid;
  435.         procsubval = &es->cmdoutval;
  436.         es = es->next;
  437.         }
  438.  
  439.         /* check for WAIT error */
  440.             if (pid == -1) {
  441.                 if (errno != ECHILD)
  442.                     zerr("wait failed: %e", NULL, errno);
  443.                 errno = old_errno;    /* WAIT changed errno, so restore the original */
  444.                 break;
  445.             }
  446.  
  447.         /* Find the process and job containing this pid and update it. */
  448.         if (findproc(pid, &jn, &pn)) {
  449.         update_process(pn, status);
  450.         update_job(jn);
  451.         } else {
  452.         /* If not found, update the shell record of time spent by
  453.          * children in sub processes anyway:  otherwise, this
  454.          * will get added on to the next found process that terminates.
  455.          */
  456.         times(&shtms);
  457.         }
  458.         }
  459.         break;
  460.  
  461.     case SIGHUP:
  462.         if (sigtrapped[SIGHUP])
  463.             dotrap(SIGHUP);
  464.         else {
  465.             stopmsg = 1;
  466.             zexit(SIGHUP, 1);
  467.         }
  468.         break;
  469.  
  470.     case SIGINT:
  471.         if (sigtrapped[SIGINT])
  472.             dotrap(SIGINT);
  473.         else {
  474.             extern int list_pipe, simple_pline;
  475.  
  476.         if (isset(PRIVILEGED) && isset(INTERACTIVE) && noerrexit < 0)
  477.         zexit(SIGINT, 1);
  478.             if (list_pipe || chline || simple_pline) {
  479.                 breaks = loops;
  480.                 errflag = 1;
  481.         inerrflush();
  482.             }
  483.         }
  484.         break;
  485.  
  486. #ifdef SIGWINCH
  487.     case SIGWINCH:
  488.         adjustwinsize(1);  /* check window size and adjust */
  489.     if (sigtrapped[SIGWINCH])
  490.         dotrap(SIGWINCH);
  491.         break;
  492. #endif
  493.  
  494.     case SIGALRM:
  495.         if (sigtrapped[SIGALRM]) {
  496.         int tmout;
  497.             dotrap(SIGALRM);
  498.             if ((tmout = getiparam("TMOUT")))
  499.                 alarm(tmout);           /* reset the alarm */
  500.         } else {
  501.         int idle = ttyidlegetfn(NULL);
  502.         int tmout = getiparam("TMOUT");
  503.         if (idle >= 0 && idle < tmout)
  504.         alarm(tmout - idle);
  505.         else {
  506.         errflag = noerrs = 0;
  507.         zerr("timeout", NULL, 0);
  508.         errflag = 0;
  509.         stopmsg = 1;
  510.         zexit(SIGALRM, 1);
  511.         }
  512.         }
  513.         break;
  514.  
  515.     default:
  516.         dotrap(sig);
  517.         break;
  518.     }   /* end of switch(sig) */
  519.  
  520.     signal_reset(sig);
  521.  
  522. /* This is used to make signal_suspend() race-free */
  523. #if defined(NO_SIGNAL_BLOCKING)
  524.     if (do_jump)
  525.         signal_longjmp(jump_to, 1);
  526. #endif
  527.  
  528. } /* handler */
  529.  
  530.  
  531. /* SIGHUP any jobs left running */
  532.  
  533. /**/
  534. void
  535. killrunjobs(int from_signal)
  536. {
  537.     int i, killed = 0;
  538.  
  539.     if (unset(HUP))
  540.         return;
  541.     for (i = 1; i < MAXJOB; i++)
  542.         if ((from_signal || i != thisjob) && (jobtab[i].stat & STAT_LOCKED) &&
  543.             !(jobtab[i].stat & STAT_NOPRINT) &&
  544.             !(jobtab[i].stat & STAT_STOPPED)) {
  545.             if (killpg(jobtab[i].gleader, SIGHUP) != -1)
  546.                 killed++;
  547.         }
  548.     if (killed)
  549.         zerr("warning: %d jobs SIGHUPed", NULL, killed);
  550. }
  551.  
  552.  
  553. /* send a signal to a job (simply involves kill if monitoring is on) */
  554.  
  555. /**/
  556. int
  557. killjb(Job jn, int sig)
  558. {
  559.     Process pn;
  560.     int err = 0;
  561.  
  562.     if (jobbing) {
  563.         if (jn->stat & STAT_SUPERJOB) {
  564.             if (sig == SIGCONT) {
  565.                 for (pn = jobtab[jn->other].procs; pn; pn = pn->next)
  566.                     kill(pn->pid, sig);
  567.  
  568.                 for (pn = jn->procs; pn->next; pn = pn->next)
  569.                     err = kill(pn->pid, sig);
  570.  
  571.                 return err;
  572.             }
  573.  
  574.             killpg(jobtab[jn->other].gleader, sig);
  575.             return killpg(jn->gleader, sig);
  576.         }
  577.         else
  578.             return (killpg(jn->gleader, sig));
  579.     }
  580.     for (pn = jn->procs; pn; pn = pn->next)
  581.         if ((err = kill(pn->pid, sig)) == -1 && errno != ESRCH)
  582.             return -1;
  583.     return err;
  584. }
  585.  
  586. /**/
  587. int
  588. settrap(int sig, List l)
  589. {
  590.     if (sig == -1)
  591.         return 1;
  592.     if (jobbing && (sig == SIGTTOU || sig == SIGTSTP || sig == SIGTTIN)) {
  593.         zerr("can't trap SIG%s in interactive shells", sigs[sig], 0);
  594.         return 1;
  595.     }
  596.     if (sigfuncs[sig])
  597.     unsettrap(sig);
  598.     sigfuncs[sig] = l;
  599.     if (!l) {
  600.     sigtrapped[sig] = ZSIG_IGNORED;
  601.         if (sig && sig <= SIGCOUNT &&
  602. #ifdef SIGWINCH
  603.             sig != SIGWINCH &&
  604. #endif
  605.             sig != SIGCHLD)
  606.             signal_ignore(sig);
  607.     } else {
  608.         sigtrapped[sig] = ZSIG_TRAPPED;
  609.         if (sig && sig <= SIGCOUNT &&
  610. #ifdef SIGWINCH
  611.             sig != SIGWINCH &&
  612. #endif
  613.             sig != SIGCHLD)
  614.             install_handler(sig);
  615.     }
  616.     return 0;
  617. }
  618.  
  619. /**/
  620. void
  621. unsettrap(int sig)
  622. {
  623.     int trapped;
  624.  
  625.     if (sig == -1 || !(trapped = sigtrapped[sig]) ||
  626.     (jobbing && (sig == SIGTTOU || sig == SIGTSTP || sig == SIGTTIN))) {
  627.         return;
  628.     }
  629.     sigtrapped[sig] = 0;
  630.     if (sig == SIGINT && interact) {
  631.     /* PWS 1995/05/16:  added test for interactive, also noholdintr() *
  632.      * as subshells ignoring SIGINT have it blocked from delivery     */
  633.         intr();
  634.     noholdintr();
  635.     } else if (sig == SIGHUP)
  636.         install_handler(sig);
  637.     else if (sig && sig <= SIGCOUNT &&
  638. #ifdef SIGWINCH
  639.              sig != SIGWINCH &&
  640. #endif
  641.              sig != SIGCHLD)
  642.         signal_default(sig);
  643.     if (trapped & ZSIG_FUNC) {
  644.     char func[20];
  645.     HashNode hn;
  646.  
  647.     sprintf(func, "TRAP%s", sigs[sig]);
  648.     if ((hn = shfunctab->removenode(shfunctab, func)))
  649.         shfunctab->freenode(hn);
  650.     } else if (sigfuncs[sig]) {
  651.     freestruct(sigfuncs[sig]);
  652.     sigfuncs[sig] = NULL;
  653.     }
  654. }
  655.  
  656. /* Execute a trap function for a given signal, possibly
  657.  * with non-standard sigtrapped & sigfuncs values
  658.  */
  659.  
  660. /**/
  661. void
  662. dotrapargs(int sig, int *sigtr, void *sigfn)
  663. {
  664.     LinkList args;
  665.     char *name, num[4];
  666.     int trapret = 0;
  667.     int obreaks = breaks;
  668.  
  669.     /* if signal is being ignored or the trap function              *
  670.      * is NULL, then return                          *
  671.      *                                      *
  672.      * Also return if errflag is set.  In fact, the code in the       *
  673.      * function will test for this, but this way we keep status flags *
  674.      * intact without working too hard.  Special cases (e.g. calling  *
  675.      * a trap for SIGINT after the error flag was set) are handled    *
  676.      * by the calling code.  (PWS 1995/06/08).                  */
  677.     if ((*sigtr & ZSIG_IGNORED) || !sigfn || errflag)
  678.         return;
  679.  
  680.     *sigtr |= ZSIG_IGNORED;
  681.  
  682.     lexsave();
  683.     execsave();
  684.     breaks = 0;
  685.     if (*sigtr & ZSIG_FUNC) {
  686.     PERMALLOC {
  687.         args = newlinklist();
  688.         name = (char *) zalloc(5 + strlen(sigs[sig]));
  689.         sprintf(name, "TRAP%s", sigs[sig]);
  690.         addlinknode(args, name);
  691.         sprintf(num, "%d", sig);
  692.         addlinknode(args, num);
  693.     } LASTALLOC;
  694.     trapreturn = -1;
  695.     doshfunc(sigfn, args, 0, 1);
  696.     freelinklist(args, (FreeFunc) NULL);
  697.     zsfree(name);
  698.     } else HEAPALLOC {
  699.     execlist(dupstruct(sigfn), 1, 0);
  700.     } LASTALLOC;
  701.     if (trapreturn > 0)
  702.     trapret = trapreturn;
  703.     else if (errflag)
  704.     trapret = 1;
  705.     execrestore();
  706.     lexrestore();
  707.  
  708.     if (trapret > 0) {
  709.     breaks = loops;
  710.     errflag = 1;
  711.     } else {
  712.     breaks += obreaks;
  713.     if (breaks > loops)
  714.         breaks = loops;
  715.     }
  716.  
  717.     if (*sigtr != ZSIG_IGNORED)
  718.     *sigtr &= ~ZSIG_IGNORED;
  719. }
  720.  
  721. /* Standard call to execute a trap for a given signal */
  722.  
  723. /**/
  724. void
  725. dotrap(int sig)
  726. {
  727.     dotrapargs(sig, sigtrapped+sig, sigfuncs[sig]);
  728. }
  729.