From 5eac9a52571f88637a83fdb3a4dd831bc06a8c80 Mon Sep 17 00:00:00 2001 From: Craig Small Date: Fri, 10 Jul 2009 06:45:14 +0000 Subject: [PATCH] * Applied patch from Kari Hautio for lazy umount'ed filesystems SF#25456 32 * Applied patch from Anonymous SF submitter to fix killall -l Fixes SF#2002570 * fuser will print mounts,nfs exports and swaps with -v Debian #356655 * pstree and fuser have long options Debian #517412 --- ChangeLog | 7 + configure.ac | 2 +- doc/fuser.1 | 5 +- src/fuser.c | 1497 ++++++++++++++++++++++++++++++------------------- src/fuser.h | 19 +- src/killall.c | 18 +- src/pstree.c | 57 +- 7 files changed, 982 insertions(+), 623 deletions(-) diff --git a/ChangeLog b/ChangeLog index 73ee714..fc2a061 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ Changes in 22.8 =============== +2009-06-10 Craig Small + * Applied patch from Kari Hautio for lazy umount'ed filesystems SF#2545632 + * Applied patch from Anonymous SF submitter to fix killall -l + Fixes SF#2002570 + * fuser will print mounts,nfs exports and swaps with -v Debian #356655 + * pstree and fuser have long options Debian #517412 + 2009-06-09 Craig Small * Fixed pstree -a off-by-one error in buffer, Debian #536243 * Changed configure.ac to not use CXX SF# 2789801 diff --git a/configure.ac b/configure.ac index b597c3e..645c45f 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.61) -AC_INIT([psmisc],[22.7]) +AC_INIT([psmisc],[22.8]) AC_CONFIG_SRCDIR([src/comm.h]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_AUX_DIR([config]) diff --git a/doc/fuser.1 b/doc/fuser.1 index b513e70..39147e2 100644 --- a/doc/fuser.1 +++ b/doc/fuser.1 @@ -101,8 +101,9 @@ Append the user name of the process owner to each PID. .IP \fB\-v\fP Verbose mode. Processes are shown in a \fBps\fP-like style. The fields PID, USER and COMMAND are similar to \fBps\fP. ACCESS shows how the process -accesses the file. If the access is by the kernel (e.g. in the case of a -mount point, a swap file, etc.), \fBkernel\fP is shown instead of the PID. +accesses the file. Verbose mode will also show when a particular file +is being access as a mount point, knfs export or swap file. In this case +\fBkernel\fP is shown instead of the PID. .IP \fB\-V\fP Display version information. .IP \fB\-4\fP diff --git a/src/fuser.c b/src/fuser.c index 4a11db2..c9b4008 100644 --- a/src/fuser.c +++ b/src/fuser.c @@ -50,84 +50,100 @@ #include "signals.h" #include "i18n.h" -/* -#define DEBUG 1 -*/ -/* -#define NFS_CHECKS -*/ +//#define DEBUG 1 #define NAME_FIELD 20 /* space reserved for file name */ /* Function defines */ -static void add_matched_proc(struct names *name_list, const pid_t pid, const uid_t uid, const char access); -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, - struct unixsocket_list *sockets, dev_t netdev); -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); +static void add_matched_proc(struct names *name_list, const pid_t pid, + const uid_t uid, const char access); +static void add_special_proc(struct names *name_list, const char ptype, + const uid_t uid, const char *command); +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, struct unixsocket_list *sockets, + dev_t netdev); +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); static struct stat *get_pidstat(const pid_t pid, const char *filename); static uid_t getpiduid(const pid_t pid); -static int print_matches(struct names *names_head, const opt_type opts, const int sig_number); -static void kill_matched_proc(struct procs *pptr, const opt_type opts, const int sig_number); - -int parse_mount(struct names *this_name, struct device_list **dev_list); -static void add_device(struct device_list **dev_list, struct names *this_name, dev_t device); -void scan_mount_devices(const opt_type opts, struct mountdev_list **mount_devices); +static int print_matches(struct names *names_head, const opt_type opts, + const int sig_number); +static void kill_matched_proc(struct procs *pptr, const opt_type opts, + const int sig_number); + +/*int parse_mount(struct names *this_name, struct device_list **dev_list);*/ +static void add_device(struct device_list **dev_list, + struct names *this_name, dev_t device); void fill_unix_cache(struct unixsocket_list **unixsocket_head); static dev_t find_net_dev(void); -static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct unixsocket_list *sockets, dev_t netdev); -#ifdef NFS_CHECKS -static void scan_knfsd(struct names *names_head, struct device_list *dev_head); -#endif /* NFS_CHECKS */ +static void scan_procs(struct names *names_head, struct inode_list *ino_head, + struct device_list *dev_head, + struct unixsocket_list *sockets, dev_t netdev); +static void scan_knfsd(struct names *names_head, struct inode_list *ino_head, + struct device_list *dev_head); +static void scan_mounts(struct names *names_head, + struct inode_list *ino_head, + struct device_list *dev_head); +static void scan_swaps(struct names *names_head, struct inode_list *ino_head, + struct device_list *dev_head); #ifdef DEBUG -static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head); +static void debug_match_lists(struct names *names_head, + struct inode_list *ino_head, + struct device_list *dev_head); #endif -static void usage (const char *errormsg) +static void usage(const char *errormsg) { if (errormsg != NULL) fprintf(stderr, "%s\n", errormsg); - fprintf (stderr, _( - "Usage: fuser [ -fuv ] [ -a | -s ] [ -4 | -6 ] [ -c | -m | -n SPACE ] [ -k [ -i ] [ -SIGNAL ]] NAME...\n" - " fuser -l\n" - " fuser -V\n" - "Show which processes use the named files, sockets, or filesystems.\n\n" - " -a display unused files too\n" - " -c Same as \-m (for POSIX compatibility)\n" - " -f silently ignored (for POSIX compatibility)\n" - " -i ask before killing (ignored without -k)\n" - " -k kill processes accessing the named file\n" - " -l list available signal names\n" - " -m show all processes using the named filesystems or block device\n" - " -n SPACE search in this name space (file, udp, or tcp)\n" - " -s silent operation\n" - " -SIGNAL send this signal instead of SIGKILL\n" - " -u display user IDs\n" - " -v verbose output\n" - " -V display version information\n")); + fprintf(stderr, + _ + ("Usage: fuser [ -fuv ] [ -a | -s ] [ -4 | -6 ] [ -c | -m | -n SPACE ] [ -k [ -i ] [ -SIGNAL ]] NAME...\n" + " fuser -l\n" " fuser -V\n" + "Show which processes use the named files, sockets, or filesystems.\n\n" + " -a display unused files too\n" + " -c Same as -m (for POSIX compatibility)\n" + " -f silently ignored (for POSIX compatibility)\n" + " -i ask before killing (ignored without -k)\n" + " -k kill processes accessing the named file\n" + " -l list available signal names\n" + " -m show all processes using the named filesystems or block device\n" + " -n SPACE search in this name space (file, udp, or tcp)\n" + " -s silent operation\n" + " -SIGNAL send this signal instead of SIGKILL\n" + " -u display user IDs\n" + " -v verbose output\n" + " -V display version information\n")); #ifdef WITH_IPV6 - fprintf (stderr, _( - " -4 search IPv4 sockets only\n" - " -6 search IPv6 sockets only\n")); + fprintf(stderr, _(" -4 search IPv4 sockets only\n" + " -6 search IPv6 sockets only\n")); #endif - fprintf (stderr, _( - " - reset options\n\n" - " udp/tcp names: [local_port][,[rmt_host][,[rmt_port]]]\n\n")); - exit (1); + fprintf(stderr, _(" - reset options\n\n" + " udp/tcp names: [local_port][,[rmt_host][,[rmt_port]]]\n\n")); + exit(1); } void print_version() { - fprintf(stderr, _("fuser (PSmisc) %s\n"), VERSION); - fprintf(stderr, _( - "Copyright (C) 1993-2009 Werner Almesberger and Craig Small\n\n")); - fprintf(stderr, _( - "PSmisc comes with ABSOLUTELY NO WARRANTY.\n" - "This is free software, and you are welcome to redistribute it under\n" - "the terms of the GNU General Public License.\n" - "For more information about these matters, see the files named COPYING.\n")); + fprintf(stderr, _("fuser (PSmisc) %s\n"), VERSION); + fprintf(stderr, + _ + ("Copyright (C) 1993-2009 Werner Almesberger and Craig Small\n\n")); + fprintf(stderr, + _("PSmisc comes with ABSOLUTELY NO WARRANTY.\n" + "This is free software, and you are welcome to redistribute it under\n" + "the terms of the GNU General Public License.\n" + "For more information about these matters, see the files named COPYING.\n")); } -static void scan_procs(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head, struct unixsocket_list *sockets, dev_t netdev) +static void +scan_procs(struct names *names_head, struct inode_list *ino_head, + struct device_list *dev_head, struct unixsocket_list *sockets, + dev_t netdev) { DIR *topproc_dir; struct dirent *topproc_dent; @@ -138,18 +154,19 @@ static void scan_procs(struct names *names_head, struct inode_list *ino_head, st uid_t uid; struct stat *cwd_stat, *exe_stat, *root_stat; - if ( (fd_dirpath = malloc(MAX_PATHNAME)) == NULL) + if ((fd_dirpath = malloc(MAX_PATHNAME)) == NULL) return; - if ( (fd_pathname = malloc(MAX_PATHNAME)) == NULL) + if ((fd_pathname = malloc(MAX_PATHNAME)) == NULL) return; - if ( (topproc_dir = opendir("/proc")) == NULL) { - fprintf(stderr, _("Cannot open /proc directory: %s\n"), strerror(errno)); + if ((topproc_dir = opendir("/proc")) == NULL) { + fprintf(stderr, _("Cannot open /proc directory: %s\n"), + strerror(errno)); exit(1); } my_pid = getpid(); - while ( (topproc_dent = readdir(topproc_dir)) != NULL) { - if (topproc_dent->d_name[0] < '0' || topproc_dent->d_name[0] > '9') /* Not a process */ + while ((topproc_dent = readdir(topproc_dir)) != NULL) { + if (topproc_dent->d_name[0] < '0' || topproc_dent->d_name[0] > '9') /* Not a process */ continue; pid = atoi(topproc_dent->d_name); /* Dont print myself */ @@ -161,47 +178,67 @@ static void scan_procs(struct names *names_head, struct inode_list *ino_head, st cwd_stat = get_pidstat(pid, "cwd"); exe_stat = get_pidstat(pid, "exe"); /* Scan the devices */ - for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) { - if (exe_stat != NULL && exe_stat->st_dev == dev_tmp->device) - add_matched_proc(dev_tmp->name, pid, uid, ACCESS_EXE); - if (root_stat != NULL && root_stat->st_dev == dev_tmp->device) - add_matched_proc(dev_tmp->name, pid, uid, ACCESS_ROOT); - if (cwd_stat != NULL && cwd_stat->st_dev == dev_tmp->device) - add_matched_proc(dev_tmp->name, pid, uid, ACCESS_CWD); + for (dev_tmp = dev_head; dev_tmp != NULL; + dev_tmp = dev_tmp->next) { + if (exe_stat != NULL + && exe_stat->st_dev == dev_tmp->device) + add_matched_proc(dev_tmp->name, pid, uid, + ACCESS_EXE); + if (root_stat != NULL + && root_stat->st_dev == dev_tmp->device) + add_matched_proc(dev_tmp->name, pid, uid, + ACCESS_ROOT); + if (cwd_stat != NULL + && cwd_stat->st_dev == dev_tmp->device) + add_matched_proc(dev_tmp->name, pid, uid, + ACCESS_CWD); } - for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) { + for (ino_tmp = ino_head; ino_tmp != NULL; + ino_tmp = ino_tmp->next) { if (exe_stat != NULL) { - if (exe_stat->st_dev == ino_tmp->device && exe_stat->st_ino == ino_tmp->inode) { - add_matched_proc(ino_tmp->name, pid, uid, ACCESS_EXE); + if (exe_stat->st_dev == ino_tmp->device + && exe_stat->st_ino == ino_tmp->inode) { + add_matched_proc(ino_tmp->name, pid, + uid, ACCESS_EXE); } } if (root_stat != NULL) { - if (root_stat->st_dev == ino_tmp->device && root_stat->st_ino == ino_tmp->inode){ - add_matched_proc(ino_tmp->name, pid, uid, ACCESS_ROOT); + if (root_stat->st_dev == ino_tmp->device + && root_stat->st_ino == ino_tmp->inode) { + add_matched_proc(ino_tmp->name, pid, + uid, ACCESS_ROOT); } } - if (cwd_stat != NULL){ - if (cwd_stat->st_dev == ino_tmp->device && cwd_stat->st_ino == ino_tmp->inode) { - add_matched_proc(ino_tmp->name, pid, uid, ACCESS_CWD); + if (cwd_stat != NULL) { + if (cwd_stat->st_dev == ino_tmp->device + && cwd_stat->st_ino == ino_tmp->inode) { + add_matched_proc(ino_tmp->name, pid, + uid, ACCESS_CWD); } } } - check_dir(pid, "lib", dev_head, ino_head, uid, ACCESS_MMAP, sockets, netdev); - check_dir(pid, "mmap", dev_head, ino_head, uid, ACCESS_MMAP, sockets, netdev); - check_dir(pid, "fd", dev_head, ino_head, uid, ACCESS_FILE, sockets, netdev); + check_dir(pid, "lib", dev_head, ino_head, uid, ACCESS_MMAP, + sockets, netdev); + check_dir(pid, "mmap", dev_head, ino_head, uid, ACCESS_MMAP, + sockets, netdev); + check_dir(pid, "fd", dev_head, ino_head, uid, ACCESS_FILE, + sockets, netdev); check_map(pid, "maps", dev_head, ino_head, uid, ACCESS_MMAP); - } /* while topproc_dent */ + } /* while topproc_dent */ closedir(topproc_dir); } -static void add_inode(struct inode_list **ino_list, struct names *this_name, dev_t device, ino_t inode) + +static void +add_inode(struct inode_list **ino_list, struct names *this_name, + dev_t device, ino_t inode) { struct inode_list *ino_tmp, *ino_head; ino_head = *ino_list; - if ( (ino_tmp = malloc(sizeof(struct inode_list))) == NULL) + if ((ino_tmp = malloc(sizeof(struct inode_list))) == NULL) return; ino_tmp->name = this_name; ino_tmp->device = device; @@ -210,14 +247,15 @@ static void add_inode(struct inode_list **ino_list, struct names *this_name, de *ino_list = ino_tmp; } -static void add_device(struct device_list **dev_list, struct names *this_name, dev_t device) +static void +add_device(struct device_list **dev_list, struct names *this_name, dev_t device) { struct device_list *dev_tmp, *dev_head; - /*printf("Adding device %s %d\n", this_name->filename, device);*/ + /*printf("Adding device %s %d\n", this_name->filename, device); */ dev_head = *dev_list; - if ( (dev_tmp = malloc(sizeof(struct device_list))) == NULL) + if ((dev_tmp = malloc(sizeof(struct device_list))) == NULL) return; dev_tmp->name = this_name; dev_tmp->device = device; @@ -225,13 +263,16 @@ static void add_device(struct device_list **dev_list, struct names *this_name, *dev_list = dev_tmp; } -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) +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) { struct ip_connections *ip_tmp, *ip_head; ip_head = *ip_list; - if ( (ip_tmp = malloc(sizeof(struct ip_connections))) == NULL) + if ((ip_tmp = malloc(sizeof(struct ip_connections))) == NULL) return; ip_tmp->name = this_name; ip_tmp->lcl_port = lcl_port; @@ -243,25 +284,31 @@ static void add_ip_conn(struct ip_connections **ip_list, const char *protocol, s } #ifdef WITH_IPV6 -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) +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) { struct ip6_connections *ip_tmp, *ip_head; ip_head = *ip_list; - if ( (ip_tmp = malloc(sizeof(struct ip6_connections))) == NULL) + if ((ip_tmp = malloc(sizeof(struct ip6_connections))) == NULL) return; ip_tmp->name = this_name; ip_tmp->lcl_port = lcl_port; ip_tmp->rmt_port = rmt_port; - memcpy(&(ip_tmp->rmt_address),&(rmt_address),sizeof(struct in6_addr)); + memcpy(&(ip_tmp->rmt_address), &(rmt_address), sizeof(struct in6_addr)); ip_tmp->next = ip_head; *ip_list = ip_tmp; } #endif -static void add_matched_proc(struct names *name_list, const pid_t pid, const uid_t uid, const char access) +/* Adds a normal process only */ +static void +add_matched_proc(struct names *name_list, const pid_t pid, const uid_t uid, + const char access) { struct procs *pptr, *last_proc; char *pathname; @@ -270,8 +317,7 @@ static void add_matched_proc(struct names *name_list, const pid_t pid, const uid FILE *fp; last_proc = NULL; - for (pptr = name_list->matched_procs; pptr != NULL ; pptr = pptr->next) - { + for (pptr = name_list->matched_procs; pptr != NULL; pptr = pptr->next) { last_proc = pptr; if (pptr->pid == pid) { pptr->access |= access; @@ -279,26 +325,32 @@ static void add_matched_proc(struct names *name_list, const pid_t pid, const uid } } /* Not found */ - if ( (pptr = malloc(sizeof (struct procs))) == NULL) { - fprintf(stderr,_("Cannot allocate memory for matched proc: %s\n"), strerror(errno)); + if ((pptr = malloc(sizeof(struct procs))) == NULL) { + fprintf(stderr, + _("Cannot allocate memory for matched proc: %s\n"), + strerror(errno)); return; } pptr->pid = pid; pptr->uid = uid; pptr->access = access; + pptr->proc_type = PTYPE_NORMAL; pptr->next = NULL; /* set command name */ pptr->command = NULL; - if ( (asprintf(&pathname, "/proc/%d/stat", pid) > 0) && - ( (fp = fopen(pathname, "r")) != NULL) && - ( fscanf(fp, "%*d (%100[^)]", cmdname) == 1)) - if ( (pptr->command = malloc(MAX_CMDNAME+1)) != NULL) { + if ((asprintf(&pathname, "/proc/%d/stat", pid) > 0) && + ((fp = fopen(pathname, "r")) != NULL) && + (fscanf(fp, "%*d (%100[^)]", cmdname) == 1)) + if ((pptr->command = malloc(MAX_CMDNAME + 1)) != NULL) { cmdlen = 0; - for (cptr = cmdname; cmdlen < MAX_CMDNAME && *cptr ; cptr++) { + for (cptr = cmdname; cmdlen < MAX_CMDNAME && *cptr; + cptr++) { if (isprint(*cptr)) pptr->command[cmdlen++] = *cptr; - else if(cmdlen < (MAX_CMDNAME-4)) - cmdlen += sprintf(&(pptr->command[cmdlen]), "\\%03o", *cptr); + else if (cmdlen < (MAX_CMDNAME - 4)) + cmdlen += + sprintf(&(pptr->command[cmdlen]), + "\\%03o", *cptr); } pptr->command[cmdlen] = '\0'; } @@ -308,21 +360,34 @@ static void add_matched_proc(struct names *name_list, const pid_t pid, const uid last_proc->next = pptr; } -int parse_mount(struct names *this_name, struct device_list **dev_list) +/* Adds a knfsd etc process */ +static void +add_special_proc(struct names *name_list, const char ptype, const uid_t uid, + const char *command) { - struct stat st; + struct procs *pptr, *last_proc; - if (stat(this_name->filename, &st) != 0) { - fprintf(stderr, _("Cannot stat mount point %s: %s\n"), - this_name->filename, - strerror(errno)); - exit(1); + last_proc = NULL; + for (pptr = name_list->matched_procs; pptr != NULL; pptr = pptr->next) { + last_proc = pptr; + if (pptr->proc_type == ptype) + return; } -#ifdef DEBUG - printf("Debug: parse_mount() adding %s\n", this_name->filename); -#endif /* DEBUG */ - add_device(dev_list, this_name, st.st_dev); - return 0; + if ((pptr = malloc(sizeof(struct procs))) == NULL) { + fprintf(stderr, + _("Cannot allocate memory for matched proc: %s\n"), + strerror(errno)); + return; + } + pptr->pid = 0; + pptr->uid = uid; + pptr->access = 0; + pptr->proc_type = ptype; + /* Append the special processes */ + pptr->next = name_list->matched_procs; + name_list->matched_procs = pptr; + /* set command name */ + pptr->command = strdup(command); } int parse_file(struct names *this_name, struct inode_list **ino_list) @@ -330,68 +395,67 @@ int parse_file(struct names *this_name, struct inode_list **ino_list) struct stat st; if (stat(this_name->filename, &st) != 0) { - fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename, - strerror(errno)); + fprintf(stderr, _("Cannot stat %s: %s\n"), this_name->filename, + strerror(errno)); return -1; } #ifdef DEBUG printf("adding file %s %lX %lX\n", this_name->filename, - (unsigned long)st.st_dev, (unsigned long)st.st_ino); -#endif /* DEBUG */ + (unsigned long)st.st_dev, (unsigned long)st.st_ino); +#endif /* DEBUG */ add_inode(ino_list, this_name, st.st_dev, st.st_ino); return 0; } -int parse_unixsockets(struct names *this_name, struct inode_list **ino_list, struct unixsocket_list *sun_head) +int +parse_unixsockets(struct names *this_name, struct inode_list **ino_list, + struct unixsocket_list *sun_head) { struct unixsocket_list *sun_tmp; struct stat st; - dev_t net_dev; - + dev_t net_dev; + if (stat(this_name->filename, &st) != 0) { - fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename, - strerror(errno)); + fprintf(stderr, _("Cannot stat %s: %s\n"), this_name->filename, + strerror(errno)); return -1; } - net_dev = find_net_dev(); + net_dev = find_net_dev(); - for (sun_tmp = sun_head; sun_tmp != NULL ; sun_tmp = sun_tmp->next) - { - if (sun_tmp->dev == st.st_dev && sun_tmp->inode == st.st_ino) { - add_inode(ino_list, this_name, net_dev, sun_tmp->net_inode); - return 0; + for (sun_tmp = sun_head; sun_tmp != NULL; sun_tmp = sun_tmp->next) { + if (sun_tmp->dev == st.st_dev && sun_tmp->inode == st.st_ino) { + add_inode(ino_list, this_name, net_dev, + sun_tmp->net_inode); + return 0; } } return 0; } -int parse_mounts(struct names *this_name, struct mountdev_list *mounts, struct device_list **dev_list, const char opts) +int +parse_mounts(struct names *this_name, struct device_list **dev_list, + const char opts) { struct stat st; - struct mountdev_list *mountptr; dev_t match_device; if (stat(this_name->filename, &st) != 0) { - fprintf(stderr,_("Cannot stat %s: %s\n"), this_name->filename, - strerror(errno)); + fprintf(stderr, _("Cannot stat %s: %s\n"), this_name->filename, + strerror(errno)); return -1; } if (S_ISBLK(st.st_mode)) match_device = st.st_rdev; else match_device = st.st_dev; - for (mountptr = mounts ; mountptr != NULL ; mountptr = mountptr->next) { - if (mountptr->device == match_device) { - /*printf("Debug: adding parse_mounts() adding %s\n", - this_name->filename);*/ - add_device(dev_list, this_name, match_device); - } - } + add_device(dev_list, this_name, match_device); return 0; } #ifdef WITH_IPV6 -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) +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) #else int parse_inet(struct names *this_name, struct ip_connections **ip_list) #endif @@ -408,19 +472,21 @@ int parse_inet(struct names *this_name, struct ip_connections **ip_list) char hostspec[100]; char *protocol; int i; - - if ( (protocol = strchr(this_name->filename, '/')) == NULL) + + if ((protocol = strchr(this_name->filename, '/')) == NULL) return -1; protocol++; if (protocol[0] == '\0') return -1; - for (i=0; i < 99 && this_name->filename[i] != '\0' && this_name->filename[i] != '/'; i++) + for (i = 0; + i < 99 && this_name->filename[i] != '\0' + && this_name->filename[i] != '/'; i++) hostspec[i] = this_name->filename[i]; hostspec[i] = '\0'; lcl_port_str = rmt_addr_str = rmt_port_str = NULL; /* Split out the names */ - if ( (tmpstr = strchr(hostspec, ',')) == NULL) { + if ((tmpstr = strchr(hostspec, ',')) == NULL) { /* Single option */ lcl_port_str = strdup(hostspec); } else { @@ -432,7 +498,7 @@ int parse_inet(struct names *this_name, struct ip_connections **ip_list) } tmpstr++; if (*tmpstr != '\0') { - if ( (tmpstr2 = strchr(tmpstr, ',')) == NULL) { + if ((tmpstr2 = strchr(tmpstr, ',')) == NULL) { /* Only 2 options */ rmt_addr_str = tmpstr; } else { @@ -449,7 +515,8 @@ int parse_inet(struct names *this_name, struct ip_connections **ip_list) } } #ifdef DEBUG - printf("parsed to lp %s rh %s rp %s\n", lcl_port_str, rmt_addr_str, rmt_port_str); + printf("parsed to lp %s rh %s rp %s\n", lcl_port_str, rmt_addr_str, + rmt_port_str); #endif memset(&hints, 0, sizeof(hints)); @@ -457,9 +524,9 @@ int parse_inet(struct names *this_name, struct ip_connections **ip_list) if (ipv6_only) { hints.ai_family = PF_INET6; } else if (ipv4_only) { - hints.ai_family = PF_INET; - } else - hints.ai_family = PF_UNSPEC; + hints.ai_family = PF_INET; + } else + hints.ai_family = PF_UNSPEC; #else hints.ai_family = PF_INET; #endif @@ -472,72 +539,104 @@ int parse_inet(struct names *this_name, struct ip_connections **ip_list) lcl_port = 0; } else { /* Resolve local port first */ - if ( (errcode = getaddrinfo(NULL, lcl_port_str, &hints, &res)) != 0) { + if ((errcode = + getaddrinfo(NULL, lcl_port_str, &hints, &res)) != 0) { fprintf(stderr, _("Cannot resolve local port %s: %s\n"), - lcl_port_str, gai_strerror(errcode)); + lcl_port_str, gai_strerror(errcode)); return -1; } if (res == NULL) return -1; - switch(res->ai_family) { - case AF_INET: - lcl_port = ((struct sockaddr_in*)(res->ai_addr))->sin_port; - break; + switch (res->ai_family) { + case AF_INET: + lcl_port = + ((struct sockaddr_in *)(res->ai_addr))->sin_port; + break; #ifdef WITH_IPV6 - case AF_INET6: - lcl_port = ((struct sockaddr_in6*)(res->ai_addr))->sin6_port; - break; + case AF_INET6: + lcl_port = + ((struct sockaddr_in6 *)(res->ai_addr))->sin6_port; + break; #endif - default: - fprintf(stderr, _("Unknown local port AF %d\n"), res->ai_family); - freeaddrinfo(res); - return -1; + default: + fprintf(stderr, _("Unknown local port AF %d\n"), + res->ai_family); + freeaddrinfo(res); + return -1; } freeaddrinfo(res); } free(lcl_port_str); res = NULL; if (rmt_addr_str == NULL && rmt_port_str == NULL) { - add_ip_conn(ip_list, protocol, this_name, ntohs(lcl_port), 0, INADDR_ANY); + add_ip_conn(ip_list, protocol, this_name, ntohs(lcl_port), 0, + INADDR_ANY); #ifdef WITH_IPV6 - add_ip6_conn(ip6_list, protocol,this_name, ntohs(lcl_port), 0, in6addr_any); + add_ip6_conn(ip6_list, protocol, this_name, ntohs(lcl_port), 0, + in6addr_any); #endif return 0; } else { /* Resolve remote address and port */ if (getaddrinfo(rmt_addr_str, rmt_port_str, &hints, &res) == 0) { - for(resptr = res ; resptr != NULL ; resptr = resptr->ai_next ) { - switch(resptr->ai_family) { - case AF_INET: - sin = (struct sockaddr_in*)resptr->ai_addr; - if (rmt_addr_str == NULL) { - add_ip_conn(ip_list, protocol, this_name, ntohs(lcl_port), ntohs(sin->sin_port), INADDR_ANY); - } else { - add_ip_conn(ip_list, protocol, this_name, ntohs(lcl_port), ntohs(sin->sin_port), sin->sin_addr.s_addr); - } + for (resptr = res; resptr != NULL; + resptr = resptr->ai_next) { + switch (resptr->ai_family) { + case AF_INET: + sin = + (struct sockaddr_in *) + resptr->ai_addr; + if (rmt_addr_str == NULL) { + add_ip_conn(ip_list, protocol, + this_name, + ntohs(lcl_port), + ntohs + (sin->sin_port), + INADDR_ANY); + } else { + add_ip_conn(ip_list, protocol, + this_name, + ntohs(lcl_port), + ntohs + (sin->sin_port), + sin-> + sin_addr.s_addr); + } break; #ifdef WITH_IPV6 case AF_INET6: - sin6 = (struct sockaddr_in6*)resptr->ai_addr; - if (rmt_addr_str == NULL) { - add_ip6_conn(ip6_list, protocol, this_name, ntohs(lcl_port), ntohs(sin6->sin6_port), in6addr_any); - } else { - add_ip6_conn(ip6_list, protocol, this_name, ntohs(lcl_port), ntohs(sin6->sin6_port), sin6->sin6_addr); - } + sin6 = + (struct sockaddr_in6 *) + resptr->ai_addr; + if (rmt_addr_str == NULL) { + add_ip6_conn(ip6_list, protocol, + this_name, + ntohs(lcl_port), + ntohs + (sin6->sin6_port), + in6addr_any); + } else { + add_ip6_conn(ip6_list, protocol, + this_name, + ntohs(lcl_port), + ntohs + (sin6->sin6_port), + sin6->sin6_addr); + } break; #endif } - } /*while */ + } /*while */ return 0; } } return 1; } - - - -void find_net_sockets(struct inode_list **ino_list, struct ip_connections *conn_list, const char *protocol, dev_t netdev) +void +find_net_sockets(struct inode_list **ino_list, + struct ip_connections *conn_list, const char *protocol, + dev_t netdev) { FILE *fp; char pathname[200], line[BUFSIZ]; @@ -546,51 +645,60 @@ void find_net_sockets(struct inode_list **ino_list, struct ip_connections *conn_ ino_t inode; struct ip_connections *conn_tmp; - if (snprintf(pathname,200, "/proc/net/%s", protocol) < 0) - return ; + if (snprintf(pathname, 200, "/proc/net/%s", protocol) < 0) + return; - if ( (fp = fopen(pathname, "r")) == NULL) { - fprintf(stderr, _("Cannot open protocol file \"%s\": %s\n"), pathname,strerror(errno)); + if ((fp = fopen(pathname, "r")) == NULL) { + fprintf(stderr, _("Cannot open protocol file \"%s\": %s\n"), + pathname, strerror(errno)); return; } while (fgets(line, BUFSIZ, fp) != NULL) { - if (sscanf(line, "%*u: %*x:%lx %08lx:%lx %*x %*x:%*x %*x:%*x %*x %*d %*d %lu", - &loc_port, - &rmt_addr, - &rmt_port, - &scanned_inode) != 4) + if (sscanf + (line, + "%*u: %*x:%lx %08lx:%lx %*x %*x:%*x %*x:%*x %*x %*d %*d %lu", + &loc_port, &rmt_addr, &rmt_port, &scanned_inode) != 4) continue; #ifdef DEBUG - printf("Found IPv4 *:%lu with %s:%lu\n", loc_port, inet_ntoa(*((struct in_addr*)&rmt_addr)), rmt_port); -#endif /* DEBUG */ + printf("Found IPv4 *:%lu with %s:%lu\n", loc_port, + inet_ntoa(*((struct in_addr *)&rmt_addr)), rmt_port); +#endif /* DEBUG */ inode = scanned_inode; - for(conn_tmp = conn_list ; conn_tmp != NULL ; conn_tmp = conn_tmp->next) { + for (conn_tmp = conn_list; conn_tmp != NULL; + conn_tmp = conn_tmp->next) { #ifdef DEBUG - printf(" Comparing with *.%lu %s:%lu\n", - conn_tmp->lcl_port, - inet_ntoa(conn_tmp->rmt_address), - conn_tmp->rmt_port); + printf(" Comparing with *.%lu %s:%lu\n", + conn_tmp->lcl_port, + inet_ntoa(conn_tmp->rmt_address), + conn_tmp->rmt_port); #endif - if ( (conn_tmp->lcl_port == 0 || conn_tmp->lcl_port == loc_port) && - (conn_tmp->rmt_port == 0 || conn_tmp->rmt_port == rmt_port) && - (conn_tmp->rmt_address.s_addr == INADDR_ANY || - (memcmp(&(conn_tmp->rmt_address), &(rmt_addr),4) ==0)) - ) { + if ((conn_tmp->lcl_port == 0 + || conn_tmp->lcl_port == loc_port) + && (conn_tmp->rmt_port == 0 + || conn_tmp->rmt_port == rmt_port) + && (conn_tmp->rmt_address.s_addr == INADDR_ANY + || + (memcmp + (&(conn_tmp->rmt_address), &(rmt_addr), + 4) == 0))) { /* add inode to list */ #ifdef DEBUG - printf("Added inode!\n"); -#endif /* DEBUG */ - add_inode(ino_list, conn_tmp->name, netdev, inode); + printf("Added inode!\n"); +#endif /* DEBUG */ + add_inode(ino_list, conn_tmp->name, netdev, + inode); } } - } - return ; + return; } #ifdef WITH_IPV6 -void find_net6_sockets(struct inode_list **ino_list, struct ip6_connections *conn_list, const char *protocol, const dev_t netdev) +void +find_net6_sockets(struct inode_list **ino_list, + struct ip6_connections *conn_list, const char *protocol, + const dev_t netdev) { FILE *fp; char pathname[200], line[BUFSIZ]; @@ -605,23 +713,22 @@ void find_net6_sockets(struct inode_list **ino_list, struct ip6_connections *con head = tmpptr = tail = NULL; - if (snprintf(pathname,200, "/proc/net/%s6", protocol) < 0) - return ; + if (snprintf(pathname, 200, "/proc/net/%s6", protocol) < 0) + return; - if ( (fp = fopen(pathname, "r")) == NULL) { + if ((fp = fopen(pathname, "r")) == NULL) { #ifdef DEBUG - printf("Cannot open protocol file \"%s\": %s\n", pathname, strerror(errno)); -#endif /* DEBUG */ - return ; + printf("Cannot open protocol file \"%s\": %s\n", pathname, + strerror(errno)); +#endif /* DEBUG */ + return; } while (fgets(line, BUFSIZ, fp) != NULL) { - if (sscanf(line, "%*u: %*x:%lx %08x%08x%08x%08x:%lx %*x %*x:%*x %*x:%*x %*x %*d %*d %lu", - &loc_port, - &(tmp_addr[0]), - &(tmp_addr[1]), - &(tmp_addr[2]), - &(tmp_addr[3]), - &rmt_port, &scanned_inode) != 7) + if (sscanf + (line, + "%*u: %*x:%lx %08x%08x%08x%08x:%lx %*x %*x:%*x %*x:%*x %*x %*d %*d %lu", + &loc_port, &(tmp_addr[0]), &(tmp_addr[1]), &(tmp_addr[2]), + &(tmp_addr[3]), &rmt_port, &scanned_inode) != 7) continue; inode = scanned_inode; rmt_addr.s6_addr32[0] = tmp_addr[0]; @@ -630,22 +737,30 @@ void find_net6_sockets(struct inode_list **ino_list, struct ip6_connections *con rmt_addr.s6_addr32[3] = tmp_addr[3]; inet_ntop(AF_INET6, &rmt_addr, rmt_addr6str, INET6_ADDRSTRLEN); #ifdef DEBUG - printf("Found IPv6 %ld with %s:%ld\n", loc_port, rmt_addr6str, rmt_port); -#endif /* DEBUG */ - for(conn_tmp = conn_list ; conn_tmp != NULL ; conn_tmp = conn_tmp->next) { - inet_ntop(AF_INET6, &conn_tmp->rmt_address, rmt_addr6str, INET6_ADDRSTRLEN); + printf("Found IPv6 %ld with %s:%ld\n", loc_port, rmt_addr6str, + rmt_port); +#endif /* DEBUG */ + for (conn_tmp = conn_list; conn_tmp != NULL; + conn_tmp = conn_tmp->next) { + inet_ntop(AF_INET6, &conn_tmp->rmt_address, + rmt_addr6str, INET6_ADDRSTRLEN); #ifdef DEBUG - printf(" Comparing with *.%lu %s:%lu ...\n", - conn_tmp->lcl_port, - rmt_addr6str, - conn_tmp->rmt_port); -#endif /* DEBUG */ - if ( (conn_tmp->lcl_port == 0 || conn_tmp->lcl_port == loc_port) && - (conn_tmp->rmt_port == 0 || conn_tmp->rmt_port == rmt_port) && - (memcmp(&(conn_tmp->rmt_address), &in6addr_any,16) == 0 || - (memcmp(&(conn_tmp->rmt_address), &(rmt_addr),16) ==0)) - ) { - add_inode(ino_list, conn_tmp->name, netdev, inode); + printf(" Comparing with *.%lu %s:%lu ...\n", + conn_tmp->lcl_port, rmt_addr6str, + conn_tmp->rmt_port); +#endif /* DEBUG */ + if ((conn_tmp->lcl_port == 0 + || conn_tmp->lcl_port == loc_port) + && (conn_tmp->rmt_port == 0 + || conn_tmp->rmt_port == rmt_port) + && + (memcmp(&(conn_tmp->rmt_address), &in6addr_any, 16) + == 0 + || + (memcmp(&(conn_tmp->rmt_address), &(rmt_addr), 16) + == 0))) { + add_inode(ino_list, conn_tmp->name, netdev, + inode); } } } @@ -654,13 +769,12 @@ void find_net6_sockets(struct inode_list **ino_list, struct ip6_connections *con int main(int argc, char *argv[]) { - opt_type opts; + opt_type opts; int sig_number; #ifdef WITH_IPV6 int ipv4_only, ipv6_only; #endif unsigned char default_namespace = NAMESPACE_FILE; - struct mountdev_list *mount_devices = NULL; struct device_list *match_devices = NULL; struct unixsocket_list *unixsockets = NULL; @@ -676,6 +790,28 @@ int main(int argc, char *argv[]) int optc; char *option; char *nsptr; + int ignore_options; + char *sig_aname; + + struct option options[] = { + {"all", 0, NULL, 'a'}, + {"kill", 0, NULL, 'k'}, + {"interactive", 0, NULL, 'i'}, + {"list-signals", 0, NULL, 'l'}, + {"mount", 0, NULL, 'm'}, + {"namespace", 1, NULL, 'n'}, + {"silent", 0, NULL, 's'}, + {"user", 0, NULL, 'u'}, + {"verbose", 0, NULL, 'v'}, + {"version", 0, NULL, 'V'}, +#ifdef WITH_IPV6 + {"ipv4", 0, NULL, '4'}, + {"ipv6", 0, NULL, '6'}, +#endif + {"SIG", 1, NULL, 'S'}, + + + }; #ifdef WITH_IPV6 ipv4_only = ipv6_only = 0; @@ -692,98 +828,115 @@ int main(int argc, char *argv[]) #endif netdev = find_net_dev(); - scan_mount_devices(opts, &mount_devices); fill_unix_cache(&unixsockets); - /* getopt doesnt like things like -SIGBLAH */ - for(optc = 1; optc < argc; optc++) { - if (argv[optc][0] == '-') { /* its an option */ - option=argv[optc] + 1; - if (argv[optc][1] == '-') { /* its a long option */ - if (argv[optc][2] == '\0') { - continue; - } - /* FIXME longopts */ - continue; - } - while (*option) { - switch(*option) { + opterr=0; + ignore_options=0; + while ((optc = #ifdef WITH_IPV6 - case '4': - ipv4_only = 1; - break; - case '6': - ipv6_only = 1; - break; + getopt_long(argc, argv, "46acfhikmn:sS:uvV", options,NULL) +#else + getopt_long(argc, argv, "acfhikmn:sS:uvV", options,NULL) #endif - case 'a': - opts |= OPT_ALLFILES; - break; - case 'c': - opts |= OPT_MOUNTPOINT; - break; - case 'f': - /* ignored */ - break; - case 'h': - usage(NULL); - break; - case 'i': - opts |= OPT_INTERACTIVE; - break; - case 'k': - opts |= OPT_KILL; - break; - case 'l': - list_signals(); - return 0; - case 'm': - opts |= OPT_MOUNTS; - break; - case 'n': - optc++; - if (optc >= argc) { - usage(_("Namespace option requires an argument.")); - } - if (strcmp(argv[optc], "tcp") == 0) - default_namespace = NAMESPACE_TCP; - else if (strcmp(argv[optc], "udp") == 0) - default_namespace = NAMESPACE_UDP; - else if (strcmp(argv[optc], "file") == 0) - default_namespace = NAMESPACE_FILE; - else - usage(_("Invalid namespace name")); - break; - case 's': - opts |= OPT_SILENT; - break; - case 'u': - opts |= OPT_USER; - break; - case 'v': - opts |= OPT_VERBOSE; - break; - case 'V': - print_version(); - return 0; - default: - if ( isupper(*option) || isdigit(*option) ) { - sig_number = get_signal(option,"fuser"); - option[1]='\0'; - - break; - } - fprintf(stderr,"%s: Invalid option %c\n",argv[0] , argv[optc][1]); - usage(NULL); - - break; - } /* switch */ - option++; + ) != -1) { + if (ignore_options > 0) { + ignore_options--; + continue; + } + switch (optc) { +#ifdef WITH_IPV6 + case '4': + ipv4_only = 1; + break; + case '6': + ipv6_only = 1; + break; +#endif + case 'a': + opts |= OPT_ALLFILES; + break; + case 'c': + opts |= OPT_MOUNTPOINT; + break; + case 'f': + /* ignored */ + break; + case 'h': + usage(NULL); + break; + case 'i': + opts |= OPT_INTERACTIVE; + break; + case 'k': + opts |= OPT_KILL; + break; + case 'l': + list_signals(); + return 0; + case 'm': + opts |= OPT_MOUNTS; + break; + case 'n': + if (strcmp(optarg, "tcp") == 0) + default_namespace = NAMESPACE_TCP; + else if (strcmp(optarg, "udp") == 0) + default_namespace = NAMESPACE_UDP; + else if (strcmp(optarg, "file") == 0) + default_namespace = NAMESPACE_FILE; + else + usage(_("Invalid namespace name")); + break; + case 's': + opts |= OPT_SILENT; + break; + case 'S': + { + char *signame; + asprintf(&signame, "S%s",optarg); + sig_number = get_signal(signame,argv[0]); + free(signame); + break; } - continue; - } + case 'u': + opts |= OPT_USER; + break; + case 'v': + opts |= OPT_VERBOSE; + break; + case 'V': + print_version(); + return 0; + case '?': + if (optopt=='n') { + usage(_ + ("Namespace option requires an argument.")); + } + if (isdigit(optopt)) { + if (strlen(argv[optind-1]) == 2) + sig_aname =strdup(argv[optind-1]+1); + else { + sig_aname = strdup(argv[optind]+1); + ignore_options = strlen(argv[optind])-2; + } + sig_number = get_signal(sig_aname,argv[0]); + free(sig_aname); + break; + } + fprintf(stderr, "%s: Invalid option %c\n", argv[0], + optopt); + exit(1); + usage(NULL); + + break; + default: + printf("unknown optc %c\n", optc); + exit(1); + + } /* switch */ + } /* while optc */ + for (optc = optind; optc < argc; optc++) { /* File specifications */ - if ( (this_name = malloc(sizeof(struct names))) == NULL) + if ((this_name = malloc(sizeof(struct names))) == NULL) continue; this_name->next = NULL; if (names_head == NULL) @@ -793,96 +946,111 @@ int main(int argc, char *argv[]) names_tail = this_name; /* try to find namespace spec */ this_name->name_space = default_namespace; - if ( ((nsptr = strchr(argv[optc], '/')) != NULL ) - && ( nsptr != argv[optc] )) { - if (strcmp(nsptr+1, "tcp") == 0) { + if (((nsptr = strchr(argv[optc], '/')) != NULL) + && (nsptr != argv[optc])) { + if (strcmp(nsptr + 1, "tcp") == 0) { this_name->name_space = NAMESPACE_TCP; *nsptr = '\0'; - } else if (strcmp(nsptr+1, "udp") == 0) { + } else if (strcmp(nsptr + 1, "udp") == 0) { this_name->name_space = NAMESPACE_UDP; *nsptr = '\0'; - } else if (strcmp(nsptr+1, "file") == 0) { + } else if (strcmp(nsptr + 1, "file") == 0) { this_name->name_space = NAMESPACE_FILE; *nsptr = '\0'; } } this_name->matched_procs = NULL; - if ((opts & OPT_MOUNTS || opts & OPT_MOUNTPOINT) && this_name->name_space != NAMESPACE_FILE) - usage(_("You can only use files with mountpoint option")); - switch(this_name->name_space) { - case NAMESPACE_TCP: - asprintf(&(this_name->filename), "%s/tcp", argv[optc]); + if ((opts & OPT_MOUNTS || opts & OPT_MOUNTPOINT) + && this_name->name_space != NAMESPACE_FILE) + usage(_ + ("You can only use files with mountpoint option")); + switch (this_name->name_space) { + case NAMESPACE_TCP: + asprintf(&(this_name->filename), "%s/tcp", argv[optc]); #ifdef WITH_IPV6 - parse_inet(this_name, ipv4_only, ipv6_only, &tcp_connection_list, &tcp6_connection_list); + parse_inet(this_name, ipv4_only, ipv6_only, + &tcp_connection_list, &tcp6_connection_list); #else - parse_inet(this_name, &tcp_connection_list); + parse_inet(this_name, &tcp_connection_list); #endif - break; - case NAMESPACE_UDP: - asprintf(&(this_name->filename), "%s/udp", argv[optc]); + break; + case NAMESPACE_UDP: + asprintf(&(this_name->filename), "%s/udp", argv[optc]); #ifdef WITH_IPV6 - parse_inet(this_name, ipv4_only, ipv6_only, &udp_connection_list, &udp6_connection_list); + parse_inet(this_name, ipv4_only, ipv6_only, + &udp_connection_list, &udp6_connection_list); #else - parse_inet(this_name, &udp_connection_list); + parse_inet(this_name, &udp_connection_list); #endif - break; - default: /* FILE */ - this_name->filename = strdup(argv[optc]); - parse_file(this_name, &match_inodes); - parse_unixsockets(this_name, &match_inodes, unixsockets); - if (opts & OPT_MOUNTPOINT || opts & OPT_MOUNTS) - parse_mounts(this_name, mount_devices, &match_devices, opts); - break; + break; + default: /* FILE */ + this_name->filename = strdup(argv[optc]); + parse_file(this_name, &match_inodes); + parse_unixsockets(this_name, &match_inodes, + unixsockets); + if (opts & OPT_MOUNTPOINT || opts & OPT_MOUNTS) + parse_mounts(this_name, &match_devices, opts); + break; } - } /* for optc */ + } /* for optc */ + if (names_head == NULL) { usage(_("No process specification given")); } /* Check conflicting operations */ if (opts & OPT_MOUNTPOINT) { if (opts & OPT_MOUNTS) - usage(_("You cannot use the mounted and mountpoint flags together")); + usage(_ + ("You cannot use the mounted and mountpoint flags together")); } - if (opts & OPT_SILENT) - { + if (opts & OPT_SILENT) { opts &= ~OPT_VERBOSE; opts &= ~OPT_USER; if (opts & OPT_ALLFILES) - usage(_("all option cannot be used with silent option.")); + usage(_ + ("all option cannot be used with silent option.")); } #ifdef WITH_IPV6 if (ipv4_only && ipv6_only) - usage(_("You cannot search for only IPv4 and only IPv6 sockets at the same time")); + usage(_ + ("You cannot search for only IPv4 and only IPv6 sockets at the same time")); if (!ipv4_only) { #endif if (tcp_connection_list != NULL) - find_net_sockets(&match_inodes, tcp_connection_list, "tcp",netdev); + find_net_sockets(&match_inodes, tcp_connection_list, + "tcp", netdev); if (udp_connection_list != NULL) - find_net_sockets(&match_inodes, udp_connection_list, "udp",netdev); + find_net_sockets(&match_inodes, udp_connection_list, + "udp", netdev); #ifdef WITH_IPV6 } if (!ipv6_only) { if (tcp6_connection_list != NULL) - find_net6_sockets(&match_inodes, tcp6_connection_list, "tcp",netdev); + find_net6_sockets(&match_inodes, tcp6_connection_list, + "tcp", netdev); if (udp6_connection_list != NULL) - find_net6_sockets(&match_inodes, udp6_connection_list, "udp",netdev); + find_net6_sockets(&match_inodes, udp6_connection_list, + "udp", netdev); } #endif #ifdef DEBUG debug_match_lists(names_head, match_inodes, match_devices); #endif - scan_procs(names_head, match_inodes, match_devices, unixsockets, netdev); -#ifdef NFS_CHECKS - scan_knfsd(names_head, match_devices); -#endif /* NFS_CHECKS */ - return print_matches(names_head,opts, sig_number); + scan_procs(names_head, match_inodes, match_devices, unixsockets, + netdev); + scan_knfsd(names_head, match_inodes, match_devices); + scan_mounts(names_head, match_inodes, match_devices); + scan_swaps(names_head, match_inodes, match_devices); + return print_matches(names_head, opts, sig_number); } /* * returns 0 if match, 1 if no match */ -static int print_matches(struct names *names_head, const opt_type opts, const int sig_number) +static int +print_matches(struct names *names_head, const opt_type opts, + const int sig_number) { struct names *nptr; struct procs *pptr; @@ -891,90 +1059,151 @@ static int print_matches(struct names *names_head, const opt_type opts, const in int len = 0; struct passwd *pwent = NULL; int have_match = 0; - - for (nptr = names_head; nptr != NULL ; nptr = nptr->next) { + int name_has_procs; + + for (nptr = names_head; nptr != NULL; nptr = nptr->next) { if (opts & OPT_SILENT) { have_match = nptr->matched_procs ? 1 : have_match; - } else { /* We're not silent */ - if (nptr->matched_procs != NULL || opts & OPT_ALLFILES) { - if (head == 0 && opts & OPT_VERBOSE) { - fprintf(stderr, _("%*s USER PID ACCESS COMMAND\n"), - NAME_FIELD, ""); - head = 1; - } - - fprintf(stderr, "%s:", nptr->filename); - len = strlen(nptr->filename) + 1; - } - - first = 1; - for (pptr = nptr->matched_procs; pptr != NULL ; pptr = pptr->next) { - have_match = 1; - if (opts & (OPT_VERBOSE|OPT_USER)) { - if (pwent == NULL || pwent->pw_uid != pptr->uid) - pwent = getpwuid(pptr->uid); - } - if (len > NAME_FIELD && (opts & OPT_VERBOSE)) { - putc('\n', stderr); - len=0; - } - if ((opts & OPT_VERBOSE) || first) - while (len++ < NAME_FIELD) - putc(' ', stderr); - if (opts & OPT_VERBOSE) { - if (pwent == NULL) - fprintf(stderr, " %-8s ", _("(unknown)")); - else - fprintf(stderr, " %-8s ", pwent->pw_name); - } - printf("%6d", pptr->pid); - fflush(stdout); - if (opts & OPT_VERBOSE) { - fprintf(stderr, " %c%c%c%c%c ", - pptr->access & ACCESS_FILE ? (pptr->access & ACCESS_FILEWR ? 'F' : 'f' ) : '.', - pptr->access & ACCESS_ROOT ? 'r' : '.', - pptr->access & ACCESS_CWD ? 'c' : '.', - pptr->access & ACCESS_EXE ? 'e' : '.', - (pptr->access & ACCESS_MMAP) && !(pptr->access & ACCESS_EXE) ? 'm' : '.'); - } else { - if (pptr->access & ACCESS_ROOT) - putc('r', stderr); - if (pptr->access & ACCESS_CWD) - putc('c', stderr); - if (pptr->access & ACCESS_EXE) - putc('e', stderr); - else if (pptr->access & ACCESS_MMAP) - putc('m', stderr); - } - if (opts & OPT_USER) { - if (pwent == NULL) - fprintf(stderr, " %-8s ", _("(unknown)")); - else - fprintf(stderr, "(%s)", pwent->pw_name); - } - if (opts & OPT_VERBOSE) { - if (pptr->command == NULL) - fprintf(stderr, "???\n"); - else - fprintf(stderr, "%s\n", pptr->command); - } - len = 0; - first = 0; - } - if (opts & OPT_VERBOSE) { - /* put a newline if showing all files and no procs*/ - if (nptr->matched_procs == NULL && (opts & OPT_ALLFILES)) - putc('\n', stderr); - } else { - if (nptr->matched_procs != NULL || (opts & OPT_ALLFILES)) - putc('\n', stderr); - } - } /* be silent */ + } else { /* We're not silent */ + if ((opts & OPT_ALLFILES) == 0) { + name_has_procs = 0; + if (opts & OPT_VERBOSE) { + if (nptr->matched_procs) + name_has_procs = 1; + } else { + for (pptr = nptr->matched_procs; + pptr != NULL; pptr = pptr->next) { + if (pptr->proc_type == + PTYPE_NORMAL) { + name_has_procs = 1; + break; + } + } + } + } + if (name_has_procs == 1 || opts & OPT_ALLFILES) { + if (head == 0 && opts & OPT_VERBOSE) { + fprintf(stderr, + _ + ("%*s USER PID ACCESS COMMAND\n"), + NAME_FIELD, ""); + head = 1; + } + + fprintf(stderr, "%s:", nptr->filename); + len = strlen(nptr->filename) + 1; + } + + first = 1; + for (pptr = nptr->matched_procs; pptr != NULL; + pptr = pptr->next) { + /* Suppress any special "processes" */ + if (!(opts & OPT_VERBOSE) + && (pptr->proc_type != PTYPE_NORMAL)) + continue; + + have_match = 1; + if (opts & (OPT_VERBOSE | OPT_USER)) { + if (pwent == NULL + || pwent->pw_uid != pptr->uid) + pwent = getpwuid(pptr->uid); + } + if (len > NAME_FIELD && (opts & OPT_VERBOSE)) { + putc('\n', stderr); + len = 0; + } + if ((opts & OPT_VERBOSE) || first) + while (len++ < NAME_FIELD) + putc(' ', stderr); + if (opts & OPT_VERBOSE) { + if (pwent == NULL) + fprintf(stderr, " %-8s ", + _("(unknown)")); + else + fprintf(stderr, " %-8s ", + pwent->pw_name); + } + if (pptr->proc_type == PTYPE_NORMAL) + printf("%6d", pptr->pid); + else + printf("kernel"); + fflush(stdout); + if (opts & OPT_VERBOSE) { + switch (pptr->proc_type) { + case PTYPE_KNFSD: + fprintf(stderr, " knfsd "); + break; + case PTYPE_MOUNT: + fprintf(stderr, " mount "); + break; + case PTYPE_SWAP: + fprintf(stderr, " swap "); + break; + default: + fprintf(stderr, " %c%c%c%c%c ", + pptr->access & + ACCESS_FILE ? (pptr-> + access & + ACCESS_FILEWR + ? 'F' : + 'f') : + '.', + pptr->access & + ACCESS_ROOT ? 'r' : '.', + pptr->access & + ACCESS_CWD ? 'c' : '.', + pptr->access & + ACCESS_EXE ? 'e' : '.', + (pptr->access & + ACCESS_MMAP) + && !(pptr->access & + ACCESS_EXE) ? 'm' : + '.'); + } /* switch */ + } else { + if (pptr->access & ACCESS_ROOT) + putc('r', stderr); + if (pptr->access & ACCESS_CWD) + putc('c', stderr); + if (pptr->access & ACCESS_EXE) + putc('e', stderr); + else if (pptr->access & ACCESS_MMAP) + putc('m', stderr); + } + if (opts & OPT_USER) { + if (pwent == NULL) + fprintf(stderr, " %-8s ", + _("(unknown)")); + else + fprintf(stderr, "(%s)", + pwent->pw_name); + } + if (opts & OPT_VERBOSE) { + if (pptr->command == NULL) + fprintf(stderr, "???\n"); + else + fprintf(stderr, "%s\n", + pptr->command); + } + len = 0; + first = 0; + } + if (opts & OPT_VERBOSE) { + /* put a newline if showing all files and no procs */ + if (nptr->matched_procs == NULL + && (opts & OPT_ALLFILES)) + putc('\n', stderr); + } else { + if (name_has_procs || (opts & OPT_ALLFILES)) + putc('\n', stderr); + } + } /* be silent */ if (opts & OPT_KILL) - kill_matched_proc(nptr->matched_procs, opts, sig_number); + kill_matched_proc(nptr->matched_procs, opts, + sig_number); - } /* next name */ - return (have_match==1?0:1); + } /* next name */ + return (have_match == 1 ? 0 : 1); } @@ -983,17 +1212,19 @@ static struct stat *get_pidstat(const pid_t pid, const char *filename) char pathname[256]; struct stat *st; - if ( (st = malloc(sizeof(struct stat))) == NULL) + if ((st = malloc(sizeof(struct stat))) == NULL) return NULL; snprintf(pathname, 256, "/proc/%d/%s", pid, filename); - if (stat(pathname, st) != 0) + if (stat(pathname, st) != 0) return NULL; else return st; } -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, - struct unixsocket_list *sockets, dev_t netdev) +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, + struct unixsocket_list *sockets, dev_t netdev) { char *dirpath, *filepath; DIR *dirp; @@ -1003,25 +1234,27 @@ static void check_dir(const pid_t pid, const char *dirname, struct device_list * struct unixsocket_list *sock_tmp; struct stat st, lst; - if ( (dirpath = malloc(MAX_PATHNAME)) == NULL) + if ((dirpath = malloc(MAX_PATHNAME)) == NULL) return; - if ( (filepath = malloc(MAX_PATHNAME)) == NULL) + if ((filepath = malloc(MAX_PATHNAME)) == NULL) return; snprintf(dirpath, MAX_PATHNAME, "/proc/%d/%s", pid, dirname); - if ( (dirp = opendir(dirpath)) == NULL) + if ((dirp = opendir(dirpath)) == NULL) return; - while ( (direntry = readdir(dirp)) != NULL) { + while ((direntry = readdir(dirp)) != NULL) { if (direntry->d_name[0] < '0' || direntry->d_name[0] > '9') continue; snprintf(filepath, MAX_PATHNAME, "/proc/%d/%s/%s", - pid, dirname, direntry->d_name); + pid, dirname, direntry->d_name); if (stat(filepath, &st) != 0) { - fprintf(stderr, _("Cannot stat file %s: %s\n"),filepath, strerror(errno)); + fprintf(stderr, _("Cannot stat file %s: %s\n"), + filepath, strerror(errno)); } else { if (st.st_dev == netdev) { - for (sock_tmp = sockets; sock_tmp != NULL; sock_tmp = sock_tmp->next) { + for (sock_tmp = sockets; sock_tmp != NULL; + sock_tmp = sock_tmp->next) { if (sock_tmp->net_inode == st.st_ino) { st.st_ino = sock_tmp->inode; st.st_dev = sock_tmp->dev; @@ -1029,30 +1262,50 @@ static void check_dir(const pid_t pid, const char *dirname, struct device_list * } } } - for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) { + for (dev_tmp = dev_head; dev_tmp != NULL; + dev_tmp = dev_tmp->next) { if (st.st_dev == dev_tmp->device) { - if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) { - add_matched_proc(dev_tmp->name, pid,uid, ACCESS_FILEWR|access); - } else { - add_matched_proc(dev_tmp->name, pid,uid, access); + if (access == ACCESS_FILE + && (lstat(filepath, &lst) == 0) + && (lst.st_mode & S_IWUSR)) { + add_matched_proc(dev_tmp->name, + pid, uid, + ACCESS_FILEWR | + access); + } else { + add_matched_proc(dev_tmp->name, + pid, uid, + access); } } } - for (ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) { - if (st.st_dev == ino_tmp->device && st.st_ino == ino_tmp->inode) { - if (access == ACCESS_FILE && (lstat(filepath, &lst)==0) && (lst.st_mode & S_IWUSR)) { - add_matched_proc(ino_tmp->name, pid,uid, ACCESS_FILEWR|access); + for (ino_tmp = ino_head; ino_tmp != NULL; + ino_tmp = ino_tmp->next) { + if (st.st_dev == ino_tmp->device + && st.st_ino == ino_tmp->inode) { + if (access == ACCESS_FILE + && (lstat(filepath, &lst) == 0) + && (lst.st_mode & S_IWUSR)) { + add_matched_proc(ino_tmp->name, + pid, uid, + ACCESS_FILEWR | + access); } else { - add_matched_proc(ino_tmp->name, pid,uid, access); + add_matched_proc(ino_tmp->name, + pid, uid, + access); } } } } - } /* while fd_dent */ + } /* while fd_dent */ closedir(dirp); } -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) +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) { char pathname[MAX_PATHNAME]; char line[BUFSIZ]; @@ -1064,18 +1317,23 @@ static void check_map(const pid_t pid, const char *filename, struct device_list dev_t tmp_device; snprintf(pathname, MAX_PATHNAME, "/proc/%d/%s", pid, filename); - if ( (fp = fopen(pathname, "r")) == NULL) + if ((fp = fopen(pathname, "r")) == NULL) return; - while (fgets(line,BUFSIZ, fp)) { - if (sscanf(line, "%*s %*s %*s %x:%x %lld", - &tmp_maj, &tmp_min, &tmp_inode) == 3) { + while (fgets(line, BUFSIZ, fp)) { + if (sscanf(line, "%*s %*s %*s %x:%x %lld", + &tmp_maj, &tmp_min, &tmp_inode) == 3) { tmp_device = tmp_maj * 256 + tmp_min; - for(dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) + for (dev_tmp = dev_head; dev_tmp != NULL; + dev_tmp = dev_tmp->next) if (dev_tmp->device == tmp_device) - add_matched_proc(dev_tmp->name, pid, uid, access); - for(ino_tmp = ino_head ; ino_tmp != NULL ; ino_tmp = ino_tmp->next) - if (ino_tmp->device == tmp_device && ino_tmp->inode == tmp_inode) - add_matched_proc(ino_tmp->name, pid, uid, access); + add_matched_proc(dev_tmp->name, pid, + uid, access); + for (ino_tmp = ino_head; ino_tmp != NULL; + ino_tmp = ino_tmp->next) + if (ino_tmp->device == tmp_device + && ino_tmp->inode == tmp_inode) + add_matched_proc(ino_tmp->name, pid, + uid, access); } } fclose(fp); @@ -1086,27 +1344,13 @@ static uid_t getpiduid(const pid_t pid) char pathname[MAX_PATHNAME]; struct stat st; - if (snprintf(pathname, MAX_PATHNAME, "/proc/%d", pid) < 0) + if (snprintf(pathname, MAX_PATHNAME, "/proc/%d", pid) < 0) return 0; if (stat(pathname, &st) != 0) return 0; return st.st_uid; } -void add_mount_device(struct mountdev_list **mount_head,const char *fsname, const char *dir, dev_t device) -{ - struct mountdev_list *newmount; - /*printf("Adding mount Path: %s Dir:%s dev:%0x\n",dir, fsname, device);*/ - - if ( (newmount = malloc(sizeof(struct mountdev_list))) == NULL) - return; - newmount->fsname = strdup(fsname); - newmount->dir = strdup(dir); - newmount->device = device; - newmount->next = *mount_head; - *mount_head = newmount; -} - /* * fill_unix_cache : Create a list of Unix sockets * This list is used later for matching purposes @@ -1119,79 +1363,56 @@ void fill_unix_cache(struct unixsocket_list **unixsocket_head) int scanned_inode; struct stat st; struct unixsocket_list *newsocket; - - if ( (fp = fopen("/proc/net/unix","r")) == NULL) { + + if ((fp = fopen("/proc/net/unix", "r")) == NULL) { fprintf(stderr, _("Cannot open /proc/net/unix: %s\n"), - strerror(errno)); + strerror(errno)); return; } while (fgets(line, BUFSIZ, fp) != NULL) { if (sscanf(line, "%*x: %*x %*x %*x %*x %*d %d %as", - &scanned_inode, - &scanned_path) != 2) + &scanned_inode, &scanned_path) != 2) continue; if (stat(scanned_path, &st) < 0) { free(scanned_path); continue; } - if ( (newsocket = malloc(sizeof(struct unixsocket_list))) == NULL) + if ((newsocket = + malloc(sizeof(struct unixsocket_list))) == NULL) continue; newsocket->sun_name = strdup(scanned_path); newsocket->inode = st.st_ino; newsocket->dev = st.st_dev; - newsocket->net_inode = scanned_inode; + newsocket->net_inode = scanned_inode; newsocket->next = *unixsocket_head; *unixsocket_head = newsocket; - } /* while */ + } /* while */ } -/* - * scan_mount_devices : Create a list of mount points and devices - * This list is used later for matching purposes - */ -void scan_mount_devices(const opt_type opts, struct mountdev_list **mount_devices) -{ - FILE *mntfp; - struct mntent *mnt_ptr; - struct stat st; - - if ( (mntfp = setmntent("/etc/mtab","r")) == NULL) { - fprintf(stderr, _("Cannot open /etc/mtab: %s\n"), - strerror(errno)); - return; - } - while ( (mnt_ptr = getmntent(mntfp)) != NULL) { - if (stat(mnt_ptr->mnt_dir, &st) == 0) { - add_mount_device(mount_devices, mnt_ptr->mnt_fsname, mnt_ptr->mnt_dir, st.st_dev); - } - } -} - #ifdef DEBUG /* often not used, doesnt need translation */ -static void debug_match_lists(struct names *names_head, struct inode_list *ino_head, struct device_list *dev_head) +static void +debug_match_lists(struct names *names_head, struct inode_list *ino_head, + struct device_list *dev_head) { struct names *nptr; struct inode_list *iptr; struct device_list *dptr; - fprintf(stderr,"Specified Names:\n"); - for (nptr=names_head; nptr!= NULL; nptr=nptr->next) - { + fprintf(stderr, "Specified Names:\n"); + for (nptr = names_head; nptr != NULL; nptr = nptr->next) { fprintf(stderr, "\t%s %c\n", nptr->filename, nptr->name_space); } - fprintf(stderr,"\nInodes:\n"); - for (iptr=ino_head; iptr!=NULL; iptr=iptr->next) - { + fprintf(stderr, "\nInodes:\n"); + for (iptr = ino_head; iptr != NULL; iptr = iptr->next) { fprintf(stderr, " Dev:%0lx Inode:(%0ld) 0x%0lx => %s\n", - (unsigned long)iptr->device, (unsigned long)iptr->inode, (unsigned long)iptr->inode, iptr->name->filename); + (unsigned long)iptr->device, (unsigned long)iptr->inode, + (unsigned long)iptr->inode, iptr->name->filename); } - fprintf(stderr,"\nDevices:\n"); - for (dptr=dev_head; dptr!=NULL; dptr=dptr->next) - { - fprintf(stderr, "\tDev:%0lx\n", - (unsigned long)dptr->device); + fprintf(stderr, "\nDevices:\n"); + for (dptr = dev_head; dptr != NULL; dptr = dptr->next) { + fprintf(stderr, "\tDev:%0lx\n", (unsigned long)dptr->device); } } @@ -1205,7 +1426,7 @@ static int ask(const pid_t pid) char *line = NULL; fflush(stdout); - while(1) { + while (1) { fprintf(stderr, _("Kill process %d ? (y/N) "), pid); fflush(stderr); if (getline(&line, &len, stdin) < 0) @@ -1219,75 +1440,173 @@ static int ask(const pid_t pid) free(line); return res; } - } /* while */ + } /* while */ } -static void kill_matched_proc(struct procs *proc_head, const opt_type opts, const int sig_number) +static void +kill_matched_proc(struct procs *proc_head, const opt_type opts, + const int sig_number) { struct procs *pptr; - for (pptr = proc_head ; pptr != NULL ; pptr = pptr->next ) { - if ( (opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0)) + for (pptr = proc_head; pptr != NULL; pptr = pptr->next) { + if ((opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0)) continue; - if ( kill (pptr->pid, sig_number) < 0) { + if (kill(pptr->pid, sig_number) < 0) { fprintf(stderr, _("Could not kill process %d: %s\n"), - pptr->pid, - strerror(errno) - ); + pptr->pid, strerror(errno)); } - + } } static dev_t find_net_dev(void) { - int skt; - struct stat st; - - if ( (skt = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { - fprintf(stderr,_("Cannot open a network socket.\n")); - return -1; - } - if ( fstat(skt, &st) != 0) { - fprintf(stderr,_("Cannot find socket's device number.\n")); - close(skt); - return -1; - } - close(skt); - return st.st_dev; + int skt; + struct stat st; + + if ((skt = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { + fprintf(stderr, _("Cannot open a network socket.\n")); + return -1; + } + if (fstat(skt, &st) != 0) { + fprintf(stderr, _("Cannot find socket's device number.\n")); + close(skt); + return -1; + } + close(skt); + return st.st_dev; } -#ifdef NFS_CHECKS -static void scan_knfsd(struct names *names_head, struct device_list *dev_head) +static void +scan_knfsd(struct names *names_head, struct inode_list *ino_head, + struct device_list *dev_head) { struct device_list *dev_tmp; + struct inode_list *ino_tmp; FILE *fp; char line[BUFSIZ]; - char *find_space; - struct stat st; + char *find_space; + struct stat st; - if ( (fp = fopen(KNFSD_EXPORTS, "r")) == NULL) { + if ((fp = fopen(KNFSD_EXPORTS, "r")) == NULL) { #ifdef DEBUG - printf("Cannot open %s\n", KNFSD_EXPORTS); + printf("Cannot open %s\n", KNFSD_EXPORTS); #endif - return; - } + return; + } while (fgets(line, BUFSIZ, fp) != NULL) { - if (line[0] == '#') { continue; } - if ( (find_space=strpbrk(line," \t")) == NULL) { - continue; - } - *find_space = '\0'; - if ( stat(line, &st) != 0) { - printf("hello %s\n", line); - continue; - } - printf("looking for dev %0x\n", st.st_dev); - /* Scan the devices */ - for (dev_tmp = dev_head ; dev_tmp != NULL ; dev_tmp = dev_tmp->next) { - printf("dev %d\n", dev_tmp->device); - } - - } + if (line[0] == '#') { + continue; + } + if ((find_space = strpbrk(line, " \t")) == NULL) + continue; + *find_space = '\0'; + if (stat(line, &st) != 0) { + continue; + } + /* Scan the devices */ + for (dev_tmp = dev_head; dev_tmp != NULL; + dev_tmp = dev_tmp->next) { + if (st.st_dev == dev_tmp->device) + add_special_proc(dev_tmp->name, PTYPE_KNFSD, 0, + line); + } + for (ino_tmp = ino_head; ino_tmp != NULL; + ino_tmp = ino_tmp->next) { + if (st.st_dev == ino_tmp->device + && st.st_ino == ino_tmp->inode) + add_special_proc(ino_tmp->name, PTYPE_KNFSD, 0, + line); + } + } +} + +static void +scan_mounts(struct names *names_head, struct inode_list *ino_head, + struct device_list *dev_head) +{ + struct device_list *dev_tmp; + struct inode_list *ino_tmp; + FILE *fp; + char line[BUFSIZ]; + char *find_mountp; + char *find_space; + struct stat st; + + if ((fp = fopen(PROC_MOUNTS, "r")) == NULL) { + fprintf(stderr, "Cannot open %s\n", PROC_MOUNTS); + return; + } + while (fgets(line, BUFSIZ, fp) != NULL) { + if ((find_mountp = strchr(line, ' ')) == NULL) + continue; + find_mountp++; + if ((find_space = strchr(find_mountp, ' ')) == NULL) + continue; + *find_space = '\0'; + if (stat(find_mountp, &st) != 0) { + continue; + } + /* Scan the devices */ + for (dev_tmp = dev_head; dev_tmp != NULL; + dev_tmp = dev_tmp->next) { + if (st.st_dev == dev_tmp->device) + add_special_proc(dev_tmp->name, PTYPE_MOUNT, 0, + find_mountp); + } + for (ino_tmp = ino_head; ino_tmp != NULL; + ino_tmp = ino_tmp->next) { + if (st.st_dev == ino_tmp->device + && st.st_ino == ino_tmp->inode) + add_special_proc(ino_tmp->name, PTYPE_MOUNT, 0, + find_mountp); + } + } +} + +static void +scan_swaps(struct names *names_head, struct inode_list *ino_head, + struct device_list *dev_head) +{ + struct device_list *dev_tmp; + struct inode_list *ino_tmp; + FILE *fp; + char line[BUFSIZ]; + char *find_space; + struct stat st; + + if ((fp = fopen(PROC_SWAPS, "r")) == NULL) { + fprintf(stderr, "Cannot open %s\n", PROC_SWAPS); + return; + } + /* lines are filename type */ + while (fgets(line, BUFSIZ, fp) != NULL) { + if ((find_space = strchr(line, ' ')) == NULL) + continue; + *find_space = '\0'; + find_space++; + while (*find_space == ' ') { + find_space++; + if (*find_space == '\0') + continue; + } + if (stat(line, &st) != 0) { + continue; + } + /* Scan the devices */ + for (dev_tmp = dev_head; dev_tmp != NULL; + dev_tmp = dev_tmp->next) { + if (st.st_dev == dev_tmp->device) + add_special_proc(dev_tmp->name, PTYPE_SWAP, 0, + line); + } + for (ino_tmp = ino_head; ino_tmp != NULL; + ino_tmp = ino_tmp->next) { + if (st.st_dev == ino_tmp->device + && st.st_ino == ino_tmp->inode) + add_special_proc(ino_tmp->name, PTYPE_SWAP, 0, + line); + } + } } -#endif /* NFSCHECKS */ diff --git a/src/fuser.h b/src/fuser.h index f15ba7e..25fb96d 100644 --- a/src/fuser.h +++ b/src/fuser.h @@ -11,16 +11,17 @@ typedef unsigned char opt_type; #define OPT_USER 64 #define OPT_MOUNTPOINT 128 - struct procs { pid_t pid; uid_t uid; char access; + char proc_type; char *username; char *command; struct procs *next; }; +/* For the access field above */ #define ACCESS_CWD 1 #define ACCESS_EXE 2 #define ACCESS_FILE 4 @@ -28,6 +29,12 @@ struct procs { #define ACCESS_MMAP 16 #define ACCESS_FILEWR 32 +/* For the proc_type field above */ +#define PTYPE_NORMAL 0 +#define PTYPE_MOUNT 1 +#define PTYPE_KNFSD 2 +#define PTYPE_SWAP 3 + struct names { char *filename; unsigned char name_space; @@ -58,14 +65,6 @@ struct inode_list { struct inode_list *next; }; -struct mountdev_list { - char *fsname; - char *dir; - dev_t device; - struct mountdev_list *next; -}; - - struct device_list { struct names *name; dev_t device; @@ -88,3 +87,5 @@ struct unixsocket_list { #define MAX_CMDNAME 16 #define KNFSD_EXPORTS "/proc/fs/nfs/exports" +#define PROC_MOUNTS "/proc/mounts" +#define PROC_SWAPS "/proc/swaps" diff --git a/src/killall.c b/src/killall.c index 1e5b92a..1c87178 100644 --- a/src/killall.c +++ b/src/killall.c @@ -371,9 +371,21 @@ kill_all (int signal, int names, char **namelist, struct passwd *pwent) continue; } } - else if (got_long ? strcmp (namelist[j], command) : - strncmp (namelist[j], comm, COMM_LEN - 1)) - continue; + else + { + if (ignore_case == 1) + { + if (got_long ? strcasecmp (namelist[j], command) : + strncasecmp (namelist[j], comm, COMM_LEN - 1)) + continue; + } + else + { + if (got_long ? strcmp (namelist[j], command) : + strncmp (namelist[j], comm, COMM_LEN - 1)) + continue; + } + } } else { diff --git a/src/pstree.c b/src/pstree.c index 5fa8bcc..21d6d8b 100644 --- a/src/pstree.c +++ b/src/pstree.c @@ -2,7 +2,7 @@ * pstree.c - display process tree * * Copyright (C) 1993-2002 Werner Almesberger - * Copyright (C) 2002-2008 Craig Small + * Copyright (C) 2002-2009 Craig Small * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -816,25 +816,26 @@ usage (void) " [ -A | -G | -U ] [ PID | USER ]\n" " pstree -V\n" "Display a tree of processes.\n\n" - " -a show command line arguments\n" - " -A use ASCII line drawing characters\n" - " -c don't compact identical subtrees\n" - " -h highlight current process and its ancestors\n" - " -H PID highlight this process and its ancestors\n" - " -G use VT100 line drawing characters\n" - " -l don't truncate long lines\n" - " -n sort output by PID\n" - " -p show PIDs; implies -c\n" - " -u show uid transitions\n" - " -U use UTF-8 (Unicode) line drawing characters\n" - " -V display version information\n")); + " -a, --arguments show command line arguments\n" + " -A, --ascii use ASCII line drawing characters\n" + " -c, --compact don't compact identical subtrees\n" + " -h, --highlight-all highlight current process and its ancestors\n" + " -H PID,\n" + " --highlight-pid=PID highlight this process and its ancestors\n" + " -G, --vt100 use VT100 line drawing characters\n" + " -l, --long don't truncate long lines\n" + " -n, --numeric-sort sort output by PID\n" + " -p, --show-pids show PIDs; implies -c\n" + " -u, --uid-changes show uid transitions\n" + " -U, --unicode use UTF-8 (Unicode) line drawing characters\n" + " -V, --version display version information\n")); #ifdef WITH_SELINUX fprintf (stderr, _( - " -Z show SELinux security contexts\n")); + " -Z show SELinux security contexts\n")); #endif /*WITH_SELINUX*/ fprintf (stderr, _( - " PID start at this PID; default is 1 (init)\n" - " USER show only trees rooted at processes of this user\n\n")); + " PID start at this PID; default is 1 (init)\n" + " USER show only trees rooted at processes of this user\n\n")); exit (1); } @@ -842,7 +843,7 @@ void print_version() { fprintf(stderr, _("pstree (PSmisc) %s\n"), VERSION); fprintf(stderr, _( - "Copyright (C) 1993-2005 Werner Almesberger and Craig Small\n\n")); + "Copyright (C) 1993-2009 Werner Almesberger and Craig Small\n\n")); fprintf(stderr, _( "PSmisc comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it under\n" @@ -862,6 +863,24 @@ main (int argc, char **argv) char *termname; int c; + struct option options[] = { + {"arguments", 0, NULL, 'a'}, + {"ascii", 0, NULL, 'A'}, + {"compact", 0, NULL, 'c'}, + {"vt100", 0, NULL, 'G'}, + {"highlight-all", 0, NULL, 'h'}, + {"highlight-pid", 1, NULL, 'H'}, + {"numeric-sort", 0, NULL, 'n'}, + {"show-pids", 0, NULL, 'p'}, + {"long", 0, NULL, 'l'}, + {"uid-changes", 0, NULL, 'u'}, + {"unicode", 0, NULL, 'U'}, + {"version", 0, NULL, 'V'}, +#ifdef WITH_SELINUX + {"security-context", 0, NULL, 'Z'}, +#endif /*WITH_SELINUX*/ + }; + if (ioctl (1, TIOCGWINSZ, &winsz) >= 0) if (winsz.ws_col) output_width = winsz.ws_col; @@ -904,9 +923,9 @@ main (int argc, char **argv) } #ifdef WITH_SELINUX - while ((c = getopt (argc, argv, "aAcGhH:npluUVZ")) != EOF) + while ((c = getopt_long (argc, argv, "aAcGhH:npluUVZ", options, NULL)) != -1) #else /*WITH_SELINUX*/ - while ((c = getopt (argc, argv, "aAcGhH:npluUV")) != EOF) + while ((c = getopt_long (argc, argv, "aAcGhH:npluUV", options, NULL)) != -1) #endif /*WITH_SELINUX*/ switch (c) { -- 2.40.0