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"