Home | History | Annotate | Download | only in acct
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 
     31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     32 
     33 #include <time.h>
     34 #include <string.h>
     35 #include <stdio.h>
     36 #include <sys/types.h>
     37 #include <sys/param.h>
     38 #include "acctdef.h"
     39 #include <grp.h>
     40 #include <sys/acct.h>
     41 #include <pwd.h>
     42 #include <sys/stat.h>
     43 #include <locale.h>
     44 #include <stdlib.h>
     45 #include <libgen.h>
     46 
     47 struct	acct ab;
     48 char	command_name[16];
     49 char	obuf[BUFSIZ];
     50 static char	time_buf[50];
     51 
     52 double	cpucut,
     53 	syscut,
     54 	hogcut,
     55 	iocut,
     56 	realtot,
     57 	cputot,
     58 	usertot,
     59 	systot,
     60 	kcoretot,
     61 	iotot,
     62 	rwtot;
     63 extern long	timezone;
     64 extern int	daylight;	/* daylight savings time if set */
     65 long	daydiff,
     66 	offset = -2,
     67 	cmdcount;
     68 ulong_t	elapsed,
     69 	sys,
     70 	user,
     71 	cpu,
     72 	io,
     73 	rw,
     74 	mem,
     75 	etime;
     76 time_t	tstrt_b,
     77 	tstrt_a,
     78 	tend_b,
     79 	tend_a;
     80 int	backward,
     81 	flag_field,
     82 	average,
     83 	quiet,
     84 	option,
     85 	verbose = 1,
     86 	uidflag,
     87 	gidflag,
     88 	unkid,	/*user doesn't have login on this machine*/
     89 	errflg,
     90 	su_user,
     91 	fileout = 0,
     92 	stdinflg,
     93 	nfiles;
     94 static int	eflg = 0,
     95 	Eflg = 0,
     96 	sflg = 0,
     97 	Sflg = 0;
     98 #ifdef uts
     99 dev_t   linedev = 0xffff;  /* changed from -1, as dev_t is now ushort */
    100 #else
    101 dev_t	linedev = (dev_t)-1;
    102 #endif
    103 uid_t	uidval;
    104 gid_t	gidval;
    105 char	*cname = NULL; /* command name pattern to match*/
    106 
    107 struct passwd *getpwnam(), *getpwuid(), *pw;
    108 struct group *getgrnam(),*grp;
    109 long	convtime();
    110 
    111 #ifdef uts
    112 float   expand();
    113 #else
    114 ulong_t	expand();
    115 #endif
    116 
    117 char	*ofile,
    118 	*devtolin(),
    119 	*uidtonam();
    120 dev_t	lintodev();
    121 
    122 void dofile(char *);
    123 void doexit(int) __NORETURN;
    124 void usage(void);
    125 void fatal(char *, char *);
    126 void println(void);
    127 void printhd(void);
    128 char *cmset(char *);
    129 
    130 FILE	*ostrm;
    131 
    132 int
    133 main(int argc, char **argv)
    134 {
    135 	int	c;
    136 
    137 	(void)setlocale(LC_ALL, "");
    138 	setbuf(stdout,obuf);
    139 	while((c = getopt(argc, argv,
    140 		"C:E:H:I:O:S:abe:fg:hikl:mn:o:qrs:tu:v")) != EOF) {
    141 		switch(c) {
    142 		case 'C':
    143 			sscanf(optarg,"%lf",&cpucut);
    144 			continue;
    145 		case 'O':
    146 			sscanf(optarg,"%lf",&syscut);
    147 			continue;
    148 		case 'H':
    149 			sscanf(optarg,"%lf",&hogcut);
    150 			continue;
    151 		case 'I':
    152 			sscanf(optarg,"%lf",&iocut);
    153 			continue;
    154 		case 'a':
    155 			average++;
    156 			continue;
    157 		case 'b':
    158 			backward++;
    159 			continue;
    160 		case 'g':
    161 			if(sscanf(optarg,"%ld",&gidval) == 1) {
    162 				if (getgrgid(gidval) == NULL)
    163 					fatal("Unknown group", optarg);
    164 			} else if((grp=getgrnam(optarg)) == NULL)
    165 				fatal("Unknown group", optarg);
    166 			else
    167 				gidval=grp->gr_gid;
    168 			gidflag++;
    169 			continue;
    170 		case 'h':
    171 			option |= HOGFACTOR;
    172 			continue;
    173 		case 'i':
    174 			option |= IORW;
    175 			continue;
    176 		case 'k':
    177 			option |= KCOREMIN;
    178 			continue;
    179 		case 'm':
    180 			option |= MEANSIZE;
    181 			continue;
    182 		case 'n':
    183 			cname=cmset(optarg);
    184 			continue;
    185 		case 't':
    186 			option |= SEPTIME;
    187 			continue;
    188 		case 'r':
    189 			option |= CPUFACTOR;
    190 			continue;
    191 		case 'v':
    192 			verbose=0;
    193 			continue;
    194 		case 'l':
    195 			linedev = lintodev(optarg);
    196 			continue;
    197 		case 'u':
    198 			if(*optarg == '?') {
    199 				unkid++;
    200 				continue;
    201 			}
    202 			if(*optarg == '#') {
    203 				su_user++;
    204 				uidval = 0;
    205 				uidflag++;
    206 				continue;
    207 			}
    208 			if((pw = getpwnam(optarg)) == NULL) {
    209 				uidval = (uid_t)atoi(optarg);
    210 				/* atoi will return 0 in abnormal situation */
    211 				if (uidval == 0 && strcmp(optarg, "0") != 0) {
    212 					fprintf(stderr, "%s: Unknown user %s\n", argv[0], optarg);
    213 					exit(1);
    214 				}
    215  				if ((pw = getpwuid(uidval)) == NULL) {
    216 					fprintf(stderr, "%s: Unknown user %s\n", argv[0], optarg);
    217 					exit(1);
    218 				}
    219 				uidflag++;
    220 			} else {
    221 				uidval = pw->pw_uid;
    222 				uidflag++;
    223 			}
    224 			continue;
    225 		case 'q':
    226 			quiet++;
    227 			verbose=0;
    228 			average++;
    229 			continue;
    230 		case 's':
    231 			sflg = 1;
    232 			tend_a = convtime(optarg);
    233 			continue;
    234 		case 'S':
    235 			Sflg = 1;
    236 			tstrt_a = convtime(optarg);
    237 			continue;
    238 		case 'f':
    239 			flag_field++;
    240 			continue;
    241 		case 'e':
    242 			eflg = 1;
    243 			tstrt_b = convtime(optarg);
    244 			continue;
    245 		case 'E':
    246 			Eflg = 1;
    247 			tend_b = convtime(optarg);
    248 			continue;
    249 		case 'o':
    250 			ofile = optarg;
    251 			fileout++;
    252 			if((ostrm = fopen(ofile, "w")) == NULL) {
    253 				perror("open error on output file");
    254 				errflg++;
    255 			}
    256 			continue;
    257 		case '?':
    258 			errflg++;
    259 			continue;
    260 		}
    261 	}
    262 
    263 	if(errflg) {
    264 		usage();
    265 		exit(1);
    266 	}
    267 
    268 
    269 	argv = &argv[optind];
    270 	while(optind++ < argc) {
    271 		dofile(*argv++);    /* change from *argv */
    272 		nfiles++;
    273 	}
    274 
    275 	if(nfiles==0) {
    276 		if(isatty(0) || isdevnull())
    277 			dofile(PACCT);
    278 		else {
    279 			stdinflg = 1;
    280 			backward = offset = 0;
    281 			dofile(NULL);
    282 		}
    283 	}
    284 	doexit(0);
    285 	/* NOTREACHED */
    286 }
    287 
    288 void
    289 dofile(char *fname)
    290 {
    291 	struct acct *a = &ab;
    292 	struct tm *t;
    293 	time_t curtime;
    294 	time_t	ts_a = 0,
    295 		ts_b = 0,
    296 		te_a = 0,
    297 		te_b = 0;
    298 	long	daystart;
    299 	long	nsize;
    300 	int	ver;	/* version of acct structure */
    301 	int	dst_secs;	/* number of seconds to adjust
    302 				   for daylight savings time */
    303 
    304 	if(fname != NULL)
    305 		if(freopen(fname, "r", stdin) == NULL) {
    306 			fprintf(stderr, "acctcom: cannot open %s\n", fname);
    307 			return;
    308 		}
    309 
    310 	if (fread((char *)&ab, sizeof(struct acct), 1, stdin) != 1)
    311 		return;
    312 	else if (ab.ac_flag & AEXPND)
    313 		ver = 2;	/* 4.0 acct structure */
    314 	else
    315 		ver = 1;	/* 3.x acct structure */
    316 
    317 	rewind(stdin);
    318 
    319 
    320 	if(backward) {
    321 		if (ver == 2)
    322 			nsize = sizeof(struct acct);	/* make sure offset is signed */
    323 		else
    324 			nsize = sizeof(struct o_acct);	/* make sure offset is signed */
    325 		fseek(stdin, (long)(-nsize), 2);
    326 	}
    327 	tzset();
    328 	daydiff = a->ac_btime - (a->ac_btime % SECSINDAY);
    329 	time(&curtime);
    330 	t = localtime(&curtime);
    331 	if (daydiff < (curtime - (curtime % SECSINDAY))) {
    332 		time_t t;
    333 		/*
    334 		 * it is older than today
    335 		 */
    336 		t = (time_t)a->ac_btime;
    337 		cftime(time_buf, DATE_FMT, &t);
    338 		fprintf(stdout, "\nACCOUNTING RECORDS FROM:  %s", time_buf);
    339 	}
    340 
    341 	/* adjust time by one hour for daylight savings time */
    342 	if (daylight && t->tm_isdst != 0)
    343 		dst_secs = 3600;
    344 	else
    345 		dst_secs = 0;
    346 	daystart = (a->ac_btime - timezone + dst_secs) -
    347 	    ((a->ac_btime - timezone + dst_secs) % SECSINDAY);
    348 	if (Sflg) {
    349 		ts_a = tstrt_a + daystart - dst_secs;
    350 		cftime(time_buf, DATE_FMT, &ts_a);
    351 		fprintf(stdout, "START AFT: %s", time_buf);
    352 	}
    353 	if (eflg) {
    354 		ts_b = tstrt_b + daystart - dst_secs;
    355 		cftime(time_buf, DATE_FMT, &ts_b);
    356 		fprintf(stdout, "START BEF: %s", time_buf);
    357 	}
    358 	if (sflg) {
    359 		te_a = tend_a + daystart - dst_secs;
    360 		cftime(time_buf, DATE_FMT, &te_a);
    361 		fprintf(stdout, "END AFTER: %s", time_buf);
    362 	}
    363 	if (Eflg) {
    364 		te_b = tend_b + daystart - dst_secs;
    365 		cftime(time_buf, DATE_FMT, &te_b);
    366 		fprintf(stdout, "END BEFOR: %s", time_buf);
    367 	}
    368 	if(ts_a) {
    369 		if (te_b && ts_a > te_b) te_b += SECSINDAY;
    370 	}
    371 
    372 	while(aread(ver) != 0) {
    373 		elapsed = expand(a->ac_etime);
    374 		etime = (ulong_t)a->ac_btime + (ulong_t)SECS(elapsed);
    375 		if(ts_a || ts_b || te_a || te_b) {
    376 
    377 			if(te_a && (etime < te_a)) {
    378 				if(backward) return;
    379 				else continue;
    380 			}
    381 			if(te_b && (etime > te_b)) {
    382 				if(backward) continue;
    383 				else return;
    384 			}
    385 			if(ts_a && (a->ac_btime < ts_a))
    386 				continue;
    387 			if(ts_b && (a->ac_btime > ts_b))
    388 				continue;
    389 		}
    390 		if(!MYKIND(a->ac_flag))
    391 			continue;
    392 		if(su_user && !SU(a->ac_flag))
    393 			continue;
    394 		sys = expand(a->ac_stime);
    395 		user = expand(a->ac_utime);
    396 		cpu = sys + user;
    397 		if(cpu == 0)
    398 			cpu = 1;
    399 		mem = expand(a->ac_mem);
    400 		(void) strncpy(command_name, a->ac_comm, 8);
    401 		io=expand(a->ac_io);
    402 		rw=expand(a->ac_rw);
    403 		if(cpucut && cpucut >= SECS(cpu))
    404 			continue;
    405 		if(syscut && syscut >= SECS(sys))
    406 			continue;
    407 #ifdef uts
    408 		if(linedev != 0xffff && a->ac_tty != linedev)
    409 			continue;
    410 #else
    411 		if(linedev != (dev_t)-1 && a->ac_tty != linedev)
    412 			continue;
    413 #endif
    414 		if(uidflag && a->ac_uid != uidval)
    415 			continue;
    416 		if(gidflag && a->ac_gid != gidval)
    417 			continue;
    418 		if(cname && !cmatch(a->ac_comm,cname))
    419 			continue;
    420 		if(iocut && iocut > io)
    421 			continue;
    422 		if(unkid && uidtonam(a->ac_uid)[0] != '?')
    423 			continue;
    424 		if(verbose && (fileout == 0)) {
    425 			printhd();
    426 			verbose = 0;
    427 		}
    428 		if(elapsed == 0)
    429 			elapsed++;
    430 		if(hogcut && hogcut >= (double)cpu/(double)elapsed)
    431 			continue;
    432 		if(fileout)
    433 			fwrite(&ab, sizeof(ab), 1, ostrm);
    434 		else
    435 			println();
    436 		if(average) {
    437 			cmdcount++;
    438 			realtot += (double)elapsed;
    439 			usertot += (double)user;
    440 			systot += (double)sys;
    441 			kcoretot += (double)mem;
    442 			iotot += (double)io;
    443 			rwtot += (double)rw;
    444 		};
    445 	}
    446 }
    447 
    448 int
    449 aread(int ver)
    450 {
    451 	static int ok = 1;
    452 	struct o_acct oab;
    453 	int ret;
    454 
    455 	if (ver != 2) {
    456 		if ((ret = fread((char *)&oab, sizeof(struct o_acct), 1, stdin)) == 1){
    457 			/* copy SVR3 acct struct to SVR4 acct struct */
    458 			ab.ac_flag = oab.ac_flag | AEXPND;
    459 			ab.ac_stat = oab.ac_stat;
    460 			ab.ac_uid = (uid_t) oab.ac_uid;
    461 			ab.ac_gid = (gid_t) oab.ac_gid;
    462 			ab.ac_tty = (dev_t) oab.ac_tty;
    463 			ab.ac_btime = oab.ac_btime;
    464 			ab.ac_utime = oab.ac_utime;
    465 			ab.ac_stime = oab.ac_stime;
    466 			ab.ac_mem = oab.ac_mem;
    467 			ab.ac_io = oab.ac_io;
    468 			ab.ac_rw = oab.ac_rw;
    469 			strcpy(ab.ac_comm, oab.ac_comm);
    470 		}
    471 	} else
    472 		ret = fread((char *)&ab, sizeof(struct acct), 1, stdin);
    473 
    474 
    475 	if(backward) {
    476 		if(ok) {
    477 			if(fseek(stdin,
    478 				(long)(offset*(ver == 2 ? sizeof(struct acct) :
    479 					sizeof(struct o_acct))), 1) != 0) {
    480 
    481 					rewind(stdin);	/* get 1st record */
    482 					ok = 0;
    483 			}
    484 		} else
    485 			ret = 0;
    486 	}
    487 	return(ret != 1 ? 0 : 1);
    488 }
    489 
    490 void
    491 printhd(void)
    492 {
    493 	fprintf(stdout, "COMMAND                           START    END          REAL");
    494 	ps("CPU");
    495 	if(option & SEPTIME)
    496 		ps("(SECS)");
    497 	if(option & IORW){
    498 		ps("CHARS");
    499 		ps("BLOCKS");
    500 	}
    501 	if(option & CPUFACTOR)
    502 		ps("CPU");
    503 	if(option & HOGFACTOR)
    504 		ps("HOG");
    505 	if(!option || (option & MEANSIZE))
    506 		ps("MEAN");
    507 	if(option & KCOREMIN)
    508 		ps("KCORE");
    509 	fprintf(stdout, "\n");
    510 	fprintf(stdout, "NAME       USER     TTYNAME       TIME     TIME       (SECS)");
    511 	if(option & SEPTIME) {
    512 		ps("SYS");
    513 		ps("USER");
    514 	} else
    515 		ps("(SECS)");
    516 	if(option & IORW) {
    517 		ps("TRNSFD");
    518 		ps("READ");
    519 	}
    520 	if(option & CPUFACTOR)
    521 		ps("FACTOR");
    522 	if(option & HOGFACTOR)
    523 		ps("FACTOR");
    524 	if(!option || (option & MEANSIZE))
    525 		ps("SIZE(K)");
    526 	if(option & KCOREMIN)
    527 		ps("MIN");
    528 	if(flag_field)
    529 		fprintf(stdout, "  F STAT");
    530 	fprintf(stdout, "\n");
    531 	fflush(stdout);
    532 }
    533 
    534 void
    535 println(void)
    536 {
    537 	char name[32];
    538 	struct acct *a = &ab;
    539 	time_t t;
    540 
    541 	if(quiet)
    542 		return;
    543 	if(!SU(a->ac_flag))
    544 		strcpy(name,command_name);
    545 	else {
    546 		strcpy(name,"#");
    547 		strcat(name,command_name);
    548 	}
    549 	fprintf(stdout, "%-*.*s", (OUTPUT_NSZ + 1),
    550 	    (OUTPUT_NSZ + 1), name);
    551 	strcpy(name,uidtonam(a->ac_uid));
    552 	if(*name != '?')
    553 		fprintf(stdout, "  %-*.*s", (OUTPUT_NSZ + 1),
    554 		    (OUTPUT_NSZ + 1), name);
    555 	else
    556 		fprintf(stdout, "  %-9d",a->ac_uid);
    557 #ifdef uts
    558 	fprintf(stdout, " %-*.*s", OUTPUT_LSZ, OUTPUT_LSZ,
    559 	    a->ac_tty != 0xffff? devtolin(a->ac_tty):"?");
    560 #else
    561 	fprintf(stdout, " %-*.*s", OUTPUT_LSZ, OUTPUT_LSZ,
    562 	    a->ac_tty != (dev_t)-1? devtolin(a->ac_tty):"?");
    563 #endif
    564 	t = a->ac_btime;
    565 	cftime(time_buf, DATE_FMT1, &t);
    566 	fprintf(stdout, "%.9s", time_buf);
    567 	cftime(time_buf, DATE_FMT1, (time_t *)&etime);
    568 	fprintf(stdout, "%.9s ", time_buf);
    569 	pf((double)SECS(elapsed));
    570 	if(option & SEPTIME) {
    571 		pf((double)sys / HZ);
    572 		pf((double)user / HZ);
    573 	} else
    574 		pf((double)cpu / HZ);
    575 	if(option & IORW)
    576 		fprintf(stdout, io < 100000000 ? "%8ld%8ld" : "%12ld%8ld",io,rw);
    577 	if(option & CPUFACTOR)
    578 		pf((double)user / cpu);
    579 	if(option & HOGFACTOR)
    580 		pf((double)cpu / elapsed);
    581 	if(!option || (option & MEANSIZE))
    582 		pf(KCORE(mem / cpu));
    583 	if(option & KCOREMIN)
    584 		pf(MINT(KCORE(mem)));
    585 	if(flag_field)
    586 		fprintf(stdout, "  %1o %3o", (unsigned char) a->ac_flag,
    587 						(unsigned char) a->ac_stat);
    588 	fprintf(stdout, "\n");
    589 }
    590 
    591 /*
    592  * convtime converts time arg to internal value
    593  * arg has form hr:min:sec, min or sec are assumed to be 0 if omitted
    594  */
    595 long
    596 convtime(str)
    597 char *str;
    598 {
    599 	long	hr, min, sec;
    600 
    601 	min = sec = 0;
    602 
    603 	if(sscanf(str, "%ld:%ld:%ld", &hr, &min, &sec) < 1) {
    604 		fatal("acctcom: bad time:", str);
    605 	}
    606 	tzset();
    607 	sec += (min*60);
    608 	sec += (hr*3600);
    609 	return(sec + timezone);
    610 }
    611 
    612 int
    613 cmatch(char *comm, char *cstr)
    614 {
    615 
    616 	char	xcomm[9];
    617 	int i;
    618 
    619 	for(i=0;i<8;i++){
    620 		if(comm[i]==' '||comm[i]=='\0')
    621 			break;
    622 		xcomm[i] = comm[i];
    623 	}
    624 	xcomm[i] = '\0';
    625 
    626 	return (regex(cstr,xcomm) ? 1 : 0);
    627 }
    628 
    629 char *
    630 cmset(char *pattern)
    631 {
    632 
    633 	if((pattern=(char *)regcmp(pattern,(char *)0))==NULL){
    634 		fatal("pattern syntax", NULL);
    635 	}
    636 
    637 	return (pattern);
    638 }
    639 
    640 void
    641 doexit(int status)
    642 {
    643 	if(!average)
    644 		exit(status);
    645 	if(cmdcount) {
    646 		fprintf(stdout, "cmds=%ld ",cmdcount);
    647 		fprintf(stdout, "Real=%-6.2f ",SECS(realtot)/cmdcount);
    648 		cputot = systot + usertot;
    649 		fprintf(stdout, "CPU=%-6.2f ",SECS(cputot)/cmdcount);
    650 		fprintf(stdout, "USER=%-6.2f ",SECS(usertot)/cmdcount);
    651 		fprintf(stdout, "SYS=%-6.2f ",SECS(systot)/cmdcount);
    652 		fprintf(stdout, "CHAR=%-8.2f ",iotot/cmdcount);
    653 		fprintf(stdout, "BLK=%-8.2f ",rwtot/cmdcount);
    654 		fprintf(stdout, "USR/TOT=%-4.2f ",usertot/cputot);
    655 		fprintf(stdout, "HOG=%-4.2f ",cputot/realtot);
    656 		fprintf(stdout, "\n");
    657 	}
    658 	else
    659 		fprintf(stdout, "\nNo commands matched\n");
    660 	exit(status);
    661 }
    662 
    663 int
    664 isdevnull(void)
    665 {
    666 	struct stat	filearg;
    667 	struct stat	devnull;
    668 
    669 	if(fstat(0,&filearg) == -1) {
    670 		fprintf(stderr,"acctcom: cannot stat stdin\n");
    671 		return (0);
    672 	}
    673 	if(stat("/dev/null",&devnull) == -1) {
    674 		fprintf(stderr,"acctcom: cannot stat /dev/null\n");
    675 		return (0);
    676 	}
    677 
    678 	if (filearg.st_rdev == devnull.st_rdev)
    679 		return (1);
    680 	else
    681 		return (0);
    682 }
    683 
    684 void
    685 fatal(char *s1, char *s2)
    686 {
    687 	fprintf(stderr,"acctcom: %s %s\n", s1, (s2 ? s2 : ""));
    688 	exit(1);
    689 }
    690 
    691 void
    692 usage(void)
    693 {
    694 	fprintf(stderr, "Usage: acctcom [options] [files]\n");
    695 	fprintf(stderr, "\nWhere options can be:\n");
    696 	diag("-b	read backwards through file");
    697 	diag("-f	print the fork/exec flag and exit status");
    698 	diag("-h	print hog factor (total-CPU-time/elapsed-time)");
    699 	diag("-i	print I/O counts");
    700 	diag("-k	show total Kcore minutes instead of memory size");
    701 	diag("-m	show mean memory size");
    702 	diag("-r	show CPU factor (user-time/(sys-time + user-time))");
    703 	diag("-t	show separate system and user CPU times");
    704 	diag("-v	don't print column headings");
    705 	diag("-a	print average statistics of selected commands");
    706 	diag("-q	print average statistics only");
    707 	diag("-l line	\tshow processes belonging to terminal /dev/line");
    708 	diag("-u user	\tshow processes belonging to user name or user ID");
    709 	diag("-u #	\tshow processes executed by super-user");
    710 	diag("-u ?	\tshow processes executed by unknown UID's");
    711 	diag("-g group	show processes belonging to group name of group ID");
    712 	diag("-s time	\tshow processes ending after time (hh[:mm[:ss]])");
    713 	diag("-e time	\tshow processes starting before time");
    714 	diag("-S time	\tshow processes starting after time");
    715 	diag("-E time	\tshow processes ending before time");
    716 	diag("-n regex	select commands matching the ed(1) regular expression");
    717 	diag("-o file	\tdo not print, put selected pacct records into file");
    718 	diag("-H factor	show processes that exceed hog factor");
    719 	diag("-O sec	\tshow processes that exceed CPU system time sec");
    720 	diag("-C sec	\tshow processes that exceed total CPU time sec");
    721 	diag("-I chars	show processes that transfer more than char chars");
    722 }
    723