sh: Add kill builtin.

This allows specifying a %job (which is equivalent to the corresponding
process group).

Additionally, it improves reliability of kill from sh in high-load
situations and ensures "kill" finds the correct utility regardless of PATH,
as required by POSIX (unless the undocumented %builtin mechanism is used).

Side effect: fatal errors (any error other than kill(2) failure) now return
exit status 2 instead of 1. (This is consistent with other sh builtins, but
not in NetBSD.)

Code size increases about 1K on i386.

Obtained from:	NetBSD
This commit is contained in:
Jilles Tjoelker 2010-12-21 22:47:34 +00:00
parent 05bcfef170
commit 0a62a9caa9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216629
8 changed files with 57 additions and 15 deletions

View File

@ -134,6 +134,7 @@ Terminate the process group with PGID 117:
.Xr csh 1 , .Xr csh 1 ,
.Xr killall 1 , .Xr killall 1 ,
.Xr ps 1 , .Xr ps 1 ,
.Xr sh 1 ,
.Xr kill 2 , .Xr kill 2 ,
.Xr sigaction 2 .Xr sigaction 2
.Sh STANDARDS .Sh STANDARDS

View File

@ -49,6 +49,12 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef SHELL
#define main killcmd
#include "bltin/bltin.h"
#include "error.h"
#endif
static void nosig(const char *); static void nosig(const char *);
static void printsignals(FILE *); static void printsignals(FILE *);
static int signame_to_signum(const char *); static int signame_to_signum(const char *);
@ -75,16 +81,16 @@ main(int argc, char *argv[])
usage(); usage();
numsig = strtol(*argv, &ep, 10); numsig = strtol(*argv, &ep, 10);
if (!**argv || *ep) if (!**argv || *ep)
errx(1, "illegal signal number: %s", *argv); errx(2, "illegal signal number: %s", *argv);
if (numsig >= 128) if (numsig >= 128)
numsig -= 128; numsig -= 128;
if (numsig <= 0 || numsig >= sys_nsig) if (numsig <= 0 || numsig >= sys_nsig)
nosig(*argv); nosig(*argv);
printf("%s\n", sys_signame[numsig]); printf("%s\n", sys_signame[numsig]);
exit(0); return (0);
} }
printsignals(stdout); printsignals(stdout);
exit(0); return (0);
} }
if (!strcmp(*argv, "-s")) { if (!strcmp(*argv, "-s")) {
@ -107,7 +113,7 @@ main(int argc, char *argv[])
} else if (isdigit(**argv)) { } else if (isdigit(**argv)) {
numsig = strtol(*argv, &ep, 10); numsig = strtol(*argv, &ep, 10);
if (!**argv || *ep) if (!**argv || *ep)
errx(1, "illegal signal number: %s", *argv); errx(2, "illegal signal number: %s", *argv);
if (numsig < 0) if (numsig < 0)
nosig(*argv); nosig(*argv);
} else } else
@ -122,16 +128,23 @@ main(int argc, char *argv[])
usage(); usage();
for (errors = 0; argc; argc--, argv++) { for (errors = 0; argc; argc--, argv++) {
pid = strtol(*argv, &ep, 10); #ifdef SHELL
if (!**argv || *ep) if (**argv == '%')
errx(1, "illegal process id: %s", *argv); pid = getjobpgrp(*argv);
else if (kill(pid, numsig) == -1) { else
#endif
{
pid = strtol(*argv, &ep, 10);
if (!**argv || *ep)
errx(2, "illegal process id: %s", *argv);
}
if (kill(pid, numsig) == -1) {
warn("%s", *argv); warn("%s", *argv);
errors = 1; errors = 1;
} }
} }
exit(errors); return (errors);
} }
static int static int
@ -154,7 +167,11 @@ nosig(const char *name)
warnx("unknown signal %s; valid signals:", name); warnx("unknown signal %s; valid signals:", name);
printsignals(stderr); printsignals(stderr);
exit(1); #ifdef SHELL
error(NULL);
#else
exit(2);
#endif
} }
static void static void
@ -180,5 +197,9 @@ usage(void)
" kill -l [exit_status]", " kill -l [exit_status]",
" kill -signal_name pid ...", " kill -signal_name pid ...",
" kill -signal_number pid ..."); " kill -signal_number pid ...");
exit(1); #ifdef SHELL
error(NULL);
#else
exit(2);
#endif
} }

View File

