Author: rwatson
Date: Sun Aug 14 00:42:09 2011
New Revision: 224859
URL: http://svn.freebsd.org/changeset/base/224859

Log:
  Updates to libprocstat(3) and procstat(1) to allow monitoring Capsicum
  capability mode and capabilities.
  
  Right now no attempt is made to unwrap capabilities when operating on
  a crashdump, so further refinement is required.
  
  Approved by:  re (bz)
  Sponsored by: Google Inc

Modified:
  head/lib/libprocstat/libprocstat.c
  head/lib/libprocstat/libprocstat.h
  head/usr.bin/procstat/procstat.1
  head/usr.bin/procstat/procstat.c
  head/usr.bin/procstat/procstat.h
  head/usr.bin/procstat/procstat_cred.c
  head/usr.bin/procstat/procstat_files.c

Modified: head/lib/libprocstat/libprocstat.c
==============================================================================
--- head/lib/libprocstat/libprocstat.c  Sun Aug 14 00:32:43 2011        
(r224858)
+++ head/lib/libprocstat/libprocstat.c  Sun Aug 14 00:42:09 2011        
(r224859)
@@ -282,7 +282,7 @@ procstat_freefiles(struct procstat *proc
 
 static struct filestat *
 filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags,
-    int refcount, off_t offset, char *path)
+    int refcount, off_t offset, char *path, cap_rights_t cap_rights)
 {
        struct filestat *entry;
 
@@ -299,6 +299,7 @@ filestat_new_entry(void *typedep, int ty
        entry->fs_ref_count = refcount;
        entry->fs_offset = offset;
        entry->fs_path = path;
+       entry->fs_cap_rights = cap_rights;
        return (entry);
 }
 
@@ -381,21 +382,21 @@ procstat_getfiles_kvm(struct procstat *p
        /* root directory vnode, if one. */
        if (filed.fd_rdir) {
                entry = filestat_new_entry(filed.fd_rdir, PS_FST_TYPE_VNODE, -1,
-                   PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL);
+                   PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL, 0);
                if (entry != NULL)
                        STAILQ_INSERT_TAIL(head, entry, next);
        }
        /* current working directory vnode. */
        if (filed.fd_cdir) {
                entry = filestat_new_entry(filed.fd_cdir, PS_FST_TYPE_VNODE, -1,
-                   PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL);
+                   PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL, 0);
                if (entry != NULL)
                        STAILQ_INSERT_TAIL(head, entry, next);
        }
        /* jail root, if any. */
        if (filed.fd_jdir) {
                entry = filestat_new_entry(filed.fd_jdir, PS_FST_TYPE_VNODE, -1,
-                   PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL);
+                   PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL, 0);
                if (entry != NULL)
                        STAILQ_INSERT_TAIL(head, entry, next);
        }
@@ -403,14 +404,14 @@ procstat_getfiles_kvm(struct procstat *p
        if (kp->ki_tracep) {
                entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, -1,
                    PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
-                   PS_FST_UFLAG_TRACE, 0, 0, NULL);
+                   PS_FST_UFLAG_TRACE, 0, 0, NULL, 0);
                if (entry != NULL)
                        STAILQ_INSERT_TAIL(head, entry, next);
        }
        /* text vnode, if one */
        if (kp->ki_textvp) {
                entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, -1,
-                   PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL);
+                   PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL, 0);
                if (entry != NULL)
                        STAILQ_INSERT_TAIL(head, entry, next);
        }
@@ -418,7 +419,7 @@ procstat_getfiles_kvm(struct procstat *p
        if ((vp = getctty(kd, kp)) != NULL) {
                entry = filestat_new_entry(vp, PS_FST_TYPE_VNODE, -1,
                    PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
-                   PS_FST_UFLAG_CTTY, 0, 0, NULL);
+                   PS_FST_UFLAG_CTTY, 0, 0, NULL, 0);
                if (entry != NULL)
                        STAILQ_INSERT_TAIL(head, entry, next);
        }
@@ -471,8 +472,9 @@ procstat_getfiles_kvm(struct procstat *p
                default:
                        continue;
                }
+               /* XXXRW: No capability rights support for kvm yet. */
                entry = filestat_new_entry(data, type, i,
-                   to_filestat_flags(file.f_flag), 0, 0, 0, NULL);
+                   to_filestat_flags(file.f_flag), 0, 0, 0, NULL, 0);
                if (entry != NULL)
                        STAILQ_INSERT_TAIL(head, entry, next);
        }
