Home | History | Annotate | Line # | Download | only in kill
kill.c revision 1.23
      1 /* $NetBSD: kill.c,v 1.23 2003/08/07 09:05:13 agc Exp $ */
      2 
      3 /*
      4  * Copyright (c) 1988, 1993, 1994
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #if !defined(lint) && !defined(SHELL)
     34 __COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\n\
     35 	The Regents of the University of California.  All rights reserved.\n");
     36 #endif /* not lint */
     37 
     38 #ifndef lint
     39 #if 0
     40 static char sccsid[] = "@(#)kill.c	8.4 (Berkeley) 4/28/95";
     41 #else
     42 __RCSID("$NetBSD: kill.c,v 1.23 2003/08/07 09:05:13 agc Exp $");
     43 #endif
     44 #endif /* not lint */
     45 
     46 #include <ctype.h>
     47 #include <err.h>
     48 #include <errno.h>
     49 #include <signal.h>
     50 #include <stdio.h>
     51 #include <stdlib.h>
     52 #include <string.h>
     53 #include <termios.h>
     54 #include <unistd.h>
     55 #include <locale.h>
     56 #include <sys/ioctl.h>
     57 
     58 #ifdef SHELL            /* sh (aka ash) builtin */
     59 #define main killcmd
     60 #include "../../bin/sh/bltin/bltin.h"
     61 #endif /* SHELL */
     62 
     63 static void nosig(char *);
     64 static void printsignals(FILE *);
     65 static int signame_to_signum(char *);
     66 static void usage(void);
     67 int main(int, char *[]);
     68 
     69 int
     70 main(int argc, char *argv[])
     71 {
     72 	int errors, numsig, pid;
     73 	char *ep;
     74 
     75 	setprogname(argv[0]);
     76 	setlocale(LC_ALL, "");
     77 	if (argc < 2)
     78 		usage();
     79 
     80 	numsig = SIGTERM;
     81 
     82 	argc--, argv++;
     83 	if (strcmp(*argv, "-l") == 0) {
     84 		argc--, argv++;
     85 		if (argc > 1)
     86 			usage();
     87 		if (argc == 1) {
     88 			if (isdigit((unsigned char)**argv) == 0)
     89 				usage();
     90 			numsig = strtol(*argv, &ep, 10);
     91 			if (*ep != '\0') {
     92 				errx(EXIT_FAILURE, "illegal signal number: %s",
     93 						*argv);
     94 				/* NOTREACHED */
     95 			}
     96 			if (numsig >= 128)
     97 				numsig -= 128;
     98 			if (numsig <= 0 || numsig >= NSIG)
     99 				nosig(*argv);
    100 			printf("%s\n", sys_signame[numsig]);
    101 			exit(0);
    102 		}
    103 		printsignals(stdout);
    104 		exit(0);
    105 	}
    106 
    107 	if (!strcmp(*argv, "-s")) {
    108 		argc--, argv++;
    109 		if (argc < 1) {
    110 			warnx("option requires an argument -- s");
    111 			usage();
    112 		}
    113 		if (strcmp(*argv, "0")) {
    114 			if ((numsig = signame_to_signum(*argv)) < 0)
    115 				nosig(*argv);
    116 		} else
    117 			numsig = 0;
    118 		argc--, argv++;
    119 	} else if (**argv == '-') {
    120 		++*argv;
    121 		if (isalpha((unsigned char)**argv)) {
    122 			if ((numsig = signame_to_signum(*argv)) < 0)
    123 				nosig(*argv);
    124 		} else if (isdigit((unsigned char)**argv)) {
    125 			numsig = strtol(*argv, &ep, 10);
    126 			if (!*argv || *ep) {
    127 				errx(EXIT_FAILURE, "illegal signal number: %s",
    128 						*argv);
    129 				/* NOTREACHED */
    130 			}
    131 			if (numsig < 0 || numsig >= NSIG)
    132 				nosig(*argv);
    133 		} else
    134 			nosig(*argv);
    135 		argc--, argv++;
    136 	}
    137 
    138 	if (argc == 0)
    139 		usage();
    140 
    141 	for (errors = 0; argc; argc--, argv++) {
    142 #ifdef SHELL
    143 		extern int getjobpgrp(const char *);
    144 		if (*argv[0] == '%') {
    145 			pid = getjobpgrp(*argv);
    146 			if (pid == 0) {
    147 				warnx("illegal job id: %s", *argv);
    148 				errors = 1;
    149 				continue;
    150 			}
    151 		} else
    152 #endif
    153 		{
    154 			pid = strtol(*argv, &ep, 10);
    155 			if (!**argv || *ep) {
    156 				warnx("illegal process id: %s", *argv);
    157 				errors = 1;
    158 				continue;
    159 			}
    160 		}
    161 		if (kill(pid, numsig) == -1) {
    162 			warn("%s", *argv);
    163 			errors = 1;
    164 		}
    165 #ifdef SHELL
    166 		/* Wakeup the process if it was suspended, so it can
    167 		   exit without an explicit 'fg'. */
    168 		if (numsig == SIGTERM || numsig == SIGHUP)
    169 			kill(pid, SIGCONT);
    170 #endif
    171 	}
    172 
    173 	exit(errors);
    174 	/* NOTREACHED */
    175 }
    176 
    177 static int
    178 signame_to_signum(char *sig)
    179 {
    180 	int n;
    181 
    182 	if (strncasecmp(sig, "sig", 3) == 0)
    183 		sig += 3;
    184 	for (n = 1; n < NSIG; n++) {
    185 		if (!strcasecmp(sys_signame[n], sig))
    186 			return (n);
    187 	}
    188 	return (-1);
    189 }
    190 
    191 static void
    192 nosig(char *name)
    193 {
    194 
    195 	warnx("unknown signal %s; valid signals:", name);
    196 	printsignals(stderr);
    197 	exit(1);
    198 	/* NOTREACHED */
    199 }
    200 
    201 static void
    202 printsignals(FILE *fp)
    203 {
    204 	int sig;
    205 	int len, nl;
    206 	const char *name;
    207 	int termwidth = 80;
    208 
    209 	if (isatty(fileno(fp))) {
    210 		struct winsize win;
    211 		if (ioctl(fileno(fp), TIOCGWINSZ, &win) == 0 && win.ws_col > 0)
    212 			termwidth = win.ws_col;
    213 	}
    214 
    215 	for (len = 0, sig = 1; sig < NSIG; sig++) {
    216 		name = sys_signame[sig];
    217 		nl = 1 + strlen(name);
    218 
    219 		if (len + nl >= termwidth) {
    220 			fprintf(fp, "\n");
    221 			len = 0;
    222 		} else
    223 			if (len != 0)
    224 				fprintf(fp, " ");
    225 		len += nl;
    226 		fprintf(fp, "%s", name);
    227 	}
    228 	if (len != 0)
    229 		fprintf(fp, "\n");
    230 }
    231 
    232 static void
    233 usage(void)
    234 {
    235 
    236 	fprintf(stderr, "usage: %s [-s signal_name] pid ...\n"
    237 	    "       %s -l [exit_status]\n"
    238 	    "       %s -signal_name pid ...\n"
    239 	    "       %s -signal_number pid ...\n",
    240 	    getprogname(), getprogname(), getprogname(), getprogname());
    241 	exit(1);
    242 	/* NOTREACHED */
    243 }
    244