/* * kill.c - send a signal to process * Copyright 1998-2002 by Albert Cahalan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "c.h" #include "signals.h" #include "strutils.h" #include "nls.h" /* kill help */ static void __attribute__ ((__noreturn__)) print_usage(FILE * out) { fputs(USAGE_HEADER, out); fprintf(out, _(" %s [options] [...]\n"), program_invocation_short_name); fputs(USAGE_OPTIONS, out); fputs(_(" [...] send signal to every listed\n"), out); fputs(_(" -, -s, --signal \n" " specify the to be sent\n"), out); fputs(_(" -q, --queue integer value to be sent with the signal\n"), out); fputs(_(" -l, --list=[] list all signal names, or convert one to a name\n"), out); fputs(_(" -L, --table list all signal names in a nice table\n"), out); fputs(USAGE_SEPARATOR, out); fputs(USAGE_HELP, out); fputs(USAGE_VERSION, out); fprintf(out, USAGE_MAN_TAIL("kill(1)")); exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } inline static int execute_kill(pid_t pid, int sig_num, const bool use_sigqueue, union sigval sigval) { if (use_sigqueue) return sigqueue(pid, sig_num, sigval); else return kill(pid, sig_num); } int main(int argc, char **argv) { int signo, i; long pid; int exitvalue = EXIT_SUCCESS; int optindex; union sigval sigval; bool use_sigqueue = false; char *sig_option; static const struct option longopts[] = { {"list", optional_argument, NULL, 'l'}, {"table", no_argument, NULL, 'L'}, {"signal", required_argument, NULL, 's'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {"queue", required_argument, NULL, 'q'}, {NULL, 0, NULL, 0} }; setlocale (LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); if (argc < 2) print_usage(stderr); signo = skill_sig_option(&argc, argv); if (signo < 0) signo = SIGTERM; opterr=0; /* suppress errors on -123 */ while ((i = getopt_long(argc, argv, "l::Ls:hVq:", longopts, &optindex)) != -1) switch (i) { case 'l': sig_option = NULL; if (optarg) { sig_option = optarg; } else if (argv[optind] != NULL && argv[optind][0] != '-') { sig_option = argv[optind]; } if (sig_option) { char *s; s = strtosig(sig_option); if (s) printf("%s\n", s); else xwarnx(_("unknown signal name %s"), sig_option); free(s); } else { unix_print_signals(); } exit(EXIT_SUCCESS); case 'L': pretty_print_signals(); exit(EXIT_SUCCESS); case 's': signo = signal_name_to_number(optarg); break; case 'h': print_usage(stdout); case 'V': fprintf(stdout, PROCPS_NG_VERSION); exit(EXIT_SUCCESS); case 'q': sigval.sival_int = strtol_or_err(optarg, _("must be an integer value to be passed with the signal.")); use_sigqueue = true; break; case '?': if (!isdigit(optopt)) { xwarnx(_("invalid argument %c"), optopt); print_usage(stderr); } else { /* Special case for signal digit negative * PIDs */ pid = (long)('0' - optopt); if (!execute_kill((pid_t) pid, signo, use_sigqueue, sigval)) exitvalue = EXIT_FAILURE; exit(exitvalue); } xerrx(EXIT_FAILURE, _("internal error")); default: print_usage(stderr); } argc -= optind; argv += optind; if (argc < 1) print_usage(stderr); for (i = 0; i < argc; i++) { pid = strtol_or_err(argv[i], _("failed to parse argument")); if (!execute_kill((pid_t) pid, signo, use_sigqueue, sigval)) continue; error(0, errno, "(%ld)", pid); exitvalue = EXIT_FAILURE; continue; } return exitvalue; }