Home | History | Annotate | Line # | Download | only in kill
kill.c revision 1.28.4.2
      1  1.28.4.2  pgoyette /* $NetBSD: kill.c,v 1.28.4.2 2018/12/26 14:01:03 pgoyette Exp $ */
      2      1.10       cgd 
      3       1.1       cgd /*
      4       1.7   mycroft  * Copyright (c) 1988, 1993, 1994
      5       1.7   mycroft  *	The Regents of the University of California.  All rights reserved.
      6       1.1       cgd  *
      7       1.1       cgd  * Redistribution and use in source and binary forms, with or without
      8       1.1       cgd  * modification, are permitted provided that the following conditions
      9       1.1       cgd  * are met:
     10       1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     11       1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     12       1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     14       1.1       cgd  *    documentation and/or other materials provided with the distribution.
     15      1.23       agc  * 3. Neither the name of the University nor the names of its contributors
     16       1.1       cgd  *    may be used to endorse or promote products derived from this software
     17       1.1       cgd  *    without specific prior written permission.
     18       1.1       cgd  *
     19       1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20       1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21       1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22       1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23       1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24       1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25       1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26       1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27       1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28       1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29       1.1       cgd  * SUCH DAMAGE.
     30       1.1       cgd  */
     31       1.1       cgd 
     32      1.13  christos #include <sys/cdefs.h>
     33      1.20  christos #if !defined(lint) && !defined(SHELL)
     34      1.25     lukem __COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\
     35      1.25     lukem  The Regents of the University of California.  All rights reserved.");
     36       1.1       cgd #endif /* not lint */
     37       1.1       cgd 
     38       1.1       cgd #ifndef lint
     39      1.10       cgd #if 0
     40      1.11       jtc static char sccsid[] = "@(#)kill.c	8.4 (Berkeley) 4/28/95";
     41      1.10       cgd #else
     42  1.28.4.2  pgoyette __RCSID("$NetBSD: kill.c,v 1.28.4.2 2018/12/26 14:01:03 pgoyette Exp $");
     43      1.10       cgd #endif
     44       1.1       cgd #endif /* not lint */
     45       1.1       cgd 
     46       1.7   mycroft #include <ctype.h>
     47       1.7   mycroft #include <err.h>
     48       1.7   mycroft #include <errno.h>
     49       1.1       cgd #include <signal.h>
     50       1.1       cgd #include <stdio.h>
     51       1.1       cgd #include <stdlib.h>
     52      1.26       spz #include <limits.h>
     53      1.26       spz #include <inttypes.h>
     54       1.1       cgd #include <string.h>
     55      1.20  christos #include <termios.h>
     56      1.20  christos #include <unistd.h>
     57      1.20  christos #include <locale.h>
     58      1.20  christos #include <sys/ioctl.h>
     59      1.20  christos 
     60      1.20  christos #ifdef SHELL            /* sh (aka ash) builtin */
     61      1.27     joerg int killcmd(int, char *argv[]);
     62      1.20  christos #define main killcmd
     63      1.20  christos #include "../../bin/sh/bltin/bltin.h"
     64      1.20  christos #endif /* SHELL */
     65      1.20  christos 
     66      1.28       kre __dead static void nosig(const char *);
     67  1.28.4.1  pgoyette void printsignals(FILE *, int);
     68      1.28       kre static int signum(const char *);
     69      1.28       kre static pid_t processnum(const char *);
     70      1.27     joerg __dead static void usage(void);
     71       1.7   mycroft 
     72       1.7   mycroft int
     73      1.18       wiz main(int argc, char *argv[])
     74       1.1       cgd {
     75      1.26       spz 	int errors;
     76      1.28       kre 	int numsig;
     77      1.28       kre 	pid_t pid;
     78      1.28       kre 	const char *sn;
     79       1.1       cgd 
     80      1.19       wiz 	setprogname(argv[0]);
     81      1.20  christos 	setlocale(LC_ALL, "");
     82       1.1       cgd 	if (argc < 2)
     83       1.1       cgd 		usage();
     84       1.1       cgd 
     85       1.4       jtc 	numsig = SIGTERM;
     86       1.7   mycroft 
     87       1.4       jtc 	argc--, argv++;
     88      1.28       kre 
     89      1.28       kre 	/*
     90      1.28       kre 	 * Process exactly 1 option, if there is one.
     91      1.28       kre 	 */
     92      1.28       kre 	if (argv[0][0] == '-') {
     93      1.28       kre 		switch (argv[0][1]) {
     94      1.28       kre 		case 'l':
     95      1.28       kre 			if (argv[0][2] != '\0')
     96      1.28       kre 				sn = argv[0] + 2;
     97      1.28       kre 			else {
     98      1.28       kre 				argc--; argv++;
     99      1.28       kre 				sn = argv[0];
    100      1.28       kre 			}
    101      1.28       kre 			if (argc > 1)
    102       1.7   mycroft 				usage();
    103      1.28       kre 			if (argc == 1) {
    104      1.28       kre 				if (isdigit((unsigned char)*sn) == 0)
    105      1.28       kre 					usage();
    106      1.28       kre 				numsig = signum(sn);
    107      1.28       kre 				if (numsig >= 128)
    108      1.28       kre 					numsig -= 128;
    109      1.28       kre 				if (numsig == 0 || signalnext(numsig) == -1)
    110      1.28       kre 					nosig(sn);
    111      1.28       kre 				sn = signalname(numsig);
    112      1.28       kre 				if (sn == NULL)
    113      1.28       kre 					errx(EXIT_FAILURE,
    114      1.28       kre 					   "unknown signal number: %d", numsig);
    115      1.28       kre 				printf("%s\n", sn);
    116      1.28       kre 				exit(0);
    117      1.28       kre 			}
    118  1.28.4.1  pgoyette 			printsignals(stdout, 0);
    119       1.7   mycroft 			exit(0);
    120       1.7   mycroft 
    121      1.28       kre 		case 's':
    122      1.28       kre 			if (argv[0][2] != '\0')
    123      1.28       kre 				sn = argv[0] + 2;
    124      1.28       kre 			else {
    125      1.28       kre 				argc--, argv++;
    126      1.28       kre 				if (argc < 1) {
    127      1.28       kre 					warnx(
    128      1.28       kre 					    "option requires an argument -- s");
    129      1.28       kre 					usage();
    130      1.28       kre 				}
    131      1.28       kre 				sn = argv[0];
    132      1.28       kre 			}
    133      1.28       kre 			if (strcmp(sn, "0") == 0)
    134      1.28       kre 				numsig = 0;
    135      1.28       kre 			else if ((numsig = signalnumber(sn)) == 0) {
    136      1.28       kre 				if (sn != argv[0])
    137      1.28       kre 					goto trysignal;
    138      1.28       kre 				nosig(sn);
    139      1.28       kre 			}
    140      1.28       kre 			argc--, argv++;
    141      1.28       kre 			break;
    142      1.28       kre 
    143      1.28       kre 		case '-':
    144      1.28       kre 			if (argv[0][2] == '\0') {
    145      1.28       kre 				/* process this one again later */
    146      1.28       kre 				break;
    147      1.28       kre 			}
    148      1.28       kre 			/* FALL THROUGH */
    149      1.28       kre 		case '\0':
    150       1.4       jtc 			usage();
    151      1.28       kre 			break;
    152      1.28       kre 
    153      1.28       kre 		default:
    154      1.28       kre  trysignal:
    155      1.28       kre 			sn = *argv + 1;
    156      1.28       kre 			if (((numsig = signalnumber(sn)) == 0)) {
    157      1.28       kre 				if (isdigit((unsigned char)*sn))
    158      1.28       kre 					numsig = signum(sn);
    159      1.28       kre 				else
    160      1.28       kre 					nosig(sn);
    161      1.22  jschauma 			}
    162      1.28       kre 
    163      1.28       kre 			if (numsig != 0 && signalnext(numsig) == -1)
    164      1.24  christos 				nosig(sn);
    165      1.28       kre 			argc--, argv++;
    166      1.28       kre 			break;
    167      1.28       kre 		}
    168      1.28       kre 	}
    169      1.28       kre 
    170      1.28       kre 	/* deal with the optional '--' end of options option */
    171      1.28       kre 	if (argc > 0 && strcmp(*argv, "--") == 0)
    172       1.7   mycroft 		argc--, argv++;
    173       1.1       cgd 
    174       1.7   mycroft 	if (argc == 0)
    175       1.1       cgd 		usage();
    176       1.1       cgd 
    177       1.7   mycroft 	for (errors = 0; argc; argc--, argv++) {
    178      1.20  christos #ifdef SHELL
    179      1.20  christos 		extern int getjobpgrp(const char *);
    180      1.20  christos 		if (*argv[0] == '%') {
    181      1.20  christos 			pid = getjobpgrp(*argv);
    182      1.20  christos 			if (pid == 0) {
    183      1.20  christos 				warnx("illegal job id: %s", *argv);
    184      1.20  christos 				errors = 1;
    185      1.20  christos 				continue;
    186      1.20  christos 			}
    187      1.20  christos 		} else
    188      1.20  christos #endif
    189      1.28       kre 			if ((pid = processnum(*argv)) == (pid_t)-1) {
    190      1.20  christos 				errors = 1;
    191      1.20  christos 				continue;
    192      1.20  christos 			}
    193      1.28       kre 
    194      1.28       kre 		if (kill(pid, numsig) == -1) {
    195       1.7   mycroft 			warn("%s", *argv);
    196       1.1       cgd 			errors = 1;
    197       1.1       cgd 		}
    198      1.21  christos #ifdef SHELL
    199      1.28       kre 		/*
    200      1.28       kre 		 * Wakeup the process if it was suspended, so it can
    201      1.28       kre 		 * exit without an explicit 'fg'.
    202      1.28       kre 		 *	(kernel handles this for SIGKILL)
    203      1.28       kre 		 */
    204      1.21  christos 		if (numsig == SIGTERM || numsig == SIGHUP)
    205      1.28       kre 			kill(pid, SIGCONT);
    206      1.21  christos #endif
    207       1.1       cgd 	}
    208       1.7   mycroft 
    209       1.1       cgd 	exit(errors);
    210      1.14   mycroft 	/* NOTREACHED */
    211       1.1       cgd }
    212       1.1       cgd 
    213      1.20  christos static int
    214      1.28       kre signum(const char *sn)
    215      1.28       kre {
    216      1.28       kre 	intmax_t n;
    217      1.28       kre 	char *ep;
    218      1.28       kre 
    219      1.28       kre 	n = strtoimax(sn, &ep, 10);
    220      1.28       kre 
    221      1.28       kre 	/* check for correctly parsed number */
    222      1.28       kre 	if (*ep || n <= INT_MIN || n >= INT_MAX )
    223      1.28       kre 		errx(EXIT_FAILURE, "illegal signal number: %s", sn);
    224      1.28       kre 		/* NOTREACHED */
    225      1.28       kre 
    226      1.28       kre 	return (int)n;
    227      1.28       kre }
    228      1.28       kre 
    229      1.28       kre static pid_t
    230      1.28       kre processnum(const char *s)
    231       1.4       jtc {
    232      1.28       kre 	intmax_t n;
    233      1.28       kre 	char *ep;
    234      1.28       kre 
    235      1.28       kre 	n = strtoimax(s, &ep, 10);
    236       1.4       jtc 
    237      1.28       kre 	/* check for correctly parsed number */
    238      1.28       kre 	if (*ep || n == INTMAX_MIN || n == INTMAX_MAX || (pid_t)n != n ||
    239      1.28       kre 	    n == -1) {
    240      1.28       kre 		warnx("illegal process%s id: %s", (n < 0 ? " group" : ""), s);
    241      1.28       kre 		n = -1;
    242       1.4       jtc 	}
    243      1.28       kre 
    244      1.28       kre 	return (pid_t)n;
    245       1.4       jtc }
    246       1.4       jtc 
    247      1.20  christos static void
    248      1.28       kre nosig(const char *name)
    249       1.1       cgd {
    250       1.7   mycroft 
    251       1.7   mycroft 	warnx("unknown signal %s; valid signals:", name);
    252  1.28.4.1  pgoyette 	printsignals(stderr, 0);
    253       1.1       cgd 	exit(1);
    254      1.15   mycroft 	/* NOTREACHED */
    255       1.1       cgd }
    256       1.1       cgd 
    257  1.28.4.2  pgoyette #ifndef SHELL
    258  1.28.4.1  pgoyette /*
    259  1.28.4.1  pgoyette  * Print the names of all the signals (neatly) to fp
    260  1.28.4.1  pgoyette  * "len" gives the number of chars already printed to
    261  1.28.4.1  pgoyette  * the current output line (in kill.c, always 0)
    262  1.28.4.1  pgoyette  */
    263  1.28.4.1  pgoyette void
    264  1.28.4.1  pgoyette printsignals(FILE *fp, int len)
    265       1.1       cgd {
    266      1.20  christos 	int sig;
    267  1.28.4.1  pgoyette 	int nl, pad;
    268      1.20  christos 	const char *name;
    269      1.20  christos 	int termwidth = 80;
    270      1.20  christos 
    271      1.28       kre 	if ((name = getenv("COLUMNS")) != 0)
    272      1.28       kre 		termwidth = atoi(name);
    273      1.28       kre 	else if (isatty(fileno(fp))) {
    274      1.20  christos 		struct winsize win;
    275      1.28       kre 
    276      1.20  christos 		if (ioctl(fileno(fp), TIOCGWINSZ, &win) == 0 && win.ws_col > 0)
    277      1.20  christos 			termwidth = win.ws_col;
    278      1.20  christos 	}
    279       1.1       cgd 
    280  1.28.4.1  pgoyette 	pad = (len | 7) + 1 - len;
    281  1.28.4.1  pgoyette 
    282  1.28.4.1  pgoyette 	for (sig = 0; (sig = signalnext(sig)) != 0; ) {
    283      1.28       kre 		name = signalname(sig);
    284      1.28       kre 		if (name == NULL)
    285      1.28       kre 			continue;
    286      1.28       kre 
    287      1.28       kre 		nl = strlen(name);
    288      1.20  christos 
    289      1.28       kre 		if (len > 0 && nl + len + pad >= termwidth) {
    290      1.20  christos 			fprintf(fp, "\n");
    291      1.20  christos 			len = 0;
    292      1.28       kre 			pad = 0;
    293      1.28       kre 		} else if (pad > 0 && len != 0)
    294      1.28       kre 			fprintf(fp, "%*s", pad, "");
    295      1.28       kre 		else
    296      1.28       kre 			pad = 0;
    297      1.28       kre 
    298      1.28       kre 		len += nl + pad;
    299      1.28       kre 		pad = (nl | 7) + 1 - nl;
    300      1.28       kre 
    301      1.20  christos 		fprintf(fp, "%s", name);
    302       1.7   mycroft 	}
    303      1.20  christos 	if (len != 0)
    304      1.20  christos 		fprintf(fp, "\n");
    305       1.1       cgd }
    306  1.28.4.2  pgoyette #endif
    307       1.1       cgd 
    308      1.20  christos static void
    309      1.18       wiz usage(void)
    310       1.1       cgd {
    311      1.28       kre 	const char *pn = getprogname();
    312       1.7   mycroft 
    313      1.20  christos 	fprintf(stderr, "usage: %s [-s signal_name] pid ...\n"
    314      1.28       kre 			"       %s -l [exit_status]\n"
    315      1.28       kre 			"       %s -signal_name pid ...\n"
    316      1.28       kre 			"       %s -signal_number pid ...\n",
    317      1.28       kre 	    pn, pn, pn, pn);
    318       1.1       cgd 	exit(1);
    319      1.15   mycroft 	/* NOTREACHED */
    320       1.1       cgd }
    321