Magellan Linux

Annotation of /tags/mkinitrd-6_5_1/busybox/procps/fuser.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1123 - (hide annotations) (download)
Wed Aug 18 21:56:57 2010 UTC (13 years, 9 months ago) by niro
Original Path: trunk/mkinitrd-magellan/busybox/procps/fuser.c
File MIME type: text/plain
File size: 6086 byte(s)
-updated to busybox-1.17.1
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * tiny fuser implementation
4     *
5     * Copyright 2004 Tony J. White
6     *
7 niro 984 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 niro 532 */
9    
10 niro 816 #include "libbb.h"
11 niro 532
12 niro 816 #define MAX_LINE 255
13 niro 532
14 niro 816 #define OPTION_STRING "mks64"
15     enum {
16     OPT_MOUNT = (1 << 0),
17     OPT_KILL = (1 << 1),
18     OPT_SILENT = (1 << 2),
19     OPT_IP6 = (1 << 3),
20     OPT_IP4 = (1 << 4),
21     };
22 niro 532
23     typedef struct inode_list {
24 niro 816 struct inode_list *next;
25 niro 532 ino_t inode;
26     dev_t dev;
27     } inode_list;
28    
29     typedef struct pid_list {
30 niro 816 struct pid_list *next;
31 niro 532 pid_t pid;
32     } pid_list;
33    
34 niro 1123
35     struct globals {
36     pid_list *pid_list_head;
37     inode_list *inode_list_head;
38     };
39     #define G (*(struct globals*)&bb_common_bufsiz1)
40     #define INIT_G() do { } while (0)
41    
42    
43     static void add_pid(const pid_t pid)
44 niro 532 {
45 niro 1123 pid_list **curr = &G.pid_list_head;
46    
47     while (*curr) {
48     if ((*curr)->pid == pid)
49     return;
50     curr = &(*curr)->next;
51 niro 532 }
52    
53 niro 1123 *curr = xzalloc(sizeof(pid_list));
54     (*curr)->pid = pid;
55 niro 532 }
56    
57 niro 1123 static void add_inode(const struct stat *st)
58 niro 532 {
59 niro 1123 inode_list **curr = &G.inode_list_head;
60 niro 532
61 niro 1123 while (*curr) {
62     if ((*curr)->dev == st->st_dev
63     && (*curr)->inode == st->st_ino
64     ) {
65     return;
66     }
67     curr = &(*curr)->next;
68 niro 532 }
69    
70 niro 1123 *curr = xzalloc(sizeof(inode_list));
71     (*curr)->dev = st->st_dev;
72     (*curr)->inode = st->st_ino;
73 niro 532 }
74    
75 niro 1123 static void scan_proc_net(const char *path, unsigned port)
76 niro 532 {
77 niro 1123 char line[MAX_LINE + 1];
78 niro 816 long long uint64_inode;
79     unsigned tmp_port;
80 niro 532 FILE *f;
81 niro 1123 struct stat st;
82     int fd;
83 niro 532
84 niro 1123 /* find socket dev */
85     st.st_dev = 0;
86     fd = socket(AF_INET, SOCK_DGRAM, 0);
87     if (fd >= 0) {
88     fstat(fd, &st);
89     close(fd);
90     }
91 niro 532
92 niro 816 f = fopen_for_read(path);
93     if (!f)
94 niro 1123 return;
95 niro 816
96     while (fgets(line, MAX_LINE, f)) {
97     char addr[68];
98     if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
99     "%*x:%*x %*x %*d %*d %llu",
100     addr, &tmp_port, &uint64_inode) == 3
101     ) {
102     int len = strlen(addr);
103     if (len == 8 && (option_mask32 & OPT_IP6))
104     continue;
105     if (len > 8 && (option_mask32 & OPT_IP4))
106     continue;
107     if (tmp_port == port) {
108 niro 1123 st.st_ino = uint64_inode;
109     add_inode(&st);
110 niro 532 }
111     }
112     }
113     fclose(f);
114     }
115    
116 niro 1123 static int search_dev_inode(const struct stat *st)
117 niro 532 {
118 niro 1123 inode_list *ilist = G.inode_list_head;
119    
120 niro 816 while (ilist) {
121 niro 1123 if (ilist->dev == st->st_dev) {
122 niro 816 if (option_mask32 & OPT_MOUNT)
123     return 1;
124 niro 1123 if (ilist->inode == st->st_ino)
125 niro 816 return 1;
126     }
127     ilist = ilist->next;
128 niro 532 }
129     return 0;
130     }
131    
132 niro 1123 static void scan_pid_maps(const char *fname, pid_t pid)
133 niro 532 {
134     FILE *file;
135 niro 816 char line[MAX_LINE + 1];
136 niro 532 int major, minor;
137     long long uint64_inode;
138 niro 1123 struct stat st;
139 niro 532
140 niro 816 file = fopen_for_read(fname);
141     if (!file)
142 niro 1123 return;
143    
144 niro 816 while (fgets(line, MAX_LINE, file)) {
145     if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3)
146     continue;
147 niro 1123 st.st_ino = uint64_inode;
148     if (major == 0 && minor == 0 && st.st_ino == 0)
149 niro 816 continue;
150 niro 1123 st.st_dev = makedev(major, minor);
151     if (search_dev_inode(&st))
152     add_pid(pid);
153 niro 532 }
154     fclose(file);
155     }
156    
157 niro 1123 static void scan_link(const char *lname, pid_t pid)
158 niro 532 {
159 niro 1123 struct stat st;
160 niro 532
161 niro 1123 if (stat(lname, &st) >= 0) {
162     if (search_dev_inode(&st))
163     add_pid(pid);
164     }
165 niro 532 }
166    
167 niro 1123 static void scan_dir_links(const char *dname, pid_t pid)
168 niro 532 {
169     DIR *d;
170     struct dirent *de;
171     char *lname;
172    
173 niro 816 d = opendir(dname);
174     if (!d)
175 niro 1123 return;
176    
177 niro 816 while ((de = readdir(d)) != NULL) {
178     lname = concat_subpath_file(dname, de->d_name);
179     if (lname == NULL)
180     continue;
181 niro 1123 scan_link(lname, pid);
182 niro 816 free(lname);
183 niro 532 }
184 niro 816 closedir(d);
185 niro 532 }
186    
187 niro 816 /* NB: does chdir internally */
188 niro 1123 static void scan_proc_pids(void)
189 niro 532 {
190     DIR *d;
191     struct dirent *de;
192     pid_t pid;
193    
194 niro 816 xchdir("/proc");
195     d = opendir("/proc");
196     if (!d)
197 niro 1123 return;
198 niro 816
199     while ((de = readdir(d)) != NULL) {
200     pid = (pid_t)bb_strtou(de->d_name, NULL, 10);
201     if (errno)
202 niro 532 continue;
203 niro 816 if (chdir(de->d_name) < 0)
204     continue;
205 niro 1123 scan_link("cwd", pid);
206     scan_link("exe", pid);
207     scan_link("root", pid);
208    
209     scan_dir_links("fd", pid);
210     scan_dir_links("lib", pid);
211     scan_dir_links("mmap", pid);
212    
213     scan_pid_maps("maps", pid);
214 niro 816 xchdir("/proc");
215 niro 532 }
216     closedir(d);
217     }
218    
219 niro 816 int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
220     int fuser_main(int argc UNUSED_PARAM, char **argv)
221 niro 532 {
222 niro 816 pid_list *plist;
223 niro 1123 pid_t mypid;
224 niro 816 char **pp;
225 niro 1123 struct stat st;
226 niro 816 unsigned port;
227     int opt;
228 niro 1123 int exitcode;
229 niro 816 int killsig;
230     /*
231 niro 1123 fuser [OPTIONS] FILE or PORT/PROTO
232 niro 816 Find processes which use FILEs or PORTs
233     -m Find processes which use same fs as FILEs
234     -4 Search only IPv4 space
235     -6 Search only IPv6 space
236 niro 1123 -s Don't display PIDs
237     -k Kill found processes
238     -SIGNAL Signal to send (default: KILL)
239 niro 816 */
240     /* Handle -SIGNAL. Oh my... */
241 niro 1123 killsig = SIGKILL; /* yes, the default is not SIGTERM */
242 niro 816 pp = argv;
243     while (*++pp) {
244     char *arg = *pp;
245     if (arg[0] != '-')
246     continue;
247     if (arg[1] == '-' && arg[2] == '\0') /* "--" */
248     break;
249     if ((arg[1] == '4' || arg[1] == '6') && arg[2] == '\0')
250     continue; /* it's "-4" or "-6" */
251     opt = get_signum(&arg[1]);
252     if (opt < 0)
253     continue;
254     /* "-SIGNAL" option found. Remove it and bail out */
255     killsig = opt;
256     do {
257     pp[0] = arg = pp[1];
258     pp++;
259     } while (arg);
260     break;
261     }
262 niro 532
263 niro 1123 opt_complementary = "-1"; /* at least one param */
264 niro 816 opt = getopt32(argv, OPTION_STRING);
265     argv += optind;
266 niro 532
267 niro 816 pp = argv;
268     while (*pp) {
269 niro 1123 /* parse net arg */
270     char path[20], tproto[5];
271     if (sscanf(*pp, "%u/%4s", &port, tproto) != 2)
272     goto file;
273     sprintf(path, "/proc/net/%s", tproto);
274     if (access(path, R_OK) != 0) { /* PORT/PROTO */
275     scan_proc_net(path, port);
276 niro 816 } else { /* FILE */
277 niro 1123 file:
278     xstat(*pp, &st);
279     add_inode(&st);
280 niro 532 }
281 niro 816 pp++;
282 niro 532 }
283    
284 niro 1123 scan_proc_pids(); /* changes dir to "/proc" */
285 niro 816
286 niro 1123 mypid = getpid();
287     plist = G.pid_list_head;
288     while (1) {
289     if (!plist)
290     return EXIT_FAILURE;
291     if (plist->pid != mypid)
292     break;
293     plist = plist->next;
294 niro 532 }
295 niro 1123
296     exitcode = EXIT_SUCCESS;
297     do {
298     if (plist->pid != mypid) {
299     if (opt & OPT_KILL) {
300     if (kill(plist->pid, killsig) != 0) {
301     bb_perror_msg("kill pid %u", (unsigned)plist->pid);
302     exitcode = EXIT_FAILURE;
303     }
304     }
305     if (!(opt & OPT_SILENT)) {
306     printf("%u ", (unsigned)plist->pid);
307     }
308     }
309     plist = plist->next;
310     } while (plist);
311    
312     if (!(opt & (OPT_SILENT))) {
313     bb_putchar('\n');
314     }
315    
316     return exitcode;
317 niro 532 }