1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * ps -- print things about processes. 35*7c478bd9Sstevel@tonic-gate */ 36*7c478bd9Sstevel@tonic-gate #include <stdio.h> 37*7c478bd9Sstevel@tonic-gate #include <ctype.h> 38*7c478bd9Sstevel@tonic-gate #include <string.h> 39*7c478bd9Sstevel@tonic-gate #include <errno.h> 40*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 41*7c478bd9Sstevel@tonic-gate #include <pwd.h> 42*7c478bd9Sstevel@tonic-gate #include <grp.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 46*7c478bd9Sstevel@tonic-gate #include <unistd.h> 47*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 48*7c478bd9Sstevel@tonic-gate #include <limits.h> 49*7c478bd9Sstevel@tonic-gate #include <dirent.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/fault.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 54*7c478bd9Sstevel@tonic-gate #include <procfs.h> 55*7c478bd9Sstevel@tonic-gate #include <locale.h> 56*7c478bd9Sstevel@tonic-gate #include <wctype.h> 57*7c478bd9Sstevel@tonic-gate #include <wchar.h> 58*7c478bd9Sstevel@tonic-gate #include <libw.h> 59*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/pset.h> 62*7c478bd9Sstevel@tonic-gate #include <project.h> 63*7c478bd9Sstevel@tonic-gate #include <zone.h> 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #define min(a, b) ((a) > (b) ? (b) : (a)) 66*7c478bd9Sstevel@tonic-gate #define max(a, b) ((a) < (b) ? (b) : (a)) 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate #define NTTYS 20 /* initial size of table for -t option */ 69*7c478bd9Sstevel@tonic-gate #define SIZ 30 /* initial size of tables for -p, -s, -g, and -z */ 70*7c478bd9Sstevel@tonic-gate #define ARGSIZ 30 /* size of buffer holding args for -t, -p, -u options */ 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate #define MAXUGNAME 10 /* max chars in a user/group name or printed u/g id */ 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate /* Structure for storing user or group info */ 75*7c478bd9Sstevel@tonic-gate struct ugdata { 76*7c478bd9Sstevel@tonic-gate id_t id; /* numeric user-id or group-id */ 77*7c478bd9Sstevel@tonic-gate char name[MAXUGNAME+1]; /* user/group name, null terminated */ 78*7c478bd9Sstevel@tonic-gate }; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate struct ughead { 81*7c478bd9Sstevel@tonic-gate size_t size; /* number of ugdata structs allocated */ 82*7c478bd9Sstevel@tonic-gate size_t nent; /* number of active entries */ 83*7c478bd9Sstevel@tonic-gate struct ugdata *ent; /* pointer to array of actual entries */ 84*7c478bd9Sstevel@tonic-gate }; 85*7c478bd9Sstevel@tonic-gate 86*7c478bd9Sstevel@tonic-gate enum fname { /* enumeration of field names */ 87*7c478bd9Sstevel@tonic-gate F_USER, /* effective user of the process */ 88*7c478bd9Sstevel@tonic-gate F_RUSER, /* real user of the process */ 89*7c478bd9Sstevel@tonic-gate F_GROUP, /* effective group of the process */ 90*7c478bd9Sstevel@tonic-gate F_RGROUP, /* real group of the process */ 91*7c478bd9Sstevel@tonic-gate F_UID, /* numeric effective uid of the process */ 92*7c478bd9Sstevel@tonic-gate F_RUID, /* numeric real uid of the process */ 93*7c478bd9Sstevel@tonic-gate F_GID, /* numeric effective gid of the process */ 94*7c478bd9Sstevel@tonic-gate F_RGID, /* numeric real gid of the process */ 95*7c478bd9Sstevel@tonic-gate F_PID, /* process id */ 96*7c478bd9Sstevel@tonic-gate F_PPID, /* parent process id */ 97*7c478bd9Sstevel@tonic-gate F_PGID, /* process group id */ 98*7c478bd9Sstevel@tonic-gate F_SID, /* session id */ 99*7c478bd9Sstevel@tonic-gate F_PSR, /* bound processor */ 100*7c478bd9Sstevel@tonic-gate F_LWP, /* lwp-id */ 101*7c478bd9Sstevel@tonic-gate F_NLWP, /* number of lwps */ 102*7c478bd9Sstevel@tonic-gate F_OPRI, /* old priority (obsolete) */ 103*7c478bd9Sstevel@tonic-gate F_PRI, /* new priority */ 104*7c478bd9Sstevel@tonic-gate F_F, /* process flags */ 105*7c478bd9Sstevel@tonic-gate F_S, /* letter indicating the state */ 106*7c478bd9Sstevel@tonic-gate F_C, /* processor utilization (obsolete) */ 107*7c478bd9Sstevel@tonic-gate F_PCPU, /* percent of recently used cpu time */ 108*7c478bd9Sstevel@tonic-gate F_PMEM, /* percent of physical memory used (rss) */ 109*7c478bd9Sstevel@tonic-gate F_OSZ, /* virtual size of the process in pages */ 110*7c478bd9Sstevel@tonic-gate F_VSZ, /* virtual size of the process in kilobytes */ 111*7c478bd9Sstevel@tonic-gate F_RSS, /* resident set size of the process in kilobytes */ 112*7c478bd9Sstevel@tonic-gate F_NICE, /* "nice" value of the process */ 113*7c478bd9Sstevel@tonic-gate F_CLASS, /* scheduler class */ 114*7c478bd9Sstevel@tonic-gate F_STIME, /* start time of the process, hh:mm:ss or Month Day */ 115*7c478bd9Sstevel@tonic-gate F_ETIME, /* elapsed time of the process, [[dd-]hh:]mm:ss */ 116*7c478bd9Sstevel@tonic-gate F_TIME, /* cpu time of the process, [[dd-]hh:]mm:ss */ 117*7c478bd9Sstevel@tonic-gate F_TTY, /* name of the controlling terminal */ 118*7c478bd9Sstevel@tonic-gate F_ADDR, /* address of the process (obsolete) */ 119*7c478bd9Sstevel@tonic-gate F_WCHAN, /* wait channel (sleep condition variable) */ 120*7c478bd9Sstevel@tonic-gate F_FNAME, /* file name of command */ 121*7c478bd9Sstevel@tonic-gate F_COMM, /* name of command (argv[0] value) */ 122*7c478bd9Sstevel@tonic-gate F_ARGS, /* name of command plus all its arguments */ 123*7c478bd9Sstevel@tonic-gate F_TASKID, /* task id */ 124*7c478bd9Sstevel@tonic-gate F_PROJID, /* project id */ 125*7c478bd9Sstevel@tonic-gate F_PROJECT, /* project name of the process */ 126*7c478bd9Sstevel@tonic-gate F_PSET, /* bound processor set */ 127*7c478bd9Sstevel@tonic-gate F_ZONE, /* zone name */ 128*7c478bd9Sstevel@tonic-gate F_ZONEID, /* zone id */ 129*7c478bd9Sstevel@tonic-gate F_CTID /* process contract id */ 130*7c478bd9Sstevel@tonic-gate }; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate struct field { 133*7c478bd9Sstevel@tonic-gate struct field *next; /* linked list */ 134*7c478bd9Sstevel@tonic-gate int fname; /* field index */ 135*7c478bd9Sstevel@tonic-gate const char *header; /* header to use */ 136*7c478bd9Sstevel@tonic-gate int width; /* width of field */ 137*7c478bd9Sstevel@tonic-gate }; 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate static struct field *fields = NULL; /* fields selected via -o */ 140*7c478bd9Sstevel@tonic-gate static struct field *last_field = NULL; 141*7c478bd9Sstevel@tonic-gate static int do_header = 0; 142*7c478bd9Sstevel@tonic-gate static struct timeval now; 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* array of defined fields, in fname order */ 145*7c478bd9Sstevel@tonic-gate struct def_field { 146*7c478bd9Sstevel@tonic-gate const char *fname; 147*7c478bd9Sstevel@tonic-gate const char *header; 148*7c478bd9Sstevel@tonic-gate int width; 149*7c478bd9Sstevel@tonic-gate int minwidth; 150*7c478bd9Sstevel@tonic-gate }; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate static struct def_field fname[] = { 153*7c478bd9Sstevel@tonic-gate /* fname header width minwidth */ 154*7c478bd9Sstevel@tonic-gate { "user", "USER", 8, 8 }, 155*7c478bd9Sstevel@tonic-gate { "ruser", "RUSER", 8, 8 }, 156*7c478bd9Sstevel@tonic-gate { "group", "GROUP", 8, 8 }, 157*7c478bd9Sstevel@tonic-gate { "rgroup", "RGROUP", 8, 8 }, 158*7c478bd9Sstevel@tonic-gate { "uid", "UID", 5, 5 }, 159*7c478bd9Sstevel@tonic-gate { "ruid", "RUID", 5, 5 }, 160*7c478bd9Sstevel@tonic-gate { "gid", "GID", 5, 5 }, 161*7c478bd9Sstevel@tonic-gate { "rgid", "RGID", 5, 5 }, 162*7c478bd9Sstevel@tonic-gate { "pid", "PID", 5, 5 }, 163*7c478bd9Sstevel@tonic-gate { "ppid", "PPID", 5, 5 }, 164*7c478bd9Sstevel@tonic-gate { "pgid", "PGID", 5, 5 }, 165*7c478bd9Sstevel@tonic-gate { "sid", "SID", 5, 5 }, 166*7c478bd9Sstevel@tonic-gate { "psr", "PSR", 3, 2 }, 167*7c478bd9Sstevel@tonic-gate { "lwp", "LWP", 6, 2 }, 168*7c478bd9Sstevel@tonic-gate { "nlwp", "NLWP", 4, 2 }, 169*7c478bd9Sstevel@tonic-gate { "opri", "PRI", 3, 2 }, 170*7c478bd9Sstevel@tonic-gate { "pri", "PRI", 3, 2 }, 171*7c478bd9Sstevel@tonic-gate { "f", "F", 2, 2 }, 172*7c478bd9Sstevel@tonic-gate { "s", "S", 1, 1 }, 173*7c478bd9Sstevel@tonic-gate { "c", "C", 2, 2 }, 174*7c478bd9Sstevel@tonic-gate { "pcpu", "%CPU", 4, 4 }, 175*7c478bd9Sstevel@tonic-gate { "pmem", "%MEM", 4, 4 }, 176*7c478bd9Sstevel@tonic-gate { "osz", "SZ", 4, 4 }, 177*7c478bd9Sstevel@tonic-gate { "vsz", "VSZ", 4, 4 }, 178*7c478bd9Sstevel@tonic-gate { "rss", "RSS", 4, 4 }, 179*7c478bd9Sstevel@tonic-gate { "nice", "NI", 2, 2 }, 180*7c478bd9Sstevel@tonic-gate { "class", "CLS", 4, 2 }, 181*7c478bd9Sstevel@tonic-gate { "stime", "STIME", 8, 8 }, 182*7c478bd9Sstevel@tonic-gate { "etime", "ELAPSED", 11, 7 }, 183*7c478bd9Sstevel@tonic-gate { "time", "TIME", 11, 5 }, 184*7c478bd9Sstevel@tonic-gate { "tty", "TT", 7, 7 }, 185*7c478bd9Sstevel@tonic-gate #ifdef _LP64 186*7c478bd9Sstevel@tonic-gate { "addr", "ADDR", 16, 8 }, 187*7c478bd9Sstevel@tonic-gate { "wchan", "WCHAN", 16, 8 }, 188*7c478bd9Sstevel@tonic-gate #else 189*7c478bd9Sstevel@tonic-gate { "addr", "ADDR", 8, 8 }, 190*7c478bd9Sstevel@tonic-gate { "wchan", "WCHAN", 8, 8 }, 191*7c478bd9Sstevel@tonic-gate #endif 192*7c478bd9Sstevel@tonic-gate { "fname", "COMMAND", 8, 8 }, 193*7c478bd9Sstevel@tonic-gate { "comm", "COMMAND", 80, 8 }, 194*7c478bd9Sstevel@tonic-gate { "args", "COMMAND", 80, 80 }, 195*7c478bd9Sstevel@tonic-gate { "taskid", "TASKID", 5, 5 }, 196*7c478bd9Sstevel@tonic-gate { "projid", "PROJID", 5, 5 }, 197*7c478bd9Sstevel@tonic-gate { "project", "PROJECT", 8, 8 }, 198*7c478bd9Sstevel@tonic-gate { "pset", "PSET", 3, 3 }, 199*7c478bd9Sstevel@tonic-gate { "zone", "ZONE", 8, 8 }, 200*7c478bd9Sstevel@tonic-gate { "zoneid", "ZONEID", 5, 5 }, 201*7c478bd9Sstevel@tonic-gate { "ctid", "CTID", 5, 5 }, 202*7c478bd9Sstevel@tonic-gate }; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate #define NFIELDS (sizeof (fname) / sizeof (fname[0])) 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate static int retcode = 1; 207*7c478bd9Sstevel@tonic-gate static int lflg; 208*7c478bd9Sstevel@tonic-gate static int Aflg; 209*7c478bd9Sstevel@tonic-gate static int uflg; 210*7c478bd9Sstevel@tonic-gate static int Uflg; 211*7c478bd9Sstevel@tonic-gate static int Gflg; 212*7c478bd9Sstevel@tonic-gate static int aflg; 213*7c478bd9Sstevel@tonic-gate static int dflg; 214*7c478bd9Sstevel@tonic-gate static int Lflg; 215*7c478bd9Sstevel@tonic-gate static int Pflg; 216*7c478bd9Sstevel@tonic-gate static int yflg; 217*7c478bd9Sstevel@tonic-gate static int pflg; 218*7c478bd9Sstevel@tonic-gate static int fflg; 219*7c478bd9Sstevel@tonic-gate static int cflg; 220*7c478bd9Sstevel@tonic-gate static int jflg; 221*7c478bd9Sstevel@tonic-gate static int gflg; 222*7c478bd9Sstevel@tonic-gate static int sflg; 223*7c478bd9Sstevel@tonic-gate static int tflg; 224*7c478bd9Sstevel@tonic-gate static int zflg; 225*7c478bd9Sstevel@tonic-gate static int Zflg; 226*7c478bd9Sstevel@tonic-gate static uid_t tuid = -1; 227*7c478bd9Sstevel@tonic-gate static int errflg; 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate static int ndev; /* number of devices */ 230*7c478bd9Sstevel@tonic-gate static int maxdev; /* number of devl structures allocated */ 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate #define DNINCR 100 233*7c478bd9Sstevel@tonic-gate #define DNSIZE 14 234*7c478bd9Sstevel@tonic-gate static struct devl { /* device list */ 235*7c478bd9Sstevel@tonic-gate char dname[DNSIZE]; /* device name */ 236*7c478bd9Sstevel@tonic-gate dev_t ddev; /* device number */ 237*7c478bd9Sstevel@tonic-gate } *devl; 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate static struct tty { 240*7c478bd9Sstevel@tonic-gate char *tname; 241*7c478bd9Sstevel@tonic-gate dev_t tdev; 242*7c478bd9Sstevel@tonic-gate } *tty = NULL; /* for t option */ 243*7c478bd9Sstevel@tonic-gate static size_t ttysz = 0; 244*7c478bd9Sstevel@tonic-gate static int ntty = 0; 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate static pid_t *pid = NULL; /* for p option */ 247*7c478bd9Sstevel@tonic-gate static size_t pidsz = 0; 248*7c478bd9Sstevel@tonic-gate static size_t npid = 0; 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate static pid_t *grpid = NULL; /* for g option */ 251*7c478bd9Sstevel@tonic-gate static size_t grpidsz = 0; 252*7c478bd9Sstevel@tonic-gate static int ngrpid = 0; 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate static pid_t *sessid = NULL; /* for s option */ 255*7c478bd9Sstevel@tonic-gate static size_t sessidsz = 0; 256*7c478bd9Sstevel@tonic-gate static int nsessid = 0; 257*7c478bd9Sstevel@tonic-gate 258*7c478bd9Sstevel@tonic-gate static zoneid_t *zoneid = NULL; /* for z option */ 259*7c478bd9Sstevel@tonic-gate static size_t zoneidsz = 0; 260*7c478bd9Sstevel@tonic-gate static int nzoneid = 0; 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate static int kbytes_per_page; 263*7c478bd9Sstevel@tonic-gate static int pidwidth; 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate static char *procdir = "/proc"; /* standard /proc directory */ 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate static struct ughead euid_tbl; /* table to store selected euid's */ 268*7c478bd9Sstevel@tonic-gate static struct ughead ruid_tbl; /* table to store selected real uid's */ 269*7c478bd9Sstevel@tonic-gate static struct ughead egid_tbl; /* table to store selected egid's */ 270*7c478bd9Sstevel@tonic-gate static struct ughead rgid_tbl; /* table to store selected real gid's */ 271*7c478bd9Sstevel@tonic-gate static prheader_t *lpsinfobuf; /* buffer to contain lpsinfo */ 272*7c478bd9Sstevel@tonic-gate static size_t lpbufsize; 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate /* 275*7c478bd9Sstevel@tonic-gate * This constant defines the sentinal number of process IDs below which we 276*7c478bd9Sstevel@tonic-gate * only examine individual entries in /proc rather than scanning through 277*7c478bd9Sstevel@tonic-gate * /proc. This optimization is a huge win in the common case. 278*7c478bd9Sstevel@tonic-gate */ 279*7c478bd9Sstevel@tonic-gate #define PTHRESHOLD 40 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate static void usage(void); 282*7c478bd9Sstevel@tonic-gate static char *getarg(char **); 283*7c478bd9Sstevel@tonic-gate static char *parse_format(char *); 284*7c478bd9Sstevel@tonic-gate static char *gettty(psinfo_t *); 285*7c478bd9Sstevel@tonic-gate static int prfind(int, psinfo_t *, char **); 286*7c478bd9Sstevel@tonic-gate static void prcom(psinfo_t *, char *); 287*7c478bd9Sstevel@tonic-gate static void prtpct(ushort_t, int); 288*7c478bd9Sstevel@tonic-gate static void print_time(time_t, int); 289*7c478bd9Sstevel@tonic-gate static void print_field(psinfo_t *, struct field *, const char *); 290*7c478bd9Sstevel@tonic-gate static void print_zombie_field(psinfo_t *, struct field *, const char *); 291*7c478bd9Sstevel@tonic-gate static void pr_fields(psinfo_t *, const char *, 292*7c478bd9Sstevel@tonic-gate void (*print_fld)(psinfo_t *, struct field *, const char *)); 293*7c478bd9Sstevel@tonic-gate static int search(pid_t *, int, pid_t); 294*7c478bd9Sstevel@tonic-gate static void add_ugentry(struct ughead *, char *); 295*7c478bd9Sstevel@tonic-gate static int uconv(struct ughead *); 296*7c478bd9Sstevel@tonic-gate static int gconv(struct ughead *); 297*7c478bd9Sstevel@tonic-gate static int ugfind(uid_t, struct ughead *); 298*7c478bd9Sstevel@tonic-gate static void prtime(timestruc_t, int, int); 299*7c478bd9Sstevel@tonic-gate static void przom(psinfo_t *); 300*7c478bd9Sstevel@tonic-gate static int namencnt(char *, int, int); 301*7c478bd9Sstevel@tonic-gate static char *err_string(int); 302*7c478bd9Sstevel@tonic-gate static int print_proc(char *pname); 303*7c478bd9Sstevel@tonic-gate static time_t delta_secs(const timestruc_t *); 304*7c478bd9Sstevel@tonic-gate static int str2id(const char *, pid_t *, long, long); 305*7c478bd9Sstevel@tonic-gate static void *Realloc(void *, size_t); 306*7c478bd9Sstevel@tonic-gate static int pidcmp(const void *p1, const void *p2); 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate int 309*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 310*7c478bd9Sstevel@tonic-gate { 311*7c478bd9Sstevel@tonic-gate char *p; 312*7c478bd9Sstevel@tonic-gate char *p1; 313*7c478bd9Sstevel@tonic-gate char *parg; 314*7c478bd9Sstevel@tonic-gate int c; 315*7c478bd9Sstevel@tonic-gate int i; 316*7c478bd9Sstevel@tonic-gate int pgerrflg = 0; /* err flg: non-numeric arg w/p & g options */ 317*7c478bd9Sstevel@tonic-gate size_t size; 318*7c478bd9Sstevel@tonic-gate DIR *dirp; 319*7c478bd9Sstevel@tonic-gate struct dirent *dentp; 320*7c478bd9Sstevel@tonic-gate pid_t maxpid; 321*7c478bd9Sstevel@tonic-gate pid_t id; 322*7c478bd9Sstevel@tonic-gate int ret; 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 325*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 326*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 327*7c478bd9Sstevel@tonic-gate #endif 328*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate (void) memset(&euid_tbl, 0, sizeof (euid_tbl)); 331*7c478bd9Sstevel@tonic-gate (void) memset(&ruid_tbl, 0, sizeof (ruid_tbl)); 332*7c478bd9Sstevel@tonic-gate (void) memset(&egid_tbl, 0, sizeof (egid_tbl)); 333*7c478bd9Sstevel@tonic-gate (void) memset(&rgid_tbl, 0, sizeof (rgid_tbl)); 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate kbytes_per_page = sysconf(_SC_PAGESIZE) / 1024; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate (void) gettimeofday(&now, NULL); 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate /* 340*7c478bd9Sstevel@tonic-gate * calculate width of pid fields based on configured MAXPID 341*7c478bd9Sstevel@tonic-gate * (must be at least 5 to retain output format compatibility) 342*7c478bd9Sstevel@tonic-gate */ 343*7c478bd9Sstevel@tonic-gate id = maxpid = (pid_t)sysconf(_SC_MAXPID); 344*7c478bd9Sstevel@tonic-gate pidwidth = 1; 345*7c478bd9Sstevel@tonic-gate while ((id /= 10) > 0) 346*7c478bd9Sstevel@tonic-gate ++pidwidth; 347*7c478bd9Sstevel@tonic-gate pidwidth = pidwidth < 5 ? 5 : pidwidth; 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate fname[F_PID].width = fname[F_PPID].width = pidwidth; 350*7c478bd9Sstevel@tonic-gate fname[F_PGID].width = fname[F_SID].width = pidwidth; 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "jlfceAadLPyZt:p:g:u:U:G:n:s:o:z:")) != 353*7c478bd9Sstevel@tonic-gate EOF) 354*7c478bd9Sstevel@tonic-gate switch (c) { 355*7c478bd9Sstevel@tonic-gate case 'l': /* long listing */ 356*7c478bd9Sstevel@tonic-gate lflg++; 357*7c478bd9Sstevel@tonic-gate break; 358*7c478bd9Sstevel@tonic-gate case 'f': /* full listing */ 359*7c478bd9Sstevel@tonic-gate fflg++; 360*7c478bd9Sstevel@tonic-gate break; 361*7c478bd9Sstevel@tonic-gate case 'j': 362*7c478bd9Sstevel@tonic-gate jflg++; 363*7c478bd9Sstevel@tonic-gate break; 364*7c478bd9Sstevel@tonic-gate case 'c': 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Format output to reflect scheduler changes: 367*7c478bd9Sstevel@tonic-gate * high numbers for high priorities and don't 368*7c478bd9Sstevel@tonic-gate * print nice or p_cpu values. 'c' option only 369*7c478bd9Sstevel@tonic-gate * effective when used with 'l' or 'f' options. 370*7c478bd9Sstevel@tonic-gate */ 371*7c478bd9Sstevel@tonic-gate cflg++; 372*7c478bd9Sstevel@tonic-gate break; 373*7c478bd9Sstevel@tonic-gate case 'A': /* list every process */ 374*7c478bd9Sstevel@tonic-gate case 'e': /* (obsolete) list every process */ 375*7c478bd9Sstevel@tonic-gate Aflg++; 376*7c478bd9Sstevel@tonic-gate tflg = Gflg = Uflg = uflg = pflg = gflg = sflg = 0; 377*7c478bd9Sstevel@tonic-gate zflg = 0; 378*7c478bd9Sstevel@tonic-gate break; 379*7c478bd9Sstevel@tonic-gate case 'a': 380*7c478bd9Sstevel@tonic-gate /* 381*7c478bd9Sstevel@tonic-gate * Same as 'e' except no session group leaders 382*7c478bd9Sstevel@tonic-gate * and no non-terminal processes. 383*7c478bd9Sstevel@tonic-gate */ 384*7c478bd9Sstevel@tonic-gate aflg++; 385*7c478bd9Sstevel@tonic-gate break; 386*7c478bd9Sstevel@tonic-gate case 'd': /* same as e except no session leaders */ 387*7c478bd9Sstevel@tonic-gate dflg++; 388*7c478bd9Sstevel@tonic-gate break; 389*7c478bd9Sstevel@tonic-gate case 'L': /* show lwps */ 390*7c478bd9Sstevel@tonic-gate Lflg++; 391*7c478bd9Sstevel@tonic-gate break; 392*7c478bd9Sstevel@tonic-gate case 'P': /* show bound processor */ 393*7c478bd9Sstevel@tonic-gate Pflg++; 394*7c478bd9Sstevel@tonic-gate break; 395*7c478bd9Sstevel@tonic-gate case 'y': /* omit F & ADDR, report RSS & SZ in Kby */ 396*7c478bd9Sstevel@tonic-gate yflg++; 397*7c478bd9Sstevel@tonic-gate break; 398*7c478bd9Sstevel@tonic-gate case 'n': /* no longer needed; retain as no-op */ 399*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 400*7c478bd9Sstevel@tonic-gate gettext("ps: warning: -n option ignored\n")); 401*7c478bd9Sstevel@tonic-gate break; 402*7c478bd9Sstevel@tonic-gate case 't': /* terminals */ 403*7c478bd9Sstevel@tonic-gate #define TSZ 30 404*7c478bd9Sstevel@tonic-gate tflg++; 405*7c478bd9Sstevel@tonic-gate p1 = optarg; 406*7c478bd9Sstevel@tonic-gate do { 407*7c478bd9Sstevel@tonic-gate char nambuf[TSZ+6]; /* for "/dev/" + '\0' */ 408*7c478bd9Sstevel@tonic-gate struct stat64 s; 409*7c478bd9Sstevel@tonic-gate parg = getarg(&p1); 410*7c478bd9Sstevel@tonic-gate p = Realloc(NULL, TSZ+1); /* for '\0' */ 411*7c478bd9Sstevel@tonic-gate /* zero the buffer before using it */ 412*7c478bd9Sstevel@tonic-gate p[0] = '\0'; 413*7c478bd9Sstevel@tonic-gate size = TSZ; 414*7c478bd9Sstevel@tonic-gate if (isdigit(*parg)) { 415*7c478bd9Sstevel@tonic-gate (void) strcpy(p, "tty"); 416*7c478bd9Sstevel@tonic-gate size -= 3; 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate (void) strncat(p, parg, size); 419*7c478bd9Sstevel@tonic-gate if (ntty == ttysz) { 420*7c478bd9Sstevel@tonic-gate if ((ttysz *= 2) == 0) 421*7c478bd9Sstevel@tonic-gate ttysz = NTTYS; 422*7c478bd9Sstevel@tonic-gate tty = Realloc(tty, 423*7c478bd9Sstevel@tonic-gate (ttysz + 1) * sizeof (struct tty)); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate tty[ntty].tdev = PRNODEV; 426*7c478bd9Sstevel@tonic-gate (void) strcpy(nambuf, "/dev/"); 427*7c478bd9Sstevel@tonic-gate (void) strcat(nambuf, p); 428*7c478bd9Sstevel@tonic-gate if (stat64(nambuf, &s) == 0) 429*7c478bd9Sstevel@tonic-gate tty[ntty].tdev = s.st_rdev; 430*7c478bd9Sstevel@tonic-gate tty[ntty++].tname = p; 431*7c478bd9Sstevel@tonic-gate } while (*p1); 432*7c478bd9Sstevel@tonic-gate break; 433*7c478bd9Sstevel@tonic-gate case 'p': /* proc ids */ 434*7c478bd9Sstevel@tonic-gate pflg++; 435*7c478bd9Sstevel@tonic-gate p1 = optarg; 436*7c478bd9Sstevel@tonic-gate do { 437*7c478bd9Sstevel@tonic-gate pid_t id; 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate parg = getarg(&p1); 440*7c478bd9Sstevel@tonic-gate if ((ret = str2id(parg, &id, 0, maxpid)) != 0) { 441*7c478bd9Sstevel@tonic-gate pgerrflg++; 442*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 443*7c478bd9Sstevel@tonic-gate gettext("ps: %s "), parg); 444*7c478bd9Sstevel@tonic-gate if (ret == EINVAL) 445*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 446*7c478bd9Sstevel@tonic-gate gettext("is an invalid " 447*7c478bd9Sstevel@tonic-gate "non-numeric argument")); 448*7c478bd9Sstevel@tonic-gate else 449*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 450*7c478bd9Sstevel@tonic-gate gettext("exceeds valid " 451*7c478bd9Sstevel@tonic-gate "range")); 452*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 453*7c478bd9Sstevel@tonic-gate gettext(" for -p option\n")); 454*7c478bd9Sstevel@tonic-gate continue; 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate 457*7c478bd9Sstevel@tonic-gate if (npid == pidsz) { 458*7c478bd9Sstevel@tonic-gate if ((pidsz *= 2) == 0) 459*7c478bd9Sstevel@tonic-gate pidsz = SIZ; 460*7c478bd9Sstevel@tonic-gate pid = Realloc(pid, 461*7c478bd9Sstevel@tonic-gate pidsz * sizeof (pid_t)); 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate pid[npid++] = id; 464*7c478bd9Sstevel@tonic-gate } while (*p1); 465*7c478bd9Sstevel@tonic-gate break; 466*7c478bd9Sstevel@tonic-gate case 's': /* session */ 467*7c478bd9Sstevel@tonic-gate sflg++; 468*7c478bd9Sstevel@tonic-gate p1 = optarg; 469*7c478bd9Sstevel@tonic-gate do { 470*7c478bd9Sstevel@tonic-gate pid_t id; 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate parg = getarg(&p1); 473*7c478bd9Sstevel@tonic-gate if ((ret = str2id(parg, &id, 0, maxpid)) != 0) { 474*7c478bd9Sstevel@tonic-gate pgerrflg++; 475*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 476*7c478bd9Sstevel@tonic-gate gettext("ps: %s "), parg); 477*7c478bd9Sstevel@tonic-gate if (ret == EINVAL) 478*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 479*7c478bd9Sstevel@tonic-gate gettext("is an invalid " 480*7c478bd9Sstevel@tonic-gate "non-numeric argument")); 481*7c478bd9Sstevel@tonic-gate else 482*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 483*7c478bd9Sstevel@tonic-gate gettext("exceeds valid " 484*7c478bd9Sstevel@tonic-gate "range")); 485*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 486*7c478bd9Sstevel@tonic-gate gettext(" for -s option\n")); 487*7c478bd9Sstevel@tonic-gate continue; 488*7c478bd9Sstevel@tonic-gate } 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate if (nsessid == sessidsz) { 491*7c478bd9Sstevel@tonic-gate if ((sessidsz *= 2) == 0) 492*7c478bd9Sstevel@tonic-gate sessidsz = SIZ; 493*7c478bd9Sstevel@tonic-gate sessid = Realloc(sessid, 494*7c478bd9Sstevel@tonic-gate sessidsz * sizeof (pid_t)); 495*7c478bd9Sstevel@tonic-gate } 496*7c478bd9Sstevel@tonic-gate sessid[nsessid++] = id; 497*7c478bd9Sstevel@tonic-gate } while (*p1); 498*7c478bd9Sstevel@tonic-gate break; 499*7c478bd9Sstevel@tonic-gate case 'g': /* proc group */ 500*7c478bd9Sstevel@tonic-gate gflg++; 501*7c478bd9Sstevel@tonic-gate p1 = optarg; 502*7c478bd9Sstevel@tonic-gate do { 503*7c478bd9Sstevel@tonic-gate pid_t id; 504*7c478bd9Sstevel@tonic-gate 505*7c478bd9Sstevel@tonic-gate parg = getarg(&p1); 506*7c478bd9Sstevel@tonic-gate if ((ret = str2id(parg, &id, 0, maxpid)) != 0) { 507*7c478bd9Sstevel@tonic-gate pgerrflg++; 508*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 509*7c478bd9Sstevel@tonic-gate gettext("ps: %s "), parg); 510*7c478bd9Sstevel@tonic-gate if (ret == EINVAL) 511*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 512*7c478bd9Sstevel@tonic-gate gettext("is an invalid " 513*7c478bd9Sstevel@tonic-gate "non-numeric argument")); 514*7c478bd9Sstevel@tonic-gate else 515*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 516*7c478bd9Sstevel@tonic-gate gettext("exceeds valid " 517*7c478bd9Sstevel@tonic-gate "range")); 518*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 519*7c478bd9Sstevel@tonic-gate gettext(" for -g option\n")); 520*7c478bd9Sstevel@tonic-gate continue; 521*7c478bd9Sstevel@tonic-gate } 522*7c478bd9Sstevel@tonic-gate 523*7c478bd9Sstevel@tonic-gate if (ngrpid == grpidsz) { 524*7c478bd9Sstevel@tonic-gate if ((grpidsz *= 2) == 0) 525*7c478bd9Sstevel@tonic-gate grpidsz = SIZ; 526*7c478bd9Sstevel@tonic-gate grpid = Realloc(grpid, 527*7c478bd9Sstevel@tonic-gate grpidsz * sizeof (pid_t)); 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate grpid[ngrpid++] = id; 530*7c478bd9Sstevel@tonic-gate } while (*p1); 531*7c478bd9Sstevel@tonic-gate break; 532*7c478bd9Sstevel@tonic-gate case 'u': /* effective user name or number */ 533*7c478bd9Sstevel@tonic-gate uflg++; 534*7c478bd9Sstevel@tonic-gate p1 = optarg; 535*7c478bd9Sstevel@tonic-gate do { 536*7c478bd9Sstevel@tonic-gate parg = getarg(&p1); 537*7c478bd9Sstevel@tonic-gate add_ugentry(&euid_tbl, parg); 538*7c478bd9Sstevel@tonic-gate } while (*p1); 539*7c478bd9Sstevel@tonic-gate break; 540*7c478bd9Sstevel@tonic-gate case 'U': /* real user name or number */ 541*7c478bd9Sstevel@tonic-gate Uflg++; 542*7c478bd9Sstevel@tonic-gate p1 = optarg; 543*7c478bd9Sstevel@tonic-gate do { 544*7c478bd9Sstevel@tonic-gate parg = getarg(&p1); 545*7c478bd9Sstevel@tonic-gate add_ugentry(&ruid_tbl, parg); 546*7c478bd9Sstevel@tonic-gate } while (*p1); 547*7c478bd9Sstevel@tonic-gate break; 548*7c478bd9Sstevel@tonic-gate case 'G': /* real group name or number */ 549*7c478bd9Sstevel@tonic-gate Gflg++; 550*7c478bd9Sstevel@tonic-gate p1 = optarg; 551*7c478bd9Sstevel@tonic-gate do { 552*7c478bd9Sstevel@tonic-gate parg = getarg(&p1); 553*7c478bd9Sstevel@tonic-gate add_ugentry(&rgid_tbl, parg); 554*7c478bd9Sstevel@tonic-gate } while (*p1); 555*7c478bd9Sstevel@tonic-gate break; 556*7c478bd9Sstevel@tonic-gate case 'o': /* output format */ 557*7c478bd9Sstevel@tonic-gate p = optarg; 558*7c478bd9Sstevel@tonic-gate while ((p = parse_format(p)) != NULL) 559*7c478bd9Sstevel@tonic-gate ; 560*7c478bd9Sstevel@tonic-gate break; 561*7c478bd9Sstevel@tonic-gate case 'z': /* zone name or number */ 562*7c478bd9Sstevel@tonic-gate zflg++; 563*7c478bd9Sstevel@tonic-gate p1 = optarg; 564*7c478bd9Sstevel@tonic-gate do { 565*7c478bd9Sstevel@tonic-gate zoneid_t id; 566*7c478bd9Sstevel@tonic-gate 567*7c478bd9Sstevel@tonic-gate parg = getarg(&p1); 568*7c478bd9Sstevel@tonic-gate if (zone_get_id(parg, &id) != 0) { 569*7c478bd9Sstevel@tonic-gate pgerrflg++; 570*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 571*7c478bd9Sstevel@tonic-gate gettext("ps: unknown zone %s\n"), 572*7c478bd9Sstevel@tonic-gate parg); 573*7c478bd9Sstevel@tonic-gate continue; 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate if (nzoneid == zoneidsz) { 577*7c478bd9Sstevel@tonic-gate if ((zoneidsz *= 2) == 0) 578*7c478bd9Sstevel@tonic-gate zoneidsz = SIZ; 579*7c478bd9Sstevel@tonic-gate zoneid = Realloc(zoneid, 580*7c478bd9Sstevel@tonic-gate zoneidsz * sizeof (zoneid_t)); 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate zoneid[nzoneid++] = id; 583*7c478bd9Sstevel@tonic-gate } while (*p1); 584*7c478bd9Sstevel@tonic-gate break; 585*7c478bd9Sstevel@tonic-gate case 'Z': /* show zone name */ 586*7c478bd9Sstevel@tonic-gate Zflg++; 587*7c478bd9Sstevel@tonic-gate break; 588*7c478bd9Sstevel@tonic-gate default: /* error on ? */ 589*7c478bd9Sstevel@tonic-gate errflg++; 590*7c478bd9Sstevel@tonic-gate break; 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate if (errflg || optind < argc || pgerrflg) 594*7c478bd9Sstevel@tonic-gate usage(); 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate if (tflg) 597*7c478bd9Sstevel@tonic-gate tty[ntty].tname = NULL; 598*7c478bd9Sstevel@tonic-gate /* 599*7c478bd9Sstevel@tonic-gate * If an appropriate option has not been specified, use the 600*7c478bd9Sstevel@tonic-gate * current terminal and effective uid as the default. 601*7c478bd9Sstevel@tonic-gate */ 602*7c478bd9Sstevel@tonic-gate if (!(aflg|Aflg|dflg|Gflg|Uflg|uflg|tflg|pflg|gflg|sflg|zflg)) { 603*7c478bd9Sstevel@tonic-gate psinfo_t info; 604*7c478bd9Sstevel@tonic-gate int procfd; 605*7c478bd9Sstevel@tonic-gate char *name; 606*7c478bd9Sstevel@tonic-gate char pname[100]; 607*7c478bd9Sstevel@tonic-gate 608*7c478bd9Sstevel@tonic-gate /* get our own controlling tty name using /proc */ 609*7c478bd9Sstevel@tonic-gate (void) snprintf(pname, sizeof (pname), 610*7c478bd9Sstevel@tonic-gate "%s/self/psinfo", procdir); 611*7c478bd9Sstevel@tonic-gate if ((procfd = open(pname, O_RDONLY)) < 0 || 612*7c478bd9Sstevel@tonic-gate read(procfd, (char *)&info, sizeof (info)) < 0 || 613*7c478bd9Sstevel@tonic-gate info.pr_ttydev == PRNODEV) { 614*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 615*7c478bd9Sstevel@tonic-gate gettext("ps: no controlling terminal\n")); 616*7c478bd9Sstevel@tonic-gate exit(1); 617*7c478bd9Sstevel@tonic-gate } 618*7c478bd9Sstevel@tonic-gate (void) close(procfd); 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate i = 0; 621*7c478bd9Sstevel@tonic-gate name = gettty(&info); 622*7c478bd9Sstevel@tonic-gate if (*name == '?') { 623*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 624*7c478bd9Sstevel@tonic-gate gettext("ps: can't find controlling terminal\n")); 625*7c478bd9Sstevel@tonic-gate exit(1); 626*7c478bd9Sstevel@tonic-gate } 627*7c478bd9Sstevel@tonic-gate if (ntty == ttysz) { 628*7c478bd9Sstevel@tonic-gate if ((ttysz *= 2) == 0) 629*7c478bd9Sstevel@tonic-gate ttysz = NTTYS; 630*7c478bd9Sstevel@tonic-gate tty = Realloc(tty, (ttysz + 1) * sizeof (struct tty)); 631*7c478bd9Sstevel@tonic-gate } 632*7c478bd9Sstevel@tonic-gate tty[ntty].tdev = info.pr_ttydev; 633*7c478bd9Sstevel@tonic-gate tty[ntty++].tname = name; 634*7c478bd9Sstevel@tonic-gate tty[ntty].tname = NULL; 635*7c478bd9Sstevel@tonic-gate tflg++; 636*7c478bd9Sstevel@tonic-gate tuid = getuid(); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate if (Aflg) { 639*7c478bd9Sstevel@tonic-gate Gflg = Uflg = uflg = pflg = sflg = gflg = aflg = dflg = 0; 640*7c478bd9Sstevel@tonic-gate zflg = 0; 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate if (Aflg | aflg | dflg) 643*7c478bd9Sstevel@tonic-gate tflg = 0; 644*7c478bd9Sstevel@tonic-gate 645*7c478bd9Sstevel@tonic-gate i = 0; /* prepare to exit on name lookup errors */ 646*7c478bd9Sstevel@tonic-gate i += uconv(&euid_tbl); 647*7c478bd9Sstevel@tonic-gate i += uconv(&ruid_tbl); 648*7c478bd9Sstevel@tonic-gate i += gconv(&egid_tbl); 649*7c478bd9Sstevel@tonic-gate i += gconv(&rgid_tbl); 650*7c478bd9Sstevel@tonic-gate if (i) 651*7c478bd9Sstevel@tonic-gate exit(1); 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate /* allocate a buffer for lwpsinfo structures */ 654*7c478bd9Sstevel@tonic-gate lpbufsize = 4096; 655*7c478bd9Sstevel@tonic-gate if (Lflg && (lpsinfobuf = malloc(lpbufsize)) == NULL) { 656*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 657*7c478bd9Sstevel@tonic-gate gettext("ps: no memory\n")); 658*7c478bd9Sstevel@tonic-gate exit(1); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate if (fields) { /* print user-specified header */ 662*7c478bd9Sstevel@tonic-gate if (do_header) { 663*7c478bd9Sstevel@tonic-gate struct field *f; 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate for (f = fields; f != NULL; f = f->next) { 666*7c478bd9Sstevel@tonic-gate if (f != fields) 667*7c478bd9Sstevel@tonic-gate (void) printf(" "); 668*7c478bd9Sstevel@tonic-gate switch (f->fname) { 669*7c478bd9Sstevel@tonic-gate case F_TTY: 670*7c478bd9Sstevel@tonic-gate (void) printf("%-*s", 671*7c478bd9Sstevel@tonic-gate f->width, f->header); 672*7c478bd9Sstevel@tonic-gate break; 673*7c478bd9Sstevel@tonic-gate case F_FNAME: 674*7c478bd9Sstevel@tonic-gate case F_COMM: 675*7c478bd9Sstevel@tonic-gate case F_ARGS: 676*7c478bd9Sstevel@tonic-gate /* 677*7c478bd9Sstevel@tonic-gate * Print these headers full width 678*7c478bd9Sstevel@tonic-gate * unless they appear at the end. 679*7c478bd9Sstevel@tonic-gate */ 680*7c478bd9Sstevel@tonic-gate if (f->next != NULL) { 681*7c478bd9Sstevel@tonic-gate (void) printf("%-*s", 682*7c478bd9Sstevel@tonic-gate f->width, f->header); 683*7c478bd9Sstevel@tonic-gate } else { 684*7c478bd9Sstevel@tonic-gate (void) printf("%s", 685*7c478bd9Sstevel@tonic-gate f->header); 686*7c478bd9Sstevel@tonic-gate } 687*7c478bd9Sstevel@tonic-gate break; 688*7c478bd9Sstevel@tonic-gate default: 689*7c478bd9Sstevel@tonic-gate (void) printf("%*s", 690*7c478bd9Sstevel@tonic-gate f->width, f->header); 691*7c478bd9Sstevel@tonic-gate break; 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate } else { /* print standard header */ 697*7c478bd9Sstevel@tonic-gate if (lflg) { 698*7c478bd9Sstevel@tonic-gate if (yflg) 699*7c478bd9Sstevel@tonic-gate (void) printf(" S"); 700*7c478bd9Sstevel@tonic-gate else 701*7c478bd9Sstevel@tonic-gate (void) printf(" F S"); 702*7c478bd9Sstevel@tonic-gate } 703*7c478bd9Sstevel@tonic-gate if (Zflg) 704*7c478bd9Sstevel@tonic-gate (void) printf(" ZONE"); 705*7c478bd9Sstevel@tonic-gate if (fflg) { 706*7c478bd9Sstevel@tonic-gate if (lflg) 707*7c478bd9Sstevel@tonic-gate (void) printf(" "); 708*7c478bd9Sstevel@tonic-gate (void) printf(" UID"); 709*7c478bd9Sstevel@tonic-gate } else if (lflg) 710*7c478bd9Sstevel@tonic-gate (void) printf(" UID"); 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate (void) printf(" %*s", pidwidth, "PID"); 713*7c478bd9Sstevel@tonic-gate if (lflg || fflg) 714*7c478bd9Sstevel@tonic-gate (void) printf(" %*s", pidwidth, "PPID"); 715*7c478bd9Sstevel@tonic-gate if (jflg) 716*7c478bd9Sstevel@tonic-gate (void) printf(" %*s %*s", pidwidth, "PGID", 717*7c478bd9Sstevel@tonic-gate pidwidth, "SID"); 718*7c478bd9Sstevel@tonic-gate if (Lflg) 719*7c478bd9Sstevel@tonic-gate (void) printf(" LWP"); 720*7c478bd9Sstevel@tonic-gate if (Pflg) 721*7c478bd9Sstevel@tonic-gate (void) printf(" PSR"); 722*7c478bd9Sstevel@tonic-gate if (Lflg && fflg) 723*7c478bd9Sstevel@tonic-gate (void) printf(" NLWP"); 724*7c478bd9Sstevel@tonic-gate if (cflg) 725*7c478bd9Sstevel@tonic-gate (void) printf(" CLS PRI"); 726*7c478bd9Sstevel@tonic-gate else if (lflg || fflg) { 727*7c478bd9Sstevel@tonic-gate (void) printf(" C"); 728*7c478bd9Sstevel@tonic-gate if (lflg) 729*7c478bd9Sstevel@tonic-gate (void) printf(" PRI NI"); 730*7c478bd9Sstevel@tonic-gate } 731*7c478bd9Sstevel@tonic-gate if (lflg) { 732*7c478bd9Sstevel@tonic-gate if (yflg) 733*7c478bd9Sstevel@tonic-gate (void) printf(" RSS SZ WCHAN"); 734*7c478bd9Sstevel@tonic-gate else 735*7c478bd9Sstevel@tonic-gate (void) printf(" ADDR SZ WCHAN"); 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate if (fflg) 738*7c478bd9Sstevel@tonic-gate (void) printf(" STIME"); 739*7c478bd9Sstevel@tonic-gate if (Lflg) 740*7c478bd9Sstevel@tonic-gate (void) printf(" TTY LTIME CMD\n"); 741*7c478bd9Sstevel@tonic-gate else 742*7c478bd9Sstevel@tonic-gate (void) printf(" TTY TIME CMD\n"); 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate if (pflg && !(aflg|Aflg|dflg|Gflg|Uflg|uflg|tflg|gflg|sflg|zflg) && 747*7c478bd9Sstevel@tonic-gate npid <= PTHRESHOLD) { 748*7c478bd9Sstevel@tonic-gate /* 749*7c478bd9Sstevel@tonic-gate * If we are looking at specific processes go straight 750*7c478bd9Sstevel@tonic-gate * to their /proc entries and don't scan /proc. 751*7c478bd9Sstevel@tonic-gate */ 752*7c478bd9Sstevel@tonic-gate int i; 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate (void) qsort(pid, npid, sizeof (pid_t), pidcmp); 755*7c478bd9Sstevel@tonic-gate for (i = 0; i < npid; i++) { 756*7c478bd9Sstevel@tonic-gate char pname[12]; 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate if (i >= 1 && pid[i] == pid[i - 1]) 759*7c478bd9Sstevel@tonic-gate continue; 760*7c478bd9Sstevel@tonic-gate (void) sprintf(pname, "%d", (int)pid[i]); 761*7c478bd9Sstevel@tonic-gate if (print_proc(pname) == 0) 762*7c478bd9Sstevel@tonic-gate retcode = 0; 763*7c478bd9Sstevel@tonic-gate } 764*7c478bd9Sstevel@tonic-gate } else { 765*7c478bd9Sstevel@tonic-gate /* 766*7c478bd9Sstevel@tonic-gate * Determine which processes to print info about by searching 767*7c478bd9Sstevel@tonic-gate * the /proc directory and looking at each process. 768*7c478bd9Sstevel@tonic-gate */ 769*7c478bd9Sstevel@tonic-gate if ((dirp = opendir(procdir)) == NULL) { 770*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 771*7c478bd9Sstevel@tonic-gate gettext("ps: cannot open PROC directory %s\n"), 772*7c478bd9Sstevel@tonic-gate procdir); 773*7c478bd9Sstevel@tonic-gate exit(1); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate /* for each active process --- */ 777*7c478bd9Sstevel@tonic-gate while (dentp = readdir(dirp)) { 778*7c478bd9Sstevel@tonic-gate if (dentp->d_name[0] == '.') /* skip . and .. */ 779*7c478bd9Sstevel@tonic-gate continue; 780*7c478bd9Sstevel@tonic-gate if (print_proc(dentp->d_name) == 0) 781*7c478bd9Sstevel@tonic-gate retcode = 0; 782*7c478bd9Sstevel@tonic-gate } 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate (void) closedir(dirp); 785*7c478bd9Sstevel@tonic-gate } 786*7c478bd9Sstevel@tonic-gate return (retcode); 787*7c478bd9Sstevel@tonic-gate } 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate 790*7c478bd9Sstevel@tonic-gate int 791*7c478bd9Sstevel@tonic-gate print_proc(char *pid_name) 792*7c478bd9Sstevel@tonic-gate { 793*7c478bd9Sstevel@tonic-gate char pname[PATH_MAX]; 794*7c478bd9Sstevel@tonic-gate int pdlen; 795*7c478bd9Sstevel@tonic-gate int found; 796*7c478bd9Sstevel@tonic-gate int procfd; /* filedescriptor for /proc/nnnnn/psinfo */ 797*7c478bd9Sstevel@tonic-gate char *tp; /* ptr to ttyname, if any */ 798*7c478bd9Sstevel@tonic-gate psinfo_t info; /* process information from /proc */ 799*7c478bd9Sstevel@tonic-gate lwpsinfo_t *lwpsinfo; /* array of lwpsinfo structs */ 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate pdlen = snprintf(pname, sizeof (pname), "%s/%s/", procdir, pid_name); 802*7c478bd9Sstevel@tonic-gate if (pdlen >= sizeof (pname) - 10) 803*7c478bd9Sstevel@tonic-gate return (1); 804*7c478bd9Sstevel@tonic-gate retry: 805*7c478bd9Sstevel@tonic-gate (void) strcpy(&pname[pdlen], "psinfo"); 806*7c478bd9Sstevel@tonic-gate if ((procfd = open(pname, O_RDONLY)) == -1) { 807*7c478bd9Sstevel@tonic-gate /* Process may have exited meanwhile. */ 808*7c478bd9Sstevel@tonic-gate return (1); 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate /* 811*7c478bd9Sstevel@tonic-gate * Get the info structure for the process and close quickly. 812*7c478bd9Sstevel@tonic-gate */ 813*7c478bd9Sstevel@tonic-gate if (read(procfd, (char *)&info, sizeof (info)) < 0) { 814*7c478bd9Sstevel@tonic-gate int saverr = errno; 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate (void) close(procfd); 817*7c478bd9Sstevel@tonic-gate if (saverr == EAGAIN) 818*7c478bd9Sstevel@tonic-gate goto retry; 819*7c478bd9Sstevel@tonic-gate if (saverr != ENOENT) 820*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 821*7c478bd9Sstevel@tonic-gate gettext("ps: read() on %s: %s\n"), 822*7c478bd9Sstevel@tonic-gate pname, err_string(saverr)); 823*7c478bd9Sstevel@tonic-gate return (1); 824*7c478bd9Sstevel@tonic-gate } 825*7c478bd9Sstevel@tonic-gate (void) close(procfd); 826*7c478bd9Sstevel@tonic-gate 827*7c478bd9Sstevel@tonic-gate found = 0; 828*7c478bd9Sstevel@tonic-gate if (info.pr_lwp.pr_state == 0) /* can't happen? */ 829*7c478bd9Sstevel@tonic-gate return (1); 830*7c478bd9Sstevel@tonic-gate 831*7c478bd9Sstevel@tonic-gate /* 832*7c478bd9Sstevel@tonic-gate * Omit session group leaders for 'a' and 'd' options. 833*7c478bd9Sstevel@tonic-gate */ 834*7c478bd9Sstevel@tonic-gate if ((info.pr_pid == info.pr_sid) && (dflg || aflg)) 835*7c478bd9Sstevel@tonic-gate return (1); 836*7c478bd9Sstevel@tonic-gate if (Aflg || dflg) 837*7c478bd9Sstevel@tonic-gate found++; 838*7c478bd9Sstevel@tonic-gate else if (pflg && search(pid, npid, info.pr_pid)) 839*7c478bd9Sstevel@tonic-gate found++; /* ppid in p option arg list */ 840*7c478bd9Sstevel@tonic-gate else if (uflg && ugfind(info.pr_euid, &euid_tbl)) 841*7c478bd9Sstevel@tonic-gate found++; /* puid in u option arg list */ 842*7c478bd9Sstevel@tonic-gate else if (Uflg && ugfind(info.pr_uid, &ruid_tbl)) 843*7c478bd9Sstevel@tonic-gate found++; /* puid in U option arg list */ 844*7c478bd9Sstevel@tonic-gate #ifdef NOT_YET 845*7c478bd9Sstevel@tonic-gate else if (gflg && ugfind(info.pr_egid, &egid_tbl)) 846*7c478bd9Sstevel@tonic-gate found++; /* pgid in g option arg list */ 847*7c478bd9Sstevel@tonic-gate #endif /* NOT_YET */ 848*7c478bd9Sstevel@tonic-gate else if (Gflg && ugfind(info.pr_gid, &rgid_tbl)) 849*7c478bd9Sstevel@tonic-gate found++; /* pgid in G option arg list */ 850*7c478bd9Sstevel@tonic-gate else if (gflg && search(grpid, ngrpid, info.pr_pgid)) 851*7c478bd9Sstevel@tonic-gate found++; /* grpid in g option arg list */ 852*7c478bd9Sstevel@tonic-gate else if (sflg && search(sessid, nsessid, info.pr_sid)) 853*7c478bd9Sstevel@tonic-gate found++; /* sessid in s option arg list */ 854*7c478bd9Sstevel@tonic-gate else if (zflg && search(zoneid, nzoneid, info.pr_zoneid)) 855*7c478bd9Sstevel@tonic-gate found++; /* zoneid in z option arg list */ 856*7c478bd9Sstevel@tonic-gate if (!found && !tflg && !aflg) 857*7c478bd9Sstevel@tonic-gate return (1); 858*7c478bd9Sstevel@tonic-gate if (!prfind(found, &info, &tp)) 859*7c478bd9Sstevel@tonic-gate return (1); 860*7c478bd9Sstevel@tonic-gate if (Lflg && (info.pr_nlwp + info.pr_nzomb) > 1) { 861*7c478bd9Sstevel@tonic-gate ssize_t prsz; 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate (void) strcpy(&pname[pdlen], "lpsinfo"); 864*7c478bd9Sstevel@tonic-gate if ((procfd = open(pname, O_RDONLY)) == -1) 865*7c478bd9Sstevel@tonic-gate return (1); 866*7c478bd9Sstevel@tonic-gate /* 867*7c478bd9Sstevel@tonic-gate * Get the info structures for the lwps. 868*7c478bd9Sstevel@tonic-gate */ 869*7c478bd9Sstevel@tonic-gate prsz = read(procfd, lpsinfobuf, lpbufsize); 870*7c478bd9Sstevel@tonic-gate if (prsz == -1) { 871*7c478bd9Sstevel@tonic-gate int saverr = errno; 872*7c478bd9Sstevel@tonic-gate 873*7c478bd9Sstevel@tonic-gate (void) close(procfd); 874*7c478bd9Sstevel@tonic-gate if (saverr == EAGAIN) 875*7c478bd9Sstevel@tonic-gate goto retry; 876*7c478bd9Sstevel@tonic-gate if (saverr != ENOENT) 877*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 878*7c478bd9Sstevel@tonic-gate gettext("ps: read() on %s: %s\n"), 879*7c478bd9Sstevel@tonic-gate pname, err_string(saverr)); 880*7c478bd9Sstevel@tonic-gate return (1); 881*7c478bd9Sstevel@tonic-gate } 882*7c478bd9Sstevel@tonic-gate (void) close(procfd); 883*7c478bd9Sstevel@tonic-gate if (prsz == lpbufsize) { 884*7c478bd9Sstevel@tonic-gate /* 885*7c478bd9Sstevel@tonic-gate * buffer overflow. Realloc new buffer. 886*7c478bd9Sstevel@tonic-gate * Error handling is done in Realloc(). 887*7c478bd9Sstevel@tonic-gate */ 888*7c478bd9Sstevel@tonic-gate lpbufsize *= 2; 889*7c478bd9Sstevel@tonic-gate lpsinfobuf = Realloc(lpsinfobuf, lpbufsize); 890*7c478bd9Sstevel@tonic-gate goto retry; 891*7c478bd9Sstevel@tonic-gate } 892*7c478bd9Sstevel@tonic-gate if (lpsinfobuf->pr_nent != (info.pr_nlwp + info.pr_nzomb)) 893*7c478bd9Sstevel@tonic-gate goto retry; 894*7c478bd9Sstevel@tonic-gate lwpsinfo = (lwpsinfo_t *)(lpsinfobuf + 1); 895*7c478bd9Sstevel@tonic-gate } 896*7c478bd9Sstevel@tonic-gate if (!Lflg || (info.pr_nlwp + info.pr_nzomb) <= 1) { 897*7c478bd9Sstevel@tonic-gate prcom(&info, tp); 898*7c478bd9Sstevel@tonic-gate } else { 899*7c478bd9Sstevel@tonic-gate int nlwp = 0; 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate do { 902*7c478bd9Sstevel@tonic-gate info.pr_lwp = *lwpsinfo; 903*7c478bd9Sstevel@tonic-gate prcom(&info, tp); 904*7c478bd9Sstevel@tonic-gate /* LINTED improper alignment */ 905*7c478bd9Sstevel@tonic-gate lwpsinfo = (lwpsinfo_t *)((char *)lwpsinfo + 906*7c478bd9Sstevel@tonic-gate lpsinfobuf->pr_entsize); 907*7c478bd9Sstevel@tonic-gate } while (++nlwp < lpsinfobuf->pr_nent); 908*7c478bd9Sstevel@tonic-gate } 909*7c478bd9Sstevel@tonic-gate return (0); 910*7c478bd9Sstevel@tonic-gate } 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate static void 914*7c478bd9Sstevel@tonic-gate usage(void) /* print usage message and quit */ 915*7c478bd9Sstevel@tonic-gate { 916*7c478bd9Sstevel@tonic-gate static char usage1[] = 917*7c478bd9Sstevel@tonic-gate "ps [ -aAdeflcjLPyZ ] [ -o format ] [ -t termlist ]"; 918*7c478bd9Sstevel@tonic-gate static char usage2[] = 919*7c478bd9Sstevel@tonic-gate "\t[ -u userlist ] [ -U userlist ] [ -G grouplist ]"; 920*7c478bd9Sstevel@tonic-gate static char usage3[] = 921*7c478bd9Sstevel@tonic-gate "\t[ -p proclist ] [ -g pgrplist ] [ -s sidlist ] [ -z zonelist ]"; 922*7c478bd9Sstevel@tonic-gate static char usage4[] = 923*7c478bd9Sstevel@tonic-gate " 'format' is one or more of:"; 924*7c478bd9Sstevel@tonic-gate static char usage5[] = 925*7c478bd9Sstevel@tonic-gate "\tuser ruser group rgroup uid ruid gid rgid pid ppid pgid " 926*7c478bd9Sstevel@tonic-gate "sid taskid ctid"; 927*7c478bd9Sstevel@tonic-gate static char usage6[] = 928*7c478bd9Sstevel@tonic-gate "\tpri opri pcpu pmem vsz rss osz nice class time etime stime zone " 929*7c478bd9Sstevel@tonic-gate "zoneid"; 930*7c478bd9Sstevel@tonic-gate static char usage7[] = 931*7c478bd9Sstevel@tonic-gate "\tf s c lwp nlwp psr tty addr wchan fname comm args " 932*7c478bd9Sstevel@tonic-gate "projid project pset"; 933*7c478bd9Sstevel@tonic-gate 934*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 935*7c478bd9Sstevel@tonic-gate gettext("usage: %s\n%s\n%s\n%s\n%s\n%s\n%s\n"), 936*7c478bd9Sstevel@tonic-gate gettext(usage1), gettext(usage2), gettext(usage3), 937*7c478bd9Sstevel@tonic-gate gettext(usage4), gettext(usage5), gettext(usage6), gettext(usage7)); 938*7c478bd9Sstevel@tonic-gate exit(1); 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate /* 942*7c478bd9Sstevel@tonic-gate * getarg() finds the next argument in list and copies arg into argbuf. 943*7c478bd9Sstevel@tonic-gate * p1 first pts to arg passed back from getopt routine. p1 is then 944*7c478bd9Sstevel@tonic-gate * bumped to next character that is not a comma or blank -- p1 NULL 945*7c478bd9Sstevel@tonic-gate * indicates end of list. 946*7c478bd9Sstevel@tonic-gate */ 947*7c478bd9Sstevel@tonic-gate static char * 948*7c478bd9Sstevel@tonic-gate getarg(char **pp1) 949*7c478bd9Sstevel@tonic-gate { 950*7c478bd9Sstevel@tonic-gate static char argbuf[ARGSIZ]; 951*7c478bd9Sstevel@tonic-gate char *p1 = *pp1; 952*7c478bd9Sstevel@tonic-gate char *parga = argbuf; 953*7c478bd9Sstevel@tonic-gate int c; 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate while ((c = *p1) != '\0' && (c == ',' || isspace(c))) 956*7c478bd9Sstevel@tonic-gate p1++; 957*7c478bd9Sstevel@tonic-gate 958*7c478bd9Sstevel@tonic-gate while ((c = *p1) != '\0' && c != ',' && !isspace(c)) { 959*7c478bd9Sstevel@tonic-gate if (parga < argbuf + ARGSIZ - 1) 960*7c478bd9Sstevel@tonic-gate *parga++ = c; 961*7c478bd9Sstevel@tonic-gate p1++; 962*7c478bd9Sstevel@tonic-gate } 963*7c478bd9Sstevel@tonic-gate *parga = '\0'; 964*7c478bd9Sstevel@tonic-gate 965*7c478bd9Sstevel@tonic-gate while ((c = *p1) != '\0' && (c == ',' || isspace(c))) 966*7c478bd9Sstevel@tonic-gate p1++; 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate *pp1 = p1; 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate return (argbuf); 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate /* 974*7c478bd9Sstevel@tonic-gate * parse_format() takes the argument to the -o option, 975*7c478bd9Sstevel@tonic-gate * sets up the next output field structure, and returns 976*7c478bd9Sstevel@tonic-gate * a pointer to any further output field specifier(s). 977*7c478bd9Sstevel@tonic-gate * As a side-effect, it increments errflg if encounters a format error. 978*7c478bd9Sstevel@tonic-gate */ 979*7c478bd9Sstevel@tonic-gate static char * 980*7c478bd9Sstevel@tonic-gate parse_format(char *arg) 981*7c478bd9Sstevel@tonic-gate { 982*7c478bd9Sstevel@tonic-gate int c; 983*7c478bd9Sstevel@tonic-gate char *name; 984*7c478bd9Sstevel@tonic-gate char *header = NULL; 985*7c478bd9Sstevel@tonic-gate int width = 0; 986*7c478bd9Sstevel@tonic-gate struct def_field *df; 987*7c478bd9Sstevel@tonic-gate struct field *f; 988*7c478bd9Sstevel@tonic-gate 989*7c478bd9Sstevel@tonic-gate while ((c = *arg) != '\0' && (c == ',' || isspace(c))) 990*7c478bd9Sstevel@tonic-gate arg++; 991*7c478bd9Sstevel@tonic-gate if (c == '\0') 992*7c478bd9Sstevel@tonic-gate return (NULL); 993*7c478bd9Sstevel@tonic-gate name = arg; 994*7c478bd9Sstevel@tonic-gate arg = strpbrk(arg, " \t\r\v\f\n,="); 995*7c478bd9Sstevel@tonic-gate if (arg != NULL) { 996*7c478bd9Sstevel@tonic-gate c = *arg; 997*7c478bd9Sstevel@tonic-gate *arg++ = '\0'; 998*7c478bd9Sstevel@tonic-gate if (c == '=') { 999*7c478bd9Sstevel@tonic-gate char *s; 1000*7c478bd9Sstevel@tonic-gate 1001*7c478bd9Sstevel@tonic-gate header = arg; 1002*7c478bd9Sstevel@tonic-gate arg = NULL; 1003*7c478bd9Sstevel@tonic-gate width = strlen(header); 1004*7c478bd9Sstevel@tonic-gate s = header + width; 1005*7c478bd9Sstevel@tonic-gate while (s > header && isspace(*--s)) 1006*7c478bd9Sstevel@tonic-gate *s = '\0'; 1007*7c478bd9Sstevel@tonic-gate while (isspace(*header)) 1008*7c478bd9Sstevel@tonic-gate header++; 1009*7c478bd9Sstevel@tonic-gate } 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate for (df = &fname[0]; df < &fname[NFIELDS]; df++) 1012*7c478bd9Sstevel@tonic-gate if (strcmp(name, df->fname) == 0) { 1013*7c478bd9Sstevel@tonic-gate if (strcmp(name, "lwp") == 0) 1014*7c478bd9Sstevel@tonic-gate Lflg++; 1015*7c478bd9Sstevel@tonic-gate break; 1016*7c478bd9Sstevel@tonic-gate } 1017*7c478bd9Sstevel@tonic-gate if (df >= &fname[NFIELDS]) { 1018*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1019*7c478bd9Sstevel@tonic-gate gettext("ps: unknown output format: -o %s\n"), 1020*7c478bd9Sstevel@tonic-gate name); 1021*7c478bd9Sstevel@tonic-gate errflg++; 1022*7c478bd9Sstevel@tonic-gate return (arg); 1023*7c478bd9Sstevel@tonic-gate } 1024*7c478bd9Sstevel@tonic-gate if ((f = malloc(sizeof (*f))) == NULL) { 1025*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1026*7c478bd9Sstevel@tonic-gate gettext("ps: malloc() for output format failed, %s\n"), 1027*7c478bd9Sstevel@tonic-gate err_string(errno)); 1028*7c478bd9Sstevel@tonic-gate exit(1); 1029*7c478bd9Sstevel@tonic-gate } 1030*7c478bd9Sstevel@tonic-gate f->next = NULL; 1031*7c478bd9Sstevel@tonic-gate f->fname = df - &fname[0]; 1032*7c478bd9Sstevel@tonic-gate f->header = header? header : df->header; 1033*7c478bd9Sstevel@tonic-gate if (width == 0) 1034*7c478bd9Sstevel@tonic-gate width = df->width; 1035*7c478bd9Sstevel@tonic-gate if (*f->header != '\0') 1036*7c478bd9Sstevel@tonic-gate do_header = 1; 1037*7c478bd9Sstevel@tonic-gate f->width = max(width, df->minwidth); 1038*7c478bd9Sstevel@tonic-gate 1039*7c478bd9Sstevel@tonic-gate if (fields == NULL) 1040*7c478bd9Sstevel@tonic-gate fields = last_field = f; 1041*7c478bd9Sstevel@tonic-gate else { 1042*7c478bd9Sstevel@tonic-gate last_field->next = f; 1043*7c478bd9Sstevel@tonic-gate last_field = f; 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate return (arg); 1047*7c478bd9Sstevel@tonic-gate } 1048*7c478bd9Sstevel@tonic-gate 1049*7c478bd9Sstevel@tonic-gate static char * 1050*7c478bd9Sstevel@tonic-gate devlookup(dev_t ddev) 1051*7c478bd9Sstevel@tonic-gate { 1052*7c478bd9Sstevel@tonic-gate struct devl *dp; 1053*7c478bd9Sstevel@tonic-gate int i; 1054*7c478bd9Sstevel@tonic-gate 1055*7c478bd9Sstevel@tonic-gate for (dp = devl, i = 0; i < ndev; dp++, i++) { 1056*7c478bd9Sstevel@tonic-gate if (dp->ddev == ddev) 1057*7c478bd9Sstevel@tonic-gate return (dp->dname); 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate return (NULL); 1060*7c478bd9Sstevel@tonic-gate } 1061*7c478bd9Sstevel@tonic-gate 1062*7c478bd9Sstevel@tonic-gate static char * 1063*7c478bd9Sstevel@tonic-gate devadd(char *name, dev_t ddev) 1064*7c478bd9Sstevel@tonic-gate { 1065*7c478bd9Sstevel@tonic-gate struct devl *dp; 1066*7c478bd9Sstevel@tonic-gate int leng, start, i; 1067*7c478bd9Sstevel@tonic-gate 1068*7c478bd9Sstevel@tonic-gate if (ndev == maxdev) { 1069*7c478bd9Sstevel@tonic-gate maxdev += DNINCR; 1070*7c478bd9Sstevel@tonic-gate devl = Realloc(devl, maxdev * sizeof (struct devl)); 1071*7c478bd9Sstevel@tonic-gate } 1072*7c478bd9Sstevel@tonic-gate dp = &devl[ndev++]; 1073*7c478bd9Sstevel@tonic-gate 1074*7c478bd9Sstevel@tonic-gate dp->ddev = ddev; 1075*7c478bd9Sstevel@tonic-gate if (name == NULL) { 1076*7c478bd9Sstevel@tonic-gate (void) strcpy(dp->dname, "??"); 1077*7c478bd9Sstevel@tonic-gate return (dp->dname); 1078*7c478bd9Sstevel@tonic-gate } 1079*7c478bd9Sstevel@tonic-gate 1080*7c478bd9Sstevel@tonic-gate leng = strlen(name); 1081*7c478bd9Sstevel@tonic-gate /* Strip off /dev/ */ 1082*7c478bd9Sstevel@tonic-gate if (leng < DNSIZE + 4) 1083*7c478bd9Sstevel@tonic-gate (void) strcpy(dp->dname, &name[5]); 1084*7c478bd9Sstevel@tonic-gate else { 1085*7c478bd9Sstevel@tonic-gate start = leng - DNSIZE - 1; 1086*7c478bd9Sstevel@tonic-gate 1087*7c478bd9Sstevel@tonic-gate for (i = start; i < leng && name[i] != '/'; i++) 1088*7c478bd9Sstevel@tonic-gate ; 1089*7c478bd9Sstevel@tonic-gate if (i == leng) 1090*7c478bd9Sstevel@tonic-gate (void) strncpy(dp->dname, &name[start], DNSIZE); 1091*7c478bd9Sstevel@tonic-gate else 1092*7c478bd9Sstevel@tonic-gate (void) strncpy(dp->dname, &name[i+1], DNSIZE); 1093*7c478bd9Sstevel@tonic-gate } 1094*7c478bd9Sstevel@tonic-gate return (dp->dname); 1095*7c478bd9Sstevel@tonic-gate } 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate /* 1098*7c478bd9Sstevel@tonic-gate * gettty returns the user's tty number or ? if none. 1099*7c478bd9Sstevel@tonic-gate */ 1100*7c478bd9Sstevel@tonic-gate static char * 1101*7c478bd9Sstevel@tonic-gate gettty(psinfo_t *psinfo) 1102*7c478bd9Sstevel@tonic-gate { 1103*7c478bd9Sstevel@tonic-gate extern char *_ttyname_dev(dev_t, char *, size_t); 1104*7c478bd9Sstevel@tonic-gate char devname[TTYNAME_MAX]; 1105*7c478bd9Sstevel@tonic-gate char *retval; 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate if (psinfo->pr_ttydev == PRNODEV) 1108*7c478bd9Sstevel@tonic-gate return ("?"); 1109*7c478bd9Sstevel@tonic-gate 1110*7c478bd9Sstevel@tonic-gate if ((retval = devlookup(psinfo->pr_ttydev)) != NULL) 1111*7c478bd9Sstevel@tonic-gate return (retval); 1112*7c478bd9Sstevel@tonic-gate 1113*7c478bd9Sstevel@tonic-gate retval = _ttyname_dev(psinfo->pr_ttydev, devname, sizeof (devname)); 1114*7c478bd9Sstevel@tonic-gate 1115*7c478bd9Sstevel@tonic-gate return (devadd(retval, psinfo->pr_ttydev)); 1116*7c478bd9Sstevel@tonic-gate } 1117*7c478bd9Sstevel@tonic-gate 1118*7c478bd9Sstevel@tonic-gate /* 1119*7c478bd9Sstevel@tonic-gate * Find the process's tty and return 1 if process is to be printed. 1120*7c478bd9Sstevel@tonic-gate */ 1121*7c478bd9Sstevel@tonic-gate static int 1122*7c478bd9Sstevel@tonic-gate prfind(int found, psinfo_t *psinfo, char **tpp) 1123*7c478bd9Sstevel@tonic-gate { 1124*7c478bd9Sstevel@tonic-gate char *tp; 1125*7c478bd9Sstevel@tonic-gate struct tty *ttyp; 1126*7c478bd9Sstevel@tonic-gate 1127*7c478bd9Sstevel@tonic-gate if (psinfo->pr_nlwp == 0) { 1128*7c478bd9Sstevel@tonic-gate /* process is a zombie */ 1129*7c478bd9Sstevel@tonic-gate *tpp = "?"; 1130*7c478bd9Sstevel@tonic-gate if (tflg && !found) 1131*7c478bd9Sstevel@tonic-gate return (0); 1132*7c478bd9Sstevel@tonic-gate return (1); 1133*7c478bd9Sstevel@tonic-gate } 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate /* 1136*7c478bd9Sstevel@tonic-gate * Get current terminal. If none ("?") and 'a' is set, don't print 1137*7c478bd9Sstevel@tonic-gate * info. If 't' is set, check if term is in list of desired terminals 1138*7c478bd9Sstevel@tonic-gate * and print it if it is. 1139*7c478bd9Sstevel@tonic-gate */ 1140*7c478bd9Sstevel@tonic-gate tp = gettty(psinfo); 1141*7c478bd9Sstevel@tonic-gate if (aflg && *tp == '?') { 1142*7c478bd9Sstevel@tonic-gate *tpp = tp; 1143*7c478bd9Sstevel@tonic-gate return (0); 1144*7c478bd9Sstevel@tonic-gate } 1145*7c478bd9Sstevel@tonic-gate if (tflg && !found) { 1146*7c478bd9Sstevel@tonic-gate int match = 0; 1147*7c478bd9Sstevel@tonic-gate char *other = NULL; 1148*7c478bd9Sstevel@tonic-gate for (ttyp = tty; ttyp->tname != NULL; ttyp++) { 1149*7c478bd9Sstevel@tonic-gate /* 1150*7c478bd9Sstevel@tonic-gate * Look for a name match 1151*7c478bd9Sstevel@tonic-gate */ 1152*7c478bd9Sstevel@tonic-gate if (strcmp(tp, ttyp->tname) == 0) { 1153*7c478bd9Sstevel@tonic-gate match = 1; 1154*7c478bd9Sstevel@tonic-gate break; 1155*7c478bd9Sstevel@tonic-gate } 1156*7c478bd9Sstevel@tonic-gate /* 1157*7c478bd9Sstevel@tonic-gate * Look for same device under different names. 1158*7c478bd9Sstevel@tonic-gate */ 1159*7c478bd9Sstevel@tonic-gate if ((other == NULL) && 1160*7c478bd9Sstevel@tonic-gate (ttyp->tdev != PRNODEV) && 1161*7c478bd9Sstevel@tonic-gate (psinfo->pr_ttydev == ttyp->tdev)) 1162*7c478bd9Sstevel@tonic-gate other = ttyp->tname; 1163*7c478bd9Sstevel@tonic-gate } 1164*7c478bd9Sstevel@tonic-gate if (!match && (other != NULL)) { 1165*7c478bd9Sstevel@tonic-gate /* 1166*7c478bd9Sstevel@tonic-gate * found under a different name 1167*7c478bd9Sstevel@tonic-gate */ 1168*7c478bd9Sstevel@tonic-gate match = 1; 1169*7c478bd9Sstevel@tonic-gate tp = other; 1170*7c478bd9Sstevel@tonic-gate } 1171*7c478bd9Sstevel@tonic-gate if (!match || (tuid != -1 && tuid != psinfo->pr_euid)) { 1172*7c478bd9Sstevel@tonic-gate /* 1173*7c478bd9Sstevel@tonic-gate * not found OR not matching euid 1174*7c478bd9Sstevel@tonic-gate */ 1175*7c478bd9Sstevel@tonic-gate *tpp = tp; 1176*7c478bd9Sstevel@tonic-gate return (0); 1177*7c478bd9Sstevel@tonic-gate } 1178*7c478bd9Sstevel@tonic-gate } 1179*7c478bd9Sstevel@tonic-gate *tpp = tp; 1180*7c478bd9Sstevel@tonic-gate return (1); 1181*7c478bd9Sstevel@tonic-gate } 1182*7c478bd9Sstevel@tonic-gate 1183*7c478bd9Sstevel@tonic-gate /* 1184*7c478bd9Sstevel@tonic-gate * Print info about the process. 1185*7c478bd9Sstevel@tonic-gate */ 1186*7c478bd9Sstevel@tonic-gate static void 1187*7c478bd9Sstevel@tonic-gate prcom(psinfo_t *psinfo, char *ttyp) 1188*7c478bd9Sstevel@tonic-gate { 1189*7c478bd9Sstevel@tonic-gate char *cp; 1190*7c478bd9Sstevel@tonic-gate long tm; 1191*7c478bd9Sstevel@tonic-gate int bytesleft; 1192*7c478bd9Sstevel@tonic-gate int wcnt, length; 1193*7c478bd9Sstevel@tonic-gate wchar_t wchar; 1194*7c478bd9Sstevel@tonic-gate struct passwd *pwd; 1195*7c478bd9Sstevel@tonic-gate int zombie_lwp; 1196*7c478bd9Sstevel@tonic-gate char zonename[ZONENAME_MAX]; 1197*7c478bd9Sstevel@tonic-gate 1198*7c478bd9Sstevel@tonic-gate /* 1199*7c478bd9Sstevel@tonic-gate * If process is zombie, call zombie print routine and return. 1200*7c478bd9Sstevel@tonic-gate */ 1201*7c478bd9Sstevel@tonic-gate if (psinfo->pr_nlwp == 0) { 1202*7c478bd9Sstevel@tonic-gate if (fields != NULL) 1203*7c478bd9Sstevel@tonic-gate pr_fields(psinfo, ttyp, print_zombie_field); 1204*7c478bd9Sstevel@tonic-gate else 1205*7c478bd9Sstevel@tonic-gate przom(psinfo); 1206*7c478bd9Sstevel@tonic-gate return; 1207*7c478bd9Sstevel@tonic-gate } 1208*7c478bd9Sstevel@tonic-gate 1209*7c478bd9Sstevel@tonic-gate zombie_lwp = (Lflg && psinfo->pr_lwp.pr_sname == 'Z'); 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate /* 1212*7c478bd9Sstevel@tonic-gate * If user specified '-o format', print requested fields and return. 1213*7c478bd9Sstevel@tonic-gate */ 1214*7c478bd9Sstevel@tonic-gate if (fields != NULL) { 1215*7c478bd9Sstevel@tonic-gate pr_fields(psinfo, ttyp, print_field); 1216*7c478bd9Sstevel@tonic-gate return; 1217*7c478bd9Sstevel@tonic-gate } 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate /* 1220*7c478bd9Sstevel@tonic-gate * All fields before 'PID' are printed with a trailing space as a 1221*7c478bd9Sstevel@tonic-gate * spearator, rather than keeping track of which column is first. All 1222*7c478bd9Sstevel@tonic-gate * other fields are printed with a leading space. 1223*7c478bd9Sstevel@tonic-gate */ 1224*7c478bd9Sstevel@tonic-gate if (lflg) { 1225*7c478bd9Sstevel@tonic-gate if (!yflg) 1226*7c478bd9Sstevel@tonic-gate (void) printf("%2x ", psinfo->pr_flag & 0377); /* F */ 1227*7c478bd9Sstevel@tonic-gate (void) printf("%c ", psinfo->pr_lwp.pr_sname); /* S */ 1228*7c478bd9Sstevel@tonic-gate } 1229*7c478bd9Sstevel@tonic-gate 1230*7c478bd9Sstevel@tonic-gate if (Zflg) { /* ZONE */ 1231*7c478bd9Sstevel@tonic-gate if (getzonenamebyid(psinfo->pr_zoneid, zonename, 1232*7c478bd9Sstevel@tonic-gate sizeof (zonename)) < 0) { 1233*7c478bd9Sstevel@tonic-gate (void) printf("%7.7d ", ((int)psinfo->pr_zoneid)); 1234*7c478bd9Sstevel@tonic-gate } else { 1235*7c478bd9Sstevel@tonic-gate (void) printf("%8.8s ", zonename); 1236*7c478bd9Sstevel@tonic-gate } 1237*7c478bd9Sstevel@tonic-gate } 1238*7c478bd9Sstevel@tonic-gate 1239*7c478bd9Sstevel@tonic-gate if (fflg) { /* UID */ 1240*7c478bd9Sstevel@tonic-gate if ((pwd = getpwuid(psinfo->pr_euid)) != NULL) 1241*7c478bd9Sstevel@tonic-gate (void) printf("%8.8s ", pwd->pw_name); 1242*7c478bd9Sstevel@tonic-gate else 1243*7c478bd9Sstevel@tonic-gate (void) printf("%7.7d ", (int)psinfo->pr_euid); 1244*7c478bd9Sstevel@tonic-gate } else if (lflg) { 1245*7c478bd9Sstevel@tonic-gate (void) printf("%6d ", (int)psinfo->pr_euid); 1246*7c478bd9Sstevel@tonic-gate } 1247*7c478bd9Sstevel@tonic-gate (void) printf("%*d", pidwidth, (int)psinfo->pr_pid); /* PID */ 1248*7c478bd9Sstevel@tonic-gate if (lflg || fflg) 1249*7c478bd9Sstevel@tonic-gate (void) printf(" %*d", pidwidth, 1250*7c478bd9Sstevel@tonic-gate (int)psinfo->pr_ppid); /* PPID */ 1251*7c478bd9Sstevel@tonic-gate if (jflg) { 1252*7c478bd9Sstevel@tonic-gate (void) printf(" %*d", pidwidth, 1253*7c478bd9Sstevel@tonic-gate (int)psinfo->pr_pgid); /* PGID */ 1254*7c478bd9Sstevel@tonic-gate (void) printf(" %*d", pidwidth, 1255*7c478bd9Sstevel@tonic-gate (int)psinfo->pr_sid); /* SID */ 1256*7c478bd9Sstevel@tonic-gate } 1257*7c478bd9Sstevel@tonic-gate if (Lflg) 1258*7c478bd9Sstevel@tonic-gate (void) printf(" %5d", (int)psinfo->pr_lwp.pr_lwpid); /* LWP */ 1259*7c478bd9Sstevel@tonic-gate if (Pflg) { 1260*7c478bd9Sstevel@tonic-gate if (psinfo->pr_lwp.pr_bindpro == PBIND_NONE) /* PSR */ 1261*7c478bd9Sstevel@tonic-gate (void) printf(" -"); 1262*7c478bd9Sstevel@tonic-gate else 1263*7c478bd9Sstevel@tonic-gate (void) printf(" %3d", psinfo->pr_lwp.pr_bindpro); 1264*7c478bd9Sstevel@tonic-gate } 1265*7c478bd9Sstevel@tonic-gate if (Lflg && fflg) /* NLWP */ 1266*7c478bd9Sstevel@tonic-gate (void) printf(" %5d", psinfo->pr_nlwp + psinfo->pr_nzomb); 1267*7c478bd9Sstevel@tonic-gate if (cflg) { 1268*7c478bd9Sstevel@tonic-gate if (zombie_lwp) /* CLS */ 1269*7c478bd9Sstevel@tonic-gate (void) printf(" "); 1270*7c478bd9Sstevel@tonic-gate else 1271*7c478bd9Sstevel@tonic-gate (void) printf(" %4s", psinfo->pr_lwp.pr_clname); 1272*7c478bd9Sstevel@tonic-gate (void) printf(" %3d", psinfo->pr_lwp.pr_pri); /* PRI */ 1273*7c478bd9Sstevel@tonic-gate } else if (lflg || fflg) { 1274*7c478bd9Sstevel@tonic-gate (void) printf(" %3d", psinfo->pr_lwp.pr_cpu & 0377); /* C */ 1275*7c478bd9Sstevel@tonic-gate if (lflg) { /* PRI NI */ 1276*7c478bd9Sstevel@tonic-gate /* 1277*7c478bd9Sstevel@tonic-gate * Print priorities the old way (lower numbers 1278*7c478bd9Sstevel@tonic-gate * mean higher priority) and print nice value 1279*7c478bd9Sstevel@tonic-gate * for time sharing procs. 1280*7c478bd9Sstevel@tonic-gate */ 1281*7c478bd9Sstevel@tonic-gate (void) printf(" %3d", psinfo->pr_lwp.pr_oldpri); 1282*7c478bd9Sstevel@tonic-gate if (psinfo->pr_lwp.pr_oldpri != 0) 1283*7c478bd9Sstevel@tonic-gate (void) printf(" %2d", psinfo->pr_lwp.pr_nice); 1284*7c478bd9Sstevel@tonic-gate else 1285*7c478bd9Sstevel@tonic-gate (void) printf(" %2.2s", 1286*7c478bd9Sstevel@tonic-gate psinfo->pr_lwp.pr_clname); 1287*7c478bd9Sstevel@tonic-gate } 1288*7c478bd9Sstevel@tonic-gate } 1289*7c478bd9Sstevel@tonic-gate if (lflg) { 1290*7c478bd9Sstevel@tonic-gate if (yflg) { 1291*7c478bd9Sstevel@tonic-gate if (psinfo->pr_flag & SSYS) /* RSS */ 1292*7c478bd9Sstevel@tonic-gate (void) printf(" 0"); 1293*7c478bd9Sstevel@tonic-gate else if (psinfo->pr_rssize) 1294*7c478bd9Sstevel@tonic-gate (void) printf(" %5lu", 1295*7c478bd9Sstevel@tonic-gate (ulong_t)psinfo->pr_rssize); 1296*7c478bd9Sstevel@tonic-gate else 1297*7c478bd9Sstevel@tonic-gate (void) printf(" ?"); 1298*7c478bd9Sstevel@tonic-gate if (psinfo->pr_flag & SSYS) /* SZ */ 1299*7c478bd9Sstevel@tonic-gate (void) printf(" 0"); 1300*7c478bd9Sstevel@tonic-gate else if (psinfo->pr_size) 1301*7c478bd9Sstevel@tonic-gate (void) printf(" %6lu", 1302*7c478bd9Sstevel@tonic-gate (ulong_t)psinfo->pr_size); 1303*7c478bd9Sstevel@tonic-gate else 1304*7c478bd9Sstevel@tonic-gate (void) printf(" ?"); 1305*7c478bd9Sstevel@tonic-gate } else { 1306*7c478bd9Sstevel@tonic-gate #ifndef _LP64 1307*7c478bd9Sstevel@tonic-gate if (psinfo->pr_addr) /* ADDR */ 1308*7c478bd9Sstevel@tonic-gate (void) printf(" %8lx", 1309*7c478bd9Sstevel@tonic-gate (ulong_t)psinfo->pr_addr); 1310*7c478bd9Sstevel@tonic-gate else 1311*7c478bd9Sstevel@tonic-gate #endif 1312*7c478bd9Sstevel@tonic-gate (void) printf(" ?"); 1313*7c478bd9Sstevel@tonic-gate if (psinfo->pr_flag & SSYS) /* SZ */ 1314*7c478bd9Sstevel@tonic-gate (void) printf(" 0"); 1315*7c478bd9Sstevel@tonic-gate else if (psinfo->pr_size) 1316*7c478bd9Sstevel@tonic-gate (void) printf(" %6lu", 1317*7c478bd9Sstevel@tonic-gate (ulong_t)psinfo->pr_size / kbytes_per_page); 1318*7c478bd9Sstevel@tonic-gate else 1319*7c478bd9Sstevel@tonic-gate (void) printf(" ?"); 1320*7c478bd9Sstevel@tonic-gate } 1321*7c478bd9Sstevel@tonic-gate if (psinfo->pr_lwp.pr_sname != 'S') /* WCHAN */ 1322*7c478bd9Sstevel@tonic-gate (void) printf(" "); 1323*7c478bd9Sstevel@tonic-gate #ifndef _LP64 1324*7c478bd9Sstevel@tonic-gate else if (psinfo->pr_lwp.pr_wchan) 1325*7c478bd9Sstevel@tonic-gate (void) printf(" %8lx", 1326*7c478bd9Sstevel@tonic-gate (ulong_t)psinfo->pr_lwp.pr_wchan); 1327*7c478bd9Sstevel@tonic-gate #endif 1328*7c478bd9Sstevel@tonic-gate else 1329*7c478bd9Sstevel@tonic-gate (void) printf(" ?"); 1330*7c478bd9Sstevel@tonic-gate } 1331*7c478bd9Sstevel@tonic-gate if (fflg) { /* STIME */ 1332*7c478bd9Sstevel@tonic-gate if (Lflg) 1333*7c478bd9Sstevel@tonic-gate prtime(psinfo->pr_lwp.pr_start, 9, 1); 1334*7c478bd9Sstevel@tonic-gate else 1335*7c478bd9Sstevel@tonic-gate prtime(psinfo->pr_start, 9, 1); 1336*7c478bd9Sstevel@tonic-gate } 1337*7c478bd9Sstevel@tonic-gate (void) printf(" %-8.14s", ttyp); /* TTY */ 1338*7c478bd9Sstevel@tonic-gate if (Lflg) { 1339*7c478bd9Sstevel@tonic-gate tm = psinfo->pr_lwp.pr_time.tv_sec; 1340*7c478bd9Sstevel@tonic-gate if (psinfo->pr_lwp.pr_time.tv_nsec > 500000000) 1341*7c478bd9Sstevel@tonic-gate tm++; 1342*7c478bd9Sstevel@tonic-gate } else { 1343*7c478bd9Sstevel@tonic-gate tm = psinfo->pr_time.tv_sec; 1344*7c478bd9Sstevel@tonic-gate if (psinfo->pr_time.tv_nsec > 500000000) 1345*7c478bd9Sstevel@tonic-gate tm++; 1346*7c478bd9Sstevel@tonic-gate } 1347*7c478bd9Sstevel@tonic-gate (void) printf(" %4ld:%.2ld", tm / 60, tm % 60); /* [L]TIME */ 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate if (zombie_lwp) { 1350*7c478bd9Sstevel@tonic-gate (void) printf(" <defunct>\n"); 1351*7c478bd9Sstevel@tonic-gate return; 1352*7c478bd9Sstevel@tonic-gate } 1353*7c478bd9Sstevel@tonic-gate 1354*7c478bd9Sstevel@tonic-gate if (!fflg) { /* CMD */ 1355*7c478bd9Sstevel@tonic-gate wcnt = namencnt(psinfo->pr_fname, 16, 8); 1356*7c478bd9Sstevel@tonic-gate (void) printf(" %.*s\n", wcnt, psinfo->pr_fname); 1357*7c478bd9Sstevel@tonic-gate return; 1358*7c478bd9Sstevel@tonic-gate } 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate /* 1361*7c478bd9Sstevel@tonic-gate * PRARGSZ == length of cmd arg string. 1362*7c478bd9Sstevel@tonic-gate */ 1363*7c478bd9Sstevel@tonic-gate psinfo->pr_psargs[PRARGSZ-1] = '\0'; 1364*7c478bd9Sstevel@tonic-gate bytesleft = PRARGSZ; 1365*7c478bd9Sstevel@tonic-gate for (cp = psinfo->pr_psargs; *cp != '\0'; cp += length) { 1366*7c478bd9Sstevel@tonic-gate length = mbtowc(&wchar, cp, MB_LEN_MAX); 1367*7c478bd9Sstevel@tonic-gate if (length == 0) 1368*7c478bd9Sstevel@tonic-gate break; 1369*7c478bd9Sstevel@tonic-gate if (length < 0 || !iswprint(wchar)) { 1370*7c478bd9Sstevel@tonic-gate if (length < 0) 1371*7c478bd9Sstevel@tonic-gate length = 1; 1372*7c478bd9Sstevel@tonic-gate if (bytesleft <= length) { 1373*7c478bd9Sstevel@tonic-gate *cp = '\0'; 1374*7c478bd9Sstevel@tonic-gate break; 1375*7c478bd9Sstevel@tonic-gate } 1376*7c478bd9Sstevel@tonic-gate /* omit the unprintable character */ 1377*7c478bd9Sstevel@tonic-gate (void) memmove(cp, cp+length, bytesleft-length); 1378*7c478bd9Sstevel@tonic-gate length = 0; 1379*7c478bd9Sstevel@tonic-gate } 1380*7c478bd9Sstevel@tonic-gate bytesleft -= length; 1381*7c478bd9Sstevel@tonic-gate } 1382*7c478bd9Sstevel@tonic-gate wcnt = namencnt(psinfo->pr_psargs, PRARGSZ, lflg ? 35 : PRARGSZ); 1383*7c478bd9Sstevel@tonic-gate (void) printf(" %.*s\n", wcnt, psinfo->pr_psargs); 1384*7c478bd9Sstevel@tonic-gate } 1385*7c478bd9Sstevel@tonic-gate 1386*7c478bd9Sstevel@tonic-gate /* 1387*7c478bd9Sstevel@tonic-gate * Print percent from 16-bit binary fraction [0 .. 1] 1388*7c478bd9Sstevel@tonic-gate * Round up .01 to .1 to indicate some small percentage (the 0x7000 below). 1389*7c478bd9Sstevel@tonic-gate */ 1390*7c478bd9Sstevel@tonic-gate static void 1391*7c478bd9Sstevel@tonic-gate prtpct(ushort_t pct, int width) 1392*7c478bd9Sstevel@tonic-gate { 1393*7c478bd9Sstevel@tonic-gate uint_t value = pct; /* need 32 bits to compute with */ 1394*7c478bd9Sstevel@tonic-gate 1395*7c478bd9Sstevel@tonic-gate value = ((value * 1000) + 0x7000) >> 15; /* [0 .. 1000] */ 1396*7c478bd9Sstevel@tonic-gate if (value >= 1000) 1397*7c478bd9Sstevel@tonic-gate value = 999; 1398*7c478bd9Sstevel@tonic-gate if ((width -= 2) < 2) 1399*7c478bd9Sstevel@tonic-gate width = 2; 1400*7c478bd9Sstevel@tonic-gate (void) printf("%*u.%u", width, value / 10, value % 10); 1401*7c478bd9Sstevel@tonic-gate } 1402*7c478bd9Sstevel@tonic-gate 1403*7c478bd9Sstevel@tonic-gate static void 1404*7c478bd9Sstevel@tonic-gate print_time(time_t tim, int width) 1405*7c478bd9Sstevel@tonic-gate { 1406*7c478bd9Sstevel@tonic-gate char buf[30]; 1407*7c478bd9Sstevel@tonic-gate time_t seconds; 1408*7c478bd9Sstevel@tonic-gate time_t minutes; 1409*7c478bd9Sstevel@tonic-gate time_t hours; 1410*7c478bd9Sstevel@tonic-gate time_t days; 1411*7c478bd9Sstevel@tonic-gate 1412*7c478bd9Sstevel@tonic-gate if (tim < 0) { 1413*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1414*7c478bd9Sstevel@tonic-gate return; 1415*7c478bd9Sstevel@tonic-gate } 1416*7c478bd9Sstevel@tonic-gate 1417*7c478bd9Sstevel@tonic-gate seconds = tim % 60; 1418*7c478bd9Sstevel@tonic-gate tim /= 60; 1419*7c478bd9Sstevel@tonic-gate minutes = tim % 60; 1420*7c478bd9Sstevel@tonic-gate tim /= 60; 1421*7c478bd9Sstevel@tonic-gate hours = tim % 24; 1422*7c478bd9Sstevel@tonic-gate days = tim / 24; 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate if (days > 0) { 1425*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%ld-%2.2ld:%2.2ld:%2.2ld", 1426*7c478bd9Sstevel@tonic-gate days, hours, minutes, seconds); 1427*7c478bd9Sstevel@tonic-gate } else if (hours > 0) { 1428*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%2.2ld:%2.2ld:%2.2ld", 1429*7c478bd9Sstevel@tonic-gate hours, minutes, seconds); 1430*7c478bd9Sstevel@tonic-gate } else { 1431*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%2.2ld:%2.2ld", 1432*7c478bd9Sstevel@tonic-gate minutes, seconds); 1433*7c478bd9Sstevel@tonic-gate } 1434*7c478bd9Sstevel@tonic-gate 1435*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, buf); 1436*7c478bd9Sstevel@tonic-gate } 1437*7c478bd9Sstevel@tonic-gate 1438*7c478bd9Sstevel@tonic-gate static void 1439*7c478bd9Sstevel@tonic-gate print_field(psinfo_t *psinfo, struct field *f, const char *ttyp) 1440*7c478bd9Sstevel@tonic-gate { 1441*7c478bd9Sstevel@tonic-gate int width = f->width; 1442*7c478bd9Sstevel@tonic-gate struct passwd *pwd; 1443*7c478bd9Sstevel@tonic-gate struct group *grp; 1444*7c478bd9Sstevel@tonic-gate time_t cputime; 1445*7c478bd9Sstevel@tonic-gate int bytesleft; 1446*7c478bd9Sstevel@tonic-gate int wcnt; 1447*7c478bd9Sstevel@tonic-gate wchar_t wchar; 1448*7c478bd9Sstevel@tonic-gate char *cp; 1449*7c478bd9Sstevel@tonic-gate int length; 1450*7c478bd9Sstevel@tonic-gate ulong_t mask; 1451*7c478bd9Sstevel@tonic-gate char c, *csave; 1452*7c478bd9Sstevel@tonic-gate int zombie_lwp; 1453*7c478bd9Sstevel@tonic-gate 1454*7c478bd9Sstevel@tonic-gate zombie_lwp = (Lflg && psinfo->pr_lwp.pr_sname == 'Z'); 1455*7c478bd9Sstevel@tonic-gate 1456*7c478bd9Sstevel@tonic-gate switch (f->fname) { 1457*7c478bd9Sstevel@tonic-gate case F_RUSER: 1458*7c478bd9Sstevel@tonic-gate if ((pwd = getpwuid(psinfo->pr_uid)) != NULL) 1459*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, pwd->pw_name); 1460*7c478bd9Sstevel@tonic-gate else 1461*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_uid); 1462*7c478bd9Sstevel@tonic-gate break; 1463*7c478bd9Sstevel@tonic-gate case F_USER: 1464*7c478bd9Sstevel@tonic-gate if ((pwd = getpwuid(psinfo->pr_euid)) != NULL) 1465*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, pwd->pw_name); 1466*7c478bd9Sstevel@tonic-gate else 1467*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_euid); 1468*7c478bd9Sstevel@tonic-gate break; 1469*7c478bd9Sstevel@tonic-gate case F_RGROUP: 1470*7c478bd9Sstevel@tonic-gate if ((grp = getgrgid(psinfo->pr_gid)) != NULL) 1471*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, grp->gr_name); 1472*7c478bd9Sstevel@tonic-gate else 1473*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_gid); 1474*7c478bd9Sstevel@tonic-gate break; 1475*7c478bd9Sstevel@tonic-gate case F_GROUP: 1476*7c478bd9Sstevel@tonic-gate if ((grp = getgrgid(psinfo->pr_egid)) != NULL) 1477*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, grp->gr_name); 1478*7c478bd9Sstevel@tonic-gate else 1479*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_egid); 1480*7c478bd9Sstevel@tonic-gate break; 1481*7c478bd9Sstevel@tonic-gate case F_RUID: 1482*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_uid); 1483*7c478bd9Sstevel@tonic-gate break; 1484*7c478bd9Sstevel@tonic-gate case F_UID: 1485*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_euid); 1486*7c478bd9Sstevel@tonic-gate break; 1487*7c478bd9Sstevel@tonic-gate case F_RGID: 1488*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_gid); 1489*7c478bd9Sstevel@tonic-gate break; 1490*7c478bd9Sstevel@tonic-gate case F_GID: 1491*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_egid); 1492*7c478bd9Sstevel@tonic-gate break; 1493*7c478bd9Sstevel@tonic-gate case F_PID: 1494*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_pid); 1495*7c478bd9Sstevel@tonic-gate break; 1496*7c478bd9Sstevel@tonic-gate case F_PPID: 1497*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_ppid); 1498*7c478bd9Sstevel@tonic-gate break; 1499*7c478bd9Sstevel@tonic-gate case F_PGID: 1500*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_pgid); 1501*7c478bd9Sstevel@tonic-gate break; 1502*7c478bd9Sstevel@tonic-gate case F_SID: 1503*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_sid); 1504*7c478bd9Sstevel@tonic-gate break; 1505*7c478bd9Sstevel@tonic-gate case F_PSR: 1506*7c478bd9Sstevel@tonic-gate if (zombie_lwp || psinfo->pr_lwp.pr_bindpro == PBIND_NONE) 1507*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1508*7c478bd9Sstevel@tonic-gate else 1509*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, psinfo->pr_lwp.pr_bindpro); 1510*7c478bd9Sstevel@tonic-gate break; 1511*7c478bd9Sstevel@tonic-gate case F_LWP: 1512*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_lwp.pr_lwpid); 1513*7c478bd9Sstevel@tonic-gate break; 1514*7c478bd9Sstevel@tonic-gate case F_NLWP: 1515*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, psinfo->pr_nlwp + psinfo->pr_nzomb); 1516*7c478bd9Sstevel@tonic-gate break; 1517*7c478bd9Sstevel@tonic-gate case F_OPRI: 1518*7c478bd9Sstevel@tonic-gate if (zombie_lwp) 1519*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1520*7c478bd9Sstevel@tonic-gate else 1521*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, psinfo->pr_lwp.pr_oldpri); 1522*7c478bd9Sstevel@tonic-gate break; 1523*7c478bd9Sstevel@tonic-gate case F_PRI: 1524*7c478bd9Sstevel@tonic-gate if (zombie_lwp) 1525*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1526*7c478bd9Sstevel@tonic-gate else 1527*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, psinfo->pr_lwp.pr_pri); 1528*7c478bd9Sstevel@tonic-gate break; 1529*7c478bd9Sstevel@tonic-gate case F_F: 1530*7c478bd9Sstevel@tonic-gate mask = 0xffffffffUL; 1531*7c478bd9Sstevel@tonic-gate if (width < 8) 1532*7c478bd9Sstevel@tonic-gate mask >>= (8 - width) * 4; 1533*7c478bd9Sstevel@tonic-gate (void) printf("%*lx", width, psinfo->pr_flag & mask); 1534*7c478bd9Sstevel@tonic-gate break; 1535*7c478bd9Sstevel@tonic-gate case F_S: 1536*7c478bd9Sstevel@tonic-gate (void) printf("%*c", width, psinfo->pr_lwp.pr_sname); 1537*7c478bd9Sstevel@tonic-gate break; 1538*7c478bd9Sstevel@tonic-gate case F_C: 1539*7c478bd9Sstevel@tonic-gate if (zombie_lwp) 1540*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1541*7c478bd9Sstevel@tonic-gate else 1542*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, psinfo->pr_lwp.pr_cpu); 1543*7c478bd9Sstevel@tonic-gate break; 1544*7c478bd9Sstevel@tonic-gate case F_PCPU: 1545*7c478bd9Sstevel@tonic-gate if (zombie_lwp) 1546*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1547*7c478bd9Sstevel@tonic-gate else if (Lflg) 1548*7c478bd9Sstevel@tonic-gate prtpct(psinfo->pr_lwp.pr_pctcpu, width); 1549*7c478bd9Sstevel@tonic-gate else 1550*7c478bd9Sstevel@tonic-gate prtpct(psinfo->pr_pctcpu, width); 1551*7c478bd9Sstevel@tonic-gate break; 1552*7c478bd9Sstevel@tonic-gate case F_PMEM: 1553*7c478bd9Sstevel@tonic-gate prtpct(psinfo->pr_pctmem, width); 1554*7c478bd9Sstevel@tonic-gate break; 1555*7c478bd9Sstevel@tonic-gate case F_OSZ: 1556*7c478bd9Sstevel@tonic-gate (void) printf("%*lu", width, 1557*7c478bd9Sstevel@tonic-gate (ulong_t)psinfo->pr_size / kbytes_per_page); 1558*7c478bd9Sstevel@tonic-gate break; 1559*7c478bd9Sstevel@tonic-gate case F_VSZ: 1560*7c478bd9Sstevel@tonic-gate (void) printf("%*lu", width, (ulong_t)psinfo->pr_size); 1561*7c478bd9Sstevel@tonic-gate break; 1562*7c478bd9Sstevel@tonic-gate case F_RSS: 1563*7c478bd9Sstevel@tonic-gate (void) printf("%*lu", width, (ulong_t)psinfo->pr_rssize); 1564*7c478bd9Sstevel@tonic-gate break; 1565*7c478bd9Sstevel@tonic-gate case F_NICE: 1566*7c478bd9Sstevel@tonic-gate /* if pr_oldpri is zero, then this class has no nice */ 1567*7c478bd9Sstevel@tonic-gate if (zombie_lwp) 1568*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1569*7c478bd9Sstevel@tonic-gate else if (psinfo->pr_lwp.pr_oldpri != 0) 1570*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, psinfo->pr_lwp.pr_nice); 1571*7c478bd9Sstevel@tonic-gate else 1572*7c478bd9Sstevel@tonic-gate (void) printf("%*.*s", width, width, 1573*7c478bd9Sstevel@tonic-gate psinfo->pr_lwp.pr_clname); 1574*7c478bd9Sstevel@tonic-gate break; 1575*7c478bd9Sstevel@tonic-gate case F_CLASS: 1576*7c478bd9Sstevel@tonic-gate if (zombie_lwp) 1577*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1578*7c478bd9Sstevel@tonic-gate else 1579*7c478bd9Sstevel@tonic-gate (void) printf("%*.*s", width, width, 1580*7c478bd9Sstevel@tonic-gate psinfo->pr_lwp.pr_clname); 1581*7c478bd9Sstevel@tonic-gate break; 1582*7c478bd9Sstevel@tonic-gate case F_STIME: 1583*7c478bd9Sstevel@tonic-gate if (Lflg) 1584*7c478bd9Sstevel@tonic-gate prtime(psinfo->pr_lwp.pr_start, width, 0); 1585*7c478bd9Sstevel@tonic-gate else 1586*7c478bd9Sstevel@tonic-gate prtime(psinfo->pr_start, width, 0); 1587*7c478bd9Sstevel@tonic-gate break; 1588*7c478bd9Sstevel@tonic-gate case F_ETIME: 1589*7c478bd9Sstevel@tonic-gate if (Lflg) 1590*7c478bd9Sstevel@tonic-gate print_time(delta_secs(&psinfo->pr_lwp.pr_start), 1591*7c478bd9Sstevel@tonic-gate width); 1592*7c478bd9Sstevel@tonic-gate else 1593*7c478bd9Sstevel@tonic-gate print_time(delta_secs(&psinfo->pr_start), width); 1594*7c478bd9Sstevel@tonic-gate break; 1595*7c478bd9Sstevel@tonic-gate case F_TIME: 1596*7c478bd9Sstevel@tonic-gate if (Lflg) { 1597*7c478bd9Sstevel@tonic-gate cputime = psinfo->pr_lwp.pr_time.tv_sec; 1598*7c478bd9Sstevel@tonic-gate if (psinfo->pr_lwp.pr_time.tv_nsec > 500000000) 1599*7c478bd9Sstevel@tonic-gate cputime++; 1600*7c478bd9Sstevel@tonic-gate } else { 1601*7c478bd9Sstevel@tonic-gate cputime = psinfo->pr_time.tv_sec; 1602*7c478bd9Sstevel@tonic-gate if (psinfo->pr_time.tv_nsec > 500000000) 1603*7c478bd9Sstevel@tonic-gate cputime++; 1604*7c478bd9Sstevel@tonic-gate } 1605*7c478bd9Sstevel@tonic-gate print_time(cputime, width); 1606*7c478bd9Sstevel@tonic-gate break; 1607*7c478bd9Sstevel@tonic-gate case F_TTY: 1608*7c478bd9Sstevel@tonic-gate (void) printf("%-*s", width, ttyp); 1609*7c478bd9Sstevel@tonic-gate break; 1610*7c478bd9Sstevel@tonic-gate case F_ADDR: 1611*7c478bd9Sstevel@tonic-gate if (zombie_lwp) 1612*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1613*7c478bd9Sstevel@tonic-gate else if (Lflg) 1614*7c478bd9Sstevel@tonic-gate (void) printf("%*lx", width, 1615*7c478bd9Sstevel@tonic-gate (long)psinfo->pr_lwp.pr_addr); 1616*7c478bd9Sstevel@tonic-gate else 1617*7c478bd9Sstevel@tonic-gate (void) printf("%*lx", width, (long)psinfo->pr_addr); 1618*7c478bd9Sstevel@tonic-gate break; 1619*7c478bd9Sstevel@tonic-gate case F_WCHAN: 1620*7c478bd9Sstevel@tonic-gate if (!zombie_lwp && psinfo->pr_lwp.pr_wchan) 1621*7c478bd9Sstevel@tonic-gate (void) printf("%*lx", width, 1622*7c478bd9Sstevel@tonic-gate (long)psinfo->pr_lwp.pr_wchan); 1623*7c478bd9Sstevel@tonic-gate else 1624*7c478bd9Sstevel@tonic-gate (void) printf("%*.*s", width, width, "-"); 1625*7c478bd9Sstevel@tonic-gate break; 1626*7c478bd9Sstevel@tonic-gate case F_FNAME: 1627*7c478bd9Sstevel@tonic-gate /* 1628*7c478bd9Sstevel@tonic-gate * Print full width unless this is the last output format. 1629*7c478bd9Sstevel@tonic-gate */ 1630*7c478bd9Sstevel@tonic-gate if (zombie_lwp) { 1631*7c478bd9Sstevel@tonic-gate if (f->next != NULL) 1632*7c478bd9Sstevel@tonic-gate (void) printf("%-*s", width, "<defunct>"); 1633*7c478bd9Sstevel@tonic-gate else 1634*7c478bd9Sstevel@tonic-gate (void) printf("%s", "<defunct>"); 1635*7c478bd9Sstevel@tonic-gate break; 1636*7c478bd9Sstevel@tonic-gate } 1637*7c478bd9Sstevel@tonic-gate wcnt = namencnt(psinfo->pr_fname, 16, width); 1638*7c478bd9Sstevel@tonic-gate if (f->next != NULL) 1639*7c478bd9Sstevel@tonic-gate (void) printf("%-*.*s", width, wcnt, psinfo->pr_fname); 1640*7c478bd9Sstevel@tonic-gate else 1641*7c478bd9Sstevel@tonic-gate (void) printf("%-.*s", wcnt, psinfo->pr_fname); 1642*7c478bd9Sstevel@tonic-gate break; 1643*7c478bd9Sstevel@tonic-gate case F_COMM: 1644*7c478bd9Sstevel@tonic-gate if (zombie_lwp) { 1645*7c478bd9Sstevel@tonic-gate if (f->next != NULL) 1646*7c478bd9Sstevel@tonic-gate (void) printf("%-*s", width, "<defunct>"); 1647*7c478bd9Sstevel@tonic-gate else 1648*7c478bd9Sstevel@tonic-gate (void) printf("%s", "<defunct>"); 1649*7c478bd9Sstevel@tonic-gate break; 1650*7c478bd9Sstevel@tonic-gate } 1651*7c478bd9Sstevel@tonic-gate csave = strpbrk(psinfo->pr_psargs, " \t\r\v\f\n"); 1652*7c478bd9Sstevel@tonic-gate if (csave) { 1653*7c478bd9Sstevel@tonic-gate c = *csave; 1654*7c478bd9Sstevel@tonic-gate *csave = '\0'; 1655*7c478bd9Sstevel@tonic-gate } 1656*7c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 1657*7c478bd9Sstevel@tonic-gate case F_ARGS: 1658*7c478bd9Sstevel@tonic-gate /* 1659*7c478bd9Sstevel@tonic-gate * PRARGSZ == length of cmd arg string. 1660*7c478bd9Sstevel@tonic-gate */ 1661*7c478bd9Sstevel@tonic-gate if (zombie_lwp) { 1662*7c478bd9Sstevel@tonic-gate (void) printf("%-*s", width, "<defunct>"); 1663*7c478bd9Sstevel@tonic-gate break; 1664*7c478bd9Sstevel@tonic-gate } 1665*7c478bd9Sstevel@tonic-gate psinfo->pr_psargs[PRARGSZ-1] = '\0'; 1666*7c478bd9Sstevel@tonic-gate bytesleft = PRARGSZ; 1667*7c478bd9Sstevel@tonic-gate for (cp = psinfo->pr_psargs; *cp != '\0'; cp += length) { 1668*7c478bd9Sstevel@tonic-gate length = mbtowc(&wchar, cp, MB_LEN_MAX); 1669*7c478bd9Sstevel@tonic-gate if (length == 0) 1670*7c478bd9Sstevel@tonic-gate break; 1671*7c478bd9Sstevel@tonic-gate if (length < 0 || !iswprint(wchar)) { 1672*7c478bd9Sstevel@tonic-gate if (length < 0) 1673*7c478bd9Sstevel@tonic-gate length = 1; 1674*7c478bd9Sstevel@tonic-gate if (bytesleft <= length) { 1675*7c478bd9Sstevel@tonic-gate *cp = '\0'; 1676*7c478bd9Sstevel@tonic-gate break; 1677*7c478bd9Sstevel@tonic-gate } 1678*7c478bd9Sstevel@tonic-gate /* omit the unprintable character */ 1679*7c478bd9Sstevel@tonic-gate (void) memmove(cp, cp+length, bytesleft-length); 1680*7c478bd9Sstevel@tonic-gate length = 0; 1681*7c478bd9Sstevel@tonic-gate } 1682*7c478bd9Sstevel@tonic-gate bytesleft -= length; 1683*7c478bd9Sstevel@tonic-gate } 1684*7c478bd9Sstevel@tonic-gate wcnt = namencnt(psinfo->pr_psargs, PRARGSZ, width); 1685*7c478bd9Sstevel@tonic-gate /* 1686*7c478bd9Sstevel@tonic-gate * Print full width unless this is the last format. 1687*7c478bd9Sstevel@tonic-gate */ 1688*7c478bd9Sstevel@tonic-gate if (f->next != NULL) 1689*7c478bd9Sstevel@tonic-gate (void) printf("%-*.*s", width, wcnt, 1690*7c478bd9Sstevel@tonic-gate psinfo->pr_psargs); 1691*7c478bd9Sstevel@tonic-gate else 1692*7c478bd9Sstevel@tonic-gate (void) printf("%-.*s", wcnt, 1693*7c478bd9Sstevel@tonic-gate psinfo->pr_psargs); 1694*7c478bd9Sstevel@tonic-gate if (f->fname == F_COMM && csave) 1695*7c478bd9Sstevel@tonic-gate *csave = c; 1696*7c478bd9Sstevel@tonic-gate break; 1697*7c478bd9Sstevel@tonic-gate case F_TASKID: 1698*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_taskid); 1699*7c478bd9Sstevel@tonic-gate break; 1700*7c478bd9Sstevel@tonic-gate case F_PROJID: 1701*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_projid); 1702*7c478bd9Sstevel@tonic-gate break; 1703*7c478bd9Sstevel@tonic-gate case F_PROJECT: 1704*7c478bd9Sstevel@tonic-gate { 1705*7c478bd9Sstevel@tonic-gate struct project cproj; 1706*7c478bd9Sstevel@tonic-gate char proj_buf[PROJECT_BUFSZ]; 1707*7c478bd9Sstevel@tonic-gate 1708*7c478bd9Sstevel@tonic-gate if ((getprojbyid(psinfo->pr_projid, &cproj, 1709*7c478bd9Sstevel@tonic-gate (void *)&proj_buf, PROJECT_BUFSZ)) == NULL) 1710*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, 1711*7c478bd9Sstevel@tonic-gate (int)psinfo->pr_projid); 1712*7c478bd9Sstevel@tonic-gate else 1713*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, 1714*7c478bd9Sstevel@tonic-gate (cproj.pj_name != NULL) ? 1715*7c478bd9Sstevel@tonic-gate cproj.pj_name : "---"); 1716*7c478bd9Sstevel@tonic-gate } 1717*7c478bd9Sstevel@tonic-gate break; 1718*7c478bd9Sstevel@tonic-gate case F_PSET: 1719*7c478bd9Sstevel@tonic-gate if (zombie_lwp || psinfo->pr_lwp.pr_bindpset == PS_NONE) 1720*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1721*7c478bd9Sstevel@tonic-gate else 1722*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, psinfo->pr_lwp.pr_bindpset); 1723*7c478bd9Sstevel@tonic-gate break; 1724*7c478bd9Sstevel@tonic-gate case F_ZONEID: 1725*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, (int)psinfo->pr_zoneid); 1726*7c478bd9Sstevel@tonic-gate break; 1727*7c478bd9Sstevel@tonic-gate case F_ZONE: 1728*7c478bd9Sstevel@tonic-gate { 1729*7c478bd9Sstevel@tonic-gate char zonename[ZONENAME_MAX]; 1730*7c478bd9Sstevel@tonic-gate 1731*7c478bd9Sstevel@tonic-gate if (getzonenamebyid(psinfo->pr_zoneid, zonename, 1732*7c478bd9Sstevel@tonic-gate sizeof (zonename)) < 0) { 1733*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, 1734*7c478bd9Sstevel@tonic-gate ((int)psinfo->pr_zoneid)); 1735*7c478bd9Sstevel@tonic-gate } else { 1736*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, zonename); 1737*7c478bd9Sstevel@tonic-gate } 1738*7c478bd9Sstevel@tonic-gate } 1739*7c478bd9Sstevel@tonic-gate break; 1740*7c478bd9Sstevel@tonic-gate case F_CTID: 1741*7c478bd9Sstevel@tonic-gate if (psinfo->pr_contract == -1) 1742*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1743*7c478bd9Sstevel@tonic-gate else 1744*7c478bd9Sstevel@tonic-gate (void) printf("%*ld", width, (long)psinfo->pr_contract); 1745*7c478bd9Sstevel@tonic-gate break; 1746*7c478bd9Sstevel@tonic-gate } 1747*7c478bd9Sstevel@tonic-gate } 1748*7c478bd9Sstevel@tonic-gate 1749*7c478bd9Sstevel@tonic-gate static void 1750*7c478bd9Sstevel@tonic-gate print_zombie_field(psinfo_t *psinfo, struct field *f, const char *ttyp) 1751*7c478bd9Sstevel@tonic-gate { 1752*7c478bd9Sstevel@tonic-gate int wcnt; 1753*7c478bd9Sstevel@tonic-gate int width = f->width; 1754*7c478bd9Sstevel@tonic-gate 1755*7c478bd9Sstevel@tonic-gate switch (f->fname) { 1756*7c478bd9Sstevel@tonic-gate case F_FNAME: 1757*7c478bd9Sstevel@tonic-gate case F_COMM: 1758*7c478bd9Sstevel@tonic-gate case F_ARGS: 1759*7c478bd9Sstevel@tonic-gate /* 1760*7c478bd9Sstevel@tonic-gate * Print full width unless this is the last output format. 1761*7c478bd9Sstevel@tonic-gate */ 1762*7c478bd9Sstevel@tonic-gate wcnt = min(width, sizeof ("<defunct>")); 1763*7c478bd9Sstevel@tonic-gate if (f->next != NULL) 1764*7c478bd9Sstevel@tonic-gate (void) printf("%-*.*s", width, wcnt, "<defunct>"); 1765*7c478bd9Sstevel@tonic-gate else 1766*7c478bd9Sstevel@tonic-gate (void) printf("%-.*s", wcnt, "<defunct>"); 1767*7c478bd9Sstevel@tonic-gate break; 1768*7c478bd9Sstevel@tonic-gate 1769*7c478bd9Sstevel@tonic-gate case F_PSR: 1770*7c478bd9Sstevel@tonic-gate case F_PCPU: 1771*7c478bd9Sstevel@tonic-gate case F_PMEM: 1772*7c478bd9Sstevel@tonic-gate case F_NICE: 1773*7c478bd9Sstevel@tonic-gate case F_CLASS: 1774*7c478bd9Sstevel@tonic-gate case F_STIME: 1775*7c478bd9Sstevel@tonic-gate case F_ETIME: 1776*7c478bd9Sstevel@tonic-gate case F_WCHAN: 1777*7c478bd9Sstevel@tonic-gate case F_PSET: 1778*7c478bd9Sstevel@tonic-gate (void) printf("%*s", width, "-"); 1779*7c478bd9Sstevel@tonic-gate break; 1780*7c478bd9Sstevel@tonic-gate 1781*7c478bd9Sstevel@tonic-gate case F_OPRI: 1782*7c478bd9Sstevel@tonic-gate case F_PRI: 1783*7c478bd9Sstevel@tonic-gate case F_OSZ: 1784*7c478bd9Sstevel@tonic-gate case F_VSZ: 1785*7c478bd9Sstevel@tonic-gate case F_RSS: 1786*7c478bd9Sstevel@tonic-gate (void) printf("%*d", width, 0); 1787*7c478bd9Sstevel@tonic-gate break; 1788*7c478bd9Sstevel@tonic-gate 1789*7c478bd9Sstevel@tonic-gate default: 1790*7c478bd9Sstevel@tonic-gate print_field(psinfo, f, ttyp); 1791*7c478bd9Sstevel@tonic-gate break; 1792*7c478bd9Sstevel@tonic-gate } 1793*7c478bd9Sstevel@tonic-gate } 1794*7c478bd9Sstevel@tonic-gate 1795*7c478bd9Sstevel@tonic-gate static void 1796*7c478bd9Sstevel@tonic-gate pr_fields(psinfo_t *psinfo, const char *ttyp, 1797*7c478bd9Sstevel@tonic-gate void (*print_fld)(psinfo_t *, struct field *, const char *)) 1798*7c478bd9Sstevel@tonic-gate { 1799*7c478bd9Sstevel@tonic-gate struct field *f; 1800*7c478bd9Sstevel@tonic-gate 1801*7c478bd9Sstevel@tonic-gate for (f = fields; f != NULL; f = f->next) { 1802*7c478bd9Sstevel@tonic-gate print_fld(psinfo, f, ttyp); 1803*7c478bd9Sstevel@tonic-gate if (f->next != NULL) 1804*7c478bd9Sstevel@tonic-gate (void) printf(" "); 1805*7c478bd9Sstevel@tonic-gate } 1806*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1807*7c478bd9Sstevel@tonic-gate } 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate /* 1810*7c478bd9Sstevel@tonic-gate * Returns 1 if arg is found in array arr, of length num; 0 otherwise. 1811*7c478bd9Sstevel@tonic-gate */ 1812*7c478bd9Sstevel@tonic-gate static int 1813*7c478bd9Sstevel@tonic-gate search(pid_t *arr, int number, pid_t arg) 1814*7c478bd9Sstevel@tonic-gate { 1815*7c478bd9Sstevel@tonic-gate int i; 1816*7c478bd9Sstevel@tonic-gate 1817*7c478bd9Sstevel@tonic-gate for (i = 0; i < number; i++) 1818*7c478bd9Sstevel@tonic-gate if (arg == arr[i]) 1819*7c478bd9Sstevel@tonic-gate return (1); 1820*7c478bd9Sstevel@tonic-gate return (0); 1821*7c478bd9Sstevel@tonic-gate } 1822*7c478bd9Sstevel@tonic-gate 1823*7c478bd9Sstevel@tonic-gate /* 1824*7c478bd9Sstevel@tonic-gate * Add an entry (user, group) to the specified table. 1825*7c478bd9Sstevel@tonic-gate */ 1826*7c478bd9Sstevel@tonic-gate static void 1827*7c478bd9Sstevel@tonic-gate add_ugentry(struct ughead *tbl, char *name) 1828*7c478bd9Sstevel@tonic-gate { 1829*7c478bd9Sstevel@tonic-gate struct ugdata *entp; 1830*7c478bd9Sstevel@tonic-gate 1831*7c478bd9Sstevel@tonic-gate if (tbl->size == tbl->nent) { /* reallocate the table entries */ 1832*7c478bd9Sstevel@tonic-gate if ((tbl->size *= 2) == 0) 1833*7c478bd9Sstevel@tonic-gate tbl->size = 32; /* first time */ 1834*7c478bd9Sstevel@tonic-gate tbl->ent = Realloc(tbl->ent, tbl->size*sizeof (struct ugdata)); 1835*7c478bd9Sstevel@tonic-gate } 1836*7c478bd9Sstevel@tonic-gate entp = &tbl->ent[tbl->nent++]; 1837*7c478bd9Sstevel@tonic-gate entp->id = 0; 1838*7c478bd9Sstevel@tonic-gate (void) strncpy(entp->name, name, MAXUGNAME); 1839*7c478bd9Sstevel@tonic-gate entp->name[MAXUGNAME] = '\0'; 1840*7c478bd9Sstevel@tonic-gate } 1841*7c478bd9Sstevel@tonic-gate 1842*7c478bd9Sstevel@tonic-gate static int 1843*7c478bd9Sstevel@tonic-gate uconv(struct ughead *uhead) 1844*7c478bd9Sstevel@tonic-gate { 1845*7c478bd9Sstevel@tonic-gate struct ugdata *utbl = uhead->ent; 1846*7c478bd9Sstevel@tonic-gate int n = uhead->nent; 1847*7c478bd9Sstevel@tonic-gate struct passwd *pwd; 1848*7c478bd9Sstevel@tonic-gate int i; 1849*7c478bd9Sstevel@tonic-gate int fnd = 0; 1850*7c478bd9Sstevel@tonic-gate uid_t uid; 1851*7c478bd9Sstevel@tonic-gate 1852*7c478bd9Sstevel@tonic-gate /* 1853*7c478bd9Sstevel@tonic-gate * Ask the name service for names. 1854*7c478bd9Sstevel@tonic-gate */ 1855*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 1856*7c478bd9Sstevel@tonic-gate /* 1857*7c478bd9Sstevel@tonic-gate * If name is numeric, ask for numeric id 1858*7c478bd9Sstevel@tonic-gate */ 1859*7c478bd9Sstevel@tonic-gate if (str2id(utbl[i].name, &uid, 0, UID_MAX) == 0) 1860*7c478bd9Sstevel@tonic-gate pwd = getpwuid(uid); 1861*7c478bd9Sstevel@tonic-gate else 1862*7c478bd9Sstevel@tonic-gate pwd = getpwnam(utbl[i].name); 1863*7c478bd9Sstevel@tonic-gate 1864*7c478bd9Sstevel@tonic-gate /* 1865*7c478bd9Sstevel@tonic-gate * If found, enter found index into tbl array. 1866*7c478bd9Sstevel@tonic-gate */ 1867*7c478bd9Sstevel@tonic-gate if (pwd == NULL) { 1868*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1869*7c478bd9Sstevel@tonic-gate gettext("ps: unknown user %s\n"), utbl[i].name); 1870*7c478bd9Sstevel@tonic-gate continue; 1871*7c478bd9Sstevel@tonic-gate } 1872*7c478bd9Sstevel@tonic-gate 1873*7c478bd9Sstevel@tonic-gate utbl[fnd].id = pwd->pw_uid; 1874*7c478bd9Sstevel@tonic-gate (void) strncpy(utbl[fnd].name, pwd->pw_name, MAXUGNAME); 1875*7c478bd9Sstevel@tonic-gate fnd++; 1876*7c478bd9Sstevel@tonic-gate } 1877*7c478bd9Sstevel@tonic-gate 1878*7c478bd9Sstevel@tonic-gate uhead->nent = fnd; /* in case it changed */ 1879*7c478bd9Sstevel@tonic-gate return (n - fnd); 1880*7c478bd9Sstevel@tonic-gate } 1881*7c478bd9Sstevel@tonic-gate 1882*7c478bd9Sstevel@tonic-gate static int 1883*7c478bd9Sstevel@tonic-gate gconv(struct ughead *ghead) 1884*7c478bd9Sstevel@tonic-gate { 1885*7c478bd9Sstevel@tonic-gate struct ugdata *gtbl = ghead->ent; 1886*7c478bd9Sstevel@tonic-gate int n = ghead->nent; 1887*7c478bd9Sstevel@tonic-gate struct group *grp; 1888*7c478bd9Sstevel@tonic-gate gid_t gid; 1889*7c478bd9Sstevel@tonic-gate int i; 1890*7c478bd9Sstevel@tonic-gate int fnd = 0; 1891*7c478bd9Sstevel@tonic-gate 1892*7c478bd9Sstevel@tonic-gate /* 1893*7c478bd9Sstevel@tonic-gate * Ask the name service for names. 1894*7c478bd9Sstevel@tonic-gate */ 1895*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) { 1896*7c478bd9Sstevel@tonic-gate /* 1897*7c478bd9Sstevel@tonic-gate * If name is numeric, ask for numeric id 1898*7c478bd9Sstevel@tonic-gate */ 1899*7c478bd9Sstevel@tonic-gate if (str2id(gtbl[i].name, &gid, 0, UID_MAX) == 0) 1900*7c478bd9Sstevel@tonic-gate grp = getgrgid(gid); 1901*7c478bd9Sstevel@tonic-gate else 1902*7c478bd9Sstevel@tonic-gate grp = getgrnam(gtbl[i].name); 1903*7c478bd9Sstevel@tonic-gate /* 1904*7c478bd9Sstevel@tonic-gate * If found, enter found index into tbl array. 1905*7c478bd9Sstevel@tonic-gate */ 1906*7c478bd9Sstevel@tonic-gate if (grp == NULL) { 1907*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1908*7c478bd9Sstevel@tonic-gate gettext("ps: unknown group %s\n"), gtbl[i].name); 1909*7c478bd9Sstevel@tonic-gate continue; 1910*7c478bd9Sstevel@tonic-gate } 1911*7c478bd9Sstevel@tonic-gate 1912*7c478bd9Sstevel@tonic-gate gtbl[fnd].id = grp->gr_gid; 1913*7c478bd9Sstevel@tonic-gate (void) strncpy(gtbl[fnd].name, grp->gr_name, MAXUGNAME); 1914*7c478bd9Sstevel@tonic-gate fnd++; 1915*7c478bd9Sstevel@tonic-gate } 1916*7c478bd9Sstevel@tonic-gate 1917*7c478bd9Sstevel@tonic-gate ghead->nent = fnd; /* in case it changed */ 1918*7c478bd9Sstevel@tonic-gate return (n - fnd); 1919*7c478bd9Sstevel@tonic-gate } 1920*7c478bd9Sstevel@tonic-gate 1921*7c478bd9Sstevel@tonic-gate /* 1922*7c478bd9Sstevel@tonic-gate * Return 1 if puid is in table, otherwise 0. 1923*7c478bd9Sstevel@tonic-gate */ 1924*7c478bd9Sstevel@tonic-gate static int 1925*7c478bd9Sstevel@tonic-gate ugfind(id_t id, struct ughead *ughead) 1926*7c478bd9Sstevel@tonic-gate { 1927*7c478bd9Sstevel@tonic-gate struct ugdata *utbl = ughead->ent; 1928*7c478bd9Sstevel@tonic-gate int n = ughead->nent; 1929*7c478bd9Sstevel@tonic-gate int i; 1930*7c478bd9Sstevel@tonic-gate 1931*7c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) 1932*7c478bd9Sstevel@tonic-gate if (utbl[i].id == id) 1933*7c478bd9Sstevel@tonic-gate return (1); 1934*7c478bd9Sstevel@tonic-gate return (0); 1935*7c478bd9Sstevel@tonic-gate } 1936*7c478bd9Sstevel@tonic-gate 1937*7c478bd9Sstevel@tonic-gate /* 1938*7c478bd9Sstevel@tonic-gate * Print starting time of process unless process started more than 24 hours 1939*7c478bd9Sstevel@tonic-gate * ago, in which case the date is printed. The date is printed in the form 1940*7c478bd9Sstevel@tonic-gate * "MMM dd" if old format, else the blank is replaced with an '_' so 1941*7c478bd9Sstevel@tonic-gate * it appears as a single word (for parseability). 1942*7c478bd9Sstevel@tonic-gate */ 1943*7c478bd9Sstevel@tonic-gate static void 1944*7c478bd9Sstevel@tonic-gate prtime(timestruc_t st, int width, int old) 1945*7c478bd9Sstevel@tonic-gate { 1946*7c478bd9Sstevel@tonic-gate char sttim[26]; 1947*7c478bd9Sstevel@tonic-gate time_t starttime; 1948*7c478bd9Sstevel@tonic-gate 1949*7c478bd9Sstevel@tonic-gate starttime = st.tv_sec; 1950*7c478bd9Sstevel@tonic-gate if (st.tv_nsec > 500000000) 1951*7c478bd9Sstevel@tonic-gate starttime++; 1952*7c478bd9Sstevel@tonic-gate if ((now.tv_sec - starttime) >= 24*60*60) { 1953*7c478bd9Sstevel@tonic-gate (void) strftime(sttim, sizeof (sttim), old? \ 1954*7c478bd9Sstevel@tonic-gate "%b %d" : "%b_%d", localtime(&starttime)); 1955*7c478bd9Sstevel@tonic-gate sttim[7] = '\0'; 1956*7c478bd9Sstevel@tonic-gate } else { 1957*7c478bd9Sstevel@tonic-gate (void) strftime(sttim, sizeof (sttim), \ 1958*7c478bd9Sstevel@tonic-gate "%H:%M:%S", localtime(&starttime)); 1959*7c478bd9Sstevel@tonic-gate sttim[8] = '\0'; 1960*7c478bd9Sstevel@tonic-gate } 1961*7c478bd9Sstevel@tonic-gate (void) printf("%*.*s", width, width, sttim); 1962*7c478bd9Sstevel@tonic-gate } 1963*7c478bd9Sstevel@tonic-gate 1964*7c478bd9Sstevel@tonic-gate static void 1965*7c478bd9Sstevel@tonic-gate przom(psinfo_t *psinfo) 1966*7c478bd9Sstevel@tonic-gate { 1967*7c478bd9Sstevel@tonic-gate long tm; 1968*7c478bd9Sstevel@tonic-gate struct passwd *pwd; 1969*7c478bd9Sstevel@tonic-gate char zonename[ZONENAME_MAX]; 1970*7c478bd9Sstevel@tonic-gate 1971*7c478bd9Sstevel@tonic-gate /* 1972*7c478bd9Sstevel@tonic-gate * All fields before 'PID' are printed with a trailing space as a 1973*7c478bd9Sstevel@tonic-gate * spearator, rather than keeping track of which column is first. All 1974*7c478bd9Sstevel@tonic-gate * other fields are printed with a leading space. 1975*7c478bd9Sstevel@tonic-gate */ 1976*7c478bd9Sstevel@tonic-gate if (lflg) { /* F S */ 1977*7c478bd9Sstevel@tonic-gate if (!yflg) 1978*7c478bd9Sstevel@tonic-gate (void) printf("%2x ", psinfo->pr_flag & 0377); /* F */ 1979*7c478bd9Sstevel@tonic-gate (void) printf("%c ", psinfo->pr_lwp.pr_sname); /* S */ 1980*7c478bd9Sstevel@tonic-gate } 1981*7c478bd9Sstevel@tonic-gate if (Zflg) { 1982*7c478bd9Sstevel@tonic-gate if (getzonenamebyid(psinfo->pr_zoneid, zonename, 1983*7c478bd9Sstevel@tonic-gate sizeof (zonename)) < 0) { 1984*7c478bd9Sstevel@tonic-gate (void) printf("%7.7d ", ((int)psinfo->pr_zoneid)); 1985*7c478bd9Sstevel@tonic-gate } else { 1986*7c478bd9Sstevel@tonic-gate (void) printf("%8.8s ", zonename); 1987*7c478bd9Sstevel@tonic-gate } 1988*7c478bd9Sstevel@tonic-gate } 1989*7c478bd9Sstevel@tonic-gate if (fflg) { 1990*7c478bd9Sstevel@tonic-gate if ((pwd = getpwuid(psinfo->pr_euid)) != NULL) 1991*7c478bd9Sstevel@tonic-gate (void) printf("%8.8s ", pwd->pw_name); 1992*7c478bd9Sstevel@tonic-gate else 1993*7c478bd9Sstevel@tonic-gate (void) printf("%7.7d ", (int)psinfo->pr_euid); 1994*7c478bd9Sstevel@tonic-gate } else if (lflg) 1995*7c478bd9Sstevel@tonic-gate (void) printf("%6d ", (int)psinfo->pr_euid); 1996*7c478bd9Sstevel@tonic-gate 1997*7c478bd9Sstevel@tonic-gate (void) printf("%*d", pidwidth, (int)psinfo->pr_pid); /* PID */ 1998*7c478bd9Sstevel@tonic-gate if (lflg || fflg) 1999*7c478bd9Sstevel@tonic-gate (void) printf(" %*d", pidwidth, 2000*7c478bd9Sstevel@tonic-gate (int)psinfo->pr_ppid); /* PPID */ 2001*7c478bd9Sstevel@tonic-gate 2002*7c478bd9Sstevel@tonic-gate if (jflg) { 2003*7c478bd9Sstevel@tonic-gate (void) printf(" %*d", pidwidth, 2004*7c478bd9Sstevel@tonic-gate (int)psinfo->pr_pgid); /* PGID */ 2005*7c478bd9Sstevel@tonic-gate (void) printf(" %*d", pidwidth, 2006*7c478bd9Sstevel@tonic-gate (int)psinfo->pr_sid); /* SID */ 2007*7c478bd9Sstevel@tonic-gate } 2008*7c478bd9Sstevel@tonic-gate 2009*7c478bd9Sstevel@tonic-gate if (Lflg) 2010*7c478bd9Sstevel@tonic-gate (void) printf(" %5d", 0); /* LWP */ 2011*7c478bd9Sstevel@tonic-gate if (Pflg) 2012*7c478bd9Sstevel@tonic-gate (void) printf(" -"); /* PSR */ 2013*7c478bd9Sstevel@tonic-gate if (Lflg && fflg) 2014*7c478bd9Sstevel@tonic-gate (void) printf(" %5d", 0); /* NLWP */ 2015*7c478bd9Sstevel@tonic-gate 2016*7c478bd9Sstevel@tonic-gate if (cflg) { 2017*7c478bd9Sstevel@tonic-gate (void) printf(" %4s", "-"); /* zombies have no class */ 2018*7c478bd9Sstevel@tonic-gate (void) printf(" %3d", psinfo->pr_lwp.pr_pri); /* PRI */ 2019*7c478bd9Sstevel@tonic-gate } else if (lflg || fflg) { 2020*7c478bd9Sstevel@tonic-gate (void) printf(" %3d", psinfo->pr_lwp.pr_cpu & 0377); /* C */ 2021*7c478bd9Sstevel@tonic-gate if (lflg) 2022*7c478bd9Sstevel@tonic-gate (void) printf(" %3d %2s", 2023*7c478bd9Sstevel@tonic-gate psinfo->pr_lwp.pr_oldpri, "-"); /* PRI NI */ 2024*7c478bd9Sstevel@tonic-gate } 2025*7c478bd9Sstevel@tonic-gate if (lflg) { 2026*7c478bd9Sstevel@tonic-gate if (yflg) /* RSS SZ WCHAN */ 2027*7c478bd9Sstevel@tonic-gate (void) printf(" %5d %6d %8s", 0, 0, "-"); 2028*7c478bd9Sstevel@tonic-gate else /* ADDR SZ WCHAN */ 2029*7c478bd9Sstevel@tonic-gate (void) printf(" %8s %6d %8s", "-", 0, "-"); 2030*7c478bd9Sstevel@tonic-gate } 2031*7c478bd9Sstevel@tonic-gate if (fflg) 2032*7c478bd9Sstevel@tonic-gate (void) printf(" %8.8s", "-"); /* STIME */ 2033*7c478bd9Sstevel@tonic-gate (void) printf(" %-8.14s", "?"); /* TTY */ 2034*7c478bd9Sstevel@tonic-gate 2035*7c478bd9Sstevel@tonic-gate tm = psinfo->pr_time.tv_sec; 2036*7c478bd9Sstevel@tonic-gate if (psinfo->pr_time.tv_nsec > 500000000) 2037*7c478bd9Sstevel@tonic-gate tm++; 2038*7c478bd9Sstevel@tonic-gate (void) printf(" %4ld:%.2ld", tm / 60, tm % 60); /* TIME */ 2039*7c478bd9Sstevel@tonic-gate (void) printf(" <defunct>\n"); 2040*7c478bd9Sstevel@tonic-gate } 2041*7c478bd9Sstevel@tonic-gate 2042*7c478bd9Sstevel@tonic-gate /* 2043*7c478bd9Sstevel@tonic-gate * Function to compute the number of printable bytes in a multibyte 2044*7c478bd9Sstevel@tonic-gate * command string ("internationalization"). 2045*7c478bd9Sstevel@tonic-gate */ 2046*7c478bd9Sstevel@tonic-gate static int 2047*7c478bd9Sstevel@tonic-gate namencnt(char *cmd, int csisize, int scrsize) 2048*7c478bd9Sstevel@tonic-gate { 2049*7c478bd9Sstevel@tonic-gate int csiwcnt = 0, scrwcnt = 0; 2050*7c478bd9Sstevel@tonic-gate int ncsisz, nscrsz; 2051*7c478bd9Sstevel@tonic-gate wchar_t wchar; 2052*7c478bd9Sstevel@tonic-gate int len; 2053*7c478bd9Sstevel@tonic-gate 2054*7c478bd9Sstevel@tonic-gate while (*cmd != '\0') { 2055*7c478bd9Sstevel@tonic-gate if ((len = csisize - csiwcnt) > (int)MB_CUR_MAX) 2056*7c478bd9Sstevel@tonic-gate len = MB_CUR_MAX; 2057*7c478bd9Sstevel@tonic-gate if ((ncsisz = mbtowc(&wchar, cmd, len)) < 0) 2058*7c478bd9Sstevel@tonic-gate return (8); /* default to use for illegal chars */ 2059*7c478bd9Sstevel@tonic-gate if ((nscrsz = wcwidth(wchar)) <= 0) 2060*7c478bd9Sstevel@tonic-gate return (8); 2061*7c478bd9Sstevel@tonic-gate if (csiwcnt + ncsisz > csisize || scrwcnt + nscrsz > scrsize) 2062*7c478bd9Sstevel@tonic-gate break; 2063*7c478bd9Sstevel@tonic-gate csiwcnt += ncsisz; 2064*7c478bd9Sstevel@tonic-gate scrwcnt += nscrsz; 2065*7c478bd9Sstevel@tonic-gate cmd += ncsisz; 2066*7c478bd9Sstevel@tonic-gate } 2067*7c478bd9Sstevel@tonic-gate return (csiwcnt); 2068*7c478bd9Sstevel@tonic-gate } 2069*7c478bd9Sstevel@tonic-gate 2070*7c478bd9Sstevel@tonic-gate static char * 2071*7c478bd9Sstevel@tonic-gate err_string(int err) 2072*7c478bd9Sstevel@tonic-gate { 2073*7c478bd9Sstevel@tonic-gate static char buf[32]; 2074*7c478bd9Sstevel@tonic-gate char *str = strerror(err); 2075*7c478bd9Sstevel@tonic-gate 2076*7c478bd9Sstevel@tonic-gate if (str == NULL) 2077*7c478bd9Sstevel@tonic-gate (void) snprintf(str = buf, sizeof (buf), "Errno #%d", err); 2078*7c478bd9Sstevel@tonic-gate 2079*7c478bd9Sstevel@tonic-gate return (str); 2080*7c478bd9Sstevel@tonic-gate } 2081*7c478bd9Sstevel@tonic-gate 2082*7c478bd9Sstevel@tonic-gate /* If allocation fails, die */ 2083*7c478bd9Sstevel@tonic-gate static void * 2084*7c478bd9Sstevel@tonic-gate Realloc(void *ptr, size_t size) 2085*7c478bd9Sstevel@tonic-gate { 2086*7c478bd9Sstevel@tonic-gate ptr = realloc(ptr, size); 2087*7c478bd9Sstevel@tonic-gate if (ptr == NULL) { 2088*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("ps: no memory\n")); 2089*7c478bd9Sstevel@tonic-gate exit(1); 2090*7c478bd9Sstevel@tonic-gate } 2091*7c478bd9Sstevel@tonic-gate return (ptr); 2092*7c478bd9Sstevel@tonic-gate } 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate static time_t 2095*7c478bd9Sstevel@tonic-gate delta_secs(const timestruc_t *start) 2096*7c478bd9Sstevel@tonic-gate { 2097*7c478bd9Sstevel@tonic-gate time_t seconds = now.tv_sec - start->tv_sec; 2098*7c478bd9Sstevel@tonic-gate long nanosecs = now.tv_usec * 1000 - start->tv_nsec; 2099*7c478bd9Sstevel@tonic-gate 2100*7c478bd9Sstevel@tonic-gate if (nanosecs >= (NANOSEC / 2)) 2101*7c478bd9Sstevel@tonic-gate seconds++; 2102*7c478bd9Sstevel@tonic-gate else if (nanosecs < -(NANOSEC / 2)) 2103*7c478bd9Sstevel@tonic-gate seconds--; 2104*7c478bd9Sstevel@tonic-gate 2105*7c478bd9Sstevel@tonic-gate return (seconds); 2106*7c478bd9Sstevel@tonic-gate } 2107*7c478bd9Sstevel@tonic-gate 2108*7c478bd9Sstevel@tonic-gate /* 2109*7c478bd9Sstevel@tonic-gate * Returns the following: 2110*7c478bd9Sstevel@tonic-gate * 2111*7c478bd9Sstevel@tonic-gate * 0 No error 2112*7c478bd9Sstevel@tonic-gate * EINVAL Invalid number 2113*7c478bd9Sstevel@tonic-gate * ERANGE Value exceeds (min, max) range 2114*7c478bd9Sstevel@tonic-gate */ 2115*7c478bd9Sstevel@tonic-gate static int 2116*7c478bd9Sstevel@tonic-gate str2id(const char *p, pid_t *val, long min, long max) 2117*7c478bd9Sstevel@tonic-gate { 2118*7c478bd9Sstevel@tonic-gate char *q; 2119*7c478bd9Sstevel@tonic-gate long number; 2120*7c478bd9Sstevel@tonic-gate int error; 2121*7c478bd9Sstevel@tonic-gate 2122*7c478bd9Sstevel@tonic-gate errno = 0; 2123*7c478bd9Sstevel@tonic-gate number = strtol(p, &q, 10); 2124*7c478bd9Sstevel@tonic-gate 2125*7c478bd9Sstevel@tonic-gate if (errno != 0 || q == p || *q != '\0') { 2126*7c478bd9Sstevel@tonic-gate if ((error = errno) == 0) { 2127*7c478bd9Sstevel@tonic-gate /* 2128*7c478bd9Sstevel@tonic-gate * strtol() can fail without setting errno, or it can 2129*7c478bd9Sstevel@tonic-gate * set it to EINVAL or ERANGE. In the case errno is 2130*7c478bd9Sstevel@tonic-gate * still zero, return EINVAL. 2131*7c478bd9Sstevel@tonic-gate */ 2132*7c478bd9Sstevel@tonic-gate error = EINVAL; 2133*7c478bd9Sstevel@tonic-gate } 2134*7c478bd9Sstevel@tonic-gate } else if (number < min || number > max) { 2135*7c478bd9Sstevel@tonic-gate error = ERANGE; 2136*7c478bd9Sstevel@tonic-gate } else { 2137*7c478bd9Sstevel@tonic-gate error = 0; 2138*7c478bd9Sstevel@tonic-gate } 2139*7c478bd9Sstevel@tonic-gate 2140*7c478bd9Sstevel@tonic-gate *val = number; 2141*7c478bd9Sstevel@tonic-gate 2142*7c478bd9Sstevel@tonic-gate return (error); 2143*7c478bd9Sstevel@tonic-gate } 2144*7c478bd9Sstevel@tonic-gate 2145*7c478bd9Sstevel@tonic-gate static int 2146*7c478bd9Sstevel@tonic-gate pidcmp(const void *p1, const void *p2) 2147*7c478bd9Sstevel@tonic-gate { 2148*7c478bd9Sstevel@tonic-gate pid_t i = *((pid_t *)p1); 2149*7c478bd9Sstevel@tonic-gate pid_t j = *((pid_t *)p2); 2150*7c478bd9Sstevel@tonic-gate 2151*7c478bd9Sstevel@tonic-gate return (i - j); 2152*7c478bd9Sstevel@tonic-gate } 2153