1 /*
2 * killall.c - kill processes by name or list PIDs
3 *
4 * Copyright (C) 1993-2002 Werner Almesberger
5 * Copyright (C) 2002-2007 Craig Small
6 *
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.
11 *
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.
16 *
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
20 */
21
22
23 #ifndef _GNU_SOURCE
24 #define _GNU_SOURCE
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <dirent.h>
37 #include <signal.h>
38 #include <errno.h>
39 #include <limits.h>
40 #include <locale.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <getopt.h>
44 #include <pwd.h>
45 #include <regex.h>
46 #include <ctype.h>
47 #include <assert.h>
48
49 #ifdef WITH_SELINUX
50 #include <selinux/selinux.h>
51 #endif /*WITH_SELINUX*/
52
53 #ifdef HAVE_LOCALE_H
54 #include <locale.h>
55 #endif /* HAVE_LOCALE_H */
56
57 #include "i18n.h"
58 #include "comm.h"
59 #include "signals.h"
60
61 #define PROC_BASE "/proc"
62 #define MAX_NAMES (int)(sizeof(unsigned long)*8)
63
64 #define TSECOND "s"
65 #define TMINUTE "m"
66 #define THOUR "h"
67 #define TDAY "d"
68 #define TWEEK "w"
69 #define TMONTH "M"
70 #define TYEAR "y"
71
72 #define TMAX_SECOND 31536000
73 #define TMAX_MINUTE 525600
74 #define TMAX_HOUR 8760
75 #define TMAX_DAY 365
76 #define TMAX_WEEK 48
77 #define TMAX_MONTH 12
78 #define TMAX_YEAR 1
79
80 #define ER_REGFAIL -1
81 #define ER_NOMEM -2
82 #define ER_UNKWN -3
83 #define ER_OOFRA -4
84
85 #define NOT_PIDOF_OPTION if (pidof) usage(NULL)
86
87 static int verbose = 0, exact = 0, interactive = 0, reg = 0,
88 quiet = 0, wait_until_dead = 0, process_group = 0,
89 ignore_case = 0, pidof;
90 static long younger_than = 0, older_than = 0;
91
92 /*
93 * This is based on the implementation from 21.5, as the one in 21.6
94 * and newer uses Linux specific functions getline() and rpmatch()
95 */
96 static int
ask(char * name,pid_t pid,const int signal)97 ask (char *name, pid_t pid, const int signal)
98 {
99 int ch, c;
100
101 do
102 {
103 if (signal == SIGTERM)
104 printf (_("Kill %s(%s%d) ? (y/N) "), name, process_group ? "pgid " : "",
105 pid);
106 else
107 printf (_("Signal %s(%s%d) ? (y/N) "), name, process_group ? "pgid " : "",
108 pid);
109 fflush (stdout);
110 do
111 if ((ch = getchar ()) == EOF)
112 exit (0);
113 while (ch == '\n' || ch == '\t' || ch == ' ');
114 do
115 if ((c = getchar ()) == EOF)
116 exit (0);
117 while (c != '\n');
118 }
119 while (ch != 'y' && ch != 'n' && ch != 'Y' && ch != 'N');
120 return ch == 'y' || ch == 'Y';
121 }
122
123 static double
uptime()124 uptime()
125 {
126 char * savelocale;
127 char buf[2048];
128 FILE* file;
129 if (!(file=fopen( PROC_BASE "/uptime", "r"))) {
130 fprintf(stderr, "error opening uptime file\n");
131 exit(1);
132 }
133 savelocale = setlocale(LC_NUMERIC, NULL);
134 setlocale(LC_NUMERIC,"C");
135 if (fscanf(file, "%2047s", buf) == EOF) perror("uptime");
136 fclose(file);
137 setlocale(LC_NUMERIC,savelocale);
138 return atof(buf);
139 }
140
141 /* process age from jiffies to seconds via uptime */
process_age(const unsigned long long jf)142 static double process_age(const unsigned long long jf)
143 {
144 double sc_clk_tck = sysconf(_SC_CLK_TCK);
145 assert(sc_clk_tck > 0);
146 return uptime() - jf / sc_clk_tck;
147 }
148
149 /* returns requested time interval in seconds,
150 negative indicates error has occured
151 */
152 static long
parse_time_units(const char * age)153 parse_time_units(const char* age)
154 {
155 char *unit;
156 long num;
157
158 num = strtol(age,&unit,10);
159 if (age == unit) /* no digits found */
160 return -1;
161 if (unit[0] == '\0') /* no units found */
162 return -1;
163
164 switch(unit[0]) {
165 case 's':
166 return num;
167 case 'm':
168 return (num * 60);
169 case 'h':
170 return (num * 60 * 60);
171 case 'd':
172 return (num * 60 * 60 * 24);
173 case 'w':
174 return (num * 60 * 60 * 24 * 7);
175 case 'M':
176 return (num * 60 * 60 * 24 * 7 * 4);
177 case 'y':
178 return (num * 60 * 60 * 24 * 7 * 4 * 12);
179 }
180 return -1;
181 }
182
183 static int
match_process_uid(pid_t pid,uid_t uid)184 match_process_uid(pid_t pid, uid_t uid)
185 {
186 char buf[128];
187 uid_t puid;
188 FILE *f;
189 int re = -1;
190
191 snprintf (buf, sizeof buf, PROC_BASE "/%d/status", pid);
192 if (!(f = fopen (buf, "r")))
193 return 0;
194
195 while (fgets(buf, sizeof buf, f))
196 {
197 if (sscanf (buf, "%*s %*d %*d %*d %*d %*s %*s %*s %*s %*s %*s %*s %d", &puid))
198 {
199 re = uid==puid;
200 break;
201 }
202 }
203 fclose(f);
204 if (re==-1)
205 {
206 fprintf(stderr, _("Cannot get UID from process status\n"));
207 exit(1);
208 }
209 return re;
210 }
211
212 static regex_t *
build_regexp_list(int names,char ** namelist)213 build_regexp_list(int names, char **namelist)
214 {
215 int i;
216 regex_t *reglist;
217 int flag = REG_EXTENDED|REG_NOSUB;
218
219 if (!(reglist = malloc (sizeof (regex_t) * names)))
220 {
221 perror ("malloc");
222 exit (1);
223 }
224
225 if (ignore_case)
226 flag |= REG_ICASE;
227
228 for (i = 0; i < names; i++)
229 {
230 if (regcomp(®list[i], namelist[i], flag) != 0)
231 {
232 fprintf(stderr, _("Bad regular expression: %s\n"), namelist[i]);
233 exit (1);
234 }
235 }
236 return reglist;
237 }
238
239 #ifdef WITH_SELINUX
240 static int
kill_all(int signal,int names,char ** namelist,struct passwd * pwent,regex_t * scontext)241 kill_all(int signal, int names, char **namelist, struct passwd *pwent,
242 regex_t *scontext )
243 #else /*WITH_SELINUX*/
244 static int
245 kill_all (int signal, int names, char **namelist, struct passwd *pwent)
246 #endif /*WITH_SELINUX*/
247 {
248 DIR *dir;
249 struct dirent *de;
250 FILE *file;
251 struct stat st, sts[MAX_NAMES];
252 int *name_len = NULL;
253 char *path, comm[COMM_LEN];
254 char *command_buf;
255 char *command;
256 pid_t *pid_table, pid, self, *pid_killed;
257 pid_t *pgids;
258 int i, j, okay, length, got_long, error;
259 int pids, max_pids, pids_killed;
260 unsigned long found;
261 regex_t *reglist = NULL;;
262 #ifdef WITH_SELINUX
263 security_context_t lcontext=NULL;
264 #endif /*WITH_SELINUX*/
265
266 if (names && reg)
267 reglist = build_regexp_list(names, namelist);
268 else if (names)
269 {
270 if (!(name_len = malloc (sizeof (int) * names)))
271 {
272 perror ("malloc");
273 exit (1);
274 }
275 for (i = 0; i < names; i++)
276 {
277 if (!strchr (namelist[i], '/'))
278 {
279 sts[i].st_dev = 0;
280 name_len[i] = strlen (namelist[i]);
281 }
282 else if (stat (namelist[i], &sts[i]) < 0)
283 {
284 perror (namelist[i]);
285 exit (1);
286 }
287 }
288 }
289 self = getpid ();
290 found = 0;
291 if (!(dir = opendir (PROC_BASE)))
292 {
293 perror (PROC_BASE);
294 exit (1);
295 }
296 max_pids = 256;
297 pid_table = malloc (max_pids * sizeof (pid_t));
298 if (!pid_table)
299 {
300 perror ("malloc");
301 exit (1);
302 }
303 pids = 0;
304 while ( (de = readdir (dir)) != NULL)
305 {
306 if (!(pid = (pid_t) atoi (de->d_name)) || pid == self)
307 continue;
308 if (pids == max_pids)
309 {
310 if (!(pid_table = realloc (pid_table, 2 * pids * sizeof (pid_t))))
311 {
312 perror ("realloc");
313 exit (1);
314 }
315 max_pids *= 2;
316 }
317 pid_table[pids++] = pid;
318 }
319 (void) closedir (dir);
320 pids_killed = 0;
321 pid_killed = malloc (max_pids * sizeof (pid_t));
322 if (!pid_killed)
323 {
324 perror ("malloc");
325 exit (1);
326 }
327 if (!process_group)
328 pgids = NULL; /* silence gcc */
329 else
330 {
331 pgids = calloc (pids, sizeof (pid_t));
332 if (!pgids)
333 {
334 perror ("malloc");
335 exit (1);
336 }
337 }
338 for (i = 0; i < pids; i++)
339 {
340 pid_t id;
341 int found_name = -1;
342 double process_age_sec = 0;
343 /* match by UID */
344 if (pwent && match_process_uid(pid_table[i], pwent->pw_uid)==0)
345 continue;
346 #ifdef WITH_SELINUX
347 /* match by SELinux context */
348 if (scontext)
349 {
350 if (getpidcon(pid_table[i], &lcontext) < 0)
351 continue;
352 if (regexec(scontext, lcontext, 0, NULL, 0) != 0) {
353 freecon(lcontext);
354 continue;
355 }
356 freecon(lcontext);
357 }
358 #endif /*WITH_SELINUX*/
359 /* load process name */
360 if (asprintf (&path, PROC_BASE "/%d/status", pid_table[i]) < 0)
361 continue;
362 if (!(file = fopen (path, "r")))
363 {
364 free (path);
365 continue;
366 }
367 free (path);
368 okay = fscanf (file, "%s", comm) == 1;
369 if (!okay) {
370 fclose(file);
371 continue;
372 }
373 if ( younger_than || older_than ) {
374 rewind(file);
375 unsigned long long proc_stt_jf = 0;
376 okay = fscanf(file, "%*d %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %Lu",
377 &proc_stt_jf) == 1;
378 if (!okay) {
379 fclose(file);
380 continue;
381 }
382 process_age_sec = process_age(proc_stt_jf);
383 assert(process_age_sec > 0);
384 }
385 (void) fclose (file);
386
387 got_long = 0;
388 command = NULL; /* make gcc happy */
389 length = strlen (comm);
390 /* mach by process name */
391 for (j = 0; j < names; j++)
392 {
393 if (reg)
394 {
395 if (regexec (®list[j], got_long ? command : comm, 0, NULL, 0) != 0)
396 continue;
397 }
398 else /* non-regex */
399 {
400 if ( younger_than && process_age_sec && (process_age_sec > younger_than ) )
401 continue;
402 if ( older_than && process_age_sec && (process_age_sec < older_than ) )
403 continue;
404
405 if (!sts[j].st_dev)
406 {
407 if (length != COMM_LEN - 1 || name_len[j] < COMM_LEN - 1)
408 {
409 if (ignore_case == 1)
410 {
411 if (strcasecmp (namelist[j], comm))
412 continue;
413 }
414 else
415 {
416 if (strcmp(namelist[j], comm))
417 continue;
418 }
419 }
420 else
421 {
422 if (ignore_case == 1)
423 {
424 if (got_long ? strcasecmp (namelist[j], command) :
425 strncasecmp (namelist[j], comm, COMM_LEN - 1))
426 continue;
427 }
428 else
429 {
430 if (got_long ? strcmp (namelist[j], command) :
431 strncmp (namelist[j], comm, COMM_LEN - 1))
432 continue;
433 }
434 }
435 }
436 else
437 {
438 int ok = 1;
439
440 if (asprintf (&path, PROC_BASE "/%d/file", pid_table[i]) < 0)
441 continue;
442
443 if (stat (path, &st) < 0)
444 ok = 0;
445
446 else if (sts[j].st_dev != st.st_dev ||
447 sts[j].st_ino != st.st_ino)
448 {
449 /* maybe the binary has been modified and std[j].st_ino
450 * is not reliable anymore. We need to compare paths.
451 */
452 size_t len = strlen(namelist[j]);
453 char *linkbuf = malloc(len + 1);
454
455 if (!linkbuf ||
456 readlink(path, linkbuf, len + 1) != len ||
457 memcmp(namelist[j], linkbuf, len))
458 ok = 0;
459 free(linkbuf);
460 }
461
462 free(path);
463 if (!ok)
464 continue;
465 }
466 } /* non-regex */
467 found_name = j;
468 break;
469 }
470
471 if (names && found_name==-1)
472 continue; /* match by process name faild */
473
474 /* check for process group */
475 if (!process_group)
476 id = pid_table[i];
477 else
478 {
479 int j;
480
481 id = getpgid (pid_table[i]);
482 pgids[i] = id;
483 if (id < 0)
484 {
485 fprintf (stderr, "getpgid(%d): %s\n", pid_table[i],
486 strerror (errno));
487 }
488 for (j = 0; j < i; j++)
489 if (pgids[j] == id)
490 break;
491 if (j < i)
492 continue;
493 }
494 if (interactive && !ask (comm, id, signal))
495 continue;
496 if (pidof)
497 {
498 if (found)
499 putchar (' ');
500 printf ("%d", id);
501 found |= 1 << (found_name >= 0 ? found_name : 0);
502 }
503 else if (kill (process_group ? -id : id, signal) >= 0)
504 {
505 if (verbose)
506 fprintf (stderr, _("Killed %s(%s%d) with signal %d\n"), got_long ? command :
507 comm, process_group ? "pgid " : "", id, signal);
508 if (found_name >= 0)
509 /* mark item of namelist */
510 found |= 1 << found_name;
511 pid_killed[pids_killed++] = id;
512 }
513 else if (errno != ESRCH || interactive)
514 fprintf (stderr, "%s(%d): %s\n", got_long ? command :
515 comm, id, strerror (errno));
516 }
517 if (!quiet && !pidof)
518 for (i = 0; i < names; i++)
519 if (!(found & (1 << i)))
520 fprintf (stderr, _("%s: no process found\n"), namelist[i]);
521 if (pidof)
522 putchar ('\n');
523 if (names)
524 /* killall returns a zero return code if at least one process has
525 * been killed for each listed command. */
526 error = found == ((1 << (names - 1)) | ((1 << (names - 1)) - 1)) ? 0 : 1;
527 else
528 /* in nameless mode killall returns a zero return code if at least
529 * one process has killed */
530 error = pids_killed ? 0 : 1;
531 /*
532 * We scan all (supposedly) killed processes every second to detect dead
533 * processes as soon as possible in order to limit problems of race with
534 * PID re-use.
535 */
536 while (pids_killed && wait_until_dead)
537 {
538 for (i = 0; i < pids_killed;)
539 {
540 if (kill (process_group ? -pid_killed[i] : pid_killed[i], 0) < 0 &&
541 errno == ESRCH)
542 {
543 pid_killed[i] = pid_killed[--pids_killed];
544 continue;
545 }
546 i++;
547 }
548 sleep (1); /* wait a bit longer */
549 }
550 return error;
551 }
552
553
554 static void
usage_pidof(void)555 usage_pidof (void)
556 {
557 fprintf (stderr, _(
558 "Usage: pidof [ -eg ] NAME...\n"
559 " pidof -V\n\n"
560 " -e require exact match for very long names;\n"
561 " skip if the command line is unavailable\n"
562 " -g show process group ID instead of process ID\n"
563 " -V display version information\n\n"));
564 }
565
566
567 static void
usage_killall(const char * msg)568 usage_killall (const char *msg)
569 {
570 if (msg != NULL)
571 fprintf(stderr, "%s\n", msg);
572 #ifdef WITH_SELINUX
573 fprintf(stderr, _(
574 "Usage: killall [-Z CONTEXT] [-u USER] [ -eIgiqrvw ] [ -SIGNAL ] NAME...\n"));
575 #else /*WITH_SELINUX*/
576 fprintf(stderr, _(
577 "Usage: killall [OPTION]... [--] NAME...\n"));
578 #endif /*WITH_SELINUX*/
579 fprintf(stderr, _(
580 " killall -l, --list\n"
581 " killall -V, --version\n\n"
582 " -e,--exact require exact match for very long names\n"
583 " -I,--ignore-case case insensitive process name match\n"
584 " -g,--process-group kill process group instead of process\n"
585 " -y,--younger-than kill processes younger than TIME\n"
586 " -o,--older-than kill processes older than TIME\n"
587 " -i,--interactive ask for confirmation before killing\n"
588 " -l,--list list all known signal names\n"
589 " -q,--quiet don't print complaints\n"
590 " -r,--regexp interpret NAME as an extended regular expression\n"
591 " -s,--signal SIGNAL send this signal instead of SIGTERM\n"
592 " -u,--user USER kill only process(es) running as USER\n"
593 " -v,--verbose report if the signal was successfully sent\n"
594 " -V,--version display version information\n"
595 " -w,--wait wait for processes to die\n"));
596 #ifdef WITH_SELINUX
597 fprintf(stderr, _(
598 " -Z,--context REGEXP kill only process(es) having context\n"
599 " (must precede other arguments)\n"));
600 #endif /*WITH_SELINUX*/
601 fputc('\n', stderr);
602 }
603
604
605 static void
usage(const char * msg)606 usage (const char *msg)
607 {
608 if (pidof)
609 usage_pidof ();
610 else
611 usage_killall (msg);
612 exit (1);
613 }
614
print_version()615 void print_version()
616 {
617 fprintf(stderr, "%s (PSmisc) %s\n", pidof ? "pidof" : "killall", VERSION);
618 fprintf(stderr, _(
619 "Copyright (C) 1993-2005 Werner Almesberger and Craig Small\n\n"));
620 fprintf(stderr, _(
621 "PSmisc comes with ABSOLUTELY NO WARRANTY.\n"
622 "This is free software, and you are welcome to redistribute it under\n"
623 "the terms of the GNU General Public License.\n"
624 "For more information about these matters, see the files named COPYING.\n"));
625 }
626
627 static int
have_proc_self_stat(void)628 have_proc_self_stat (void)
629 {
630 char filename[128];
631 struct stat isproc;
632 pid_t pid = getpid();
633
634 snprintf(filename, sizeof(filename), PROC_BASE"/%d/status", (int) pid);
635 return stat(filename, &isproc) == 0;
636 }
637
638 int
main(int argc,char ** argv)639 main (int argc, char **argv)
640 {
641 char *name;
642 int sig_num;
643 int optc;
644 int myoptind;
645 struct passwd *pwent = NULL;
646 char yt[16];
647 char ot[16];
648
649 //int optsig = 0;
650
651 struct option options[] = {
652 {"exact", 0, NULL, 'e'},
653 {"ignore-case", 0, NULL, 'I'},
654 {"process-group", 0, NULL, 'g'},
655 {"younger-than", 1, NULL, 'y'},
656 {"older-than", 1, NULL, 'o'},
657 {"interactive", 0, NULL, 'i'},
658 {"list-signals", 0, NULL, 'l'},
659 {"quiet", 0, NULL, 'q'},
660 {"regexp", 0, NULL, 'r'},
661 {"signal", 1, NULL, 's'},
662 {"user", 1, NULL, 'u'},
663 {"verbose", 0, NULL, 'v'},
664 {"wait", 0, NULL, 'w'},
665 #ifdef WITH_SELINUX
666 {"context", 1, NULL, 'Z'},
667 #endif /*WITH_SELINUX*/
668 {"version", 0, NULL, 'V'},
669 {0,0,0,0 }};
670
671 /* Setup the i18n */
672 #ifdef ENABLE_NLS
673 setlocale(LC_ALL, "");
674 bindtextdomain(PACKAGE, LOCALEDIR);
675 textdomain(PACKAGE);
676 #endif
677 #ifdef WITH_SELINUX
678 security_context_t scontext = NULL;
679 regex_t scontext_reg;
680
681 if ( argc < 2 ) usage(NULL); /* do the obvious thing... */
682 #endif /*WITH_SELINUX*/
683
684 name = strrchr (*argv, '/');
685 if (name)
686 name++;
687 else
688 name = *argv;
689 pidof = strcmp (name, "killall");
690 sig_num = SIGTERM;
691
692
693 opterr = 0;
694 #ifdef WITH_SELINUX
695 while ( (optc = getopt_long_only(argc,argv,"egy:o:ilqrs:u:vwZ:VI",options,NULL)) != -1) {
696 #else
697 while ( (optc = getopt_long_only(argc,argv,"egy:o:ilqrs:u:vwVI",options,NULL)) != -1) {
698 #endif
699 switch (optc) {
700 case 'e':
701 exact = 1;
702 break;
703 case 'g':
704 process_group = 1;
705 break;
706 case 'y':
707 NOT_PIDOF_OPTION;
708 strncpy(yt, optarg, 16);
709 yt[15] = '\0';
710 if ( 0 >= (younger_than = parse_time_units(yt) ) )
711 usage(_("Invalid time format"));
712 break;
713 case 'o':
714 NOT_PIDOF_OPTION;
715 strncpy(ot, optarg, 16);
716 ot[15] = '\0';
717 if ( 0 >= (older_than = parse_time_units(ot) ) )
718 usage(_("Invalid time format"));
719 break;
720 case 'i':
721 NOT_PIDOF_OPTION;
722 interactive = 1;
723 break;
724 case 'l':
725 NOT_PIDOF_OPTION;
726 list_signals();
727 return 0;
728 break;
729 case 'q':
730 NOT_PIDOF_OPTION;
731 quiet = 1;
732 break;
733 case 'r':
734 NOT_PIDOF_OPTION;
735 reg = 1;
736 break;
737 case 's':
738 sig_num = get_signal (optarg, "killall");
739 break;
740 case 'u':
741 NOT_PIDOF_OPTION;
742 if (!(pwent = getpwnam(optarg))) {
743 fprintf (stderr, _("Cannot find user %s\n"), optarg);
744 exit (1);
745 }
746 break;
747 case 'v':
748 NOT_PIDOF_OPTION;
749 verbose = 1;
750 break;
751 case 'w':
752 NOT_PIDOF_OPTION;
753 wait_until_dead = 1;
754 break;
755 case 'I':
756 /* option check is optind-1 but sig name is optind */
757 if (strcmp(argv[optind-1],"-I") == 0 || strncmp(argv[optind-1],"--",2) == 0) {
758 ignore_case = 1;
759 } else {
760 NOT_PIDOF_OPTION;
761 sig_num = get_signal (argv[optind]+1, "killall");
762 }
763 break;
764 case 'V':
765 /* option check is optind-1 but sig name is optind */
766 if (strcmp(argv[optind-1],"-V") == 0 || strncmp(argv[optind-1],"--",2) == 0) {
767 print_version();
768 return 0;
769 }
770 NOT_PIDOF_OPTION;
771 sig_num = get_signal (argv[optind]+1, "killall");
772 break;
773 #ifdef WITH_SELINUX
774 case 'Z':
775 if (is_selinux_enabled()>0) {
776 scontext=optarg;
777 if (regcomp(&scontext_reg, scontext, REG_EXTENDED|REG_NOSUB) != 0) {
778 fprintf(stderr, _("Bad regular expression: %s\n"), scontext);
779 exit (1);
780 }
781 } else
782 fprintf(stderr, "Warning: -Z (--context) ignored. Requires an SELinux enabled kernel\n");
783 break;
784 #endif /*WITH_SELINUX*/
785 case '?':
786 /* Signal names are in uppercase, so check to see if the argv
787 * is upper case */
788 if (argv[optind-1][1] >= 'A' && argv[optind-1][1] <= 'Z') {
789 sig_num = get_signal (argv[optind-1]+1, "killall");
790 } else {
791 /* Might also be a -## signal too */
792 if (argv[optind-1][1] >= '0' && argv[optind-1][1] <= '9') {
793 sig_num = atoi(argv[optind-1]+1);
794 } else {
795 usage(NULL);
796 }
797 }
798 break;
799 }
800 }
801 myoptind = optind;
802 #ifdef WITH_SELINUX
803 if ((argc - myoptind < 1) && pwent==NULL && scontext==NULL)
804 #else
805 if ((argc - myoptind < 1) && pwent==NULL)
806 #endif
807 usage(NULL);
808
809 if (argc - myoptind > MAX_NAMES + 1) {
810 fprintf (stderr, _("Maximum number of names is %d\n"), MAX_NAMES);
811 exit (1);
812 }
813 if (!have_proc_self_stat()) {
814 fprintf (stderr, _("%s lacks process entries (not mounted ?)\n"), PROC_BASE);
815 exit (1);
816 }
817 argv = argv + myoptind;
818 /*printf("sending signal %d to procs\n", sig_num);*/
819 #ifdef WITH_SELINUX
820 return kill_all(sig_num,argc - myoptind, argv, pwent,
821 scontext ? &scontext_reg : NULL);
822 #else /*WITH_SELINUX*/
823 return kill_all(sig_num,argc - myoptind, argv, pwent);
824 #endif /*WITH_SELINUX*/
825 }
826