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
top/top_nls.h \
top/top_nls.c \
lib/fileutils.c
+ lib/signals.c
top_top_LDADD = $(LDADD) @NCURSES_LIBS@ $(DL_LIB)
endif
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
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=
proc/readproc.h \
proc/readstat.c \
proc/readstat.h \
- proc/sig.c \
- proc/sig.h \
proc/slab.c \
proc/slab.h \
proc/sysinfo.c \
proc/procps.h \
proc/pwcache.h \
proc/readproc.h \
- proc/sig.h \
proc/slab.h \
proc/sysinfo.h \
proc/uptime.h \
ps/select.c \
ps/sortformat.c \
ps/stacktrace.c \
- lib/fileutils.c
+ lib/fileutils.c \
+ lib/signals.c
# lib/test_* binaries
noinst_PROGRAMS = \
nls.h \
nsutils.h \
rpmatch.h \
+ signals.h \
strutils.h \
xalloc.h
* GNU Library General Public License for more details.
*/
-#include <proc/procps.h>
-
__BEGIN_DECLS
-/* return -1 on failure */
-extern int signal_name_to_number(const char *__restrict name);
-
-extern const char *signal_number_to_name(int signo);
+extern const int number_of_signals;
-extern int print_given_signals(int argc, const char *__restrict const *__restrict argv, int max_line);
+extern const char *get_sigtable_name(int row);
-extern char *strtosig(const char *__restrict s);
+extern const int get_sigtable_num(int row);
-extern void pretty_print_signals(void);
+/* return -1 on failure */
+extern int signal_name_to_number(const char *__restrict name);
-extern void unix_print_signals(void);
+extern const char *signal_number_to_name(int signo);
__END_DECLS
#endif
--- /dev/null
+/*
+ * 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 <ctype.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#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 <signal.h> 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 <signal.h> 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;
+}
+
#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 */
static int __attribute__ ((__noreturn__)) usage(int opt)
{
- int err = (opt == '?');
- FILE *fp = err ? stderr : stdout;
-
- fputs(USAGE_HEADER, fp);
- fprintf(fp, _(" %s [options] <pattern>\n"), program_invocation_short_name);
- fputs(USAGE_OPTIONS, fp);
- if (i_am_pkill == 0) {
- fputs(_(" -d, --delimiter <string> 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(_(" -<sig>, --signal <sig> 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 <PGID,...> match listed process group IDs\n"), fp);
- fputs(_(" -G, --group <GID,...> 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 <PPID,...> match only child processes of the given parent\n"), fp);
- fputs(_(" -s, --session <SID,...> match session IDs\n"), fp);
- fputs(_(" -t, --terminal <tty,...> match by controlling terminal\n"), fp);
- fputs(_(" -u, --euid <ID,...> match by effective IDs\n"), fp);
- fputs(_(" -U, --uid <ID,...> match by real IDs\n"), fp);
- fputs(_(" -x, --exact match exactly with the command name\n"), fp);
- fputs(_(" -F, --pidfile <file> read PIDs from file\n"), fp);
- fputs(_(" -L, --logpidfile fail if PID file is not locked\n"), fp);
- fputs(_(" --ns <PID> match the processes that belong to the same\n"
- " namespace as <pid>\n"), fp);
- fputs(_(" --nslist <ns,...> 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);
+ int err = (opt == '?');
+ FILE *fp = err ? stderr : stdout;
+
+ fputs(USAGE_HEADER, fp);
+ fprintf(fp, _(" %s [options] <pattern>\n"), program_invocation_short_name);
+ fputs(USAGE_OPTIONS, fp);
+ if (i_am_pkill == 0) {
+ fputs(_(" -d, --delimiter <string> 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(_(" -<sig>, --signal <sig> 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 <PGID,...> match listed process group IDs\n"), fp);
+ fputs(_(" -G, --group <GID,...> 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 <PPID,...> match only child processes of the given parent\n"), fp);
+ fputs(_(" -s, --session <SID,...> match session IDs\n"), fp);
+ fputs(_(" -t, --terminal <tty,...> match by controlling terminal\n"), fp);
+ fputs(_(" -u, --euid <ID,...> match by effective IDs\n"), fp);
+ fputs(_(" -U, --uid <ID,...> match by real IDs\n"), fp);
+ fputs(_(" -x, --exact match exactly with the command name\n"), fp);
+ fputs(_(" -F, --pidfile <file> read PIDs from file\n"), fp);
+ fputs(_(" -L, --logpidfile fail if PID file is not locked\n"), fp);
+ fputs(_(" --ns <PID> match the processes that belong to the same\n"
+ " namespace as <pid>\n"), fp);
+ fputs(_(" --nslist <ns,...> 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);
}
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;
-
- if (str[0] == '\0')
- return NULL;
-
- 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);
-
- free (copy);
- if (!i) {
- free (list);
- list = NULL;
- } else {
- list[0].num = i;
- }
- return list;
+ char *copy;
+ char *ptr;
+ char *sep_pos;
+ int i = 0;
+ int size = 0;
+ struct el *list = NULL;
+
+ if (str[0] == '\0')
+ return NULL;
+
+ 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);
+
+ 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;
-
- 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;
+ int res = 0;
+ int 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;
}
#include <sys/file.h>
* 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;
-
- 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;
+ 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;
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;
-
- 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;
+ struct passwd *pwd;
+
+ 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;
}
static int conv_gid (const char *restrict name, struct el *restrict e)
{
- struct group *grp;
-
- 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;
+ struct group *grp;
+
+ 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;
}
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;
-
- 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;
+ 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;
}
static regex_t * do_regcomp (void)
{
- regex_t *preg = NULL;
-
- 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;
- }
-
- re_err = regcomp (preg, re, REG_EXTENDED | REG_NOSUB | opt_case);
-
- if (opt_exact) free(re);
-
- if (re_err) {
- regerror (re_err, preg, errbuf, sizeof(errbuf));
- fputs(errbuf,stderr);
- exit (EXIT_USAGE);
- }
- }
- return preg;
+ regex_t *preg = NULL;
+
+ 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;
+ }
+
+ re_err = regcomp (preg, re, REG_EXTENDED | REG_NOSUB | opt_case);
+
+ if (opt_exact) free(re);
+
+ 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;
-
- ptp = do_openproc();
- preg = do_regcomp();
-
- 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);
- }
-
- 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;
-
- /* 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;
- }
- }
-
- 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 (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"));
- }
-
- // 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));
- }
- }
-
-
-
- }
-
-
-
-
-
- memset (&task, 0, sizeof (task));
- }
- closeproc (ptp);
- *num = matches;
- return list;
+ 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();
+
+ 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);
+ }
+
+ 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;
+
+ /* 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;
+ }
+ }
+
+ 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 (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"));
+ }
+
+ // 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));
+ }
+ }
+
+
+
+ }
+
+
+
+
+
+ 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;
-
- 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");
- }
-
- 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;
- }
- }
-
- 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 (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);
+ 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}
+ };
+
+ 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");
+
+ 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_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);
}
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);
-
- 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) */
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+ atexit(close_stdout);
+
+ 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) */
}
meminfo;
openproc;
page_bytes;
- pretty_print_signals;
print_uptime;
put_slabinfo;
readeither;
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;
+++ /dev/null
-/*
- * 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 <ctype.h>
-#include <signal.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#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 <signal.h> 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 <signal.h> 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;
-}
#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
#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;
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;
-
- 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);
-
- if (len == -1)
- break;
-
- ptr+= len + 1;
- }
- return 0;
+ 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);
+ }
+
+ 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;
+
+ 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;
-
- 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 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 CMD: ", cmd_count);
- if (cmds) {
- i = cmd_count;
- while (i--)
- fprintf(stderr, "%s%c", cmds[i], i ? ' ' : '\n');
- } else
- fprintf(stderr, "\n");
+ int i;
+
+ 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 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 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] <pid> [...]\n"), program_invocation_short_name);
- fputs(USAGE_OPTIONS, out);
- fputs(_(" <pid> [...] send signal to every <pid> listed\n"), out);
- fputs(_(" -<signal>, -s, --signal <signal>\n"
- " specify the <signal> to be sent\n"), out);
- fputs(_(" -l, --list=[<signal>] 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(_(" <pid> [...] send signal to every <pid> listed\n"), out);
+ fputs(_(" -<signal>, -s, --signal <signal>\n"
+ " specify the <signal> to be sent\n"), out);
+ fputs(_(" -l, --list=[<signal>] 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);
-
- if (program == PROG_SKILL) {
- fprintf(out,
- _(" %s [signal] [options] <expression>\n"),
- program_invocation_short_name);
- } else {
- fprintf(out,
- _(" %s [new priority] [options] <expression>\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 <command> expression is a command name\n"), out);
- fputs(_(" -p, --pid <pid> expression is a process id number\n"), out);
- fputs(_(" -t, --tty <tty> expression is a terminal\n"), out);
- fputs(_(" -u, --user <username> expression is a username\n"), out);
- fputs(USAGE_SEPARATOR, out);
- fputs(_("Alternatively, expression can be:\n"), out);
- fputs(_(" --ns <pid> match the processes that belong to the same\n"
- " namespace as <pid>\n"), out);
- fputs(_(" --nslist <ns,...> 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_HEADER, out);
+
+ if (program == PROG_SKILL) {
+ fprintf(out,
+ _(" %s [signal] [options] <expression>\n"),
+ program_invocation_short_name);
+ } else {
+ fprintf(out,
+ _(" %s [new priority] [options] <expression>\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 <command> expression is a command name\n"), out);
+ fputs(_(" -p, --pid <pid> expression is a process id number\n"), out);
+ fputs(_(" -t, --tty <tty> expression is a terminal\n"), out);
+ fputs(_(" -u, --user <username> expression is a username\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Alternatively, expression can be:\n"), out);
+ fputs(_(" --ns <pid> match the processes that belong to the same\n"
+ " namespace as <pid>\n"), out);
+ fputs(_(" --nslist <ns,...> 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);
}
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;
-
- static const struct option longopts[] = {
- {"list", optional_argument, NULL, 'l'},
- {"table", no_argument, NULL, 'L'},
- {"signal", required_argument, NULL, 's'},
- {"help", no_argument, NULL, 'h'},
- {"version", no_argument, NULL, 'V'},
- {NULL, 0, NULL, 0}
- };
-
- setlocale (LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
- atexit(close_stdout);
-
- if (argc < 2)
- kill_usage(stderr);
-
- signo = skill_sig_option(&argc, argv);
- if (signo < 0)
- signo = SIGTERM;
- else
- sigopt++;
-
- opterr=0; /* suppress errors on -123 */
- while (loop == 1 && (i = getopt_long(argc, argv, "l::Ls:hV", longopts, NULL)) != -1)
- switch (i) {
- case 'l':
- if (optarg) {
- char *s;
- s = strtosig(optarg);
- if (s)
- printf("%s\n", s);
- else
- xwarnx(_("unknown signal name %s"),
- optarg);
- free(s);
- } else {
- unix_print_signals();
- }
- exit(EXIT_SUCCESS);
- case 'L':
- pretty_print_signals();
- exit(EXIT_SUCCESS);
- case 's':
- signo = signal_name_to_number(optarg);
- break;
- case 'h':
- kill_usage(stdout);
- case 'V':
- display_kill_version();
- exit(EXIT_SUCCESS);
- case '?':
- if (!isdigit(optopt)) {
- xwarnx(_("invalid argument %c"), optopt);
- kill_usage(stderr);
- } else {
- /* Special case for signal digit negative
- * PIDs */
- pid = (long)('0' - optopt);
- if (kill((pid_t)pid, signo) != 0)
- exitvalue = EXIT_FAILURE;
- exit(exitvalue);
- }
- loop=0;
- break;
- default:
- kill_usage(stderr);
- }
-
- argc -= optind + sigopt;
- argv += optind;
-
- for (i = 0; i < argc; i++) {
- pid = strtol_or_err(argv[i], _("failed to parse argument"));
- if (!kill((pid_t) pid, signo))
- continue;
- exitvalue = EXIT_FAILURE;
- continue;
- }
-
- exit(exitvalue);
+ int signo, i;
+ int sigopt = 0;
+ int loop = 1;
+ long pid;
+ int exitvalue = EXIT_SUCCESS;
+
+ static const struct option longopts[] = {
+ {"list", optional_argument, NULL, 'l'},
+ {"table", no_argument, NULL, 'L'},
+ {"signal", required_argument, NULL, 's'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'V'},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+ atexit(close_stdout);
+
+ if (argc < 2)
+ kill_usage(stderr);
+
+ signo = skill_sig_option(&argc, argv);
+ if (signo < 0)
+ signo = SIGTERM;
+ else
+ sigopt++;
+
+ opterr=0; /* suppress errors on -123 */
+ while (loop == 1 && (i = getopt_long(argc, argv, "l::Ls:hV", longopts, NULL)) != -1)
+ switch (i) {
+ case 'l':
+ if (optarg) {
+ char *s;
+ s = strtosig(optarg);
+ if (s)
+ printf("%s\n", s);
+ else
+ xwarnx(_("unknown signal name %s"),
+ optarg);
+ free(s);
+ } else {
+ unix_print_signals();
+ }
+ exit(EXIT_SUCCESS);
+ case 'L':
+ pretty_print_signals();
+ exit(EXIT_SUCCESS);
+ case 's':
+ signo = signal_name_to_number(optarg);
+ break;
+ case 'h':
+ kill_usage(stdout);
+ case 'V':
+ display_kill_version();
+ exit(EXIT_SUCCESS);
+ case '?':
+ if (!isdigit(optopt)) {
+ xwarnx(_("invalid argument %c"), optopt);
+ kill_usage(stderr);
+ } else {
+ /* Special case for signal digit negative
+ * PIDs */
+ pid = (long)('0' - optopt);
+ if (kill((pid_t)pid, signo) != 0)
+ exitvalue = EXIT_FAILURE;
+ exit(exitvalue);
+ }
+ loop=0;
+ break;
+ default:
+ kill_usage(stderr);
+ }
+
+ argc -= optind + sigopt;
+ argv += optind;
+
+ for (i = 0; i < argc; i++) {
+ pid = strtol_or_err(argv[i], _("failed to parse argument"));
+ if (!kill((pid_t) pid, signo))
+ continue;
+ exitvalue = EXIT_FAILURE;
+ continue;
+ }
+
+ exit(exitvalue);
}
#if 0
static void _skillsnice_usage(int line)
{
- fprintf(stderr, _("something at line %d\n"), line);
- skillsnice_usage(stderr);
+ fprintf(stderr, _("something at line %d\n"), line);
+ skillsnice_usage(stderr);
}
#define skillsnice_usage() _skillsnice_usage(__LINE__)
static int snice_prio_option(int *argc, char **argv)
{
- 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;
+ 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;
}
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;
-
- 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}
- };
-
- if (argc < 2)
- skillsnice_usage(stderr);
-
- 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;
- }
- }
-
- 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);
- }
-
- 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;
-
- 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;
+ int signo = -1;
+ int prino = DEFAULT_NICE;
+ int ch, i;
+
+ 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}
+ };
+
+ if (argc < 2)
+ skillsnice_usage(stderr);
+
+ 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;
+ }
+ }
+
+ 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);
+ }
+
+ 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;
+
+ 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;
}
/* 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();
-
- 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;
+ 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;
+
+ 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;
}
#include <sys/types.h> // also available via <stdlib.h>
#include "../include/fileutils.h"
+#include "../include/signals.h"
#include "../include/nls.h"
#include "../proc/devname.h"
#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"