From dada@lend.tu-graz.ac.at  Wed Nov  5 02:27:06 1997
Received: from fcggsg07.icg.tu-graz.ac.at (fcggsg07.icg.tu-graz.ac.at [129.27.201.16])
          by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id CAA01018
          for <FreeBSD-gnats-submit@freebsd.org>; Wed, 5 Nov 1997 02:27:00 -0800 (PST)
          (envelope-from dada@lend.tu-graz.ac.at)
Received: from lend.tu-graz.ac.at (isdn075.tu-graz.ac.at [129.27.240.75])
          by fcggsg07.icg.tu-graz.ac.at (8.8.4/8.8.4) with ESMTP
	  id LAA03198 for <FreeBSD-gnats-submit@freebsd.org>; Wed, 5 Nov 1997 11:26:41 +0100 (MET)
Received: (from dada@localhost)
	by lend.tu-graz.ac.at (8.8.5/8.8.5) id LAA06379;
	Wed, 5 Nov 1997 11:22:43 +0100 (CET)
Message-Id: <199711051022.LAA06379@lend.tu-graz.ac.at>
Date: Wed, 5 Nov 1997 11:22:43 +0100 (CET)
From: Martin Kammerhofer <dada@sbox.tu-graz.ac.at>
Reply-To: dada@sbox.tu-graz.ac.at
To: FreeBSD-gnats-submit@freebsd.org
Subject: ps(1) output is not parsable and -Ortprio doesn't work
X-Send-Pr-Version: 3.2

>Number:         4947
>Category:       bin
>Synopsis:       ps(1) output is not parsable and -Ortprio doesn't work
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    steve
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Nov  5 02:30:03 PST 1997
>Closed-Date:    Thu Jun 4 15:19:15 PDT 1998
>Last-Modified:  Thu Jun  4 15:21:01 PDT 1998
>Originator:     Martin Kammerhofer
>Release:        FreeBSD 2.2-STABLE i386
>Organization:
Graz University of Technology
>Environment:

nothing special

>Description:

I am parsing ps(1)'s output with perl. When I request *all*
information ps(1) supplies (confer `ps -L`) on all processes (-ax) I
run into trouble.  Although care has been taken to print a default '-'
or '?' for unknown/unset/empty fields this has been forgotten for
'LOGIN'.  Processes 0,2,3 and 4 (they never call setlogin) just print
a *blank* field - thereby confusing any perl/awk parser because the
number of output fields is inconsistent.

