1 /* kill -- send a signal to a process
2 Copyright (C) 2002-2023 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 <https://www.gnu.org/licenses/>. */
17 /* Written by Paul Eggert. */
20 #include <stdckdint.h>
23 #include <sys/types.h>
28 #include "operand2sig.h"
31 /* The official name of this program (e.g., no 'g' prefix). */
32 #define PROGRAM_NAME "kill"
34 #define AUTHORS proper_name ("Paul Eggert")
36 static char const short_options
[] =
37 "0::1::2::3::4::5::6::7::8::9::"
38 "A::B::C::D::E::F::G::H::I::J::K::M::"
39 "N::O::P::Q::R::S::T::U::V::W::X::Y::Z::"
42 static struct option
const long_options
[] =
44 {"list", no_argument
, nullptr, 'l'},
45 {"signal", required_argument
, nullptr, 's'},
46 {"table", no_argument
, nullptr, 't'},
47 {GETOPT_HELP_OPTION_DECL
},
48 {GETOPT_VERSION_OPTION_DECL
},
49 {nullptr, 0, nullptr, 0}
55 if (status
!= EXIT_SUCCESS
)
60 Usage: %s [-s SIGNAL | -SIGNAL] PID...\n\
61 or: %s -l [SIGNAL]...\n\
62 or: %s -t [SIGNAL]...\n\
64 program_name
, program_name
, program_name
);
66 Send signals to processes, or list signals.\n\
69 emit_mandatory_arg_note ();
72 -s, --signal=SIGNAL, -SIGNAL\n\
73 specify the name or number of the signal to be sent\n\
74 -l, --list list signal names, or convert signal names to/from numbers\n\
75 -t, --table print a table of signal information\n\
77 fputs (HELP_OPTION_DESCRIPTION
, stdout
);
78 fputs (VERSION_OPTION_DESCRIPTION
, stdout
);
80 SIGNAL may be a signal name like 'HUP', or a signal number like '1',\n\
81 or the exit status of a process terminated by a signal.\n\
82 PID is an integer; if negative it identifies a process group.\n\
84 printf (USAGE_BUILTIN_WARNING
, PROGRAM_NAME
);
85 emit_ancillary_info (PROGRAM_NAME
);
90 /* Print a row of 'kill -t' output. NUM_WIDTH is the maximum signal
91 number width, and SIGNUM is the signal number to print. The
92 maximum name width is NAME_WIDTH, and SIGNAME is the name to print. */
95 print_table_row (int num_width
, int signum
,
96 int name_width
, char const *signame
)
98 char const *description
= strsignal (signum
);
99 printf ("%*d %-*s %s\n", num_width
, signum
, name_width
, signame
,
100 description
? description
: "?");
103 /* Print a list of signal names. If TABLE, print a table.
104 Print the names specified by ARGV if nonzero; otherwise,
105 print all known names. Return a suitable exit status. */
108 list_signals (bool table
, char *const *argv
)
111 int status
= EXIT_SUCCESS
;
112 char signame
[SIG2STR_MAX
];
118 /* Compute the maximum width of a signal number. */
120 for (signum
= 1; signum
<= SIGNUM_BOUND
/ 10; signum
*= 10)
123 /* Compute the maximum width of a signal name. */
124 for (signum
= 1; signum
<= SIGNUM_BOUND
; signum
++)
125 if (sig2str (signum
, signame
) == 0)
127 idx_t len
= strlen (signame
);
128 if (name_width
< len
)
133 for (; *argv
; argv
++)
135 signum
= operand2sig (*argv
, signame
);
137 status
= EXIT_FAILURE
;
139 print_table_row (num_width
, signum
, name_width
, signame
);
142 for (signum
= 1; signum
<= SIGNUM_BOUND
; signum
++)
143 if (sig2str (signum
, signame
) == 0)
144 print_table_row (num_width
, signum
, name_width
, signame
);
149 for (; *argv
; argv
++)
151 signum
= operand2sig (*argv
, signame
);
153 status
= EXIT_FAILURE
;
156 if (ISDIGIT (**argv
))
159 printf ("%d\n", signum
);
163 for (signum
= 1; signum
<= SIGNUM_BOUND
; signum
++)
164 if (sig2str (signum
, signame
) == 0)
171 /* Send signal SIGNUM to all the processes or process groups specified
172 by ARGV. Return a suitable exit status. */
175 send_signals (int signum
, char *const *argv
)
177 int status
= EXIT_SUCCESS
;
178 char const *arg
= *argv
;
183 intmax_t n
= (errno
= 0, strtoimax (arg
, &endp
, 10));
186 if (errno
== ERANGE
|| ckd_add (&pid
, n
, 0)
187 || arg
== endp
|| *endp
)
189 error (0, 0, _("%s: invalid process id"), quote (arg
));
190 status
= EXIT_FAILURE
;
192 else if (kill (pid
, signum
) != 0)
194 error (0, errno
, "%s", quote (arg
));
195 status
= EXIT_FAILURE
;
198 while ((arg
= *++argv
));
204 main (int argc
, char **argv
)
210 char signame
[SIG2STR_MAX
];
212 initialize_main (&argc
, &argv
);
213 set_program_name (argv
[0]);
214 setlocale (LC_ALL
, "");
215 bindtextdomain (PACKAGE
, LOCALEDIR
);
216 textdomain (PACKAGE
);
218 atexit (close_stdout
);
220 while ((optc
= getopt_long (argc
, argv
, short_options
, long_options
, nullptr))
224 case '0': case '1': case '2': case '3': case '4':
225 case '5': case '6': case '7': case '8': case '9':
228 /* This option is actually a process-id. */
230 goto no_more_options
;
233 case 'A': case 'B': case 'C': case 'D': case 'E':
234 case 'F': case 'G': case 'H': case 'I': case 'J':
235 case 'K': /*case 'L':*/ case 'M': case 'N': case 'O':
236 case 'P': case 'Q': case 'R': case 'S': case 'T':
237 case 'U': case 'V': case 'W': case 'X': case 'Y':
240 optarg
= argv
[optind
- 1] + strlen (argv
[optind
- 1]);
241 if (optarg
!= argv
[optind
- 1] + 2)
243 error (0, 0, _("invalid option -- %c"), optc
);
244 usage (EXIT_FAILURE
);
248 case 'n': /* -n is not documented, but is for Bash compatibility. */
252 error (0, 0, _("%s: multiple signals specified"), quote (optarg
));
253 usage (EXIT_FAILURE
);
255 signum
= operand2sig (optarg
, signame
);
257 usage (EXIT_FAILURE
);
260 case 'L': /* -L is not documented, but is for procps compatibility. */
267 error (0, 0, _("multiple -l or -t options specified"));
268 usage (EXIT_FAILURE
);
273 case_GETOPT_HELP_CHAR
;
274 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
276 usage (EXIT_FAILURE
);
284 error (0, 0, _("cannot combine signal with -l or -t"));
285 usage (EXIT_FAILURE
);
288 if ( ! list
&& argc
<= optind
)
290 error (0, 0, _("no process ID specified"));
291 usage (EXIT_FAILURE
);
295 ? list_signals (table
, optind
< argc
? argv
+ optind
: nullptr)
296 : send_signals (signum
, argv
+ optind
));