2 * fuser.c - identify processes using files
4 * Based on fuser.c Copyright (C) 1993-2005 Werner Almesberger and Craig Small
6 * Completely re-written
7 * Copyright (C) 2005-2007 Craig Small
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.
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.
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
35 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <arpa/inet.h>
39 #include <netinet/in.h>
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);
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);
77 static void scan_knfsd(struct names *names_head, struct device_list *dev_head);
78 #endif /* NFS_CHECKS */
80 static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head);
83 static void usage (const char *errormsg)
86 fprintf(stderr, "%s\n", errormsg);
89 "Usage: fuser [ -a | -s | -c ] [ -n SPACE ] [ -SIGNAL ] [ -kimuv ] NAME...\n"
90 " [ - ] [ -n SPACE ] [ -SIGNAL ] [ -kimuv ] NAME...\n"
93 "Show which processes use the named files, sockets, or filesystems.\n\n"
94 " -a display unused files too\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"));
109 " -4 search IPv4 sockets only\n"
110 " -6 search IPv6 sockets only\n"));
113 " - reset options\n\n"
114 " udp/tcp names: [local_port][,[rmt_host][,[rmt_port]]]\n\n"));
120 fprintf(stderr, _("fuser (PSmisc) %s\n"), VERSION);
122 "Copyright (C) 1993-2005 Werner Almesberger and Craig Small\n\n"));
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"));
130 static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head)
133 struct dirent *topproc_dent;
134 char *fd_dirpath, *fd_pathname;
135 struct inode_list *ino_tmp;
136 struct device_list *dev_tmp;
139 struct stat *cwd_stat, *exe_stat, *root_stat;
141 if ( (fd_dirpath = malloc(MAX_PATHNAME)) == NULL)
143 if ( (fd_pathname = malloc(MAX_PATHNAME)) == NULL)
146 if ( (topproc_dir = opendir("/proc")) == NULL) {
147 fprintf(stderr, _("Cannot open /proc directory: %s\n"), strerror(errno));
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 */
154 pid = atoi(topproc_dent->d_name);
155 /* Dont print myself */
158 uid = getpiduid(pid);
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);
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);
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);
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);
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);
195 } /* while topproc_dent */
196 closedir(topproc_dir);
198 static void add_inode(struct inode_list **ino_list, struct names *this_name, dev_t device, ino_t inode)
200 struct inode_list *ino_tmp, *ino_head;
202 ino_head = *ino_list;
204 if ( (ino_tmp = malloc(sizeof(struct inode_list))) == NULL)
206 ino_tmp->name = this_name;
207 ino_tmp->device = device;
208 ino_tmp->inode = inode;
209 ino_tmp->next = ino_head;
213 static void add_device(struct device_list **dev_list, struct names *this_name, dev_t device)
215 struct device_list *dev_tmp, *dev_head;
217 /*printf("Adding device %s %d\n", this_name->filename, device);*/
218 dev_head = *dev_list;
220 if ( (dev_tmp = malloc(sizeof(struct device_list))) == NULL)
222 dev_tmp->name = this_name;
223 dev_tmp->device = device;
224 dev_tmp->next = dev_head;
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)
230 struct ip_connections *ip_tmp, *ip_head;
234 if ( (ip_tmp = malloc(sizeof(struct ip_connections))) == NULL)
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;
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)
248 struct ip6_connections *ip_tmp, *ip_head;
252 if ( (ip_tmp = malloc(sizeof(struct ip6_connections))) == NULL)
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;
264 static void add_matched_proc(struct names *name_list, const pid_t pid, const uid_t uid, const char access)
266 struct procs *pptr, *last_proc;
268 char cmdname[101], *cptr;
273 for (pptr = name_list->matched_procs; pptr != NULL ; pptr = pptr->next)
276 if (pptr->pid == pid) {
277 pptr->access |= access;
282 if ( (pptr = malloc(sizeof (struct procs))) == NULL) {
283 fprintf(stderr,_("Cannot allocate memory for matched proc: %s\n"), strerror(errno));
288 pptr->access = access;
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) {
297 for (cptr = cmdname; cmdlen < MAX_CMDNAME && *cptr ; cptr++) {
299 pptr->command[cmdlen++] = *cptr;
300 else if(cmdlen < (MAX_CMDNAME-4))
301 cmdlen += sprintf(&(pptr->command[cmdlen]), "\\%03o", *cptr);
303 pptr->command[cmdlen] = '\0';
305 if (last_proc == NULL)
306 name_list->matched_procs = pptr;
308 last_proc->next = pptr;
311 int parse_mount(struct names *this_name, struct device_list **dev_list)
315 if (stat(this_name->filename, &st) != 0) {
316 fprintf(stderr, _("Cannot stat mount point %s: %s\n"),
322 printf("Debug: parse_mount() adding %s\n", this_name->filename);
324 add_device(dev_list, this_name, st.st_dev);
328 int parse_file(struct names *this_name, struct inode_list **ino_list)
332 if (stat(this_name->filename, &st) != 0) {
333 fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
338 printf("adding file %s %lX %lX\n", this_name->filename,
339 (unsigned long)st.st_dev, (unsigned long)st.st_ino);
341 add_inode(ino_list, this_name, st.st_dev, st.st_ino);
345 int parse_unixsockets(struct names *this_name, struct inode_list **ino_list, struct unixsocket_list *sun_head)
347 struct unixsocket_list *sun_tmp;
351 if (stat(this_name->filename, &st) != 0) {
352 fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
356 net_dev = find_net_dev();
358 for (sun_tmp = sun_head; sun_tmp != NULL ; sun_tmp = sun_tmp->next)
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);
368 int parse_mounts(struct names *this_name, struct mountdev_list *mounts, struct device_list **dev_list, const char opts)
371 struct mountdev_list *mountptr;
374 if (stat(this_name->filename, &st) != 0) {
375 fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename,
379 if (S_ISBLK(st.st_mode))
380 match_device = st.st_rdev;
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);
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)
396 int parse_inet(struct names *this_name, struct ip_connections **ip_list)
399 struct addrinfo *res, *resptr;
400 struct addrinfo hints;
402 char *lcl_port_str, *rmt_addr_str, *rmt_port_str, *tmpstr, *tmpstr2;
404 struct sockaddr_in *sin;
406 struct sockaddr_in6 *sin6;
412 if ( (protocol = strchr(this_name->filename, '/')) == NULL)
415 if (protocol[0] == '\0')
417 for (i=0; i < 99 && this_name->filename[i] != '\0' && this_name->filename[i] != '/'; i++)
418 hostspec[i] = this_name->filename[i];
421 lcl_port_str = rmt_addr_str = rmt_port_str = NULL;
422 /* Split out the names */
423 if ( (tmpstr = strchr(hostspec, ',')) == NULL) {
425 lcl_port_str = strdup(hostspec);
427 if (tmpstr == hostspec)
431 lcl_port_str = strdup(hostspec);
434 if (*tmpstr != '\0') {
435 if ( (tmpstr2 = strchr(tmpstr, ',')) == NULL) {
437 rmt_addr_str = tmpstr;
439 if (tmpstr2 == tmpstr)
442 rmt_addr_str = tmpstr;
446 if (*tmpstr2 != '\0')
447 rmt_port_str = tmpstr2;
452 printf("parsed to lp %s rh %s rp %s\n", lcl_port_str, rmt_addr_str, rmt_port_str);
455 memset(&hints, 0, sizeof(hints));
458 hints.ai_family = PF_INET6;
459 } else if (ipv4_only) {
460 hints.ai_family = PF_INET;
462 hints.ai_family = PF_UNSPEC;
464 hints.ai_family = PF_INET;
466 if (strcmp(protocol, "tcp") == 0)
467 hints.ai_socktype = SOCK_STREAM;
469 hints.ai_socktype = SOCK_DGRAM;
471 if (lcl_port_str == NULL) {
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));
482 switch(res->ai_family) {
484 lcl_port = ((struct sockaddr_in*)(res->ai_addr))->sin_port;
488 lcl_port = ((struct sockaddr_in6*)(res->ai_addr))->sin6_port;
492 fprintf(stderr, _("Unknown local port AF %d\n"), res->ai_family);
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);
503 add_ip6_conn(ip6_list, protocol,this_name, ntohs(lcl_port), 0, in6addr_any);
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) {
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);
516 add_ip_conn(ip_list, protocol, this_name, ntohs(lcl_port), ntohs(sin->sin_port), sin->sin_addr.s_addr);
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);
525 add_ip6_conn(ip6_list, protocol, this_name, ntohs(lcl_port), ntohs(sin6->sin6_port), sin6->sin6_addr);
540 void find_net_sockets(struct inode_list **ino_list, struct ip_connections *conn_list, const char *protocol, dev_t netdev)
543 char pathname[200], line[BUFSIZ];
544 unsigned long loc_port, rmt_port;
545 unsigned long rmt_addr, scanned_inode;
547 struct ip_connections *conn_tmp;
549 if (snprintf(pathname,200, "/proc/net/%s", protocol) < 0)
552 if ( (fp = fopen(pathname, "r")) == NULL) {
553 fprintf(stderr, _("Cannot open protocol file \"%s\": %s\n"), pathname,strerror(errno));
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",
561 &scanned_inode) != 4)
564 printf("Found IPv4 *:%lu with %s:%lu\n", loc_port, inet_ntoa(*((struct in_addr*)&rmt_addr)), rmt_port);
566 inode = scanned_inode;
567 for(conn_tmp = conn_list ; conn_tmp != NULL ; conn_tmp = conn_tmp->next) {
569 printf(" Comparing with *.%lu %s:%lu\n",
571 inet_ntoa(conn_tmp->rmt_address),
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))
579 /* add inode to list */
581 printf("Added inode!\n");
583 add_inode(ino_list, conn_tmp->name, netdev, inode);
593 void find_net6_sockets(struct inode_list **ino_list, struct ip6_connections *conn_list, const char *protocol, const dev_t netdev)
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;
606 head = tmpptr = tail = NULL;
608 if (snprintf(pathname,200, "/proc/net/%s6", protocol) < 0)
611 if ( (fp = fopen(pathname, "r")) == NULL) {
613 printf("Cannot open protocol file \"%s\": %s\n", pathname, strerror(errno));
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",
624 &rmt_port, &scanned_inode) != 7)
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);
633 printf("Found IPv6 %ld with %s:%ld\n", loc_port, rmt_addr6str, rmt_port);
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);
638 printf(" Comparing with *.%lu %s:%lu ...\n",
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))
648 add_inode(ino_list, conn_tmp->name, netdev, inode);
655 int main(int argc, char *argv[])
660 int ipv4_only, ipv6_only;
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;
668 struct ip_connections *tcp_connection_list = NULL;
669 struct ip_connections *udp_connection_list = NULL;
671 struct ip6_connections *tcp6_connection_list = NULL;
672 struct ip6_connections *udp6_connection_list = NULL;
674 struct inode_list *match_inodes = NULL;
675 struct names *names_head, *this_name, *names_tail;
681 ipv4_only = ipv6_only = 0;
683 names_head = this_name = names_tail = NULL;
685 sig_number = SIGKILL;
688 /* Set up the i18n */
689 setlocale(LC_ALL, "");
690 bindtextdomain(PACKAGE, LOCALEDIR);
694 netdev = find_net_dev();
695 scan_mount_devices(opts, &mount_devices);
696 fill_unix_cache(&unixsockets);
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') {
720 opts |= OPT_ALLFILES;
723 opts |= OPT_MOUNTPOINT;
732 opts |= OPT_INTERACTIVE;
746 usage(_("Namespace option requires an argument."));
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;
755 usage(_("Invalid namespace name"));
770 if ( isupper(*option) || isdigit(*option) ) {
771 sig_number = get_signal(option,"fuser");
776 fprintf(stderr,"%s: Invalid option %c\n",argv[0] , argv[optc][1]);
785 /* File specifications */
786 if ( (this_name = malloc(sizeof(struct names))) == NULL)
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;
801 } else if (strcmp(nsptr+1, "udp") == 0) {
802 this_name->name_space = NAMESPACE_UDP;
804 } else if (strcmp(nsptr+1, "file") == 0) {
805 this_name->name_space = NAMESPACE_FILE;
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) {
814 asprintf(&(this_name->filename), "%s/tcp", argv[optc]);
816 parse_inet(this_name, ipv4_only, ipv6_only, &tcp_connection_list, &tcp6_connection_list);
818 parse_inet(this_name, &tcp_connection_list);
822 asprintf(&(this_name->filename), "%s/udp", argv[optc]);
824 parse_inet(this_name, ipv4_only, ipv6_only, &tcp_connection_list, &tcp6_connection_list);
826 parse_inet(this_name, &tcp_connection_list);
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);
839 if (names_head == NULL) {
840 usage(_("No process specification given"));
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"));
847 if (opts & OPT_SILENT)
849 opts &= ~OPT_VERBOSE;
851 if (opts & OPT_ALLFILES)
852 usage(_("all option cannot be used with silent option."));
855 if (ipv4_only && ipv6_only)
856 usage(_("You cannot search for only IPv4 and only IPv6 sockets at the same time"));
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);
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);
873 debug_match_lists(names_head, match_inodes, match_devices);
875 scan_procs(names_head, match_inodes, match_devices);
877 scan_knfsd(names_head, match_devices);
878 #endif /* NFS_CHECKS */
879 return print_matches(names_head,opts, sig_number);
883 * returns 0 if match, 1 if no match
885 static int print_matches(struct names *names_head, const opt_type opts, const int sig_number)
892 struct passwd *pwent = NULL;
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"),
906 fprintf(stderr, "%s:", nptr->filename);
907 len = strlen(nptr->filename) + 1;
911 for (pptr = nptr->matched_procs; pptr != NULL ; pptr = pptr->next) {
913 if (opts & (OPT_VERBOSE|OPT_USER)) {
914 if (pwent == NULL || pwent->pw_uid != pptr->uid)
915 pwent = getpwuid(pptr->uid);
917 if (len > NAME_FIELD && (opts & OPT_VERBOSE)) {
921 if ((opts & OPT_VERBOSE) || first)
922 while (len++ < NAME_FIELD)
924 if (opts & OPT_VERBOSE) {
926 fprintf(stderr, " %-8s ", _("(unknown)"));
928 fprintf(stderr, " %-8s ", pwent->pw_name);
930 printf("%6d", pptr->pid);
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' : '.');
940 if (pptr->access & ACCESS_ROOT)
942 if (pptr->access & ACCESS_CWD)
944 if (pptr->access & ACCESS_EXE)
946 else if (pptr->access & ACCESS_MMAP)
949 if (opts & OPT_USER) {
951 fprintf(stderr, " %-8s ", _("(unknown)"));
953 fprintf(stderr, "(%s)", pwent->pw_name);
955 if (opts & OPT_VERBOSE) {
956 if (pptr->command == NULL)
957 fprintf(stderr, "???\n");
959 fprintf(stderr, "%s\n", pptr->command);
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))
969 if (nptr->matched_procs != NULL || (opts & OPT_ALLFILES))
974 kill_matched_proc(nptr->matched_procs, opts, sig_number);
977 return (have_match==1?0:1);
981 static struct stat *get_pidstat(const pid_t pid, const char *filename)
986 if ( (st = malloc(sizeof(struct stat))) == NULL)
988 snprintf(pathname, 256, "/proc/%d/%s", pid, filename);
989 if (stat(pathname, st) != 0)
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)
997 char *dirpath, *filepath;
999 struct dirent *direntry;
1000 struct inode_list *ino_tmp;
1001 struct device_list *dev_tmp;
1002 struct stat st, lst;
1004 if ( (dirpath = malloc(MAX_PATHNAME)) == NULL)
1006 if ( (filepath = malloc(MAX_PATHNAME)) == NULL)
1009 snprintf(dirpath, MAX_PATHNAME, "/proc/%d/%s", pid, dirname);
1010 if ( (dirp = opendir(dirpath)) == NULL)
1012 while ( (direntry = readdir(dirp)) != NULL) {
1013 if (direntry->d_name[0] < '0' || direntry->d_name[0] > '9')
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));
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);
1026 add_matched_proc(dev_tmp->name, pid,uid, access);
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);
1035 add_matched_proc(ino_tmp->name, pid,uid, access);
1040 } /* while fd_dent */
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)
1046 char pathname[MAX_PATHNAME];
1048 struct inode_list *ino_tmp;
1049 struct device_list *dev_tmp;
1051 unsigned long long tmp_inode;
1052 unsigned int tmp_maj, tmp_min;
1055 snprintf(pathname, MAX_PATHNAME, "/proc/%d/%s", pid, filename);
1056 if ( (fp = fopen(pathname, "r")) == NULL)
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);
1073 static uid_t getpiduid(const pid_t pid)
1075 char pathname[MAX_PATHNAME];
1078 if (snprintf(pathname, MAX_PATHNAME, "/proc/%d", pid) < 0)
1080 if (stat(pathname, &st) != 0)
1085 void add_mount_device(struct mountdev_list **mount_head,const char *fsname, const char *dir, dev_t device)
1087 struct mountdev_list *newmount;
1088 /*printf("Adding mount Path: %s Dir:%s dev:%0x\n",dir, fsname, device);*/
1090 if ( (newmount = malloc(sizeof(struct mountdev_list))) == NULL)
1092 newmount->fsname = strdup(fsname);
1093 newmount->dir = strdup(dir);
1094 newmount->device = device;
1095 newmount->next = *mount_head;
1096 *mount_head = newmount;
1100 * fill_unix_cache : Create a list of Unix sockets
1101 * This list is used later for matching purposes
1103 void fill_unix_cache(struct unixsocket_list **unixsocket_head)
1110 struct unixsocket_list *newsocket;
1112 if ( (fp = fopen("/proc/net/unix","r")) == NULL) {
1113 fprintf(stderr, _("Cannot open /proc/net/unix: %s\n"),
1117 while (fgets(line, BUFSIZ, fp) != NULL) {
1118 if (sscanf(line, "%*x: %*x %*x %*x %*x %*d %d %as",
1120 &scanned_path) != 2)
1122 if (stat(scanned_path, &st) < 0) {
1126 if ( (newsocket = malloc(sizeof(struct unixsocket_list))) == NULL)
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;
1139 * scan_mount_devices : Create a list of mount points and devices
1140 * This list is used later for matching purposes
1142 void scan_mount_devices(const opt_type opts, struct mountdev_list **mount_devices)
1145 struct mntent *mnt_ptr;
1148 if ( (mntfp = setmntent("/etc/mtab","r")) == NULL) {
1149 fprintf(stderr, _("Cannot open /etc/mtab: %s\n"),
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);
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)
1165 struct inode_list *iptr;
1166 struct device_list *dptr;
1168 fprintf(stderr,"Specified Names:\n");
1169 for (nptr=names_head; nptr!= NULL; nptr=nptr->next)
1171 fprintf(stderr, "\t%s %c\n", nptr->filename, nptr->name_space);
1173 fprintf(stderr,"\nInodes:\n");
1174 for (iptr=ino_head; iptr!=NULL; iptr=iptr->next)
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);
1179 fprintf(stderr,"\nDevices:\n");
1180 for (dptr=dev_head; dptr!=NULL; dptr=dptr->next)
1182 fprintf(stderr, "\tDev:%0lx\n",
1183 (unsigned long)dptr->device);
1190 static int ask(const pid_t pid)
1198 fprintf(stderr, _("Kill process %d ? (y/N) "), pid);
1200 if (getline(&line, &len, stdin) < 0)
1202 if (line[0] == '\n') {
1206 res = rpmatch(line);
1214 static void kill_matched_proc(struct procs *proc_head, const opt_type opts, const int sig_number)
1218 for (pptr = proc_head ; pptr != NULL ; pptr = pptr->next ) {
1219 if ( (opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0))
1221 if ( kill (pptr->pid, sig_number) < 0) {
1222 fprintf(stderr, _("Could not kill process %d: %s\n"),
1231 static dev_t find_net_dev(void)
1236 if ( (skt = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
1237 fprintf(stderr,_("Cannot open a network socket.\n"));
1240 if ( fstat(skt, &st) != 0) {
1241 fprintf(stderr,_("Cannot find socket's device number.\n"));
1250 static void scan_knfsd(struct names *names_head, struct device_list *dev_head)
1252 struct device_list *dev_tmp;
1258 if ( (fp = fopen(KNFSD_EXPORTS, "r")) == NULL) {
1260 printf("Cannot open %s\n", KNFSD_EXPORTS);
1264 while (fgets(line, BUFSIZ, fp) != NULL) {
1265 if (line[0] == '#') { continue; }
1266 if ( (find_space=strpbrk(line," \t")) == NULL) {
1270 if ( stat(line, &st) != 0) {
1271 printf("hello %s\n", line);
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);
1282 #endif /* NFSCHECKS */