Another bug (yes, it's two bugs in one PR here) is that ps(1) cannot
print a process's real time priority correctly. Currently with 'ps
-Ortprio' you get the number (rtprio.prio << 16 + rtprio.type) which
doesn't make much sense. The problem here is that a structure of two
ushorts is printed as a long. (See /usr/include/sys/rtprio.h).

Another bug (#3) remains: "ps -p0" doesn't work. This seems to be
kvm_getprocs()'s fault and no fix is provided here.

>How-To-Repeat:

BUG #1:
<ttyp5 /var/tmp>ps -axOlogin | head
  PID LOGIN         TT  STAT      TIME COMMAND
    0               ??  DLs    0:00.07  (swapper)
    1 root          ??  Ss     0:00.12 /sbin/init --
    2               ??  DL     0:02.50  (pagedaemon)
    3               ??  DL     0:00.00  (vmdaemon)
    4               ??  DL     0:26.16  (update)
   43 root          ??  Is     0:00.03 adjkerntz -i
   91 root          ??  Is     0:01.24 syslogd
   97 root          ??  Is     0:00.12 named -b /etc/namedb/named.boot
  102 root          ??  Is     0:00.01 portmap

BUG #2:
<ttyp5 /var/tmp>su
# rtprio 10 sleep 100 &
[1] 5143
# idprio 20 sleep 200 &
[2] 5156
# ps -TOrtprio
  PID  RTPRIO  TT  STAT      TIME COMMAND
 5090       1  p5  Is     0:00.50 -usr/local/bin/tcsh -i
 5120       1  p5  S      0:00.46 -su (csh)
 5143  655360  p5  I      0:00.05 sleep 100
 5156 1310722  p5  S      0:00.04 sleep 200
 5169       1  p5  R+     0:00.03 ps -TOrtprio

After applying my patch these look like:
FIXED #1:
<ttyp5 /var/tmp>ps -axOlogin | head
  PID LOGIN         TT  STAT      TIME COMMAND
    0 -             ??  DLs    0:00.07  (swapper)
    1 root          ??  Is     0:00.12 /sbin/init --
    2 -             ??  DL     0:02.50  (pagedaemon)
    3 -             ??  DL     0:00.00  (vmdaemon)
    4 -             ??  DL     0:26.62  (update)
   43 root          ??  Is     0:00.03 adjkerntz -i
   91 root          ??  Is     0:01.24 syslogd
   97 root          ??  Is     0:00.12 named -b /etc/namedb/named.boot
  102 root          ??  Is     0:00.01 portmap

FIXED #2:
<ttyp5 /var/tmp>su
# rtprio 10 sleep 100 &
[1] 5357
# idprio 20 sleep 200 &
[2] 5361
# ps -TOrtprio
  PID  RTPRIO  TT  STAT      TIME COMMAND
 5090  normal  p5  Ss     0:00.55 -usr/local/bin/tcsh -i
 5356  normal  p5  S      0:00.41 -su (csh)
 5357 real:10  p5  S      0:00.04 sleep 100
 5361 idle:20  p5  S      0:00.04 sleep 200
 5371  normal  p5  R+     0:00.06 ps -TOrtprio

>Fix:

apply this patch in /usr/src/bin/ps:
	
Index: extern.h
===================================================================
RCS file: /home/dada/cvsroot/bin/ps/extern.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -K -r1.1.1.1 -r1.2
--- extern.h	1996/10/21 07:30:23	1.1.1.1
+++ extern.h	1997/11/04 22:50:59	1.2
@@ -64,6 +64,7 @@
 void	 pcpu __P((KINFO *, VARENT *));
 void	 pmem __P((KINFO *, VARENT *));
 void	 pri __P((KINFO *, VARENT *));
+void	 rtprior __P((KINFO *, VARENT *));
 void	 printheader __P((void));
 void	 pvar __P((KINFO *, VARENT *));
 void	 rssize __P((KINFO *, VARENT *));
Index: keyword.c
===================================================================
RCS file: /home/dada/cvsroot/bin/ps/keyword.c,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -K -r1.1.1.1 -r1.4
--- keyword.c	1996/07/31 09:27:23	1.1.1.1
+++ keyword.c	1997/11/05 10:03:00	1.4
@@ -139,7 +139,7 @@
 	{"rss", "RSS", NULL, 0, p_rssize, 4},
 	{"rssize", "", "rsz"},
 	{"rsz", "RSZ", NULL, 0, rssize, 4},
-	{"rtprio", "RTPRIO", NULL, 0, pvar, 7, POFF(p_rtprio), LONG, "d"},
+	{"rtprio", "RTPRIO", NULL, 0, rtprior, 7, POFF(p_rtprio)},
 	{"ruid", "RUID", NULL, 0, evar, UIDLEN, EOFF(e_pcred.p_ruid),
 		ULONG, UIDFMT},
 	{"ruser", "RUSER", NULL, LJUST, runame, USERLEN},
Index: print.c
===================================================================
RCS file: /home/dada/cvsroot/bin/ps/print.c,v
retrieving revision 1.1.1.1
retrieving revision 1.3
diff -u -K -r1.1.1.1 -r1.3
--- print.c	1997/04/16 16:10:48	1.1.1.1
+++ print.c	1997/11/05 08:59:33	1.3
@@ -164,12 +164,13 @@
 	VARENT *ve;
 {
 	VAR *v;
+	char *s;
 
 	v = ve->var;
 #ifndef NEWVM
 	(void)printf("%-*s", v->width, KI_PROC(k)->p_logname);
 #else
-	(void)printf("%-*s", v->width, KI_EPROC(k)->e_login);
+	(void)printf("%-*s", v->width, (s = KI_EPROC(k)->e_login, *s) ? s : "-");
 #endif
 }
 
@@ -656,6 +657,38 @@
 	(void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xrssize));
 }
 #endif
