From 56399212c86846ff3b19739db154ccefa13f1546 Mon Sep 17 00:00:00 2001 From: Craig Small Date: Mon, 29 Jun 2015 21:52:51 +1000 Subject: [PATCH] library: Remove signal name from library Procps library previously held functions that were about either listing or finding signal names. These are not really the right location for a library about reading procfs. This patch handles signal related functions in two ways: For functions purely found in skill, these have been moved back into this binary as they are used nowhere else. For functions used across the binaries, these have been moved into include/signals.h and lib/signals.c. Besides formatting, these functions are largely the same. To assist the skill functions, two functions to access the signal map array have been added to lib/signals.c --- Makefile.am | 17 +- include/Makefile.am | 1 + proc/sig.h => include/signals.h | 16 +- lib/signals.c | 200 +++++ pgrep.c | 1366 +++++++++++++++---------------- proc/libprocps.sym | 5 - proc/sig.c | 294 ------- ps/display.c | 2 +- skill.c | 1224 ++++++++++++++------------- top/top.c | 2 +- 10 files changed, 1548 insertions(+), 1579 deletions(-) rename proc/sig.h => include/signals.h (74%) create mode 100644 lib/signals.c delete mode 100644 proc/sig.c diff --git a/Makefile.am b/Makefile.am index fe05f12c..2026b5e4 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/nsutils.c +kill_SOURCES = skill.c lib/strutils.c lib/fileutils.c lib/nsutils.c lib/signals.c else EXTRA_DIST += kill.1 endif @@ -102,6 +102,7 @@ top_top_SOURCES = \ top/top_nls.h \ top/top_nls.c \ lib/fileutils.c + lib/signals.c top_top_LDADD = $(LDADD) @NCURSES_LIBS@ $(DL_LIB) endif @@ -109,8 +110,8 @@ if BUILD_SKILL bin_PROGRAMS += \ skill \ snice -skill_SOURCES = skill.c lib/strutils.c lib/fileutils.c lib/nsutils.c -snice_SOURCES = skill.c lib/strutils.c lib/fileutils.c lib/nsutils.c +skill_SOURCES = skill.c lib/strutils.c lib/fileutils.c lib/nsutils.c lib/signals.c +snice_SOURCES = skill.c lib/strutils.c lib/fileutils.c lib/nsutils.c lib/signals.c dist_man_MANS += \ skill.1 \ snice.1 @@ -121,8 +122,8 @@ else endif free_SOURCES = free.c lib/strutils.c lib/fileutils.c -pgrep_SOURCES = pgrep.c lib/fileutils.c lib/nsutils.c -pkill_SOURCES = pgrep.c lib/fileutils.c lib/nsutils.c +pgrep_SOURCES = pgrep.c lib/fileutils.c lib/nsutils.c lib/signals.c +pkill_SOURCES = pgrep.c lib/fileutils.c lib/nsutils.c lib/signals.c pmap_SOURCES = pmap.c lib/fileutils.c pwdx_SOURCES = pwdx.c lib/fileutils.c pwdx_LDADD= @@ -167,8 +168,6 @@ proc_libprocps_la_SOURCES = \ proc/readproc.h \ proc/readstat.c \ proc/readstat.h \ - proc/sig.c \ - proc/sig.h \ proc/slab.c \ proc/slab.h \ proc/sysinfo.c \ @@ -190,7 +189,6 @@ proc_libprocps_la_include_HEADERS = \ proc/procps.h \ proc/pwcache.h \ proc/readproc.h \ - proc/sig.h \ proc/slab.h \ proc/sysinfo.h \ proc/uptime.h \ @@ -221,7 +219,8 @@ ps_pscommand_SOURCES = \ ps/select.c \ ps/sortformat.c \ ps/stacktrace.c \ - lib/fileutils.c + lib/fileutils.c \ + lib/signals.c # lib/test_* binaries noinst_PROGRAMS = \ diff --git a/include/Makefile.am b/include/Makefile.am index fee45ca5..752557da 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -4,5 +4,6 @@ dist_noinst_HEADERS = \ nls.h \ nsutils.h \ rpmatch.h \ + signals.h \ strutils.h \ xalloc.h diff --git a/proc/sig.h b/include/signals.h similarity index 74% rename from proc/sig.h rename to include/signals.h index d8b1ab48..474685fa 100644 --- a/proc/sig.h +++ b/include/signals.h @@ -11,22 +11,18 @@ * GNU Library General Public License for more details. */ -#include - __BEGIN_DECLS +extern const int number_of_signals; + +extern const char *get_sigtable_name(int row); + +extern const int get_sigtable_num(int row); + /* return -1 on failure */ extern int signal_name_to_number(const char *__restrict name); extern const char *signal_number_to_name(int signo); -extern int print_given_signals(int argc, const char *__restrict const *__restrict argv, int max_line); - -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/lib/signals.c b/lib/signals.c new file mode 100644 index 00000000..6b468d22 --- /dev/null +++ b/lib/signals.c @@ -0,0 +1,200 @@ +/* + * signals.c - signal name, and number, conversions + * Copyright 1998-2003 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 "signals.h" +#include "c.h" + +/* Linux signals: + * + * SIGSYS is required by Unix98. + * SIGEMT is part of SysV, BSD, and ancient UNIX tradition. + * + * They are provided by these Linux ports: alpha, mips, sparc, and sparc64. + * You get SIGSTKFLT and SIGUNUSED instead on i386, m68k, ppc, and arm. + * (this is a Linux & libc bug -- both must be fixed) + * + * Total garbage: SIGIO SIGINFO SIGIOT SIGLOST SIGCLD + * (popular ones are handled as aliases) + * Nearly garbage: SIGSTKFLT SIGUNUSED (nothing else to fill slots) + */ + +/* Linux 2.3.29 replaces SIGUNUSED with the standard SIGSYS signal */ +#ifndef SIGSYS +# warning Standards require that define SIGSYS +# define SIGSYS SIGUNUSED +#endif + +/* If we see both, it is likely SIGSTKFLT (junk) was replaced. */ +#ifdef SIGEMT +# undef SIGSTKFLT +#endif + +#ifndef SIGRTMIN +# warning Standards require that define SIGRTMIN; assuming 32 +# define SIGRTMIN 32 +#endif + +/* It seems the SPARC libc does not know the kernel supports SIGPWR. */ +#ifndef SIGPWR +# warning Your header files lack SIGPWR. (assuming it is number 29) +# define SIGPWR 29 +#endif + +typedef struct mapstruct { + const char *name; + int num; +} mapstruct; + + +static const mapstruct sigtable[] = { + {"ABRT", SIGABRT}, /* IOT */ + {"ALRM", SIGALRM}, + {"BUS", SIGBUS}, + {"CHLD", SIGCHLD}, /* CLD */ + {"CONT", SIGCONT}, +#ifdef SIGEMT + {"EMT", SIGEMT}, +#endif + {"FPE", SIGFPE}, + {"HUP", SIGHUP}, + {"ILL", SIGILL}, + {"INT", SIGINT}, + {"KILL", SIGKILL}, + {"PIPE", SIGPIPE}, + {"POLL", SIGPOLL}, /* IO */ + {"PROF", SIGPROF}, + {"PWR", SIGPWR}, + {"QUIT", SIGQUIT}, + {"SEGV", SIGSEGV}, +#ifdef SIGSTKFLT + {"STKFLT", SIGSTKFLT}, +#endif + {"STOP", SIGSTOP}, + {"SYS", SIGSYS}, /* UNUSED */ + {"TERM", SIGTERM}, + {"TRAP", SIGTRAP}, + {"TSTP", SIGTSTP}, + {"TTIN", SIGTTIN}, + {"TTOU", SIGTTOU}, + {"URG", SIGURG}, + {"USR1", SIGUSR1}, + {"USR2", SIGUSR2}, + {"VTALRM", SIGVTALRM}, + {"WINCH", SIGWINCH}, + {"XCPU", SIGXCPU}, + {"XFSZ", SIGXFSZ} +}; + +const int number_of_signals = sizeof(sigtable)/sizeof(mapstruct); + +static int compare_signal_names(const void *a, const void *b){ + return strcasecmp( ((const mapstruct*)a)->name, ((const mapstruct*)b)->name ); +} + + +const char *get_sigtable_name(int row) +{ + if (row < 0 || row >= number_of_signals) + return NULL; + return sigtable[row].name; +} + +const int get_sigtable_num(int row) +{ + if (row < 0 || row >= number_of_signals) + return -1; + return sigtable[row].num; +} + +/* return -1 on failure */ +int signal_name_to_number(const char *restrict name){ + long val; + int offset; + + /* clean up name */ + if(!strncasecmp(name,"SIG",3)) + name += 3; + + if(!strcasecmp(name,"CLD")) + return SIGCHLD; + if(!strcasecmp(name,"IO")) + return SIGPOLL; + if(!strcasecmp(name,"IOT")) + return SIGABRT; + /* search the table */ + { + const mapstruct ms = {name,0}; + const mapstruct *restrict const ptr = bsearch( + &ms, + sigtable, + number_of_signals, + sizeof(mapstruct), + compare_signal_names); + if(ptr) + return ptr->num; + } + + if(!strcasecmp(name,"RTMIN")) + return SIGRTMIN; + if(!strcasecmp(name,"EXIT")) + return 0; + if(!strcasecmp(name,"NULL")) + return 0; + + offset = 0; + if(!strncasecmp(name,"RTMIN+",6)) { + name += 6; + offset = SIGRTMIN; + } + + /* not found, so try as a number */ + { + char *endp; + val = strtol(name,&endp,10); + if(*endp || endp==name) + return -1; /* not valid */ + } + if(val+SIGRTMIN>127) + return -1; /* not valid */ + return val+offset; +} + +const char *signal_number_to_name(int signo) +{ + static char buf[32]; + int n = number_of_signals; + signo &= 0x7f; /* need to process exit values too */ + while (n--) { + if(sigtable[n].num==signo) + return sigtable[n].name; + } + if (signo == SIGRTMIN) + return "RTMIN"; + if (signo) + sprintf(buf, "RTMIN+%d", signo-SIGRTMIN); + else + strcpy(buf,"0"); /* AIX has NULL; Solaris has EXIT */ + return buf; +} + diff --git a/pgrep.c b/pgrep.c index 9a61e6d5..8dec30bf 100644 --- a/pgrep.c +++ b/pgrep.c @@ -48,17 +48,17 @@ #include "fileutils.h" #include "nsutils.h" #include "nls.h" +#include "signals.h" #include "xalloc.h" #include "proc/readproc.h" -#include "proc/sig.h" #include "proc/devname.h" #include "proc/sysinfo.h" static int i_am_pkill = 0; struct el { - long num; - char * str; + long num; + char * str; }; /* User supplied arguments */ @@ -96,114 +96,114 @@ static int ns_flags = 0x3f; static int __attribute__ ((__noreturn__)) usage(int opt) { - int err = (opt == '?'); - FILE *fp = err ? stderr : stdout; + int err = (opt == '?'); + FILE *fp = err ? stderr : stdout; - fputs(USAGE_HEADER, fp); - fprintf(fp, _(" %s [options] \n"), program_invocation_short_name); - fputs(USAGE_OPTIONS, fp); - if (i_am_pkill == 0) { - fputs(_(" -d, --delimiter specify output delimiter\n"),fp); - fputs(_(" -l, --list-name list PID and process name\n"),fp); - fputs(_(" -a, --list-full list PID and full command line\n"),fp); - fputs(_(" -v, --inverse negates the matching\n"),fp); - fputs(_(" -w, --lightweight list all TID\n"), fp); - } - if (i_am_pkill == 1) { - fputs(_(" -, --signal signal to send (either number or name)\n"), fp); - fputs(_(" -e, --echo display what is killed\n"), fp); - } - fputs(_(" -c, --count count of matching processes\n"), fp); - fputs(_(" -f, --full use full process name to match\n"), fp); - fputs(_(" -g, --pgroup match listed process group IDs\n"), fp); - fputs(_(" -G, --group match real group IDs\n"), fp); - fputs(_(" -i, --ignore-case match case insensitively\n"), fp); - fputs(_(" -n, --newest select most recently started\n"), fp); - fputs(_(" -o, --oldest select least recently started\n"), fp); - fputs(_(" -P, --parent match only child processes of the given parent\n"), fp); - fputs(_(" -s, --session match session IDs\n"), fp); - fputs(_(" -t, --terminal match by controlling terminal\n"), fp); - fputs(_(" -u, --euid match by effective IDs\n"), fp); - fputs(_(" -U, --uid match by real IDs\n"), fp); - fputs(_(" -x, --exact match exactly with the command name\n"), fp); - fputs(_(" -F, --pidfile read PIDs from file\n"), fp); - fputs(_(" -L, --logpidfile fail if PID file is not locked\n"), fp); - fputs(_(" --ns match the processes that belong to the same\n" - " namespace as \n"), fp); - fputs(_(" --nslist list which namespaces will be considered for\n" - " the --ns option.\n" - " Available namespaces: ipc, mnt, net, pid, user, uts\n"), fp); - fputs(USAGE_SEPARATOR, fp); - fputs(USAGE_HELP, fp); - fputs(USAGE_VERSION, fp); - fprintf(fp, USAGE_MAN_TAIL("pgrep(1)")); + fputs(USAGE_HEADER, fp); + fprintf(fp, _(" %s [options] \n"), program_invocation_short_name); + fputs(USAGE_OPTIONS, fp); + if (i_am_pkill == 0) { + fputs(_(" -d, --delimiter specify output delimiter\n"),fp); + fputs(_(" -l, --list-name list PID and process name\n"),fp); + fputs(_(" -a, --list-full list PID and full command line\n"),fp); + fputs(_(" -v, --inverse negates the matching\n"),fp); + fputs(_(" -w, --lightweight list all TID\n"), fp); + } + if (i_am_pkill == 1) { + fputs(_(" -, --signal signal to send (either number or name)\n"), fp); + fputs(_(" -e, --echo display what is killed\n"), fp); + } + fputs(_(" -c, --count count of matching processes\n"), fp); + fputs(_(" -f, --full use full process name to match\n"), fp); + fputs(_(" -g, --pgroup match listed process group IDs\n"), fp); + fputs(_(" -G, --group match real group IDs\n"), fp); + fputs(_(" -i, --ignore-case match case insensitively\n"), fp); + fputs(_(" -n, --newest select most recently started\n"), fp); + fputs(_(" -o, --oldest select least recently started\n"), fp); + fputs(_(" -P, --parent match only child processes of the given parent\n"), fp); + fputs(_(" -s, --session match session IDs\n"), fp); + fputs(_(" -t, --terminal match by controlling terminal\n"), fp); + fputs(_(" -u, --euid match by effective IDs\n"), fp); + fputs(_(" -U, --uid match by real IDs\n"), fp); + fputs(_(" -x, --exact match exactly with the command name\n"), fp); + fputs(_(" -F, --pidfile read PIDs from file\n"), fp); + fputs(_(" -L, --logpidfile fail if PID file is not locked\n"), fp); + fputs(_(" --ns match the processes that belong to the same\n" + " namespace as \n"), fp); + fputs(_(" --nslist list which namespaces will be considered for\n" + " the --ns option.\n" + " Available namespaces: ipc, mnt, net, pid, user, uts\n"), fp); + fputs(USAGE_SEPARATOR, fp); + fputs(USAGE_HELP, fp); + fputs(USAGE_VERSION, fp); + fprintf(fp, USAGE_MAN_TAIL("pgrep(1)")); - exit(fp == stderr ? EXIT_USAGE : EXIT_SUCCESS); + exit(fp == stderr ? EXIT_USAGE : EXIT_SUCCESS); } static struct el *split_list (const char *restrict str, int (*convert)(const char *, struct el *)) { - char *copy; - char *ptr; - char *sep_pos; - int i = 0; - int size = 0; - struct el *list = NULL; + char *copy; + char *ptr; + char *sep_pos; + int i = 0; + int size = 0; + struct el *list = NULL; - if (str[0] == '\0') - return NULL; + if (str[0] == '\0') + return NULL; - copy = xstrdup (str); - ptr = copy; + copy = xstrdup (str); + ptr = copy; - do { - if (i == size) { - size = size * 5 / 4 + 4; - /* add 1 because slot zero is a count */ - list = xrealloc (list, (1 + size) * sizeof *list); - } - sep_pos = strchr (ptr, ','); - if (sep_pos) - *sep_pos = 0; - /* Use ++i instead of i++ because slot zero is a count */ - if (list && !convert (ptr, &list[++i])) - exit (EXIT_USAGE); - if (sep_pos) - ptr = sep_pos + 1; - } while (sep_pos); + do { + if (i == size) { + size = size * 5 / 4 + 4; + /* add 1 because slot zero is a count */ + list = xrealloc (list, (1 + size) * sizeof *list); + } + sep_pos = strchr (ptr, ','); + if (sep_pos) + *sep_pos = 0; + /* Use ++i instead of i++ because slot zero is a count */ + if (list && !convert (ptr, &list[++i])) + exit (EXIT_USAGE); + if (sep_pos) + ptr = sep_pos + 1; + } while (sep_pos); - free (copy); - if (!i) { - free (list); - list = NULL; - } else { - list[0].num = i; - } - return list; + free (copy); + if (!i) { + free (list); + list = NULL; + } else { + list[0].num = i; + } + return list; } /* strict_atol returns a Boolean: TRUE if the input string * contains a plain number, FALSE if there are any non-digits. */ static int strict_atol (const char *restrict str, long *restrict value) { - int res = 0; - int sign = 1; + int res = 0; + int sign = 1; - if (*str == '+') - ++str; - else if (*str == '-') { - ++str; - sign = -1; - } + if (*str == '+') + ++str; + else if (*str == '-') { + ++str; + sign = -1; + } - for ( ; *str; ++str) { - if (! isdigit (*str)) - return (0); - res *= 10; - res += *str - '0'; - } - *value = sign * res; - return 1; + for ( ; *str; ++str) { + if (! isdigit (*str)) + return (0); + res *= 10; + res += *str - '0'; + } + *value = sign * res; + return 1; } #include @@ -212,734 +212,734 @@ static int strict_atol (const char *restrict str, long *restrict value) * Seen using flock: FreeBSD code */ static int has_flock(int fd) { - return flock(fd, LOCK_SH|LOCK_NB)==-1 && errno==EWOULDBLOCK; + return flock(fd, LOCK_SH|LOCK_NB)==-1 && errno==EWOULDBLOCK; } /* We try a read lock. The daemon should have a write lock. * Seen using fcntl: libslack */ static int has_fcntl(int fd) { - struct flock f; /* seriously, struct flock is for a fnctl lock! */ - f.l_type = F_RDLCK; - f.l_whence = SEEK_SET; - f.l_start = 0; - f.l_len = 0; - return fcntl(fd,F_SETLK,&f)==-1 && (errno==EACCES || errno==EAGAIN); + struct flock f; /* seriously, struct flock is for a fnctl lock! */ + f.l_type = F_RDLCK; + f.l_whence = SEEK_SET; + f.l_start = 0; + f.l_len = 0; + return fcntl(fd,F_SETLK,&f)==-1 && (errno==EACCES || errno==EAGAIN); } static struct el *read_pidfile(void) { - char buf[12]; - int fd; - struct stat sbuf; - char *endp; - int n, pid; - struct el *list = NULL; + char buf[12]; + int fd; + struct stat sbuf; + char *endp; + int n, pid; + struct el *list = NULL; - fd = open(opt_pidfile, O_RDONLY|O_NOCTTY|O_NONBLOCK); - if(fd<0) - goto just_ret; - if(fstat(fd,&sbuf) || !S_ISREG(sbuf.st_mode) || sbuf.st_size<1) - goto out; - /* type of lock, if any, is not standardized on Linux */ - if(opt_lock && !has_flock(fd) && !has_fcntl(fd)) - goto out; - memset(buf,'\0',sizeof buf); - n = read(fd,buf+1,sizeof buf-2); - if (n<1) - goto out; - pid = strtoul(buf+1,&endp,10); - if(endp<=buf+1 || pid<1 || pid>0x7fffffff) - goto out; - if(*endp && !isspace(*endp)) - goto out; - list = xmalloc(2 * sizeof *list); - list[0].num = 1; - list[1].num = pid; + fd = open(opt_pidfile, O_RDONLY|O_NOCTTY|O_NONBLOCK); + if(fd<0) + goto just_ret; + if(fstat(fd,&sbuf) || !S_ISREG(sbuf.st_mode) || sbuf.st_size<1) + goto out; + /* type of lock, if any, is not standardized on Linux */ + if(opt_lock && !has_flock(fd) && !has_fcntl(fd)) + goto out; + memset(buf,'\0',sizeof buf); + n = read(fd,buf+1,sizeof buf-2); + if (n<1) + goto out; + pid = strtoul(buf+1,&endp,10); + if(endp<=buf+1 || pid<1 || pid>0x7fffffff) + goto out; + if(*endp && !isspace(*endp)) + goto out; + list = xmalloc(2 * sizeof *list); + list[0].num = 1; + list[1].num = pid; out: - close(fd); + close(fd); just_ret: - return list; + return list; } static int conv_uid (const char *restrict name, struct el *restrict e) { - struct passwd *pwd; + struct passwd *pwd; - if (strict_atol (name, &e->num)) - return (1); + if (strict_atol (name, &e->num)) + return (1); - pwd = getpwnam (name); - if (pwd == NULL) { - xwarnx(_("invalid user name: %s"), name); - return 0; - } - e->num = pwd->pw_uid; - return 1; + pwd = getpwnam (name); + if (pwd == NULL) { + xwarnx(_("invalid user name: %s"), name); + return 0; + } + e->num = pwd->pw_uid; + return 1; } static int conv_gid (const char *restrict name, struct el *restrict e) { - struct group *grp; + struct group *grp; - if (strict_atol (name, &e->num)) - return 1; + if (strict_atol (name, &e->num)) + return 1; - grp = getgrnam (name); - if (grp == NULL) { - xwarnx(_("invalid group name: %s"), name); - return 0; - } - e->num = grp->gr_gid; - return 1; + grp = getgrnam (name); + if (grp == NULL) { + xwarnx(_("invalid group name: %s"), name); + return 0; + } + e->num = grp->gr_gid; + return 1; } static int conv_pgrp (const char *restrict name, struct el *restrict e) { - if (! strict_atol (name, &e->num)) { - xwarnx(_("invalid process group: %s"), name); - return 0; - } - if (e->num == 0) - e->num = getpgrp (); - return 1; + if (! strict_atol (name, &e->num)) { + xwarnx(_("invalid process group: %s"), name); + return 0; + } + if (e->num == 0) + e->num = getpgrp (); + return 1; } static int conv_sid (const char *restrict name, struct el *restrict e) { - if (! strict_atol (name, &e->num)) { - xwarnx(_("invalid session id: %s"), name); - return 0; - } - if (e->num == 0) - e->num = getsid (0); - return 1; + if (! strict_atol (name, &e->num)) { + xwarnx(_("invalid session id: %s"), name); + return 0; + } + if (e->num == 0) + e->num = getsid (0); + return 1; } static int conv_num (const char *restrict name, struct el *restrict e) { - if (! strict_atol (name, &e->num)) { - xwarnx(_("not a number: %s"), name); - return 0; - } - return 1; + if (! strict_atol (name, &e->num)) { + xwarnx(_("not a number: %s"), name); + return 0; + } + return 1; } static int conv_str (const char *restrict name, struct el *restrict e) { - e->str = xstrdup (name); - return 1; + e->str = xstrdup (name); + return 1; } static int conv_ns (const char *restrict name, struct el *restrict e) { - int rc = conv_str(name, e); - int id; + int rc = conv_str(name, e); + int id; - ns_flags = 0; - id = get_ns_id(name); - if (id == -1) - return 0; - ns_flags |= (1 << id); + ns_flags = 0; + id = get_ns_id(name); + if (id == -1) + return 0; + ns_flags |= (1 << id); - return rc; + return rc; } static int match_numlist (long value, const struct el *restrict list) { - int found = 0; - if (list == NULL) - found = 0; - else { - int i; - for (i = list[0].num; i > 0; i--) { - if (list[i].num == value) - found = 1; - } - } - return found; + int found = 0; + if (list == NULL) + found = 0; + else { + int i; + for (i = list[0].num; i > 0; i--) { + if (list[i].num == value) + found = 1; + } + } + return found; } static int match_strlist (const char *restrict value, const struct el *restrict list) { - int found = 0; - if (list == NULL) - found = 0; - else { - int i; - for (i = list[0].num; i > 0; i--) { - if (! strcmp (list[i].str, value)) - found = 1; - } - } - return found; + int found = 0; + if (list == NULL) + found = 0; + else { + int i; + for (i = list[0].num; i > 0; i--) { + if (! strcmp (list[i].str, value)) + found = 1; + } + } + return found; } static int match_ns (const proc_t *task, const proc_t *ns_task) { - int found = 1; - int i; + int found = 1; + int i; - for (i = 0; i < NUM_NS; i++) { - if (ns_flags & (1 << i)) { - if (task->ns[i] != ns_task->ns[i]) - found = 0; - } - } + for (i = 0; i < NUM_NS; i++) { + if (ns_flags & (1 << i)) { + if (task->ns[i] != ns_task->ns[i]) + found = 0; + } + } - return found; + return found; } static void output_numlist (const struct el *restrict list, int num) { - int i; - const char *delim = opt_delim; - for (i = 0; i < num; i++) { - if(i+1==num) - delim = "\n"; - printf ("%ld%s", list[i].num, delim); - } + int i; + const char *delim = opt_delim; + for (i = 0; i < num; i++) { + if(i+1==num) + delim = "\n"; + printf ("%ld%s", list[i].num, delim); + } } static void output_strlist (const struct el *restrict list, int num) { /* FIXME: escape codes */ - int i; - const char *delim = opt_delim; - for (i = 0; i < num; i++) { - if(i+1==num) - delim = "\n"; - printf ("%lu %s%s", list[i].num, list[i].str, delim); - } + int i; + const char *delim = opt_delim; + for (i = 0; i < num; i++) { + if(i+1==num) + delim = "\n"; + printf ("%lu %s%s", list[i].num, list[i].str, delim); + } } static PROCTAB *do_openproc (void) { - PROCTAB *ptp; - int flags = 0; + PROCTAB *ptp; + int flags = 0; - if (opt_pattern || opt_full || opt_longlong) - flags |= PROC_FILLCOM; - if (opt_ruid || opt_rgid) - flags |= PROC_FILLSTATUS; - if (opt_oldest || opt_newest || opt_pgrp || opt_sid || opt_term) - flags |= PROC_FILLSTAT; - if (!(flags & PROC_FILLSTAT)) - flags |= PROC_FILLSTATUS; /* FIXME: need one, and PROC_FILLANY broken */ - if (opt_ns_pid) - flags |= PROC_FILLNS; - if (opt_euid && !opt_negate) { - int num = opt_euid[0].num; - int i = num; - uid_t *uids = xmalloc (num * sizeof (uid_t)); - while (i-- > 0) { - uids[i] = opt_euid[i+1].num; - } - flags |= PROC_UID; - ptp = openproc (flags, uids, num); - } else { - ptp = openproc (flags); - } - return ptp; + if (opt_pattern || opt_full || opt_longlong) + flags |= PROC_FILLCOM; + if (opt_ruid || opt_rgid) + flags |= PROC_FILLSTATUS; + if (opt_oldest || opt_newest || opt_pgrp || opt_sid || opt_term) + flags |= PROC_FILLSTAT; + if (!(flags & PROC_FILLSTAT)) + flags |= PROC_FILLSTATUS; /* FIXME: need one, and PROC_FILLANY broken */ + if (opt_ns_pid) + flags |= PROC_FILLNS; + if (opt_euid && !opt_negate) { + int num = opt_euid[0].num; + int i = num; + uid_t *uids = xmalloc (num * sizeof (uid_t)); + while (i-- > 0) { + uids[i] = opt_euid[i+1].num; + } + flags |= PROC_UID; + ptp = openproc (flags, uids, num); + } else { + ptp = openproc (flags); + } + return ptp; } static regex_t * do_regcomp (void) { - regex_t *preg = NULL; + regex_t *preg = NULL; - if (opt_pattern) { - char *re; - char errbuf[256]; - int re_err; + if (opt_pattern) { + char *re; + char errbuf[256]; + int re_err; - preg = xmalloc (sizeof (regex_t)); - if (opt_exact) { - re = xmalloc (strlen (opt_pattern) + 5); - sprintf (re, "^(%s)$", opt_pattern); - } else { - re = opt_pattern; - } + preg = xmalloc (sizeof (regex_t)); + if (opt_exact) { + re = xmalloc (strlen (opt_pattern) + 5); + sprintf (re, "^(%s)$", opt_pattern); + } else { + re = opt_pattern; + } - re_err = regcomp (preg, re, REG_EXTENDED | REG_NOSUB | opt_case); + re_err = regcomp (preg, re, REG_EXTENDED | REG_NOSUB | opt_case); - if (opt_exact) free(re); + if (opt_exact) free(re); - if (re_err) { - regerror (re_err, preg, errbuf, sizeof(errbuf)); - fputs(errbuf,stderr); - exit (EXIT_USAGE); - } - } - return preg; + if (re_err) { + regerror (re_err, preg, errbuf, sizeof(errbuf)); + fputs(errbuf,stderr); + exit (EXIT_USAGE); + } + } + return preg; } static struct el * select_procs (int *num) { - PROCTAB *ptp; - proc_t task; - unsigned long long saved_start_time; /* for new/old support */ - pid_t saved_pid = 0; /* for new/old support */ - int matches = 0; - int size = 0; - regex_t *preg; - pid_t myself = getpid(); - struct el *list = NULL; - char cmdline[CMDSTRSIZE]; - char cmdsearch[CMDSTRSIZE]; - char cmdoutput[CMDSTRSIZE]; - proc_t ns_task; + PROCTAB *ptp; + proc_t task; + unsigned long long saved_start_time; /* for new/old support */ + pid_t saved_pid = 0; /* for new/old support */ + int matches = 0; + int size = 0; + regex_t *preg; + pid_t myself = getpid(); + struct el *list = NULL; + char cmdline[CMDSTRSIZE]; + char cmdsearch[CMDSTRSIZE]; + char cmdoutput[CMDSTRSIZE]; + proc_t ns_task; - ptp = do_openproc(); - preg = do_regcomp(); + ptp = do_openproc(); + preg = do_regcomp(); - if (opt_newest) saved_start_time = 0ULL; - else saved_start_time = ~0ULL; + if (opt_newest) saved_start_time = 0ULL; + else saved_start_time = ~0ULL; - if (opt_newest) saved_pid = 0; - if (opt_oldest) saved_pid = INT_MAX; - if (opt_ns_pid && ns_read(opt_ns_pid, &ns_task)) { - fputs(_("Error reading reference namespace information\n"), - stderr); - exit (EXIT_FATAL); - } + if (opt_newest) saved_pid = 0; + if (opt_oldest) saved_pid = INT_MAX; + if (opt_ns_pid && ns_read(opt_ns_pid, &ns_task)) { + fputs(_("Error reading reference namespace information\n"), + stderr); + exit (EXIT_FATAL); + } - memset(&task, 0, sizeof (task)); - while(readproc(ptp, &task)) { - int match = 1; + memset(&task, 0, sizeof (task)); + while(readproc(ptp, &task)) { + int match = 1; - if (task.XXXID == myself) - continue; - else if (opt_newest && task.start_time < saved_start_time) - match = 0; - else if (opt_oldest && task.start_time > saved_start_time) - match = 0; - else if (opt_ppid && ! match_numlist (task.ppid, opt_ppid)) - match = 0; - else if (opt_pid && ! match_numlist (task.tgid, opt_pid)) - match = 0; - else if (opt_pgrp && ! match_numlist (task.pgrp, opt_pgrp)) - match = 0; - else if (opt_euid && ! match_numlist (task.euid, opt_euid)) - match = 0; - else if (opt_ruid && ! match_numlist (task.ruid, opt_ruid)) - match = 0; - else if (opt_rgid && ! match_numlist (task.rgid, opt_rgid)) - match = 0; - else if (opt_sid && ! match_numlist (task.session, opt_sid)) - match = 0; - else if (opt_ns_pid && ! match_ns (&task, &ns_task)) - match = 0; - else if (opt_term) { - if (task.tty == 0) { - match = 0; - } else { - char tty[256]; - dev_to_tty (tty, sizeof(tty) - 1, - task.tty, task.XXXID, ABBREV_DEV); - match = match_strlist (tty, opt_term); - } - } - if (task.cmdline && (opt_longlong || opt_full) ) { - int i = 0; - int bytes = sizeof (cmdline) - 1; + if (task.XXXID == myself) + continue; + else if (opt_newest && task.start_time < saved_start_time) + match = 0; + else if (opt_oldest && task.start_time > saved_start_time) + match = 0; + else if (opt_ppid && ! match_numlist (task.ppid, opt_ppid)) + match = 0; + else if (opt_pid && ! match_numlist (task.tgid, opt_pid)) + match = 0; + else if (opt_pgrp && ! match_numlist (task.pgrp, opt_pgrp)) + match = 0; + else if (opt_euid && ! match_numlist (task.euid, opt_euid)) + match = 0; + else if (opt_ruid && ! match_numlist (task.ruid, opt_ruid)) + match = 0; + else if (opt_rgid && ! match_numlist (task.rgid, opt_rgid)) + match = 0; + else if (opt_sid && ! match_numlist (task.session, opt_sid)) + match = 0; + else if (opt_ns_pid && ! match_ns (&task, &ns_task)) + match = 0; + else if (opt_term) { + if (task.tty == 0) { + match = 0; + } else { + char tty[256]; + dev_to_tty (tty, sizeof(tty) - 1, + task.tty, task.XXXID, ABBREV_DEV); + match = match_strlist (tty, opt_term); + } + } + if (task.cmdline && (opt_longlong || opt_full) ) { + int i = 0; + int bytes = sizeof (cmdline) - 1; - /* make sure it is always NUL-terminated */ - cmdline[bytes] = 0; - /* make room for SPC in loop below */ - --bytes; + /* make sure it is always NUL-terminated */ + cmdline[bytes] = 0; + /* make room for SPC in loop below */ + --bytes; - strncpy (cmdline, task.cmdline[i], bytes); - bytes -= strlen (task.cmdline[i++]); - while (task.cmdline[i] && bytes > 0) { - strncat (cmdline, " ", bytes); - strncat (cmdline, task.cmdline[i], bytes); - bytes -= strlen (task.cmdline[i++]) + 1; - } - } + strncpy (cmdline, task.cmdline[i], bytes); + bytes -= strlen (task.cmdline[i++]); + while (task.cmdline[i] && bytes > 0) { + strncat (cmdline, " ", bytes); + strncat (cmdline, task.cmdline[i], bytes); + bytes -= strlen (task.cmdline[i++]) + 1; + } + } - if (opt_long || opt_longlong || (match && opt_pattern)) { - if (opt_longlong && task.cmdline) - strncpy (cmdoutput, cmdline, CMDSTRSIZE); - else - strncpy (cmdoutput, task.cmd, CMDSTRSIZE); - } + if (opt_long || opt_longlong || (match && opt_pattern)) { + if (opt_longlong && task.cmdline) + strncpy (cmdoutput, cmdline, CMDSTRSIZE); + else + strncpy (cmdoutput, task.cmd, CMDSTRSIZE); + } - if (match && opt_pattern) { - if (opt_full && task.cmdline) - strncpy (cmdsearch, cmdline, CMDSTRSIZE); - else - strncpy (cmdsearch, task.cmd, CMDSTRSIZE); + if (match && opt_pattern) { + if (opt_full && task.cmdline) + strncpy (cmdsearch, cmdline, CMDSTRSIZE); + else + strncpy (cmdsearch, task.cmd, CMDSTRSIZE); - if (regexec (preg, cmdsearch, 0, NULL, 0) != 0) - match = 0; - } + if (regexec (preg, cmdsearch, 0, NULL, 0) != 0) + match = 0; + } - if (match ^ opt_negate) { /* Exclusive OR is neat */ - if (opt_newest) { - if (saved_start_time == task.start_time && - saved_pid > task.XXXID) - continue; - saved_start_time = task.start_time; - saved_pid = task.XXXID; - matches = 0; - } - if (opt_oldest) { - if (saved_start_time == task.start_time && - saved_pid < task.XXXID) - continue; - saved_start_time = task.start_time; - saved_pid = task.XXXID; - matches = 0; - } - if (matches == size) { - size = size * 5 / 4 + 4; - list = xrealloc(list, size * sizeof *list); - } - if (list && (opt_long || opt_longlong || opt_echo)) { - list[matches].num = task.XXXID; - list[matches++].str = xstrdup (cmdoutput); - } else if (list) { - list[matches++].num = task.XXXID; - } else { - xerrx(EXIT_FAILURE, _("internal error")); - } + if (match ^ opt_negate) { /* Exclusive OR is neat */ + if (opt_newest) { + if (saved_start_time == task.start_time && + saved_pid > task.XXXID) + continue; + saved_start_time = task.start_time; + saved_pid = task.XXXID; + matches = 0; + } + if (opt_oldest) { + if (saved_start_time == task.start_time && + saved_pid < task.XXXID) + continue; + saved_start_time = task.start_time; + saved_pid = task.XXXID; + matches = 0; + } + if (matches == size) { + size = size * 5 / 4 + 4; + list = xrealloc(list, size * sizeof *list); + } + if (list && (opt_long || opt_longlong || opt_echo)) { + list[matches].num = task.XXXID; + list[matches++].str = xstrdup (cmdoutput); + } else if (list) { + list[matches++].num = task.XXXID; + } else { + xerrx(EXIT_FAILURE, _("internal error")); + } - // pkill does not need subtasks! - // this control is still done at - // argparse time, but a further - // control is free - if (opt_threads && !i_am_pkill) { - proc_t subtask; - memset(&subtask, 0, sizeof (subtask)); - while (readtask(ptp, &task, &subtask)){ - // don't add redundand tasks - if (task.XXXID == subtask.XXXID) - continue; + // pkill does not need subtasks! + // this control is still done at + // argparse time, but a further + // control is free + if (opt_threads && !i_am_pkill) { + proc_t subtask; + memset(&subtask, 0, sizeof (subtask)); + while (readtask(ptp, &task, &subtask)){ + // don't add redundand tasks + if (task.XXXID == subtask.XXXID) + continue; - // eventually grow output buffer - if (matches == size) { - size = size * 5 / 4 + 4; - list = realloc(list, size * sizeof *list); - if (list == NULL) - exit (EXIT_FATAL); - } - if (opt_long || opt_longlong) { - list[matches].str = xstrdup (cmdoutput); - list[matches++].num = subtask.XXXID; - } else { - list[matches++].num = subtask.XXXID; - } - memset(&subtask, 0, sizeof (subtask)); - } - } + // eventually grow output buffer + if (matches == size) { + size = size * 5 / 4 + 4; + list = realloc(list, size * sizeof *list); + if (list == NULL) + exit (EXIT_FATAL); + } + if (opt_long || opt_longlong) { + list[matches].str = xstrdup (cmdoutput); + list[matches++].num = subtask.XXXID; + } else { + list[matches++].num = subtask.XXXID; + } + memset(&subtask, 0, sizeof (subtask)); + } + } - } + } - memset (&task, 0, sizeof (task)); - } - closeproc (ptp); - *num = matches; - return list; + memset (&task, 0, sizeof (task)); + } + closeproc (ptp); + *num = matches; + return list; } static int signal_option(int *argc, char **argv) { - int sig; - int i; - for (i = 1; i < *argc; i++) { - if (argv[i][0] == '-') { - sig = signal_name_to_number(argv[i] + 1); - if (sig == -1 && isdigit(argv[i][1])) - sig = atoi(argv[i] + 1); - if (-1 < sig) { - memmove(argv + i, argv + i + 1, - sizeof(char *) * (*argc - i)); - (*argc)--; - return sig; - } - } - } - return -1; + int sig; + int i; + for (i = 1; i < *argc; i++) { + if (argv[i][0] == '-') { + sig = signal_name_to_number(argv[i] + 1); + if (sig == -1 && isdigit(argv[i][1])) + sig = atoi(argv[i] + 1); + if (-1 < sig) { + memmove(argv + i, argv + i + 1, + sizeof(char *) * (*argc - i)); + (*argc)--; + return sig; + } + } + } + return -1; } static void parse_opts (int argc, char **argv) { - char opts[64] = ""; - int opt; - int criteria_count = 0; + char opts[64] = ""; + int opt; + int criteria_count = 0; - enum { - SIGNAL_OPTION = CHAR_MAX + 1, - NS_OPTION, - NSLIST_OPTION, - }; - static const struct option longopts[] = { - {"signal", required_argument, NULL, SIGNAL_OPTION}, - {"count", no_argument, NULL, 'c'}, - {"delimiter", required_argument, NULL, 'd'}, - {"list-name", no_argument, NULL, 'l'}, - {"list-full", no_argument, NULL, 'a'}, - {"full", no_argument, NULL, 'f'}, - {"pgroup", required_argument, NULL, 'g'}, - {"group", required_argument, NULL, 'G'}, - {"ignore-case", no_argument, NULL, 'i'}, - {"newest", no_argument, NULL, 'n'}, - {"oldest", no_argument, NULL, 'o'}, - {"parent", required_argument, NULL, 'P'}, - {"session", required_argument, NULL, 's'}, - {"terminal", required_argument, NULL, 't'}, - {"euid", required_argument, NULL, 'u'}, - {"uid", required_argument, NULL, 'U'}, - {"inverse", no_argument, NULL, 'v'}, - {"lightweight", no_argument, NULL, 'w'}, - {"exact", no_argument, NULL, 'x'}, - {"pidfile", required_argument, NULL, 'F'}, - {"logpidfile", no_argument, NULL, 'L'}, - {"echo", no_argument, NULL, 'e'}, - {"ns", required_argument, NULL, NS_OPTION}, - {"nslist", required_argument, NULL, NSLIST_OPTION}, - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {NULL, 0, NULL, 0} - }; + enum { + SIGNAL_OPTION = CHAR_MAX + 1, + NS_OPTION, + NSLIST_OPTION, + }; + static const struct option longopts[] = { + {"signal", required_argument, NULL, SIGNAL_OPTION}, + {"count", no_argument, NULL, 'c'}, + {"delimiter", required_argument, NULL, 'd'}, + {"list-name", no_argument, NULL, 'l'}, + {"list-full", no_argument, NULL, 'a'}, + {"full", no_argument, NULL, 'f'}, + {"pgroup", required_argument, NULL, 'g'}, + {"group", required_argument, NULL, 'G'}, + {"ignore-case", no_argument, NULL, 'i'}, + {"newest", no_argument, NULL, 'n'}, + {"oldest", no_argument, NULL, 'o'}, + {"parent", required_argument, NULL, 'P'}, + {"session", required_argument, NULL, 's'}, + {"terminal", required_argument, NULL, 't'}, + {"euid", required_argument, NULL, 'u'}, + {"uid", required_argument, NULL, 'U'}, + {"inverse", no_argument, NULL, 'v'}, + {"lightweight", no_argument, NULL, 'w'}, + {"exact", no_argument, NULL, 'x'}, + {"pidfile", required_argument, NULL, 'F'}, + {"logpidfile", no_argument, NULL, 'L'}, + {"echo", no_argument, NULL, 'e'}, + {"ns", required_argument, NULL, NS_OPTION}, + {"nslist", required_argument, NULL, NSLIST_OPTION}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} + }; - if (strstr (program_invocation_short_name, "pkill")) { - int sig; - i_am_pkill = 1; - sig = signal_option(&argc, argv); - if (-1 < sig) - opt_signal = sig; - /* These options are for pkill only */ - strcat (opts, "e"); - } else { - /* These options are for pgrep only */ - strcat (opts, "lad:vw"); - } + if (strstr (program_invocation_short_name, "pkill")) { + int sig; + i_am_pkill = 1; + sig = signal_option(&argc, argv); + if (-1 < sig) + opt_signal = sig; + /* These options are for pkill only */ + strcat (opts, "e"); + } else { + /* These options are for pgrep only */ + strcat (opts, "lad:vw"); + } - strcat (opts, "LF:cfinoxP:g:s:u:U:G:t:?Vh"); + strcat (opts, "LF:cfinoxP:g:s:u:U:G:t:?Vh"); - while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != -1) { - switch (opt) { - case SIGNAL_OPTION: - opt_signal = signal_name_to_number (optarg); - if (opt_signal == -1 && isdigit (optarg[0])) - opt_signal = atoi (optarg); - break; - case 'e': - opt_echo = 1; - break; -/* case 'D': / * FreeBSD: print info about non-matches for debugging * / - * break; */ - case 'F': /* FreeBSD: the arg is a file containing a PID to match */ - opt_pidfile = xstrdup (optarg); - ++criteria_count; - break; - case 'G': /* Solaris: match rgid/rgroup */ - opt_rgid = split_list (optarg, conv_gid); - if (opt_rgid == NULL) - usage ('?'); - ++criteria_count; - break; -/* case 'I': / * FreeBSD: require confirmation before killing * / - * break; */ -/* case 'J': / * Solaris: match by project ID (name or number) * / - * break; */ - case 'L': /* FreeBSD: fail if pidfile (see -F) not locked */ - opt_lock++; - break; -/* case 'M': / * FreeBSD: specify core (OS crash dump) file * / - * break; */ -/* case 'N': / * FreeBSD: specify alternate namelist file (for us, System.map -- but we don't need it) * / - * break; */ - case 'P': /* Solaris: match by PPID */ - opt_ppid = split_list (optarg, conv_num); - if (opt_ppid == NULL) - usage ('?'); - ++criteria_count; - break; -/* case 'S': / * FreeBSD: don't ignore the built-in kernel tasks * / - * break; */ -/* case 'T': / * Solaris: match by "task ID" (probably not a Linux task) * / - * break; */ - case 'U': /* Solaris: match by ruid/rgroup */ - opt_ruid = split_list (optarg, conv_uid); - if (opt_ruid == NULL) - usage ('?'); - ++criteria_count; - break; - case 'V': - printf(PROCPS_NG_VERSION); - exit(EXIT_SUCCESS); -/* case 'c': / * Solaris: match by contract ID * / - * break; */ - case 'c': - opt_count = 1; - break; - case 'd': /* Solaris: change the delimiter */ - opt_delim = xstrdup (optarg); - break; - case 'f': /* Solaris: match full process name (as in "ps -f") */ - opt_full = 1; - break; - case 'g': /* Solaris: match pgrp */ - opt_pgrp = split_list (optarg, conv_pgrp); - if (opt_pgrp == NULL) - usage ('?'); - ++criteria_count; - break; - case 'i': /* FreeBSD: ignore case. OpenBSD: withdrawn. See -I. This sucks. */ - if (opt_case) - usage (opt); - opt_case = REG_ICASE; - break; -/* case 'j': / * FreeBSD: restricted to the given jail ID * / - * break; */ - case 'l': /* Solaris: long output format (pgrep only) Should require -f for beyond argv[0] maybe? */ - opt_long = 1; - break; - case 'a': - opt_longlong = 1; - break; - case 'n': /* Solaris: match only the newest */ - if (opt_oldest|opt_negate|opt_newest) - usage ('?'); - opt_newest = 1; - ++criteria_count; - break; - case 'o': /* Solaris: match only the oldest */ - if (opt_oldest|opt_negate|opt_newest) - usage ('?'); - opt_oldest = 1; - ++criteria_count; - break; - case 's': /* Solaris: match by session ID -- zero means self */ - opt_sid = split_list (optarg, conv_sid); - if (opt_sid == NULL) - usage ('?'); - ++criteria_count; - break; - case 't': /* Solaris: match by tty */ - opt_term = split_list (optarg, conv_str); - if (opt_term == NULL) - usage ('?'); - ++criteria_count; - break; - case 'u': /* Solaris: match by euid/egroup */ - opt_euid = split_list (optarg, conv_uid); - if (opt_euid == NULL) - usage ('?'); - ++criteria_count; - break; - case 'v': /* Solaris: as in grep, invert the matching (uh... applied after selection I think) */ - if (opt_oldest|opt_negate|opt_newest) - usage ('?'); - opt_negate = 1; - break; - case 'w': // Linux: show threads (lightweight process) too - opt_threads = 1; - break; - /* OpenBSD -x, being broken, does a plain string */ - case 'x': /* Solaris: use ^(regexp)$ in place of regexp (FreeBSD too) */ - opt_exact = 1; - break; -/* case 'z': / * Solaris: match by zone ID * / - * break; */ - case NS_OPTION: - opt_ns_pid = atoi(optarg); - if (opt_ns_pid == 0) - usage ('?'); - ++criteria_count; - break; - case NSLIST_OPTION: - opt_nslist = split_list (optarg, conv_ns); - if (opt_nslist == NULL) - usage ('?'); - break; - case 'h': - case '?': - usage (opt); - break; - } - } + while ((opt = getopt_long (argc, argv, opts, longopts, NULL)) != -1) { + switch (opt) { + case SIGNAL_OPTION: + opt_signal = signal_name_to_number (optarg); + if (opt_signal == -1 && isdigit (optarg[0])) + opt_signal = atoi (optarg); + break; + case 'e': + opt_echo = 1; + break; +/* case 'D': / * FreeBSD: print info about non-matches for debugging * / + * break; */ + case 'F': /* FreeBSD: the arg is a file containing a PID to match */ + opt_pidfile = xstrdup (optarg); + ++criteria_count; + break; + case 'G': /* Solaris: match rgid/rgroup */ + opt_rgid = split_list (optarg, conv_gid); + if (opt_rgid == NULL) + usage ('?'); + ++criteria_count; + break; +/* case 'I': / * FreeBSD: require confirmation before killing * / + * break; */ +/* case 'J': / * Solaris: match by project ID (name or number) * / + * break; */ + case 'L': /* FreeBSD: fail if pidfile (see -F) not locked */ + opt_lock++; + break; +/* case 'M': / * FreeBSD: specify core (OS crash dump) file * / + * break; */ +/* case 'N': / * FreeBSD: specify alternate namelist file (for us, System.map -- but we don't need it) * / + * break; */ + case 'P': /* Solaris: match by PPID */ + opt_ppid = split_list (optarg, conv_num); + if (opt_ppid == NULL) + usage ('?'); + ++criteria_count; + break; +/* case 'S': / * FreeBSD: don't ignore the built-in kernel tasks * / + * break; */ +/* case 'T': / * Solaris: match by "task ID" (probably not a Linux task) * / + * break; */ + case 'U': /* Solaris: match by ruid/rgroup */ + opt_ruid = split_list (optarg, conv_uid); + if (opt_ruid == NULL) + usage ('?'); + ++criteria_count; + break; + case 'V': + printf(PROCPS_NG_VERSION); + exit(EXIT_SUCCESS); +/* case 'c': / * Solaris: match by contract ID * / + * break; */ + case 'c': + opt_count = 1; + break; + case 'd': /* Solaris: change the delimiter */ + opt_delim = xstrdup (optarg); + break; + case 'f': /* Solaris: match full process name (as in "ps -f") */ + opt_full = 1; + break; + case 'g': /* Solaris: match pgrp */ + opt_pgrp = split_list (optarg, conv_pgrp); + if (opt_pgrp == NULL) + usage ('?'); + ++criteria_count; + break; + case 'i': /* FreeBSD: ignore case. OpenBSD: withdrawn. See -I. This sucks. */ + if (opt_case) + usage (opt); + opt_case = REG_ICASE; + break; +/* case 'j': / * FreeBSD: restricted to the given jail ID * / + * break; */ + case 'l': /* Solaris: long output format (pgrep only) Should require -f for beyond argv[0] maybe? */ + opt_long = 1; + break; + case 'a': + opt_longlong = 1; + break; + case 'n': /* Solaris: match only the newest */ + if (opt_oldest|opt_negate|opt_newest) + usage ('?'); + opt_newest = 1; + ++criteria_count; + break; + case 'o': /* Solaris: match only the oldest */ + if (opt_oldest|opt_negate|opt_newest) + usage ('?'); + opt_oldest = 1; + ++criteria_count; + break; + case 's': /* Solaris: match by session ID -- zero means self */ + opt_sid = split_list (optarg, conv_sid); + if (opt_sid == NULL) + usage ('?'); + ++criteria_count; + break; + case 't': /* Solaris: match by tty */ + opt_term = split_list (optarg, conv_str); + if (opt_term == NULL) + usage ('?'); + ++criteria_count; + break; + case 'u': /* Solaris: match by euid/egroup */ + opt_euid = split_list (optarg, conv_uid); + if (opt_euid == NULL) + usage ('?'); + ++criteria_count; + break; + case 'v': /* Solaris: as in grep, invert the matching (uh... applied after selection I think) */ + if (opt_oldest|opt_negate|opt_newest) + usage ('?'); + opt_negate = 1; + break; + case 'w': // Linux: show threads (lightweight process) too + opt_threads = 1; + break; + /* OpenBSD -x, being broken, does a plain string */ + case 'x': /* Solaris: use ^(regexp)$ in place of regexp (FreeBSD too) */ + opt_exact = 1; + break; +/* case 'z': / * Solaris: match by zone ID * / + * break; */ + case NS_OPTION: + opt_ns_pid = atoi(optarg); + if (opt_ns_pid == 0) + usage ('?'); + ++criteria_count; + break; + case NSLIST_OPTION: + opt_nslist = split_list (optarg, conv_ns); + if (opt_nslist == NULL) + usage ('?'); + break; + case 'h': + case '?': + usage (opt); + break; + } + } - if(opt_lock && !opt_pidfile) - xerrx(EXIT_USAGE, _("-L without -F makes no sense\n" - "Try `%s --help' for more information."), - program_invocation_short_name); + if(opt_lock && !opt_pidfile) + xerrx(EXIT_USAGE, _("-L without -F makes no sense\n" + "Try `%s --help' for more information."), + program_invocation_short_name); - if(opt_pidfile){ - opt_pid = read_pidfile(); - if(!opt_pid) - xerrx(EXIT_FAILURE, _("pidfile not valid\n" - "Try `%s --help' for more information."), - program_invocation_short_name); - } + if(opt_pidfile){ + opt_pid = read_pidfile(); + if(!opt_pid) + xerrx(EXIT_FAILURE, _("pidfile not valid\n" + "Try `%s --help' for more information."), + program_invocation_short_name); + } - if (argc - optind == 1) - opt_pattern = argv[optind]; - else if (argc - optind > 1) - xerrx(EXIT_USAGE, _("only one pattern can be provided\n" - "Try `%s --help' for more information."), - program_invocation_short_name); - else if (criteria_count == 0) - xerrx(EXIT_USAGE, _("no matching criteria specified\n" - "Try `%s --help' for more information."), - program_invocation_short_name); + if (argc - optind == 1) + opt_pattern = argv[optind]; + else if (argc - optind > 1) + xerrx(EXIT_USAGE, _("only one pattern can be provided\n" + "Try `%s --help' for more information."), + program_invocation_short_name); + else if (criteria_count == 0) + xerrx(EXIT_USAGE, _("no matching criteria specified\n" + "Try `%s --help' for more information."), + program_invocation_short_name); } int main (int argc, char **argv) { - struct el *procs; - int num; + struct el *procs; + int num; #ifdef HAVE_PROGRAM_INVOCATION_NAME - program_invocation_name = program_invocation_short_name; + program_invocation_name = program_invocation_short_name; #endif - setlocale (LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - atexit(close_stdout); + setlocale (LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); - parse_opts (argc, argv); + parse_opts (argc, argv); - procs = select_procs (&num); - if (i_am_pkill) { - int i; - for (i = 0; i < num; i++) { - if (kill (procs[i].num, opt_signal) != -1) { - if (opt_echo) - printf(_("%s killed (pid %lu)\n"), procs[i].str, procs[i].num); - continue; - } - if (errno==ESRCH) - /* gone now, which is OK */ - continue; - xwarn(_("killing pid %ld failed"), procs[i].num); - } - if (opt_count) - fprintf(stdout, "%d\n", num); - } else { - if (opt_count) { - fprintf(stdout, "%d\n", num); - } else { - if (opt_long || opt_longlong) - output_strlist (procs,num); - else - output_numlist (procs,num); - } - } - return !num; /* exit(EXIT_SUCCESS) if match, otherwise exit(EXIT_FAILURE) */ + procs = select_procs (&num); + if (i_am_pkill) { + int i; + for (i = 0; i < num; i++) { + if (kill (procs[i].num, opt_signal) != -1) { + if (opt_echo) + printf(_("%s killed (pid %lu)\n"), procs[i].str, procs[i].num); + continue; + } + if (errno==ESRCH) + /* gone now, which is OK */ + continue; + xwarn(_("killing pid %ld failed"), procs[i].num); + } + if (opt_count) + fprintf(stdout, "%d\n", num); + } else { + if (opt_count) { + fprintf(stdout, "%d\n", num); + } else { + if (opt_long || opt_longlong) + output_strlist (procs,num); + else + output_numlist (procs,num); + } + } + return !num; /* exit(EXIT_SUCCESS) if match, otherwise exit(EXIT_FAILURE) */ } diff --git a/proc/libprocps.sym b/proc/libprocps.sym index 77655d94..7b215194 100644 --- a/proc/libprocps.sym +++ b/proc/libprocps.sym @@ -40,7 +40,6 @@ global: meminfo; openproc; page_bytes; - pretty_print_signals; print_uptime; put_slabinfo; readeither; @@ -49,13 +48,9 @@ global: readproctab3; readproctab; readtask; - signal_name_to_number; - signal_number_to_name; smp_num_cpus; sprint_uptime; - strtosig; tty_to_dev; - unix_print_signals; user_from_uid; uptime; sprint_uptime; diff --git a/proc/sig.c b/proc/sig.c deleted file mode 100644 index 461db1dd..00000000 --- a/proc/sig.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * sig.c - signal name, and number, conversions - * Copyright 1998-2003 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 "sig.h" -#include "c.h" - -/* Linux signals: - * - * SIGSYS is required by Unix98. - * SIGEMT is part of SysV, BSD, and ancient UNIX tradition. - * - * They are provided by these Linux ports: alpha, mips, sparc, and sparc64. - * You get SIGSTKFLT and SIGUNUSED instead on i386, m68k, ppc, and arm. - * (this is a Linux & libc bug -- both must be fixed) - * - * Total garbage: SIGIO SIGINFO SIGIOT SIGLOST SIGCLD - * (popular ones are handled as aliases) - * Nearly garbage: SIGSTKFLT SIGUNUSED (nothing else to fill slots) - */ - -/* Linux 2.3.29 replaces SIGUNUSED with the standard SIGSYS signal */ -#ifndef SIGSYS -# warning Standards require that define SIGSYS -# define SIGSYS SIGUNUSED -#endif - -/* If we see both, it is likely SIGSTKFLT (junk) was replaced. */ -#ifdef SIGEMT -# undef SIGSTKFLT -#endif - -#ifndef SIGRTMIN -# warning Standards require that define SIGRTMIN; assuming 32 -# define SIGRTMIN 32 -#endif - -/* It seems the SPARC libc does not know the kernel supports SIGPWR. */ -#ifndef SIGPWR -# warning Your header files lack SIGPWR. (assuming it is number 29) -# define SIGPWR 29 -#endif - -typedef struct mapstruct { - const char *name; - int num; -} mapstruct; - - -static const mapstruct sigtable[] = { - {"ABRT", SIGABRT}, /* IOT */ - {"ALRM", SIGALRM}, - {"BUS", SIGBUS}, - {"CHLD", SIGCHLD}, /* CLD */ - {"CONT", SIGCONT}, -#ifdef SIGEMT - {"EMT", SIGEMT}, -#endif - {"FPE", SIGFPE}, - {"HUP", SIGHUP}, - {"ILL", SIGILL}, - {"INT", SIGINT}, - {"KILL", SIGKILL}, - {"PIPE", SIGPIPE}, - {"POLL", SIGPOLL}, /* IO */ - {"PROF", SIGPROF}, - {"PWR", SIGPWR}, - {"QUIT", SIGQUIT}, - {"SEGV", SIGSEGV}, -#ifdef SIGSTKFLT - {"STKFLT", SIGSTKFLT}, -#endif - {"STOP", SIGSTOP}, - {"SYS", SIGSYS}, /* UNUSED */ - {"TERM", SIGTERM}, - {"TRAP", SIGTRAP}, - {"TSTP", SIGTSTP}, - {"TTIN", SIGTTIN}, - {"TTOU", SIGTTOU}, - {"URG", SIGURG}, - {"USR1", SIGUSR1}, - {"USR2", SIGUSR2}, - {"VTALRM", SIGVTALRM}, - {"WINCH", SIGWINCH}, - {"XCPU", SIGXCPU}, - {"XFSZ", SIGXFSZ} -}; - -static const int number_of_signals = sizeof(sigtable)/sizeof(mapstruct); - -static int compare_signal_names(const void *a, const void *b){ - return strcasecmp( ((const mapstruct*)a)->name, ((const mapstruct*)b)->name ); -} - -/* return -1 on failure */ -int signal_name_to_number(const char *restrict name){ - long val; - int offset; - - /* clean up name */ - if(!strncasecmp(name,"SIG",3)) name += 3; - - if(!strcasecmp(name,"CLD")) return SIGCHLD; - if(!strcasecmp(name,"IO")) return SIGPOLL; - if(!strcasecmp(name,"IOT")) return SIGABRT; - - /* search the table */ - { - const mapstruct ms = {name,0}; - const mapstruct *restrict const ptr = bsearch( - &ms, - sigtable, - number_of_signals, - sizeof(mapstruct), - compare_signal_names - ); - if(ptr) return ptr->num; - } - - if(!strcasecmp(name,"RTMIN")) return SIGRTMIN; - if(!strcasecmp(name,"EXIT")) return 0; - if(!strcasecmp(name,"NULL")) return 0; - - offset = 0; - if(!strncasecmp(name,"RTMIN+",6)){ - name += 6; - offset = SIGRTMIN; - } - - /* not found, so try as a number */ - { - char *endp; - val = strtol(name,&endp,10); - if(*endp || endp==name) return -1; /* not valid */ - } - if(val+SIGRTMIN>127) return -1; /* not valid */ - return val+offset; -} - -const char *signal_number_to_name(int signo){ - static char buf[32]; - int n = number_of_signals; - signo &= 0x7f; /* need to process exit values too */ - while(n--){ - if(sigtable[n].num==signo) return sigtable[n].name; - } - if(signo == SIGRTMIN) return "RTMIN"; - if(signo) sprintf(buf, "RTMIN+%d", signo-SIGRTMIN); - else strcpy(buf,"0"); /* AIX has NULL; Solaris has EXIT */ - return buf; -} - -int print_given_signals(int argc, const char *restrict const *restrict argv, int max_line){ - char buf[1280]; /* 128 signals, "RTMIN+xx" is largest */ - int ret = 0; /* to be used as exit code by caller */ - int place = 0; /* position on this line */ - int amt; - if(argc > 128) return 1; - while(argc--){ - char tmpbuf[16]; - const char *restrict const txt = *argv; - if(*txt >= '0' && *txt <= '9'){ - long val; - char *endp; - val = strtol(txt,&endp,10); - if(*endp){ - fprintf(stderr, "Signal \"%s\" not known.\n", txt); - ret = 1; - goto end; - } - amt = sprintf(tmpbuf, "%s", signal_number_to_name(val)); - }else{ - int sno; - sno = signal_name_to_number(txt); - if(sno == -1){ - fprintf(stderr, "Signal \"%s\" not known.\n", txt); - ret = 1; - goto end; - } - amt = sprintf(tmpbuf, "%d", sno); - } - - if(!place){ - strcpy(buf,tmpbuf); - place = amt; - goto end; - } - if(amt+place+1 > max_line){ - printf("%s\n", buf); - strcpy(buf,tmpbuf); - place = amt; - goto end; - } - sprintf(buf+place, " %s", tmpbuf); - place += amt+1; -end: - argv++; - } - if(place) printf("%s\n", buf); - return ret; -} - -/* 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 == sigtable[i].num){ - converted = strdup(sigtable[i].name); - break; - } - } - } else { - for (i = 0; i < number_of_signals; i++){ - if (strcmp(p, sigtable[i].name) == 0){ - converted = malloc(sizeof(char) * 8); - if (converted) - snprintf(converted, sizeof(converted) - 1, "%d", sigtable[i].num); - break; - } - } - } - free(p); - return converted; -} - -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"); -} - -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"); -} - -/* sanity check */ -static int init_signal_list(void) __attribute__((constructor)); -static int init_signal_list(void){ - if(number_of_signals != 31){ - fprintf(stderr, "WARNING: %d signals -- adjust and recompile.\n", number_of_signals); - } - return 0; -} diff --git a/ps/display.c b/ps/display.c index 0c95cc69..275cd827 100644 --- a/ps/display.c +++ b/ps/display.c @@ -31,13 +31,13 @@ #include "../proc/alloc.h" #include "../proc/readproc.h" -#include "../proc/sig.h" #include "../proc/sysinfo.h" #include "../proc/version.h" #include "../proc/wchan.h" #include "../include/fileutils.h" #include "../include/c.h" +#include "../include/signals.h" #include "common.h" #ifndef SIGCHLD diff --git a/skill.c b/skill.c index 9a19a8bb..a49c8a1b 100644 --- a/skill.c +++ b/skill.c @@ -37,26 +37,26 @@ #include "c.h" #include "fileutils.h" #include "nsutils.h" +#include "signals.h" #include "strutils.h" #include "nls.h" #include "xalloc.h" #include "proc/pwcache.h" -#include "proc/sig.h" #include "proc/devname.h" -#include "proc/procps.h" /* char *user_from_uid(uid_t uid) */ +#include "proc/procps.h" /* char *user_from_uid(uid_t uid) */ #include "proc/readproc.h" -#include "proc/version.h" /* procps_version */ +#include "proc/version.h" /* procps_version */ #include "rpmatch.h" #define DEFAULT_NICE 4 struct run_time_conf_t { - int fast; - int interactive; - int verbose; - int warnings; - int noaction; - int debugging; + int fast; + int interactive; + int verbose; + int warnings; + int noaction; + int debugging; }; static int tty_count, uid_count, cmd_count, pid_count, namespace_count; static int *ttys; @@ -78,442 +78,514 @@ static int saved_argc; static int sig_or_pri; enum { - PROG_UNKNOWN, - PROG_KILL, - PROG_SKILL, - PROG_SNICE + PROG_UNKNOWN, + PROG_KILL, + PROG_SKILL, + PROG_SNICE }; static int program = PROG_UNKNOWN; static void display_kill_version(void) { - fprintf(stdout, PROCPS_NG_VERSION); + fprintf(stdout, PROCPS_NG_VERSION); } static int ns_flags = 0x3f; static int parse_namespaces(char *optarg) { - char *ptr = optarg, *tmp; - int len, id; + char *ptr = optarg, *tmp; + int len, id; - ns_flags = 0; - while (1) { - if (strchr(ptr, ',') == NULL) { - len = -1; - tmp = strdup(ptr); - } else { - len = strchr(ptr, ',') - ptr; - tmp = strndup(ptr, len); - } + ns_flags = 0; + while (1) { + if (strchr(ptr, ',') == NULL) { + len = -1; + tmp = strdup(ptr); + } else { + len = strchr(ptr, ',') - ptr; + tmp = strndup(ptr, len); + } - id = get_ns_id(tmp); - if (id == -1) { - fprintf(stderr, "%s is not a valid namespace\n", tmp); - free(tmp); - return 1; - } - ns_flags |= (1 << id); - ENLIST(namespace, tmp); + id = get_ns_id(tmp); + if (id == -1) { + fprintf(stderr, "%s is not a valid namespace\n", tmp); + free(tmp); + return 1; + } + ns_flags |= (1 << id); + ENLIST(namespace, tmp); - if (len == -1) - break; + if (len == -1) + break; - ptr+= len + 1; - } - return 0; + ptr+= len + 1; + } + 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) + struct run_time_conf_t *run_time) { - int failed; - char dn_buf[1000]; - dev_to_tty(dn_buf, 999, tty, pid, ABBREV_DEV); - if (run_time->interactive) { - char *buf; - size_t len = 0; - fprintf(stderr, "%-8s %-8s %5d %-16.16s ? ", - (char *)dn_buf, user_from_uid(uid), pid, cmd); - fflush (stdout); - if (getline(&buf, &len, stdin) == -1) - return; - if (rpmatch(buf) < 1) { - free(buf); - return; - } - free(buf); - } - /* do the actual work */ - errno = 0; - if (program == PROG_SKILL) - failed = kill(pid, sig_or_pri); - else - failed = setpriority(PRIO_PROCESS, pid, sig_or_pri); - if ((run_time->warnings && failed) || run_time->debugging || run_time->verbose) { - fprintf(stderr, "%-8s %-8s %5d %-16.16s ", - (char *)dn_buf, user_from_uid(uid), pid, cmd); - perror(""); - return; - } - if (run_time->interactive) - return; - if (run_time->noaction) { - printf("%d\n", pid); - return; - } + int failed; + char dn_buf[1000]; + dev_to_tty(dn_buf, 999, tty, pid, ABBREV_DEV); + if (run_time->interactive) { + char *buf; + size_t len = 0; + fprintf(stderr, "%-8s %-8s %5d %-16.16s ? ", + (char *)dn_buf, user_from_uid(uid), pid, cmd); + fflush (stdout); + if (getline(&buf, &len, stdin) == -1) + return; + if (rpmatch(buf) < 1) { + free(buf); + return; + } + free(buf); + } + /* do the actual work */ + errno = 0; + if (program == PROG_SKILL) + failed = kill(pid, sig_or_pri); + else + failed = setpriority(PRIO_PROCESS, pid, sig_or_pri); + if ((run_time->warnings && failed) || run_time->debugging || run_time->verbose) { + fprintf(stderr, "%-8s %-8s %5d %-16.16s ", + (char *)dn_buf, user_from_uid(uid), pid, cmd); + perror(""); + return; + } + if (run_time->interactive) + return; + if (run_time->noaction) { + printf("%d\n", pid); + return; + } } /* check one process */ static void check_proc(int pid, struct run_time_conf_t *run_time) { - char buf[128]; - struct stat statbuf; - proc_t task; - char *tmp; - int tty; - int fd; - int i; - if (pid == my_pid || pid == 0) - return; - /* pid (cmd) state ppid pgrp session tty */ - sprintf(buf, "/proc/%d/stat", pid); - fd = open(buf, O_RDONLY); - if (fd == -1) { - /* process exited maybe */ - if (run_time->warnings) - xwarn(_("cannot open file %s"), buf); - return; - } - fstat(fd, &statbuf); - if (uids) { - /* check the EUID */ - i = uid_count; - while (i--) - if (uids[i] == statbuf.st_uid) - break; - if (i == -1) - goto closure; - } - if (read(fd, buf, 128) <= 0) - goto closure; - buf[127] = '\0'; - tmp = strrchr(buf, ')'); - *tmp++ = '\0'; - i = 5; - while (i--) - while (*tmp++ != ' ') - /* scan to find tty */ ; - tty = atoi(tmp); - if (ttys) { - i = tty_count; - while (i--) - if (ttys[i] == tty) - break; - if (i == -1) - goto closure; - } - tmp = strchr(buf, '(') + 1; - if (cmds) { - i = cmd_count; - /* fast comparison trick -- useful? */ - while (i--) - if (cmds[i][0] == *tmp && !strcmp(cmds[i], tmp)) - break; - if (i == -1) - goto closure; - } - if (ns_pid) { - if (ns_read(pid, &task)) - goto closure; - for (i = 0; i < NUM_NS; i++) { - if (ns_flags & (1 << i)) { - if (task.ns[i] != ns_task.ns[i]) - goto closure; - } - } - } - /* This is where we kill/nice something. */ - /* for debugging purposes? - fprintf(stderr, "PID %d, UID %d, TTY %d,%d, COMM %s\n", - pid, statbuf.st_uid, tty >> 8, tty & 0xf, tmp); - */ - hurt_proc(tty, statbuf.st_uid, pid, tmp, run_time); + char buf[128]; + struct stat statbuf; + proc_t task; + char *tmp; + int tty; + int fd; + int i; + if (pid == my_pid || pid == 0) + return; + /* pid (cmd) state ppid pgrp session tty */ + sprintf(buf, "/proc/%d/stat", pid); + fd = open(buf, O_RDONLY); + if (fd == -1) { + /* process exited maybe */ + if (run_time->warnings) + xwarn(_("cannot open file %s"), buf); + return; + } + fstat(fd, &statbuf); + if (uids) { + /* check the EUID */ + i = uid_count; + while (i--) + if (uids[i] == statbuf.st_uid) + break; + if (i == -1) + goto closure; + } + if (read(fd, buf, 128) <= 0) + goto closure; + buf[127] = '\0'; + tmp = strrchr(buf, ')'); + *tmp++ = '\0'; + i = 5; + while (i--) + while (*tmp++ != ' ') + /* scan to find tty */ ; + tty = atoi(tmp); + if (ttys) { + i = tty_count; + while (i--) + if (ttys[i] == tty) + break; + if (i == -1) + goto closure; + } + tmp = strchr(buf, '(') + 1; + if (cmds) { + i = cmd_count; + /* fast comparison trick -- useful? */ + while (i--) + if (cmds[i][0] == *tmp && !strcmp(cmds[i], tmp)) + break; + if (i == -1) + goto closure; + } + if (ns_pid) { + if (ns_read(pid, &task)) + goto closure; + for (i = 0; i < NUM_NS; i++) { + if (ns_flags & (1 << i)) { + if (task.ns[i] != ns_task.ns[i]) + goto closure; + } + } + } + /* This is where we kill/nice something. */ + /* for debugging purposes? + fprintf(stderr, "PID %d, UID %d, TTY %d,%d, COMM %s\n", + pid, statbuf.st_uid, tty >> 8, tty & 0xf, tmp); + */ + hurt_proc(tty, statbuf.st_uid, pid, tmp, run_time); closure: - /* kill/nice _first_ to avoid PID reuse */ - close(fd); + /* kill/nice _first_ to avoid PID reuse */ + close(fd); } /* debug function */ static void show_lists(void) { - int i; + int i; - fprintf(stderr, "signal: %d\n", sig_or_pri); + fprintf(stderr, "signal: %d\n", sig_or_pri); - fprintf(stderr, "%d TTY: ", tty_count); - if (ttys) { - i = tty_count; - while (i--) { - fprintf(stderr, "%d,%d%c", (ttys[i] >> 8) & 0xff, - ttys[i] & 0xff, i ? ' ' : '\n'); - } - } else - fprintf(stderr, "\n"); + fprintf(stderr, "%d TTY: ", tty_count); + if (ttys) { + i = tty_count; + while (i--) { + fprintf(stderr, "%d,%d%c", (ttys[i] >> 8) & 0xff, + ttys[i] & 0xff, i ? ' ' : '\n'); + } + } else + fprintf(stderr, "\n"); - fprintf(stderr, "%d UID: ", uid_count); - if (uids) { - i = uid_count; - while (i--) - fprintf(stderr, "%d%c", uids[i], i ? ' ' : '\n'); - } else - fprintf(stderr, "\n"); + fprintf(stderr, "%d UID: ", uid_count); + if (uids) { + i = uid_count; + while (i--) + fprintf(stderr, "%d%c", uids[i], i ? ' ' : '\n'); + } else + fprintf(stderr, "\n"); - fprintf(stderr, "%d PID: ", pid_count); - if (pids) { - i = pid_count; - while (i--) - fprintf(stderr, "%d%c", pids[i], i ? ' ' : '\n'); - } else - fprintf(stderr, "\n"); + fprintf(stderr, "%d PID: ", pid_count); + if (pids) { + i = pid_count; + while (i--) + fprintf(stderr, "%d%c", pids[i], i ? ' ' : '\n'); + } else + fprintf(stderr, "\n"); - fprintf(stderr, "%d CMD: ", cmd_count); - if (cmds) { - i = cmd_count; - while (i--) - fprintf(stderr, "%s%c", cmds[i], i ? ' ' : '\n'); - } else - fprintf(stderr, "\n"); + fprintf(stderr, "%d CMD: ", cmd_count); + if (cmds) { + i = cmd_count; + while (i--) + fprintf(stderr, "%s%c", cmds[i], i ? ' ' : '\n'); + } else + fprintf(stderr, "\n"); } /* iterate over all PIDs */ static void iterate(struct run_time_conf_t *run_time) { - int pid; - DIR *d; - struct dirent *de; - if (pids) { - pid = pid_count; - while (pid--) - check_proc(pids[pid], run_time); - return; - } + int pid; + DIR *d; + struct dirent *de; + if (pids) { + pid = pid_count; + while (pid--) + check_proc(pids[pid], run_time); + return; + } #if 0 - /* could setuid() and kill -1 to have the kernel wipe out a user */ - if (!ttys && !cmds && !pids && !run_time->interactive) { - } + /* could setuid() and kill -1 to have the kernel wipe out a user */ + if (!ttys && !cmds && !pids && !run_time->interactive) { + } #endif - d = opendir("/proc"); - if (!d) - xerr(EXIT_FAILURE, "/proc"); - while ((de = readdir(d))) { - if (de->d_name[0] > '9') - continue; - if (de->d_name[0] < '1') - continue; - pid = atoi(de->d_name); - if (pid) - check_proc(pid, run_time); - } - closedir(d); + d = opendir("/proc"); + if (!d) + xerr(EXIT_FAILURE, "/proc"); + while ((de = readdir(d))) { + if (de->d_name[0] > '9') + continue; + if (de->d_name[0] < '1') + continue; + pid = atoi(de->d_name); + if (pid) + check_proc(pid, run_time); + } + closedir(d); } /* kill help */ static void __attribute__ ((__noreturn__)) kill_usage(FILE * out) { - fputs(USAGE_HEADER, out); - fprintf(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); + 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) { - fputs(USAGE_HEADER, out); + fputs(USAGE_HEADER, out); - if (program == PROG_SKILL) { - fprintf(out, - _(" %s [signal] [options] \n"), - program_invocation_short_name); - } else { - fprintf(out, - _(" %s [new priority] [options] \n"), - program_invocation_short_name); - } - fputs(USAGE_OPTIONS, out); - fputs(_(" -f, --fast fast mode (not implemented)\n"), out); - fputs(_(" -i, --interactive interactive\n"), out); - fputs(_(" -l, --list list all signal names\n"), out); - fputs(_(" -L, --table list all signal names in a nice table\n"), out); - fputs(_(" -n, --no-action do not actually kill processes; just print what would happen\n"), out); - fputs(_(" -v, --verbose explain what is being done\n"), out); - fputs(_(" -w, --warnings enable warnings (not implemented)\n"), out); - fputs(USAGE_SEPARATOR, out); - fputs(_("Expression can be: terminal, user, pid, command.\n" - "The options below may be used to ensure correct interpretation.\n"), out); - fputs(_(" -c, --command expression is a command name\n"), out); - fputs(_(" -p, --pid expression is a process id number\n"), out); - fputs(_(" -t, --tty expression is a terminal\n"), out); - fputs(_(" -u, --user expression is a username\n"), out); - fputs(USAGE_SEPARATOR, out); - fputs(_("Alternatively, expression can be:\n"), out); - fputs(_(" --ns match the processes that belong to the same\n" - " namespace as \n"), out); - fputs(_(" --nslist list which namespaces will be considered for\n" - " the --ns option; available namespaces are\n:" - " ipc, mnt, net, pid, user, uts\n"), out); + if (program == PROG_SKILL) { + fprintf(out, + _(" %s [signal] [options] \n"), + program_invocation_short_name); + } else { + fprintf(out, + _(" %s [new priority] [options] \n"), + program_invocation_short_name); + } + fputs(USAGE_OPTIONS, out); + fputs(_(" -f, --fast fast mode (not implemented)\n"), out); + fputs(_(" -i, --interactive interactive\n"), out); + fputs(_(" -l, --list list all signal names\n"), out); + fputs(_(" -L, --table list all signal names in a nice table\n"), out); + fputs(_(" -n, --no-action do not actually kill processes; just print what would happen\n"), out); + fputs(_(" -v, --verbose explain what is being done\n"), out); + fputs(_(" -w, --warnings enable warnings (not implemented)\n"), out); + fputs(USAGE_SEPARATOR, out); + fputs(_("Expression can be: terminal, user, pid, command.\n" + "The options below may be used to ensure correct interpretation.\n"), out); + fputs(_(" -c, --command expression is a command name\n"), out); + fputs(_(" -p, --pid expression is a process id number\n"), out); + fputs(_(" -t, --tty expression is a terminal\n"), out); + fputs(_(" -u, --user expression is a username\n"), out); + fputs(USAGE_SEPARATOR, out); + fputs(_("Alternatively, expression can be:\n"), out); + fputs(_(" --ns match the processes that belong to the same\n" + " namespace as \n"), out); + fputs(_(" --nslist list which namespaces will be considered for\n" + " the --ns option; available namespaces are\n:" + " ipc, mnt, net, pid, user, uts\n"), out); - fputs(USAGE_SEPARATOR, out); - fputs(USAGE_SEPARATOR, out); - fputs(USAGE_HELP, out); - fputs(USAGE_VERSION, out); - if (program == PROG_SKILL) { - fprintf(out, - _("\n" - "The default signal is TERM. Use -l or -L to list available signals.\n" - "Particularly useful signals include HUP, INT, KILL, STOP, CONT, and 0.\n" - "Alternate signals may be specified in three ways: -SIGKILL -KILL -9\n")); - fprintf(out, USAGE_MAN_TAIL("skill(1)")); - } else { - fprintf(out, - _("\n" - "The default priority is +4. (snice +4 ...)\n" - "Priority numbers range from +20 (slowest) to -20 (fastest).\n" - "Negative priority numbers are restricted to administrative users.\n")); - fprintf(out, USAGE_MAN_TAIL("snice(1)")); - } - exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_HELP, out); + fputs(USAGE_VERSION, out); + if (program == PROG_SKILL) { + fprintf(out, + _("\n" + "The default signal is TERM. Use -l or -L to list available signals.\n" + "Particularly useful signals include HUP, INT, KILL, STOP, CONT, and 0.\n" + "Alternate signals may be specified in three ways: -SIGKILL -KILL -9\n")); + fprintf(out, USAGE_MAN_TAIL("skill(1)")); + } else { + fprintf(out, + _("\n" + "The default priority is +4. (snice +4 ...)\n" + "Priority numbers range from +20 (slowest) to -20 (fastest).\n" + "Negative priority numbers are restricted to administrative users.\n")); + fprintf(out, USAGE_MAN_TAIL("snice(1)")); + } + 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; + 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; + 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} - }; + 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); + setlocale (LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); - if (argc < 2) - kill_usage(stderr); + if (argc < 2) + kill_usage(stderr); - signo = skill_sig_option(&argc, argv); - if (signo < 0) - signo = SIGTERM; - else - sigopt++; + 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); - } + 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; + 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; - } + 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); + exit(exitvalue); } #if 0 static void _skillsnice_usage(int line) { - fprintf(stderr, _("something at line %d\n"), line); - skillsnice_usage(stderr); + fprintf(stderr, _("something at line %d\n"), line); + skillsnice_usage(stderr); } #define skillsnice_usage() _skillsnice_usage(__LINE__) @@ -525,238 +597,238 @@ static void _skillsnice_usage(int line) static int snice_prio_option(int *argc, char **argv) { - int i = 1, nargs = *argc; - long prio = DEFAULT_NICE; + int i = 1, nargs = *argc; + long prio = DEFAULT_NICE; - while (i < nargs) { - if ((argv[i][0] == '-' || argv[i][0] == '+') - && isdigit(argv[i][1])) { - prio = strtol_or_err(argv[i], - _("failed to parse argument")); - if (prio < INT_MIN || INT_MAX < prio) - xerrx(EXIT_FAILURE, - _("priority %lu out of range"), prio); - nargs--; - if (nargs - i) - memmove(argv + i, argv + i + 1, - sizeof(char *) * (nargs - i)); - } else - i++; - } - *argc = nargs; - return (int)prio; + while (i < nargs) { + if ((argv[i][0] == '-' || argv[i][0] == '+') + && isdigit(argv[i][1])) { + prio = strtol_or_err(argv[i], + _("failed to parse argument")); + if (prio < INT_MIN || INT_MAX < prio) + xerrx(EXIT_FAILURE, + _("priority %lu out of range"), prio); + nargs--; + if (nargs - i) + memmove(argv + i, argv + i + 1, + sizeof(char *) * (nargs - i)); + } else + i++; + } + *argc = nargs; + return (int)prio; } static void skillsnice_parse(int argc, - char **argv, struct run_time_conf_t *run_time) + char **argv, struct run_time_conf_t *run_time) { - int signo = -1; - int prino = DEFAULT_NICE; - int ch, i; + int signo = -1; + int prino = DEFAULT_NICE; + int ch, i; - enum { - NS_OPTION = CHAR_MAX + 1, - NSLIST_OPTION, - }; + enum { + NS_OPTION = CHAR_MAX + 1, + NSLIST_OPTION, + }; - static const struct option longopts[] = { - {"command", required_argument, NULL, 'c'}, - {"debug", no_argument, NULL, 'd'}, - {"fast", no_argument, NULL, 'f'}, - {"interactive", no_argument, NULL, 'i'}, - {"list", no_argument, NULL, 'l'}, - {"no-action", no_argument, NULL, 'n'}, - {"pid", required_argument, NULL, 'p'}, - {"table", no_argument, NULL, 'L'}, - {"tty", required_argument, NULL, 't'}, - {"user", required_argument, NULL, 'u'}, - {"ns", required_argument, NULL, NS_OPTION}, - {"nslist", required_argument, NULL, NSLIST_OPTION}, - {"verbose", no_argument, NULL, 'v'}, - {"warnings", no_argument, NULL, 'w'}, - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {NULL, 0, NULL, 0} - }; + static const struct option longopts[] = { + {"command", required_argument, NULL, 'c'}, + {"debug", no_argument, NULL, 'd'}, + {"fast", no_argument, NULL, 'f'}, + {"interactive", no_argument, NULL, 'i'}, + {"list", no_argument, NULL, 'l'}, + {"no-action", no_argument, NULL, 'n'}, + {"pid", required_argument, NULL, 'p'}, + {"table", no_argument, NULL, 'L'}, + {"tty", required_argument, NULL, 't'}, + {"user", required_argument, NULL, 'u'}, + {"ns", required_argument, NULL, NS_OPTION}, + {"nslist", required_argument, NULL, NSLIST_OPTION}, + {"verbose", no_argument, NULL, 'v'}, + {"warnings", no_argument, NULL, 'w'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} + }; - if (argc < 2) - skillsnice_usage(stderr); + if (argc < 2) + skillsnice_usage(stderr); - sig_or_pri = -1; + sig_or_pri = -1; - if (program == PROG_SNICE) - prino = snice_prio_option(&argc, argv); - else if (program == PROG_SKILL) { - signo = skill_sig_option(&argc, argv); - if (-1 < signo) { - sig_or_pri = signo; - argc -= 1; - } - } + if (program == PROG_SNICE) + prino = snice_prio_option(&argc, argv); + else if (program == PROG_SKILL) { + signo = skill_sig_option(&argc, argv); + if (-1 < signo) { + sig_or_pri = signo; + argc -= 1; + } + } - pid_count = 0; + pid_count = 0; - while ((ch = - getopt_long(argc, argv, "c:dfilnp:Lt:u:vwhV", longopts, - NULL)) != -1) - switch (ch) { - case 'c': - ENLIST(cmd, optarg); - break; - case 'd': - run_time->debugging = 1; - break; - case 'f': - run_time->fast = 1; - break; - case 'i': - run_time->interactive = 1; - break; - case 'l': - unix_print_signals(); - exit(EXIT_SUCCESS); - case 'n': - run_time->noaction = 1; - break; - case 'p': - ENLIST(pid, - strtol_or_err(optarg, - _("failed to parse argument"))); - pid_count++; - break; - case 'L': - pretty_print_signals(); - exit(EXIT_SUCCESS); - case 't': - { - struct stat sbuf; - char path[32]; - snprintf(path, 32, "/dev/%s", optarg); - if (stat(path, &sbuf) >= 0 - && S_ISCHR(sbuf.st_mode)) { - ENLIST(tty, sbuf.st_rdev); - } - } - break; - case 'u': - { - struct passwd *passwd_data; - passwd_data = getpwnam(optarg); - if (passwd_data) { - ENLIST(uid, passwd_data->pw_uid); - } - } - break; - case NS_OPTION: - ns_pid = atoi(optarg); - if (ns_pid == 0) { - xwarnx(_("invalid pid number %s"), optarg); - kill_usage(stderr); - } - if (ns_read(ns_pid, &ns_task)) { - xwarnx(_("error reading reference namespace " - "information")); - kill_usage(stderr); - } + while ((ch = + getopt_long(argc, argv, "c:dfilnp:Lt:u:vwhV", longopts, + NULL)) != -1) + switch (ch) { + case 'c': + ENLIST(cmd, optarg); + break; + case 'd': + run_time->debugging = 1; + break; + case 'f': + run_time->fast = 1; + break; + case 'i': + run_time->interactive = 1; + break; + case 'l': + unix_print_signals(); + exit(EXIT_SUCCESS); + case 'n': + run_time->noaction = 1; + break; + case 'p': + ENLIST(pid, + strtol_or_err(optarg, + _("failed to parse argument"))); + pid_count++; + break; + case 'L': + pretty_print_signals(); + exit(EXIT_SUCCESS); + case 't': + { + struct stat sbuf; + char path[32]; + snprintf(path, 32, "/dev/%s", optarg); + if (stat(path, &sbuf) >= 0 + && S_ISCHR(sbuf.st_mode)) { + ENLIST(tty, sbuf.st_rdev); + } + } + break; + case 'u': + { + struct passwd *passwd_data; + passwd_data = getpwnam(optarg); + if (passwd_data) { + ENLIST(uid, passwd_data->pw_uid); + } + } + break; + case NS_OPTION: + ns_pid = atoi(optarg); + if (ns_pid == 0) { + xwarnx(_("invalid pid number %s"), optarg); + kill_usage(stderr); + } + if (ns_read(ns_pid, &ns_task)) { + xwarnx(_("error reading reference namespace " + "information")); + kill_usage(stderr); + } - break; - case NSLIST_OPTION: - if (parse_namespaces(optarg)) { - xwarnx(_("invalid namespace list")); - kill_usage(stderr); - } - break; - case 'v': - run_time->verbose = 1; - break; - case 'w': - run_time->warnings = 1; - break; - case 'h': - skillsnice_usage(stdout); - case 'V': - display_kill_version(); - exit(EXIT_SUCCESS); - default: - skillsnice_usage(stderr); - } + break; + case NSLIST_OPTION: + if (parse_namespaces(optarg)) { + xwarnx(_("invalid namespace list")); + kill_usage(stderr); + } + break; + case 'v': + run_time->verbose = 1; + break; + case 'w': + run_time->warnings = 1; + break; + case 'h': + skillsnice_usage(stdout); + case 'V': + display_kill_version(); + exit(EXIT_SUCCESS); + default: + skillsnice_usage(stderr); + } - argc -= optind; - argv += optind; + argc -= optind; + argv += optind; - for (i = 0; i < argc; i++) { - long num; - char *end = NULL; - errno = 0; - num = strtol(argv[0], &end, 10); - if (errno == 0 && argv[0] != end && end != NULL && *end == '\0') { - ENLIST(pid, num); - pid_count++; - } else { - ENLIST(cmd, argv[0]); - } - argv++; - } + for (i = 0; i < argc; i++) { + long num; + char *end = NULL; + errno = 0; + num = strtol(argv[0], &end, 10); + if (errno == 0 && argv[0] != end && end != NULL && *end == '\0') { + ENLIST(pid, num); + pid_count++; + } else { + ENLIST(cmd, argv[0]); + } + argv++; + } - /* No more arguments to process. Must sanity check. */ - if (!tty_count && !uid_count && !cmd_count && !pid_count && !ns_pid) - xerrx(EXIT_FAILURE, _("no process selection criteria")); - if ((run_time->fast | run_time->interactive | run_time-> - verbose | run_time->warnings | run_time->noaction) & ~1) - xerrx(EXIT_FAILURE, _("general flags may not be repeated")); - if (run_time->interactive - && (run_time->verbose | run_time->fast | run_time->noaction)) - xerrx(EXIT_FAILURE, _("-i makes no sense with -v, -f, and -n")); - if (run_time->verbose && (run_time->interactive | run_time->fast)) - xerrx(EXIT_FAILURE, _("-v makes no sense with -i and -f")); - if (run_time->noaction) { - program = PROG_SKILL; - /* harmless */ - sig_or_pri = 0; - } - if (program == PROG_SNICE) - sig_or_pri = prino; - else if (sig_or_pri < 0) - sig_or_pri = SIGTERM; + /* No more arguments to process. Must sanity check. */ + if (!tty_count && !uid_count && !cmd_count && !pid_count && !ns_pid) + xerrx(EXIT_FAILURE, _("no process selection criteria")); + if ((run_time->fast | run_time->interactive | run_time-> + verbose | run_time->warnings | run_time->noaction) & ~1) + xerrx(EXIT_FAILURE, _("general flags may not be repeated")); + if (run_time->interactive + && (run_time->verbose | run_time->fast | run_time->noaction)) + xerrx(EXIT_FAILURE, _("-i makes no sense with -v, -f, and -n")); + if (run_time->verbose && (run_time->interactive | run_time->fast)) + xerrx(EXIT_FAILURE, _("-v makes no sense with -i and -f")); + if (run_time->noaction) { + program = PROG_SKILL; + /* harmless */ + sig_or_pri = 0; + } + if (program == PROG_SNICE) + sig_or_pri = prino; + else if (sig_or_pri < 0) + sig_or_pri = SIGTERM; } /* main body */ int main(int argc, char ** argv) { #ifdef HAVE_PROGRAM_INVOCATION_NAME - program_invocation_name = program_invocation_short_name; + program_invocation_name = program_invocation_short_name; #endif - struct run_time_conf_t run_time; - memset(&run_time, 0, sizeof(struct run_time_conf_t)); - my_pid = getpid(); + struct run_time_conf_t run_time; + 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 || - strcmp(program_invocation_short_name, "lt-skill") == 0) - program = PROG_SKILL; - else if (strcmp(program_invocation_short_name, "snice") == 0 || - strcmp(program_invocation_short_name, "lt-snice") == 0) - program = PROG_SNICE; + 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 || + strcmp(program_invocation_short_name, "lt-skill") == 0) + program = PROG_SKILL; + else if (strcmp(program_invocation_short_name, "snice") == 0 || + strcmp(program_invocation_short_name, "lt-snice") == 0) + program = PROG_SNICE; - switch (program) { - case PROG_SNICE: - case PROG_SKILL: - setpriority(PRIO_PROCESS, my_pid, -20); - skillsnice_parse(argc, argv, &run_time); - if (run_time.debugging) - 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); - fprintf(stderr, USAGE_MAN_TAIL("skill(1)")); - return EXIT_FAILURE; - } - return EXIT_SUCCESS; + switch (program) { + case PROG_SNICE: + case PROG_SKILL: + setpriority(PRIO_PROCESS, my_pid, -20); + skillsnice_parse(argc, argv, &run_time); + if (run_time.debugging) + 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); + fprintf(stderr, USAGE_MAN_TAIL("skill(1)")); + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } diff --git a/top/top.c b/top/top.c index 90f04af5..710e95b2 100644 --- a/top/top.c +++ b/top/top.c @@ -47,6 +47,7 @@ #include // also available via #include "../include/fileutils.h" +#include "../include/signals.h" #include "../include/nls.h" #include "../proc/devname.h" @@ -54,7 +55,6 @@ #include "../proc/procps.h" #include "../proc/readproc.h" #include "../proc/readstat.h" -#include "../proc/sig.h" #include "../proc/sysinfo.h" #include "../proc/version.h" #include "../proc/wchan.h"