@ -4,7 +4,7 @@
PROG= sh PROG= sh
INSTALLFLAGS= -S INSTALLFLAGS= -S
SHSRCS= alias.c arith.y arith_lex.l cd.c echo.c error.c eval.c exec.c expand.c \ SHSRCS= alias.c arith.y arith_lex.l cd.c echo.c error.c eval.c exec.c expand.c \
histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \ histedit.c input.c jobs.c kill.c mail.c main.c memalloc.c miscbltin.c \
mystring.c options.c output.c parser.c printf.c redir.c show.c \ mystring.c options.c output.c parser.c printf.c redir.c show.c \
test.c trap.c var.c test.c trap.c var.c
GENSRCS= builtins.c init.c nodes.c syntax.c GENSRCS= builtins.c init.c nodes.c syntax.c
@ -26,6 +26,7 @@ WARNS?= 2
WFORMAT=0 WFORMAT=0
.PATH: ${.CURDIR}/bltin \ .PATH: ${.CURDIR}/bltin \
${.CURDIR}/../kill \
${.CURDIR}/../test \ ${.CURDIR}/../test \
${.CURDIR}/../../usr.bin/printf ${.CURDIR}/../../usr.bin/printf

View File

@ -43,6 +43,7 @@
#include "../mystring.h" #include "../mystring.h"
#ifdef SHELL #ifdef SHELL
#include "../output.h" #include "../output.h"
#define FILE struct output
#undef stdout #undef stdout
#define stdout out1 #define stdout out1
#undef stderr #undef stderr
@ -58,6 +59,7 @@
#define fflush flushout #define fflush flushout
#define INITARGS(argv) #define INITARGS(argv)
#define warnx warning #define warnx warning
#define warn(fmt, ...) warning(fmt ": %s", __VA_ARGS__, strerror(errno))
#define errx(exitstatus, ...) error(__VA_ARGS__) #define errx(exitstatus, ...) error(__VA_ARGS__)
#else #else
@ -67,8 +69,11 @@
#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else #define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else
#endif #endif
#include <unistd.h>
pointer stalloc(int); pointer stalloc(int);
void error(const char *, ...) __printf0like(1, 2); void error(const char *, ...) __printf0like(1, 2);
pid_t getjobpgrp(char *);
int echocmd(int, char **); int echocmd(int, char **);
int testcmd(int, char **); int testcmd(int, char **);

View File

@ -70,6 +70,7 @@ hashcmd hash
histcmd -h fc histcmd -h fc
jobidcmd jobid jobidcmd jobid
jobscmd jobs jobscmd jobs
killcmd kill
localcmd local localcmd local
printfcmd printf printfcmd printf
pwdcmd pwd pwdcmd pwd

View File

@ -632,6 +632,14 @@ currentjob: if ((jp = getcurjob(NULL)) == NULL)
} }
pid_t
getjobpgrp(char *name)
{
struct job *jp;
jp = getjob(name);
return -jp->ps[0].pid;
}
/* /*
* Return a new job structure, * Return a new job structure,

View File

@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd December 3, 2010 .Dd December 21, 2010
.Dt SH 1 .Dt SH 1
.Os .Os
.Sh NAME .Sh NAME
@ -2049,6 +2049,10 @@ If the
.Fl s .Fl s
option is specified, only the PIDs of the job commands are printed, one per option is specified, only the PIDs of the job commands are printed, one per
line. line.
.It Ic kill
A built-in equivalent of
.Xr kill 1
that additionally supports sending signals to jobs.
.It Ic local Oo Ar variable ... Oc Op Fl .It Ic local Oo Ar variable ... Oc Op Fl
See the See the
.Sx Functions .Sx Functions
@ -2477,6 +2481,7 @@ will return the argument.
.Xr echo 1 , .Xr echo 1 ,
.Xr ed 1 , .Xr ed 1 ,
.Xr emacs 1 , .Xr emacs 1 ,
.Xr kill 1 ,
.Xr printf 1 , .Xr printf 1 ,
.Xr pwd 1 , .Xr pwd 1 ,
.Xr test 1 , .Xr test 1 ,

View File

@ -26,7 +26,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd November 19, 2010 .Dd December 21, 2010
.Dt BUILTIN 1 .Dt BUILTIN 1
.Os .Os
.Sh NAME .Sh NAME
@ -251,7 +251,7 @@ but are implemented as scripts using a builtin command of the same name.
.It Ic if Ta \&No Ta Yes Ta Yes .It Ic if Ta \&No Ta Yes Ta Yes
.It Ic jobid Ta \&No Ta \&No Ta Yes .It Ic jobid Ta \&No Ta \&No Ta Yes
.It Ic jobs Ta No** Ta Yes Ta Yes .It Ic jobs Ta No** Ta Yes Ta Yes
.It Ic kill Ta Yes Ta Yes Ta \&No .It Ic kill Ta Yes Ta Yes Ta Yes
.It Ic limit Ta \&No Ta Yes Ta \&No .It Ic limit Ta \&No Ta Yes Ta \&No
.It Ic local Ta \&No Ta \&No Ta Yes .It Ic local Ta \&No Ta \&No Ta Yes
.It Ic log Ta \&No Ta Yes Ta \&No .It Ic log Ta \&No Ta Yes Ta \&No