Include -Wunreachable-code when building.
[sysvinit.git] / src / killall5.c
1 /*
2 * kilall5.c Kill all processes except processes that have the
3 * same session id, so that the shell that called us
4 * won't be killed. Typically used in shutdown scripts.
5 *
6 * pidof.c Tries to get the pid of the process[es] named.
7 *
8 * Version: 2.86 30-Jul-2004 MvS
9 *
10 * Usage: killall5 [-][signal]
11 * pidof [-s] [-o omitpid [-o omitpid]] program [program..]
12 *
13 * Authors: Miquel van Smoorenburg, miquels@cistron.nl
14 *
15 * Riku Meskanen, <mesrik@jyu.fi>
16 * - return all running pids of given program name
17 * - single shot '-s' option for backwards combatibility
18 * - omit pid '-o' option and %PPID (parent pid metavariable)
19 * - syslog() only if not a connected to controlling terminal
20 * - swapped out programs pids are caught now
21 *
22 * Werner Fink
23 * - make omit dynamic
24 * - provide '-n' to skip stat(2) syscall on network based FS
25 *
26 * This file is part of the sysvinit suite,
27 * Copyright (C) 1991-2004 Miquel van Smoorenburg.
28 *
29 * This program is free software; you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by
31 * the Free Software Foundation; either version 2 of the License, or
32 * (at your option) any later version.
33 *
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
42 */
43 #include <dirent.h>
44 #include <errno.h>
45 #include <getopt.h>
46 #include <limits.h>
47 #include <mntent.h>
48 #include <stdarg.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <signal.h>
52 #include <string.h>
53 #include <syslog.h>
54 #include <sys/mman.h>
55 #include <sys/param.h>
56 #include <sys/stat.h>
57 #include <sys/types.h>
58 #include <sys/wait.h>
59 #include <unistd.h>
60
61 char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
62
63 #ifndef PATH_MAX
64 # ifdef MAXPATHLEN
65 # define PATH_MAX MAXPATHLEN
66 # else
67 # define PATH_MAX 2048
68 # endif
69 #endif
70
71 #define STATNAMELEN 15
72 #define DO_NETFS 2
73 #define DO_STAT 1
74 #define NO_STAT 0
75
76 /* Info about a process. */
77 typedef struct proc {
78 char *pathname; /* full path to executable */
79 char *argv0; /* Name as found out from argv[0] */
80 char *argv0base; /* `basename argv[1]` */
81 char *argv1; /* Name as found out from argv[1] */
82 char *argv1base; /* `basename argv[1]` */
83 char *statname; /* the statname without braces */
84 ino_t ino; /* Inode number */
85 dev_t dev; /* Device it is on */
86 pid_t pid; /* Process ID. */
87 pid_t sid; /* Session ID. */
88 char kernel; /* Kernel thread or zombie. */
89 char nfs; /* Name found on network FS. */
90 struct proc *next; /* Pointer to next struct. */
91 } PROC;
92
93 /* pid queue */
94
95 typedef struct pidq {
96 PROC *proc;
97 struct pidq *next;
98 } PIDQ;
99
100 typedef struct {
101 PIDQ *head;
102 PIDQ *tail;
103 PIDQ *next;
104 } PIDQ_HEAD;
105
106 typedef struct _s_omit {
107 struct _s_omit *next;
108 struct _s_omit *prev;
109 pid_t pid;
110 } OMIT;
111
112 typedef struct _s_shadow
113 {
114 struct _s_shadow *next;
115 struct _s_shadow *prev;
116 size_t nlen;
117 char * name;
118 } SHADOW;
119
120 typedef struct _s_nfs
121 {
122 struct _s_nfs *next; /* Pointer to next struct. */
123 struct _s_nfs *prev; /* Pointer to previous st. */
124 SHADOW *shadow; /* Pointer to shadows */
125 size_t nlen;
126 char * name;
127 } NFS;
128
129 /* List of processes. */
130 PROC *plist;
131
132 /* List of processes to omit. */
133 OMIT *omit;
134
135 /* List of NFS mountes partitions. */
136 NFS *nlist;
137
138 /* Did we stop all processes ? */
139 int sent_sigstop;
140
141 int scripts_too = 0;
142
143 char *progname; /* the name of the running program */
144 #ifdef __GNUC__
145 __attribute__ ((format (printf, 2, 3)))
146 #endif
147 void nsyslog(int pri, char *fmt, ...);
148
149 #if !defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L)
150 # ifndef inline
151 # define inline __inline__
152 # endif
153 # ifndef restrict
154 # define restrict __restrict__
155 # endif
156 #endif
157 #define alignof(type) ((sizeof(type)+(sizeof(void*)-1)) & ~(sizeof(void*)-1))
158
159 /*
160 * Malloc space, barf if out of memory.
161 */
162 #ifdef __GNUC__
163 static void *xmalloc(size_t) __attribute__ ((__malloc__));
164 #endif
165 static void *xmalloc(size_t bytes)
166 {
167 void *p;
168
169 if ((p = malloc(bytes)) == NULL) {
170 if (sent_sigstop) kill(-1, SIGCONT);
171 nsyslog(LOG_ERR, "out of memory");
172 exit(1);
173 }
174 return p;
175 }
176
177 #ifdef __GNUC__
178 static inline void xmemalign(void **, size_t, size_t) __attribute__ ((__nonnull__ (1)));
179 #endif
180 static inline void xmemalign(void **memptr, size_t alignment, size_t size)
181 {
182 if ((posix_memalign(memptr, alignment, size)) < 0) {
183 if (sent_sigstop) kill(-1, SIGCONT);
184 nsyslog(LOG_ERR, "out of memory");
185 exit(1);
186 }
187 }
188
189 /*
190 * See if the proc filesystem is there. Mount if needed.
191 */
192 int mount_proc(void)
193 {
194 struct stat st;
195 char *args[] = { "mount", "-t", "proc", "proc", "/proc", 0 };
196 pid_t pid, rc;
197 int wst;
198 int did_mount = 0;
199
200 /* Stat /proc/version to see if /proc is mounted. */
201 if (stat("/proc/version", &st) < 0 && errno == ENOENT) {
202
203 /* It's not there, so mount it. */
204 if ((pid = fork()) < 0) {
205 nsyslog(LOG_ERR, "cannot fork");
206 exit(1);
207 }
208 if (pid == 0) {
209 /* Try a few mount binaries. */
210 execv("/bin/mount", args);
211 execv("/sbin/mount", args);
212
213 /* Okay, I give up. */
214 nsyslog(LOG_ERR, "cannot execute mount");
215 exit(1);
216 }
217 /* Wait for child. */
218 while ((rc = wait(&wst)) != pid)
219 if (rc < 0 && errno == ECHILD)
220 break;
221 if (rc != pid || WEXITSTATUS(wst) != 0)
222 nsyslog(LOG_ERR, "mount returned non-zero exit status");
223
224 did_mount = 1;
225 }
226
227 /* See if mount succeeded. */
228 if (stat("/proc/version", &st) < 0) {
229 if (errno == ENOENT)
230 nsyslog(LOG_ERR, "/proc not mounted, failed to mount.");
231 else
232 nsyslog(LOG_ERR, "/proc unavailable.");
233 exit(1);
234 }
235
236 return did_mount;
237 }
238
239 static inline int isnetfs(const char * type)
240 {
241 static const char* netfs[] = {"nfs", "nfs4", "smbfs", "cifs", "afs", "ncpfs", (char*)0};
242 int n;
243 for (n = 0; netfs[n]; n++) {
244 if (!strcasecmp(netfs[n], type))
245 return 1;
246 }
247 return 0;
248 }
249
250 /*
251 * Remember all NFS typed partitions.
252 */
253 void init_nfs(void)
254 {
255 struct stat st;
256 struct mntent * ent;
257 FILE * mnt;
258
259 nlist = (NFS*)0;
260
261 if (stat("/proc/version", &st) < 0)
262 return;
263 if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0)
264 return;
265
266 while ((ent = getmntent(mnt))) {
267 if (isnetfs(ent->mnt_type)) {
268 size_t nlen = strlen(ent->mnt_dir);
269 NFS *restrict p;
270 xmemalign((void*)&p, sizeof(void*), alignof(NFS)+(nlen+1));
271 p->name = ((char*)p)+alignof(NFS);
272 p->nlen = nlen;
273 p->shadow = (SHADOW*)0;
274
275 strcpy(p->name, ent->mnt_dir);
276 if (nlist)
277 nlist->prev = p;
278 p->next = nlist;
279 p->prev = (NFS*)0;
280 nlist = p;
281 }
282 }
283 endmntent(mnt);
284
285 if ((mnt = setmntent("/proc/mounts", "r")) == (FILE*)0)
286 return;
287
288 while ((ent = getmntent(mnt))) {
289 NFS *p;
290
291 for (p = nlist; p; p = p->next) {
292 SHADOW * restrict s;
293 size_t nlen;
294
295 if (strcmp(ent->mnt_dir, p->name) == 0)
296 continue;
297 if (strncmp(ent->mnt_dir, p->name, p->nlen) != 0)
298 continue;
299
300 nlen = strlen(ent->mnt_dir);
301 xmemalign((void*)&s, sizeof(void*), alignof(SHADOW)+(nlen+1));
302 s->name = ((char*)s)+alignof(SHADOW);
303 s->nlen = nlen;
304
305 strcpy(s->name, ent->mnt_dir);
306 if (p->shadow)
307 p->shadow->prev = s;
308 s->next = p->shadow;
309 s->prev = (SHADOW*)0;
310 p->shadow = s;
311 }
312 }
313 endmntent(mnt);
314 }
315
316 static void clear_shadow(SHADOW *restrict shadow)
317 {
318 SHADOW *s, *n, *l;
319
320 n = shadow;
321 l = (SHADOW*)0;
322 for (s = shadow; n; s = n) {
323 l = s->prev;
324 n = s->next;
325 if (s == shadow) {
326 if (n) n->prev = (SHADOW*)0;
327 shadow = n;
328 } else if (l) {
329 if (n) n->prev = l;
330 l->next = n;
331 }
332 free(s);
333 }
334 }
335
336 static void clear_mnt(void)
337 {
338 NFS *p, *n, *l;
339
340 n = nlist;
341 l = (NFS*)0;
342 for (p = nlist; n; p = n) {
343 l = p->prev;
344 n = p->next;
345 if (p == nlist) {
346 if (n) n->prev = (NFS*)0;
347 nlist = n;
348 } else if (l) {
349 if (n) n->prev = l;
350 l->next = n;
351 }
352 if (p->shadow)
353 clear_shadow(p->shadow);
354 free(p);
355 }
356 }
357
358 /*
359 * Check if path is a shadow off a NFS partition.
360 */
361 static int shadow(SHADOW *restrict this, const char *restrict name, const size_t nlen)
362 {
363 SHADOW *s;
364
365 if (!this)
366 goto out;
367 for (s = this; s; s = s->next) {
368 if (nlen < s->nlen)
369 continue;
370 if (name[s->nlen] != '\0' && name[s->nlen] != '/')
371 continue;
372 if (strncmp(name, s->name, s->nlen) == 0)
373 return 1;
374 }
375 out:
376 return 0;
377 }
378
379 /*
380 * Get the maximal number of symlinks to follow. Use sysconf() on
381 * Hurd where the hardcoded value MAXSYMLINKS is not available.
382 */
383 static int maxsymlinks(void)
384 {
385 int v = sysconf(_SC_SYMLOOP_MAX);
386 #ifdef MAXSYMLINKS
387 if (v == -1)
388 return MAXSYMLINKS;
389 #endif
390 return v;
391 }
392
393 /*
394 * Check path is located on a network based partition.
395 */
396 int check4nfs(const char * path, char * real)
397 {
398 char buf[PATH_MAX+1];
399 const char *curr;
400 int deep = maxsymlinks();
401
402 if (!nlist) return 0;
403
404 curr = path;
405 do {
406 const char *prev;
407 int len;
408
409 if ((prev = strdupa(curr)) == NULL) {
410 nsyslog(LOG_ERR, "strdupa(): %s\n", strerror(errno));
411 return 0;
412 }
413
414 errno = 0;
415 if ((len = readlink(curr, buf, PATH_MAX)) < 0)
416 break;
417 buf[len] = '\0';
418
419 if (buf[0] != '/') {
420 const char *slash;
421
422 if ((slash = strrchr(prev, '/'))) {
423 size_t off = slash - prev + 1;
424
425 if (off + len > PATH_MAX)
426 len = PATH_MAX - off;
427
428 memmove(&buf[off], &buf[0], len + 1);
429 memcpy(&buf[0], prev, off);
430 }
431 }
432 curr = &buf[0];
433
434 if (deep-- <= 0) return 0;
435
436 } while (1);
437
438 if (real) strcpy(real, curr);
439
440 if (errno == EINVAL) {
441 const size_t nlen = strlen(curr);
442 NFS *p;
443 for (p = nlist; p; p = p->next) {
444 if (nlen < p->nlen)
445 continue;
446 if (curr[p->nlen] != '\0' && curr[p->nlen] != '/')
447 continue;
448 if (!strncmp(curr, p->name, p->nlen)) {
449 if (shadow(p->shadow, curr, nlen))
450 continue;
451 return 1;
452 }
453 }
454 }
455
456 return 0;
457 }
458
459 int readarg(FILE *fp, char *buf, int sz)
460 {
461 int c = 0, f = 0;
462
463 while (f < (sz-1) && (c = fgetc(fp)) != EOF && c)
464 buf[f++] = c;
465 buf[f] = 0;
466
467 return (c == EOF && f == 0) ? c : f;
468 }
469
470 /*
471 * Read the proc filesystem.
472 * CWD must be /proc to avoid problems if / is affected by the killing (ie depend on fuse).
473 */
474 int readproc(int do_stat)
475 {
476 DIR *dir;
477 FILE *fp;
478 PROC *p, *n;
479 struct dirent *d;
480 struct stat st;
481 char path[PATH_MAX+1];
482 char buf[PATH_MAX+1];
483 char *s, *q;
484 unsigned long startcode, endcode;
485 int pid, f;
486 ssize_t len;
487
488 /* Open the /proc directory. */
489 if (chdir("/proc") == -1) {
490 nsyslog(LOG_ERR, "chdir /proc failed");
491 return -1;
492 }
493 if ((dir = opendir(".")) == NULL) {
494 nsyslog(LOG_ERR, "cannot opendir(/proc)");
495 return -1;
496 }
497
498 /* Free the already existing process list. */
499 n = plist;
500 for (p = plist; n; p = n) {
501 n = p->next;
502 if (p->argv0) free(p->argv0);
503 if (p->argv1) free(p->argv1);
504 if (p->statname) free(p->statname);
505 free(p->pathname);
506 free(p);
507 }
508 plist = NULL;
509
510 /* Walk through the directory. */
511 while ((d = readdir(dir)) != NULL) {
512
513 /* See if this is a process */
514 if ((pid = atoi(d->d_name)) == 0) continue;
515
516 /* Get a PROC struct . */
517 p = (PROC *)xmalloc(sizeof(PROC));
518 memset(p, 0, sizeof(PROC));
519
520 /* Open the status file. */
521 snprintf(path, sizeof(path), "%s/stat", d->d_name);
522
523 /* Read SID & statname from it. */
524 if ((fp = fopen(path, "r")) != NULL) {
525 size_t len;
526
527 len = fread(buf, sizeof(char), sizeof(buf)-1, fp);
528 buf[len] = '\0';
529
530 if (buf[0] == '\0') {
531 nsyslog(LOG_ERR,
532 "can't read from %s\n", path);
533 fclose(fp);
534 free(p);
535 continue;
536 }
537
538 /* See if name starts with '(' */
539 s = buf;
540 while (*s && *s != ' ') s++;
541 if (*s) s++;
542 if (*s == '(') {
543 /* Read program name. */
544 q = strrchr(buf, ')');
545 if (q == NULL) {
546 p->sid = 0;
547 nsyslog(LOG_ERR,
548 "can't get program name from /proc/%s\n",
549 path);
550 fclose(fp);
551 if (p->argv0) free(p->argv0);
552 if (p->argv1) free(p->argv1);
553 if (p->statname) free(p->statname);
554 free(p->pathname);
555 free(p);
556 continue;
557 }
558 s++;
559 } else {
560 q = s;
561 while (*q && *q != ' ') q++;
562 }
563 if (*q) *q++ = 0;
564 while (*q == ' ') q++;
565 p->statname = (char *)xmalloc(strlen(s)+1);
566 strcpy(p->statname, s);
567
568 /* Get session, startcode, endcode. */
569 startcode = endcode = 0;
570 if (sscanf(q, "%*c %*d %*d %d %*d %*d %*u %*u "
571 "%*u %*u %*u %*u %*u %*d %*d "
572 "%*d %*d %*d %*d %*u %*u %*d "
573 "%*u %lu %lu",
574 &p->sid, &startcode, &endcode) != 3) {
575 p->sid = 0;
576 nsyslog(LOG_ERR, "can't read sid from %s\n",
577 path);
578 fclose(fp);
579 if (p->argv0) free(p->argv0);
580 if (p->argv1) free(p->argv1);
581 if (p->statname) free(p->statname);
582 free(p->pathname);
583 free(p);
584 continue;
585 }
586 if (startcode == 0 && endcode == 0)
587 p->kernel = 1;
588 fclose(fp);
589 } else {
590 /* Process disappeared.. */
591 if (p->argv0) free(p->argv0);
592 if (p->argv1) free(p->argv1);
593 if (p->statname) free(p->statname);
594 free(p->pathname);
595 free(p);
596 continue;
597 }
598
599 snprintf(path, sizeof(path), "%s/cmdline", d->d_name);
600 if ((fp = fopen(path, "r")) != NULL) {
601
602 /* Now read argv[0] */
603 f = readarg(fp, buf, sizeof(buf));
604
605 if (buf[0]) {
606 /* Store the name into malloced memory. */
607 p->argv0 = (char *)xmalloc(f + 1);
608 strcpy(p->argv0, buf);
609
610 /* Get a pointer to the basename. */
611 p->argv0base = strrchr(p->argv0, '/');
612 if (p->argv0base != NULL)
613 p->argv0base++;
614 else
615 p->argv0base = p->argv0;
616 }
617
618 /* And read argv[1] */
619 while ((f = readarg(fp, buf, sizeof(buf))) != EOF)
620 if (buf[0] != '-') break;
621
622 if (buf[0]) {
623 /* Store the name into malloced memory. */
624 p->argv1 = (char *)xmalloc(f + 1);
625 strcpy(p->argv1, buf);
626
627 /* Get a pointer to the basename. */
628 p->argv1base = strrchr(p->argv1, '/');
629 if (p->argv1base != NULL)
630 p->argv1base++;
631 else
632 p->argv1base = p->argv1;
633 }
634
635 fclose(fp);
636
637 } else {
638 /* Process disappeared.. */
639 if (p->argv0) free(p->argv0);
640 if (p->argv1) free(p->argv1);
641 if (p->statname) free(p->statname);
642 free(p->pathname);
643 free(p);
644 continue;
645 }
646
647 /* Try to stat the executable. */
648 snprintf(path, sizeof(path), "/proc/%s/exe", d->d_name);
649
650 p->nfs = 0;
651
652 switch (do_stat) {
653 case DO_NETFS:
654 if ((p->nfs = check4nfs(path, buf)))
655 goto link;
656 case DO_STAT:
657 if (stat(path, &st) != 0) {
658 char * ptr;
659
660 len = readlink(path, buf, PATH_MAX);
661 if (len <= 0)
662 break;
663 buf[len] = '\0';
664
665 ptr = strstr(buf, " (deleted)");
666 if (!ptr)
667 break;
668 *ptr = '\0';
669 len -= strlen(" (deleted)");
670
671 if (stat(buf, &st) != 0)
672 break;
673 p->dev = st.st_dev;
674 p->ino = st.st_ino;
675 p->pathname = (char *)xmalloc(len + 1);
676 memcpy(p->pathname, buf, len);
677 p->pathname[len] = '\0';
678
679 /* All done */
680 break;
681 }
682
683 p->dev = st.st_dev;
684 p->ino = st.st_ino;
685
686 /* Fall through */
687 default:
688 link:
689 len = readlink(path, buf, PATH_MAX);
690 if (len > 0) {
691 p->pathname = (char *)xmalloc(len + 1);
692 memcpy(p->pathname, buf, len);
693 p->pathname[len] = '\0';
694 }
695 break;
696 }
697
698 /* Link it into the list. */
699 p->next = plist;
700 plist = p;
701 p->pid = pid;
702 }
703 closedir(dir);
704
705 /* Done. */
706 return 0;
707 }
708
709 PIDQ_HEAD *init_pid_q(PIDQ_HEAD *q)
710 {
711 q->head = q->next = q->tail = NULL;
712 return q;
713 }
714
715 int empty_q(PIDQ_HEAD *q)
716 {
717 return (q->head == NULL);
718 }
719
720 int add_pid_to_q(PIDQ_HEAD *q, PROC *p)
721 {
722 PIDQ *tmp;
723
724 tmp = (PIDQ *)xmalloc(sizeof(PIDQ));
725
726 tmp->proc = p;
727 tmp->next = NULL;
728
729 if (empty_q(q)) {
730 q->head = tmp;
731 q->tail = tmp;
732 } else {
733 q->tail->next = tmp;
734 q->tail = tmp;
735 }
736 return 0;
737 }
738
739 PROC *get_next_from_pid_q(PIDQ_HEAD *q)
740 {
741 PROC *p;
742 PIDQ *tmp = q->head;
743
744 if (!empty_q(q)) {
745 p = q->head->proc;
746 q->head = tmp->next;
747 free(tmp);
748 return p;
749 }
750
751 return NULL;
752 }
753
754 /* Try to get the process ID of a given process. */
755 PIDQ_HEAD *pidof(char *prog)
756 {
757 PROC *p;
758 PIDQ_HEAD *q;
759 struct stat st;
760 char *s;
761 int nfs = 0;
762 int dostat = 0;
763 int foundone = 0;
764 int ok = 0;
765 const int root = (getuid() == 0);
766 char real[PATH_MAX+1];
767
768 if (! prog)
769 return NULL;
770
771 /* Try to stat the executable. */
772 if (prog[0] == '/') {
773 memset(&real[0], 0, sizeof(real));
774
775 if (check4nfs(prog, real))
776 nfs++;
777
778 if (real[0] != '\0')
779 prog = &real[0]; /* Binary located on network FS. */
780
781 if ((nfs == 0) && (stat(prog, &st) == 0))
782 dostat++; /* Binary located on a local FS. */
783 }
784
785 /* Get basename of program. */
786 if ((s = strrchr(prog, '/')) == NULL)
787 s = prog;
788 else
789 s++;
790
791 if (! *s)
792 return NULL;
793
794 q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD));
795 q = init_pid_q(q);
796
797 /* First try to find a match based on dev/ino pair. */
798 if (dostat && !nfs) {
799 for (p = plist; p; p = p->next) {
800 if (p->nfs)
801 continue;
802 if (p->dev == st.st_dev && p->ino == st.st_ino) {
803 add_pid_to_q(q, p);
804 foundone++;
805 }
806 }
807 }
808
809 /* Second try to find a match based on full path name on
810 * network FS located binaries */
811 if (!foundone && nfs) {
812 for (p = plist; p; p = p->next) {
813 if (!p->pathname)
814 continue;
815 if (!p->nfs)
816 continue;
817 if (strcmp(prog, p->pathname) != 0)
818 continue;
819 add_pid_to_q(q, p);
820 foundone++;
821 }
822 }
823
824 /* If we didn't find a match based on dev/ino, try the name. */
825 if (!foundone) for (p = plist; p; p = p->next) {
826 if (prog[0] == '/') {
827 if (!p->pathname) {
828 if (root)
829 continue;
830 goto fallback;
831 }
832 if (strcmp(prog, p->pathname)) {
833 int len = strlen(prog);
834 if (strncmp(prog, p->pathname, len))
835 {
836 if (scripts_too)
837 goto fallback;
838 continue;
839 }
840 if (strcmp(" (deleted)", p->pathname + len))
841 {
842 if (scripts_too)
843 goto fallback;
844 continue;
845 }
846 }
847 add_pid_to_q(q, p);
848 continue;
849 }
850
851 fallback:
852 ok = 0;
853
854 /* matching nonmatching
855 * proc name prog name prog name
856 * --- ----------- ------------
857 * b b, p/b, q/b
858 * p/b b, p/b q/b
859 *
860 * Algorithm: Match if:
861 * cmd = arg
862 * or cmd = base(arg)
863 * or base(cmd) = arg
864 *
865 * Specifically, do not match just because base(cmd) = base(arg)
866 * as was done in earlier versions of this program, since this
867 * allows /aaa/foo to match /bbb/foo .
868 */
869 ok |=
870 (p->argv0 && strcmp(p->argv0, prog) == 0)
871 || (p->argv0 && s != prog && strcmp(p->argv0, s) == 0)
872 || (p->argv0base && strcmp(p->argv0base, prog) == 0);
873
874 /* For scripts, compare argv[1] as well. */
875 if (
876 scripts_too && p->statname && p->argv1base
877 && !strncmp(p->statname, p->argv1base, STATNAMELEN)
878 ) {
879 ok |=
880 (p->argv1 && strcmp(p->argv1, prog) == 0)
881 || (p->argv1 && s != prog && strcmp(p->argv1, s) == 0)
882 || (p->argv1base && strcmp(p->argv1base, prog) == 0);
883 }
884
885 /*
886 * if we have a space in argv0, process probably
887 * used setproctitle so try statname.
888 */
889 if (strlen(s) <= STATNAMELEN &&
890 (p->argv0 == NULL ||
891 p->argv0[0] == 0 ||
892 strchr(p->argv0, ' '))) {
893 ok |= (strcmp(p->statname, s) == 0);
894 }
895
896 /*
897 * if we have a `-' as the first character, process
898 * probably used as a login shell
899 */
900 if (strlen(s) <= STATNAMELEN &&
901 p->argv1 == NULL &&
902 (p->argv0 != NULL &&
903 p->argv0[0] == '-')) {
904 ok |= (strcmp(p->statname, s) == 0);
905 }
906
907 if (ok) add_pid_to_q(q, p);
908 }
909
910 return q;
911 }
912
913 /* Give usage message and exit. */
914 void usage(void)
915 {
916 nsyslog(LOG_ERR, "only one argument, a signal number, allowed");
917 closelog();
918 exit(1);
919 }
920
921 /* write to syslog file if not open terminal */
922 #ifdef __GNUC__
923 __attribute__ ((format (printf, 2, 3)))
924 #endif
925 void nsyslog(int pri, char *fmt, ...)
926 {
927 va_list args;
928
929 va_start(args, fmt);
930
931 if (ttyname(0) == NULL) {
932 vsyslog(pri, fmt, args);
933 } else {
934 fprintf(stderr, "%s: ",progname);
935 vfprintf(stderr, fmt, args);
936 fprintf(stderr, "\n");
937 }
938
939 va_end(args);
940 }
941
942 #define PIDOF_SINGLE 0x01
943 #define PIDOF_OMIT 0x02
944 #define PIDOF_NETFS 0x04
945
946 /*
947 * Pidof functionality.
948 */
949 int main_pidof(int argc, char **argv)
950 {
951 PIDQ_HEAD *q;
952 PROC *p;
953 char *token, *here;
954 int f;
955 int first = 1;
956 int opt, flags = 0;
957 int chroot_check = 0;
958 struct stat st;
959 char tmp[512];
960
961 omit = (OMIT*)0;
962 nlist = (NFS*)0;
963 opterr = 0;
964
965 if ((token = getenv("PIDOF_NETFS")) && (strcmp(token,"no") != 0))
966 flags |= PIDOF_NETFS;
967
968 while ((opt = getopt(argc,argv,"hco:sxn")) != EOF) switch (opt) {
969 case '?':
970 nsyslog(LOG_ERR,"invalid options on command line!\n");
971 closelog();
972 exit(1);
973 case 'c':
974 if (geteuid() == 0) chroot_check = 1;
975 break;
976 case 'o':
977 here = optarg;
978 while ((token = strsep(&here, ",;:"))) {
979 OMIT *restrict optr;
980 pid_t opid;
981
982 if (strcmp("%PPID", token) == 0)
983 opid = getppid();
984 else
985 opid = (pid_t)atoi(token);
986
987 if (opid < 1) {
988 nsyslog(LOG_ERR,
989 "illegal omit pid value "
990 "(%s)!\n", token);
991 continue;
992 }
993 xmemalign((void*)&optr, sizeof(void*), alignof(OMIT));
994 optr->next = omit;
995 optr->prev = (OMIT*)0;
996 optr->pid = opid;
997 omit = optr;
998 }
999 flags |= PIDOF_OMIT;
1000 break;
1001 case 's':
1002 flags |= PIDOF_SINGLE;
1003 break;
1004 case 'x':
1005 scripts_too++;
1006 break;
1007 case 'n':
1008 flags |= PIDOF_NETFS;
1009 break;
1010 default:
1011 /* Nothing */
1012 break;
1013 }
1014 argc -= optind;
1015 argv += optind;
1016
1017 /* Check if we are in a chroot */
1018 if (chroot_check) {
1019 snprintf(tmp, 512, "/proc/%d/root", getpid());
1020 if (stat(tmp, &st) < 0) {
1021 nsyslog(LOG_ERR, "stat failed for %s!\n", tmp);
1022 closelog();
1023 exit(1);
1024 }
1025 }
1026
1027 if (flags & PIDOF_NETFS)
1028 init_nfs(); /* Which network based FS are online? */
1029
1030 /* Print out process-ID's one by one. */
1031 readproc((flags & PIDOF_NETFS) ? DO_NETFS : DO_STAT);
1032
1033 for(f = 0; f < argc; f++) {
1034 if ((q = pidof(argv[f])) != NULL) {
1035 pid_t spid = 0;
1036 while ((p = get_next_from_pid_q(q))) {
1037 if ((flags & PIDOF_OMIT) && omit) {
1038 OMIT * optr;
1039 for (optr = omit; optr; optr = optr->next) {
1040 if (optr->pid == p->pid)
1041 break;
1042 }
1043
1044 /*
1045 * On a match, continue with
1046 * the for loop above.
1047 */
1048 if (optr)
1049 continue;
1050 }
1051 if (flags & PIDOF_SINGLE) {
1052 if (spid)
1053 continue;
1054 else
1055 spid = 1;
1056 }
1057 if (chroot_check) {
1058 struct stat st2;
1059 snprintf(tmp, 512, "/proc/%d/root",
1060 p->pid);
1061 if (stat(tmp, &st2) < 0 ||
1062 st.st_dev != st2.st_dev ||
1063 st.st_ino != st2.st_ino) {
1064 continue;
1065 }
1066 }
1067 if (!first)
1068 printf(" ");
1069 printf("%d", p->pid);
1070 first = 0;
1071 }
1072 }
1073 }
1074 if (!first)
1075 printf("\n");
1076
1077 clear_mnt();
1078
1079 closelog();
1080 return(first ? 1 : 0);
1081 }
1082
1083 /* Main for either killall or pidof. */
1084 int main(int argc, char **argv)
1085 {
1086 PROC *p;
1087 int pid, sid = -1;
1088 int sig = SIGKILL;
1089 int c;
1090
1091 /* return non-zero if no process was killed */
1092 int retval = 2;
1093
1094 /* Get program name. */
1095 if ((progname = strrchr(argv[0], '/')) == NULL)
1096 progname = argv[0];
1097 else
1098 progname++;
1099
1100 /* Now connect to syslog. */
1101 openlog(progname, LOG_CONS|LOG_PID, LOG_DAEMON);
1102
1103 /* Were we called as 'pidof' ? */
1104 if (strcmp(progname, "pidof") == 0)
1105 return main_pidof(argc, argv);
1106
1107 /* Right, so we are "killall". */
1108 omit = (OMIT*)0;
1109
1110 if (argc > 1) {
1111 for (c = 1; c < argc; c++) {
1112 if (argv[c][0] == '-') (argv[c])++;
1113 if (argv[c][0] == 'o') {
1114 char * token, * here;
1115
1116 if (++c >= argc)
1117 usage();
1118
1119 here = argv[c];
1120 while ((token = strsep(&here, ",;:"))) {
1121 OMIT *restrict optr;
1122 pid_t opid = (pid_t)atoi(token);
1123
1124 if (opid < 1) {
1125 nsyslog(LOG_ERR,
1126 "illegal omit pid value "
1127 "(%s)!\n", token);
1128 continue;
1129 }
1130 xmemalign((void*)&optr, sizeof(void*), alignof(OMIT));
1131 optr->next = omit;
1132 optr->prev = (OMIT*)0;
1133 optr->pid = opid;
1134 omit = optr;
1135 }
1136 }
1137 else if ((sig = atoi(argv[1])) <= 0 || sig > 31)
1138 usage();
1139 }
1140 }
1141
1142 /* First get the /proc filesystem online. */
1143 mount_proc();
1144
1145 /*
1146 * Ignoring SIGKILL and SIGSTOP do not make sense, but
1147 * someday kill(-1, sig) might kill ourself if we don't
1148 * do this. This certainly is a valid concern for SIGTERM-
1149 * Linux 2.1 might send the calling process the signal too.
1150 */
1151 signal(SIGTERM, SIG_IGN);
1152 signal(SIGSTOP, SIG_IGN);
1153 signal(SIGKILL, SIG_IGN);
1154
1155 /* lock us into memory */
1156 mlockall(MCL_CURRENT | MCL_FUTURE);
1157
1158 /* Now stop all processes. */
1159 kill(-1, SIGSTOP);
1160 sent_sigstop = 1;
1161
1162 /* Read /proc filesystem */
1163 if (readproc(NO_STAT) < 0) {
1164 kill(-1, SIGCONT);
1165 return(1);
1166 }
1167
1168 /* Now kill all processes except init (pid 1) and our session. */
1169 sid = (int)getsid(0);
1170 pid = (int)getpid();
1171 for (p = plist; p; p = p->next) {
1172 if (p->pid == 1 || p->pid == pid || p->sid == sid || p->kernel)
1173 continue;
1174
1175 if (omit) {
1176 OMIT * optr;
1177 for (optr = omit; optr; optr = optr->next) {
1178 if (optr->pid == p->pid)
1179 break;
1180 }
1181
1182 /* On a match, continue with the for loop above. */
1183 if (optr)
1184 continue;
1185 }
1186
1187 kill(p->pid, sig);
1188 retval = 0;
1189 }
1190
1191 /* And let them continue. */
1192 kill(-1, SIGCONT);
1193
1194 /* Done. */
1195 closelog();
1196
1197 /* Force the kernel to run the scheduler */
1198 usleep(1);
1199
1200 return retval;
1201 }