convert single-author programs to use proper_name
[platform/upstream/coreutils.git] / src / kill.c
1 /* kill -- send a signal to a process
2    Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>.  */
16
17 /* Written by Paul Eggert.  */
18
19 #include <config.h>
20 #include <stdio.h>
21 #include <getopt.h>
22 #include <sys/types.h>
23 #include <signal.h>
24
25 #if HAVE_SYS_WAIT_H
26 # include <sys/wait.h>
27 #endif
28 #ifndef WIFSIGNALED
29 # define WIFSIGNALED(s) (((s) & 0xFFFF) - 1 < (unsigned int) 0xFF)
30 #endif
31 #ifndef WTERMSIG
32 # define WTERMSIG(s) ((s) & 0x7F)
33 #endif
34
35 #include "system.h"
36 #include "error.h"
37 #include "sig2str.h"
38
39 /* The official name of this program (e.g., no `g' prefix).  */
40 #define PROGRAM_NAME "kill"
41
42 #define AUTHORS proper_name ("Paul Eggert")
43 \f
44 #if ! (HAVE_DECL_STRSIGNAL || defined strsignal)
45 # if ! (HAVE_DECL_SYS_SIGLIST || defined sys_siglist)
46 #  if HAVE_DECL__SYS_SIGLIST || defined _sys_siglist
47 #   define sys_siglist _sys_siglist
48 #  elif HAVE_DECL___SYS_SIGLIST || defined __sys_siglist
49 #   define sys_siglist __sys_siglist
50 #  endif
51 # endif
52 # if HAVE_DECL_SYS_SIGLIST || defined sys_siglist
53 #  define strsignal(signum) (0 <= (signum) && (signum) <= SIGNUM_BOUND \
54                              ? sys_siglist[signum] \
55                              : 0)
56 # endif
57 # ifndef strsignal
58 #  define strsignal(signum) 0
59 # endif
60 #endif
61 \f
62 /* The name this program was run with, for error messages.  */
63 char *program_name;
64
65 static char const short_options[] =
66   "0::1::2::3::4::5::6::7::8::9::"
67   "A::B::C::D::E::F::G::H::I::J::K::L::M::"
68   "N::O::P::Q::R::S::T::U::V::W::X::Y::Z::"
69   "ln:s:t";
70
71 static struct option const long_options[] =
72 {
73   {"list", no_argument, NULL, 'l'},
74   {"signal", required_argument, NULL, 's'},
75   {"table", no_argument, NULL, 't'},
76   {GETOPT_HELP_OPTION_DECL},
77   {GETOPT_VERSION_OPTION_DECL},
78   {NULL, 0, NULL, 0}
79 };
80
81 void
82 usage (int status)
83 {
84   if (status != EXIT_SUCCESS)
85     fprintf (stderr, _("Try `%s --help' for more information.\n"),
86              program_name);
87   else
88     {
89       printf (_("\
90 Usage: %s [-s SIGNAL | -SIGNAL] PID...\n\
91   or:  %s -l [SIGNAL]...\n\
92   or:  %s -t [SIGNAL]...\n\
93 "),
94               program_name, program_name, program_name);
95       fputs (_("\
96 Send signals to processes, or list signals.\n\
97 \n\
98 "), stdout);
99       fputs (_("\
100 Mandatory arguments to long options are mandatory for short options too.\n\
101 "), stdout);
102       fputs (_("\
103   -s, --signal=SIGNAL, -SIGNAL\n\
104                    specify the name or number of the signal to be sent\n\
105   -l, --list       list signal names, or convert signal names to/from numbers\n\
106   -t, --table      print a table of signal information\n\
107 "), stdout);
108       fputs (HELP_OPTION_DESCRIPTION, stdout);
109       fputs (VERSION_OPTION_DESCRIPTION, stdout);
110       fputs (_("\n\
111 SIGNAL may be a signal name like `HUP', or a signal number like `1',\n\
112 or an exit status of a process terminated by a signal.\n\
113 PID is an integer; if negative it identifies a process group.\n\
114 "), stdout);
115       printf (USAGE_BUILTIN_WARNING, PROGRAM_NAME);
116       emit_bug_reporting_address ();
117     }
118   exit (status);
119 }
120 \f
121 /* Convert OPERAND to a signal number with printable representation SIGNAME.
122    Return the signal number, or -1 if unsuccessful.  */
123
124 static int
125 operand2sig (char const *operand, char *signame)
126 {
127   int signum;
128
129   if (ISDIGIT (*operand))
130     {
131       char *endp;
132       long int l = (errno = 0, strtol (operand, &endp, 10));
133       int i = l;
134       signum = (operand == endp || *endp || errno || i != l ? -1
135                 : WIFSIGNALED (i) ? WTERMSIG (i)
136                 : i);
137     }
138   else
139     {
140       /* Convert signal to upper case in the C locale, not in the
141          current locale.  Don't assume ASCII; it might be EBCDIC.  */
142       char *upcased = xstrdup (operand);
143       char *p;
144       for (p = upcased; *p; p++)
145         if (strchr ("abcdefghijklmnopqrstuvwxyz", *p))
146           *p += 'A' - 'a';
147
148       /* Look for the signal name, possibly prefixed by "SIG",
149          and possibly lowercased.  */
150       if (! (str2sig (upcased, &signum) == 0
151              || (upcased[0] == 'S' && upcased[1] == 'I' && upcased[2] == 'G'
152                  && str2sig (upcased + 3, &signum) == 0)))
153         signum = -1;
154
155       free (upcased);
156     }
157
158   if (signum < 0 || sig2str (signum, signame) != 0)
159     {
160       error (0, 0, _("%s: invalid signal"), operand);
161       return -1;
162     }
163
164   return signum;
165 }
166 \f
167 /* Print a row of `kill -t' output.  NUM_WIDTH is the maximum signal
168    number width, and SIGNUM is the signal number to print.  The
169    maximum name width is NAME_WIDTH, and SIGNAME is the name to print.  */
170
171 static void
172 print_table_row (unsigned int num_width, int signum,
173                  unsigned int name_width, char const *signame)
174 {
175   char const *description = strsignal (signum);
176   printf ("%*d %-*s %s\n", num_width, signum, name_width, signame,
177           description ? description : "?");
178 }
179
180 /* Print a list of signal names.  If TABLE, print a table.
181    Print the names specified by ARGV if nonzero; otherwise,
182    print all known names.  Return a suitable exit status.  */
183
184 static int
185 list_signals (bool table, char *const *argv)
186 {
187   int signum;
188   int status = EXIT_SUCCESS;
189   char signame[SIG2STR_MAX];
190
191   if (table)
192     {
193       unsigned int name_width = 0;
194
195       /* Compute the maximum width of a signal number.  */
196       unsigned int num_width = 1;
197       for (signum = 1; signum <= SIGNUM_BOUND / 10; signum *= 10)
198         num_width++;
199
200       /* Compute the maximum width of a signal name.  */
201       for (signum = 1; signum <= SIGNUM_BOUND; signum++)
202         if (sig2str (signum, signame) == 0)
203           {
204             size_t len = strlen (signame);
205             if (name_width < len)
206               name_width = len;
207           }
208
209       if (argv)
210         for (; *argv; argv++)
211           {
212             signum = operand2sig (*argv, signame);
213             if (signum < 0)
214               status = EXIT_FAILURE;
215             else
216               print_table_row (num_width, signum, name_width, signame);
217           }
218       else
219         for (signum = 1; signum <= SIGNUM_BOUND; signum++)
220           if (sig2str (signum, signame) == 0)
221             print_table_row (num_width, signum, name_width, signame);
222     }
223   else
224     {
225       if (argv)
226         for (; *argv; argv++)
227           {
228             signum = operand2sig (*argv, signame);
229             if (signum < 0)
230               status = EXIT_FAILURE;
231             else
232               {
233                 if (ISDIGIT (**argv))
234                   puts (signame);
235                 else
236                   printf ("%d\n", signum);
237               }
238           }
239       else
240         for (signum = 1; signum <= SIGNUM_BOUND; signum++)
241           if (sig2str (signum, signame) == 0)
242             puts (signame);
243     }
244
245   return status;
246 }
247 \f
248 /* Send signal SIGNUM to all the processes or process groups specified
249    by ARGV.  Return a suitable exit status.  */
250
251 static int
252 send_signals (int signum, char *const *argv)
253 {
254   int status = EXIT_SUCCESS;
255   char const *arg = *argv;
256
257   do
258     {
259       char *endp;
260       intmax_t n = (errno = 0, strtoimax (arg, &endp, 10));
261       pid_t pid = n;
262
263       if (errno == ERANGE || pid != n || arg == endp || *endp)
264         {
265           error (0, 0, _("%s: invalid process id"), arg);
266           status = EXIT_FAILURE;
267         }
268       else if (kill (pid, signum) != 0)
269         {
270           error (0, errno, "%s", arg);
271           status = EXIT_FAILURE;
272         }
273     }
274   while ((arg = *++argv));
275
276   return status;
277 }
278 \f
279 int
280 main (int argc, char **argv)
281 {
282   int optc;
283   bool list = false;
284   bool table = false;
285   int signum = -1;
286   char signame[SIG2STR_MAX];
287
288   initialize_main (&argc, &argv);
289   program_name = argv[0];
290   setlocale (LC_ALL, "");
291   bindtextdomain (PACKAGE, LOCALEDIR);
292   textdomain (PACKAGE);
293
294   atexit (close_stdout);
295
296   while ((optc = getopt_long (argc, argv, short_options, long_options, NULL))
297          != -1)
298     switch (optc)
299       {
300       case '0': case '1': case '2': case '3': case '4':
301       case '5': case '6': case '7': case '8': case '9':
302         if (optind != 2)
303           {
304             /* This option is actually a process-id.  */
305             optind--;
306             goto no_more_options;
307           }
308         /* Fall through.  */
309       case 'A': case 'B': case 'C': case 'D': case 'E':
310       case 'F': case 'G': case 'H': case 'I': case 'J':
311       case 'K': case 'L': case 'M': case 'N': case 'O':
312       case 'P': case 'Q': case 'R': case 'S': case 'T':
313       case 'U': case 'V': case 'W': case 'X': case 'Y':
314       case 'Z':
315         if (! optarg)
316           optarg = argv[optind - 1] + strlen (argv[optind - 1]);
317         if (optarg != argv[optind - 1] + 2)
318           {
319             error (0, 0, _("invalid option -- %c"), optc);
320             usage (EXIT_FAILURE);
321           }
322         optarg--;
323         /* Fall through.  */
324       case 'n': /* -n is not documented, but is for Bash compatibility.  */
325       case 's':
326         if (0 <= signum)
327           {
328             error (0, 0, _("%s: multiple signals specified"), optarg);
329             usage (EXIT_FAILURE);
330           }
331         signum = operand2sig (optarg, signame);
332         if (signum < 0)
333           usage (EXIT_FAILURE);
334         break;
335
336       case 't':
337         table = true;
338         /* Fall through.  */
339       case 'l':
340         if (list)
341           {
342             error (0, 0, _("multiple -l or -t options specified"));
343             usage (EXIT_FAILURE);
344           }
345         list = true;
346         break;
347
348       case_GETOPT_HELP_CHAR;
349       case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
350       default:
351         usage (EXIT_FAILURE);
352       }
353  no_more_options:;
354
355   if (signum < 0)
356     signum = SIGTERM;
357   else if (list)
358     {
359       error (0, 0, _("cannot combine signal with -l or -t"));
360       usage (EXIT_FAILURE);
361     }
362
363   if ( ! list && argc <= optind)
364     {
365       error (0, 0, _("no process ID specified"));
366       usage (EXIT_FAILURE);
367     }
368
369   return (list
370           ? list_signals (table, optind < argc ? argv + optind : NULL)
371           : send_signals (signum, argv + optind));
372 }