]> granicus.if.org Git - psmisc/commitdiff
-M option for fuser
authorCraig Small <csmall@users.sourceforge.net>
Mon, 23 Nov 2009 10:20:35 +0000 (10:20 +0000)
committerCraig Small <csmall@users.sourceforge.net>
Mon, 23 Nov 2009 10:20:35 +0000 (10:20 +0000)
ChangeLog
doc/Makefile.am
doc/fuser.1
doc/prtstat.1 [new file with mode: 0644]
src/fuser.c
src/fuser.h
src/prtstat.c
src/prtstat.h

index e3818b3d5b41fc9fe84adc053ace5045327a3523..043ad1b86c331cd1efab90d1f261e11ad13ed07f 100644 (file)
--- 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
 ===============
index 1185f8226dc3461a72ca46a746f931d702854e6a..0008ad669230ce584d5e90520f60614aca163756 100644 (file)
@@ -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)
index 409f771e86f41461917139f360b9a22058f03eb9..4afbccb31d434b593430af781f0151fcf656d9f8 100644 (file)
@@ -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 (file)
index 0000000..e1efad9
--- /dev/null
@@ -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/<PID>/stat source of the information \fBprtstat\fR uses
+.fi
+.SH AUTHORS
+.PP
+Craig Small <csmall@enc.com.au>
index 291b657c2ae5779186016c4434a8419196aecb02..1823da9e618ab4755616eedd9f21850ed078a062 100644 (file)
@@ -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));
                }
-
        }
 }
 
index 25fb96d8bfce37161f126fb880743e1a9c43bf98..91dd426a969cbbcd31098585b930689df0ecf821 100644 (file)
@@ -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
index ac7933cb5d6359ebafbb5f2c09c9a1ba2437d1d1..92a1fb338cc4bf5b438913e5454400fc2e393770 100644 (file)
@@ -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
index 973c4590112cd4f50b1b91c08eb6c7ebbbfee7a5..f3f93e1dc291010ea1779f4c5b82ecd01cbea942 100644 (file)
@@ -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;
+};