home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
pdksh-4.9-src.tgz
/
tar.out
/
contrib
/
pdksh
/
sh
/
trap.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
5KB
|
218 lines
/*
* signal handling
*/
#ifndef lint
static char *RCSid = "$Id: trap.c,v 1.4 93/05/05 21:17:12 sjg Exp $";
#endif
#include "stdh.h"
#include <errno.h>
#include <signal.h>
#include <setjmp.h>
#include "sh.h"
Trap sigtraps [SIGNALS] = {
{0, "EXIT", "Signal 0"}, /* todo: belongs in e.loc->exit */
{SIGHUP, "HUP", "Hangup"},
{SIGINT, "INT", "Interrupt"},
{SIGQUIT, "QUIT", "Quit"},
{SIGILL, "ILL", "Illegal instruction"},
{SIGTRAP, "TRAP", "Trace trap"},
#ifdef SIGABRT
{SIGIOT, "ABRT", "Abort"},
#else
{SIGIOT, "IOT", "IOT instruction"},
#endif
{SIGEMT, "EMT", "EMT trap"},
{SIGFPE, "FPE", "Floating exception"},
{SIGKILL, "KILL", "Killed"},
#ifdef _MINIX
{SIGUSR1, "USR1", "User defined signal 1"},
{SIGSEGV, "SEGV", "Memory fault"},
{SIGUSR2, "USR2", "User defined signal 2"},
#else
{SIGBUS, "BUS", "Bus error"},
{SIGSEGV, "SEGV", "Memory fault"},
{SIGSYS, "SYS", "Bad system call"},
#endif
{SIGPIPE, "PIPE", "Broken pipe"},
{SIGALRM, "ALRM", "Alarm clock"},
{SIGTERM, "TERM", "Terminated"},
#ifdef _MINIX
{SIGSTKFLT, "STKFLT", "Stack fault"},
#endif
#ifdef _SYSV
{SIGUSR1, "USR1", "User defined signal 1"},
{SIGUSR2, "USR2", "User defined signal 2"},
{SIGCLD, "CLD", "Death of a child"},
{SIGPWR, "PWR", "Power-fail restart"},
#ifdef JOBS /* todo: need to be more portable */
{SIGTSTP, "TSTP", "Stop"},
{SIGTTIN, "TTIN", "Stop (tty input)"},
#ifdef SIGPOLL
{SIGPOLL, "POLL", "Pollable event occured"},
#endif
{SIGSTOP, "STOP", "Stop (signal)"},
{SIGTTOU, "TTOU", "Stop (tty output)"},
{SIGCONT, "CONT", "Continue"},
#endif
#else
#ifdef JOBS /* todo: need to be more portable */
{SIGURG, "URG", "Urgent condition"}, /* BSDism */
{SIGSTOP, "STOP", "Stop (signal)"},
{SIGTSTP, "TSTP", "Stop"},
{SIGCONT, "CONT", "Continue"},
{SIGCHLD, "CHLD", "Waiting children"},
{SIGTTIN, "TTIN", "Stop (tty input)"},
{SIGTTOU, "TTOU", "Stop (tty output)"},
#endif
#endif
};
Trap *
gettrap(name)
char *name;
{
int i;
register Trap *p;
if (digit(*name)) {
i = getn(name);
return (0 <= i && i < SIGNALS) ? &sigtraps[getn(name)] : NULL;
}
#if 0
if (strcmp("ERR", name) == 0)
return &e.loc->err;
if (strcmp("EXIT", name) == 0)
return &e.loc->exit;
#endif
for (p = sigtraps, i = SIGNALS; --i >= 0; p++)
if (p->name != NULL && strcmp(p->name, name) == 0)
return p;
return NULL;
}
/*
* trap signal handler
*/
void
trapsig(i)
int i;
{
trap = sigtraps[i].set = 1;
if (i == SIGINT && (e.type == E_PARSE || e.type == E_LOOP))
/* dangerous but necessary to deal with BSD silly signals */
longjmp(e.jbuf, 1);
#ifdef USE_SIGACT
sigaction(i, &Sigact_trap, NULL);
#else
(void) signal(i, trapsig);
#endif
}
#ifdef amigaos
/* need to copy any allocated trap command strings in child, or we free
memory of the parent when afree() is invoked */
void
child_dup_traps ()
{
Trap *p;
for (p = sigtraps; p < &sigtraps[sizeof (sigtraps) / sizeof (Trap)]; p++)
if (p->trap)
p->trap = strsave (p->trap, APERM);
}
#endif /* amigaos */
/*
* run any pending traps
*/
runtraps()
{
int i;
register Trap *p;
for (p = sigtraps, i = SIGNALS; --i >= 0; p++)
if (p->set)
runtrap(p);
trap = 0;
}
runtrap(p)
Trap *p;
{
char *trapstr;
p->set = 0;
if ((trapstr = p->trap) == NULL)
if (p->signal == SIGINT)
unwind(); /* return to shell() */
else
return;
if (p->signal == 0) /* ??? */
p->trap = 0;
command(trapstr);
}
/* restore signals for children */
cleartraps()
{
int i;
register Trap *p;
if ((p = sigtraps)->trap != NULL) { /* Maybe put in exchild() */
afree((void *)p->trap,APERM); /* Necessary? */
p->trap = NULL;
}
for (i = SIGNALS, p = sigtraps; --i >= 0; p++) {
p->set = 0;
#ifdef USE_SIGACT
if (p->ourtrap)
{
sigaction(p->signal, &Sigact_ign, &Sigact);
if (Sigact.sa_handler != SIG_IGN)
sigaction(p->signal, &Sigact_dfl, NULL);
}
#else
if (p->ourtrap && signal(p->signal, SIG_IGN) != SIG_IGN)
(void) signal(p->signal, SIG_DFL);
#endif
}
}
ignoresig(i)
int i;
{
#ifdef USE_SIGACT
sigaction(i, &Sigact_ign, &Sigact);
sigemptyset(&Sigact.sa_mask);
Sigact.sa_flags = 0;
if (Sigact.sa_handler != SIG_IGN)
sigtraps[i].sig_dfl = 1;
#else
if (signal(i, SIG_IGN) != SIG_IGN)
sigtraps[i].sig_dfl = 1;
#endif
}
restoresigs()
{
int i;
register Trap *p;
for (p = sigtraps, i = SIGNALS; --i >= 0; p++)
if (p->sig_dfl) {
p->sig_dfl = 0;
#ifdef USE_SIGACT
sigaction(p->signal, &Sigact_dfl, NULL);
#else
(void) signal(p->signal, SIG_DFL);
#endif
}
}