11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1990, 1993, 1994 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * Redistribution and use in source and binary forms, with or without 61556Srgrimes * modification, are permitted provided that the following conditions 71556Srgrimes * are met: 81556Srgrimes * 1. Redistributions of source code must retain the above copyright 91556Srgrimes * notice, this list of conditions and the following disclaimer. 101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111556Srgrimes * notice, this list of conditions and the following disclaimer in the 121556Srgrimes * documentation and/or other materials provided with the distribution. 131556Srgrimes * 4. Neither the name of the University nor the names of its contributors 141556Srgrimes * may be used to endorse or promote products derived from this software 151556Srgrimes * without specific prior written permission. 161556Srgrimes * 171556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271556Srgrimes * SUCH DAMAGE. 281556Srgrimes */ 291556Srgrimes 3090143Smarkm#if 0 311556Srgrimes#ifndef lint 3228052Sstevestatic char sccsid[] = "@(#)keyword.c 8.5 (Berkeley) 4/2/94"; 3390143Smarkm#endif /* not lint */ 3428052Ssteve#endif 3599110Sobrien#include <sys/cdefs.h> 3699110Sobrien__FBSDID("$FreeBSD$"); 371556Srgrimes 381556Srgrimes#include <sys/param.h> 391556Srgrimes#include <sys/time.h> 401556Srgrimes#include <sys/resource.h> 411556Srgrimes#include <sys/proc.h> 4228054Ssteve#include <sys/sysctl.h> 4328054Ssteve#include <sys/user.h> 441556Srgrimes 451556Srgrimes#include <err.h> 461556Srgrimes#include <stddef.h> 471556Srgrimes#include <stdio.h> 481556Srgrimes#include <stdlib.h> 491556Srgrimes#include <string.h> 501556Srgrimes 511556Srgrimes#include "ps.h" 521556Srgrimes 53109504Sjmallettstatic VAR *findvar(char *, int, char **header); 5490110Simpstatic int vcmp(const void *, const void *); 551556Srgrimes 561556Srgrimes/* Compute offset in common structures. */ 5769896Smckusick#define KOFF(x) offsetof(struct kinfo_proc, x) 581556Srgrimes#define ROFF(x) offsetof(struct rusage, x) 591556Srgrimes 60130827Sgad#define LWPFMT "d" 61130827Sgad#define NLWPFMT "d" 621556Srgrimes#define UIDFMT "u" 631556Srgrimes#define PIDFMT "d" 641556Srgrimes 65110411Ssobomax/* PLEASE KEEP THE TABLE BELOW SORTED ALPHABETICALLY!!! */ 6690143Smarkmstatic VAR var[] = { 67235891Strasz {"%cpu", "%CPU", NULL, 0, pcpu, 0, CHAR, NULL, 0}, 68235891Strasz {"%mem", "%MEM", NULL, 0, pmem, 0, CHAR, NULL, 0}, 69235891Strasz {"acflag", "ACFLG", NULL, 0, kvar, KOFF(ki_acflag), USHORT, "x", 0}, 70235891Strasz {"acflg", "", "acflag", 0, NULL, 0, CHAR, NULL, 0}, 71235891Strasz {"args", "COMMAND", NULL, COMM|LJUST|USER, arguments, 0, 7297958Sjmallett CHAR, NULL, 0}, 73235891Strasz {"blocked", "", "sigmask", 0, NULL, 0, CHAR, NULL, 0}, 74235891Strasz {"caught", "", "sigcatch", 0, NULL, 0, CHAR, NULL, 0}, 75235891Strasz {"class", "CLASS", NULL, LJUST, loginclass, 0, CHAR, NULL, 0}, 76235891Strasz {"comm", "COMMAND", NULL, LJUST, ucomm, 0, CHAR, NULL, 0}, 77235891Strasz {"command", "COMMAND", NULL, COMM|LJUST|USER, command, 0, 7897850Sjmallett CHAR, NULL, 0}, 79236293Skib {"cow", "COW", NULL, 0, kvar, KOFF(ki_cow), UINT, "u", 0}, 80235891Strasz {"cpu", "CPU", NULL, 0, kvar, KOFF(ki_estcpu), UINT, "d", 0}, 81235891Strasz {"cputime", "", "time", 0, NULL, 0, CHAR, NULL, 0}, 82241158Szont {"dsiz", "DSIZ", NULL, 0, kvar, KOFF(ki_dsize), PGTOK, "ld", 0}, 83235891Strasz {"egid", "", "gid", 0, NULL, 0, CHAR, NULL, 0}, 84235891Strasz {"egroup", "", "group", 0, NULL, 0, CHAR, NULL, 0}, 85235891Strasz {"emul", "EMUL", NULL, LJUST, emulname, 0, CHAR, NULL, 0}, 86235891Strasz {"etime", "ELAPSED", NULL, USER, elapsed, 0, CHAR, NULL, 0}, 87235891Strasz {"etimes", "ELAPSED", NULL, USER, elapseds, 0, CHAR, NULL, 0}, 88235891Strasz {"euid", "", "uid", 0, NULL, 0, CHAR, NULL, 0}, 89235891Strasz {"f", "F", NULL, 0, kvar, KOFF(ki_flag), INT, "x", 0}, 90235891Strasz {"flags", "", "f", 0, NULL, 0, CHAR, NULL, 0}, 91235891Strasz {"gid", "GID", NULL, 0, kvar, KOFF(ki_groups), UINT, UIDFMT, 0}, 92235891Strasz {"group", "GROUP", NULL, LJUST, egroupname, 0, CHAR, NULL, 0}, 93235891Strasz {"ignored", "", "sigignore", 0, NULL, 0, CHAR, NULL, 0}, 94235891Strasz {"inblk", "INBLK", NULL, USER, rvar, ROFF(ru_inblock), LONG, "ld", 0}, 95235891Strasz {"inblock", "", "inblk", 0, NULL, 0, CHAR, NULL, 0}, 96235891Strasz {"jid", "JID", NULL, 0, kvar, KOFF(ki_jid), INT, "d", 0}, 97235891Strasz {"jobc", "JOBC", NULL, 0, kvar, KOFF(ki_jobc), SHORT, "d", 0}, 98235891Strasz {"ktrace", "KTRACE", NULL, 0, kvar, KOFF(ki_traceflag), INT, "x", 0}, 99235891Strasz {"label", "LABEL", NULL, LJUST, label, 0, CHAR, NULL, 0}, 100235891Strasz {"lim", "LIM", NULL, 0, maxrss, 0, CHAR, NULL, 0}, 101235891Strasz {"lockname", "LOCK", NULL, LJUST, lockname, 0, CHAR, NULL, 0}, 102235891Strasz {"login", "LOGIN", NULL, LJUST, logname, 0, CHAR, NULL, 0}, 103235891Strasz {"logname", "", "login", 0, NULL, 0, CHAR, NULL, 0}, 104235891Strasz {"lstart", "STARTED", NULL, LJUST|USER, lstarted, 0, CHAR, NULL, 0}, 105235891Strasz {"lwp", "LWP", NULL, 0, kvar, KOFF(ki_tid), UINT, LWPFMT, 0}, 106235891Strasz {"majflt", "MAJFLT", NULL, USER, rvar, ROFF(ru_majflt), LONG, "ld", 0}, 107235891Strasz {"minflt", "MINFLT", NULL, USER, rvar, ROFF(ru_minflt), LONG, "ld", 0}, 108235891Strasz {"msgrcv", "MSGRCV", NULL, USER, rvar, ROFF(ru_msgrcv), LONG, "ld", 0}, 109235891Strasz {"msgsnd", "MSGSND", NULL, USER, rvar, ROFF(ru_msgsnd), LONG, "ld", 0}, 110235891Strasz {"mwchan", "MWCHAN", NULL, LJUST, mwchan, 0, CHAR, NULL, 0}, 111235891Strasz {"ni", "", "nice", 0, NULL, 0, CHAR, NULL, 0}, 112235891Strasz {"nice", "NI", NULL, 0, kvar, KOFF(ki_nice), CHAR, "d", 0}, 113235891Strasz {"nivcsw", "NIVCSW", NULL, USER, rvar, ROFF(ru_nivcsw), LONG, "ld", 0}, 114235891Strasz {"nlwp", "NLWP", NULL, 0, kvar, KOFF(ki_numthreads), UINT, NLWPFMT, 0}, 115235891Strasz {"nsignals", "", "nsigs", 0, NULL, 0, CHAR, NULL, 0}, 116235891Strasz {"nsigs", "NSIGS", NULL, USER, rvar, ROFF(ru_nsignals), LONG, "ld", 0}, 117235891Strasz {"nswap", "NSWAP", NULL, USER, rvar, ROFF(ru_nswap), LONG, "ld", 0}, 118235891Strasz {"nvcsw", "NVCSW", NULL, USER, rvar, ROFF(ru_nvcsw), LONG, "ld", 0}, 119235891Strasz {"nwchan", "NWCHAN", NULL, LJUST, nwchan, 0, CHAR, NULL, 0}, 120235891Strasz {"oublk", "OUBLK", NULL, USER, rvar, ROFF(ru_oublock), LONG, "ld", 0}, 121235891Strasz {"oublock", "", "oublk", 0, NULL, 0, CHAR, NULL, 0}, 122235891Strasz {"paddr", "PADDR", NULL, 0, kvar, KOFF(ki_paddr), KPTR, "lx", 0}, 123235891Strasz {"pagein", "PAGEIN", NULL, USER, pagein, 0, CHAR, NULL, 0}, 124235891Strasz {"pcpu", "", "%cpu", 0, NULL, 0, CHAR, NULL, 0}, 125235891Strasz {"pending", "", "sig", 0, NULL, 0, CHAR, NULL, 0}, 126235891Strasz {"pgid", "PGID", NULL, 0, kvar, KOFF(ki_pgid), UINT, PIDFMT, 0}, 127235891Strasz {"pid", "PID", NULL, 0, kvar, KOFF(ki_pid), UINT, PIDFMT, 0}, 128235891Strasz {"pmem", "", "%mem", 0, NULL, 0, CHAR, NULL, 0}, 129235891Strasz {"ppid", "PPID", NULL, 0, kvar, KOFF(ki_ppid), UINT, PIDFMT, 0}, 130235891Strasz {"pri", "PRI", NULL, 0, pri, 0, CHAR, NULL, 0}, 131235891Strasz {"re", "RE", NULL, INF127, kvar, KOFF(ki_swtime), UINT, "d", 0}, 132235891Strasz {"rgid", "RGID", NULL, 0, kvar, KOFF(ki_rgid), UINT, UIDFMT, 0}, 133235891Strasz {"rgroup", "RGROUP", NULL, LJUST, rgroupname, 0, CHAR, NULL, 0}, 134235891Strasz {"rss", "RSS", NULL, 0, kvar, KOFF(ki_rssize), PGTOK, "ld", 0}, 135235891Strasz {"rtprio", "RTPRIO", NULL, 0, priorityr, KOFF(ki_pri), CHAR, NULL, 0}, 136235891Strasz {"ruid", "RUID", NULL, 0, kvar, KOFF(ki_ruid), UINT, UIDFMT, 0}, 137235891Strasz {"ruser", "RUSER", NULL, LJUST, runame, 0, CHAR, NULL, 0}, 138235891Strasz {"sid", "SID", NULL, 0, kvar, KOFF(ki_sid), UINT, PIDFMT, 0}, 139235891Strasz {"sig", "PENDING", NULL, 0, kvar, KOFF(ki_siglist), INT, "x", 0}, 140235891Strasz {"sigcatch", "CAUGHT", NULL, 0, kvar, KOFF(ki_sigcatch), UINT, "x", 0}, 141235891Strasz {"sigignore", "IGNORED", NULL, 0, kvar, KOFF(ki_sigignore), 14290143Smarkm UINT, "x", 0}, 143235891Strasz {"sigmask", "BLOCKED", NULL, 0, kvar, KOFF(ki_sigmask), UINT, "x", 0}, 144235891Strasz {"sl", "SL", NULL, INF127, kvar, KOFF(ki_slptime), UINT, "d", 0}, 145241158Szont {"ssiz", "SSIZ", NULL, 0, kvar, KOFF(ki_ssize), PGTOK, "ld", 0}, 146235891Strasz {"start", "STARTED", NULL, LJUST|USER, started, 0, CHAR, NULL, 0}, 147235891Strasz {"stat", "", "state", 0, NULL, 0, CHAR, NULL, 0}, 148235891Strasz {"state", "STAT", NULL, LJUST, state, 0, CHAR, NULL, 0}, 149235891Strasz {"svgid", "SVGID", NULL, 0, kvar, KOFF(ki_svgid), UINT, UIDFMT, 0}, 150235891Strasz {"svuid", "SVUID", NULL, 0, kvar, KOFF(ki_svuid), UINT, UIDFMT, 0}, 151235891Strasz {"systime", "SYSTIME", NULL, USER, systime, 0, CHAR, NULL, 0}, 152235891Strasz {"tdaddr", "TDADDR", NULL, 0, kvar, KOFF(ki_tdaddr), KPTR, "lx", 0}, 153235891Strasz {"tdev", "TDEV", NULL, 0, tdev, 0, CHAR, NULL, 0}, 154235891Strasz {"tdnam", "TDNAM", NULL, LJUST, tdnam, 0, CHAR, NULL, 0}, 155235891Strasz {"time", "TIME", NULL, USER, cputime, 0, CHAR, NULL, 0}, 156235891Strasz {"tpgid", "TPGID", NULL, 0, kvar, KOFF(ki_tpgid), UINT, PIDFMT, 0}, 157235891Strasz {"tsid", "TSID", NULL, 0, kvar, KOFF(ki_tsid), UINT, PIDFMT, 0}, 158235891Strasz {"tsiz", "TSIZ", NULL, 0, kvar, KOFF(ki_tsize), PGTOK, "ld", 0}, 159235891Strasz {"tt", "TT ", NULL, 0, tname, 0, CHAR, NULL, 0}, 160235891Strasz {"tty", "TTY", NULL, LJUST, longtname, 0, CHAR, NULL, 0}, 161235891Strasz {"ucomm", "UCOMM", NULL, LJUST, ucomm, 0, CHAR, NULL, 0}, 162235891Strasz {"uid", "UID", NULL, 0, kvar, KOFF(ki_uid), UINT, UIDFMT, 0}, 163235891Strasz {"upr", "UPR", NULL, 0, upr, 0, CHAR, NULL, 0}, 164235891Strasz {"uprocp", "UPROCP", NULL, 0, kvar, KOFF(ki_paddr), KPTR, "lx", 0}, 165235891Strasz {"user", "USER", NULL, LJUST, uname, 0, CHAR, NULL, 0}, 166235891Strasz {"usertime", "USERTIME", NULL, USER, usertime, 0, CHAR, NULL, 0}, 167235891Strasz {"usrpri", "", "upr", 0, NULL, 0, CHAR, NULL, 0}, 168235891Strasz {"vsize", "", "vsz", 0, NULL, 0, CHAR, NULL, 0}, 169235891Strasz {"vsz", "VSZ", NULL, 0, vsize, 0, CHAR, NULL, 0}, 170235891Strasz {"wchan", "WCHAN", NULL, LJUST, wchan, 0, CHAR, NULL, 0}, 171235891Strasz {"xstat", "XSTAT", NULL, 0, kvar, KOFF(ki_xstat), USHORT, "x", 0}, 172235891Strasz {"", NULL, NULL, 0, NULL, 0, CHAR, NULL, 0}, 1731556Srgrimes}; 1741556Srgrimes 1751556Srgrimesvoid 17690110Simpshowkey(void) 1771556Srgrimes{ 1781556Srgrimes VAR *v; 1791556Srgrimes int i; 18090143Smarkm const char *p, *sep; 1811556Srgrimes 1821556Srgrimes i = 0; 1831556Srgrimes sep = ""; 1841556Srgrimes for (v = var; *(p = v->name); ++v) { 1851556Srgrimes int len = strlen(p); 1861556Srgrimes if (termwidth && (i += len + 1) > termwidth) { 1871556Srgrimes i = len; 1881556Srgrimes sep = "\n"; 1891556Srgrimes } 1901556Srgrimes (void) printf("%s%s", sep, p); 1911556Srgrimes sep = " "; 1921556Srgrimes } 1931556Srgrimes (void) printf("\n"); 1941556Srgrimes} 1951556Srgrimes 1961556Srgrimesvoid 197109502Sjmallettparsefmt(const char *p, int user) 1981556Srgrimes{ 19990143Smarkm char *tempstr, *tempstr1; 2001556Srgrimes 20198050Sjmallett#define FMTSEP " \t,\n" 20290143Smarkm tempstr1 = tempstr = strdup(p); 20390143Smarkm while (tempstr && *tempstr) { 204109504Sjmallett char *cp, *hp; 2051556Srgrimes VAR *v; 2061556Srgrimes struct varent *vent; 2071556Srgrimes 20897944Sjmallett /* 20998050Sjmallett * If an item contains an equals sign, it specifies a column 21098050Sjmallett * header, may contain embedded separator characters and 21198050Sjmallett * is always the last item. 21297944Sjmallett */ 21398050Sjmallett if (tempstr[strcspn(tempstr, "="FMTSEP)] != '=') 21498050Sjmallett while ((cp = strsep(&tempstr, FMTSEP)) != NULL && 21598050Sjmallett *cp == '\0') 21698050Sjmallett /* void */; 21798050Sjmallett else { 21898050Sjmallett cp = tempstr; 21998050Sjmallett tempstr = NULL; 22098050Sjmallett } 221109504Sjmallett if (cp == NULL || !(v = findvar(cp, user, &hp))) 2221556Srgrimes continue; 223109502Sjmallett if (!user) { 224109502Sjmallett /* 225109502Sjmallett * If the user is NOT adding this field manually, 226109502Sjmallett * get on with our lives if this VAR is already 227109502Sjmallett * represented in the list. 228109502Sjmallett */ 229109502Sjmallett vent = find_varentry(v); 230109502Sjmallett if (vent != NULL) 231109502Sjmallett continue; 232109502Sjmallett } 2331556Srgrimes if ((vent = malloc(sizeof(struct varent))) == NULL) 23497877Sjmallett errx(1, "malloc failed"); 235109504Sjmallett vent->header = v->header; 236109504Sjmallett if (hp) { 237109504Sjmallett hp = strdup(hp); 238109504Sjmallett if (hp) 239109504Sjmallett vent->header = hp; 240109504Sjmallett } 24197848Sjmallett vent->var = malloc(sizeof(*vent->var)); 24297848Sjmallett if (vent->var == NULL) 24397877Sjmallett errx(1, "malloc failed"); 24497848Sjmallett memcpy(vent->var, v, sizeof(*vent->var)); 245130999Sgad STAILQ_INSERT_TAIL(&varlist, vent, next_ve); 2461556Srgrimes } 24790143Smarkm free(tempstr1); 248130999Sgad if (STAILQ_EMPTY(&varlist)) { 249104026Sjmallett warnx("no valid keywords; valid keywords:"); 250104026Sjmallett showkey(); 251104026Sjmallett exit(1); 252104026Sjmallett } 2531556Srgrimes} 2541556Srgrimes 2551556Srgrimesstatic VAR * 256109504Sjmallettfindvar(char *p, int user, char **header) 2571556Srgrimes{ 258156423Sgad size_t rflen; 2591556Srgrimes VAR *v, key; 260156423Sgad char *hp, *realfmt; 2611556Srgrimes 2621556Srgrimes hp = strchr(p, '='); 2631556Srgrimes if (hp) 2641556Srgrimes *hp++ = '\0'; 2651556Srgrimes 2661556Srgrimes key.name = p; 2671556Srgrimes v = bsearch(&key, var, sizeof(var)/sizeof(VAR) - 1, sizeof(VAR), vcmp); 2681556Srgrimes 2691556Srgrimes if (v && v->alias) { 270156423Sgad /* 271157559Sgad * If the user specified an alternate-header for this 272157559Sgad * (aliased) format-name, then we need to copy that 273157559Sgad * alternate-header when making the recursive call to 274157559Sgad * process the alias. 275156423Sgad */ 276157559Sgad if (hp == NULL) 277157559Sgad parsefmt(v->alias, user); 278157559Sgad else { 279157559Sgad /* 280157559Sgad * XXX - This processing will not be correct for 281157559Sgad * any alias which expands into a list of format 282157559Sgad * keywords. Presently there are no aliases 283157559Sgad * which do that. 284157559Sgad */ 285157559Sgad rflen = strlen(v->alias) + strlen(hp) + 2; 286157559Sgad realfmt = malloc(rflen); 287189078Sattilio if (realfmt == NULL) 288189078Sattilio errx(1, "malloc failed"); 289157559Sgad snprintf(realfmt, rflen, "%s=%s", v->alias, hp); 290157559Sgad parsefmt(realfmt, user); 291199351Snetchild free(realfmt); 292157559Sgad } 2931556Srgrimes return ((VAR *)NULL); 2941556Srgrimes } 2951556Srgrimes if (!v) { 2961556Srgrimes warnx("%s: keyword not found", p); 2971556Srgrimes eval = 1; 298109504Sjmallett } 299109504Sjmallett if (header) 300109504Sjmallett *header = hp; 3011556Srgrimes return (v); 3021556Srgrimes} 3031556Srgrimes 3041556Srgrimesstatic int 30590110Simpvcmp(const void *a, const void *b) 3061556Srgrimes{ 30790143Smarkm return (strcmp(((const VAR *)a)->name, ((const VAR *)b)->name)); 3081556Srgrimes} 309