aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-17 08:44:58 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-17 08:44:58 +0000
commitafc4113ed747330c7f0cc281618bf3e19579810d (patch)
tree19f473eec85cd12174b4ba59fb0a807559366c18
parentcdf62770af9e8bf7d5bb2344ddef8acb3216cfe2 (diff)
downloadbusybox-w32-afc4113ed747330c7f0cc281618bf3e19579810d.tar.gz
busybox-w32-afc4113ed747330c7f0cc281618bf3e19579810d.tar.bz2
busybox-w32-afc4113ed747330c7f0cc281618bf3e19579810d.zip
fuser: bugfixes and shrink. It was assuming that xmalloc zeroes returned area!
function old new delta scan_dir_links - 106 +106 add_inode - 89 +89 scan_link - 78 +78 file_to_dev_inode - 64 +64 search_dev_inode - 63 +63 add_pid - 39 +39 packed_usage 23948 23928 -20 fuser_add_pid 49 - -49 fuser_file_to_dev_inode 64 - -64 fuser_search_dev_inode 77 - -77 fuser_scan_link 91 - -91 fuser_scan_dir_links 108 - -108 fuser_add_inode 124 - -124 fuser_main 1450 1243 -207 ------------------------------------------------------------------------------ (add/remove: 6/6 grow/shrink: 0/2 up/down: 439/-740) Total: -301 bytes text data bss dec hex filename 798327 658 7428 806413 c4e0d busybox_old 797988 658 7428 806074 c4cba busybox_unstripped
-rw-r--r--include/usage.h23
-rw-r--r--procps/fuser.c400
2 files changed, 191 insertions, 232 deletions
diff --git a/include/usage.h b/include/usage.h
index fdf96d256..2a49454a1 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -757,7 +757,7 @@ USE_FEATURE_BRCTL_FANCY("\n" \
757#define dos2unix_full_usage \ 757#define dos2unix_full_usage \
758 "Convert FILE from dos to unix format.\n" \ 758 "Convert FILE from dos to unix format.\n" \
759 "When no file is given, use stdin/stdout.\n" \ 759 "When no file is given, use stdin/stdout.\n" \
760 "\nOptions:\n" \ 760 "\nOptions:" \
761 "\n -u dos2unix" \ 761 "\n -u dos2unix" \
762 "\n -d unix2dos" 762 "\n -d unix2dos"
763 763
@@ -1024,7 +1024,7 @@ USE_FEATURE_BRCTL_FANCY("\n" \
1024 "[-C CYLINDERS] [-H HEADS] [-S SECTORS] [-b SSZ] DISK" 1024 "[-C CYLINDERS] [-H HEADS] [-S SECTORS] [-b SSZ] DISK"
1025#define fdisk_full_usage \ 1025#define fdisk_full_usage \
1026 "Change partition table\n" \ 1026 "Change partition table\n" \
1027 "\nOptions:\n" \ 1027 "\nOptions:" \
1028 "\n -u Start and End are in sectors (instead of cylinders)" \ 1028 "\n -u Start and End are in sectors (instead of cylinders)" \
1029 "\n -l Show partition table for each DISK, then exit" \ 1029 "\n -l Show partition table for each DISK, then exit" \
1030 USE_FEATURE_FDISK_BLKSIZE( \ 1030 USE_FEATURE_FDISK_BLKSIZE( \
@@ -1213,13 +1213,14 @@ USE_FEATURE_BRCTL_FANCY("\n" \
1213#define fuser_trivial_usage \ 1213#define fuser_trivial_usage \
1214 "[options] FILE or PORT/PROTO" 1214 "[options] FILE or PORT/PROTO"
1215#define fuser_full_usage \ 1215#define fuser_full_usage \
1216 "Options:\n" \ 1216 "Find processes which use FILEs or PORTs\n" \
1217 " -m Show all processes on the same mounted fs\n" \ 1217 "\nOptions:" \
1218 " -s Don't print or kill anything\n" \ 1218 "\n -m Find processes which use same fs as FILEs" \
1219 " -4 Search only IPv4 space\n" \ 1219 "\n -4 Search only IPv4 space" \
1220 " -6 Search only IPv6 space\n" \ 1220 "\n -6 Search only IPv6 space" \
1221 " -k Kill all processes that match\n" \ 1221 "\n -s Silent: just exit with 0 if any processes are found" \
1222 " -SIGNAL Signal to send (default: TERM)" 1222 "\n -k Kill found processes (otherwise display PIDs)" \
1223 "\n -SIGNAL Signal to send (default: TERM)"
1223 1224
1224#define getenforce_trivial_usage 1225#define getenforce_trivial_usage
1225#define getenforce_full_usage 1226#define getenforce_full_usage
@@ -4093,7 +4094,7 @@ USE_FEATURE_BRCTL_FANCY("\n" \
4093 "[flags] FILESYSTEM|DIRECTORY" 4094 "[flags] FILESYSTEM|DIRECTORY"
4094#define umount_full_usage \ 4095#define umount_full_usage \
4095 "Unmount file systems" \ 4096 "Unmount file systems" \
4096 "\n\nOptions:\n" \ 4097 "\n\nOptions:" \
4097 USE_FEATURE_UMOUNT_ALL( \ 4098 USE_FEATURE_UMOUNT_ALL( \
4098 "\n -a Unmount all file systems" USE_FEATURE_MTAB_SUPPORT(" in /etc/mtab")) \ 4099 "\n -a Unmount all file systems" USE_FEATURE_MTAB_SUPPORT(" in /etc/mtab")) \
4099 USE_FEATURE_MTAB_SUPPORT( \ 4100 USE_FEATURE_MTAB_SUPPORT( \
@@ -4168,7 +4169,7 @@ USE_FEATURE_BRCTL_FANCY("\n" \
4168#define unix2dos_full_usage \ 4169#define unix2dos_full_usage \
4169 "Convert FILE from unix to dos format.\n" \ 4170 "Convert FILE from unix to dos format.\n" \
4170 "When no file is given, use stdin/stdout.\n" \ 4171 "When no file is given, use stdin/stdout.\n" \
4171 "\nOptions:\n" \ 4172 "\nOptions:" \
4172 "\n -u dos2unix" \ 4173 "\n -u dos2unix" \
4173 "\n -d unix2dos" 4174 "\n -d unix2dos"
4174 4175
diff --git a/procps/fuser.c b/procps/fuser.c
index 36d634d91..d625b16ab 100644
--- a/procps/fuser.c
+++ b/procps/fuser.c
@@ -10,187 +10,148 @@
10 10
11#include "libbb.h" 11#include "libbb.h"
12 12
13#define FUSER_PROC_DIR "/proc" 13#define MAX_LINE 255
14#define FUSER_MAX_LINE 255
15 14
16#define FUSER_OPT_MOUNT 1 15#define OPTION_STRING "mks64"
17#define FUSER_OPT_KILL 2 16enum {
18#define FUSER_OPT_SILENT 4 17 OPT_MOUNT = (1 << 0),
19#define FUSER_OPT_IP6 8 18 OPT_KILL = (1 << 1),
20#define FUSER_OPT_IP4 16 19 OPT_SILENT = (1 << 2),
20 OPT_IP6 = (1 << 3),
21 OPT_IP4 = (1 << 4),
22};
21 23
22typedef struct inode_list { 24typedef struct inode_list {
25 struct inode_list *next;
23 ino_t inode; 26 ino_t inode;
24 dev_t dev; 27 dev_t dev;
25 struct inode_list *next;
26} inode_list; 28} inode_list;
27 29
28typedef struct pid_list { 30typedef struct pid_list {
29 pid_t pid;
30 struct pid_list *next; 31 struct pid_list *next;
32 pid_t pid;
31} pid_list; 33} pid_list;
32 34
33static int fuser_option(char *option) 35static dev_t find_socket_dev(void)
34{ 36{
35 int opt = 0; 37 int fd = socket(AF_INET, SOCK_DGRAM, 0);
36 38 if (fd >= 0) {
37 if (!option[0]) 39 struct stat buf;
38 return 0; 40 int r = fstat(fd, &buf);
39 if (option[0] != '-') 41 close(fd);
40 return 0; 42 if (r == 0)
41 ++option; 43 return buf.st_dev;
42 while (*option != '\0') {
43 if (*option == 'm') opt |= FUSER_OPT_MOUNT;
44 else if (*option == 'k') opt |= FUSER_OPT_KILL;
45 else if (*option == 's') opt |= FUSER_OPT_SILENT;
46 else if (*option == '6') opt |= FUSER_OPT_IP6;
47 else if (*option == '4') opt |= FUSER_OPT_IP4;
48 else
49 bb_error_msg_and_die("unsupported option '%c'", *option);
50 ++option;
51 } 44 }
52 return opt; 45 return 0;
53} 46}
54 47
55static int fuser_file_to_dev_inode(const char *filename, 48static int file_to_dev_inode(const char *filename, dev_t *dev, ino_t *inode)
56 dev_t *dev, ino_t *inode)
57{ 49{
58 struct stat f_stat; 50 struct stat f_stat;
59 if ((stat(filename, &f_stat)) < 0) 51 if (stat(filename, &f_stat))
60 return 0; 52 return 0;
61 *inode = f_stat.st_ino; 53 *inode = f_stat.st_ino;
62 *dev = f_stat.st_dev; 54 *dev = f_stat.st_dev;
63 return 1; 55 return 1;
64} 56}
65 57
66static int fuser_find_socket_dev(dev_t *dev) 58static char *parse_net_arg(const char *arg, unsigned *port)
67{ 59{
68 int fd = socket(PF_INET, SOCK_DGRAM,0); 60 char path[12], tproto[5];
69 struct stat buf; 61
70 62 if (sscanf(arg, "%u/%4s", port, tproto) != 2)
71 if (fd >= 0 && (fstat(fd, &buf)) == 0) { 63 return NULL;
72 *dev = buf.st_dev; 64 sprintf(path, "net/%s", tproto);
73 close(fd); 65 if (access(path, R_OK) != 0)
74 return 1; 66 return NULL;
75 } 67 return xstrdup(tproto);
76 return 0;
77} 68}
78 69
79static int fuser_parse_net_arg(const char *filename, 70static pid_list *add_pid(pid_list *plist, pid_t pid)
80 const char **proto, int *port)
81{ 71{
82 char path[sizeof(FUSER_PROC_DIR)+12], tproto[5]; 72 pid_list *curr = plist;
83
84 if ((sscanf(filename, "%d/%4s", port, tproto)) != 2)
85 return 0;
86 sprintf(path, FUSER_PROC_DIR "/net/%s", tproto);
87 if ((access(path, R_OK)) != 0)
88 return 0;
89 *proto = xstrdup(tproto);
90 return 1;
91}
92
93static int fuser_add_pid(pid_list *plist, pid_t pid)
94{
95 pid_list *curr = NULL, *last = NULL;
96
97 if (plist->pid == 0)
98 plist->pid = pid;
99 curr = plist;
100 while (curr != NULL) { 73 while (curr != NULL) {
101 if (curr->pid == pid) 74 if (curr->pid == pid)
102 return 1; 75 return plist;
103 last = curr;
104 curr = curr->next; 76 curr = curr->next;
105 } 77 }
106 curr = xzalloc(sizeof(pid_list)); 78 curr = xmalloc(sizeof(pid_list));
107 last->next = curr;
108 curr->pid = pid; 79 curr->pid = pid;
109 /*curr->next = NULL;*/ 80 curr->next = plist;
110 return 1; 81 return curr;
111} 82}
112 83
113static int fuser_add_inode(inode_list *ilist, dev_t dev, ino_t inode) 84static inode_list *add_inode(inode_list *ilist, dev_t dev, ino_t inode)
114{ 85{
115 inode_list *curr = NULL, *last = NULL; 86 inode_list *curr = ilist;
116
117 if (!ilist->inode && !ilist->dev) {
118 ilist->dev = dev;
119 ilist->inode = inode;
120 }
121 curr = ilist;
122 while (curr != NULL) { 87 while (curr != NULL) {
123 if (curr->inode == inode && curr->dev == dev) 88 if (curr->inode == inode && curr->dev == dev)
124 return 1; 89 return ilist;
125 last = curr;
126 curr = curr->next; 90 curr = curr->next;
127 } 91 }
128 curr = xzalloc(sizeof(inode_list)); 92 curr = xmalloc(sizeof(inode_list));
129 last->next = curr;
130 curr->dev = dev; 93 curr->dev = dev;
131 curr->inode = inode; 94 curr->inode = inode;
132 /*curr->next = NULL;*/ 95 curr->next = ilist;
133 return 1; 96 return curr;
134} 97}
135 98
136static int fuser_scan_proc_net(int opts, const char *proto, 99static inode_list *scan_proc_net(const char *proto,
137 int port, inode_list *ilist) 100 unsigned port, inode_list *ilist)
138{ 101{
139 char path[sizeof(FUSER_PROC_DIR)+12], line[FUSER_MAX_LINE+1]; 102 char path[12], line[MAX_LINE + 1];
140 char addr[128]; 103 char addr[128];
141 ino_t tmp_inode; 104 ino_t tmp_inode;
142 dev_t tmp_dev; 105 dev_t tmp_dev;
143 long long uint64_inode; 106 long long uint64_inode;
144 int tmp_port; 107 unsigned tmp_port;
145 FILE *f; 108 FILE *f;
146 109
147 if (!fuser_find_socket_dev(&tmp_dev)) 110 tmp_dev = find_socket_dev();
148 tmp_dev = 0;
149 sprintf(path, FUSER_PROC_DIR "/net/%s", proto);
150 111
112 sprintf(path, "net/%s", proto);
151 f = fopen(path, "r"); 113 f = fopen(path, "r");
152 if (!f) 114 if (!f)
153 return 0; 115 return ilist;
154 while (fgets(line, FUSER_MAX_LINE, f)) { 116
117 while (fgets(line, MAX_LINE, f)) {
155 if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x " 118 if (sscanf(line, "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x %*x:%*x "
156 "%*x:%*x %*x %*d %*d %llu", 119 "%*x:%*x %*x %*d %*d %llu",
157 addr, &tmp_port, &uint64_inode) == 3 120 addr, &tmp_port, &uint64_inode) == 3
158 ) { 121 ) {
159 if (strlen(addr) == 8 && (opts & FUSER_OPT_IP6)) 122 if (strlen(addr) == 8 && (option_mask32 & OPT_IP6))
160 continue; 123 continue;
161 if (strlen(addr) > 8 && (opts & FUSER_OPT_IP4)) 124 if (strlen(addr) > 8 && (option_mask32 & OPT_IP4))
162 continue; 125 continue;
163 if (tmp_port == port) { 126 if (tmp_port == port) {
164 tmp_inode = uint64_inode; 127 tmp_inode = uint64_inode;
165 fuser_add_inode(ilist, tmp_dev, tmp_inode); 128 ilist = add_inode(ilist, tmp_dev, tmp_inode);
166 } 129 }
167 } 130 }
168 } 131 }
169 fclose(f); 132 fclose(f);
170 return 1; 133 return ilist;
171} 134}
172 135
173static int fuser_search_dev_inode(int opts, inode_list *ilist, 136static int search_dev_inode(inode_list *ilist, dev_t dev, ino_t inode)
174 dev_t dev, ino_t inode)
175{ 137{
176 inode_list *curr; 138 while (ilist) {
177 curr = ilist; 139 if (ilist->dev == dev) {
178 140 if (option_mask32 & OPT_MOUNT)
179 while (curr) { 141 return 1;
180 if ((opts & FUSER_OPT_MOUNT) && curr->dev == dev) 142 if (ilist->inode == inode)
181 return 1; 143 return 1;
182 if (curr->inode == inode && curr->dev == dev) 144 }
183 return 1; 145 ilist = ilist->next;
184 curr = curr->next;
185 } 146 }
186 return 0; 147 return 0;
187} 148}
188 149
189static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid, 150static pid_list *scan_pid_maps(const char *fname, pid_t pid,
190 inode_list *ilist, pid_list *plist) 151 inode_list *ilist, pid_list *plist)
191{ 152{
192 FILE *file; 153 FILE *file;
193 char line[FUSER_MAX_LINE + 1]; 154 char line[MAX_LINE + 1];
194 int major, minor; 155 int major, minor;
195 ino_t inode; 156 ino_t inode;
196 long long uint64_inode; 157 long long uint64_inode;
@@ -198,37 +159,36 @@ static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid,
198 159
199 file = fopen(fname, "r"); 160 file = fopen(fname, "r");
200 if (!file) 161 if (!file)
201 return 0; 162 return plist;
202 while (fgets(line, FUSER_MAX_LINE, file)) { 163 while (fgets(line, MAX_LINE, file)) {
203 if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3) 164 if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3)
204 continue; 165 continue;
205 inode = uint64_inode; 166 inode = uint64_inode;
206 if (major == 0 && minor == 0 && inode == 0) 167 if (major == 0 && minor == 0 && inode == 0)
207 continue; 168 continue;
208 dev = makedev(major, minor); 169 dev = makedev(major, minor);
209 if (fuser_search_dev_inode(opts, ilist, dev, inode)) { 170 if (search_dev_inode(ilist, dev, inode))
210 fuser_add_pid(plist, pid); 171 plist = add_pid(plist, pid);
211 }
212 } 172 }
213 fclose(file); 173 fclose(file);
214 return 1; 174 return plist;
215} 175}
216 176
217static int fuser_scan_link(int opts, const char *lname, pid_t pid, 177static pid_list *scan_link(const char *lname, pid_t pid,
218 inode_list *ilist, pid_list *plist) 178 inode_list *ilist, pid_list *plist)
219{ 179{
220 ino_t inode; 180 ino_t inode;
221 dev_t dev; 181 dev_t dev;
222 182
223 if (!fuser_file_to_dev_inode(lname, &dev, &inode)) 183 if (!file_to_dev_inode(lname, &dev, &inode))
224 return 0; 184 return plist;
225 if (fuser_search_dev_inode(opts, ilist, dev, inode)) 185 if (search_dev_inode(ilist, dev, inode))
226 fuser_add_pid(plist, pid); 186 plist = add_pid(plist, pid);
227 return 1; 187 return plist;
228} 188}
229 189
230static int fuser_scan_dir_links(int opts, const char *dname, pid_t pid, 190static pid_list *scan_dir_links(const char *dname, pid_t pid,
231 inode_list *ilist, pid_list *plist) 191 inode_list *ilist, pid_list *plist)
232{ 192{
233 DIR *d; 193 DIR *d;
234 struct dirent *de; 194 struct dirent *de;
@@ -236,82 +196,72 @@ static int fuser_scan_dir_links(int opts, const char *dname, pid_t pid,
236 196
237 d = opendir(dname); 197 d = opendir(dname);
238 if (!d) 198 if (!d)
239 return 0; 199 return plist;
240 while ((de = readdir(d)) != NULL) { 200 while ((de = readdir(d)) != NULL) {
241 lname = concat_subpath_file(dname, de->d_name); 201 lname = concat_subpath_file(dname, de->d_name);
242 if (lname == NULL) 202 if (lname == NULL)
243 continue; 203 continue;
244 fuser_scan_link(opts, lname, pid, ilist, plist); 204 plist = scan_link(lname, pid, ilist, plist);
245 free(lname); 205 free(lname);
246 } 206 }
247 closedir(d); 207 closedir(d);
248 return 1; 208 return plist;
249} 209}
250 210
251static int fuser_scan_proc_pids(int opts, inode_list *ilist, pid_list *plist) 211static pid_list *scan_proc_pids(inode_list *ilist)
252{ 212{
253 DIR *d; 213 DIR *d;
254 struct dirent *de; 214 struct dirent *de;
255 pid_t pid; 215 pid_t pid;
256 char *dname; 216 pid_list *plist;
257 217
258 d = opendir(FUSER_PROC_DIR); 218 d = opendir(".");
259 if (!d) 219 if (!d)
260 return 0; 220 return NULL;
221
222 plist = NULL;
261 while ((de = readdir(d)) != NULL) { 223 while ((de = readdir(d)) != NULL) {
262 pid = (pid_t)atoi(de->d_name); 224 pid = (pid_t)bb_strtou(de->d_name, NULL, 10);
263 if (!pid) 225 if (errno)
264 continue; 226 continue;
265 dname = concat_subpath_file(FUSER_PROC_DIR, de->d_name); 227 if (chdir(de->d_name) < 0)
266 if (chdir(dname) < 0) {
267 free(dname);
268 continue; 228 continue;
269 } 229 plist = scan_link("cwd", pid, ilist, plist);
270 free(dname); 230 plist = scan_link("exe", pid, ilist, plist);
271 fuser_scan_link(opts, "cwd", pid, ilist, plist); 231 plist = scan_link("root", pid, ilist, plist);
272 fuser_scan_link(opts, "exe", pid, ilist, plist); 232 plist = scan_dir_links("fd", pid, ilist, plist);
273 fuser_scan_link(opts, "root", pid, ilist, plist); 233 plist = scan_dir_links("lib", pid, ilist, plist);
274 fuser_scan_dir_links(opts, "fd", pid, ilist, plist); 234 plist = scan_dir_links("mmap", pid, ilist, plist);
275 fuser_scan_dir_links(opts, "lib", pid, ilist, plist); 235 plist = scan_pid_maps("maps", pid, ilist, plist);
276 fuser_scan_dir_links(opts, "mmap", pid, ilist, plist); 236 xchdir("/proc");
277 fuser_scan_pid_maps(opts, "maps", pid, ilist, plist);
278 chdir("..");
279 } 237 }
280 closedir(d); 238 closedir(d);
281 return 1; 239 return plist;
282} 240}
283 241
284static int fuser_print_pid_list(pid_list *plist) 242static int print_pid_list(pid_list *plist)
285{ 243{
286 pid_list *curr = plist; 244 while (plist != NULL) {
287 245 printf("%u ", (unsigned)plist->pid);
288 if (plist == NULL) 246 plist = plist->next;
289 return 0;
290 while (curr != NULL) {
291 if (curr->pid > 0)
292 printf("%d ", curr->pid);
293 curr = curr->next;
294 } 247 }
295 bb_putchar('\n'); 248 bb_putchar('\n');
296 return 1; 249 return 1;
297} 250}
298 251
299static int fuser_kill_pid_list(pid_list *plist, int sig) 252static int kill_pid_list(pid_list *plist, int sig)
300{ 253{
301 pid_list *curr = plist;
302 pid_t mypid = getpid(); 254 pid_t mypid = getpid();
303 int success = 1; 255 int success = 1;
304 256
305 if (plist == NULL) 257 while (plist != NULL) {
306 return 0; 258 if (plist->pid != mypid) {
307 while (curr != NULL) { 259 if (kill(plist->pid, sig) != 0) {
308 if (curr->pid > 0 && curr->pid != mypid) { 260 bb_perror_msg("kill pid %u", (unsigned)plist->pid);
309 if (kill(curr->pid, sig) != 0) {
310 bb_perror_msg("kill pid '%d'", curr->pid);
311 success = 0; 261 success = 0;
312 } 262 }
313 } 263 }
314 curr = curr->next; 264 plist = plist->next;
315 } 265 }
316 return success; 266 return success;
317} 267}
@@ -319,69 +269,77 @@ static int fuser_kill_pid_list(pid_list *plist, int sig)
319int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 269int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
320int fuser_main(int argc, char **argv) 270int fuser_main(int argc, char **argv)
321{ 271{
322 /*static -- huh???*/ int opt = 0; /* FUSER_OPT_ */ 272 pid_list *plist;
323 273 inode_list *ilist;
324 int port, i, optn; 274 char **pp;
325 int* fni; /* file name indexes of argv */
326 int fnic = 0; /* file name index count */
327 const char *proto;
328 dev_t dev; 275 dev_t dev;
329 ino_t inode; 276 ino_t inode;
330 pid_list *pids; 277 unsigned port;
331 inode_list *inodes; 278 int opt;
332 int killsig = SIGTERM; 279 int success;
333 int success = 1; 280 int killsig;
334 281/*
335 if (argc < 2) 282fuser [options] FILEs or PORT/PROTOs
336 bb_show_usage(); 283Find processes which use FILEs or PORTs
337 284 -m Find processes which use same fs as FILEs
338 fni = xmalloc(sizeof(int)); 285 -4 Search only IPv4 space
339 for (i = 1; i < argc; i++) { 286 -6 Search only IPv6 space
340 optn = fuser_option(argv[i]); 287 -s Silent: just exit with 0 if any processes are found
341 if (optn) 288 -k Kill found processes (otherwise display PIDs)
342 opt |= optn; 289 -SIGNAL Signal to send (default: TERM)
343 else if (argv[i][0] == '-') { 290*/
344 killsig = get_signum(argv[i]+1); 291 /* Handle -SIGNAL. Oh my... */
345 if (killsig < 0) 292 killsig = SIGTERM;
346 killsig = SIGTERM; 293 pp = argv;
347 } else { 294 while (*++pp) {
348 fni = xrealloc(fni, sizeof(int) * (fnic+2)); 295 char *arg = *pp;
349 fni[fnic++] = i; 296 if (arg[0] != '-')
350 } 297 continue;
298 if (arg[1] == '-' && arg[2] == '\0') /* "--" */
299 break;
300 if ((arg[1] == '4' || arg[1] == '6') && arg[2] == '\0')
301 continue; /* it's "-4" or "-6" */
302 opt = get_signum(&arg[1]);
303 if (opt < 0)
304 continue;
305 /* "-SIGNAL" option found. Remove it and bail out */
306 killsig = opt;
307 do {
308 pp[0] = arg = pp[1];
309 pp++;
310 } while (arg);
311 break;
351 } 312 }
352 313
353 if (!fnic) 314 opt = getopt32(argv, OPTION_STRING);
354 return 1; 315 argv += optind;
355 316
356 inodes = xmalloc(sizeof(inode_list)); 317 xchdir("/proc");
357 for (i = 0; i < fnic; i++) { 318
358 if (fuser_parse_net_arg(argv[fni[i]], &proto, &port)) { 319 ilist = NULL;
359 fuser_scan_proc_net(opt, proto, port, inodes); 320 pp = argv;
360 } else { 321 while (*pp) {
361 if (!fuser_file_to_dev_inode(argv[fni[i]], &dev, &inode)) { 322 char *proto = parse_net_arg(*pp, &port);
362 if (ENABLE_FEATURE_CLEAN_UP) 323 if (proto) { /* PORT/PROTO */
363 free(inodes); 324 ilist = scan_proc_net(proto, port, ilist);
364 bb_perror_msg_and_die("cannot open '%s'", argv[fni[i]]); 325 free(proto);
365 } 326 } else { /* FILE */
366 fuser_add_inode(inodes, dev, inode); 327 if (!file_to_dev_inode(*pp, &dev, &inode))
328 bb_perror_msg_and_die("can't open %s", *pp);
329 ilist = add_inode(ilist, dev, inode);
367 } 330 }
331 pp++;
368 } 332 }
369 pids = xmalloc(sizeof(pid_list)); 333
370 success = fuser_scan_proc_pids(opt, inodes, pids); 334 plist = scan_proc_pids(ilist);
371 /* if the first pid in the list is 0, none have been found */ 335
372 if (pids->pid == 0) 336 if (!plist)
373 success = 0; 337 return EXIT_FAILURE;
374 if (success) { 338 success = 1;
375 if (opt & FUSER_OPT_KILL) { 339 if (opt & OPT_KILL) {
376 success = fuser_kill_pid_list(pids, killsig); 340 success = kill_pid_list(plist, killsig);
377 } else if (!(opt & FUSER_OPT_SILENT)) { 341 } else if (!(opt & OPT_SILENT)) {
378 success = fuser_print_pid_list(pids); 342 success = print_pid_list(plist);
379 }
380 }
381 if (ENABLE_FEATURE_CLEAN_UP) {
382 free(pids);
383 free(inodes);
384 } 343 }
385 /* return 0 on (success == 1) 1 otherwise */ 344 return (success != 1); /* 0 == success */
386 return (success != 1);
387} 345}