diff --git a/Makefile.am b/Makefile.am index 1efa3327..e48f0aa4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -78,7 +78,7 @@ endif if BUILD_KILL bin_PROGRAMS += kill dist_man_MANS += kill.1 -kill_SOURCES = skill.c lib/strutils.c lib/fileutils.c lib/signals.c +kill_SOURCES = kill.c lib/strutils.c lib/fileutils.c lib/signals.c else EXTRA_DIST += kill.1 endif diff --git a/include/signals.h b/include/signals.h index 474685fa..695b2997 100644 --- a/include/signals.h +++ b/include/signals.h @@ -24,5 +24,13 @@ extern int signal_name_to_number(const char *__restrict name); extern const char *signal_number_to_name(int signo); +extern int skill_sig_option(int *argc, char **argv); + +extern char *strtosig(const char *restrict s); + +extern void pretty_print_signals(void); + +extern void unix_print_signals(void); + __END_DECLS #endif diff --git a/kill.c b/kill.c new file mode 100644 index 00000000..ce1e3c29 --- /dev/null +++ b/kill.c @@ -0,0 +1,139 @@ +/* + * 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 "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(_(" -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); +} + +int main(int argc, char **argv) +{ + int signo, i, sigopt=0, loop=1; + long pid; + int exitvalue = EXIT_SUCCESS; + + 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'}, + {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; + else + sigopt++; + + opterr=0; /* suppress errors on -123 */ + while (loop == 1 && (i = getopt_long(argc, argv, "l::Ls:hV", longopts, NULL)) != -1) + switch (i) { + case 'l': + if (optarg) { + char *s; + s = strtosig(optarg); + if (s) + printf("%s\n", s); + else + xwarnx(_("unknown signal name %s"), + optarg); + 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 '?': + if (!isdigit(optopt)) { + xwarnx(_("invalid argument %c"), optopt); + print_usage(stderr); + } else { + /* Special case for signal digit negative + * PIDs */ + pid = (long)('0' - optopt); + if (kill((pid_t)pid, signo) != 0) + exitvalue = EXIT_FAILURE; + exit(exitvalue); + } + loop=0; + break; + default: + print_usage(stderr); + } + + argc -= optind + sigopt; + argv += optind; + + for (i = 0; i < argc; i++) { + pid = strtol_or_err(argv[i], _("failed to parse argument")); + if (!kill((pid_t) pid, signo)) + continue; + exitvalue = EXIT_FAILURE; + continue; + } + + return exitvalue; +} diff --git a/lib/signals.c b/lib/signals.c index 6b468d22..cff3966c 100644 --- a/lib/signals.c +++ b/lib/signals.c @@ -198,3 +198,96 @@ const char *signal_number_to_name(int signo) return buf; } +int skill_sig_option(int *argc, char **argv) +{ + int i, nargs = *argc; + int signo = -1; + for (i = 1; i < nargs; i++) { + if (argv[i][0] == '-') { + signo = signal_name_to_number(argv[i] + 1); + if (-1 < signo) { + if (nargs - i) { + nargs--; + memmove(argv + i, argv + i + 1, + sizeof(char *) * (nargs - i)); + } + return signo; + } + } + } + return signo; +} + + +/* strtosig is similar to print_given_signals() with exception, that + * this function takes a string, and converts it to a signal name or + * a number string depending on which way a round conversion is + * queried. Non-existing signals return NULL. Notice that the + * returned string should be freed after use. + */ +char *strtosig(const char *restrict s) +{ + char *converted = NULL, *copy, *p, *endp; + int i, numsignal = 0; + + copy = strdup(s); + if (!copy) + xerrx(EXIT_FAILURE, "cannot duplicate string"); + for (p = copy; *p != '\0'; p++) + *p = toupper(*p); + p = copy; + if (p[0] == 'S' && p[1] == 'I' && p[2] == 'G') + p += 3; + if (isdigit(*p)){ + numsignal = strtol(s,&endp,10); + if(*endp || endp==s) + return NULL; /* not valid */ + } + if (numsignal){ + for (i = 0; i < number_of_signals; i++){ + if (numsignal == get_sigtable_num(i)){ + converted = strdup(get_sigtable_name(i)); + break; + } + } + } else { + for (i = 0; i < number_of_signals; i++){ + if (strcmp(p, get_sigtable_name(i)) == 0){ + converted = malloc(sizeof(char) * 8); + if (converted) + snprintf(converted, + sizeof(converted) - 1, + "%d", get_sigtable_num(i)); + break; + } + } + } + free(p); + return converted; +} + +void unix_print_signals(void) +{ + int pos = 0; + int i = 0; + while(++i <= number_of_signals){ + if(i-1) printf("%c", (pos>73)?(pos=0,'\n'):(pos++,' ') ); + pos += printf("%s", signal_number_to_name(i)); + } + printf("\n"); +} + +void pretty_print_signals(void) +{ + int i = 0; + while(++i <= number_of_signals){ + int n; + n = printf("%2d %s", i, signal_number_to_name(i)); + if(n>0 && i%7) + printf("%s", " \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + n); + else + printf("\n"); + } + if((i-1)%7) printf("\n"); +} + diff --git a/skill.c b/skill.c index fcd5c54b..584e22ee 100644 --- a/skill.c +++ b/skill.c @@ -76,17 +76,11 @@ static int sig_or_pri; enum { PROG_UNKNOWN, - PROG_KILL, PROG_SKILL, PROG_SNICE }; static int program = PROG_UNKNOWN; -static void display_kill_version(void) -{ - fprintf(stdout, PROCPS_NG_VERSION); -} - static int ns_flags = 0x3f; static int parse_namespaces(char *optarg) { @@ -120,78 +114,6 @@ static int parse_namespaces(char *optarg) return 0; } -static void unix_print_signals(void) -{ - int pos = 0; - int i = 0; - while(++i <= number_of_signals){ - if(i-1) printf("%c", (pos>73)?(pos=0,'\n'):(pos++,' ') ); - pos += printf("%s", signal_number_to_name(i)); - } - printf("\n"); -} - -static void pretty_print_signals(void) -{ - int i = 0; - while(++i <= number_of_signals){ - int n; - n = printf("%2d %s", i, signal_number_to_name(i)); - if(n>0 && i%7) - printf("%s", " \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + n); - else - printf("\n"); - } - if((i-1)%7) printf("\n"); -} - -/* strtosig is similar to print_given_signals() with exception, that - * this function takes a string, and converts it to a signal name or - * a number string depending on which way a round conversion is - * queried. Non-existing signals return NULL. Notice that the - * returned string should be freed after use. - */ -static char *strtosig(const char *restrict s) -{ - char *converted = NULL, *copy, *p, *endp; - int i, numsignal = 0; - - copy = strdup(s); - if (!copy) - xerrx(EXIT_FAILURE, "cannot duplicate string"); - for (p = copy; *p != '\0'; p++) - *p = toupper(*p); - p = copy; - if (p[0] == 'S' && p[1] == 'I' && p[2] == 'G') - p += 3; - if (isdigit(*p)){ - numsignal = strtol(s,&endp,10); - if(*endp || endp==s) - return NULL; /* not valid */ - } - if (numsignal){ - for (i = 0; i < number_of_signals; i++){ - if (numsignal == get_sigtable_num(i)){ - converted = strdup(get_sigtable_name(i)); - break; - } - } - } else { - for (i = 0; i < number_of_signals; i++){ - if (strcmp(p, get_sigtable_name(i)) == 0){ - converted = malloc(sizeof(char) * 8); - if (converted) - snprintf(converted, - sizeof(converted) - 1, - "%d", get_sigtable_num(i)); - break; - } - } - } - free(p); - return converted; -} - /* kill or nice a process */ static void hurt_proc(int tty, int uid, int pid, const char *restrict const cmd, struct run_time_conf_t *run_time) @@ -387,25 +309,6 @@ static void iterate(struct run_time_conf_t *run_time) closedir(d); } -/* kill help */ -static void __attribute__ ((__noreturn__)) kill_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(_(" -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); -} - /* skill and snice help */ static void __attribute__ ((__noreturn__)) skillsnice_usage(FILE * out) { @@ -465,132 +368,6 @@ static void __attribute__ ((__noreturn__)) skillsnice_usage(FILE * out) exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); } -static int skill_sig_option(int *argc, char **argv) -{ - int i, nargs = *argc; - int signo = -1; - for (i = 1; i < nargs; i++) { - if (argv[i][0] == '-') { - signo = signal_name_to_number(argv[i] + 1); - if (-1 < signo) { - if (nargs - i) { - nargs--; - memmove(argv + i, argv + i + 1, - sizeof(char *) * (nargs - i)); - } - return signo; - } - } - } - return signo; -} - -/* kill */ -static void __attribute__ ((__noreturn__)) - kill_main(int argc, char **argv) -{ - int signo, i; - int sigopt = 0; - int loop = 1; - long pid; - int exitvalue = EXIT_SUCCESS; - - 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'}, - {NULL, 0, NULL, 0} - }; - - setlocale (LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - atexit(close_stdout); - - if (argc < 2) - kill_usage(stderr); - - signo = skill_sig_option(&argc, argv); - if (signo < 0) - signo = SIGTERM; - else - sigopt++; - - opterr=0; /* suppress errors on -123 */ - while (loop == 1 && (i = getopt_long(argc, argv, "l::Ls:hV", longopts, NULL)) != -1) - switch (i) { - case 'l': - if (optarg) { - char *s; - s = strtosig(optarg); - if (s) - printf("%s\n", s); - else - xwarnx(_("unknown signal name %s"), - optarg); - 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': - kill_usage(stdout); - case 'V': - display_kill_version(); - exit(EXIT_SUCCESS); - case '?': - if (!isdigit(optopt)) { - xwarnx(_("invalid argument %c"), optopt); - kill_usage(stderr); - } else { - /* Special case for signal digit negative - * PIDs */ - pid = (long)('0' - optopt); - if (kill((pid_t)pid, signo) != 0) - exitvalue = EXIT_FAILURE; - exit(exitvalue); - } - loop=0; - break; - default: - kill_usage(stderr); - } - - argc -= optind + sigopt; - argv += optind; - - for (i = 0; i < argc; i++) { - pid = strtol_or_err(argv[i], _("failed to parse argument")); - if (!kill((pid_t) pid, signo)) - continue; - exitvalue = EXIT_FAILURE; - continue; - } - - exit(exitvalue); -} - -#if 0 -static void _skillsnice_usage(int line) -{ - fprintf(stderr, _("something at line %d\n"), line); - skillsnice_usage(stderr); -} - -#define skillsnice_usage() _skillsnice_usage(__LINE__) -#endif - -#define NEXTARG (argc?( argc--, ((argptr=*++argv)) ):NULL) - -/* common skill/snice argument parsing code */ static int snice_prio_option(int *argc, char **argv) { @@ -720,19 +497,19 @@ static void skillsnice_parse(int argc, ns_pid = atoi(optarg); if (ns_pid == 0) { xwarnx(_("invalid pid number %s"), optarg); - kill_usage(stderr); + skillsnice_usage(stderr); } if (procps_ns_read_pid(ns_pid, &ns) < 0) { xwarnx(_("error reading reference namespace " "information")); - kill_usage(stderr); + skillsnice_usage(stderr); } break; case NSLIST_OPTION: if (parse_namespaces(optarg)) { xwarnx(_("invalid namespace list")); - kill_usage(stderr); + skillsnice_usage(stderr); } break; case 'v': @@ -744,7 +521,7 @@ static void skillsnice_parse(int argc, case 'h': skillsnice_usage(stdout); case 'V': - display_kill_version(); + fprintf(stdout, PROCPS_NG_VERSION); exit(EXIT_SUCCESS); default: skillsnice_usage(stderr); @@ -799,10 +576,7 @@ int main(int argc, char ** argv) memset(&run_time, 0, sizeof(struct run_time_conf_t)); my_pid = getpid(); - if (strcmp(program_invocation_short_name, "kill") == 0 || - strcmp(program_invocation_short_name, "lt-kill") == 0) - program = PROG_KILL; - else if (strcmp(program_invocation_short_name, "skill") == 0 || + if (strcmp(program_invocation_short_name, "skill") == 0 || strcmp(program_invocation_short_name, "lt-skill") == 0) program = PROG_SKILL; else if (strcmp(program_invocation_short_name, "snice") == 0 || @@ -818,9 +592,6 @@ int main(int argc, char ** argv) show_lists(); iterate(&run_time); break; - case PROG_KILL: - kill_main(argc, argv); - break; default: fprintf(stderr, _("skill: \"%s\" is not supported\n"), program_invocation_short_name);