Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 21 Jan 2009 11:58:46 GMT
From:      Robert Watson <rwatson@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 156463 for review
Message-ID:  <200901211158.n0LBwkLY084290@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=156463

Change 156463 by rwatson@rwatson_freebsd_capabilities on 2009/01/21 11:58:03

	Teach procstat(1) how to print out, when an optional -C flag is
	specified, the capability mask associated with a file descriptor.

Affected files ...

.. //depot/projects/trustedbsd/capabilities/src/usr.bin/procstat/procstat.1#6 edit
.. //depot/projects/trustedbsd/capabilities/src/usr.bin/procstat/procstat.c#4 edit
.. //depot/projects/trustedbsd/capabilities/src/usr.bin/procstat/procstat.h#2 edit
.. //depot/projects/trustedbsd/capabilities/src/usr.bin/procstat/procstat_files.c#12 edit

Differences ...

==== //depot/projects/trustedbsd/capabilities/src/usr.bin/procstat/procstat.1#6 (text+ko) ====

@@ -33,7 +33,7 @@
 .Nd get detailed process information
 .Sh SYNOPSIS
 .Nm
-.Op Fl h
+.Op Fl hC
 .Op Fl w Ar interval
 .Op Fl b | c | f | k | s | t | v
 .Op Fl a | Ar pid ...
@@ -83,6 +83,11 @@
 .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
@@ -111,7 +116,8 @@
 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
@@ -203,7 +209,17 @@
 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 Kernel Thread Stacks
 Display kernel thread stacks for a process, allowing further interpretation
 of thread wait channels.
@@ -345,6 +361,7 @@
 .Xr fstat 1 ,
 .Xr ps 1 ,
 .Xr sockstat 1 ,
+.Xr cap_new 2 ,
 .Xr ddb 4 ,
 .Xr stack 9
 .Sh AUTHORS

==== //depot/projects/trustedbsd/capabilities/src/usr.bin/procstat/procstat.c#4 (text+ko) ====

@@ -39,14 +39,14 @@
 #include "procstat.h"
 
 static int aflag, bflag, cflag, fflag, kflag, sflag, tflag, vflag;
-int	hflag;
+int	hflag, Cflag;
 
 static void
 usage(void)
 {
 
-	fprintf(stderr, "usage: procstat [-h] [-w interval] [-b | -c | -f | "
-	    "-k | -s | -t | -v]\n");
+	fprintf(stderr, "usage: procstat [-hC] [-w interval] [-b | -c | -f "
+	    " | -k | -s | -t | -v]\n");
 	fprintf(stderr, "                [-a | pid ...]\n");
 	exit(EX_USAGE);
 }
@@ -109,7 +109,7 @@
 	char *dummy;
 
 	interval = 0;
