diff -urN netbsd-sh/jobs.c ash-0.3.7.orig/jobs.c --- netbsd-sh/jobs.c Tue May 23 12:03:19 2000 +++ ash-0.3.7.orig/jobs.c Mon Apr 23 22:16:46 2001 @@ -189,6 +193,94 @@ #if JOBS int +killcmd(argc, argv) + int argc; + char **argv; +{ + extern char *signal_names[]; + int signo = -1; + int list = 0; + int i; + pid_t pid; + struct job *jp; + + if (argc <= 1) { + error( +"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n" +"kill -l [exitstatus]" + ); + } + + if (*argv[1] == '-') { + signo = decode_signal(argv[1]+1); + if (signo < 0) { + int c; + + while ((c = nextopt("ls:")) != '\0') + switch (c) { + case 'l': + list = 1; + break; + case 's': + signo = decode_signal(optarg); + break; + default: + error( + "nextopt returned character code 0%o", c); + } + } else + argptr++; + } + + if (!list && signo < 0) + signo = SIGTERM; + + if ((signo < 0 || !*argptr) ^ list) { + error( +"Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n" +"kill -l [exitstatus]" + ); + } + + if (list) { + if (!*argptr) { + out1fmt("0\n"); + for (i = 1; i < NSIG; i++) { + if (strncmp(signal_names[i], "SIGJUNK(", 8) + == 0) + continue; + out1fmt("%s\n", signal_names[i] + 3); + } + return 0; + } + signo = atoi(*argptr); + if (signo > 128) + signo -= 128; + if (0 < signo && signo < NSIG) + out1fmt("%s\n", signal_names[signo] + 3); + else + error("invalid signal number or exit status: %s", + *argptr); + return 0; + } + + do { + if (**argptr == '%') { + jp = getjob(*argptr); + if (jp->jobctl == 0) + error("job %s not created under job control", + *argptr); + pid = -jp->ps[0].pid; + } else + pid = atoi(*argptr); + if (kill(pid, signo) != 0) + error("%s: %s", *argptr, strerror(errno)); + } while (*++argptr); + + return 0; +} + +int fgcmd(argc, argv) int argc; char **argv; diff -urN netbsd-sh/jobs.h ash-0.3.7.orig/jobs.h --- netbsd-sh/jobs.h Tue May 23 12:03:19 2000 +++ ash-0.3.7.orig/jobs.h Mon Apr 23 22:16:46 2001 @@ -80,6 +80,7 @@ extern int job_warning; /* user was warned about stopped jobs */ void setjobctl __P((int)); +int killcmd __P((int, char **)); int fgcmd __P((int, char **)); int bgcmd __P((int, char **)); int jobscmd __P((int, char **)); diff -urN netbsd-sh/builtins.def ash-0.3.7.orig/builtins.def --- netbsd-sh/builtins.def Mon Apr 10 13:02:58 2000 +++ ash-0.3.7.orig/builtins.def Mon Apr 23 22:16:46 2001 @@ -70,6 +71,7 @@ hashcmd hash jobidcmd jobid jobscmd jobs +killcmd -j kill #linecmd line localcmd local #nlechocmd nlecho diff -urN netbsd-sh/mksignames.c ash-0.3.7.orig/mksignames.c --- netbsd-sh/mksignames.c Thu Jan 1 01:00:00 1970 +++ ash-0.3.7.orig/mksignames.c Mon Apr 23 22:16:46 2001 @@ -0,0 +1,400 @@ +/* signames.c -- Create and write `signames.c', which contains an array of + signal names. */ + +/* Copyright (C) 1992 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include +#include +#include +#include + +#if !defined (NSIG) +# define NSIG 64 +#endif + +char *signal_names[2 * NSIG]; + +char *progname; + +#if defined (SIGRTMAX) || defined (SIGRTMIN) +# define RTLEN 14 +# define RTLIM 256 +#endif + +void +initialize_signames () +{ + register int i; +#if defined (SIGRTMAX) || defined (SIGRTMIN) + int rtmin, rtmax, rtcnt; +#endif + + for (i = 1; i < sizeof(signal_names)/sizeof(signal_names[0]); i++) + signal_names[i] = (char *)NULL; + + /* `signal' 0 is what we do on exit. */ + signal_names[0] = "EXIT"; + + /* Place signal names which can be aliases for more common signal + names first. This allows (for example) SIGABRT to overwrite SIGLOST. */ + + /* POSIX 1003.1b-1993 real time signals, but take care of incomplete + implementations. Acoording to the standard, both, SIGRTMIN and + SIGRTMAX must be defined, SIGRTMIN must be stricly less than + SIGRTMAX, and the difference must be at least 7, that is, there + must be at least eight distinct real time signals. */ + + /* The generated signal names are SIGRTMIN, SIGRTMIN+1, ..., + SIGRTMIN+x, SIGRTMAX-x, ..., SIGRTMAX-1, SIGRTMAX. If the number + of RT signals is odd, there is an extra SIGRTMIN+(x+1). + These names are the ones used by ksh and /usr/xpg4/bin/sh on SunOS5. */ + +#if defined (SIGRTMIN) + rtmin = SIGRTMIN; + signal_names[rtmin] = "SIGRTMIN"; +#endif + +#if defined (SIGRTMAX) + rtmax = SIGRTMAX; + signal_names[rtmax] = "SIGRTMAX"; +#endif + +#if defined (SIGRTMAX) && defined (SIGRTMIN) + if (rtmax > rtmin) + { + rtcnt = (rtmax - rtmin - 1) / 2; + /* croak if there are too many RT signals */ + if (rtcnt >= RTLIM/2) + { + rtcnt = RTLIM/2-1; + fprintf(stderr, "%s: error: more than %i real time signals, fix `%s'\n", + progname, RTLIM, progname); + } + + for (i = 1; i <= rtcnt; i++) + { + signal_names[rtmin+i] = (char *)malloc(RTLEN); + sprintf (signal_names[rtmin+i], "SIGRTMIN+%d", i); + signal_names[rtmax-i] = (char *)malloc(RTLEN); + sprintf (signal_names[rtmax-i], "SIGRTMAX-%d", i); + } + + if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2) + { + /* Need an extra RTMIN signal */ + signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN); + sprintf (signal_names[rtmin+rtcnt+1], "SIGRTMIN+%d", rtcnt+1); + } + } +#endif /* SIGRTMIN && SIGRTMAX */ + +/* AIX */ +#if defined (SIGLOST) /* resource lost (eg, record-lock lost) */ + signal_names[SIGLOST] = "SIGLOST"; +#endif + +#if defined (SIGMSG) /* HFT input data pending */ + signal_names[SIGMSG] = "SIGMSG"; +#endif + +#if defined (SIGDANGER) /* system crash imminent */ + signal_names[SIGDANGER] = "SIGDANGER"; +#endif + +#if defined (SIGMIGRATE) /* migrate process to another CPU */ + signal_names[SIGMIGRATE] = "SIGMIGRATE"; +#endif + +#if defined (SIGPRE) /* programming error */ + signal_names[SIGPRE] = "SIGPRE"; +#endif + +#if defined (SIGVIRT) /* AIX virtual time alarm */ + signal_names[SIGVIRT] = "SIGVIRT"; +#endif + +#if defined (SIGALRM1) /* m:n condition variables */ + signal_names[SIGALRM1] = "SIGALRM1"; +#endif + +#if defined (SIGWAITING) /* m:n scheduling */ + signal_names[SIGWAITING] = "SIGWAITING"; +#endif + +#if defined (SIGGRANT) /* HFT monitor mode granted */ + signal_names[SIGGRANT] = "SIGGRANT"; +#endif + +#if defined (SIGKAP) /* keep alive poll from native keyboard */ + signal_names[SIGKAP] = "SIGKAP"; +#endif + +#if defined (SIGRETRACT) /* HFT monitor mode retracted */ + signal_names[SIGRETRACT] = "SIGRETRACT"; +#endif + +#if defined (SIGSOUND) /* HFT sound sequence has completed */ + signal_names[SIGSOUND] = "SIGSOUND"; +#endif + +#if defined (SIGSAK) /* Secure Attention Key */ + signal_names[SIGSAK] = "SIGSAK"; +#endif + +/* SunOS5 */ +#if defined (SIGLWP) /* special signal used by thread library */ + signal_names[SIGLWP] = "SIGLWP"; +#endif + +#if defined (SIGFREEZE) /* special signal used by CPR */ + signal_names[SIGFREEZE] = "SIGFREEZE"; +#endif + +#if defined (SIGTHAW) /* special signal used by CPR */ + signal_names[SIGTHAW] = "SIGTHAW"; +#endif + +#if defined (SIGCANCEL) /* thread cancellation signal used by libthread */ + signal_names[SIGCANCEL] = "SIGCANCEL"; +#endif + +/* HP-UX */ +#if defined (SIGDIL) /* DIL signal (?) */ + signal_names[SIGDIL] = "SIGDIL"; +#endif + +/* System V */ +#if defined (SIGCLD) /* Like SIGCHLD. */ + signal_names[SIGCLD] = "SIGCLD"; +#endif + +#if defined (SIGPWR) /* power state indication */ + signal_names[SIGPWR] = "SIGPWR"; +#endif + +#if defined (SIGPOLL) /* Pollable event (for streams) */ + signal_names[SIGPOLL] = "SIGPOLL"; +#endif + +/* Unknown */ +#if defined (SIGWINDOW) + signal_names[SIGWINDOW] = "SIGWINDOW"; +#endif + +/* Common */ +#if defined (SIGHUP) /* hangup */ + signal_names[SIGHUP] = "SIGHUP"; +#endif + +#if defined (SIGINT) /* interrupt */ + signal_names[SIGINT] = "SIGINT"; +#endif + +#if defined (SIGQUIT) /* quit */ + signal_names[SIGQUIT] = "SIGQUIT"; +#endif + +#if defined (SIGILL) /* illegal instruction (not reset when caught) */ + signal_names[SIGILL] = "SIGILL"; +#endif + +#if defined (SIGTRAP) /* trace trap (not reset when caught) */ + signal_names[SIGTRAP] = "SIGTRAP"; +#endif + +#if defined (SIGIOT) /* IOT instruction */ + signal_names[SIGIOT] = "SIGIOT"; +#endif + +#if defined (SIGABRT) /* Cause current process to dump core. */ + signal_names[SIGABRT] = "SIGABRT"; +#endif + +#if defined (SIGEMT) /* EMT instruction */ + signal_names[SIGEMT] = "SIGEMT"; +#endif + +#if defined (SIGFPE) /* floating point exception */ + signal_names[SIGFPE] = "SIGFPE"; +#endif + +#if defined (SIGKILL) /* kill (cannot be caught or ignored) */ + signal_names[SIGKILL] = "SIGKILL"; +#endif + +#if defined (SIGBUS) /* bus error */ + signal_names[SIGBUS] = "SIGBUS"; +#endif + +#if defined (SIGSEGV) /* segmentation violation */ + signal_names[SIGSEGV] = "SIGSEGV"; +#endif + +#if defined (SIGSYS) /* bad argument to system call */ + signal_names[SIGSYS] = "SIGSYS"; +#endif + +#if defined (SIGPIPE) /* write on a pipe with no one to read it */ + signal_names[SIGPIPE] = "SIGPIPE"; +#endif + +#if defined (SIGALRM) /* alarm clock */ + signal_names[SIGALRM] = "SIGALRM"; +#endif + +#if defined (SIGTERM) /* software termination signal from kill */ + signal_names[SIGTERM] = "SIGTERM"; +#endif + +#if defined (SIGURG) /* urgent condition on IO channel */ + signal_names[SIGURG] = "SIGURG"; +#endif + +#if defined (SIGSTOP) /* sendable stop signal not from tty */ + signal_names[SIGSTOP] = "SIGSTOP"; +#endif + +#if defined (SIGTSTP) /* stop signal from tty */ + signal_names[SIGTSTP] = "SIGTSTP"; +#endif + +#if defined (SIGCONT) /* continue a stopped process */ + signal_names[SIGCONT] = "SIGCONT"; +#endif + +#if defined (SIGCHLD) /* to parent on child stop or exit */ + signal_names[SIGCHLD] = "SIGCHLD"; +#endif + +#if defined (SIGTTIN) /* to readers pgrp upon background tty read */ + signal_names[SIGTTIN] = "SIGTTIN"; +#endif + +#if defined (SIGTTOU) /* like TTIN for output if (tp->t_local<OSTOP) */ + signal_names[SIGTTOU] = "SIGTTOU"; +#endif + +#if defined (SIGIO) /* input/output possible signal */ + signal_names[SIGIO] = "SIGIO"; +#endif + +#if defined (SIGXCPU) /* exceeded CPU time limit */ + signal_names[SIGXCPU] = "SIGXCPU"; +#endif + +#if defined (SIGXFSZ) /* exceeded file size limit */ + signal_names[SIGXFSZ] = "SIGXFSZ"; +#endif + +#if defined (SIGVTALRM) /* virtual time alarm */ + signal_names[SIGVTALRM] = "SIGVTALRM"; +#endif + +#if defined (SIGPROF) /* profiling time alarm */ + signal_names[SIGPROF] = "SIGPROF"; +#endif + +#if defined (SIGWINCH) /* window changed */ + signal_names[SIGWINCH] = "SIGWINCH"; +#endif + +/* 4.4 BSD */ +#if defined (SIGINFO) && !defined (_SEQUENT_) /* information request */ + signal_names[SIGINFO] = "SIGINFO"; +#endif + +#if defined (SIGUSR1) /* user defined signal 1 */ + signal_names[SIGUSR1] = "SIGUSR1"; +#endif + +#if defined (SIGUSR2) /* user defined signal 2 */ + signal_names[SIGUSR2] = "SIGUSR2"; +#endif + +#if defined (SIGKILLTHR) /* BeOS: Kill Thread */ + signal_names[SIGKILLTHR] = "SIGKILLTHR"; +#endif + + for (i = 0; i < NSIG; i++) + if (signal_names[i] == (char *)NULL) + { + signal_names[i] = (char *)malloc (18); + sprintf (signal_names[i], "SIGJUNK(%d)", i); + } + + signal_names[NSIG] = "DEBUG"; +} + +void +write_signames (stream) + FILE *stream; +{ + register int i; + + fprintf (stream, "/* This file was automatically created by %s.\n", + progname); + fprintf (stream, " Do not edit. Edit support/mksignames.c instead. */\n\n"); + fprintf (stream, "#include \n\n"); + fprintf (stream, + "/* A translation list so we can be polite to our users. */\n"); + fprintf (stream, "char *signal_names[NSIG + 2] = {\n"); + + for (i = 0; i <= NSIG; i++) + fprintf (stream, " \"%s\",\n", signal_names[i]); + + fprintf (stream, " (char *)0x0,\n"); + fprintf (stream, "};\n"); +} + +int +main (argc, argv) + int argc; + char **argv; +{ + char *stream_name; + FILE *stream; + + progname = argv[0]; + + if (argc == 1) + { + stream_name = "signames.c"; + } + else if (argc == 2) + { + stream_name = argv[1]; + } + else + { + fprintf (stderr, "Usage: %s [output-file]\n", progname); + exit (1); + } + + stream = fopen (stream_name, "w"); + if (!stream) + { + fprintf (stderr, "%s: %s: cannot open for writing\n", + progname, stream_name); + exit (2); + } + + initialize_signames (); + write_signames (stream); + exit (0); +} diff -urN netbsd-sh/trap.c ash-0.3.7.orig/trap.c --- netbsd-sh/trap.c Tue May 23 12:03:19 2000 +++ ash-0.3.7.orig/trap.c Mon Apr 23 22:16:46 2001 @@ -84,7 +88,7 @@ char gotsig[NSIG]; /* indicates specified signal received */ int pendingsigs; /* indicates some signal received */ -static int getsigaction __P((int, sig_t *)); +extern char *signal_names[]; /* * The trap builtin. @@ -107,16 +111,20 @@ return 0; } ap = argv + 1; - if (is_number(*ap)) + if (argc == 2) action = NULL; else action = *ap++; while (*ap) { - if ((signo = number(*ap)) < 0 || signo > NSIG) + if ((signo = decode_signal(*ap)) < 0) error("%s: bad trap", *ap); INTOFF; - if (action) - action = savestr(action); + if (action) { + if (action[0] == '-' && action[1] == '\0') + action = NULL; + else + action = savestr(action); + } if (trap[signo]) ckfree(trap[signo]); trap[signo] = action; @@ -157,13 +165,13 @@ * out what it should be set to. */ -long +void setsignal(signo) int signo; { int action; - sig_t sigact = SIG_DFL; char *t; + struct sigaction act; if ((t = trap[signo]) == NULL) action = S_DFL; @@ -206,15 +214,15 @@ /* * current setting unknown */ - if (!getsigaction(signo, &sigact)) { + if (sigaction(signo, 0, &act) == -1) { /* * Pretend it worked; maybe we should give a warning * here, but other shells don't. We don't alter * sigmode, so that we retry every time. */ - return 0; + return; } - if (sigact == SIG_IGN) { + if (act.sa_handler == SIG_IGN) { if (mflag && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)) { *t = S_IGN; /* don't hard ignore these */ @@ -225,31 +233,21 @@ } } if (*t == S_HARD_IGN || *t == action) - return 0; + return; switch (action) { - case S_DFL: sigact = SIG_DFL; break; - case S_CATCH: sigact = onsig; break; - case S_IGN: sigact = SIG_IGN; break; + case S_CATCH: + act.sa_handler = onsig; + break; + case S_IGN: + act.sa_handler = SIG_IGN; + break; + default: + act.sa_handler = SIG_DFL; } *t = action; - siginterrupt(signo, 1); - return (long)signal(signo, sigact); -} - -/* - * Return the current setting for sig w/o changing it. - */ -static int -getsigaction(signo, sigact) - int signo; - sig_t *sigact; -{ - struct sigaction sa; - - if (sigaction(signo, (struct sigaction *)0, &sa) == -1) - return 0; - *sigact = (sig_t) sa.sa_handler; - return 1; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(signo, &act, 0); } /* @@ -382,4 +384,18 @@ #endif l2: _exit(status); /* NOTREACHED */ +} + +int decode_signal(const char *string) +{ + int signo; + + if (is_number(string)) return atoi(string); + + for (signo=0; signo < NSIG; signo++) + if (strcasecmp(string, signal_names[signo]) == 0 || + strcasecmp(string, &(signal_names[signo])[3]) == 0) + return signo; + + return -1; } diff -urN netbsd-sh/trap.h ash-0.3.7.orig/trap.h --- netbsd-sh/trap.h Tue May 23 12:03:19 2000 +++ ash-0.3.7.orig/trap.h Mon Apr 23 22:16:46 2001 @@ -42,9 +42,10 @@ int trapcmd __P((int, char **)); void clear_traps __P((void)); -long setsignal __P((int)); +void setsignal __P((int)); void ignoresig __P((int)); void onsig __P((int)); void dotrap __P((void)); void setinteractive __P((int)); void exitshell __P((int)) __attribute__((noreturn)); +int decode_signal __P((const char *));