diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-17 08:44:58 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-17 08:44:58 +0000 |
commit | afc4113ed747330c7f0cc281618bf3e19579810d (patch) | |
tree | 19f473eec85cd12174b4ba59fb0a807559366c18 | |
parent | cdf62770af9e8bf7d5bb2344ddef8acb3216cfe2 (diff) | |
download | busybox-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.h | 23 | ||||
-rw-r--r-- | procps/fuser.c | 400 |
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 | 16 | enum { |
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 | ||
22 | typedef struct inode_list { | 24 | typedef 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 | ||
28 | typedef struct pid_list { | 30 | typedef 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 | ||
33 | static int fuser_option(char *option) | 35 | static 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 | ||
55 | static int fuser_file_to_dev_inode(const char *filename, | 48 | static 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 | ||
66 | static int fuser_find_socket_dev(dev_t *dev) | 58 | static 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 | ||
79 | static int fuser_parse_net_arg(const char *filename, | 70 | static 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 | |||
93 | static 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 | ||
113 | static int fuser_add_inode(inode_list *ilist, dev_t dev, ino_t inode) | 84 | static 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 | ||
136 | static int fuser_scan_proc_net(int opts, const char *proto, | 99 | static 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 | ||
173 | static int fuser_search_dev_inode(int opts, inode_list *ilist, | 136 | static 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 | ||
189 | static int fuser_scan_pid_maps(int opts, const char *fname, pid_t pid, | 150 | static 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 | ||
217 | static int fuser_scan_link(int opts, const char *lname, pid_t pid, | 177 | static 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 | ||
230 | static int fuser_scan_dir_links(int opts, const char *dname, pid_t pid, | 190 | static 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 | ||
251 | static int fuser_scan_proc_pids(int opts, inode_list *ilist, pid_list *plist) | 211 | static 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 | ||
284 | static int fuser_print_pid_list(pid_list *plist) | 242 | static 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 | ||
299 | static int fuser_kill_pid_list(pid_list *plist, int sig) | 252 | static 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) | |||
319 | int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 269 | int fuser_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
320 | int fuser_main(int argc, char **argv) | 270 | int 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) | 282 | fuser [options] FILEs or PORT/PROTOs |
336 | bb_show_usage(); | 283 | Find 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 | } |