+
+void
+rtprior(k, ve)
+	KINFO *k;
+	VARENT *ve;
+{
+	VAR *v;
+	struct rtprio *prtp;
+	char str[8];
+	unsigned prio;
+
+	v = ve->var;
+	prtp = (struct rtprio *) ((char *)KI_PROC(k) + v->off);
+	prio = prtp->prio;
+	if (prio > 99)
+	    prio = 99;	/* ensure that 'str' can *never* overflow */
+	switch (prtp->type) {
+	case RTP_PRIO_REALTIME:
+	    sprintf(str, "real:%u", prio);
+	    break;
+	case RTP_PRIO_NORMAL:
+	    strncpy(str, "normal", 7);
+	    break;
+	case RTP_PRIO_IDLE:
+	    sprintf(str, "idle:%u", prio);
+	    break;
+	default:
+	    strncpy(str, "?", 2);
+	    break;
+	}
+	(void)printf("%*s", v->width, str);
+}
 
 /*
  * Generic output routines.  Print fields from various prototype
>Release-Note:
>Audit-Trail:

From: Bill Fenner <fenner@parc.xerox.com>
To: dada@sbox.tu-graz.ac.at
Cc: FreeBSD-gnats-submit@freebsd.org
Subject: Re: bin/4947: ps(1) output is not parsable and -Ortprio doesn't work 
Date: Wed, 5 Nov 1997 07:36:52 PST

 Martin Kammerhofer <dada@sbox.tu-graz.ac.at> wrote:
 >+	default:
 >+	    strncpy(str, "?", 2);
 
 I'd do something like "%d:%d", prtp->type, prio (taking care, of course,
 not to overflow) -- someone someday is going to be *really* frustrated that
 ps just prints a "?".
 
   Bill

From: Martin Kammerhofer <dada@sbox.tu-graz.ac.at>
To: FreeBSD problems <FreeBSD-gnats-submit@freebsd.org>
Cc:  Subject: Re: bin/4947: ps(1) output is not parsable and -Ortprio doesn't work 
Date: Wed, 5 Nov 1997 19:15:10 +0100 (CET)

 On Wed, 5 Nov 1997, Bill Fenner wrote:
 
 > >+	default:
 > >+	    strncpy(str, "?", 2);
 > 
 > I'd do something like "%d:%d", prtp->type, prio (taking care, of course,
 > not to overflow) -- someone someday is going to be *really* frustrated that
 > ps just prints a "?".
 > 
 
 You're right. Although currently 0 <= type <= 2 and 0 <= prio <= 31 holds,
 it isn't guaranteed to be that way for all times.
 How about this (relative to the last patch)?
 
 Index: print.c
 ===================================================================
 RCS file: /home/dada/cvsroot/bin/ps/print.c,v
 retrieving revision 1.3
 diff -u -K -r1.3 print.c
 --- print.c	1997/11/05 08:59:33	1.3
 +++ print.c	1997/11/05 18:05:12
 @@ -666,27 +666,26 @@
  	VAR *v;
  	struct rtprio *prtp;
  	char str[8];
 -	unsigned prio;
 +	unsigned type, prio;
  
  	v = ve->var;
  	prtp = (struct rtprio *) ((char *)KI_PROC(k) + v->off);
  	prio = prtp->prio;
 -	if (prio > 99)
 -	    prio = 99;	/* ensure that 'str' can *never* overflow */
 -	switch (prtp->type) {
 +	switch (type = prtp->type) {
  	case RTP_PRIO_REALTIME:
 -	    sprintf(str, "real:%u", prio);
 +	    snprintf(str, sizeof(str), "real:%u", prio);
  	    break;
  	case RTP_PRIO_NORMAL:
 -	    strncpy(str, "normal", 7);
 +	    strncpy(str, "normal", sizeof(str));
  	    break;
  	case RTP_PRIO_IDLE:
 -	    sprintf(str, "idle:%u", prio);
 +	    snprintf(str, sizeof(str), "idle:%u", prio);
  	    break;
  	default:
 -	    strncpy(str, "?", 2);
 +	    snprintf(str, sizeof(str), "%u:%u", type, prio);
  	    break;
  	}
 +	str[sizeof(str)-1] = '\0';
  	(void)printf("%*s", v->width, str);
  }
  
 
 
Responsible-Changed-From-To: freebsd-bugs->steve 
Responsible-Changed-By: steve 
Responsible-Changed-When: Sun May 24 22:08:41 PDT 1998 
Responsible-Changed-Why:  
Slightly tweaked patch committed to -current, thanks!  I will 
merge this into -stable soon. 
State-Changed-From-To: open->closed 
State-Changed-By: steve 
State-Changed-When: Thu Jun 4 15:19:15 PDT 1998 
State-Changed-Why:  
Patch committed to both -stable and -current.  Thanks! 
>Unformatted:
