1 --- killall5.c 2001-09-26 12:59:46.000000000 +0200
2 +++ ../../sysvinit-2.86.ds1/src/killall5.c 2004-07-30 14:16:23.000000000 +0200
5 * pidof.c Tries to get the pid of the process[es] named.
7 - * Version: 2.81 31-Jul-2001 MvS
8 + * Version: 2.86 30-Jul-2004 MvS
10 * Usage: killall5 [-][signal]
11 * pidof [-s] [-o omitpid [-o omitpid]] program [program..]
13 * - swapped out programs pids are caught now
15 * This file is part of the sysvinit suite,
16 - * Copyright 1991-2001 Miquel van Smoorenburg.
17 + * Copyright 1991-2004 Miquel van Smoorenburg.
19 * This program is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU General Public License
22 #include <sys/types.h>
33 -char *Version = "@(#)killall5 2.81 31-Jul-2001 miquels@cistron.nl";
34 +char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl";
36 +#define STATNAMELEN 15
38 /* Info about a process. */
39 -typedef struct _proc_
41 - char *fullname; /* Name as found out from argv[0] */
42 - char *basename; /* Only the part after the last / */
43 - char *statname; /* the statname without braces */
44 - ino_t ino; /* Inode number */
45 - dev_t dev; /* Device it is on */
46 - pid_t pid; /* Process ID. */
47 - int sid; /* Session ID. */
48 - struct _proc_ *next; /* Pointer to next struct. */
49 +typedef struct proc {
50 + char *argv0; /* Name as found out from argv[0] */
51 + char *argv0base; /* `basename argv[1]` */
52 + char *argv1; /* Name as found out from argv[1] */
53 + char *argv1base; /* `basename argv[1]` */
54 + char *statname; /* the statname without braces */
55 + ino_t ino; /* Inode number */
56 + dev_t dev; /* Device it is on */
57 + pid_t pid; /* Process ID. */
58 + int sid; /* Session ID. */
59 + int kernel; /* Kernel thread or zombie. */
60 + struct proc *next; /* Pointer to next struct. */
64 -typedef struct _pidq_ {
65 - struct _pidq_ *front;
66 - struct _pidq_ *next;
67 - struct _pidq_ *rear;
70 +typedef struct pidq {
81 /* List of processes. */
84 -/* Did we stop a number of processes? */
86 +/* Did we stop all processes ? */
94 if ((p = malloc(bytes)) == NULL) {
95 - if (stopped) kill(-1, SIGCONT);
96 + if (sent_sigstop) kill(-1, SIGCONT);
97 nsyslog(LOG_ERR, "out of memory");
106 - char *args[] = { "mount", "-t", "proc", "none", "/proc", NULL };
109 + char *args[] = { "mount", "-t", "proc", "proc", "/proc", 0 };
114 /* Stat /proc/version to see if /proc is mounted. */
115 - if (stat("/proc/version", &st) < 0) {
116 + if (stat("/proc/version", &st) < 0 && errno == ENOENT) {
118 /* It's not there, so mount it. */
119 if ((pid = fork()) < 0) {
122 /* Try a few mount binaries. */
123 execv("/sbin/mount", args);
124 - execv("/etc/mount", args);
125 execv("/bin/mount", args);
127 /* Okay, I give up. */
131 /* Wait for child. */
132 - while (wait(&wst) != pid)
134 - if (WEXITSTATUS(wst) != 0)
135 + while ((rc = wait(&wst)) != pid)
136 + if (rc < 0 && errno == ECHILD)
138 + if (rc != pid || WEXITSTATUS(wst) != 0)
139 nsyslog(LOG_ERR, "mount returned non-zero exit status");
142 @@ -131,28 +142,42 @@
144 /* See if mount succeeded. */
145 if (stat("/proc/version", &st) < 0) {
146 - nsyslog(LOG_ERR, "/proc not mounted, failed to mount.");
147 + if (errno == ENOENT)
148 + nsyslog(LOG_ERR, "/proc not mounted, failed to mount.");
150 + nsyslog(LOG_ERR, "/proc unavailable.");
157 +int readarg(FILE *fp, char *buf, int sz)
161 + while (f < (sz-1) && (c = fgetc(fp)) != EOF && c)
165 + return (c == EOF && f == 0) ? c : f;
169 * Read the proc filesystem.
191 + unsigned long startcode, endcode;
194 /* Open the /proc directory. */
195 if ((dir = opendir("/proc")) == NULL) {
198 for (p = plist; n; p = n) {
200 - if (p->fullname) free(p->fullname);
201 + if (p->argv0) free(p->argv0);
202 + if (p->argv1) free(p->argv1);
207 /* Read SID & statname from it. */
208 if ((fp = fopen(path, "r")) != NULL) {
210 - fgets(buf, 256, fp);
211 + fgets(buf, sizeof(buf), fp);
213 /* See if name starts with '(' */
215 @@ -212,14 +238,21 @@
216 p->statname = (char *)xmalloc(strlen(s)+1);
217 strcpy(p->statname, s);
219 - /* This could be replaced by getsid(pid) */
220 - if (sscanf(q, "%*c %*d %*d %d", &p->sid) != 1) {
221 + /* Get session, startcode, endcode. */
222 + startcode = endcode = 0;
223 + if (sscanf(q, "%*c %*d %*d %d %*d %*d %*u %*u "
224 + "%*u %*u %*u %*u %*u %*d %*d "
225 + "%*d %*d %*d %*d %*u %*u %*d "
227 + &p->sid, &startcode, &endcode) != 3) {
229 nsyslog(LOG_ERR, "can't read sid from %s\n",
234 + if (startcode == 0 && endcode == 0)
238 /* Process disappeared.. */
239 @@ -227,24 +260,44 @@
243 - /* Now read argv[0] */
244 snprintf(path, sizeof(path), "/proc/%s/cmdline", d->d_name);
245 if ((fp = fopen(path, "r")) != NULL) {
247 - while(f < 127 && (c = fgetc(fp)) != EOF && c)
251 + /* Now read argv[0] */
252 + f = readarg(fp, buf, sizeof(buf));
255 + /* Store the name into malloced memory. */
256 + p->argv0 = (char *)xmalloc(f + 1);
257 + strcpy(p->argv0, buf);
259 + /* Get a pointer to the basename. */
260 + p->argv0base = strrchr(p->argv0, '/');
261 + if (p->argv0base != NULL)
264 + p->argv0base = p->argv0;
267 + /* And read argv[1] */
268 + while ((f = readarg(fp, buf, sizeof(buf))) != EOF)
269 + if (buf[0] != '-') break;
272 + /* Store the name into malloced memory. */
273 + p->argv1 = (char *)xmalloc(f + 1);
274 + strcpy(p->argv1, buf);
276 + /* Get a pointer to the basename. */
277 + p->argv1base = strrchr(p->argv1, '/');
278 + if (p->argv1base != NULL)
281 + p->argv1base = p->argv1;
286 - /* Store the name into malloced memory. */
287 - p->fullname = (char *)xmalloc(f);
288 - strcpy(p->fullname, buf);
290 - /* Get a pointer to the basename. */
291 - if ((p->basename = strrchr(p->fullname, '/')) != NULL)
294 - p->basename = p->fullname;
296 /* Process disappeared.. */
298 @@ -269,19 +322,18 @@
302 -PIDQ *init_pid_q(PIDQ *q)
303 +PIDQ_HEAD *init_pid_q(PIDQ_HEAD *q)
305 - q->front = q->next = q->rear = NULL;
307 + q->head = q->next = q->tail = NULL;
311 -int empty_q(PIDQ *q)
312 +int empty_q(PIDQ_HEAD *q)
314 - return (q->front == NULL);
315 + return (q->head == NULL);
318 -int add_pid_to_q(PIDQ *q, PROC *p)
319 +int add_pid_to_q(PIDQ_HEAD *q, PROC *p)
323 @@ -291,23 +343,23 @@
332 - q->rear->next = tmp;
334 + q->tail->next = tmp;
340 -PROC *get_next_from_pid_q(PIDQ *q)
341 +PROC *get_next_from_pid_q(PIDQ_HEAD *q)
344 - PIDQ *tmp = q->front;
346 + PIDQ *tmp = q->head;
349 - p = q->front->proc;
350 - q->front = tmp->next;
352 + q->head = tmp->next;
356 @@ -316,15 +368,15 @@
359 /* Try to get the process ID of a given process. */
360 -PIDQ *pidof(char *prog)
361 +PIDQ_HEAD *pidof(char *prog)
378 /* Try to stat the executable. */
379 if (prog[0] == '/' && stat(prog, &st) == 0) dostat++;
384 - q = (PIDQ *)xmalloc(sizeof(PIDQ));
385 + q = (PIDQ_HEAD *)xmalloc(sizeof(PIDQ_HEAD));
388 /* First try to find a match based on dev/ino pair. */
389 @@ -349,20 +401,31 @@
392 /* If we didn't find a match based on dev/ino, try the name. */
394 - for (p = plist; p; p = p->next) {
396 + if (!foundone) for (p = plist; p; p = p->next) {
399 - ok += (strcmp(p->fullname, prog) == 0);
400 - ok += (strcmp(p->basename, s) == 0);
402 - if (p->fullname[0] == 0 ||
403 - strchr(p->fullname, ' ') ||
405 - ok += (strcmp(p->statname, s) == 0);
406 + /* Compare name (both basename and full path) */
407 + ok += (p->argv0 && strcmp(p->argv0, prog) == 0);
408 + ok += (p->argv0 && strcmp(p->argv0base, s) == 0);
410 + /* For scripts, compare argv[1] as well. */
411 + if (scripts_too && p->argv1 &&
412 + !strncmp(p->statname, p->argv1base, STATNAMELEN)) {
413 + ok += (strcmp(p->argv1, prog) == 0);
414 + ok += (strcmp(p->argv1base, s) == 0);
417 - if (ok) add_pid_to_q(q, p);
419 + * if we have a space in argv0, process probably
420 + * used setproctitle so try statname.
422 + if (strlen(s) <= STATNAMELEN &&
423 + (p->argv0 == NULL ||
424 + p->argv0[0] == 0 ||
425 + strchr(p->argv0, ' '))) {
426 + ok += (strcmp(p->statname, s) == 0);
428 + if (ok) add_pid_to_q(q, p);
432 @@ -407,12 +470,12 @@
434 int main_pidof(int argc, char **argv)
440 - int i,oind, opt, flags = 0;
441 - pid_t opid[PIDOF_OMITSZ], spid;
444 + pid_t opid[PIDOF_OMITSZ], spid;
447 + int i, oind, opt, flags = 0;
449 for (oind = PIDOF_OMITSZ-1; oind > 0; oind--)
452 /* Main for either killall or pidof. */
453 int main(int argc, char **argv)
462 /* Get program name. */
463 if ((progname = strrchr(argv[0], '/')) == NULL)
465 /* Now connect to syslog. */
466 openlog(progname, LOG_CONS|LOG_PID, LOG_DAEMON);
468 - /* First get the /proc filesystem online. */
471 /* Were we called as 'pidof' ? */
472 if (strcmp(progname, "pidof") == 0)
473 return main_pidof(argc, argv);
475 if ((sig = atoi(argv[1])) <= 0 || sig > 31) usage();
478 + /* First get the /proc filesystem online. */
482 * Ignoring SIGKILL and SIGSTOP do not make sense, but
483 * someday kill(-1, sig) might kill ourself if we don't
484 @@ -534,24 +597,19 @@
486 /* Now stop all processes. */
491 - /* Find out our own 'sid'. */
492 + /* Read /proc filesystem */
493 if (readproc() < 0) {
499 - for (p = plist; p; p = p->next)
500 - if (p->pid == pid) {
505 /* Now kill all processes except our session. */
506 + sid = (int)getsid(0);
507 + pid = (int)getpid();
508 for (p = plist; p; p = p->next)
509 - if (p->pid != pid && p->sid != sid)
510 + if (p->pid != pid && p->sid != sid && !p->kernel)
513 /* And let them continue. */