1 /* kill -- send a signal to a process
2 Copyright (C) 2002, 2003, 2004, 2005, 2008 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Written by Paul Eggert. */
22 #include <sys/types.h>
26 # include <sys/wait.h>
29 # define WIFSIGNALED(s) (((s) & 0xFFFF) - 1 < (unsigned int) 0xFF)
32 # define WTERMSIG(s) ((s) & 0x7F)
38 #include "operand2sig.h"
40 /* The official name of this program (e.g., no `g' prefix). */
41 #define PROGRAM_NAME "kill"
43 #define AUTHORS proper_name ("Paul Eggert")
45 #if ! (HAVE_DECL_STRSIGNAL || defined strsignal)
46 # if ! (HAVE_DECL_SYS_SIGLIST || defined sys_siglist)
47 # if HAVE_DECL__SYS_SIGLIST || defined _sys_siglist
48 # define sys_siglist _sys_siglist
49 # elif HAVE_DECL___SYS_SIGLIST || defined __sys_siglist
50 # define sys_siglist __sys_siglist
53 # if HAVE_DECL_SYS_SIGLIST || defined sys_siglist
54 # define strsignal(signum) (0 <= (signum) && (signum) <= SIGNUM_BOUND \
55 ? sys_siglist[signum] \
59 # define strsignal(signum) 0
63 /* The name this program was run with, for error messages. */
64 char const *program_name;
66 static char const short_options[] =
67 "0::1::2::3::4::5::6::7::8::9::"
68 "A::B::C::D::E::F::G::H::I::J::K::L::M::"
69 "N::O::P::Q::R::S::T::U::V::W::X::Y::Z::"
72 static struct option const long_options[] =
74 {"list", no_argument, NULL, 'l'},
75 {"signal", required_argument, NULL, 's'},
76 {"table", no_argument, NULL, 't'},
77 {GETOPT_HELP_OPTION_DECL},
78 {GETOPT_VERSION_OPTION_DECL},
85 if (status != EXIT_SUCCESS)
86 fprintf (stderr, _("Try `%s --help' for more information.\n"),
91 Usage: %s [-s SIGNAL | -SIGNAL] PID...\n\
92 or: %s -l [SIGNAL]...\n\
93 or: %s -t [SIGNAL]...\n\
95 program_name, program_name, program_name);
97 Send signals to processes, or list signals.\n\
101 Mandatory arguments to long options are mandatory for short options too.\n\
104 -s, --signal=SIGNAL, -SIGNAL\n\
105 specify the name or number of the signal to be sent\n\
106 -l, --list list signal names, or convert signal names to/from numbers\n\
107 -t, --table print a table of signal information\n\
109 fputs (HELP_OPTION_DESCRIPTION, stdout);
110 fputs (VERSION_OPTION_DESCRIPTION, stdout);
112 SIGNAL may be a signal name like `HUP', or a signal number like `1',\n\
113 or an exit status of a process terminated by a signal.\n\
114 PID is an integer; if negative it identifies a process group.\n\
116 printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
117 emit_bug_reporting_address ();
122 /* Print a row of `kill -t' output. NUM_WIDTH is the maximum signal
123 number width, and SIGNUM is the signal number to print. The
124 maximum name width is NAME_WIDTH, and SIGNAME is the name to print. */
127 print_table_row (unsigned int num_width, int signum,
128 unsigned int name_width, char const *signame)
130 char const *description = strsignal (signum);
131 printf ("%*d %-*s %s\n", num_width, signum, name_width, signame,
132 description ? description : "?");
135 /* Print a list of signal names. If TABLE, print a table.
136 Print the names specified by ARGV if nonzero; otherwise,
137 print all known names. Return a suitable exit status. */
140 list_signals (bool table, char *const *argv)
143 int status = EXIT_SUCCESS;
144 char signame[SIG2STR_MAX];
148 unsigned int name_width = 0;
150 /* Compute the maximum width of a signal number. */
151 unsigned int num_width = 1;
152 for (signum = 1; signum <= SIGNUM_BOUND / 10; signum *= 10)
155 /* Compute the maximum width of a signal name. */
156 for (signum = 1; signum <= SIGNUM_BOUND; signum++)
157 if (sig2str (signum, signame) == 0)
159 size_t len = strlen (signame);
160 if (name_width < len)
165 for (; *argv; argv++)
167 signum = operand2sig (*argv, signame);
169 status = EXIT_FAILURE;
171 print_table_row (num_width, signum, name_width, signame);
174 for (signum = 1; signum <= SIGNUM_BOUND; signum++)
175 if (sig2str (signum, signame) == 0)
176 print_table_row (num_width, signum, name_width, signame);
181 for (; *argv; argv++)
183 signum = operand2sig (*argv, signame);
185 status = EXIT_FAILURE;
188 if (ISDIGIT (**argv))
191 printf ("%d\n", signum);
195 for (signum = 1; signum <= SIGNUM_BOUND; signum++)
196 if (sig2str (signum, signame) == 0)
203 /* Send signal SIGNUM to all the processes or process groups specified
204 by ARGV. Return a suitable exit status. */
207 send_signals (int signum, char *const *argv)
209 int status = EXIT_SUCCESS;
210 char const *arg = *argv;
215 intmax_t n = (errno = 0, strtoimax (arg, &endp, 10));
218 if (errno == ERANGE || pid != n || arg == endp || *endp)
220 error (0, 0, _("%s: invalid process id"), arg);
221 status = EXIT_FAILURE;
223 else if (kill (pid, signum) != 0)
225 error (0, errno, "%s", arg);
226 status = EXIT_FAILURE;
229 while ((arg = *++argv));
235 main (int argc, char **argv)
241 char signame[SIG2STR_MAX];
243 initialize_main (&argc, &argv);
244 program_name = argv[0];
245 setlocale (LC_ALL, "");
246 bindtextdomain (PACKAGE, LOCALEDIR);
247 textdomain (PACKAGE);
249 atexit (close_stdout);
251 while ((optc = getopt_long (argc, argv, short_options, long_options, NULL))
255 case '0': case '1': case '2': case '3': case '4':
256 case '5': case '6': case '7': case '8': case '9':
259 /* This option is actually a process-id. */
261 goto no_more_options;
264 case 'A': case 'B': case 'C': case 'D': case 'E':
265 case 'F': case 'G': case 'H': case 'I': case 'J':
266 case 'K': case 'L': case 'M': case 'N': case 'O':
267 case 'P': case 'Q': case 'R': case 'S': case 'T':
268 case 'U': case 'V': case 'W': case 'X': case 'Y':
271 optarg = argv[optind - 1] + strlen (argv[optind - 1]);
272 if (optarg != argv[optind - 1] + 2)
274 error (0, 0, _("invalid option -- %c"), optc);
275 usage (EXIT_FAILURE);
279 case 'n': /* -n is not documented, but is for Bash compatibility. */
283 error (0, 0, _("%s: multiple signals specified"), optarg);
284 usage (EXIT_FAILURE);
286 signum = operand2sig (optarg, signame);
288 usage (EXIT_FAILURE);
297 error (0, 0, _("multiple -l or -t options specified"));
298 usage (EXIT_FAILURE);
303 case_GETOPT_HELP_CHAR;
304 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
306 usage (EXIT_FAILURE);
314 error (0, 0, _("cannot combine signal with -l or -t"));
315 usage (EXIT_FAILURE);
318 if ( ! list && argc <= optind)
320 error (0, 0, _("no process ID specified"));
321 usage (EXIT_FAILURE);
325 ? list_signals (table, optind < argc ? argv + optind : NULL)
326 : send_signals (signum, argv + optind));