Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/procps/fuser.c
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/procps/fuser.c
r2859 r3232 8 8 */ 9 9 10 //usage:#define fuser_trivial_usage 11 //usage: "[OPTIONS] FILE or PORT/PROTO" 12 //usage:#define fuser_full_usage "\n\n" 13 //usage: "Find processes which use FILEs or PORTs\n" 14 //usage: "\n -m Find processes which use same fs as FILEs" 15 //usage: "\n -4,-6 Search only IPv4/IPv6 space" 16 //usage: "\n -s Don't display PIDs" 17 //usage: "\n -k Kill found processes" 18 //usage: "\n -SIGNAL Signal to send (default: KILL)" 19 10 20 #include "libbb.h" 11 21 … … 27 37 } inode_list; 28 38 29 typedef struct pid_list {30 struct pid_list *next;31 pid_t pid;32 } pid_list;33 34 35 39 struct globals { 36 pid_list *pid_list_head; 40 int recursion_depth; 41 pid_t mypid; 37 42 inode_list *inode_list_head; 38 }; 43 smallint kill_failed; 44 int killsig; 45 } FIX_ALIASING; 39 46 #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 { 45 pid_list **curr = &G.pid_list_head; 46 47 while (*curr) { 48 if ((*curr)->pid == pid) 49 return; 50 curr = &(*curr)->next; 51 } 52 53 *curr = xzalloc(sizeof(pid_list)); 54 (*curr)->pid = pid; 55 } 47 #define INIT_G() do { \ 48 G.mypid = getpid(); \ 49 G.killsig = SIGKILL; \ 50 } while (0) 56 51 57 52 static void add_inode(const struct stat *st) … … 73 68 } 74 69 75 static void scan_proc_net(const char *path, unsigned port) 76 { 77 char line[MAX_LINE + 1]; 78 long long uint64_inode; 79 unsigned tmp_port; 80 FILE *f; 81 struct stat st; 82 int fd; 83 84 /* 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 92 f = fopen_for_read(path); 93 if (!f) 94 return; 95 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 st.st_ino = uint64_inode; 109 add_inode(&st); 110 } 111 } 112 } 113 fclose(f); 114 } 115 116 static int search_dev_inode(const struct stat *st) 70 static smallint search_dev_inode(const struct stat *st) 117 71 { 118 72 inode_list *ilist = G.inode_list_head; … … 130 84 } 131 85 132 static void scan_pid_maps(const char *fname, pid_t pid) 133 { 134 FILE *file; 135 char line[MAX_LINE + 1]; 136 int major, minor; 86 enum { 87 PROC_NET = 0, 88 PROC_DIR, 89 PROC_DIR_LINKS, 90 PROC_SUBDIR_LINKS, 91 }; 92 93 static smallint scan_proc_net_or_maps(const char *path, unsigned port) 94 { 95 FILE *f; 96 char line[MAX_LINE + 1], addr[68]; 97 int major, minor, r; 137 98 long long uint64_inode; 138 struct stat st; 139 140 file = fopen_for_read(fname); 141 if (!file) 142 return; 143 144 while (fgets(line, MAX_LINE, file)) { 145 if (sscanf(line, "%*s %*s %*s %x:%x %llu", &major, &minor, &uint64_inode) != 3) 99 unsigned tmp_port; 100 smallint retval; 101 struct stat statbuf; 102 const char *fmt; 103 void *fag, *sag; 104 105 f = fopen_for_read(path); 106 if (!f) 107 return 0; 108 109 if (G.recursion_depth == PROC_NET) { 110 int fd; 111 112 /* find socket dev */ 113 statbuf.st_dev = 0; 114 fd = socket(AF_INET, SOCK_DGRAM, 0); 115 if (fd >= 0) { 116 fstat(fd, &statbuf); 117 close(fd); 118 } 119 120 fmt = "%*d: %64[0-9A-Fa-f]:%x %*x:%*x %*x " 121 "%*x:%*x %*x:%*x %*x %*d %*d %llu"; 122 fag = addr; 123 sag = &tmp_port; 124 } else { 125 fmt = "%*s %*s %*s %x:%x %llu"; 126 fag = &major; 127 sag = &minor; 128 } 129 130 retval = 0; 131 while (fgets(line, MAX_LINE, f)) { 132 r = sscanf(line, fmt, fag, sag, &uint64_inode); 133 if (r != 3) 146 134 continue; 147 st.st_ino = uint64_inode; 148 if (major == 0 && minor == 0 && st.st_ino == 0) 149 continue; 150 st.st_dev = makedev(major, minor); 151 if (search_dev_inode(&st)) 152 add_pid(pid); 153 } 154 fclose(file); 155 } 156 157 static void scan_link(const char *lname, pid_t pid) 158 { 159 struct stat st; 160 161 if (stat(lname, &st) >= 0) { 162 if (search_dev_inode(&st)) 163 add_pid(pid); 164 } 165 } 166 167 static void scan_dir_links(const char *dname, pid_t pid) 135 136 statbuf.st_ino = uint64_inode; 137 if (G.recursion_depth == PROC_NET) { 138 r = strlen(addr); 139 if (r == 8 && (option_mask32 & OPT_IP6)) 140 continue; 141 if (r > 8 && (option_mask32 & OPT_IP4)) 142 continue; 143 if (tmp_port == port) 144 add_inode(&statbuf); 145 } else { 146 if (major != 0 && minor != 0 && statbuf.st_ino != 0) { 147 statbuf.st_dev = makedev(major, minor); 148 retval = search_dev_inode(&statbuf); 149 if (retval) 150 break; 151 } 152 } 153 } 154 fclose(f); 155 156 return retval; 157 } 158 159 static smallint scan_recursive(const char *path) 168 160 { 169 161 DIR *d; 170 struct dirent *de; 171 char *lname; 172 173 d = opendir(dname); 174 if (!d) 175 return; 176 177 while ((de = readdir(d)) != NULL) { 178 lname = concat_subpath_file(dname, de->d_name); 179 if (lname == NULL) 180 continue; 181 scan_link(lname, pid); 182 free(lname); 162 struct dirent *d_ent; 163 smallint stop_scan; 164 smallint retval; 165 166 d = opendir(path); 167 if (d == NULL) 168 return 0; 169 170 G.recursion_depth++; 171 retval = 0; 172 stop_scan = 0; 173 while (!stop_scan && (d_ent = readdir(d)) != NULL) { 174 struct stat statbuf; 175 pid_t pid; 176 char *subpath; 177 178 subpath = concat_subpath_file(path, d_ent->d_name); 179 if (subpath == NULL) 180 continue; /* . or .. */ 181 182 switch (G.recursion_depth) { 183 case PROC_DIR: 184 pid = (pid_t)bb_strtou(d_ent->d_name, NULL, 10); 185 if (errno != 0 186 || pid == G.mypid 187 /* "this PID doesn't use specified FILEs or PORT/PROTO": */ 188 || scan_recursive(subpath) == 0 189 ) { 190 break; 191 } 192 if (option_mask32 & OPT_KILL) { 193 if (kill(pid, G.killsig) != 0) { 194 bb_perror_msg("kill pid %s", d_ent->d_name); 195 G.kill_failed = 1; 196 } 197 } 198 if (!(option_mask32 & OPT_SILENT)) 199 printf("%s ", d_ent->d_name); 200 retval = 1; 201 break; 202 203 case PROC_DIR_LINKS: 204 switch ( 205 index_in_substrings( 206 "cwd" "\0" "exe" "\0" 207 "root" "\0" "fd" "\0" 208 "lib" "\0" "mmap" "\0" 209 "maps" "\0", 210 d_ent->d_name 211 ) 212 ) { 213 enum { 214 CWD_LINK, 215 EXE_LINK, 216 ROOT_LINK, 217 FD_DIR_LINKS, 218 LIB_DIR_LINKS, 219 MMAP_DIR_LINKS, 220 MAPS, 221 }; 222 case CWD_LINK: 223 case EXE_LINK: 224 case ROOT_LINK: 225 goto scan_link; 226 case FD_DIR_LINKS: 227 case LIB_DIR_LINKS: 228 case MMAP_DIR_LINKS: 229 stop_scan = scan_recursive(subpath); 230 if (stop_scan) 231 retval = stop_scan; 232 break; 233 case MAPS: 234 stop_scan = scan_proc_net_or_maps(subpath, 0); 235 if (stop_scan) 236 retval = stop_scan; 237 default: 238 break; 239 } 240 break; 241 case PROC_SUBDIR_LINKS: 242 scan_link: 243 if (stat(subpath, &statbuf) < 0) 244 break; 245 stop_scan = search_dev_inode(&statbuf); 246 if (stop_scan) 247 retval = stop_scan; 248 default: 249 break; 250 } 251 free(subpath); 183 252 } 184 253 closedir(d); 185 } 186 187 /* NB: does chdir internally */ 188 static void scan_proc_pids(void) 189 { 190 DIR *d; 191 struct dirent *de; 192 pid_t pid; 193 194 xchdir("/proc"); 195 d = opendir("/proc"); 196 if (!d) 197 return; 198 199 while ((de = readdir(d)) != NULL) { 200 pid = (pid_t)bb_strtou(de->d_name, NULL, 10); 201 if (errno) 202 continue; 203 if (chdir(de->d_name) < 0) 204 continue; 205 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 xchdir("/proc"); 215 } 216 closedir(d); 254 G.recursion_depth--; 255 return retval; 217 256 } 218 257 … … 220 259 int fuser_main(int argc UNUSED_PARAM, char **argv) 221 260 { 222 pid_list *plist;223 pid_t mypid;224 261 char **pp; 225 struct stat st; 226 unsigned port; 227 int opt; 228 int exitcode; 229 int killsig; 230 /* 231 fuser [OPTIONS] FILE or PORT/PROTO 232 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 -s Don't display PIDs 237 -k Kill found processes 238 -SIGNAL Signal to send (default: KILL) 239 */ 262 263 INIT_G(); 264 240 265 /* Handle -SIGNAL. Oh my... */ 241 killsig = SIGKILL; /* yes, the default is not SIGTERM */242 266 pp = argv; 243 267 while (*++pp) { 268 int sig; 244 269 char *arg = *pp; 270 245 271 if (arg[0] != '-') 246 272 continue; … … 249 275 if ((arg[1] == '4' || arg[1] == '6') && arg[2] == '\0') 250 276 continue; /* it's "-4" or "-6" */ 251 opt= get_signum(&arg[1]);252 if ( opt< 0)277 sig = get_signum(&arg[1]); 278 if (sig < 0) 253 279 continue; 254 280 /* "-SIGNAL" option found. Remove it and bail out */ 255 killsig = opt;281 G.killsig = sig; 256 282 do { 257 283 pp[0] = arg = pp[1]; … … 262 288 263 289 opt_complementary = "-1"; /* at least one param */ 264 opt =getopt32(argv, OPTION_STRING);290 getopt32(argv, OPTION_STRING); 265 291 argv += optind; 266 292 … … 268 294 while (*pp) { 269 295 /* 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 } else { /* FILE */ 277 file: 278 xstat(*pp, &st); 279 add_inode(&st); 296 unsigned port; 297 char path[sizeof("/proc/net/TCP6")]; 298 299 strcpy(path, "/proc/net/"); 300 if (sscanf(*pp, "%u/%4s", &port, path + sizeof("/proc/net/")-1) == 2 301 && access(path, R_OK) == 0 302 ) { 303 /* PORT/PROTO */ 304 scan_proc_net_or_maps(path, port); 305 } else { 306 /* FILE */ 307 struct stat statbuf; 308 xstat(*pp, &statbuf); 309 add_inode(&statbuf); 280 310 } 281 311 pp++; 282 312 } 283 313 284 scan_proc_pids(); /* changes dir to "/proc" */ 285 286 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 } 295 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 } 314 if (scan_recursive("/proc")) { 315 if (!(option_mask32 & OPT_SILENT)) 316 bb_putchar('\n'); 317 return G.kill_failed; 318 } 319 320 return EXIT_FAILURE; 321 }
Note:
See TracChangeset
for help on using the changeset viewer.