xref: /freebsd/bin/kill/kill.c (revision 4db78cacdee1b6f3b7880eb8c5560e8edaf91698)
1  /*-
2   * SPDX-License-Identifier: BSD-3-Clause
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   * Important: This file is used both as a standalone program /bin/kill and
33   * as a builtin for /bin/sh (#define SHELL).
34   */
35  
36  #if 0
37  #ifndef lint
38  static char const copyright[] =
39  "@(#) Copyright (c) 1988, 1993, 1994\n\
40  	The Regents of the University of California.  All rights reserved.\n";
41  #endif /* not lint */
42  
43  #ifndef lint
44  static char sccsid[] = "@(#)kill.c	8.4 (Berkeley) 4/28/95";
45  #endif /* not lint */
46  #endif
47  #include <sys/cdefs.h>
48  __FBSDID("$FreeBSD$");
49  
50  #include <ctype.h>
51  #include <err.h>
52  #include <errno.h>
53  #include <signal.h>
54  #include <stdio.h>
55  #include <stdlib.h>
56  #include <string.h>
57  
58  #ifdef SHELL
59  #define main killcmd
60  #include "bltin/bltin.h"
61  #endif
62  
63  static void nosig(const char *);
64  static void printsignals(FILE *);
65  static int signame_to_signum(const char *);
66  static void usage(void);
67  
68  int
69  main(int argc, char *argv[])
70  {
71  	long pidl;
72  	pid_t pid;
73  	int errors, numsig, ret;
74  	char *ep;
75  
76  	if (argc < 2)
77  		usage();
78  
79  	numsig = SIGTERM;
80  
81  	argc--, argv++;
82  	if (!strcmp(*argv, "-l")) {
83  		argc--, argv++;
84  		if (argc > 1)
85  			usage();
86  		if (argc == 1) {
87  			if (!isdigit(**argv))
88  				usage();
89  			numsig = strtol(*argv, &ep, 10);
90  			if (!**argv || *ep)
91  				errx(2, "illegal signal number: %s", *argv);
92  			if (numsig >= 128)
93  				numsig -= 128;
94  			if (numsig <= 0 || numsig >= sys_nsig)
95  				nosig(*argv);
96  			printf("%s\n", sys_signame[numsig]);
97  			return (0);
98  		}
99  		printsignals(stdout);
100  		return (0);
101  	}
102  
103  	if (!strcmp(*argv, "-s")) {
104  		argc--, argv++;
105  		if (argc < 1) {
106  			warnx("option requires an argument -- s");
107  			usage();
108  		}
109  		if (strcmp(*argv, "0")) {
110  			if ((numsig = signame_to_signum(*argv)) < 0)
111  				nosig(*argv);
112  		} else
113  			numsig = 0;
114  		argc--, argv++;
115  	} else if (**argv == '-' && *(*argv + 1) != '-') {
116  		++*argv;
117  		if (isalpha(**argv)) {
118  			if ((numsig = signame_to_signum(*argv)) < 0)
119  				nosig(*argv);
120  		} else if (isdigit(**argv)) {
121  			numsig = strtol(*argv, &ep, 10);
122  			if (!**argv || *ep)
123  				errx(2, "illegal signal number: %s", *argv);
124  			if (numsig < 0)
125  				nosig(*argv);
126  		} else
127  			nosig(*argv);
128  		argc--, argv++;
129  	}
130  
131  	if (argc > 0 && strncmp(*argv, "--", 2) == 0)
132  		argc--, argv++;
133  
134  	if (argc == 0)
135  		usage();
136  
137  	for (errors = 0; argc; argc--, argv++) {
138  #ifdef SHELL
139  		if (**argv == '%')
140  			ret = killjob(*argv, numsig);
141  		else
142  #endif
143  		{
144  			pidl = strtol(*argv, &ep, 10);
145  			/* Check for overflow of pid_t. */
146  			pid = (pid_t)pidl;
147  			if (!**argv || *ep || pid != pidl)
148  				errx(2, "illegal process id: %s", *argv);
149  			ret = kill(pid, numsig);
150  		}
151  		if (ret == -1) {
152  			warn("%s", *argv);
153  			errors = 1;
154  		}
155  	}
156  
157  	return (errors);
158  }
159  
160  static int
161  signame_to_signum(const char *sig)
162  {
163  	int n;
164  
165  	if (strncasecmp(sig, "SIG", 3) == 0)
166  		sig += 3;
167  	for (n = 1; n < sys_nsig; n++) {
168  		if (!strcasecmp(sys_signame[n], sig))
169  			return (n);
170  	}
171  	return (-1);
172  }
173  
174  static void
175  nosig(const char *name)
176  {
177  
178  	warnx("unknown signal %s; valid signals:", name);
179  	printsignals(stderr);
180  #ifdef SHELL
181  	error(NULL);
182  #else
183  	exit(2);
184  #endif
185  }
186  
187  static void
188  printsignals(FILE *fp)
189  {
190  	int n;
191  
192  	for (n = 1; n < sys_nsig; n++) {
193  		(void)fprintf(fp, "%s", sys_signame[n]);
194  		if (n == (sys_nsig / 2) || n == (sys_nsig - 1))
195  			(void)fprintf(fp, "\n");
196  		else
197  			(void)fprintf(fp, " ");
198  	}
199  }
200  
201  static void
202  usage(void)
203  {
204  
205  	(void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
206  		"usage: kill [-s signal_name] pid ...",
207  		"       kill -l [exit_status]",
208  		"       kill -signal_name pid ...",
209  		"       kill -signal_number pid ...");
210  #ifdef SHELL
211  	error(NULL);
212  #else
213  	exit(2);
214  #endif
215  }
216