tizen beta release
[external/psmisc.git] / src / fuser.c
1 /*
2  * fuser.c - identify processes using files
3  *
4  * Based on fuser.c Copyright (C) 1993-2005 Werner Almesberger and Craig Small
5  *
6  * Completely re-written
7  * Copyright (C) 2005-2007 Craig Small
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 #ifndef _GNU_SOURCE
24 #define _GNU_SOURCE
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/socket.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
40 #include <pwd.h>
41 #include <netdb.h>
42 #include <dirent.h>
43 #include <unistd.h>
44 #include <ctype.h>
45 #include <mntent.h>
46 #include <signal.h>
47 #include <getopt.h>
48
49 #include "fuser.h"
50 #include "signals.h"
51 #include "i18n.h"
52
53 /*
54 #define DEBUG 1
55 */
56 /*
57 #define NFS_CHECKS 
58 */
59
60 #define NAME_FIELD 20           /* space reserved for file name */
61 /* Function defines */
62 static void add_matched_proc(struct names *name_list, const pid_t pid, const uid_t uid, const char access);
63 static void check_dir(const pid_t pid, const char *dirname, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access);
64 static void check_map(const pid_t pid, const char *filename, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access);
65 static struct stat *get_pidstat(const pid_t pid, const char *filename);
66 static uid_t getpiduid(const pid_t pid);
67 static int print_matches(struct names *names_head, const opt_type opts, const int sig_number);
68 static void kill_matched_proc(struct procs *pptr, const opt_type opts, const int sig_number);
69
70 int parse_mount(struct names *this_name, struct device_list **dev_list);
71 static void add_device(struct device_list **dev_list, struct names  *this_name, dev_t device);
72 void scan_mount_devices(const opt_type opts, struct mountdev_list **mount_devices);
73 void fill_unix_cache(struct unixsocket_list **unixsocket_head);
74 static dev_t find_net_dev(void);
75 static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head);
76 #ifdef NFS_CHECKS
77 static void scan_knfsd(struct names *names_head, struct device_list *dev_head);
78 #endif /* NFS_CHECKS */
79 #ifdef DEBUG
80 static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head);
81 #endif
82
83 static void usage (const char *errormsg)
84 {
85         if (errormsg != NULL)
86                 fprintf(stderr, "%s\n", errormsg);
87
88   fprintf (stderr, _(
89     "Usage: fuser [ -a | -s | -c ] [ -n SPACE ] [ -SIGNAL ] [ -kimuv ] NAME...\n"
90     "             [ - ] [ -n SPACE ] [ -SIGNAL ] [ -kimuv ] NAME...\n"
91     "       fuser -l\n"
92     "       fuser -V\n"
93     "Show which processes use the named files, sockets, or filesystems.\n\n"
94     "    -a        display unused files too\n"
95     "    -c        mounted FS\n"
96     "    -f        silently ignored (for POSIX compatibility)\n"
97     "    -i        ask before killing (ignored without -k)\n"
98     "    -k        kill processes accessing the named file\n"
99     "    -l        list available signal names\n"
100     "    -m        show all processes using the named filesystems\n"
101     "    -n SPACE  search in this name space (file, udp, or tcp)\n"
102     "    -s        silent operation\n"
103     "    -SIGNAL   send this signal instead of SIGKILL\n"
104     "    -u        display user IDs\n"
105     "    -v        verbose output\n"
106     "    -V        display version information\n"));
107 #ifdef WITH_IPV6
108   fprintf (stderr, _(
109     "    -4        search IPv4 sockets only\n"
110     "    -6        search IPv6 sockets only\n"));
111 #endif
112   fprintf (stderr, _(
113     "    -         reset options\n\n"
114     "  udp/tcp names: [local_port][,[rmt_host][,[rmt_port]]]\n\n"));
115   exit (1);
116 }
117
118 void print_version()
119 {
120   fprintf(stderr, _("fuser (PSmisc) %s\n"), VERSION);
121   fprintf(stderr, _(
122     "Copyright (C) 1993-2005 Werner Almesberger and Craig Small\n\n"));
123   fprintf(stderr, _(
124     "PSmisc comes with ABSOLUTELY NO WARRANTY.\n"
125     "This is free software, and you are welcome to redistribute it under\n"
126     "the terms of the GNU General Public License.\n"
127     "For more information about these matters, see the files named COPYING.\n"));
128 }
129
130 static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head)
131 {
132         DIR *topproc_dir;
133         struct dirent *topproc_dent;
134         char *fd_dirpath, *fd_pathname;
135         struct inode_list *ino_tmp;
136         struct device_list *dev_tmp;
137         pid_t pid, my_pid;
138         uid_t uid;
139         struct stat *cwd_stat, *exe_stat, *root_stat;
140
141         if ( (fd_dirpath = malloc(MAX_PATHNAME)) == NULL)
142                 return;
143         if ( (fd_pathname = malloc(MAX_PATHNAME)) == NULL)
144                 return;
145
146         if ( (topproc_dir = opendir("/proc")) == NULL) {
147                 fprintf(stderr, _("Cannot open /proc directory: %s\n"), strerror(errno));
148                 exit(1);
149         }
150         my_pid = getpid();
151         while ( (topproc_dent = readdir(topproc_dir)) != NULL) {
152                 if (topproc_dent->d_name[0] < '0' || topproc_dent->d_name[0] > '9') /* Not a process */
153                         continue;
154                 pid = atoi(topproc_dent->d_name);
155                 /* Dont print myself */
156                 if (pid == my_pid)
157                         continue;
158                 uid = getpiduid(pid);
159
160                 root_stat = get_pidstat(pid, "root");
161                 cwd_stat = get_pidstat(pid, "cwd");
162                 exe_stat = get_pidstat(pid, "exe");
163                 /* Scan the devices */
164                 for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) {
165                         if (exe_stat != NULL && exe_stat->st_dev == dev_tmp->device) 
166                                 add_matched_proc(dev_tmp->name, pid, uid, ACCESS_EXE);
167                         if (root_stat != NULL && root_stat->st_dev == dev_tmp->device) 
168                                 add_matched_proc(dev_tmp->name, pid, uid, ACCESS_ROOT);
169                         if (cwd_stat != NULL && cwd_stat->st_dev == dev_tmp->device) 
170                                 add_matched_proc(dev_tmp->name, pid, uid, ACCESS_CWD);
171                 }
172                 for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) {
173                         if (exe_stat != NULL) {
174                                 if (exe_stat->st_dev == ino_tmp->device && exe_stat->st_ino == ino_tmp->inode) {
175                                         add_matched_proc(ino_tmp->name, pid, uid, ACCESS_EXE);
176                                 }
177                         }
178                         if (root_stat != NULL) {
179                                 if (root_stat->st_dev == ino_tmp->device && root_stat->st_ino == ino_tmp->inode){
180                                         add_matched_proc(ino_tmp->name, pid, uid, ACCESS_ROOT);
181                                 }
182
183                         }
184                         if (cwd_stat != NULL){
185                                 if (cwd_stat->st_dev == ino_tmp->device && cwd_stat->st_ino == ino_tmp->inode) {
186                                         add_matched_proc(ino_tmp->name, pid, uid, ACCESS_CWD);
187                                 }
188                         }
189                 }
190                 check_dir(pid, "lib", dev_head, ino_head, uid, ACCESS_MMAP);
191                 check_dir(pid, "mmap", dev_head, ino_head, uid, ACCESS_MMAP);
192                 check_dir(pid, "fd", dev_head, ino_head, uid, ACCESS_FILE);
193                 check_map(pid, "maps", dev_head, ino_head, uid, ACCESS_MMAP);
194
195         } /* while topproc_dent */
196         closedir(topproc_dir);
197 }
198 static void add_inode(struct inode_list **ino_list, struct names  *this_name, dev_t device, ino_t inode)
199 {
200         struct inode_list *ino_tmp, *ino_head;
201
202         ino_head = *ino_list;
203
204         if ( (ino_tmp = malloc(sizeof(struct inode_list))) == NULL)
205                 return;
206         ino_tmp->name = this_name;
207         ino_tmp->device = device;
208         ino_tmp->inode = inode;
209         ino_tmp->next = ino_head;
210         *ino_list = ino_tmp;
211 }
212
213 static void add_device(struct device_list **dev_list, struct names  *this_name, dev_t device)
214 {
215         struct device_list *dev_tmp, *dev_head;
216
217         /*printf("Adding device %s %d\n", this_name->filename, device);*/
218         dev_head = *dev_list;
219
220         if ( (dev_tmp = malloc(sizeof(struct device_list))) == NULL)
221                 return;
222         dev_tmp->name = this_name;
223         dev_tmp->device = device;
224         dev_tmp->next = dev_head;
225         *dev_list = dev_tmp;
226 }
227
228 static void add_ip_conn(struct ip_connections **ip_list, const char *protocol, struct names *this_name, const int lcl_port, const int rmt_port, unsigned long rmt_address)
229 {
230         struct ip_connections *ip_tmp, *ip_head;
231
232         ip_head = *ip_list;
233
234         if ( (ip_tmp = malloc(sizeof(struct ip_connections))) == NULL)
235                 return;
236         ip_tmp->name = this_name;
237         ip_tmp->lcl_port = lcl_port;
238         ip_tmp->rmt_port = rmt_port;
239         ip_tmp->rmt_address.s_addr = rmt_address;
240         ip_tmp->next = ip_head;
241
242         *ip_list = ip_tmp;
243 }
244
245 #ifdef WITH_IPV6
246 static void add_ip6_conn(struct ip6_connections **ip_list, const char *protocol, struct names *this_name, const int lcl_port, const int rmt_port, struct in6_addr rmt_address)
247 {
248         struct ip6_connections *ip_tmp, *ip_head;
249
250         ip_head = *ip_list;
251
252         if ( (ip_tmp = malloc(sizeof(struct ip6_connections))) == NULL)
253                 return;
254         ip_tmp->name = this_name;
255         ip_tmp->lcl_port = lcl_port;
256         ip_tmp->rmt_port = rmt_port;
257         memcpy(&(ip_tmp->rmt_address),&(rmt_address),sizeof(struct in6_addr));
258         ip_tmp->next = ip_head;
259
260         *ip_list = ip_tmp;
261 }
262 #endif
263
264 static void add_matched_proc(struct names *name_list, const pid_t pid, const uid_t uid, const char access)
265 {
266         struct procs *pptr, *last_proc;
267         char *pathname;
268         char cmdname[101], *cptr;
269         int cmdlen;
270         FILE *fp;
271
272         last_proc = NULL;
273         for (pptr = name_list->matched_procs; pptr != NULL ; pptr = pptr->next)
274         {
275                 last_proc = pptr;
276                 if (pptr->pid == pid) {
277                         pptr->access |= access;
278                         return;
279                 }
280         }
281         /* Not found */
282         if ( (pptr = malloc(sizeof (struct procs))) == NULL) {
283                 fprintf(stderr,_("Cannot allocate memory for matched proc: %s\n"), strerror(errno));
284                 return;
285         }
286         pptr->pid = pid;
287         pptr->uid = uid;
288         pptr->access = access;
289         pptr->next = NULL;
290         /* set command name */
291         pptr->command = NULL;
292         if ( (asprintf(&pathname, "/proc/%d/stat", pid) > 0) &&
293                         ( (fp = fopen(pathname, "r")) != NULL) &&
294                         ( fscanf(fp, "%*d (%100[^)]", cmdname) == 1)) 
295                 if ( (pptr->command = malloc(MAX_CMDNAME+1)) != NULL) {
296                         cmdlen = 0;
297                         for (cptr = cmdname; cmdlen < MAX_CMDNAME && *cptr ; cptr++) {
298                                 if (isprint(*cptr))
299                                         pptr->command[cmdlen++] = *cptr;
300                                 else if(cmdlen < (MAX_CMDNAME-4))
301                                         cmdlen += sprintf(&(pptr->command[cmdlen]), "\\%03o", *cptr);
302                         }
303                         pptr->command[cmdlen] = '\0';
304                 }
305         if (last_proc == NULL)
306                 name_list->matched_procs = pptr;
307         else
308                 last_proc->next = pptr;
309 }
310
311 int parse_mount(struct names *this_name, struct device_list **dev_list)
312 {
313         struct stat st;
314
315         if (stat(this_name->filename, &st) != 0) {
316                 fprintf(stderr, _("Cannot stat mount point %s: %s\n"), 
317                                 this_name->filename,
318                                 strerror(errno));
319                 exit(1);
320         }
321 #ifdef DEBUG
322         printf("Debug: parse_mount() adding %s\n", this_name->filename);
323 #endif /* DEBUG */
324         add_device(dev_list, this_name, st.st_dev);
325         return 0;
326 }
327
328 int parse_file(struct names *this_name, struct inode_list **ino_list)
329 {
330         struct stat st;
331
332         if (stat(this_name->filename, &st) != 0) {
333                 fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
334                                 strerror(errno));
335                 return -1;
336         }
337 #ifdef DEBUG
338         printf("adding file %s %lX %lX\n", this_name->filename,
339                         (unsigned long)st.st_dev, (unsigned long)st.st_ino);
340 #endif /* DEBUG */
341         add_inode(ino_list, this_name, st.st_dev, st.st_ino);
342         return 0;
343 }
344
345 int parse_unixsockets(struct names *this_name, struct inode_list **ino_list, struct unixsocket_list *sun_head)
346 {
347         struct unixsocket_list *sun_tmp;
348         struct stat st;
349     dev_t net_dev;
350     
351         if (stat(this_name->filename, &st) != 0) {
352                 fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
353                                 strerror(errno));
354                 return -1;
355         }
356     net_dev = find_net_dev();
357
358         for (sun_tmp = sun_head; sun_tmp != NULL ; sun_tmp = sun_tmp->next)
359         {
360       if (sun_tmp->dev == st.st_dev && sun_tmp->inode == st.st_ino) {
361                         add_inode(ino_list, this_name, net_dev, sun_tmp->net_inode);
362             return 0;
363                 }
364         }
365         return 0;
366 }
367
368 int parse_mounts(struct names *this_name, struct mountdev_list *mounts, struct device_list **dev_list, const char opts) 
369 {
370         struct stat st;
371         struct mountdev_list *mountptr;
372         dev_t match_device;
373
374         if (stat(this_name->filename, &st) != 0) {
375                 fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
376                                 strerror(errno));
377                 return -1;
378         }
379         if (S_ISBLK(st.st_mode))
380                 match_device = st.st_rdev;
381         else
382                 match_device = st.st_dev;
383         for (mountptr = mounts ; mountptr != NULL ; mountptr = mountptr->next) {
384                 if (mountptr->device == match_device) {
385                         /*printf("Debug: adding parse_mounts() adding %s\n", 
386                                         this_name->filename);*/
387                         add_device(dev_list, this_name, match_device);
388                 }
389         }
390         return 0;
391 }
392
393 #ifdef WITH_IPV6
394 int parse_inet(struct names *this_name, const int ipv6_only, const int ipv4_only, struct ip_connections **ip_list, struct ip6_connections **ip6_list)
395 #else
396 int parse_inet(struct names *this_name, struct ip_connections **ip_list)
397 #endif
398 {
399         struct addrinfo *res, *resptr;
400         struct addrinfo hints;
401         int errcode;
402         char *lcl_port_str, *rmt_addr_str, *rmt_port_str, *tmpstr, *tmpstr2;
403         in_port_t lcl_port;
404         struct sockaddr_in *sin;
405 #ifdef WITH_IPV6
406         struct sockaddr_in6 *sin6;
407 #endif
408         char hostspec[100];
409         char *protocol;
410         int i;
411         
412         if ( (protocol = strchr(this_name->filename, '/')) == NULL)
413                 return -1;
414         protocol++;
415         if (protocol[0] == '\0')
416                 return -1;
417         for (i=0; i < 99 && this_name->filename[i] != '\0' && this_name->filename[i] != '/'; i++)
418                 hostspec[i] = this_name->filename[i];
419         hostspec[i] = '\0';
420
421         lcl_port_str = rmt_addr_str = rmt_port_str = NULL;
422         /* Split out the names */
423         if ( (tmpstr = strchr(hostspec, ',')) == NULL) {
424                 /* Single option */
425                 lcl_port_str = strdup(hostspec);
426         } else {
427                 if (tmpstr == hostspec)
428                         lcl_port_str = NULL;
429                 else {
430                         *tmpstr = '\0';
431                         lcl_port_str = strdup(hostspec);
432                 }
433                 tmpstr++;
434                 if (*tmpstr != '\0') {
435                         if ( (tmpstr2 = strchr(tmpstr, ',')) == NULL) {
436                                 /* Only 2 options */
437                                 rmt_addr_str = tmpstr;
438                         } else {
439                                 if (tmpstr2 == tmpstr)
440                                         rmt_addr_str = NULL;
441                                 else {
442                                         rmt_addr_str = tmpstr;
443                                         *tmpstr2 = '\0';
444                                 }
445                                 tmpstr2++;
446                                 if (*tmpstr2 != '\0')
447                                         rmt_port_str = tmpstr2;
448                         }
449                 }
450         }
451 #ifdef DEBUG
452         printf("parsed to lp %s rh %s rp %s\n", lcl_port_str, rmt_addr_str, rmt_port_str);
453 #endif
454
455         memset(&hints, 0, sizeof(hints));
456 #ifdef WITH_IPV6
457         if (ipv6_only) {
458                 hints.ai_family = PF_INET6;
459         } else if (ipv4_only) {
460                         hints.ai_family = PF_INET;
461                 } else 
462                         hints.ai_family = PF_UNSPEC;
463 #else
464         hints.ai_family = PF_INET;
465 #endif
466         if (strcmp(protocol, "tcp") == 0)
467                 hints.ai_socktype = SOCK_STREAM;
468         else
469                 hints.ai_socktype = SOCK_DGRAM;
470
471         if (lcl_port_str == NULL) {
472                 lcl_port = 0;
473         } else {
474                 /* Resolve local port first */
475                 if ( (errcode = getaddrinfo(NULL, lcl_port_str, &hints, &res)) != 0) {
476                         fprintf(stderr, _("Cannot resolve local port %s: %s\n"),
477                                         lcl_port_str, gai_strerror(errcode));
478                         return -1;
479                 }
480                 if (res == NULL)
481                         return -1;
482                 switch(res->ai_family) {
483                         case AF_INET:
484                                 lcl_port = ((struct sockaddr_in*)(res->ai_addr))->sin_port;
485                                 break;
486 #ifdef WITH_IPV6
487                         case AF_INET6:
488                                 lcl_port = ((struct sockaddr_in6*)(res->ai_addr))->sin6_port;
489                                 break;
490 #endif
491                         default:
492                                 fprintf(stderr, _("Unknown local port AF %d\n"), res->ai_family);
493                                 freeaddrinfo(res);
494                                 return -1;
495                 }
496                 freeaddrinfo(res);
497         }
498         free(lcl_port_str);
499         res = NULL;
500         if (rmt_addr_str == NULL && rmt_port_str == NULL) {
501                 add_ip_conn(ip_list, protocol, this_name, ntohs(lcl_port), 0, INADDR_ANY);
502 #ifdef WITH_IPV6
503                 add_ip6_conn(ip6_list, protocol,this_name, ntohs(lcl_port), 0, in6addr_any);
504 #endif
505                 return 0;
506         } else {
507                 /* Resolve remote address and port */
508                 if (getaddrinfo(rmt_addr_str, rmt_port_str, &hints, &res) == 0) {
509                         for(resptr = res ; resptr != NULL ; resptr = resptr->ai_next ) {
510                                 switch(resptr->ai_family) {
511                                         case AF_INET:
512                       sin = (struct sockaddr_in*)resptr->ai_addr;
513                       if (rmt_addr_str == NULL) {
514                                                 add_ip_conn(ip_list, protocol, this_name, ntohs(lcl_port), ntohs(sin->sin_port), INADDR_ANY);
515                       } else {
516                                                 add_ip_conn(ip_list, protocol, this_name, ntohs(lcl_port), ntohs(sin->sin_port), sin->sin_addr.s_addr);
517                       }
518                                         break;
519 #ifdef WITH_IPV6
520                                 case AF_INET6:
521                     sin6 = (struct sockaddr_in6*)resptr->ai_addr;
522                     if (rmt_addr_str == NULL) {
523                                                 add_ip6_conn(ip6_list, protocol, this_name, ntohs(lcl_port), ntohs(sin6->sin6_port), in6addr_any);
524                     } else {
525                       add_ip6_conn(ip6_list, protocol, this_name, ntohs(lcl_port), ntohs(sin6->sin6_port), sin6->sin6_addr);
526                     }
527                                         break;
528 #endif
529                                 }
530                         } /*while */
531                         return 0;
532                 }
533         }
534         return 1;
535 }
536
537
538
539
540 void find_net_sockets(struct inode_list **ino_list, struct ip_connections *conn_list, const char *protocol, dev_t netdev)
541 {
542         FILE *fp;
543         char pathname[200], line[BUFSIZ];
544         unsigned long loc_port, rmt_port;
545         unsigned long rmt_addr, scanned_inode;
546         ino_t inode;
547         struct ip_connections *conn_tmp;
548
549         if (snprintf(pathname,200, "/proc/net/%s", protocol) < 0) 
550                 return ;
551
552         if ( (fp = fopen(pathname, "r")) == NULL) {
553                 fprintf(stderr, _("Cannot open protocol file \"%s\": %s\n"), pathname,strerror(errno));
554                 return;
555         }
556         while (fgets(line, BUFSIZ, fp) != NULL) {
557                 if (sscanf(line, "%*u: %*x:%lx %08lx:%lx %*x %*x:%*x %*x:%*x %*x %*d %*d %lu",
558                         &loc_port,
559                         &rmt_addr,
560                         &rmt_port,
561                         &scanned_inode) != 4)
562                         continue;
563 #ifdef DEBUG
564                 printf("Found IPv4 *:%lu with %s:%lu\n", loc_port, inet_ntoa(*((struct in_addr*)&rmt_addr)), rmt_port);
565 #endif /* DEBUG */
566                 inode = scanned_inode;
567                 for(conn_tmp = conn_list ; conn_tmp != NULL ; conn_tmp = conn_tmp->next) {
568 #ifdef DEBUG
569                         printf("  Comparing with *.%lu %s:%lu\n", 
570                                         conn_tmp->lcl_port,
571                                         inet_ntoa(conn_tmp->rmt_address),
572                                         conn_tmp->rmt_port);
573 #endif
574                         if ( (conn_tmp->lcl_port == 0 || conn_tmp->lcl_port == loc_port) &&
575                                  (conn_tmp->rmt_port == 0 || conn_tmp->rmt_port == rmt_port) &&
576                  (conn_tmp->rmt_address.s_addr == INADDR_ANY ||
577                                         (memcmp(&(conn_tmp->rmt_address), &(rmt_addr),4) ==0))
578                            ) {
579                                 /* add inode to list */
580 #ifdef DEBUG
581                 printf("Added inode!\n");
582 #endif /* DEBUG */
583                                 add_inode(ino_list, conn_tmp->name, netdev, inode);
584                         }
585                 }
586                         
587
588         }
589         return ;
590 }
591
592 #ifdef WITH_IPV6
593 void find_net6_sockets(struct inode_list **ino_list, struct ip6_connections *conn_list, const char *protocol, const dev_t netdev)
594 {
595         FILE *fp;
596         char pathname[200], line[BUFSIZ];
597         unsigned long loc_port, rmt_port;
598         struct in6_addr rmt_addr;
599         unsigned int tmp_addr[4];
600         char rmt_addr6str[INET6_ADDRSTRLEN];
601         struct ip6_connections *head, *tmpptr, *tail;
602         struct ip6_connections *conn_tmp;
603         unsigned long scanned_inode;
604         ino_t inode;
605
606         head = tmpptr = tail = NULL;
607
608         if (snprintf(pathname,200, "/proc/net/%s6", protocol) < 0) 
609                 return ;
610
611         if ( (fp = fopen(pathname, "r")) == NULL) {
612 #ifdef DEBUG
613                 printf("Cannot open protocol file \"%s\": %s\n", pathname, strerror(errno));
614 #endif /* DEBUG */
615                 return ;
616         }
617         while (fgets(line, BUFSIZ, fp) != NULL) {
618                 if (sscanf(line, "%*u: %*x:%lx %08x%08x%08x%08x:%lx %*x %*x:%*x %*x:%*x %*x %*d %*d %lu",
619                         &loc_port, 
620                         &(tmp_addr[0]),
621                         &(tmp_addr[1]),
622                         &(tmp_addr[2]),
623                         &(tmp_addr[3]),
624                         &rmt_port, &scanned_inode) != 7)
625                         continue;
626                 inode = scanned_inode;
627                 rmt_addr.s6_addr32[0] = tmp_addr[0];
628                 rmt_addr.s6_addr32[1] = tmp_addr[1];
629                 rmt_addr.s6_addr32[2] = tmp_addr[2];
630                 rmt_addr.s6_addr32[3] = tmp_addr[3];
631                 inet_ntop(AF_INET6, &rmt_addr, rmt_addr6str, INET6_ADDRSTRLEN);
632 #ifdef DEBUG
633                 printf("Found IPv6 %ld with %s:%ld\n", loc_port, rmt_addr6str, rmt_port);
634 #endif /* DEBUG */
635                 for(conn_tmp = conn_list ; conn_tmp != NULL ; conn_tmp = conn_tmp->next) {
636                         inet_ntop(AF_INET6, &conn_tmp->rmt_address, rmt_addr6str, INET6_ADDRSTRLEN);
637 #ifdef DEBUG
638                         printf("  Comparing with *.%lu %s:%lu ...\n", 
639                                         conn_tmp->lcl_port,
640                                         rmt_addr6str,
641                                         conn_tmp->rmt_port);
642 #endif /* DEBUG */
643                         if ( (conn_tmp->lcl_port == 0 || conn_tmp->lcl_port == loc_port) &&
644                                   (conn_tmp->rmt_port == 0 || conn_tmp->rmt_port == rmt_port) &&
645                   (memcmp(&(conn_tmp->rmt_address), &in6addr_any,16) == 0 ||
646                                         (memcmp(&(conn_tmp->rmt_address), &(rmt_addr),16) ==0))
647                            ) {
648                                 add_inode(ino_list, conn_tmp->name, netdev, inode);
649                         }
650                 }
651         }
652 }
653 #endif
654
655 int main(int argc, char *argv[])
656 {
657         opt_type opts; 
658         int sig_number;
659 #ifdef WITH_IPV6
660         int ipv4_only, ipv6_only;
661 #endif
662         unsigned char default_namespace = NAMESPACE_FILE;
663         struct mountdev_list *mount_devices = NULL;
664         struct device_list *match_devices = NULL;
665         struct unixsocket_list *unixsockets = NULL;
666
667         dev_t netdev;
668         struct ip_connections *tcp_connection_list = NULL;
669         struct ip_connections *udp_connection_list = NULL;
670 #ifdef WITH_IPV6
671         struct ip6_connections *tcp6_connection_list = NULL;
672         struct ip6_connections *udp6_connection_list = NULL;
673 #endif
674         struct inode_list *match_inodes = NULL;
675         struct names *names_head, *this_name, *names_tail;
676         int optc;
677         char *option;
678         char *nsptr;
679
680 #ifdef WITH_IPV6
681         ipv4_only = ipv6_only = 0;
682 #endif
683         names_head = this_name = names_tail = NULL;
684         opts = 0;
685         sig_number = SIGKILL;
686
687 #ifdef ENABLE_NLS
688         /* Set up the i18n */
689         setlocale(LC_ALL, "");
690         bindtextdomain(PACKAGE, LOCALEDIR);
691         textdomain(PACKAGE);
692 #endif
693
694         netdev = find_net_dev();
695         scan_mount_devices(opts, &mount_devices);
696         fill_unix_cache(&unixsockets);
697
698         /* getopt doesnt like things like -SIGBLAH */
699         for(optc = 1; optc < argc; optc++) {
700                 if (argv[optc][0] == '-') { /* its an option */
701                         option=argv[optc] + 1;
702                         if (argv[optc][1] == '-') { /* its a long option */
703                                 if (argv[optc][2] == '\0') {
704                                         continue;
705                                 }
706                                 /* FIXME longopts */
707                                 continue;
708                         }
709                         while (*option) {
710                                 switch(*option) {
711 #ifdef WITH_IPV6
712                                 case '4':
713                                         ipv4_only = 1;
714                                         break;
715                                 case '6':
716                                         ipv6_only = 1;
717                                         break;
718 #endif
719                                 case 'a':
720                                         opts |= OPT_ALLFILES;
721                                         break;
722                                 case 'c':
723                                         opts |= OPT_MOUNTPOINT;
724                                         break;
725                                 case 'f':
726                                         /* ignored */
727                                         break;
728                                 case 'h':
729                                         usage(NULL);
730                                         break;
731                                 case 'i':
732                                         opts |= OPT_INTERACTIVE;
733                                         break;
734                                 case 'k':
735                                         opts |= OPT_KILL;
736                                         break;
737                                 case 'l':
738                                         list_signals();
739                                         return 0;
740                                 case 'm':
741                                         opts |= OPT_MOUNTS;
742                                         break;
743                                 case 'n':
744                                         optc++;
745                                         if (optc >= argc) {
746                                                 usage(_("Namespace option requires an argument."));
747                                         }
748                                         if (strcmp(argv[optc], "tcp") == 0)
749                                                 default_namespace = NAMESPACE_TCP;
750                                         else if (strcmp(argv[optc], "udp") == 0)
751                                                 default_namespace = NAMESPACE_UDP;
752                                         else if (strcmp(argv[optc], "file") == 0)
753                                                 default_namespace = NAMESPACE_FILE;
754                                         else 
755                                                 usage(_("Invalid namespace name"));
756                                         break;
757                                 case 's':
758                                         opts |= OPT_SILENT;
759                                         break;
760                                 case 'u':
761                                         opts |= OPT_USER;
762                                         break;
763                                 case 'v':
764                                         opts |= OPT_VERBOSE;
765                                         break;
766                                 case 'V':
767                                         print_version();
768                                         return 0;
769                                 default:
770                                         if ( isupper(*option) || isdigit(*option) ) {
771                                                 sig_number = get_signal(option,"fuser");
772                                                 option[1]='\0';
773
774                                                 break;
775                                         }
776                                         fprintf(stderr,"%s: Invalid option %c\n",argv[0] , argv[optc][1]);
777                                         usage(NULL);
778
779                                         break;
780                                 } /* switch */
781                                 option++;
782                         }
783                         continue;
784                 }
785                 /* File specifications */
786                 if ( (this_name = malloc(sizeof(struct names))) == NULL)
787                         continue;
788                 this_name->next = NULL;
789                 if (names_head == NULL)
790                         names_head = this_name;
791                 if (names_tail != NULL)
792                         names_tail->next = this_name;
793                 names_tail = this_name;
794                 /* try to find namespace spec */
795                 this_name->name_space = default_namespace;
796                 if ( ((nsptr = strchr(argv[optc], '/')) != NULL )
797                         && ( nsptr != argv[optc] )) {
798                         if (strcmp(nsptr+1, "tcp") == 0) {
799                                 this_name->name_space = NAMESPACE_TCP;
800                                 *nsptr = '\0';
801                         } else if (strcmp(nsptr+1, "udp") == 0) {
802                                 this_name->name_space = NAMESPACE_UDP;
803                                 *nsptr = '\0';
804                         } else if (strcmp(nsptr+1, "file") == 0) {
805                                 this_name->name_space = NAMESPACE_FILE;
806                                 *nsptr = '\0';
807                         }
808                 }
809                 this_name->matched_procs = NULL;
810                 if ((opts & OPT_MOUNTS || opts & OPT_MOUNTPOINT) && this_name->name_space != NAMESPACE_FILE)
811                         usage(_("You can only use files with mountpoint option"));
812                 switch(this_name->name_space) {
813                         case NAMESPACE_TCP:
814                                 asprintf(&(this_name->filename), "%s/tcp", argv[optc]);
815 #ifdef WITH_IPV6
816                                 parse_inet(this_name, ipv4_only, ipv6_only, &tcp_connection_list, &tcp6_connection_list);
817 #else
818                                 parse_inet(this_name, &tcp_connection_list);
819 #endif
820                                 break;
821                         case NAMESPACE_UDP:
822                                 asprintf(&(this_name->filename), "%s/udp", argv[optc]);
823 #ifdef WITH_IPV6
824                                 parse_inet(this_name, ipv4_only, ipv6_only, &tcp_connection_list, &tcp6_connection_list);
825 #else
826                                 parse_inet(this_name, &tcp_connection_list);
827 #endif
828                                 break;
829                         default: /* FILE */
830                                 this_name->filename = strdup(argv[optc]);
831                                         parse_file(this_name, &match_inodes);
832                                         parse_unixsockets(this_name, &match_inodes, unixsockets);
833                                 if (opts & OPT_MOUNTPOINT || opts & OPT_MOUNTS)
834                                         parse_mounts(this_name, mount_devices, &match_devices, opts);
835                                 break;
836                 }
837
838         } /* for optc */
839         if (names_head == NULL) {
840                 usage(_("No process specification given"));
841         }
842         /* Check conflicting operations */
843         if (opts & OPT_MOUNTPOINT) {
844                 if (opts & OPT_MOUNTS)
845                         usage(_("You cannot use the mounted and mountpoint flags together"));
846         }
847         if (opts & OPT_SILENT) 
848         {
849                 opts &= ~OPT_VERBOSE;
850                 opts &= ~OPT_USER;
851                 if (opts & OPT_ALLFILES)
852                         usage(_("all option cannot be used with silent option."));
853         }
854 #ifdef WITH_IPV6
855         if (ipv4_only && ipv6_only)
856                 usage(_("You cannot search for only IPv4 and only IPv6 sockets at the same time"));
857         if (!ipv4_only) {
858 #endif
859                 if (tcp_connection_list != NULL)
860                         find_net_sockets(&match_inodes, tcp_connection_list, "tcp",netdev);
861                 if (udp_connection_list != NULL)
862                         find_net_sockets(&match_inodes, udp_connection_list, "udp",netdev);
863 #ifdef WITH_IPV6
864         }
865         if (!ipv6_only) {
866                 if (tcp6_connection_list != NULL)
867                         find_net6_sockets(&match_inodes, tcp6_connection_list, "tcp",netdev);
868                 if (udp6_connection_list != NULL)
869                         find_net6_sockets(&match_inodes,  udp6_connection_list, "udp",netdev);
870         }
871 #endif
872 #ifdef DEBUG
873         debug_match_lists(names_head, match_inodes, match_devices);
874 #endif
875         scan_procs(names_head, match_inodes, match_devices);
876 #ifdef NFS_CHECKS
877     scan_knfsd(names_head, match_devices);
878 #endif /* NFS_CHECKS */
879         return print_matches(names_head,opts, sig_number);
880 }
881
882 /* 
883  * returns 0 if match, 1 if no match
884  */
885 static int print_matches(struct names *names_head, const opt_type opts, const int sig_number)
886 {
887         struct names *nptr;
888         struct procs *pptr;
889         char head = 0;
890         char first = 1;
891         int len = 0;
892         struct passwd *pwent = NULL;
893         int have_match = 0;
894         
895         for (nptr = names_head; nptr != NULL ; nptr = nptr->next) {
896                 if (opts & OPT_SILENT) {
897                         have_match = nptr->matched_procs ? 1 : have_match;
898                 } else { /* We're not silent */
899                         if (nptr->matched_procs != NULL || opts & OPT_ALLFILES) {
900                                 if (head == 0 && opts & OPT_VERBOSE) {
901                                         fprintf(stderr, _("%*s USER        PID ACCESS COMMAND\n"),
902                                                 NAME_FIELD, "");
903                                         head = 1;
904                                 }
905     
906                                 fprintf(stderr, "%s:", nptr->filename);
907                                 len = strlen(nptr->filename) + 1;
908                         }
909     
910                         first = 1;
911                         for (pptr = nptr->matched_procs; pptr != NULL ; pptr = pptr->next) {
912                                 have_match = 1;
913                                 if (opts & (OPT_VERBOSE|OPT_USER)) {
914                                         if (pwent == NULL || pwent->pw_uid != pptr->uid)
915                                                 pwent = getpwuid(pptr->uid);
916                                 }
917                                 if (len > NAME_FIELD && (opts & OPT_VERBOSE)) {
918                                         putc('\n', stderr);
919                                         len=0;
920                                 }
921                                 if ((opts & OPT_VERBOSE) || first) 
922                                         while (len++ < NAME_FIELD)
923                                                 putc(' ', stderr);
924                                 if (opts & OPT_VERBOSE) {
925                                         if (pwent == NULL)
926                                                 fprintf(stderr, " %-8s ", _("(unknown)"));
927                                         else
928                                                 fprintf(stderr, " %-8s ", pwent->pw_name);
929                                 }
930                                 printf("%6d", pptr->pid);
931                                 fflush(stdout);
932                                 if (opts & OPT_VERBOSE) {
933                                         fprintf(stderr, " %c%c%c%c%c ",
934                                                 pptr->access & ACCESS_FILE ? (pptr->access & ACCESS_FILEWR ? 'F' : 'f' ) : '.',
935                                                 pptr->access & ACCESS_ROOT ? 'r' : '.',
936                                                 pptr->access & ACCESS_CWD ? 'c' : '.',
937                                                 pptr->access & ACCESS_EXE ? 'e' : '.',
938                                                 (pptr->access & ACCESS_MMAP) && !(pptr->access & ACCESS_EXE) ? 'm' : '.');
939                                 } else {
940                                         if (pptr->access & ACCESS_ROOT)
941                                                 putc('r', stderr);
942                                         if (pptr->access & ACCESS_CWD)
943                                                 putc('c', stderr);
944                                         if (pptr->access & ACCESS_EXE)
945                                                 putc('e', stderr);
946                                         else if (pptr->access & ACCESS_MMAP)
947                                                 putc('m', stderr);
948                                 }
949                                 if (opts & OPT_USER) {
950                                         if (pwent == NULL)
951                                                 fprintf(stderr, " %-8s ", _("(unknown)"));
952                                         else
953                                                 fprintf(stderr, "(%s)", pwent->pw_name);
954                                 }
955                                 if (opts & OPT_VERBOSE) {
956                                         if (pptr->command == NULL)
957                                                 fprintf(stderr, "???\n");
958                                         else 
959                                                 fprintf(stderr, "%s\n", pptr->command);
960                                 }
961                                 len = 0;
962                                 first = 0;
963                         }
964                 if (opts & OPT_VERBOSE) {
965                   /* put a newline if showing all files and no procs*/
966                   if (nptr->matched_procs == NULL && (opts & OPT_ALLFILES))
967                     putc('\n', stderr);
968                 } else {
969                           if (nptr->matched_procs != NULL || (opts & OPT_ALLFILES))
970                                 putc('\n', stderr);
971                 }
972                 } /* be silent */
973                 if (opts & OPT_KILL)
974                         kill_matched_proc(nptr->matched_procs,  opts, sig_number);
975
976         } /* next name */
977         return (have_match==1?0:1);
978
979 }
980
981 static struct stat *get_pidstat(const pid_t pid, const char *filename)
982 {
983         char pathname[256];
984         struct stat *st;
985
986         if ( (st = malloc(sizeof(struct stat))) == NULL)
987                 return NULL;
988         snprintf(pathname, 256, "/proc/%d/%s", pid, filename);
989         if (stat(pathname, st) != 0) 
990                 return NULL;
991         else
992                 return st;
993 }
994
995 static void check_dir(const pid_t pid, const char *dirname, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access)
996 {
997         char *dirpath, *filepath;
998         DIR *dirp;
999         struct dirent *direntry;
1000         struct inode_list *ino_tmp;
1001         struct device_list *dev_tmp;
1002         struct stat st, lst;
1003
1004         if ( (dirpath = malloc(MAX_PATHNAME)) == NULL)
1005                 return;
1006         if ( (filepath = malloc(MAX_PATHNAME)) == NULL)
1007                 return;
1008
1009         snprintf(dirpath, MAX_PATHNAME, "/proc/%d/%s", pid, dirname);
1010         if ( (dirp = opendir(dirpath)) == NULL)
1011                 return;
1012         while ( (direntry = readdir(dirp)) != NULL) {
1013                 if (direntry->d_name[0] < '0' || direntry->d_name[0] > '9')
1014                         continue;
1015
1016                 snprintf(filepath, MAX_PATHNAME, "/proc/%d/%s/%s",
1017                         pid, dirname, direntry->d_name);
1018                 if (stat(filepath, &st) != 0) {
1019                         fprintf(stderr, _("Cannot stat file %s: %s\n"),filepath, strerror(errno));
1020                 } else {
1021                         for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) {
1022                                 if (st.st_dev == dev_tmp->device) {
1023                                         if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) {
1024                                                 add_matched_proc(dev_tmp->name, pid,uid, ACCESS_FILEWR|access);
1025                                         } else  {
1026                                                 add_matched_proc(dev_tmp->name, pid,uid, access);
1027                                         }
1028                                 }
1029                         }
1030                         for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) {
1031                                 if (st.st_dev == ino_tmp->device && st.st_ino == ino_tmp->inode) {
1032                                         if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) {
1033                                                 add_matched_proc(ino_tmp->name, pid,uid, ACCESS_FILEWR|access);
1034                                         } else {
1035                                                 add_matched_proc(ino_tmp->name, pid,uid, access);
1036                                         }
1037                                 }
1038                         }
1039                 }
1040         } /* while fd_dent */
1041         closedir(dirp);
1042 }
1043
1044 static void check_map(const pid_t pid, const char *filename, struct device_list *dev_head, struct inode_list *ino_head, const uid_t uid, const char access)
1045 {
1046         char pathname[MAX_PATHNAME];
1047         char line[BUFSIZ];
1048         struct inode_list *ino_tmp;
1049         struct device_list *dev_tmp;
1050         FILE *fp;
1051         unsigned long long tmp_inode;
1052         unsigned int tmp_maj, tmp_min;
1053         dev_t tmp_device;
1054
1055         snprintf(pathname, MAX_PATHNAME, "/proc/%d/%s", pid, filename);
1056         if ( (fp = fopen(pathname, "r")) == NULL)
1057                 return;
1058         while (fgets(line,BUFSIZ, fp)) {
1059                 if (sscanf(line, "%*s %*s %*s %x:%x %lld", 
1060                                         &tmp_maj, &tmp_min, &tmp_inode) == 3) {
1061                         tmp_device = tmp_maj * 256 + tmp_min;
1062                         for(dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next)
1063                                 if (dev_tmp->device == tmp_device)
1064                                         add_matched_proc(dev_tmp->name, pid, uid, access);
1065                         for(ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next)
1066                                 if (ino_tmp->device == tmp_device && ino_tmp->inode == tmp_inode)
1067                                         add_matched_proc(ino_tmp->name, pid, uid, access);
1068                 }
1069         }
1070         fclose(fp);
1071 }
1072
1073 static uid_t getpiduid(const pid_t pid)
1074 {
1075         char pathname[MAX_PATHNAME];
1076         struct stat st;
1077
1078         if (snprintf(pathname, MAX_PATHNAME, "/proc/%d", pid) < 0) 
1079                 return 0;
1080         if (stat(pathname, &st) != 0)
1081                 return 0;
1082         return st.st_uid;
1083 }
1084
1085 void add_mount_device(struct mountdev_list **mount_head,const char *fsname, const char *dir, dev_t device)
1086 {
1087         struct mountdev_list *newmount;
1088         /*printf("Adding mount Path: %s Dir:%s dev:%0x\n",dir, fsname, device);*/
1089
1090         if ( (newmount = malloc(sizeof(struct mountdev_list))) == NULL)
1091                 return;
1092         newmount->fsname = strdup(fsname);
1093         newmount->dir = strdup(dir);
1094         newmount->device = device;
1095         newmount->next = *mount_head;
1096         *mount_head = newmount;
1097 }
1098
1099 /*
1100  * fill_unix_cache : Create a list of Unix sockets
1101  *   This list is used later for matching purposes
1102  */
1103 void fill_unix_cache(struct unixsocket_list **unixsocket_head)
1104 {
1105         FILE *fp;
1106         char line[BUFSIZ];
1107         char *scanned_path;
1108         int scanned_inode;
1109         struct stat st;
1110         struct unixsocket_list *newsocket;
1111         
1112         if ( (fp = fopen("/proc/net/unix","r")) == NULL) {
1113                 fprintf(stderr, _("Cannot open /proc/net/unix: %s\n"),
1114                                 strerror(errno));
1115                 return;
1116         }
1117         while (fgets(line, BUFSIZ, fp) != NULL) {
1118                 if (sscanf(line, "%*x: %*x %*x %*x %*x %*d %d %as",
1119                         &scanned_inode,
1120                         &scanned_path) != 2) 
1121                         continue;
1122                 if (stat(scanned_path, &st) < 0) {
1123                         free(scanned_path);
1124                         continue;
1125                 }
1126                 if ( (newsocket = malloc(sizeof(struct unixsocket_list))) == NULL)
1127                         continue;
1128                 newsocket->sun_name = strdup(scanned_path);
1129                 newsocket->inode = st.st_ino;
1130                 newsocket->dev = st.st_dev;
1131         newsocket->net_inode = scanned_inode;
1132                 newsocket->next = *unixsocket_head;
1133                 *unixsocket_head = newsocket;
1134         } /* while */
1135
1136 }
1137
1138 /*
1139  * scan_mount_devices : Create a list of mount points and devices
1140  *   This list is used later for matching purposes
1141  */
1142 void scan_mount_devices(const opt_type opts, struct mountdev_list **mount_devices)
1143 {
1144         FILE *mntfp;
1145         struct mntent *mnt_ptr;
1146         struct stat st;
1147         
1148         if ( (mntfp = setmntent("/etc/mtab","r")) == NULL) {
1149                 fprintf(stderr, _("Cannot open /etc/mtab: %s\n"),
1150                                 strerror(errno));
1151                 return;
1152         }
1153         while ( (mnt_ptr = getmntent(mntfp)) != NULL) {
1154                 if (stat(mnt_ptr->mnt_dir, &st) == 0) {
1155                         add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, st.st_dev);
1156                 }
1157         }
1158 }
1159
1160 #ifdef DEBUG
1161 /* often not used, doesnt need translation */
1162 static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head)
1163 {
1164         struct names *nptr;
1165         struct inode_list *iptr;
1166         struct device_list *dptr;
1167
1168         fprintf(stderr,"Specified Names:\n");
1169         for (nptr=names_head; nptr!= NULL; nptr=nptr->next) 
1170         {
1171                 fprintf(stderr, "\t%s %c\n", nptr->filename, nptr->name_space);
1172         }
1173         fprintf(stderr,"\nInodes:\n");
1174         for (iptr=ino_head; iptr!=NULL; iptr=iptr->next)
1175         {
1176                 fprintf(stderr, "  Dev:%0lx Inode:(%0ld) 0x%0lx => %s\n",
1177                                 (unsigned long)iptr->device, (unsigned long)iptr->inode, (unsigned long)iptr->inode, iptr->name->filename);
1178         }
1179         fprintf(stderr,"\nDevices:\n");
1180         for (dptr=dev_head; dptr!=NULL; dptr=dptr->next)
1181         {
1182                 fprintf(stderr, "\tDev:%0lx\n",
1183                                 (unsigned long)dptr->device);
1184         }
1185 }
1186
1187 #endif
1188
1189 /* 0 = no, 1=yes */
1190 static int ask(const pid_t pid)
1191 {
1192         int res;
1193         size_t len = 0;
1194         char *line = NULL;
1195
1196         fflush(stdout);
1197         while(1) {
1198                 fprintf(stderr, _("Kill process %d ? (y/N) "), pid);
1199                 fflush(stderr);
1200                 if (getline(&line, &len, stdin) < 0)
1201                         return 0;
1202                 if (line[0] == '\n') {
1203                         free(line);
1204                         return 0;
1205                 }
1206                 res = rpmatch(line);
1207                 if (res >= 0) {
1208                         free(line);
1209                         return res;
1210                 }
1211         } /* while */
1212 }
1213
1214 static void kill_matched_proc(struct procs *proc_head, const opt_type opts, const int sig_number)
1215 {
1216         struct procs *pptr;
1217
1218         for (pptr = proc_head ; pptr != NULL ; pptr = pptr->next ) {
1219                 if ( (opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0))
1220                         continue;
1221                 if ( kill (pptr->pid, sig_number) < 0) {
1222                         fprintf(stderr, _("Could not kill process %d: %s\n"),
1223                                         pptr->pid,
1224                                         strerror(errno)
1225                                 );
1226                 }
1227                                         
1228         }
1229 }
1230
1231 static dev_t find_net_dev(void)
1232 {
1233   int skt;
1234   struct stat st;
1235
1236   if ( (skt = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
1237     fprintf(stderr,_("Cannot open a network socket.\n"));
1238     return -1;
1239   }
1240   if ( fstat(skt, &st) != 0) {
1241     fprintf(stderr,_("Cannot find socket's device number.\n"));
1242     close(skt);
1243     return -1;
1244   }
1245   close(skt);
1246   return st.st_dev;
1247 }
1248
1249 #ifdef NFS_CHECKS
1250 static void scan_knfsd(struct names *names_head, struct device_list *dev_head)
1251 {
1252         struct device_list *dev_tmp;
1253         FILE *fp;
1254         char line[BUFSIZ];
1255     char *find_space;
1256     struct stat st;
1257
1258     if ( (fp = fopen(KNFSD_EXPORTS, "r")) == NULL) {
1259 #ifdef DEBUG
1260       printf("Cannot open %s\n", KNFSD_EXPORTS);
1261 #endif
1262       return;
1263     }
1264         while (fgets(line, BUFSIZ, fp) != NULL) {
1265       if (line[0] == '#') { continue; }
1266       if ( (find_space=strpbrk(line," \t")) == NULL) {
1267         continue;
1268       }
1269       *find_space = '\0';
1270       if ( stat(line, &st) != 0) {
1271     printf("hello %s\n", line);
1272         continue;
1273       }
1274       printf("looking for dev %0x\n", st.st_dev);
1275       /* Scan the devices */
1276           for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) {
1277          printf("dev %d\n", dev_tmp->device);
1278        }
1279
1280     }
1281 }
1282 #endif /* NFSCHECKS */