@@ -531,7 +533,7 @@ do_mmapped:
                         */
                        entry = filestat_new_entry(object.handle,
                            PS_FST_TYPE_VNODE, -1, fflags,
-                           PS_FST_UFLAG_MMAP, 0, 0, NULL);
+                           PS_FST_UFLAG_MMAP, 0, 0, NULL, 0);
                        if (entry != NULL)
                                STAILQ_INSERT_TAIL(head, entry, next);
                }
@@ -586,6 +588,7 @@ kinfo_fflags2fst(int kfflags)
        } kfflags2fst[] = {
                { KF_FLAG_APPEND, PS_FST_FFLAG_APPEND },
                { KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC },
+               { KF_FLAG_CAPABILITY, PS_FST_FFLAG_CAPABILITY },
                { KF_FLAG_CREAT, PS_FST_FFLAG_CREAT },
                { KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT },
                { KF_FLAG_EXCL, PS_FST_FFLAG_EXCL },
@@ -644,6 +647,7 @@ procstat_getfiles_sysctl(struct procstat
        int cnt, fd, fflags;
        int i, type, uflags;
        int refcount;
+       cap_rights_t cap_rights;
 
        assert(kp);
        if (kp->ki_fd == NULL)
@@ -676,12 +680,13 @@ procstat_getfiles_sysctl(struct procstat
                        path = strdup(kif->kf_path);
                else
                        path = NULL;
+               cap_rights = kif->kf_cap_rights;
 
                /*
                 * Create filestat entry.
                 */
                entry = filestat_new_entry(kif, type, fd, fflags, uflags,
-                   refcount, offset, path);
+                   refcount, offset, path, cap_rights);
                if (entry != NULL)
                        STAILQ_INSERT_TAIL(head, entry, next);
        }
@@ -707,7 +712,8 @@ procstat_getfiles_sysctl(struct procstat
                        else
                                path = NULL;
                        entry = filestat_new_entry(kve, PS_FST_TYPE_VNODE, -1,
-                           fflags, PS_FST_UFLAG_MMAP, refcount, offset, path);
+                           fflags, PS_FST_UFLAG_MMAP, refcount, offset, path,
+                           0);
                        if (entry != NULL)
                                STAILQ_INSERT_TAIL(head, entry, next);
                }

Modified: head/lib/libprocstat/libprocstat.h
==============================================================================
--- head/lib/libprocstat/libprocstat.h  Sun Aug 14 00:32:43 2011        
(r224858)
+++ head/lib/libprocstat/libprocstat.h  Sun Aug 14 00:42:09 2011        
(r224859)
@@ -88,6 +88,7 @@
 #define        PS_FST_FFLAG_DIRECT     0x1000
 #define        PS_FST_FFLAG_EXEC       0x2000
 #define        PS_FST_FFLAG_HASLOCK    0x4000
