allow coexistance of N build and AC build.
[tomato.git] / release / src / router / shared / process.c
blob37967a767147339d0a339bdeca53c00a33d94b0a
1 /*
3 Tomato Firmware
4 Copyright (C) 2006-2009 Jonathan Zarate
6 */
7 #include <string.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <signal.h>
12 #include <dirent.h>
14 #include "shared.h"
17 //# cat /proc/1/stat
18 //1 (init) S 0 0 0 0 -1 256 287 10043 109 21377 7 110 473 1270 9 0 0 0 27 1810432 126 2147483647 4194304 4369680 2147450688 2147449688 717374852 0 0 0 514751 2147536844 0 0 0 0
20 char *psname(int pid, char *buffer, int maxlen)
22 char buf[512];
23 char path[64];
24 char *p;
26 if (maxlen <= 0) return NULL;
27 *buffer = 0;
28 sprintf(path, "/proc/%d/stat", pid);
29 if ((f_read_string(path, buf, sizeof(buf)) > 4) && ((p = strrchr(buf, ')')) != NULL)) {
30 *p = 0;
31 if (((p = strchr(buf, '(')) != NULL) && (atoi(buf) == pid)) {
32 strlcpy(buffer, p + 1, maxlen);
35 return buffer;
38 /* There is a race condition when a brand new daemon starts up using the double-fork method.
39 * Example: dnsmasq
40 * There are 2 windows of vulnerability.
41 * 1) At the beginning of process startup, the new process has the wrong name, such as "init" because
42 * init forks a child which execve()'s dnsmasq, but the execve() hasn't happened yet.
43 * 2) At the end of process startup, the timing can be such that we don't see the long-lived process,
44 * only the pid(s) of the short-lived process(es), but the psname fails because they've exited by then.
46 * The 1st can be covered by a retry after a slight delay.
47 * The 2nd can be covered by a retry immediately.
49 static int _pidof(const char *name, pid_t **pids)
51 const char *p;
52 char *e;
53 DIR *dir;
54 struct dirent *de;
55 pid_t i;
56 int count;
57 char buf[256];
59 count = 0;
60 if (pids != NULL)
61 *pids = NULL;
62 if ((p = strrchr(name, '/')) != NULL) name = p + 1;
63 if ((dir = opendir("/proc")) != NULL) {
64 while ((de = readdir(dir)) != NULL) {
65 i = strtol(de->d_name, &e, 10);
66 if (*e != 0) continue;
67 if (strcmp(name, psname(i, buf, sizeof(buf))) == 0) {
68 if (pids == NULL) {
69 count = i;
70 break;
72 if ((*pids = realloc(*pids, sizeof(pid_t) * (count + 1))) == NULL) {
73 return -1;
75 (*pids)[count++] = i;
79 closedir(dir);
80 return count;
83 /* If we hit both windows, it will take three tries to discover the pid. */
84 int pidof(const char *name)
86 pid_t p;
88 p = _pidof(name, NULL);
89 if (p < 1) {
90 usleep(10 * 1000);
91 p = _pidof(name, NULL);
92 if (p < 1)
93 p = _pidof(name, NULL);
95 if (p < 1)
96 return -1;
97 return p;
100 int ppid(int pid) {
101 char buf[512];
102 char path[64];
103 int ppid = 0;
105 buf[0] = 0;
106 sprintf(path, "/proc/%d/stat", pid);
107 if ((f_read_string(path, buf, sizeof(buf)) > 4))
108 sscanf(buf, "%*d %*s %*c %d", &ppid);
110 return ppid;
114 int killall(const char *name, int sig)
116 pid_t *pids;
117 int i;
118 int r;
120 if ((i = _pidof(name, &pids)) > 0) {
121 r = 0;
122 do {
123 r |= kill(pids[--i], sig);
124 } while (i > 0);
125 free(pids);
126 return r;
128 return -2;