1 /* kill -- send a signal to a process
2 Copyright (C) 2002 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 2, or (at your option)
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, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* Written by Paul Eggert. */
23 #include <sys/types.h>
27 # include <sys/wait.h>
30 # define WIFSIGNALED(s) (((s) & 0xFFFF) - 1 < (unsigned int) 0xFF)
33 # define WTERMSIG(s) ((s) & 0x7F)
41 /* The official name of this program (e.g., no `g' prefix). */
42 #define PROGRAM_NAME "kill"
44 #define AUTHORS "Paul Eggert"
46 #if ! (HAVE_DECL_STRTOIMAX || defined strtoimax)
47 intmax_t strtoimax ();
50 #if ! (HAVE_DECL_STRSIGNAL || defined strsignal)
51 # if ! (HAVE_DECL_SYS_SIGLIST || defined sys_siglist)
52 # if HAVE_DECL__SYS_SIGLIST || defined _sys_siglist
53 # define sys_siglist _sys_siglist
56 # if HAVE_DECL_SYS_SIGLIST || defined sys_siglist
57 # define strsignal(signum) (0 <= (signum) && (signum) <= SIGNUM_BOUND \
58 ? sys_siglist[signum] \
62 # define strsignal(signum) 0
66 /* The name this program was run with, for error messages. */
69 static char const short_options
[] =
70 "0::1::2::3::4::5::6::7::8::9::"
71 "A::B::C::D::E::F::G::H::I::J::K::L::M::"
72 "N::O::P::Q::R::S::T::U::V::W::X::Y::Z::"
75 static struct option
const long_options
[] =
77 {"list", no_argument
, NULL
, 'l'},
78 {"signal", required_argument
, NULL
, 's'},
79 {"table", no_argument
, NULL
, 't'},
80 {GETOPT_HELP_OPTION_DECL
},
81 {GETOPT_VERSION_OPTION_DECL
},
89 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
94 Usage: %s [-s SIGNAL | -SIGNAL] PID...\n\
95 or: %s -l [SIGNAL]...\n\
96 or: %s -t [SIGNAL]...\n\
98 program_name
, program_name
, program_name
);
100 Send signals to processes, or list signals.\n\
104 Mandatory arguments to long options are mandatory for short options too.\n\
107 -s, --signal=SIGNAL, -SIGNAL\n\
108 specify the name or number of the signal to be sent\n\
109 -l, --list list signal names, or convert signal names to/from numbers\n\
110 -t, --table print a table of signal information\n\
112 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
113 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
115 SIGNAL may be a signal name like `HUP', or a signal number like `1',\n\
116 or an exit status of a process terminated by a signal.\n\
117 PID is an integer; if negative it identifies a process group.\n\
119 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT
);
124 /* Convert OPERAND to a signal number with printable representation SIGNAME.
125 Return the signal number, or -1 if unsuccessful. */
128 operand2sig (char const *operand
, char *signame
)
132 if (ISDIGIT (*operand
))
135 long int l
= (errno
= 0, strtol (operand
, &endp
, 10));
137 signum
= (operand
== endp
|| *endp
|| errno
|| i
!= l
? -1
138 : WIFSIGNALED (i
) ? WTERMSIG (i
)
143 /* Convert signal to upper case in the C locale, not in the
144 current locale. Don't assume ASCII; it might be EBCDIC. */
145 char *upcased
= xstrdup (operand
);
147 for (p
= upcased
; *p
; p
++)
148 if (strchr ("abcdefghijklmnopqrstuvwxyz", *p
))
151 /* Look for the signal name, possibly prefixed by "SIG",
152 and possibly lowercased. */
153 if (! (str2sig (upcased
, &signum
) == 0
154 || (upcased
[0] == 'S' && upcased
[1] == 'I' && upcased
[2] == 'G'
155 && str2sig (upcased
+ 3, &signum
) == 0)))
161 if (signum
< 0 || sig2str (signum
, signame
) != 0)
163 error (0, 0, _("%s: invalid signal"), operand
);
170 /* Print a row of `kill -t' output. NUM_WIDTH is the maximum signal
171 number width, and SIGNUM is the signal number to print. The
172 maximum name width is NAME_WIDTH, and SIGNAME is the name to print. */
175 print_table_row (int num_width
, int signum
,
176 int name_width
, char const *signame
)
178 char const *description
= strsignal (signum
);
179 printf ("%*d %-*s %s\n", num_width
, signum
, name_width
, signame
,
180 description
? description
: "?");
183 /* Print a list of signal names. If TABLE, print a table.
184 Print the names specified by ARGV if nonzero; otherwise,
185 print all known names. Return a suitable exit status. */
188 list_signals (bool table
, char *const *argv
)
191 int status
= EXIT_SUCCESS
;
192 char signame
[SIG2STR_MAX
];
198 /* Compute the maximum width of a signal number. */
200 for (signum
= 1; signum
<= SIGNUM_BOUND
/ 10; signum
*= 10)
203 /* Compute the maximum width of a signal name. */
204 for (signum
= 1; signum
<= SIGNUM_BOUND
; signum
++)
205 if (sig2str (signum
, signame
) == 0)
207 size_t len
= strlen (signame
);
208 if (name_width
< len
)
213 for (; *argv
; argv
++)
215 signum
= operand2sig (*argv
, signame
);
217 status
= EXIT_FAILURE
;
219 print_table_row (num_width
, signum
, name_width
, signame
);
222 for (signum
= 1; signum
<= SIGNUM_BOUND
; signum
++)
223 if (sig2str (signum
, signame
) == 0)
224 print_table_row (num_width
, signum
, name_width
, signame
);
229 for (; *argv
; argv
++)
231 signum
= operand2sig (*argv
, signame
);
233 status
= EXIT_FAILURE
;
236 if (ISDIGIT (**argv
))
239 printf ("%d\n", signum
);
243 for (signum
= 1; signum
<= SIGNUM_BOUND
; signum
++)
244 if (sig2str (signum
, signame
) == 0)
251 /* Send signal SIGNUM to all the processes or process groups specified
252 by ARGV. Return a suitable exit status. */
255 send_signals (int signum
, char *const *argv
)
257 int status
= EXIT_SUCCESS
;
258 char const *arg
= *argv
;
262 error (0, 0, _("missing operand after `%s'"), argv
[-1]);
263 usage (EXIT_FAILURE
);
269 intmax_t n
= (errno
= 0, strtoimax (arg
, &endp
, 10));
272 if (errno
== ERANGE
|| pid
!= n
|| arg
== endp
|| *endp
)
274 error (0, 0, _("%s: invalid process id"), arg
);
275 status
= EXIT_FAILURE
;
277 else if (kill (pid
, signum
) != 0)
279 error (0, errno
, "%s", arg
);
280 status
= EXIT_FAILURE
;
283 while ((arg
= *++argv
));
289 main (int argc
, char **argv
)
295 char signame
[SIG2STR_MAX
];
297 program_name
= argv
[0];
298 setlocale (LC_ALL
, "");
299 bindtextdomain (PACKAGE
, LOCALEDIR
);
300 textdomain (PACKAGE
);
302 atexit (close_stdout
);
304 while ((optc
= getopt_long (argc
, argv
, short_options
, long_options
, NULL
))
308 case '0': case '1': case '2': case '3': case '4':
309 case '5': case '6': case '7': case '8': case '9':
312 /* This option is actually a process-id. */
314 goto no_more_options
;
317 case 'A': case 'B': case 'C': case 'D': case 'E':
318 case 'F': case 'G': case 'H': case 'I': case 'J':
319 case 'K': case 'L': case 'M': case 'N': case 'O':
320 case 'P': case 'Q': case 'R': case 'S': case 'T':
321 case 'U': case 'V': case 'W': case 'X': case 'Y':
324 optarg
= argv
[optind
- 1] + strlen (argv
[optind
- 1]);
325 if (optarg
!= argv
[optind
- 1] + 2)
327 error (0, 0, _("invalid option -- %c"), optc
);
328 usage (EXIT_FAILURE
);
332 case 'n': /* -n is not documented, but is for Bash compatibility. */
336 error (0, 0, _("%s: multiple signals specified"), optarg
);
337 usage (EXIT_FAILURE
);
339 signum
= operand2sig (optarg
, signame
);
341 usage (EXIT_FAILURE
);
350 error (0, 0, _("multiple -l or -t options specified"));
351 usage (EXIT_FAILURE
);
356 case_GETOPT_HELP_CHAR
;
357 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
359 usage (EXIT_FAILURE
);
367 error (0, 0, _("cannot combine signal with -l or -t"));
368 usage (EXIT_FAILURE
);
372 ? list_signals (table
, optind
== argc
? NULL
: argv
+ optind
)
373 : send_signals (signum
, argv
+ optind
));