1*c72b5b24Smillert /* $OpenBSD: ps.c,v 1.26 2002/02/16 21:27:07 millert Exp $ */ 2df930be7Sderaadt /* $NetBSD: ps.c,v 1.15 1995/05/18 20:33:25 mycroft Exp $ */ 3df930be7Sderaadt 4df930be7Sderaadt /*- 5df930be7Sderaadt * Copyright (c) 1990, 1993, 1994 6df930be7Sderaadt * The Regents of the University of California. All rights reserved. 7df930be7Sderaadt * 8df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 9df930be7Sderaadt * modification, are permitted provided that the following conditions 10df930be7Sderaadt * are met: 11df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 12df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 13df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 14df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 15df930be7Sderaadt * documentation and/or other materials provided with the distribution. 16df930be7Sderaadt * 3. All advertising materials mentioning features or use of this software 17df930be7Sderaadt * must display the following acknowledgement: 18df930be7Sderaadt * This product includes software developed by the University of 19df930be7Sderaadt * California, Berkeley and its contributors. 20df930be7Sderaadt * 4. Neither the name of the University nor the names of its contributors 21df930be7Sderaadt * may be used to endorse or promote products derived from this software 22df930be7Sderaadt * without specific prior written permission. 23df930be7Sderaadt * 24df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34df930be7Sderaadt * SUCH DAMAGE. 35df930be7Sderaadt */ 36df930be7Sderaadt 37df930be7Sderaadt #ifndef lint 38df930be7Sderaadt static char copyright[] = 39df930be7Sderaadt "@(#) Copyright (c) 1990, 1993, 1994\n\ 40df930be7Sderaadt The Regents of the University of California. All rights reserved.\n"; 41df930be7Sderaadt #endif /* not lint */ 42df930be7Sderaadt 43df930be7Sderaadt #ifndef lint 44df930be7Sderaadt #if 0 45df930be7Sderaadt static char sccsid[] = "@(#)ps.c 8.4 (Berkeley) 4/2/94"; 46df930be7Sderaadt #else 47*c72b5b24Smillert static char rcsid[] = "$OpenBSD: ps.c,v 1.26 2002/02/16 21:27:07 millert Exp $"; 48df930be7Sderaadt #endif 49df930be7Sderaadt #endif /* not lint */ 50df930be7Sderaadt 51df930be7Sderaadt #include <sys/param.h> 52df930be7Sderaadt #include <sys/user.h> 53df930be7Sderaadt #include <sys/time.h> 54df930be7Sderaadt #include <sys/resource.h> 55df930be7Sderaadt #include <sys/proc.h> 56df930be7Sderaadt #include <sys/stat.h> 57df930be7Sderaadt #include <sys/ioctl.h> 58df930be7Sderaadt #include <sys/sysctl.h> 5952576792Salex #include <sys/types.h> 60df930be7Sderaadt 61df930be7Sderaadt #include <ctype.h> 62df930be7Sderaadt #include <err.h> 63df930be7Sderaadt #include <errno.h> 64df930be7Sderaadt #include <fcntl.h> 65df930be7Sderaadt #include <kvm.h> 66df930be7Sderaadt #include <nlist.h> 67df930be7Sderaadt #include <paths.h> 6852576792Salex #include <pwd.h> 69df930be7Sderaadt #include <stdio.h> 70df930be7Sderaadt #include <stdlib.h> 71df930be7Sderaadt #include <string.h> 72df930be7Sderaadt #include <unistd.h> 736763c4d8Sderaadt #include <limits.h> 74df930be7Sderaadt 75df930be7Sderaadt #include "ps.h" 76df930be7Sderaadt 779517852aSmpech extern char *__progname; 789517852aSmpech 79df930be7Sderaadt KINFO *kinfo; 80df930be7Sderaadt struct varent *vhead, *vtail; 81df930be7Sderaadt 82df930be7Sderaadt int eval; /* exit value */ 83df930be7Sderaadt int rawcpu; /* -C */ 84df930be7Sderaadt int sumrusage; /* -S */ 85df930be7Sderaadt int termwidth; /* width of screen (0 == infinity) */ 86df930be7Sderaadt int totwidth; /* calculated width of requested variables */ 87df930be7Sderaadt 88618c5e0dSmillert int needcomm, needenv, commandonly; 89df930be7Sderaadt 904527c594Smillert enum sort { DEFAULT, SORTMEM, SORTCPU } sortby = DEFAULT; 91df930be7Sderaadt 92*c72b5b24Smillert static char *kludge_oldps_options(char *); 93*c72b5b24Smillert static int pscomp(const void *, const void *); 94*c72b5b24Smillert static void saveuser(KINFO *); 95*c72b5b24Smillert static void scanvars(void); 96*c72b5b24Smillert static void usage(void); 97df930be7Sderaadt 98df930be7Sderaadt char dfmt[] = "pid tt state time command"; 99df930be7Sderaadt char jfmt[] = "user pid ppid pgid sess jobc state tt time command"; 100df930be7Sderaadt char lfmt[] = "uid pid ppid cpu pri nice vsz rss wchan state tt time command"; 101df930be7Sderaadt char o1[] = "pid"; 102df930be7Sderaadt char o2[] = "tt state time command"; 103df930be7Sderaadt char ufmt[] = "user pid %cpu %mem vsz rss tt state start time command"; 104df930be7Sderaadt char vfmt[] = "pid state time sl re pagein vsz rss lim tsiz %cpu %mem command"; 105df930be7Sderaadt 106df930be7Sderaadt kvm_t *kd; 107df930be7Sderaadt 108df930be7Sderaadt int 109df930be7Sderaadt main(argc, argv) 110df930be7Sderaadt int argc; 111df930be7Sderaadt char *argv[]; 112df930be7Sderaadt { 113df930be7Sderaadt struct kinfo_proc *kp; 114df930be7Sderaadt struct varent *vent; 115df930be7Sderaadt struct winsize ws; 11652576792Salex struct passwd *pwd; 117df930be7Sderaadt dev_t ttydev; 118df930be7Sderaadt pid_t pid; 119df930be7Sderaadt uid_t uid; 1202c41d2f9Sangelos int all, ch, flag, i, fmt, lineno, nentries, mib[4], mibcnt, nproc; 1213f2d366dSniklas int prtheader, wflag, kflag, what, xflg; 1226763c4d8Sderaadt char *nlistf, *memf, *swapf, errbuf[_POSIX2_LINE_MAX]; 123e6592a11Sangelos size_t size; 124df930be7Sderaadt 125df930be7Sderaadt if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&ws) == -1 && 126df930be7Sderaadt ioctl(STDERR_FILENO, TIOCGWINSZ, (char *)&ws) == -1 && 127df930be7Sderaadt ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&ws) == -1) || 128df930be7Sderaadt ws.ws_col == 0) 129df930be7Sderaadt termwidth = 79; 130df930be7Sderaadt else 131df930be7Sderaadt termwidth = ws.ws_col - 1; 132df930be7Sderaadt 133df930be7Sderaadt if (argc > 1) 134df930be7Sderaadt argv[1] = kludge_oldps_options(argv[1]); 135df930be7Sderaadt 1363f2d366dSniklas all = fmt = prtheader = wflag = kflag = xflg = 0; 137df930be7Sderaadt pid = -1; 138df930be7Sderaadt uid = (uid_t) -1; 139df930be7Sderaadt ttydev = NODEV; 140df930be7Sderaadt memf = nlistf = swapf = NULL; 141df930be7Sderaadt while ((ch = getopt(argc, argv, 1423f2d366dSniklas "acCeghjkLlM:mN:O:o:p:rSTt:U:uvW:wx")) != -1) 143df930be7Sderaadt switch((char)ch) { 144df930be7Sderaadt case 'a': 145df930be7Sderaadt all = 1; 146df930be7Sderaadt break; 147df930be7Sderaadt case 'c': 148df930be7Sderaadt commandonly = 1; 149df930be7Sderaadt break; 150df930be7Sderaadt case 'e': /* XXX set ufmt */ 151df930be7Sderaadt needenv = 1; 152df930be7Sderaadt break; 153df930be7Sderaadt case 'C': 154df930be7Sderaadt rawcpu = 1; 155df930be7Sderaadt break; 156df930be7Sderaadt case 'g': 157df930be7Sderaadt break; /* no-op */ 158df930be7Sderaadt case 'h': 159df930be7Sderaadt prtheader = ws.ws_row > 5 ? ws.ws_row : 22; 160df930be7Sderaadt break; 161df930be7Sderaadt case 'j': 162df930be7Sderaadt parsefmt(jfmt); 163df930be7Sderaadt fmt = 1; 164df930be7Sderaadt jfmt[0] = '\0'; 165df930be7Sderaadt break; 1663f2d366dSniklas case 'k': 1673f2d366dSniklas kflag++; 1683f2d366dSniklas break; 169df930be7Sderaadt case 'L': 170df930be7Sderaadt showkey(); 171df930be7Sderaadt exit(0); 172df930be7Sderaadt case 'l': 173df930be7Sderaadt parsefmt(lfmt); 174df930be7Sderaadt fmt = 1; 175df930be7Sderaadt lfmt[0] = '\0'; 176df930be7Sderaadt break; 177df930be7Sderaadt case 'M': 178df930be7Sderaadt memf = optarg; 179df930be7Sderaadt break; 180df930be7Sderaadt case 'm': 181df930be7Sderaadt sortby = SORTMEM; 182df930be7Sderaadt break; 183df930be7Sderaadt case 'N': 184df930be7Sderaadt nlistf = optarg; 185df930be7Sderaadt break; 186df930be7Sderaadt case 'O': 187df930be7Sderaadt parsefmt(o1); 188df930be7Sderaadt parsefmt(optarg); 189df930be7Sderaadt parsefmt(o2); 190df930be7Sderaadt o1[0] = o2[0] = '\0'; 191df930be7Sderaadt fmt = 1; 192df930be7Sderaadt break; 193df930be7Sderaadt case 'o': 194df930be7Sderaadt parsefmt(optarg); 195df930be7Sderaadt fmt = 1; 196df930be7Sderaadt break; 197df930be7Sderaadt case 'p': 198df930be7Sderaadt pid = atol(optarg); 199df930be7Sderaadt xflg = 1; 200df930be7Sderaadt break; 201df930be7Sderaadt case 'r': 202df930be7Sderaadt sortby = SORTCPU; 203df930be7Sderaadt break; 204df930be7Sderaadt case 'S': 205df930be7Sderaadt sumrusage = 1; 206df930be7Sderaadt break; 207df930be7Sderaadt case 'T': 208df930be7Sderaadt if ((optarg = ttyname(STDIN_FILENO)) == NULL) 209df930be7Sderaadt errx(1, "stdin: not a terminal"); 210df930be7Sderaadt /* FALLTHROUGH */ 211df930be7Sderaadt case 't': { 212df930be7Sderaadt struct stat sb; 213df930be7Sderaadt char *ttypath, pathbuf[MAXPATHLEN]; 214df930be7Sderaadt 215df930be7Sderaadt if (strcmp(optarg, "co") == 0) 216df930be7Sderaadt ttypath = _PATH_CONSOLE; 217df930be7Sderaadt else if (*optarg != '/') 218df930be7Sderaadt (void)snprintf(ttypath = pathbuf, 219df930be7Sderaadt sizeof(pathbuf), "%s%s", _PATH_TTY, optarg); 220df930be7Sderaadt else 221df930be7Sderaadt ttypath = optarg; 222df930be7Sderaadt if (stat(ttypath, &sb) == -1) 223df930be7Sderaadt err(1, "%s", ttypath); 224df930be7Sderaadt if (!S_ISCHR(sb.st_mode)) 225df930be7Sderaadt errx(1, "%s: not a terminal", ttypath); 226df930be7Sderaadt ttydev = sb.st_rdev; 227df930be7Sderaadt break; 228df930be7Sderaadt } 22952576792Salex case 'U': 23052576792Salex pwd = getpwnam(optarg); 23152576792Salex if (pwd == NULL) 23252576792Salex errx(1, "%s: no such user", optarg); 23352576792Salex uid = pwd->pw_uid; 23452576792Salex endpwent(); 23552576792Salex xflg = 1; 23652576792Salex break; 237df930be7Sderaadt case 'u': 238df930be7Sderaadt parsefmt(ufmt); 239df930be7Sderaadt sortby = SORTCPU; 240df930be7Sderaadt fmt = 1; 241df930be7Sderaadt ufmt[0] = '\0'; 242df930be7Sderaadt break; 243df930be7Sderaadt case 'v': 244df930be7Sderaadt parsefmt(vfmt); 245df930be7Sderaadt sortby = SORTMEM; 246df930be7Sderaadt fmt = 1; 247df930be7Sderaadt vfmt[0] = '\0'; 248df930be7Sderaadt break; 249df930be7Sderaadt case 'W': 250df930be7Sderaadt swapf = optarg; 251df930be7Sderaadt break; 252df930be7Sderaadt case 'w': 253df930be7Sderaadt if (wflag) 254df930be7Sderaadt termwidth = UNLIMITED; 255df930be7Sderaadt else if (termwidth < 131) 256df930be7Sderaadt termwidth = 131; 257df930be7Sderaadt wflag++; 258df930be7Sderaadt break; 259df930be7Sderaadt case 'x': 260df930be7Sderaadt xflg = 1; 261df930be7Sderaadt break; 262df930be7Sderaadt default: 263df930be7Sderaadt usage(); 264df930be7Sderaadt } 265df930be7Sderaadt argc -= optind; 266df930be7Sderaadt argv += optind; 267df930be7Sderaadt 268df930be7Sderaadt #define BACKWARD_COMPATIBILITY 269df930be7Sderaadt #ifdef BACKWARD_COMPATIBILITY 270df930be7Sderaadt if (*argv) { 271df930be7Sderaadt nlistf = *argv; 272df930be7Sderaadt if (*++argv) { 273df930be7Sderaadt memf = *argv; 274df930be7Sderaadt if (*++argv) 275df930be7Sderaadt swapf = *argv; 276df930be7Sderaadt } 277df930be7Sderaadt } 278df930be7Sderaadt #endif 279df930be7Sderaadt /* 280df930be7Sderaadt * Discard setgid privileges if not the running kernel so that bad 281df930be7Sderaadt * guys can't print interesting stuff from kernel memory. 282df930be7Sderaadt */ 2834bd36bfbStholo if (nlistf != NULL || memf != NULL || swapf != NULL) { 2844bd36bfbStholo setegid(getgid()); 285df930be7Sderaadt setgid(getgid()); 2864bd36bfbStholo } 287df930be7Sderaadt 288df930be7Sderaadt kd = kvm_openfiles(nlistf, memf, swapf, O_RDONLY, errbuf); 289bb929088Smickey if (kd == NULL && (nlistf != NULL || memf != NULL || swapf != NULL)) 290df930be7Sderaadt errx(1, "%s", errbuf); 291df930be7Sderaadt 292e46873ebSderaadt setegid(getgid()); 293e46873ebSderaadt setgid(getgid()); 294e46873ebSderaadt 295df930be7Sderaadt if (!fmt) 296df930be7Sderaadt parsefmt(dfmt); 297df930be7Sderaadt 29852576792Salex /* XXX - should be cleaner */ 29952576792Salex if (!all && ttydev == NODEV && pid == -1 && uid == (uid_t)-1) 300df930be7Sderaadt uid = getuid(); 301df930be7Sderaadt 302df930be7Sderaadt /* 303df930be7Sderaadt * scan requested variables, noting what structures are needed, 304df930be7Sderaadt * and adjusting header widths as appropiate. 305df930be7Sderaadt */ 306df930be7Sderaadt scanvars(); 307df930be7Sderaadt /* 308df930be7Sderaadt * get proc list 309df930be7Sderaadt */ 310df930be7Sderaadt if (uid != (uid_t) -1) { 311e6592a11Sangelos what = mib[2] = KERN_PROC_UID; 312e6592a11Sangelos flag = mib[3] = uid; 313e6592a11Sangelos mibcnt = 4; 314df930be7Sderaadt } else if (ttydev != NODEV) { 315e6592a11Sangelos what = mib[2] = KERN_PROC_TTY; 316e6592a11Sangelos flag = mib[3] = ttydev; 317e6592a11Sangelos mibcnt = 4; 318df930be7Sderaadt } else if (pid != -1) { 319e6592a11Sangelos what = mib[2] = KERN_PROC_PID; 320e6592a11Sangelos flag = mib[3] = pid; 321e6592a11Sangelos mibcnt = 4; 3223f2d366dSniklas } else if (kflag) { 323e6592a11Sangelos what = mib[2] = KERN_PROC_KTHREAD; 3243f2d366dSniklas flag = 0; 325e6592a11Sangelos mibcnt = 3; 326df930be7Sderaadt } else { 327e6592a11Sangelos what = mib[2] = KERN_PROC_ALL; 328df930be7Sderaadt flag = 0; 329e6592a11Sangelos mibcnt = 3; 330df930be7Sderaadt } 331df930be7Sderaadt /* 332df930be7Sderaadt * select procs 333df930be7Sderaadt */ 334e6592a11Sangelos if (kd != NULL) { 335df930be7Sderaadt if ((kp = kvm_getprocs(kd, what, flag, &nentries)) == 0) 336df930be7Sderaadt errx(1, "%s", kvm_geterr(kd)); 337e6592a11Sangelos } 338e6592a11Sangelos else { 339e6592a11Sangelos mib[0] = CTL_KERN; 3402c41d2f9Sangelos mib[1] = KERN_NPROCS; 3412c41d2f9Sangelos size = sizeof (nproc); 3422c41d2f9Sangelos if (sysctl(mib, 2, &nproc, &size, NULL, 0) < 0) 3432c41d2f9Sangelos err(1, "could not get kern.nproc"); 3442c41d2f9Sangelos /* Allocate more memory than is needed, just in case */ 3452c41d2f9Sangelos size = (5 * nproc * sizeof(struct kinfo_proc)) / 4; 346e6592a11Sangelos kp = calloc(size, sizeof(char)); 347e6592a11Sangelos if (kp == NULL) 348e6592a11Sangelos err(1, 349e6592a11Sangelos "failed to allocated memory for proc structures"); 3502c41d2f9Sangelos mib[1] = KERN_PROC; 351e6592a11Sangelos if (sysctl(mib, mibcnt, kp, &size, NULL, 0) < 0) 352e6592a11Sangelos err(1, "could not read kern.proc"); 353e6592a11Sangelos nentries = size / sizeof(struct kinfo_proc); 354e6592a11Sangelos } 355e6592a11Sangelos 356df930be7Sderaadt if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL) 357df930be7Sderaadt err(1, NULL); 358df930be7Sderaadt for (i = nentries; --i >= 0; ++kp) { 359df930be7Sderaadt kinfo[i].ki_p = kp; 360df930be7Sderaadt saveuser(&kinfo[i]); 361df930be7Sderaadt } 362df930be7Sderaadt /* 363df930be7Sderaadt * print header 364df930be7Sderaadt */ 365df930be7Sderaadt printheader(); 366df930be7Sderaadt if (nentries == 0) 367a30d4cafSmichaels exit(1); 368df930be7Sderaadt /* 369df930be7Sderaadt * sort proc list 370df930be7Sderaadt */ 371df930be7Sderaadt qsort(kinfo, nentries, sizeof(KINFO), pscomp); 372df930be7Sderaadt /* 373df930be7Sderaadt * for each proc, call each variable output function. 374df930be7Sderaadt */ 375df930be7Sderaadt for (i = lineno = 0; i < nentries; i++) { 376df930be7Sderaadt KINFO *ki = &kinfo[i]; 377df930be7Sderaadt 378df930be7Sderaadt if (xflg == 0 && (KI_EPROC(ki)->e_tdev == NODEV || 379df930be7Sderaadt (KI_PROC(ki)->p_flag & P_CONTROLT ) == 0)) 380df930be7Sderaadt continue; 381df930be7Sderaadt for (vent = vhead; vent; vent = vent->next) { 382df930be7Sderaadt (vent->var->oproc)(ki, vent); 383df930be7Sderaadt if (vent->next != NULL) 384df930be7Sderaadt (void)putchar(' '); 385df930be7Sderaadt } 386df930be7Sderaadt (void)putchar('\n'); 387df930be7Sderaadt if (prtheader && lineno++ == prtheader - 4) { 388df930be7Sderaadt (void)putchar('\n'); 389df930be7Sderaadt printheader(); 390df930be7Sderaadt lineno = 0; 391df930be7Sderaadt } 392df930be7Sderaadt } 393df930be7Sderaadt exit(eval); 394df930be7Sderaadt } 395df930be7Sderaadt 396df930be7Sderaadt static void 397df930be7Sderaadt scanvars() 398df930be7Sderaadt { 399df930be7Sderaadt struct varent *vent; 400df930be7Sderaadt VAR *v; 401df930be7Sderaadt int i; 402df930be7Sderaadt 403df930be7Sderaadt for (vent = vhead; vent; vent = vent->next) { 404df930be7Sderaadt v = vent->var; 405df930be7Sderaadt i = strlen(v->header); 406df930be7Sderaadt if (v->width < i) 407df930be7Sderaadt v->width = i; 408df930be7Sderaadt totwidth += v->width + 1; /* +1 for space */ 409df930be7Sderaadt if (v->flag & COMM) 410df930be7Sderaadt needcomm = 1; 411df930be7Sderaadt } 412df930be7Sderaadt totwidth--; 413df930be7Sderaadt } 414df930be7Sderaadt 415df930be7Sderaadt static void 416df930be7Sderaadt saveuser(ki) 417df930be7Sderaadt KINFO *ki; 418df930be7Sderaadt { 419df930be7Sderaadt struct pstats pstats; 420df930be7Sderaadt struct usave *usp; 421df930be7Sderaadt 422df930be7Sderaadt usp = &ki->ki_u; 423bb929088Smickey if (kd != NULL && kvm_read(kd, (u_long)&KI_PROC(ki)->p_addr->u_stats, 424980f60fcSart &pstats, sizeof(pstats)) == sizeof(pstats)) { 425df930be7Sderaadt /* 426df930be7Sderaadt * The u-area might be swapped out, and we can't get 427df930be7Sderaadt * at it because we have a crashdump and no swap. 428df930be7Sderaadt * If it's here fill in these fields, otherwise, just 429df930be7Sderaadt * leave them 0. 430df930be7Sderaadt */ 431df930be7Sderaadt usp->u_start = pstats.p_start; 432df930be7Sderaadt usp->u_ru = pstats.p_ru; 433df930be7Sderaadt usp->u_cru = pstats.p_cru; 434df930be7Sderaadt usp->u_valid = 1; 435df930be7Sderaadt } else 436df930be7Sderaadt usp->u_valid = 0; 437df930be7Sderaadt } 438df930be7Sderaadt 439df930be7Sderaadt static int 440df930be7Sderaadt pscomp(a, b) 441df930be7Sderaadt const void *a, *b; 442df930be7Sderaadt { 443df930be7Sderaadt int i; 444df930be7Sderaadt #define VSIZE(k) (KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize + \ 445df930be7Sderaadt KI_EPROC(k)->e_vm.vm_tsize) 446fffbb510Smillert #define STARTTIME(k) (k->ki_u.u_start.tv_sec) 447fffbb510Smillert #define STARTuTIME(k) (k->ki_u.u_start.tv_usec) 448df930be7Sderaadt 449df930be7Sderaadt if (sortby == SORTCPU) 450df930be7Sderaadt return (getpcpu((KINFO *)b) - getpcpu((KINFO *)a)); 451df930be7Sderaadt if (sortby == SORTMEM) 452df930be7Sderaadt return (VSIZE((KINFO *)b) - VSIZE((KINFO *)a)); 4534527c594Smillert i = KI_EPROC((KINFO *)a)->e_tdev - KI_EPROC((KINFO *)b)->e_tdev; 4544527c594Smillert if (i == 0) 455fffbb510Smillert i = STARTTIME(((KINFO *)a)) - STARTTIME(((KINFO *)b)); 456fffbb510Smillert if (i == 0) 457fffbb510Smillert i = STARTuTIME(((KINFO *)a)) - STARTuTIME(((KINFO *)b)); 458fffbb510Smillert return (i); 459fffbb510Smillert } 460df930be7Sderaadt 461df930be7Sderaadt /* 462df930be7Sderaadt * ICK (all for getopt), would rather hide the ugliness 463df930be7Sderaadt * here than taint the main code. 464df930be7Sderaadt * 465df930be7Sderaadt * ps foo -> ps -foo 466df930be7Sderaadt * ps 34 -> ps -p34 467df930be7Sderaadt * 468df930be7Sderaadt * The old convention that 't' with no trailing tty arg means the users 469df930be7Sderaadt * tty, is only supported if argv[1] doesn't begin with a '-'. This same 470df930be7Sderaadt * feature is available with the option 'T', which takes no argument. 471df930be7Sderaadt */ 472df930be7Sderaadt static char * 473df930be7Sderaadt kludge_oldps_options(s) 474df930be7Sderaadt char *s; 475df930be7Sderaadt { 476df930be7Sderaadt size_t len; 477df930be7Sderaadt char *newopts, *ns, *cp; 478df930be7Sderaadt 479df930be7Sderaadt len = strlen(s); 4804c163512Sderaadt if ((newopts = ns = malloc(len + 3)) == NULL) 481df930be7Sderaadt err(1, NULL); 482df930be7Sderaadt /* 483df930be7Sderaadt * options begin with '-' 484df930be7Sderaadt */ 485df930be7Sderaadt if (*s != '-') 486df930be7Sderaadt *ns++ = '-'; /* add option flag */ 487df930be7Sderaadt /* 488df930be7Sderaadt * gaze to end of argv[1] 489df930be7Sderaadt */ 490df930be7Sderaadt cp = s + len - 1; 491df930be7Sderaadt /* 492df930be7Sderaadt * if last letter is a 't' flag with no argument (in the context 493df930be7Sderaadt * of the oldps options -- option string NOT starting with a '-' -- 494df930be7Sderaadt * then convert to 'T' (meaning *this* terminal, i.e. ttyname(0)). 495df930be7Sderaadt */ 496df930be7Sderaadt if (*cp == 't' && *s != '-') 497df930be7Sderaadt *cp = 'T'; 498df930be7Sderaadt else { 499df930be7Sderaadt /* 500df930be7Sderaadt * otherwise check for trailing number, which *may* be a 501df930be7Sderaadt * pid. 502df930be7Sderaadt */ 503df930be7Sderaadt while (cp >= s && isdigit(*cp)) 504df930be7Sderaadt --cp; 505df930be7Sderaadt } 506df930be7Sderaadt cp++; 507df930be7Sderaadt memmove(ns, s, (size_t)(cp - s)); /* copy up to trailing number */ 508df930be7Sderaadt ns += cp - s; 509df930be7Sderaadt /* 510df930be7Sderaadt * if there's a trailing number, and not a preceding 'p' (pid) or 511df930be7Sderaadt * 't' (tty) flag, then assume it's a pid and insert a 'p' flag. 512df930be7Sderaadt */ 513764064c4Smickey if (isdigit(*cp) && (cp == s || (cp[-1] != 't' && cp[-1] != 'p' && 514764064c4Smickey (cp - 1 == s || cp[-2] != 't')))) 515df930be7Sderaadt *ns++ = 'p'; 516df930be7Sderaadt (void)strcpy(ns, cp); /* and append the number */ 517df930be7Sderaadt 518df930be7Sderaadt return (newopts); 519df930be7Sderaadt } 520df930be7Sderaadt 521df930be7Sderaadt static void 522df930be7Sderaadt usage() 523df930be7Sderaadt { 524df930be7Sderaadt (void)fprintf(stderr, 5259517852aSmpech "usage: %s [-][aChjlmrSTuvwx] [-O|o fmt] [-p pid] [-t tty] [-U user]\n", 5269517852aSmpech __progname); 5279517852aSmpech (void)fprintf(stderr, 5289517852aSmpech "%-*s[-M core] [-N system] [-W swap]\n", strlen(__progname) + 8, ""); 5299517852aSmpech (void)fprintf(stderr, " %s [-L]\n", __progname); 530df930be7Sderaadt exit(1); 531df930be7Sderaadt } 532