-	while ((ch = getopt(argc, argv, "abcfkhstvw:")) != -1) {
+	while ((ch = getopt(argc, argv, "abcfkhstvw:C")) != -1) {
 		switch (ch) {
 		case 'a':
 			aflag++;
@@ -156,6 +156,10 @@
 			interval = l;
 			break;
 
+		case 'C':
+			Cflag++;
+			break;
+
 		case '?':
 		default:
 			usage();
@@ -178,6 +182,10 @@
 	if (!(aflag == 1 && argc == 0) && !(aflag == 0 && argc > 0))
 		usage();
 
+	/* Only allow -C with -f. */
+	if (Cflag && !fflag)
+		usage();
+
 	do {
 		if (aflag) {
 			name[0] = CTL_KERN;

==== //depot/projects/trustedbsd/capabilities/src/usr.bin/procstat/procstat.h#2 (text+ko) ====

@@ -29,7 +29,7 @@
 #ifndef PROCSTAT_H
 #define	PROCSTAT_H
 
-extern int	hflag;
+extern int	hflag, Cflag;
 
 struct kinfo_proc;
 void	kinfo_proc_sort(struct kinfo_proc *kipp, int count);

==== //depot/projects/trustedbsd/capabilities/src/usr.bin/procstat/procstat_files.c#12 (text+ko) ====

@@ -132,7 +132,6 @@
 	printf("%s", addr);
 }
 
-#if notyet
 static struct cap_desc {
 	cap_rights_t	 cd_right;
 	const char	*cd_desc;
@@ -184,42 +183,96 @@
 	{ CAP_PDWAIT,		"pw" },
 	{ CAP_PDKILL,		"pk" },
 };
-static const int	cap_desc_count = sizeof(cap_desc) /
+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)
+print_capability(cap_rights_t rights, u_int capwidth)
 {
-	int count, i;
+	u_int count, i, width;
 
 	count = 0;
+	width = 0;
+	for (i = width_capability(rights); i < capwidth; i++) {
+		if (rights || i != (capwidth - 1))
+			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++;
 		}
 	}
 }
-#endif
 
 void
 procstat_files(pid_t pid, struct kinfo_proc *kipp)
 {
 	struct kinfo_file *freep, *kif;
+	u_int capwidth, width;
 	int i, cnt;
 	const char *str;
 
-	if (!hflag)
-		printf("%5s %-16s %4s %1s %1s %-9s %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;
+	freep = kinfo_getfile(pid, &cnt);
+	if (freep != NULL && Cflag) {
+		for (i = 0; i < cnt; i++) {
+			kif = &freep[i];
+			width = width_capability(kif->kf_cap_rights);
+			if (width > capwidth)
+				capwidth = width;
+		}
+		if (capwidth < strlen("CAPABILITIES"))
+			capwidth = strlen("CAPABILITIES");
+	}
+	printf("capwidth: %d\n", capwidth);
+
+	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");
+	}
 
-	freep = kinfo_getfile(pid, &cnt);
 	if (freep == NULL)
 		return;
 	for (i = 0; i < cnt; i++) {
 		kif = &freep[i];
-		
+
 		printf("%5d ", pid);
 		printf("%-16s ", kipp->ki_comm);
 		switch (kif->kf_fd) {
@@ -291,49 +344,51 @@
 			break;
 		}
 		printf("%1s ", str);
-		str = "-";
-		if (kif->kf_type == KF_TYPE_VNODE) {
-			switch (kif->kf_vnode_type) {
-			case KF_VTYPE_VREG:
-				str = "r";
-				break;
+		if (!Cflag) {
+			str = "-";
+			if (kif->kf_type == KF_TYPE_VNODE) {
+				switch (kif->kf_vnode_type) {
+				case KF_VTYPE_VREG:
+					str = "r";
+					break;
 
-			case KF_VTYPE_VDIR:
-				str = "d";
-				break;
+				case KF_VTYPE_VDIR:
+					str = "d";
+					break;
 
-			case KF_VTYPE_VBLK:
-				str = "b";
-				break;
+				case KF_VTYPE_VBLK:
+					str = "b";
+					break;
 
-			case KF_VTYPE_VCHR:
-				str = "c";
-				break;
+				case KF_VTYPE_VCHR:
+					str = "c";
+					break;
 
-			case KF_VTYPE_VLNK:
-				str = "l";
-				break;
+				case KF_VTYPE_VLNK:
+					str = "l";
+					break;
 
-			case KF_VTYPE_VSOCK:
-				str = "s";
-				break;
+				case KF_VTYPE_VSOCK:
+					str = "s";
+					break;
 
-			case KF_VTYPE_VFIFO:
-				str = "f";
-				break;
+				case KF_VTYPE_VFIFO:
+					str = "f";
+					break;
 
-			case KF_VTYPE_VBAD:
-				str = "x";
-				break;
+				case KF_VTYPE_VBAD:
+					str = "x";
+					break;
 
-			case KF_VTYPE_VNON:
-			case KF_VTYPE_UNKNOWN:
-			default:
-				str = "?";
-				break;
+				case KF_VTYPE_VNON:
+				case KF_VTYPE_UNKNOWN:
+				default:
+					str = "?";
+					break;
+				}
 			}
+			printf("%1s ", str);
 		}
-		printf("%1s ", str);
 		printf("%s", kif->kf_flags & KF_FLAG_READ ? "r" : "-");
 		printf("%s", kif->kf_flags & KF_FLAG_WRITE ? "w" : "-");
 		printf("%s", kif->kf_flags & KF_FLAG_APPEND ? "a" : "-");
@@ -343,27 +398,50 @@
 		printf("%s", kif->kf_flags & KF_FLAG_DIRECT ? "d" : "-");
 		printf("%s", kif->kf_flags & KF_FLAG_HASLOCK ? "l" : "-");
 		printf("%s ", kif->kf_flags & KF_FLAG_CAPABILITY ? "c" : "-");
-		if (kif->kf_ref_count > -1)
-			printf("%3d ", kif->kf_ref_count);
-		else
-			printf("%3c ", '-');
-		if (kif->kf_offset > -1)
-			printf("%7jd ", (intmax_t)kif->kf_offset);
-		else
-			printf("%7c ", '-');
+		if (!Cflag) {
+			if (kif->kf_ref_count > -1)
+				printf("%3d ", kif->kf_ref_count);
+			else
+				printf("%3c ", '-');
+			if (kif->kf_offset > -1)
+				printf("%7jd ", (intmax_t)kif->kf_offset);
+			else
+				printf("%7c ", '-');
+		}
+
+		if (Cflag) {
+			print_capability(kif->kf_cap_rights, capwidth);
+			printf(" ");
+		}
 
 		switch (kif->kf_type) {
 		case KF_TYPE_VNODE:
 		case KF_TYPE_FIFO:
 		case KF_TYPE_PTS:
 			printf("%-3s ", "-");
-			printf("%-18s", kif->kf_path);
 			break;
 
 		case KF_TYPE_SOCKET:
 			printf("%-3s ",
 			    protocol_to_string(kif->kf_sock_domain,
 			    kif->kf_sock_type, kif->kf_sock_protocol));
+			break;
+
+		case KF_TYPE_PROCDESC:
+			printf("%-3s %d", "-", kif->kf_pid);
+			break;
+
+		default:
+			printf("%-3s ", "-");
+		}
+
+		switch (kif->kf_type) {
+		case KF_TYPE_VNODE:
+		case KF_TYPE_FIFO:
+		case KF_TYPE_PTS:
+			printf("%-18s", kif->kf_path);
+
+		case KF_TYPE_SOCKET:
 			/*
 			 * While generally we like to print two addresses,
 			 * local and peer, for sockets, it turns out to be
@@ -387,11 +465,10 @@
 			break;
 
 		case KF_TYPE_PROCDESC:
-			printf("%-3s %d", "-", kif->kf_pid);
+			printf("%d", kif->kf_pid);
 			break;
 
 		default:
-			printf("%-3s ", "-");
 			printf("%-18s", "-");
 		}
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901211158.n0LBwkLY084290>