From: Craig Small Date: Mon, 23 Nov 2009 10:20:35 +0000 (+0000) Subject: -M option for fuser X-Git-Tag: v22.11~14 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4998944fe28ea3946af41a0fc66af1622081a7ca;p=psmisc -M option for fuser --- diff --git a/ChangeLog b/ChangeLog index e3818b3..043ad1b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,8 @@ Changes in 22.9 * short option l returned in fuser Debian #539087 * long options terminated with 0s Debian #551833 * fuser only kills normal processes, patch thanks to Erik Li SF# 2892724 + * New fuser -M if you REALLY want mount points, patch thanks to + Jeremie LE HEN SF#2899709 Changes in 22.8 =============== diff --git a/doc/Makefile.am b/doc/Makefile.am index 1185f82..0008ad6 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,4 +1,4 @@ -man_MANS = fuser.1 killall.1 peekfd.1 pstree.1 +man_MANS = fuser.1 killall.1 peekfd.1 prtstat.1 pstree.1 EXTRA_DIST = $(man_MANS) diff --git a/doc/fuser.1 b/doc/fuser.1 index 409f771..4afbccb 100644 --- a/doc/fuser.1 +++ b/doc/fuser.1 @@ -1,4 +1,4 @@ -.TH FUSER 1 2009-07-15 "Linux" "User Commands" +.TH FUSER 1 2009-11-23 "Linux" "User Commands" .SH NAME fuser \- identify processes using files or sockets .SH SYNOPSIS @@ -11,6 +11,7 @@ fuser \- identify processes using files or sockets .IR space\ ] .RB [ \-k .RB [ \-i ] +.RB [ \-M ] .RB [ \- \fISIGNAL ] ] .IR name " ..." @@ -90,6 +91,11 @@ If a directory file is specified, it is automatically changed to \fINAME\fR/. to use any file system that might be mounted on that directory. .TP +\fB\-M\f, \fB\-\-ismountpoint\fR +Request will be fulfilled only if \fINAME\fR specifies a mountpoint. +This is an invaluable seatbelt which prevents you from killing the machine +if \fINAME\fR happens to not be a filesystem. +.TP \fB\-n \fISPACE\fR, \fB\-\-namespace\fR \fISPACE\fR Select a different name space. The name spaces \fBfile\fR (file names, the default), \fBudp\fR (local UDP ports), and \fBtcp\fR (local TCP ports) are diff --git a/doc/prtstat.1 b/doc/prtstat.1 new file mode 100644 index 0000000..e1efad9 --- /dev/null +++ b/doc/prtstat.1 @@ -0,0 +1,37 @@ +.TH PRSTAT 1 2009-11-19 "Linux" "User Commands" +.SH NAME +prstat \- print statistics of a process +.SH SYNOPSIS +.ad l +.B prtstat +.RB [ \-r | \-\-raw ] +.I pid +.br +.B prtstat +.RB \-V | \-\-version +.ad b +.SH DESCRIPTION +.B prtstat +prints the statistics of the specified process. This information comes from +the \fI/proc/PID/stat\fR file. +.SH OPTIONS +.TP +.BR \-r , \-\-raw +Print the information in raw format. +.TP +.BR \-V , \-\-version +Show the version information for \fBprtstat\fR. +.SH OPTIONS +.TP +.BR \-r , \-\-raw +Print the information in raw format. +.TP +.BR \-V , \-\-version +Show the version information for \fBprtstat\fR. +.SH FILES +.nf +/proc//stat source of the information \fBprtstat\fR uses +.fi +.SH AUTHORS +.PP +Craig Small diff --git a/src/fuser.c b/src/fuser.c index 291b657..1823da9 100644 --- a/src/fuser.c +++ b/src/fuser.c @@ -102,7 +102,7 @@ static void usage(const char *errormsg) fprintf(stderr, _ - ("Usage: fuser [ -fuv ] [ -a | -s ] [ -4 | -6 ] [ -c | -m | -n SPACE ] [ -k [ -i ] [ -SIGNAL ]] NAME...\n" + ("Usage: fuser [-fMuv] [-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" @@ -112,6 +112,7 @@ static void usage(const char *errormsg) " -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" + " -M fulfill request only if NAME is a mount point\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" @@ -767,6 +768,56 @@ find_net6_sockets(struct inode_list **ino_list, } #endif +static void +read_proc_mounts(struct mount_list **mnt_list) +{ + FILE *fp; + char line[BUFSIZ]; + char *find_mountp; + char *find_space; + struct mount_list *mnt_tmp; + + 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 ((mnt_tmp = malloc(sizeof(struct mount_list))) == NULL) + continue; + if ((mnt_tmp->mountpoint = strdup(find_mountp)) == NULL) + continue; + mnt_tmp->next = *mnt_list; + *mnt_list = mnt_tmp; + } + fclose(fp); +} + +static int +is_mountpoint(struct mount_list **mnt_list, char *arg) +{ + char *p; + struct mount_list *mnt_tmp; + + if (*arg == '\0') + return 0; + /* Remove trailing slashes. */ + for (p = arg; *p != '\0'; p++) + ; + while (*(--p) == '/' && p > arg) + *p = '\0'; + + for (mnt_tmp = *mnt_list; mnt_tmp != NULL; mnt_tmp = mnt_tmp->next) + if (!strcmp(mnt_tmp->mountpoint, arg)) + return 1; + return 0; +} + int main(int argc, char *argv[]) { opt_type opts; @@ -777,6 +828,7 @@ int main(int argc, char *argv[]) unsigned char default_namespace = NAMESPACE_FILE; struct device_list *match_devices = NULL; struct unixsocket_list *unixsockets = NULL; + struct mount_list *mounts = NULL; dev_t netdev; struct ip_connections *tcp_connection_list = NULL; @@ -798,6 +850,7 @@ int main(int argc, char *argv[]) {"interactive", 0, NULL, 'i'}, {"list-signals", 0, NULL, 'l'}, {"mount", 0, NULL, 'm'}, + {"ismountpoint", 0, NULL, 'M'}, {"namespace", 1, NULL, 'n'}, {"silent", 0, NULL, 's'}, {"user", 0, NULL, 'u'}, @@ -832,9 +885,9 @@ int main(int argc, char *argv[]) ignore_options=0; while ((optc = #ifdef WITH_IPV6 - getopt_long(argc, argv, "46acfhiklmn:sS:uvV", options,NULL) + getopt_long(argc, argv, "46acfhiklmMn:sS:uvV", options,NULL) #else - getopt_long(argc, argv, "acfhikilmn:sS:uvV", options,NULL) + getopt_long(argc, argv, "acfhikilmMn:sS:uvV", options,NULL) #endif ) != -1) { if (ignore_options > 0) { @@ -854,7 +907,7 @@ int main(int argc, char *argv[]) opts |= OPT_ALLFILES; break; case 'c': - opts |= OPT_MOUNTPOINT; + opts |= OPT_MOUNTS; break; case 'f': /* ignored */ @@ -874,6 +927,9 @@ int main(int argc, char *argv[]) case 'm': opts |= OPT_MOUNTS; break; + case 'M': + opts |= OPT_ISMOUNTPOINT; + break; case 'n': if (strcmp(optarg, "tcp") == 0) default_namespace = NAMESPACE_TCP; @@ -933,16 +989,15 @@ int main(int argc, char *argv[]) } /* switch */ } /* while optc */ + if (optc == argc) + usage(_("No process specification given")); + if (opts & OPT_ISMOUNTPOINT) + read_proc_mounts(&mounts); for (optc = optind; optc < argc; optc++) { /* File specifications */ if ((this_name = malloc(sizeof(struct names))) == NULL) continue; this_name->next = NULL; - if (names_head == NULL) - names_head = this_name; - if (names_tail != NULL) - names_tail->next = this_name; - names_tail = this_name; /* try to find namespace spec */ this_name->name_space = default_namespace; if (((nsptr = strchr(argv[optc], '/')) != NULL) @@ -959,10 +1014,15 @@ int main(int argc, char *argv[]) } } this_name->matched_procs = NULL; - if ((opts & OPT_MOUNTS || opts & OPT_MOUNTPOINT) + if (opts & (OPT_MOUNTS|OPT_ISMOUNTPOINT) && this_name->name_space != NAMESPACE_FILE) usage(_ - ("You can only use files with mountpoint option")); + ("You can only use files with mountpoint options")); + if (opts & OPT_ISMOUNTPOINT && + !is_mountpoint(&mounts, argv[optc])) { + free(this_name); + continue; + } switch (this_name->name_space) { case NAMESPACE_TCP: if (asprintf(&(this_name->filename), "%s/tcp", argv[optc]) > 0) { @@ -989,22 +1049,18 @@ int main(int argc, char *argv[]) parse_file(this_name, &match_inodes); parse_unixsockets(this_name, &match_inodes, unixsockets); - if (opts & OPT_MOUNTPOINT || opts & OPT_MOUNTS) + if (opts & OPT_MOUNTS) parse_mounts(this_name, &match_devices, opts); break; } + if (names_head == NULL) + names_head = this_name; + if (names_tail != NULL) + names_tail->next = this_name; + names_tail = this_name; } /* 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")); - } if (opts & OPT_SILENT) { opts &= ~OPT_VERBOSE; opts &= ~OPT_USER; @@ -1451,15 +1507,14 @@ kill_matched_proc(struct procs *proc_head, const opt_type opts, struct procs *pptr; for (pptr = proc_head; pptr != NULL; pptr = pptr->next) { - if ( pptr->proc_type == PTYPE_NORMAL ){ - if ((opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0)) - continue; - if ( kill(pptr->pid, sig_number) < 0) { - fprintf(stderr, _("Could not kill process %d: %s\n"), - pptr->pid, strerror(errno)); - } + if ( pptr->proc_type == PTYPE_NORMAL ) + continue; + if ((opts & OPT_INTERACTIVE) && (ask(pptr->pid) == 0)) + continue; + if ( kill(pptr->pid, sig_number) < 0) { + fprintf(stderr, _("Could not kill process %d: %s\n"), + pptr->pid, strerror(errno)); } - } } diff --git a/src/fuser.h b/src/fuser.h index 25fb96d..91dd426 100644 --- a/src/fuser.h +++ b/src/fuser.h @@ -9,7 +9,7 @@ typedef unsigned char opt_type; #define OPT_INTERACTIVE 16 #define OPT_SILENT 32 #define OPT_USER 64 -#define OPT_MOUNTPOINT 128 +#define OPT_ISMOUNTPOINT 128 struct procs { pid_t pid; @@ -79,6 +79,11 @@ struct unixsocket_list { struct unixsocket_list *next; }; +struct mount_list { + char *mountpoint; + struct mount_list *next; +}; + #define NAMESPACE_FILE 0 #define NAMESPACE_TCP 1 #define NAMESPACE_UDP 2 diff --git a/src/prtstat.c b/src/prtstat.c index ac7933c..92a1fb3 100644 --- a/src/prtstat.c +++ b/src/prtstat.c @@ -214,6 +214,9 @@ static void print_stat(const int pid, const opt_type options) char *bptr; FILE *fp; + struct proc_statnames psn[] = { + {"d", "blah", (union proc_values)3} + }; struct proc_info *pr; pr = malloc(sizeof(struct proc_info)); @@ -285,7 +288,8 @@ int main(int argc, char *argv[]) struct option options[] = { {"raw" ,0, NULL, 'r' }, - {"version", 0, NULL, 'V'} + {"version", 0, NULL, 'V'}, + { 0, 0, 0, 0} }; #ifdef ENABLE_NLS diff --git a/src/prtstat.h b/src/prtstat.h index 973c459..f3f93e1 100644 --- a/src/prtstat.h +++ b/src/prtstat.h @@ -18,3 +18,19 @@ struct proc_info itrealvalue, rss, cguest_time; unsigned long long starttime, blkio; }; + +union proc_values { + int d; + char c; + long x; + unsigned long lu; + long ld; + unsigned long long lX; +}; + + +struct proc_statnames { + char fmt[3]; + char *name; + union proc_values value; +};