2 * killall.c - kill processes by name or list PIDs
4 * Copyright (C) 1993-2002 Werner Almesberger
5 * Copyright (C) 2002-2007 Craig Small
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
39 #include <sys/types.h>
46 #include <selinux/selinux.h>
47 #endif /*WITH_SELINUX*/
54 #define PROC_BASE "/proc"
55 #define MAX_NAMES (int)(sizeof(unsigned long)*8)
58 static int verbose = 0, exact = 0, interactive = 0, reg = 0,
59 quiet = 0, wait_until_dead = 0, process_group = 0,
60 ignore_case = 0, pidof;
63 ask (char *name, pid_t pid, const int signal)
73 if (signal == SIGTERM)
74 printf (_("Kill %s(%s%d) ? (y/N) "), name, process_group ? "pgid " : "",
77 printf (_("Signal %s(%s%d) ? (y/N) "), name, process_group ? "pgid " : "",
82 if (getline (&line, &len, stdin) < 0)
84 /* Check for default */
85 if (line[0] == '\n') {
95 /* Never should get here */
99 match_process_uid(pid_t pid, uid_t uid)
106 snprintf (buf, sizeof buf, PROC_BASE "/%d/status", pid);
107 if (!(f = fopen (buf, "r")))
110 while (fgets(buf, sizeof buf, f))
112 if (sscanf (buf, "Uid:\t%d", &puid))
121 fprintf(stderr, _("Cannot get UID from process status\n"));
128 build_regexp_list(int names, char **namelist)
132 int flag = REG_EXTENDED|REG_NOSUB;
134 if (!(reglist = malloc (sizeof (regex_t) * names)))
143 for (i = 0; i < names; i++)
145 if (regcomp(®list[i], namelist[i], flag) != 0)
147 fprintf(stderr, _("Bad regular expression: %s\n"), namelist[i]);
156 kill_all(int signal, int names, char **namelist, struct passwd *pwent,
158 #else /*WITH_SELINUX*/
160 kill_all (int signal, int names, char **namelist, struct passwd *pwent)
161 #endif /*WITH_SELINUX*/
166 struct stat st, sts[MAX_NAMES];
167 int *name_len = NULL;
168 char *path, comm[COMM_LEN];
171 pid_t *pid_table, pid, self, *pid_killed;
173 int i, j, okay, length, got_long, error;
174 int pids, max_pids, pids_killed;
176 regex_t *reglist = NULL;;
178 security_context_t lcontext=NULL;
179 #endif /*WITH_SELINUX*/
182 reglist = build_regexp_list(names, namelist);
185 if (!(name_len = malloc (sizeof (int) * names)))
190 for (i = 0; i < names; i++)
192 if (!strchr (namelist[i], '/'))
195 name_len[i] = strlen (namelist[i]);
197 else if (stat (namelist[i], &sts[i]) < 0)
199 perror (namelist[i]);
206 if (!(dir = opendir (PROC_BASE)))
212 pid_table = malloc (max_pids * sizeof (pid_t));
219 while ( (de = readdir (dir)) != NULL)
221 if (!(pid = (pid_t) atoi (de->d_name)) || pid == self)
223 if (pids == max_pids)
225 if (!(pid_table = realloc (pid_table, 2 * pids * sizeof (pid_t))))
232 pid_table[pids++] = pid;
234 (void) closedir (dir);
236 pid_killed = malloc (max_pids * sizeof (pid_t));
243 pgids = NULL; /* silence gcc */
246 pgids = malloc (pids * sizeof (pid_t));
253 for (i = 0; i < pids; i++)
259 if (pwent && match_process_uid(pid_table[i], pwent->pw_uid)==0)
262 /* match by SELinux context */
265 if (getpidcon(pid_table[i], &lcontext) < 0)
267 if (regexec(scontext, lcontext, 0, NULL, 0) != 0) {
273 #endif /*WITH_SELINUX*/
274 /* load process name */
275 if (asprintf (&path, PROC_BASE "/%d/stat", pid_table[i]) < 0)
277 if (!(file = fopen (path, "r")))
283 okay = fscanf (file, "%*d (%15[^)]", comm) == 1;
284 (void) fclose (file);
288 command = NULL; /* make gcc happy */
289 length = strlen (comm);
290 if (length == COMM_LEN - 1)
292 if (asprintf (&path, PROC_BASE "/%d/cmdline", pid_table[i]) < 0)
294 if (!(file = fopen (path, "r"))) {
300 /* look for actual command so we skip over initial "sh" if any */
303 command_buf = (char *)malloc (cmd_size);
307 /* 'cmdline' has arguments separated by nulls */
308 for (p=command_buf; ; p++) {
310 if (p == (command_buf + cmd_size))
312 int cur_size = cmd_size;
314 command_buf = (char *)realloc(command_buf, cmd_size);
317 p = command_buf + cur_size;
320 if (c == EOF || c == '\0') {
327 if (strlen(command_buf) == 0) {
331 p = strrchr(command_buf,'/');
332 p = p ? p+1 : command_buf;
333 if (strncmp(p, comm, COMM_LEN-1) == 0) {
343 fprintf (stderr, _("skipping partial match %s(%d)\n"), comm,
349 /* mach by process name */
350 for (j = 0; j < names; j++)
354 if (regexec (®list[j], got_long ? command : comm, 0, NULL, 0) != 0)
361 if (length != COMM_LEN - 1 || name_len[j] < COMM_LEN - 1)
363 if (ignore_case == 1)
365 if (strcasecmp (namelist[j], comm))
370 if (strcmp(namelist[j], comm))
374 else if (got_long ? strcmp (namelist[j], command) :
375 strncmp (namelist[j], comm, COMM_LEN - 1))
382 if (asprintf (&path, PROC_BASE "/%d/exe", pid_table[i]) < 0)
385 if (stat (path, &st) < 0)
388 else if (sts[j].st_dev != st.st_dev ||
389 sts[j].st_ino != st.st_ino)
391 /* maybe the binary has been modified and std[j].st_ino
392 * is not reliable anymore. We need to compare paths.
394 char linkbuf[PATH_MAX];
396 if (readlink(path, linkbuf, sizeof(linkbuf)) <= 0 ||
397 strcmp(namelist[j], linkbuf))
410 if (names && found_name==-1)
411 continue; /* match by process name faild */
413 /* check for process group */
420 id = getpgid (pid_table[i]);
424 fprintf (stderr, "getpgid(%d): %s\n", pid_table[i],
427 for (j = 0; j < i; j++)
433 if (interactive && !ask (comm, id, signal))
440 found |= 1 << (found_name >= 0 ? found_name : 0);
442 else if (kill (process_group ? -id : id, signal) >= 0)
445 fprintf (stderr, _("Killed %s(%s%d) with signal %d\n"), got_long ? command :
446 comm, process_group ? "pgid " : "", id, signal);
448 /* mark item of namelist */
449 found |= 1 << found_name;
450 pid_killed[pids_killed++] = id;
452 else if (errno != ESRCH || interactive)
453 fprintf (stderr, "%s(%d): %s\n", got_long ? command :
454 comm, id, strerror (errno));
456 if (!quiet && !pidof)
457 for (i = 0; i < names; i++)
458 if (!(found & (1 << i)))
459 fprintf (stderr, _("%s: no process killed\n"), namelist[i]);
463 /* killall returns a zero return code if at least one process has
464 * been killed for each listed command. */
465 error = found == ((1 << (names - 1)) | ((1 << (names - 1)) - 1)) ? 0 : 1;
467 /* in nameless mode killall returns a zero return code if at least
468 * one process has killed */
469 error = pids_killed ? 0 : 1;
471 * We scan all (supposedly) killed processes every second to detect dead
472 * processes as soon as possible in order to limit problems of race with
475 while (pids_killed && wait_until_dead)
477 for (i = 0; i < pids_killed;)
479 if (kill (process_group ? -pid_killed[i] : pid_killed[i], 0) < 0 &&
482 pid_killed[i] = pid_killed[--pids_killed];
487 sleep (1); /* wait a bit longer */
497 "Usage: pidof [ -eg ] NAME...\n"
499 " -e require exact match for very long names;\n"
500 " skip if the command line is unavailable\n"
501 " -g show process group ID instead of process ID\n"
502 " -V display version information\n\n"));
511 "Usage: killall [-Z CONTEXT] [-u USER] [ -eIgiqrvw ] [ -SIGNAL ] NAME...\n"));
512 #else /*WITH_SELINUX*/
514 "Usage: killall [OPTION]... [--] NAME...\n"));
515 #endif /*WITH_SELINUX*/
517 " killall -l, --list\n"
518 " killall -V, --version\n\n"
519 " -e,--exact require exact match for very long names\n"
520 " -I,--ignore-case case insensitive process name match\n"
521 " -g,--process-group kill process group instead of process\n"
522 " -i,--interactive ask for confirmation before killing\n"
523 " -l,--list list all known signal names\n"
524 " -q,--quiet don't print complaints\n"
525 " -r,--regexp interpret NAME as an extended regular expression\n"
526 " -s,--signal SIGNAL send this signal instead of SIGTERM\n"
527 " -u,--user USER kill only process(es) running as USER\n"
528 " -v,--verbose report if the signal was successfully sent\n"
529 " -V,--version display version information\n"
530 " -w,--wait wait for processes to die\n"));
533 " -Z,--context REGEXP kill only process(es) having context\n"
534 " (must precede other arguments)\n"));
535 #endif /*WITH_SELINUX*/
552 fprintf(stderr, "%s (PSmisc) %s\n", pidof ? "pidof" : "killall", VERSION);
554 "Copyright (C) 1993-2005 Werner Almesberger and Craig Small\n\n"));
556 "PSmisc comes with ABSOLUTELY NO WARRANTY.\n"
557 "This is free software, and you are welcome to redistribute it under\n"
558 "the terms of the GNU General Public License.\n"
559 "For more information about these matters, see the files named COPYING.\n"));
563 main (int argc, char **argv)
569 struct passwd *pwent = NULL;
574 struct option options[] = {
575 {"exact", 0, NULL, 'e'},
576 {"ignore-case", 0, NULL, 'I'},
577 {"process-group", 0, NULL, 'g'},
578 {"interactive", 0, NULL, 'i'},
579 {"list-signals", 0, NULL, 'l'},
580 {"quiet", 0, NULL, 'q'},
581 {"regexp", 0, NULL, 'r'},
582 {"signal", 1, NULL, 's'},
583 {"user", 1, NULL, 'u'},
584 {"verbose", 0, NULL, 'v'},
585 {"wait", 0, NULL, 'w'},
587 {"context", 1, NULL, 'Z'},
588 #endif /*WITH_SELINUX*/
589 {"version", 0, NULL, 'V'},
594 setlocale(LC_ALL, "");
595 bindtextdomain(PACKAGE, LOCALEDIR);
599 security_context_t scontext = NULL;
600 regex_t scontext_reg;
602 if ( argc < 2 ) usage(); /* do the obvious thing... */
603 #endif /*WITH_SELINUX*/
605 name = strrchr (*argv, '/');
610 pidof = strcmp (name, "killall");
616 while ( (optc = getopt_long_only(argc,argv,"egilqrs:u:vwZ:VI",options,NULL)) != EOF) {
618 while ( (optc = getopt_long_only(argc,argv,"egilqrs:u:vwVI",options,NULL)) != EOF) {
649 sig_num = get_signal (optarg, "killall");
654 if (!(pwent = getpwnam(optarg)))
656 fprintf (stderr, _("Cannot find user %s\n"), optarg);
679 if (is_selinux_enabled()>0) {
681 if (regcomp(&scontext_reg, scontext, REG_EXTENDED|REG_NOSUB) != 0) {
682 fprintf(stderr, _("Bad regular expression: %s\n"), scontext);
686 fprintf(stderr, "Warning: -Z (--context) ignored. Requires an SELinux enabled kernel\n");
688 #endif /*WITH_SELINUX*/
690 /* Signal names are in uppercase, so check to see if the argv
692 if (argv[optind-1][1] >= 'A' && argv[optind-1][1] <= 'Z') {
693 sig_num = get_signal (argv[optind-1]+1, "killall");
695 /* Might also be a -## signal too */
696 if (argv[optind-1][1] >= '0' && argv[optind-1][1] <= '9') {
697 sig_num = atoi(argv[optind-1]+1);
707 if ((argc - myoptind < 1) && pwent==NULL && scontext==NULL)
709 if ((argc - myoptind < 1) && pwent==NULL)
713 if (argc - myoptind > MAX_NAMES + 1)
715 fprintf (stderr, _("Maximum number of names is %d\n"), MAX_NAMES);
718 if (stat("/proc/self/stat", &isproc)==-1)
720 fprintf (stderr, _("%s is empty (not mounted ?)\n"), PROC_BASE);
723 argv = argv + myoptind;
724 /*printf("sending signal %d to procs\n", sig_num);*/
726 return kill_all(sig_num,argc - myoptind, argv, pwent,
727 scontext ? &scontext_reg : NULL);
728 #else /*WITH_SELINUX*/
729 return kill_all(sig_num,argc - myoptind, argv, pwent);
730 #endif /*WITH_SELINUX*/