+#define        PS_FST_FFLAG_CAPABILITY 0x8000
 
 struct procstat;
 struct filestat {
@@ -101,6 +102,7 @@ struct filestat {
        void    *fs_typedep;    /* Type dependent data. */
        char    *fs_path;
        STAILQ_ENTRY(filestat)  next;
+       cap_rights_t    fs_cap_rights;  /* Capability rights, if flag set. */
 };
 struct vnstat {
        uint64_t        vn_fileid;

Modified: head/usr.bin/procstat/procstat.1
==============================================================================
--- head/usr.bin/procstat/procstat.1    Sun Aug 14 00:32:43 2011        
(r224858)
+++ head/usr.bin/procstat/procstat.1    Sun Aug 14 00:42:09 2011        
(r224859)
@@ -1,5 +1,5 @@
 .\"-
-.\" Copyright (c) 2007-2008 Robert N. M. Watson
+.\" Copyright (c) 2007-2009 Robert N. M. Watson
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 7, 2010
+.Dd August 14, 2011
 .Dt PROCSTAT 1
 .Os
 .Sh NAME
@@ -35,6 +35,7 @@
 .Nm
 .Op Fl h
 .Op Fl n
+.Op Fl C
 .Op Fl w Ar interval
 .Op Fl b | c | f | i | j | k | s | t | v
 .Op Fl a | Ar pid ...
@@ -88,6 +89,11 @@ If the
 .Fl w
 flag is not specified, the output will not repeat.
 .Pp
+The
+.Fl C
+flag requests the printing of additional capability information in the file
+descriptor view.
+.Pp
 Some information, such as VM and file descriptor information, is available
 only to the owner of a process or the superuser.
 .Ss Binary Information
@@ -116,7 +122,8 @@ command line arguments (if available)
 Display detailed information about each file descriptor referenced by a
 process, including the process ID, command, file descriptor number, and
 per-file descriptor object information, such as object type and file system
-path:
+path.
+By default, the following information will be printed:
 .Pp
 .Bl -tag -width indent -compact
 .It PID
@@ -208,7 +215,17 @@ non-blocking
 direct I/O
 .It l
 lock held
+.It c
+descriptor is a capability
 .El
+.Pp
+If the
+.Fl C
+flag is specified, the vnode type, reference count, and offset fields will be
+omitted, and a new capabilities field will be included listing capabilities,
+as described in
+.Xr cap_new 2 ,
+present for each capability descriptor.
 .Ss Signal Disposition Information
 Display signal pending and disposition for a process:
 .Pp
@@ -306,9 +323,18 @@ effective group ID
 real group ID
 .It SVGID
 saved group ID
+.It FLAGS
+credential flags
 .It GROUPS
 group set
 .El
+.Pp
+The following credential flags may be displayed:
+.Pp
+.Bl -tag -width X -compact
+.It C
+capability mode
+.El
 .Ss Thread Information
 Display per-thread information, including process ID, per-thread ID, name,
 CPU, and execution state:
@@ -402,6 +428,8 @@ needs copy
 .Xr fstat 1 ,
 .Xr ps 1 ,
 .Xr sockstat 1 ,
+.Xr cap_enter 2 ,
+.Xr cap_new 2 ,
 .Xr ddb 4 ,
 .Xr stack 9
 .Sh AUTHORS

Modified: head/usr.bin/procstat/procstat.c
==============================================================================
--- head/usr.bin/procstat/procstat.c    Sun Aug 14 00:32:43 2011        
(r224858)
+++ head/usr.bin/procstat/procstat.c    Sun Aug 14 00:42:09 2011        
(r224859)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2007, 2011 Robert N. M. Watson
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,13 +40,13 @@
 #include "procstat.h"
 
 static int aflag, bflag, cflag, fflag, iflag, jflag, kflag, sflag, tflag, 
vflag;
-int    hflag, nflag;
+int    hflag, nflag, Cflag;
 
 static void
 usage(void)
 {
 
-       fprintf(stderr, "usage: procstat [-h] [-M core] [-N system] "
+       fprintf(stderr, "usage: procstat [-h] [-C] [-M core] [-N system] "
            "[-w interval] [-b | -c | -f | -i | -j | -k | -s | -t | -v]\n");
        fprintf(stderr, "                [-a | pid ...]\n");
        exit(EX_USAGE);
@@ -117,8 +117,12 @@ main(int argc, char *argv[])
 
        interval = 0;
        memf = nlistf = NULL;
-       while ((ch = getopt(argc, argv, "N:M:abcfijkhstvw:")) != -1) {
+       while ((ch = getopt(argc, argv, "CN:M:abcfijkhstvw:")) != -1) {
                switch (ch) {
+               case 'C':
+                       Cflag++;
+                       break;
+
                case 'M':
                        memf = optarg;
                        break;
@@ -204,6 +208,10 @@ main(int argc, char *argv[])
        if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0))
                usage();
 
+       /* Only allow -C with -f. */
+       if (Cflag && !fflag)
+               usage();
+
        if (memf != NULL)
                prstat = procstat_open_kvm(nlistf, memf);
        else

Modified: head/usr.bin/procstat/procstat.h
==============================================================================
--- head/usr.bin/procstat/procstat.h    Sun Aug 14 00:32:43 2011        
(r224858)
+++ head/usr.bin/procstat/procstat.h    Sun Aug 14 00:42:09 2011        
(r224859)
@@ -29,7 +29,7 @@
 #ifndef PROCSTAT_H
 #define        PROCSTAT_H
 
-extern int     hflag, nflag;
+extern int     hflag, nflag, Cflag;
 
 struct kinfo_proc;
 void   kinfo_proc_sort(struct kinfo_proc *kipp, int count);

Modified: head/usr.bin/procstat/procstat_cred.c
==============================================================================
--- head/usr.bin/procstat/procstat_cred.c       Sun Aug 14 00:32:43 2011        
(r224858)
+++ head/usr.bin/procstat/procstat_cred.c       Sun Aug 14 00:42:09 2011        
(r224859)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2007-2008 Robert N. M. Watson
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -48,9 +48,9 @@ procstat_cred(struct kinfo_proc *kipp)
        gid_t *groups = NULL;
 
        if (!hflag)
-               printf("%5s %-16s %5s %5s %5s %5s %5s %5s %-20s\n", "PID",
+               printf("%5s %-16s %5s %5s %5s %5s %5s %5s %5s %-15s\n", "PID",
                    "COMM", "EUID", "RUID", "SVUID", "EGID", "RGID", "SVGID",
-                   "GROUPS");
+                   "FLAGS", "GROUPS");
 
        printf("%5d ", kipp->ki_pid);
        printf("%-16s ", kipp->ki_comm);
@@ -60,6 +60,8 @@ procstat_cred(struct kinfo_proc *kipp)
        printf("%5d ", kipp->ki_groups[0]);
        printf("%5d ", kipp->ki_rgid);
        printf("%5d ", kipp->ki_svgid);
+       printf("%s", kipp->ki_cr_flags & CRED_FLAG_CAPMODE ? "C" : "-");
+       printf("     ");
 
        /*
         * We may have too many groups to fit in kinfo_proc's statically

Modified: head/usr.bin/procstat/procstat_files.c
==============================================================================
--- head/usr.bin/procstat/procstat_files.c      Sun Aug 14 00:32:43 2011        
(r224858)
+++ head/usr.bin/procstat/procstat_files.c      Sun Aug 14 00:42:09 2011        
(r224859)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2007-2011 Robert N. M. Watson
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -27,6 +27,7 @@
  */
 
 #include <sys/param.h>
+#include <sys/capability.h>
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 #include <sys/un.h>
@@ -131,6 +132,133 @@ print_address(struct sockaddr_storage *s
        printf("%s", addr);
 }
 
+static struct cap_desc {
+       cap_rights_t     cd_right;
+       const char      *cd_desc;
+} cap_desc[] = {
+       /* General file I/O. */
+       { CAP_READ,             "rd" },
+       { CAP_WRITE,            "wr" },
+       { CAP_MMAP,             "mm" },
+       { CAP_MAPEXEC,          "me" },
+       { CAP_FEXECVE,          "fe" },
+       { CAP_FSYNC,            "fy" },
+       { CAP_FTRUNCATE,        "ft" },
+       { CAP_SEEK,             "se" },
+
+       /* VFS methods. */
+       { CAP_FCHFLAGS,         "cf" },
+       { CAP_FCHDIR,           "cd" },
+       { CAP_FCHMOD,           "cm" },
+       { CAP_FCHOWN,           "cn" },
+       { CAP_FCNTL,            "fc" },
+       { CAP_FPATHCONF,        "fp" },
+       { CAP_FLOCK,            "fl" },
+       { CAP_FSCK,             "fk" },
+       { CAP_FSTAT,            "fs" },
+       { CAP_FSTATFS,          "sf" },
+       { CAP_FUTIMES,          "fu" },
+       { CAP_CREATE,           "cr" },
+       { CAP_DELETE,           "de" },
+       { CAP_MKDIR,            "md" },
+       { CAP_RMDIR,            "rm" },
+       { CAP_MKFIFO,           "mf" },
+
+       /* Lookups - used to constraint *at() calls. */
+       { CAP_LOOKUP,           "lo" },
+
+       /* Extended attributes. */
+       { CAP_EXTATTR_GET,      "eg" },
+       { CAP_EXTATTR_SET,      "es" },
+       { CAP_EXTATTR_DELETE,   "ed" },
+       { CAP_EXTATTR_LIST,     "el" },
+
+       /* Access Control Lists. */
+       { CAP_ACL_GET,          "ag" },
+       { CAP_ACL_SET,          "as" },
+       { CAP_ACL_DELETE,       "ad" },
+       { CAP_ACL_CHECK,        "ac" },
+
+       /* Socket operations. */
+       { CAP_ACCEPT,           "at" },
+       { CAP_BIND,             "bd" },
+       { CAP_CONNECT,          "co" },
+       { CAP_GETPEERNAME,      "pn" },
+       { CAP_GETSOCKNAME,      "sn" },
+       { CAP_GETSOCKOPT,       "gs" },
+       { CAP_LISTEN,           "ln" },
+       { CAP_PEELOFF,          "pf" },
+       { CAP_SETSOCKOPT,       "ss" },
+       { CAP_SHUTDOWN,         "sh" },
+
+       /* Mandatory Access Control. */
+       { CAP_MAC_GET,          "mg" },
+       { CAP_MAC_SET,          "ms" },
+
+       /* Methods on semaphores. */
+       { CAP_SEM_GETVALUE,     "sg" },
+       { CAP_SEM_POST,         "sp" },
+       { CAP_SEM_WAIT,         "sw" },
+
+       /* Event monitoring and posting. */
+       { CAP_POLL_EVENT,       "po" },
+       { CAP_POST_EVENT,       "ev" },
+
+       /* Strange and powerful rights that should not be given lightly. */
+       { CAP_IOCTL,            "io" },
+       { CAP_TTYHOOK,          "ty" },
+
+#ifdef NOTYET
+       { CAP_PDGETPID,         "pg" },
+       { CAP_PDWAIT4,          "pw" },
+       { CAP_PDKILL,           "pk" },
+#endif
+};
+static const u_int     cap_desc_count = sizeof(cap_desc) /
+                           sizeof(cap_desc[0]);
+
+static u_int
+width_capability(cap_rights_t rights)
+{
+       u_int count, i, width;
+
+       count = 0;
+       width = 0;
+       for (i = 0; i < cap_desc_count; i++) {
+               if (rights & cap_desc[i].cd_right) {
+                       width += strlen(cap_desc[i].cd_desc);
+                       if (count)
+                               width++;
+                       count++;
+               }
+       }
+       return (width);
+}
+
+static void
+print_capability(cap_rights_t rights, u_int capwidth)
+{
+       u_int count, i, width;
+
+       count = 0;
+       width = 0;
+       for (i = width_capability(rights); i < capwidth; i++) {
+               if (rights || i != 0)
+                       printf(" ");
+               else
+                       printf("-");
+       }
+       for (i = 0; i < cap_desc_count; i++) {
+               if (rights & cap_desc[i].cd_right) {
+                       printf("%s%s", count ? "," : "", cap_desc[i].cd_desc);
+                       width += strlen(cap_desc[i].cd_desc);
+                       if (count)
+                               width++;
+                       count++;
+               }
+       }
+}
+
 void
 procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
 { 
@@ -139,14 +267,39 @@ procstat_files(struct procstat *procstat
        struct filestat *fst;
        const char *str;
        struct vnstat vn;
+       u_int capwidth, width;
        int error;
 
-       if (!hflag)
-               printf("%5s %-16s %4s %1s %1s %-8s %3s %7s %-3s %-12s\n",
-                   "PID", "COMM", "FD", "T", "V", "FLAGS", "REF", "OFFSET",
-                   "PRO", "NAME");
-
+       /*
+        * To print the header in capability mode, we need to know the width
+        * of the widest capability string.  Even if we get no processes
+        * back, we will print the header, so we defer aborting due to a lack
+        * of processes until after the header logic.
+        */
+       capwidth = 0;
        head = procstat_getfiles(procstat, kipp, 0);
+       if (head != NULL && Cflag) {
+               STAILQ_FOREACH(fst, head, next) {
+                       width = width_capability(fst->fs_cap_rights);
+                       if (width > capwidth)
+                               capwidth = width;
+               }
+               if (capwidth < strlen("CAPABILITIES"))
+                       capwidth = strlen("CAPABILITIES");
+       }
+
+       if (!hflag) {
+               if (Cflag)
+                       printf("%5s %-16s %4s %1s %-9s %-*s "
+                           "%-3s %-12s\n", "PID", "COMM", "FD", "T",
+                           "FLAGS", capwidth, "CAPABILITIES", "PRO",
+                           "NAME");
+               else
+                       printf("%5s %-16s %4s %1s %1s %-9s "
+                           "%3s %7s %-3s %-12s\n", "PID", "COMM", "FD", "T",
+                           "V", "FLAGS", "REF", "OFFSET", "PRO", "NAME");
+       }
+
        if (head == NULL)
                return;
        STAILQ_FOREACH(fst, head, next) {
@@ -215,50 +368,53 @@ procstat_files(struct procstat *procstat
                        break;
                }
                printf("%1s ", str);
-               str = "-";
-               if (fst->fs_type == PS_FST_TYPE_VNODE) {
-                       error = procstat_get_vnode_info(procstat, fst, &vn, 
NULL);
-                       switch (vn.vn_type) {
-                       case PS_FST_VTYPE_VREG:
-                               str = "r";
-                               break;
-
-                       case PS_FST_VTYPE_VDIR:
-                               str = "d";
-                               break;
-
-                       case PS_FST_VTYPE_VBLK:
-                               str = "b";
-                               break;
-
-                       case PS_FST_VTYPE_VCHR:
-                               str = "c";
-                               break;
-
-                       case PS_FST_VTYPE_VLNK:
-                               str = "l";
-                               break;
-
-                       case PS_FST_VTYPE_VSOCK:
-                               str = "s";
-                               break;
-
-                       case PS_FST_VTYPE_VFIFO:
-                               str = "f";
-                               break;
-
-                       case PS_FST_VTYPE_VBAD:
-                               str = "x";
-                               break;
-
-                       case PS_FST_VTYPE_VNON:
-                       case PS_FST_VTYPE_UNKNOWN:
-                       default:
-                               str = "?";
-                               break;
+               if (!Cflag) {
+                       str = "-";
+                       if (fst->fs_type == PS_FST_TYPE_VNODE) {
+                               error = procstat_get_vnode_info(procstat, fst,
+                                   &vn, NULL);
+                               switch (vn.vn_type) {
+                               case PS_FST_VTYPE_VREG:
+                                       str = "r";
+                                       break;
+
+                               case PS_FST_VTYPE_VDIR:
+                                       str = "d";
+                                       break;
+
+                               case PS_FST_VTYPE_VBLK:
+                                       str = "b";
+                                       break;
+
+                               case PS_FST_VTYPE_VCHR:
+                                       str = "c";
+                                       break;
+
+                               case PS_FST_VTYPE_VLNK:
+                                       str = "l";
+                                       break;
+
+                               case PS_FST_VTYPE_VSOCK:
+                                       str = "s";
+                                       break;
+
+                               case PS_FST_VTYPE_VFIFO:
+                                       str = "f";
+                                       break;
+
+                               case PS_FST_VTYPE_VBAD:
+                                       str = "x";
+                                       break;
+
+                               case PS_FST_VTYPE_VNON:
+                               case PS_FST_VTYPE_UNKNOWN:
+                               default:
+                                       str = "?";
+                                       break;
+                               }
                        }
+                       printf("%1s ", str);
                }
-               printf("%1s ", str);
                printf("%s", fst->fs_fflags & PS_FST_FFLAG_READ ? "r" : "-");
                printf("%s", fst->fs_fflags & PS_FST_FFLAG_WRITE ? "w" : "-");
                printf("%s", fst->fs_fflags & PS_FST_FFLAG_APPEND ? "a" : "-");
@@ -266,16 +422,23 @@ procstat_files(struct procstat *procstat
                printf("%s", fst->fs_fflags & PS_FST_FFLAG_SYNC ? "f" : "-");
                printf("%s", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ? "n" : 
"-");
                printf("%s", fst->fs_fflags & PS_FST_FFLAG_DIRECT ? "d" : "-");
-               printf("%s ", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ? "l" : 
"-");
-               if (fst->fs_ref_count > -1)
-                       printf("%3d ", fst->fs_ref_count);
-               else
-                       printf("%3c ", '-');
-               if (fst->fs_offset > -1)
-                       printf("%7jd ", (intmax_t)fst->fs_offset);
-               else
-                       printf("%7c ", '-');
-
+               printf("%s", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ? "l" : "-");
+               printf("%s ", fst->fs_fflags & PS_FST_FFLAG_CAPABILITY ?
+                   "c" : "-");
+               if (!Cflag) {
+                       if (fst->fs_ref_count > -1)
+                               printf("%3d ", fst->fs_ref_count);
+                       else
+                               printf("%3c ", '-');
+                       if (fst->fs_offset > -1)
+                               printf("%7jd ", (intmax_t)fst->fs_offset);
+                       else
+                               printf("%7c ", '-');
+               }
+               if (Cflag) {
+                       print_capability(fst->fs_cap_rights, capwidth);
+                       printf(" ");
+               }
                switch (fst->fs_type) {
                case PS_FST_TYPE_VNODE:
                case PS_FST_TYPE_FIFO:
@@ -314,7 +477,6 @@ procstat_files(struct procstat *procstat
                        break;
 
                default:
-                       printf("%-3s ", "-");
                        printf("%-18s", "-");
                }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to