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(&reglist[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 (&reglist[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