xref: /openbsd/bin/kill/kill.c (revision a6445c1d)
1 /*	$OpenBSD: kill.c,v 1.12 2014/03/23 12:44:00 millert Exp $	*/
2 /*	$NetBSD: kill.c,v 1.11 1995/09/07 06:30:27 jtc Exp $	*/
3 
4 /*
5  * Copyright (c) 1988, 1993, 1994
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <ctype.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <signal.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 extern	char *__progname;
42 
43 void nosig(char *);
44 void printsignals(FILE *);
45 int signame_to_signum(char *);
46 void usage(void);
47 
48 int
49 main(int argc, char *argv[])
50 {
51 	int errors, numsig, pid;
52 	char *ep;
53 
54 	if (argc < 2)
55 		usage();
56 
57 	numsig = SIGTERM;
58 
59 	argc--, argv++;
60 	if (!strcmp(*argv, "-l")) {
61 		argc--, argv++;
62 		if (argc > 0 && !strcmp(*argv, "--"))
63 			argc--, argv++;
64 		if (argc > 1)
65 			usage();
66 		if (argc == 1) {
67 			if (!isdigit((unsigned char)**argv))
68 				usage();
69 			numsig = strtol(*argv, &ep, 10);
70 			if (*ep)
71 				errx(1, "illegal signal number: %s", *argv);
72 			if (numsig >= 128)
73 				numsig -= 128;
74 			if (numsig <= 0 || numsig >= NSIG)
75 				nosig(*argv);
76 			printf("%s\n", sys_signame[numsig]);
77 			exit(0);
78 		}
79 		printsignals(stdout);
80 		exit(0);
81 	}
82 
83 	if (!strcmp(*argv, "-s")) {
84 		argc--, argv++;
85 		if (argc > 0 && !strcmp(*argv, "--"))
86 			argc--, argv++;
87 		if (argc < 1) {
88 			warnx("option requires an argument -- s");
89 			usage();
90 		}
91 		if (strcmp(*argv, "0")) {
92 			if ((numsig = signame_to_signum(*argv)) < 0)
93 				nosig(*argv);
94 		} else
95 			numsig = 0;
96 		argc--, argv++;
97 	} else if (**argv == '-') {
98 		if (strcmp(*argv, "--")) {
99 			++*argv;
100 			if (isalpha((unsigned char)**argv)) {
101 				if ((numsig = signame_to_signum(*argv)) < 0)
102 					nosig(*argv);
103 			} else if (isdigit((unsigned char)**argv)) {
104 				numsig = strtol(*argv, &ep, 10);
105 				if (*ep)
106 					errx(1, "illegal signal number: %s", *argv);
107 				if (numsig < 0 || numsig >= NSIG)
108 					nosig(*argv);
109 			} else
110 				nosig(*argv);
111 		}
112 		argc--, argv++;
113 	}
114 
115 	if (argc == 0)
116 		usage();
117 
118 	for (errors = 0; argc; argc--, argv++) {
119 		pid = strtol(*argv, &ep, 10);
120 		if (!**argv || *ep) {
121 			warnx("illegal process id: %s", *argv);
122 			errors = 1;
123 		} else if (kill(pid, numsig) == -1) {
124 			warn("%s", *argv);
125 			errors = 1;
126 		}
127 	}
128 
129 	exit(errors);
130 }
131 
132 int
133 signame_to_signum(char *sig)
134 {
135 	int n;
136 
137 	if (!strncasecmp(sig, "sig", 3))
138 		sig += 3;
139 	for (n = 1; n < NSIG; n++) {
140 		if (!strcasecmp(sys_signame[n], sig))
141 			return (n);
142 	}
143 	return (-1);
144 }
145 
146 void
147 nosig(char *name)
148 {
149 
150 	warnx("unknown signal %s; valid signals:", name);
151 	printsignals(stderr);
152 	exit(1);
153 }
154 
155 void
156 printsignals(FILE *fp)
157 {
158 	int n;
159 
160 	for (n = 1; n < NSIG; n++) {
161 		(void)fprintf(fp, "%s", sys_signame[n]);
162 		if (n == (NSIG / 2) || n == (NSIG - 1))
163 			(void)fprintf(fp, "\n");
164 		else
165 			(void)fprintf(fp, " ");
166 	}
167 }
168 
169 void
170 usage(void)
171 {
172 	(void)fprintf(stderr, "usage: %s [-s signal_name] pid ...\n",
173 	    __progname);
174 	(void)fprintf(stderr, "       %s -l [exit_status]\n", __progname);
175 	(void)fprintf(stderr, "       %s -signal_name pid ...\n",
176 	    __progname);
177 	(void)fprintf(stderr, "       %s -signal_number pid ...\n",
178 	    __progname);
179 	exit(1);
180 }
181