1*8822SCasper.Dik@Sun.COM /*
2*8822SCasper.Dik@Sun.COM * CDDL HEADER START
3*8822SCasper.Dik@Sun.COM *
4*8822SCasper.Dik@Sun.COM * The contents of this file are subject to the terms of the
5*8822SCasper.Dik@Sun.COM * Common Development and Distribution License (the "License").
6*8822SCasper.Dik@Sun.COM * You may not use this file except in compliance with the License.
7*8822SCasper.Dik@Sun.COM *
8*8822SCasper.Dik@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8822SCasper.Dik@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*8822SCasper.Dik@Sun.COM * See the License for the specific language governing permissions
11*8822SCasper.Dik@Sun.COM * and limitations under the License.
12*8822SCasper.Dik@Sun.COM *
13*8822SCasper.Dik@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*8822SCasper.Dik@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8822SCasper.Dik@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*8822SCasper.Dik@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*8822SCasper.Dik@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*8822SCasper.Dik@Sun.COM *
19*8822SCasper.Dik@Sun.COM * CDDL HEADER END
20*8822SCasper.Dik@Sun.COM */
21*8822SCasper.Dik@Sun.COM /*
22*8822SCasper.Dik@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23*8822SCasper.Dik@Sun.COM * Use is subject to license terms.
24*8822SCasper.Dik@Sun.COM */
25*8822SCasper.Dik@Sun.COM
26*8822SCasper.Dik@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27*8822SCasper.Dik@Sun.COM /* All Rights Reserved */
28*8822SCasper.Dik@Sun.COM
29*8822SCasper.Dik@Sun.COM /*
30*8822SCasper.Dik@Sun.COM * University Copyright- Copyright (c) 1982, 1986, 1988
31*8822SCasper.Dik@Sun.COM * The Regents of the University of California
32*8822SCasper.Dik@Sun.COM * All Rights Reserved
33*8822SCasper.Dik@Sun.COM *
34*8822SCasper.Dik@Sun.COM * University Acknowledgment- Portions of this document are derived from
35*8822SCasper.Dik@Sun.COM * software developed by the University of California, Berkeley, and its
36*8822SCasper.Dik@Sun.COM * contributors.
37*8822SCasper.Dik@Sun.COM */
38*8822SCasper.Dik@Sun.COM
39*8822SCasper.Dik@Sun.COM /*
40*8822SCasper.Dik@Sun.COM * ps -- print things about processes.
41*8822SCasper.Dik@Sun.COM */
42*8822SCasper.Dik@Sun.COM
43*8822SCasper.Dik@Sun.COM #define _SYSCALL32
44*8822SCasper.Dik@Sun.COM
45*8822SCasper.Dik@Sun.COM #include <stdio.h>
46*8822SCasper.Dik@Sun.COM #include <ctype.h>
47*8822SCasper.Dik@Sun.COM #include <string.h>
48*8822SCasper.Dik@Sun.COM #include <errno.h>
49*8822SCasper.Dik@Sun.COM #include <fcntl.h>
50*8822SCasper.Dik@Sun.COM #include <pwd.h>
51*8822SCasper.Dik@Sun.COM #include <sys/types.h>
52*8822SCasper.Dik@Sun.COM #include <sys/stat.h>
53*8822SCasper.Dik@Sun.COM #include <sys/mkdev.h>
54*8822SCasper.Dik@Sun.COM #include <unistd.h>
55*8822SCasper.Dik@Sun.COM #include <stdlib.h>
56*8822SCasper.Dik@Sun.COM #include <limits.h>
57*8822SCasper.Dik@Sun.COM #include <dirent.h>
58*8822SCasper.Dik@Sun.COM #include <procfs.h>
59*8822SCasper.Dik@Sun.COM #include <sys/param.h>
60*8822SCasper.Dik@Sun.COM #include <sys/ttold.h>
61*8822SCasper.Dik@Sun.COM #include <libelf.h>
62*8822SCasper.Dik@Sun.COM #include <gelf.h>
63*8822SCasper.Dik@Sun.COM #include <locale.h>
64*8822SCasper.Dik@Sun.COM #include <wctype.h>
65*8822SCasper.Dik@Sun.COM #include <stdarg.h>
66*8822SCasper.Dik@Sun.COM #include <sys/proc.h>
67*8822SCasper.Dik@Sun.COM #include <priv_utils.h>
68*8822SCasper.Dik@Sun.COM
69*8822SCasper.Dik@Sun.COM #define NTTYS 2 /* max ttys that can be specified with the -t option */
70*8822SCasper.Dik@Sun.COM /* only one tty can be specified with SunOS ps */
71*8822SCasper.Dik@Sun.COM #define SIZ 30 /* max processes that can be specified with -p and -g */
72*8822SCasper.Dik@Sun.COM #define ARGSIZ 30 /* size of buffer holding args for -t, -p, -u options */
73*8822SCasper.Dik@Sun.COM
74*8822SCasper.Dik@Sun.COM #define FSTYPE_MAX 8
75*8822SCasper.Dik@Sun.COM
76*8822SCasper.Dik@Sun.COM struct psent {
77*8822SCasper.Dik@Sun.COM psinfo_t *psinfo;
78*8822SCasper.Dik@Sun.COM char *psargs;
79*8822SCasper.Dik@Sun.COM int found;
80*8822SCasper.Dik@Sun.COM };
81*8822SCasper.Dik@Sun.COM
82*8822SCasper.Dik@Sun.COM static int tplen, maxlen, twidth;
83*8822SCasper.Dik@Sun.COM static char hdr[81];
84*8822SCasper.Dik@Sun.COM static struct winsize win;
85*8822SCasper.Dik@Sun.COM
86*8822SCasper.Dik@Sun.COM static int retcode = 1;
87*8822SCasper.Dik@Sun.COM static int lflg; /* long format */
88*8822SCasper.Dik@Sun.COM static int uflg; /* user-oriented output */
89*8822SCasper.Dik@Sun.COM static int aflg; /* Display all processes */
90*8822SCasper.Dik@Sun.COM static int eflg; /* Display environment as well as arguments */
91*8822SCasper.Dik@Sun.COM static int gflg; /* Display process group leaders */
92*8822SCasper.Dik@Sun.COM static int tflg; /* Processes running on specific terminals */
93*8822SCasper.Dik@Sun.COM static int rflg; /* Running processes only flag */
94*8822SCasper.Dik@Sun.COM static int Sflg; /* Accumulated time plus all reaped children */
95*8822SCasper.Dik@Sun.COM static int xflg; /* Include processes with no controlling tty */
96*8822SCasper.Dik@Sun.COM static int cflg; /* Display command name */
97*8822SCasper.Dik@Sun.COM static int vflg; /* Virtual memory-oriented output */
98*8822SCasper.Dik@Sun.COM static int nflg; /* Numerical output */
99*8822SCasper.Dik@Sun.COM static int pflg; /* Specific process id passed as argument */
100*8822SCasper.Dik@Sun.COM static int Uflg; /* Update private database, ups_data */
101*8822SCasper.Dik@Sun.COM static int errflg;
102*8822SCasper.Dik@Sun.COM
103*8822SCasper.Dik@Sun.COM static char *gettty();
104*8822SCasper.Dik@Sun.COM static char argbuf[ARGSIZ];
105*8822SCasper.Dik@Sun.COM static char *parg;
106*8822SCasper.Dik@Sun.COM static char *p1; /* points to successive option arguments */
107*8822SCasper.Dik@Sun.COM static uid_t my_uid;
108*8822SCasper.Dik@Sun.COM static char stdbuf[BUFSIZ];
109*8822SCasper.Dik@Sun.COM
110*8822SCasper.Dik@Sun.COM static int ndev; /* number of devices */
111*8822SCasper.Dik@Sun.COM static int maxdev; /* number of devl structures allocated */
112*8822SCasper.Dik@Sun.COM
113*8822SCasper.Dik@Sun.COM #define DNINCR 100
114*8822SCasper.Dik@Sun.COM #define DNSIZE 14
115*8822SCasper.Dik@Sun.COM static struct devl { /* device list */
116*8822SCasper.Dik@Sun.COM char dname[DNSIZE]; /* device name */
117*8822SCasper.Dik@Sun.COM dev_t ddev; /* device number */
118*8822SCasper.Dik@Sun.COM } *devl;
119*8822SCasper.Dik@Sun.COM
120*8822SCasper.Dik@Sun.COM static struct tty {
121*8822SCasper.Dik@Sun.COM char *tname;
122*8822SCasper.Dik@Sun.COM dev_t tdev;
123*8822SCasper.Dik@Sun.COM } tty[NTTYS]; /* for t option */
124*8822SCasper.Dik@Sun.COM static int ntty = 0;
125*8822SCasper.Dik@Sun.COM static pid_t pidsave;
126*8822SCasper.Dik@Sun.COM static int pidwidth;
127*8822SCasper.Dik@Sun.COM
128*8822SCasper.Dik@Sun.COM static char *procdir = "/proc"; /* standard /proc directory */
129*8822SCasper.Dik@Sun.COM static void usage(); /* print usage message and quit */
130*8822SCasper.Dik@Sun.COM static void getarg(void);
131*8822SCasper.Dik@Sun.COM static void prtime(timestruc_t st);
132*8822SCasper.Dik@Sun.COM static void przom(psinfo_t *psinfo);
133*8822SCasper.Dik@Sun.COM static int num(char *);
134*8822SCasper.Dik@Sun.COM static int preadargs(int, psinfo_t *, char *);
135*8822SCasper.Dik@Sun.COM static int preadenvs(int, psinfo_t *, char *);
136*8822SCasper.Dik@Sun.COM static int prcom(int, psinfo_t *, char *);
137*8822SCasper.Dik@Sun.COM static int namencnt(char *, int, int);
138*8822SCasper.Dik@Sun.COM static int pscompare(const void *, const void *);
139*8822SCasper.Dik@Sun.COM static char *err_string(int);
140*8822SCasper.Dik@Sun.COM
141*8822SCasper.Dik@Sun.COM extern int scrwidth(wchar_t); /* header file? */
142*8822SCasper.Dik@Sun.COM
143*8822SCasper.Dik@Sun.COM int
ucbmain(int argc,char ** argv)144*8822SCasper.Dik@Sun.COM ucbmain(int argc, char **argv)
145*8822SCasper.Dik@Sun.COM {
146*8822SCasper.Dik@Sun.COM psinfo_t info; /* process information structure from /proc */
147*8822SCasper.Dik@Sun.COM char *psargs = NULL; /* pointer to buffer for -w and -ww options */
148*8822SCasper.Dik@Sun.COM char *svpsargs = NULL;
149*8822SCasper.Dik@Sun.COM struct psent *psent;
150*8822SCasper.Dik@Sun.COM int entsize;
151*8822SCasper.Dik@Sun.COM int nent;
152*8822SCasper.Dik@Sun.COM pid_t maxpid;
153*8822SCasper.Dik@Sun.COM
154*8822SCasper.Dik@Sun.COM struct tty *ttyp = tty;
155*8822SCasper.Dik@Sun.COM char *tmp;
156*8822SCasper.Dik@Sun.COM char *p;
157*8822SCasper.Dik@Sun.COM int c;
158*8822SCasper.Dik@Sun.COM pid_t pid; /* pid: process id */
159*8822SCasper.Dik@Sun.COM pid_t ppid; /* ppid: parent process id */
160*8822SCasper.Dik@Sun.COM int i, found;
161*8822SCasper.Dik@Sun.COM
162*8822SCasper.Dik@Sun.COM size_t size;
163*8822SCasper.Dik@Sun.COM
164*8822SCasper.Dik@Sun.COM DIR *dirp;
165*8822SCasper.Dik@Sun.COM struct dirent *dentp;
166*8822SCasper.Dik@Sun.COM char psname[100];
167*8822SCasper.Dik@Sun.COM char asname[100];
168*8822SCasper.Dik@Sun.COM int pdlen;
169*8822SCasper.Dik@Sun.COM size_t len;
170*8822SCasper.Dik@Sun.COM
171*8822SCasper.Dik@Sun.COM (void) setlocale(LC_ALL, "");
172*8822SCasper.Dik@Sun.COM
173*8822SCasper.Dik@Sun.COM my_uid = getuid();
174*8822SCasper.Dik@Sun.COM
175*8822SCasper.Dik@Sun.COM /*
176*8822SCasper.Dik@Sun.COM * This program needs the proc_owner privilege
177*8822SCasper.Dik@Sun.COM */
178*8822SCasper.Dik@Sun.COM (void) __init_suid_priv(PU_CLEARLIMITSET, PRIV_PROC_OWNER,
179*8822SCasper.Dik@Sun.COM (char *)NULL);
180*8822SCasper.Dik@Sun.COM
181*8822SCasper.Dik@Sun.COM /*
182*8822SCasper.Dik@Sun.COM * calculate width of pid fields based on configured MAXPID
183*8822SCasper.Dik@Sun.COM * (must be at least 5 to retain output format compatibility)
184*8822SCasper.Dik@Sun.COM */
185*8822SCasper.Dik@Sun.COM maxpid = (pid_t)sysconf(_SC_MAXPID);
186*8822SCasper.Dik@Sun.COM pidwidth = 1;
187*8822SCasper.Dik@Sun.COM while ((maxpid /= 10) > 0)
188*8822SCasper.Dik@Sun.COM ++pidwidth;
189*8822SCasper.Dik@Sun.COM pidwidth = pidwidth < 5 ? 5 : pidwidth;
190*8822SCasper.Dik@Sun.COM
191*8822SCasper.Dik@Sun.COM if (ioctl(1, TIOCGWINSZ, &win) == -1)
192*8822SCasper.Dik@Sun.COM twidth = 80;
193*8822SCasper.Dik@Sun.COM else
194*8822SCasper.Dik@Sun.COM twidth = (win.ws_col == 0 ? 80 : win.ws_col);
195*8822SCasper.Dik@Sun.COM
196*8822SCasper.Dik@Sun.COM /* add the '-' for BSD compatibility */
197*8822SCasper.Dik@Sun.COM if (argc > 1) {
198*8822SCasper.Dik@Sun.COM if (argv[1][0] != '-' && !isdigit(argv[1][0])) {
199*8822SCasper.Dik@Sun.COM len = strlen(argv[1]) + 2;
200*8822SCasper.Dik@Sun.COM tmp = malloc(len);
201*8822SCasper.Dik@Sun.COM if (tmp != NULL) {
202*8822SCasper.Dik@Sun.COM (void) snprintf(tmp, len, "%s%s", "-", argv[1]);
203*8822SCasper.Dik@Sun.COM argv[1] = tmp;
204*8822SCasper.Dik@Sun.COM }
205*8822SCasper.Dik@Sun.COM }
206*8822SCasper.Dik@Sun.COM }
207*8822SCasper.Dik@Sun.COM
208*8822SCasper.Dik@Sun.COM setbuf(stdout, stdbuf);
209*8822SCasper.Dik@Sun.COM while ((c = getopt(argc, argv, "lcaengrSt:xuvwU")) != EOF)
210*8822SCasper.Dik@Sun.COM switch (c) {
211*8822SCasper.Dik@Sun.COM case 'g':
212*8822SCasper.Dik@Sun.COM gflg++; /* include process group leaders */
213*8822SCasper.Dik@Sun.COM break;
214*8822SCasper.Dik@Sun.COM case 'c': /* display internal command name */
215*8822SCasper.Dik@Sun.COM cflg++;
216*8822SCasper.Dik@Sun.COM break;
217*8822SCasper.Dik@Sun.COM case 'r': /* restrict output to running processes */
218*8822SCasper.Dik@Sun.COM rflg++;
219*8822SCasper.Dik@Sun.COM break;
220*8822SCasper.Dik@Sun.COM case 'S': /* display time by process and all reaped children */
221*8822SCasper.Dik@Sun.COM Sflg++;
222*8822SCasper.Dik@Sun.COM break;
223*8822SCasper.Dik@Sun.COM case 'x': /* process w/o controlling tty */
224*8822SCasper.Dik@Sun.COM xflg++;
225*8822SCasper.Dik@Sun.COM break;
226*8822SCasper.Dik@Sun.COM case 'l': /* long listing */
227*8822SCasper.Dik@Sun.COM lflg++;
228*8822SCasper.Dik@Sun.COM uflg = vflg = 0;
229*8822SCasper.Dik@Sun.COM break;
230*8822SCasper.Dik@Sun.COM case 'u': /* user-oriented output */
231*8822SCasper.Dik@Sun.COM uflg++;
232*8822SCasper.Dik@Sun.COM lflg = vflg = 0;
233*8822SCasper.Dik@Sun.COM break;
234*8822SCasper.Dik@Sun.COM case 'U': /* update private database ups_data */
235*8822SCasper.Dik@Sun.COM Uflg++;
236*8822SCasper.Dik@Sun.COM break;
237*8822SCasper.Dik@Sun.COM case 'w': /* increase display width */
238*8822SCasper.Dik@Sun.COM if (twidth < 132)
239*8822SCasper.Dik@Sun.COM twidth = 132;
240*8822SCasper.Dik@Sun.COM else /* second w option */
241*8822SCasper.Dik@Sun.COM twidth = NCARGS;
242*8822SCasper.Dik@Sun.COM break;
243*8822SCasper.Dik@Sun.COM case 'v': /* display virtual memory format */
244*8822SCasper.Dik@Sun.COM vflg++;
245*8822SCasper.Dik@Sun.COM lflg = uflg = 0;
246*8822SCasper.Dik@Sun.COM break;
247*8822SCasper.Dik@Sun.COM case 'a':
248*8822SCasper.Dik@Sun.COM /*
249*8822SCasper.Dik@Sun.COM * display all processes except process group
250*8822SCasper.Dik@Sun.COM * leaders and processes w/o controlling tty
251*8822SCasper.Dik@Sun.COM */
252*8822SCasper.Dik@Sun.COM aflg++;
253*8822SCasper.Dik@Sun.COM gflg++;
254*8822SCasper.Dik@Sun.COM break;
255*8822SCasper.Dik@Sun.COM case 'e':
256*8822SCasper.Dik@Sun.COM /* Display environment along with aguments. */
257*8822SCasper.Dik@Sun.COM eflg++;
258*8822SCasper.Dik@Sun.COM break;
259*8822SCasper.Dik@Sun.COM case 'n': /* Display numerical output */
260*8822SCasper.Dik@Sun.COM nflg++;
261*8822SCasper.Dik@Sun.COM break;
262*8822SCasper.Dik@Sun.COM case 't': /* restrict output to named terminal */
263*8822SCasper.Dik@Sun.COM #define TSZ 30
264*8822SCasper.Dik@Sun.COM tflg++;
265*8822SCasper.Dik@Sun.COM gflg++;
266*8822SCasper.Dik@Sun.COM xflg = 0;
267*8822SCasper.Dik@Sun.COM
268*8822SCasper.Dik@Sun.COM p1 = optarg;
269*8822SCasper.Dik@Sun.COM do { /* only loop through once (NTTYS = 2) */
270*8822SCasper.Dik@Sun.COM parg = argbuf;
271*8822SCasper.Dik@Sun.COM if (ntty >= NTTYS-1)
272*8822SCasper.Dik@Sun.COM break;
273*8822SCasper.Dik@Sun.COM getarg();
274*8822SCasper.Dik@Sun.COM if ((p = malloc(TSZ+1)) == NULL) {
275*8822SCasper.Dik@Sun.COM (void) fprintf(stderr,
276*8822SCasper.Dik@Sun.COM "ps: no memory\n");
277*8822SCasper.Dik@Sun.COM exit(1);
278*8822SCasper.Dik@Sun.COM }
279*8822SCasper.Dik@Sun.COM p[0] = '\0';
280*8822SCasper.Dik@Sun.COM size = TSZ;
281*8822SCasper.Dik@Sun.COM if (isdigit(*parg)) {
282*8822SCasper.Dik@Sun.COM (void) strcpy(p, "tty");
283*8822SCasper.Dik@Sun.COM size -= 3;
284*8822SCasper.Dik@Sun.COM }
285*8822SCasper.Dik@Sun.COM
286*8822SCasper.Dik@Sun.COM (void) strncat(p, parg, size);
287*8822SCasper.Dik@Sun.COM ttyp->tdev = PRNODEV;
288*8822SCasper.Dik@Sun.COM if (parg && *parg == '?')
289*8822SCasper.Dik@Sun.COM xflg++;
290*8822SCasper.Dik@Sun.COM else {
291*8822SCasper.Dik@Sun.COM char nambuf[TSZ+6]; /* for /dev/+\0 */
292*8822SCasper.Dik@Sun.COM struct stat64 s;
293*8822SCasper.Dik@Sun.COM (void) strcpy(nambuf, "/dev/");
294*8822SCasper.Dik@Sun.COM (void) strcat(nambuf, p);
295*8822SCasper.Dik@Sun.COM if (stat64(nambuf, &s) == 0)
296*8822SCasper.Dik@Sun.COM ttyp->tdev = s.st_rdev;
297*8822SCasper.Dik@Sun.COM }
298*8822SCasper.Dik@Sun.COM ttyp++->tname = p;
299*8822SCasper.Dik@Sun.COM ntty++;
300*8822SCasper.Dik@Sun.COM } while (*p1);
301*8822SCasper.Dik@Sun.COM break;
302*8822SCasper.Dik@Sun.COM default: /* error on ? */
303*8822SCasper.Dik@Sun.COM errflg++;
304*8822SCasper.Dik@Sun.COM break;
305*8822SCasper.Dik@Sun.COM }
306*8822SCasper.Dik@Sun.COM
307*8822SCasper.Dik@Sun.COM if (errflg)
308*8822SCasper.Dik@Sun.COM usage();
309*8822SCasper.Dik@Sun.COM
310*8822SCasper.Dik@Sun.COM if (optind + 1 < argc) { /* more than one additional argument */
311*8822SCasper.Dik@Sun.COM (void) fprintf(stderr, "ps: too many arguments\n");
312*8822SCasper.Dik@Sun.COM usage();
313*8822SCasper.Dik@Sun.COM }
314*8822SCasper.Dik@Sun.COM
315*8822SCasper.Dik@Sun.COM /*
316*8822SCasper.Dik@Sun.COM * The -U option is obsolete. Attempts to use it cause ps to exit
317*8822SCasper.Dik@Sun.COM * without printing anything.
318*8822SCasper.Dik@Sun.COM */
319*8822SCasper.Dik@Sun.COM if (Uflg)
320*8822SCasper.Dik@Sun.COM exit(0);
321*8822SCasper.Dik@Sun.COM
322*8822SCasper.Dik@Sun.COM if (optind < argc) { /* user specified a specific proc id */
323*8822SCasper.Dik@Sun.COM pflg++;
324*8822SCasper.Dik@Sun.COM p1 = argv[optind];
325*8822SCasper.Dik@Sun.COM parg = argbuf;
326*8822SCasper.Dik@Sun.COM getarg();
327*8822SCasper.Dik@Sun.COM if (!num(parg)) {
328*8822SCasper.Dik@Sun.COM (void) fprintf(stderr,
329*8822SCasper.Dik@Sun.COM "ps: %s is an invalid non-numeric argument for a process id\n", parg);
330*8822SCasper.Dik@Sun.COM usage();
331*8822SCasper.Dik@Sun.COM }
332*8822SCasper.Dik@Sun.COM pidsave = (pid_t)atol(parg);
333*8822SCasper.Dik@Sun.COM aflg = rflg = xflg = 0;
334*8822SCasper.Dik@Sun.COM gflg++;
335*8822SCasper.Dik@Sun.COM }
336*8822SCasper.Dik@Sun.COM
337*8822SCasper.Dik@Sun.COM if (tflg)
338*8822SCasper.Dik@Sun.COM ttyp->tname = NULL;
339*8822SCasper.Dik@Sun.COM
340*8822SCasper.Dik@Sun.COM /* allocate an initial guess for the number of processes */
341*8822SCasper.Dik@Sun.COM entsize = 1024;
342*8822SCasper.Dik@Sun.COM psent = malloc(entsize * sizeof (struct psent));
343*8822SCasper.Dik@Sun.COM if (psent == NULL) {
344*8822SCasper.Dik@Sun.COM (void) fprintf(stderr, "ps: no memory\n");
345*8822SCasper.Dik@Sun.COM exit(1);
346*8822SCasper.Dik@Sun.COM }
347*8822SCasper.Dik@Sun.COM nent = 0; /* no active entries yet */
348*8822SCasper.Dik@Sun.COM
349*8822SCasper.Dik@Sun.COM if (lflg) {
350*8822SCasper.Dik@Sun.COM (void) sprintf(hdr,
351*8822SCasper.Dik@Sun.COM " F UID%*s%*s %%C PRI NI SZ RSS "
352*8822SCasper.Dik@Sun.COM "WCHAN S TT TIME COMMAND", pidwidth + 1, "PID",
353*8822SCasper.Dik@Sun.COM pidwidth + 1, "PPID");
354*8822SCasper.Dik@Sun.COM } else if (uflg) {
355*8822SCasper.Dik@Sun.COM if (nflg)
356*8822SCasper.Dik@Sun.COM (void) sprintf(hdr,
357*8822SCasper.Dik@Sun.COM " UID%*s %%CPU %%MEM SZ RSS "
358*8822SCasper.Dik@Sun.COM "TT S START TIME COMMAND",
359*8822SCasper.Dik@Sun.COM pidwidth + 1, "PID");
360*8822SCasper.Dik@Sun.COM else
361*8822SCasper.Dik@Sun.COM (void) sprintf(hdr,
362*8822SCasper.Dik@Sun.COM "USER %*s %%CPU %%MEM SZ RSS "
363*8822SCasper.Dik@Sun.COM "TT S START TIME COMMAND",
364*8822SCasper.Dik@Sun.COM pidwidth + 1, "PID");
365*8822SCasper.Dik@Sun.COM } else if (vflg) {
366*8822SCasper.Dik@Sun.COM (void) sprintf(hdr,
367*8822SCasper.Dik@Sun.COM "%*s TT S TIME SIZE RSS %%CPU %%MEM "
368*8822SCasper.Dik@Sun.COM "COMMAND", pidwidth + 1, "PID");
369*8822SCasper.Dik@Sun.COM } else
370*8822SCasper.Dik@Sun.COM (void) sprintf(hdr, "%*s TT S TIME COMMAND",
371*8822SCasper.Dik@Sun.COM pidwidth + 1, "PID");
372*8822SCasper.Dik@Sun.COM
373*8822SCasper.Dik@Sun.COM twidth = twidth - strlen(hdr) + 6;
374*8822SCasper.Dik@Sun.COM (void) printf("%s\n", hdr);
375*8822SCasper.Dik@Sun.COM
376*8822SCasper.Dik@Sun.COM if (twidth > PRARGSZ && (psargs = malloc(twidth)) == NULL) {
377*8822SCasper.Dik@Sun.COM (void) fprintf(stderr, "ps: no memory\n");
378*8822SCasper.Dik@Sun.COM exit(1);
379*8822SCasper.Dik@Sun.COM }
380*8822SCasper.Dik@Sun.COM svpsargs = psargs;
381*8822SCasper.Dik@Sun.COM
382*8822SCasper.Dik@Sun.COM /*
383*8822SCasper.Dik@Sun.COM * Determine which processes to print info about by searching
384*8822SCasper.Dik@Sun.COM * the /proc directory and looking at each process.
385*8822SCasper.Dik@Sun.COM */
386*8822SCasper.Dik@Sun.COM if ((dirp = opendir(procdir)) == NULL) {
387*8822SCasper.Dik@Sun.COM (void) fprintf(stderr, "ps: cannot open PROC directory %s\n",
388*8822SCasper.Dik@Sun.COM procdir);
389*8822SCasper.Dik@Sun.COM exit(1);
390*8822SCasper.Dik@Sun.COM }
391*8822SCasper.Dik@Sun.COM
392*8822SCasper.Dik@Sun.COM (void) strcpy(psname, procdir);
393*8822SCasper.Dik@Sun.COM pdlen = strlen(psname);
394*8822SCasper.Dik@Sun.COM psname[pdlen++] = '/';
395*8822SCasper.Dik@Sun.COM
396*8822SCasper.Dik@Sun.COM /* for each active process --- */
397*8822SCasper.Dik@Sun.COM while (dentp = readdir(dirp)) {
398*8822SCasper.Dik@Sun.COM int psfd; /* file descriptor for /proc/nnnnn/psinfo */
399*8822SCasper.Dik@Sun.COM int asfd; /* file descriptor for /proc/nnnnn/as */
400*8822SCasper.Dik@Sun.COM
401*8822SCasper.Dik@Sun.COM if (dentp->d_name[0] == '.') /* skip . and .. */
402*8822SCasper.Dik@Sun.COM continue;
403*8822SCasper.Dik@Sun.COM (void) strcpy(psname + pdlen, dentp->d_name);
404*8822SCasper.Dik@Sun.COM (void) strcpy(asname, psname);
405*8822SCasper.Dik@Sun.COM (void) strcat(psname, "/psinfo");
406*8822SCasper.Dik@Sun.COM (void) strcat(asname, "/as");
407*8822SCasper.Dik@Sun.COM retry:
408*8822SCasper.Dik@Sun.COM if ((psfd = open(psname, O_RDONLY)) == -1)
409*8822SCasper.Dik@Sun.COM continue;
410*8822SCasper.Dik@Sun.COM asfd = -1;
411*8822SCasper.Dik@Sun.COM if (psargs != NULL || eflg) {
412*8822SCasper.Dik@Sun.COM
413*8822SCasper.Dik@Sun.COM /* now we need the proc_owner privilege */
414*8822SCasper.Dik@Sun.COM (void) __priv_bracket(PRIV_ON);
415*8822SCasper.Dik@Sun.COM
416*8822SCasper.Dik@Sun.COM asfd = open(asname, O_RDONLY);
417*8822SCasper.Dik@Sun.COM
418*8822SCasper.Dik@Sun.COM /* drop proc_owner privilege after open */
419*8822SCasper.Dik@Sun.COM (void) __priv_bracket(PRIV_OFF);
420*8822SCasper.Dik@Sun.COM }
421*8822SCasper.Dik@Sun.COM
422*8822SCasper.Dik@Sun.COM /*
423*8822SCasper.Dik@Sun.COM * Get the info structure for the process
424*8822SCasper.Dik@Sun.COM */
425*8822SCasper.Dik@Sun.COM if (read(psfd, &info, sizeof (info)) != sizeof (info)) {
426*8822SCasper.Dik@Sun.COM int saverr = errno;
427*8822SCasper.Dik@Sun.COM
428*8822SCasper.Dik@Sun.COM (void) close(psfd);
429*8822SCasper.Dik@Sun.COM if (asfd > 0)
430*8822SCasper.Dik@Sun.COM (void) close(asfd);
431*8822SCasper.Dik@Sun.COM if (saverr == EAGAIN)
432*8822SCasper.Dik@Sun.COM goto retry;
433*8822SCasper.Dik@Sun.COM if (saverr != ENOENT)
434*8822SCasper.Dik@Sun.COM (void) fprintf(stderr, "ps: read() on %s: %s\n",
435*8822SCasper.Dik@Sun.COM psname, err_string(saverr));
436*8822SCasper.Dik@Sun.COM continue;
437*8822SCasper.Dik@Sun.COM }
438*8822SCasper.Dik@Sun.COM (void) close(psfd);
439*8822SCasper.Dik@Sun.COM
440*8822SCasper.Dik@Sun.COM found = 0;
441*8822SCasper.Dik@Sun.COM if (info.pr_lwp.pr_state == 0) /* can't happen? */
442*8822SCasper.Dik@Sun.COM goto closeit;
443*8822SCasper.Dik@Sun.COM pid = info.pr_pid;
444*8822SCasper.Dik@Sun.COM ppid = info.pr_ppid;
445*8822SCasper.Dik@Sun.COM
446*8822SCasper.Dik@Sun.COM /* Display only process from command line */
447*8822SCasper.Dik@Sun.COM if (pflg) { /* pid in arg list */
448*8822SCasper.Dik@Sun.COM if (pidsave == pid)
449*8822SCasper.Dik@Sun.COM found++;
450*8822SCasper.Dik@Sun.COM else
451*8822SCasper.Dik@Sun.COM goto closeit;
452*8822SCasper.Dik@Sun.COM }
453*8822SCasper.Dik@Sun.COM
454*8822SCasper.Dik@Sun.COM /*
455*8822SCasper.Dik@Sun.COM * Omit "uninteresting" processes unless 'g' option.
456*8822SCasper.Dik@Sun.COM */
457*8822SCasper.Dik@Sun.COM if ((ppid == 1) && !(gflg))
458*8822SCasper.Dik@Sun.COM goto closeit;
459*8822SCasper.Dik@Sun.COM
460*8822SCasper.Dik@Sun.COM /*
461*8822SCasper.Dik@Sun.COM * Omit non-running processes for 'r' option
462*8822SCasper.Dik@Sun.COM */
463*8822SCasper.Dik@Sun.COM if (rflg &&
464*8822SCasper.Dik@Sun.COM !(info.pr_lwp.pr_sname == 'O' ||
465*8822SCasper.Dik@Sun.COM info.pr_lwp.pr_sname == 'R'))
466*8822SCasper.Dik@Sun.COM goto closeit;
467*8822SCasper.Dik@Sun.COM
468*8822SCasper.Dik@Sun.COM if (!found && !tflg && !aflg && info.pr_euid != my_uid)
469*8822SCasper.Dik@Sun.COM goto closeit;
470*8822SCasper.Dik@Sun.COM
471*8822SCasper.Dik@Sun.COM /*
472*8822SCasper.Dik@Sun.COM * Read the args for the -w and -ww cases
473*8822SCasper.Dik@Sun.COM */
474*8822SCasper.Dik@Sun.COM if (asfd > 0) {
475*8822SCasper.Dik@Sun.COM if ((psargs != NULL &&
476*8822SCasper.Dik@Sun.COM preadargs(asfd, &info, psargs) == -1) ||
477*8822SCasper.Dik@Sun.COM (eflg && preadenvs(asfd, &info, psargs) == -1)) {
478*8822SCasper.Dik@Sun.COM int saverr = errno;
479*8822SCasper.Dik@Sun.COM
480*8822SCasper.Dik@Sun.COM (void) close(asfd);
481*8822SCasper.Dik@Sun.COM if (saverr == EAGAIN)
482*8822SCasper.Dik@Sun.COM goto retry;
483*8822SCasper.Dik@Sun.COM if (saverr != ENOENT)
484*8822SCasper.Dik@Sun.COM (void) fprintf(stderr,
485*8822SCasper.Dik@Sun.COM "ps: read() on %s: %s\n",
486*8822SCasper.Dik@Sun.COM asname, err_string(saverr));
487*8822SCasper.Dik@Sun.COM continue;
488*8822SCasper.Dik@Sun.COM }
489*8822SCasper.Dik@Sun.COM } else {
490*8822SCasper.Dik@Sun.COM psargs = info.pr_psargs;
491*8822SCasper.Dik@Sun.COM }
492*8822SCasper.Dik@Sun.COM
493*8822SCasper.Dik@Sun.COM if (nent >= entsize) {
494*8822SCasper.Dik@Sun.COM entsize *= 2;
495*8822SCasper.Dik@Sun.COM psent = (struct psent *)realloc((char *)psent,
496*8822SCasper.Dik@Sun.COM entsize * sizeof (struct psent));
497*8822SCasper.Dik@Sun.COM if (psent == NULL) {
498*8822SCasper.Dik@Sun.COM (void) fprintf(stderr, "ps: no memory\n");
499*8822SCasper.Dik@Sun.COM exit(1);
500*8822SCasper.Dik@Sun.COM }
501*8822SCasper.Dik@Sun.COM }
502*8822SCasper.Dik@Sun.COM if ((psent[nent].psinfo = malloc(sizeof (psinfo_t)))
503*8822SCasper.Dik@Sun.COM == NULL) {
504*8822SCasper.Dik@Sun.COM (void) fprintf(stderr, "ps: no memory\n");
505*8822SCasper.Dik@Sun.COM exit(1);
506*8822SCasper.Dik@Sun.COM }
507*8822SCasper.Dik@Sun.COM *psent[nent].psinfo = info;
508*8822SCasper.Dik@Sun.COM if (psargs == NULL)
509*8822SCasper.Dik@Sun.COM psent[nent].psargs = NULL;
510*8822SCasper.Dik@Sun.COM else {
511*8822SCasper.Dik@Sun.COM if ((psent[nent].psargs = malloc(strlen(psargs)+1))
512*8822SCasper.Dik@Sun.COM == NULL) {
513*8822SCasper.Dik@Sun.COM (void) fprintf(stderr, "ps: no memory\n");
514*8822SCasper.Dik@Sun.COM exit(1);
515*8822SCasper.Dik@Sun.COM }
516*8822SCasper.Dik@Sun.COM (void) strcpy(psent[nent].psargs, psargs);
517*8822SCasper.Dik@Sun.COM }
518*8822SCasper.Dik@Sun.COM psent[nent].found = found;
519*8822SCasper.Dik@Sun.COM nent++;
520*8822SCasper.Dik@Sun.COM closeit:
521*8822SCasper.Dik@Sun.COM if (asfd > 0)
522*8822SCasper.Dik@Sun.COM (void) close(asfd);
523*8822SCasper.Dik@Sun.COM psargs = svpsargs;
524*8822SCasper.Dik@Sun.COM }
525*8822SCasper.Dik@Sun.COM
526*8822SCasper.Dik@Sun.COM /* revert to non-privileged user */
527*8822SCasper.Dik@Sun.COM (void) __priv_relinquish();
528*8822SCasper.Dik@Sun.COM
529*8822SCasper.Dik@Sun.COM (void) closedir(dirp);
530*8822SCasper.Dik@Sun.COM
531*8822SCasper.Dik@Sun.COM qsort((char *)psent, nent, sizeof (psent[0]), pscompare);
532*8822SCasper.Dik@Sun.COM
533*8822SCasper.Dik@Sun.COM for (i = 0; i < nent; i++) {
534*8822SCasper.Dik@Sun.COM struct psent *pp = &psent[i];
535*8822SCasper.Dik@Sun.COM if (prcom(pp->found, pp->psinfo, pp->psargs)) {
536*8822SCasper.Dik@Sun.COM (void) printf("\n");
537*8822SCasper.Dik@Sun.COM retcode = 0;
538*8822SCasper.Dik@Sun.COM }
539*8822SCasper.Dik@Sun.COM }
540*8822SCasper.Dik@Sun.COM
541*8822SCasper.Dik@Sun.COM return (retcode);
542*8822SCasper.Dik@Sun.COM }
543*8822SCasper.Dik@Sun.COM
544*8822SCasper.Dik@Sun.COM static void
usage()545*8822SCasper.Dik@Sun.COM usage() /* print usage message and quit */
546*8822SCasper.Dik@Sun.COM {
547*8822SCasper.Dik@Sun.COM static char usage1[] = "ps [ -aceglnrSuUvwx ] [ -t term ] [ num ]";
548*8822SCasper.Dik@Sun.COM
549*8822SCasper.Dik@Sun.COM (void) fprintf(stderr, "usage: %s\n", usage1);
550*8822SCasper.Dik@Sun.COM exit(1);
551*8822SCasper.Dik@Sun.COM }
552*8822SCasper.Dik@Sun.COM
553*8822SCasper.Dik@Sun.COM /*
554*8822SCasper.Dik@Sun.COM * Read the process arguments from the process.
555*8822SCasper.Dik@Sun.COM * This allows >PRARGSZ characters of arguments to be displayed but,
556*8822SCasper.Dik@Sun.COM * unlike pr_psargs[], the process may have changed them.
557*8822SCasper.Dik@Sun.COM */
558*8822SCasper.Dik@Sun.COM #define NARG 100
559*8822SCasper.Dik@Sun.COM static int
preadargs(int pfd,psinfo_t * psinfo,char * psargs)560*8822SCasper.Dik@Sun.COM preadargs(int pfd, psinfo_t *psinfo, char *psargs)
561*8822SCasper.Dik@Sun.COM {
562*8822SCasper.Dik@Sun.COM off_t argvoff = (off_t)psinfo->pr_argv;
563*8822SCasper.Dik@Sun.COM size_t len;
564*8822SCasper.Dik@Sun.COM char *psa = psargs;
565*8822SCasper.Dik@Sun.COM int bsize = twidth;
566*8822SCasper.Dik@Sun.COM int narg = NARG;
567*8822SCasper.Dik@Sun.COM off_t argv[NARG];
568*8822SCasper.Dik@Sun.COM off_t argoff;
569*8822SCasper.Dik@Sun.COM off_t nextargoff;
570*8822SCasper.Dik@Sun.COM int i;
571*8822SCasper.Dik@Sun.COM #ifdef _LP64
572*8822SCasper.Dik@Sun.COM caddr32_t argv32[NARG];
573*8822SCasper.Dik@Sun.COM int is32 = (psinfo->pr_dmodel != PR_MODEL_LP64);
574*8822SCasper.Dik@Sun.COM #endif
575*8822SCasper.Dik@Sun.COM
576*8822SCasper.Dik@Sun.COM if (psinfo->pr_nlwp == 0 ||
577*8822SCasper.Dik@Sun.COM strcmp(psinfo->pr_lwp.pr_clname, "SYS") == 0)
578*8822SCasper.Dik@Sun.COM goto out;
579*8822SCasper.Dik@Sun.COM
580*8822SCasper.Dik@Sun.COM (void) memset(psa, 0, bsize--);
581*8822SCasper.Dik@Sun.COM nextargoff = 0;
582*8822SCasper.Dik@Sun.COM errno = EIO;
583*8822SCasper.Dik@Sun.COM while (bsize > 0) {
584*8822SCasper.Dik@Sun.COM if (narg == NARG) {
585*8822SCasper.Dik@Sun.COM (void) memset(argv, 0, sizeof (argv));
586*8822SCasper.Dik@Sun.COM #ifdef _LP64
587*8822SCasper.Dik@Sun.COM if (is32) {
588*8822SCasper.Dik@Sun.COM if ((i = pread(pfd, argv32, sizeof (argv32),
589*8822SCasper.Dik@Sun.COM argvoff)) <= 0) {
590*8822SCasper.Dik@Sun.COM if (i == 0 || errno == EIO)
591*8822SCasper.Dik@Sun.COM break;
592*8822SCasper.Dik@Sun.COM return (-1);
593*8822SCasper.Dik@Sun.COM }
594*8822SCasper.Dik@Sun.COM for (i = 0; i < NARG; i++)
595*8822SCasper.Dik@Sun.COM argv[i] = argv32[i];
596*8822SCasper.Dik@Sun.COM } else
597*8822SCasper.Dik@Sun.COM #endif
598*8822SCasper.Dik@Sun.COM if ((i = pread(pfd, argv, sizeof (argv),
599*8822SCasper.Dik@Sun.COM argvoff)) <= 0) {
600*8822SCasper.Dik@Sun.COM if (i == 0 || errno == EIO)
601*8822SCasper.Dik@Sun.COM break;
602*8822SCasper.Dik@Sun.COM return (-1);
603*8822SCasper.Dik@Sun.COM }
604*8822SCasper.Dik@Sun.COM narg = 0;
605*8822SCasper.Dik@Sun.COM }
606*8822SCasper.Dik@Sun.COM if ((argoff = argv[narg++]) == 0)
607*8822SCasper.Dik@Sun.COM break;
608*8822SCasper.Dik@Sun.COM if (argoff != nextargoff &&
609*8822SCasper.Dik@Sun.COM (i = pread(pfd, psa, bsize, argoff)) <= 0) {
610*8822SCasper.Dik@Sun.COM if (i == 0 || errno == EIO)
611*8822SCasper.Dik@Sun.COM break;
612*8822SCasper.Dik@Sun.COM return (-1);
613*8822SCasper.Dik@Sun.COM }
614*8822SCasper.Dik@Sun.COM len = strlen(psa);
615*8822SCasper.Dik@Sun.COM psa += len;
616*8822SCasper.Dik@Sun.COM *psa++ = ' ';
617*8822SCasper.Dik@Sun.COM bsize -= len + 1;
618*8822SCasper.Dik@Sun.COM nextargoff = argoff + len + 1;
619*8822SCasper.Dik@Sun.COM #ifdef _LP64
620*8822SCasper.Dik@Sun.COM argvoff += is32? sizeof (caddr32_t) : sizeof (caddr_t);
621*8822SCasper.Dik@Sun.COM #else
622*8822SCasper.Dik@Sun.COM argvoff += sizeof (caddr_t);
623*8822SCasper.Dik@Sun.COM #endif
624*8822SCasper.Dik@Sun.COM }
625*8822SCasper.Dik@Sun.COM while (psa > psargs && isspace(*(psa-1)))
626*8822SCasper.Dik@Sun.COM psa--;
627*8822SCasper.Dik@Sun.COM
628*8822SCasper.Dik@Sun.COM out:
629*8822SCasper.Dik@Sun.COM *psa = '\0';
630*8822SCasper.Dik@Sun.COM if (strlen(psinfo->pr_psargs) > strlen(psargs))
631*8822SCasper.Dik@Sun.COM (void) strcpy(psargs, psinfo->pr_psargs);
632*8822SCasper.Dik@Sun.COM
633*8822SCasper.Dik@Sun.COM return (0);
634*8822SCasper.Dik@Sun.COM }
635*8822SCasper.Dik@Sun.COM
636*8822SCasper.Dik@Sun.COM /*
637*8822SCasper.Dik@Sun.COM * Read environment variables from the process.
638*8822SCasper.Dik@Sun.COM * Append them to psargs if there is room.
639*8822SCasper.Dik@Sun.COM */
640*8822SCasper.Dik@Sun.COM static int
preadenvs(int pfd,psinfo_t * psinfo,char * psargs)641*8822SCasper.Dik@Sun.COM preadenvs(int pfd, psinfo_t *psinfo, char *psargs)
642*8822SCasper.Dik@Sun.COM {
643*8822SCasper.Dik@Sun.COM off_t envpoff = (off_t)psinfo->pr_envp;
644*8822SCasper.Dik@Sun.COM int len;
645*8822SCasper.Dik@Sun.COM char *psa;
646*8822SCasper.Dik@Sun.COM char *psainit;
647*8822SCasper.Dik@Sun.COM int bsize;
648*8822SCasper.Dik@Sun.COM int nenv = NARG;
649*8822SCasper.Dik@Sun.COM off_t envp[NARG];
650*8822SCasper.Dik@Sun.COM off_t envoff;
651*8822SCasper.Dik@Sun.COM off_t nextenvoff;
652*8822SCasper.Dik@Sun.COM int i;
653*8822SCasper.Dik@Sun.COM #ifdef _LP64
654*8822SCasper.Dik@Sun.COM caddr32_t envp32[NARG];
655*8822SCasper.Dik@Sun.COM int is32 = (psinfo->pr_dmodel != PR_MODEL_LP64);
656*8822SCasper.Dik@Sun.COM #endif
657*8822SCasper.Dik@Sun.COM
658*8822SCasper.Dik@Sun.COM psainit = psa = (psargs != NULL)? psargs : psinfo->pr_psargs;
659*8822SCasper.Dik@Sun.COM len = strlen(psa);
660*8822SCasper.Dik@Sun.COM psa += len;
661*8822SCasper.Dik@Sun.COM bsize = twidth - len - 1;
662*8822SCasper.Dik@Sun.COM
663*8822SCasper.Dik@Sun.COM if (bsize <= 0 || psinfo->pr_nlwp == 0 ||
664*8822SCasper.Dik@Sun.COM strcmp(psinfo->pr_lwp.pr_clname, "SYS") == 0)
665*8822SCasper.Dik@Sun.COM return (0);
666*8822SCasper.Dik@Sun.COM
667*8822SCasper.Dik@Sun.COM nextenvoff = 0;
668*8822SCasper.Dik@Sun.COM errno = EIO;
669*8822SCasper.Dik@Sun.COM while (bsize > 0) {
670*8822SCasper.Dik@Sun.COM if (nenv == NARG) {
671*8822SCasper.Dik@Sun.COM (void) memset(envp, 0, sizeof (envp));
672*8822SCasper.Dik@Sun.COM #ifdef _LP64
673*8822SCasper.Dik@Sun.COM if (is32) {
674*8822SCasper.Dik@Sun.COM if ((i = pread(pfd, envp32, sizeof (envp32),
675*8822SCasper.Dik@Sun.COM envpoff)) <= 0) {
676*8822SCasper.Dik@Sun.COM if (i == 0 || errno == EIO)
677*8822SCasper.Dik@Sun.COM break;
678*8822SCasper.Dik@Sun.COM return (-1);
679*8822SCasper.Dik@Sun.COM }
680*8822SCasper.Dik@Sun.COM for (i = 0; i < NARG; i++)
681*8822SCasper.Dik@Sun.COM envp[i] = envp32[i];
682*8822SCasper.Dik@Sun.COM } else
683*8822SCasper.Dik@Sun.COM #endif
684*8822SCasper.Dik@Sun.COM if ((i = pread(pfd, envp, sizeof (envp),
685*8822SCasper.Dik@Sun.COM envpoff)) <= 0) {
686*8822SCasper.Dik@Sun.COM if (i == 0 || errno == EIO)
687*8822SCasper.Dik@Sun.COM break;
688*8822SCasper.Dik@Sun.COM return (-1);
689*8822SCasper.Dik@Sun.COM }
690*8822SCasper.Dik@Sun.COM nenv = 0;
691*8822SCasper.Dik@Sun.COM }
692*8822SCasper.Dik@Sun.COM if ((envoff = envp[nenv++]) == 0)
693*8822SCasper.Dik@Sun.COM break;
694*8822SCasper.Dik@Sun.COM if (envoff != nextenvoff &&
695*8822SCasper.Dik@Sun.COM (i = pread(pfd, psa+1, bsize, envoff)) <= 0) {
696*8822SCasper.Dik@Sun.COM if (i == 0 || errno == EIO)
697*8822SCasper.Dik@Sun.COM break;
698*8822SCasper.Dik@Sun.COM return (-1);
699*8822SCasper.Dik@Sun.COM }
700*8822SCasper.Dik@Sun.COM *psa++ = ' ';
701*8822SCasper.Dik@Sun.COM len = strlen(psa);
702*8822SCasper.Dik@Sun.COM psa += len;
703*8822SCasper.Dik@Sun.COM bsize -= len + 1;
704*8822SCasper.Dik@Sun.COM nextenvoff = envoff + len + 1;
705*8822SCasper.Dik@Sun.COM #ifdef _LP64
706*8822SCasper.Dik@Sun.COM envpoff += is32? sizeof (caddr32_t) : sizeof (caddr_t);
707*8822SCasper.Dik@Sun.COM #else
708*8822SCasper.Dik@Sun.COM envpoff += sizeof (caddr_t);
709*8822SCasper.Dik@Sun.COM #endif
710*8822SCasper.Dik@Sun.COM }
711*8822SCasper.Dik@Sun.COM while (psa > psainit && isspace(*(psa-1)))
712*8822SCasper.Dik@Sun.COM psa--;
713*8822SCasper.Dik@Sun.COM *psa = '\0';
714*8822SCasper.Dik@Sun.COM
715*8822SCasper.Dik@Sun.COM return (0);
716*8822SCasper.Dik@Sun.COM }
717*8822SCasper.Dik@Sun.COM
718*8822SCasper.Dik@Sun.COM /*
719*8822SCasper.Dik@Sun.COM * getarg() finds the next argument in list and copies arg into argbuf.
720*8822SCasper.Dik@Sun.COM * p1 first pts to arg passed back from getopt routine. p1 is then
721*8822SCasper.Dik@Sun.COM * bumped to next character that is not a comma or blank -- p1 NULL
722*8822SCasper.Dik@Sun.COM * indicates end of list.
723*8822SCasper.Dik@Sun.COM */
724*8822SCasper.Dik@Sun.COM
725*8822SCasper.Dik@Sun.COM static void
getarg()726*8822SCasper.Dik@Sun.COM getarg()
727*8822SCasper.Dik@Sun.COM {
728*8822SCasper.Dik@Sun.COM char *parga;
729*8822SCasper.Dik@Sun.COM int c;
730*8822SCasper.Dik@Sun.COM
731*8822SCasper.Dik@Sun.COM while ((c = *p1) != '\0' && (c == ',' || isspace(c)))
732*8822SCasper.Dik@Sun.COM p1++;
733*8822SCasper.Dik@Sun.COM
734*8822SCasper.Dik@Sun.COM parga = argbuf;
735*8822SCasper.Dik@Sun.COM while ((c = *p1) != '\0' && c != ',' && !isspace(c)) {
736*8822SCasper.Dik@Sun.COM if (parga < argbuf + ARGSIZ - 1)
737*8822SCasper.Dik@Sun.COM *parga++ = c;
738*8822SCasper.Dik@Sun.COM p1++;
739*8822SCasper.Dik@Sun.COM }
740*8822SCasper.Dik@Sun.COM *parga = '\0';
741*8822SCasper.Dik@Sun.COM
742*8822SCasper.Dik@Sun.COM while ((c = *p1) != '\0' && (c == ',' || isspace(c)))
743*8822SCasper.Dik@Sun.COM p1++;
744*8822SCasper.Dik@Sun.COM }
745*8822SCasper.Dik@Sun.COM
746*8822SCasper.Dik@Sun.COM static char *
devlookup(dev_t ddev)747*8822SCasper.Dik@Sun.COM devlookup(dev_t ddev)
748*8822SCasper.Dik@Sun.COM {
749*8822SCasper.Dik@Sun.COM struct devl *dp;
750*8822SCasper.Dik@Sun.COM int i;
751*8822SCasper.Dik@Sun.COM
752*8822SCasper.Dik@Sun.COM for (dp = devl, i = 0; i < ndev; dp++, i++) {
753*8822SCasper.Dik@Sun.COM if (dp->ddev == ddev)
754*8822SCasper.Dik@Sun.COM return (dp->dname);
755*8822SCasper.Dik@Sun.COM }
756*8822SCasper.Dik@Sun.COM return (NULL);
757*8822SCasper.Dik@Sun.COM }
758*8822SCasper.Dik@Sun.COM
759*8822SCasper.Dik@Sun.COM static char *
devadd(char * name,dev_t ddev)760*8822SCasper.Dik@Sun.COM devadd(char *name, dev_t ddev)
761*8822SCasper.Dik@Sun.COM {
762*8822SCasper.Dik@Sun.COM struct devl *dp;
763*8822SCasper.Dik@Sun.COM int leng, start, i;
764*8822SCasper.Dik@Sun.COM
765*8822SCasper.Dik@Sun.COM if (ndev == maxdev) {
766*8822SCasper.Dik@Sun.COM maxdev += DNINCR;
767*8822SCasper.Dik@Sun.COM devl = realloc(devl, maxdev * sizeof (struct devl));
768*8822SCasper.Dik@Sun.COM if (devl == NULL) {
769*8822SCasper.Dik@Sun.COM (void) fprintf(stderr,
770*8822SCasper.Dik@Sun.COM "ps: not enough memory for %d devices\n", maxdev);
771*8822SCasper.Dik@Sun.COM exit(1);
772*8822SCasper.Dik@Sun.COM }
773*8822SCasper.Dik@Sun.COM }
774*8822SCasper.Dik@Sun.COM dp = &devl[ndev++];
775*8822SCasper.Dik@Sun.COM
776*8822SCasper.Dik@Sun.COM dp->ddev = ddev;
777*8822SCasper.Dik@Sun.COM if (name == NULL) {
778*8822SCasper.Dik@Sun.COM (void) strcpy(dp->dname, "??");
779*8822SCasper.Dik@Sun.COM return (dp->dname);
780*8822SCasper.Dik@Sun.COM }
781*8822SCasper.Dik@Sun.COM
782*8822SCasper.Dik@Sun.COM leng = strlen(name);
783*8822SCasper.Dik@Sun.COM /* Strip off /dev/ */
784*8822SCasper.Dik@Sun.COM if (leng < DNSIZE + 4)
785*8822SCasper.Dik@Sun.COM (void) strcpy(dp->dname, &name[5]);
786*8822SCasper.Dik@Sun.COM else {
787*8822SCasper.Dik@Sun.COM start = leng - (DNSIZE - 1);
788*8822SCasper.Dik@Sun.COM
789*8822SCasper.Dik@Sun.COM for (i = start; i < leng && name[i] != '/'; i++)
790*8822SCasper.Dik@Sun.COM ;
791*8822SCasper.Dik@Sun.COM if (i == leng)
792*8822SCasper.Dik@Sun.COM (void) strlcpy(dp->dname, &name[start], DNSIZE);
793*8822SCasper.Dik@Sun.COM else
794*8822SCasper.Dik@Sun.COM (void) strlcpy(dp->dname, &name[i+1], DNSIZE);
795*8822SCasper.Dik@Sun.COM }
796*8822SCasper.Dik@Sun.COM return (dp->dname);
797*8822SCasper.Dik@Sun.COM }
798*8822SCasper.Dik@Sun.COM
799*8822SCasper.Dik@Sun.COM /*
800*8822SCasper.Dik@Sun.COM * gettty returns the user's tty number or ? if none.
801*8822SCasper.Dik@Sun.COM */
802*8822SCasper.Dik@Sun.COM static char *
gettty(psinfo_t * psinfo)803*8822SCasper.Dik@Sun.COM gettty(psinfo_t *psinfo)
804*8822SCasper.Dik@Sun.COM {
805*8822SCasper.Dik@Sun.COM extern char *_ttyname_dev(dev_t, char *, size_t);
806*8822SCasper.Dik@Sun.COM char devname[TTYNAME_MAX];
807*8822SCasper.Dik@Sun.COM char *retval;
808*8822SCasper.Dik@Sun.COM
809*8822SCasper.Dik@Sun.COM if (psinfo->pr_ttydev == PRNODEV)
810*8822SCasper.Dik@Sun.COM return ("?");
811*8822SCasper.Dik@Sun.COM
812*8822SCasper.Dik@Sun.COM if ((retval = devlookup(psinfo->pr_ttydev)) != NULL)
813*8822SCasper.Dik@Sun.COM return (retval);
814*8822SCasper.Dik@Sun.COM
815*8822SCasper.Dik@Sun.COM retval = _ttyname_dev(psinfo->pr_ttydev, devname, sizeof (devname));
816*8822SCasper.Dik@Sun.COM
817*8822SCasper.Dik@Sun.COM return (devadd(retval, psinfo->pr_ttydev));
818*8822SCasper.Dik@Sun.COM }
819*8822SCasper.Dik@Sun.COM
820*8822SCasper.Dik@Sun.COM /*
821*8822SCasper.Dik@Sun.COM * Print percent from 16-bit binary fraction [0 .. 1]
822*8822SCasper.Dik@Sun.COM * Round up .01 to .1 to indicate some small percentage (the 0x7000 below).
823*8822SCasper.Dik@Sun.COM */
824*8822SCasper.Dik@Sun.COM static void
prtpct(ushort_t pct)825*8822SCasper.Dik@Sun.COM prtpct(ushort_t pct)
826*8822SCasper.Dik@Sun.COM {
827*8822SCasper.Dik@Sun.COM uint_t value = pct; /* need 32 bits to compute with */
828*8822SCasper.Dik@Sun.COM
829*8822SCasper.Dik@Sun.COM value = ((value * 1000) + 0x7000) >> 15; /* [0 .. 1000] */
830*8822SCasper.Dik@Sun.COM (void) printf("%3u.%u", value / 10, value % 10);
831*8822SCasper.Dik@Sun.COM }
832*8822SCasper.Dik@Sun.COM
833*8822SCasper.Dik@Sun.COM /*
834*8822SCasper.Dik@Sun.COM * Print info about the process.
835*8822SCasper.Dik@Sun.COM */
836*8822SCasper.Dik@Sun.COM static int
prcom(int found,psinfo_t * psinfo,char * psargs)837*8822SCasper.Dik@Sun.COM prcom(int found, psinfo_t *psinfo, char *psargs)
838*8822SCasper.Dik@Sun.COM {
839*8822SCasper.Dik@Sun.COM char *cp;
840*8822SCasper.Dik@Sun.COM char *tp;
841*8822SCasper.Dik@Sun.COM char *psa;
842*8822SCasper.Dik@Sun.COM long tm;
843*8822SCasper.Dik@Sun.COM int i, wcnt, length;
844*8822SCasper.Dik@Sun.COM wchar_t wchar;
845*8822SCasper.Dik@Sun.COM struct tty *ttyp;
846*8822SCasper.Dik@Sun.COM
847*8822SCasper.Dik@Sun.COM /*
848*8822SCasper.Dik@Sun.COM * If process is zombie, call print routine and return.
849*8822SCasper.Dik@Sun.COM */
850*8822SCasper.Dik@Sun.COM if (psinfo->pr_nlwp == 0) {
851*8822SCasper.Dik@Sun.COM if (tflg && !found)
852*8822SCasper.Dik@Sun.COM return (0);
853*8822SCasper.Dik@Sun.COM else {
854*8822SCasper.Dik@Sun.COM przom(psinfo);
855*8822SCasper.Dik@Sun.COM return (1);
856*8822SCasper.Dik@Sun.COM }
857*8822SCasper.Dik@Sun.COM }
858*8822SCasper.Dik@Sun.COM
859*8822SCasper.Dik@Sun.COM /*
860*8822SCasper.Dik@Sun.COM * Get current terminal. If none ("?") and 'a' is set, don't print
861*8822SCasper.Dik@Sun.COM * info. If 't' is set, check if term is in list of desired terminals
862*8822SCasper.Dik@Sun.COM * and print it if it is.
863*8822SCasper.Dik@Sun.COM */
864*8822SCasper.Dik@Sun.COM i = 0;
865*8822SCasper.Dik@Sun.COM tp = gettty(psinfo);
866*8822SCasper.Dik@Sun.COM
867*8822SCasper.Dik@Sun.COM if (*tp == '?' && !found && !xflg)
868*8822SCasper.Dik@Sun.COM return (0);
869*8822SCasper.Dik@Sun.COM
870*8822SCasper.Dik@Sun.COM if (!(*tp == '?' && aflg) && tflg && !found) {
871*8822SCasper.Dik@Sun.COM int match = 0;
872*8822SCasper.Dik@Sun.COM char *other = NULL;
873*8822SCasper.Dik@Sun.COM for (ttyp = tty; ttyp->tname != NULL; ttyp++) {
874*8822SCasper.Dik@Sun.COM /*
875*8822SCasper.Dik@Sun.COM * Look for a name match
876*8822SCasper.Dik@Sun.COM */
877*8822SCasper.Dik@Sun.COM if (strcmp(tp, ttyp->tname) == 0) {
878*8822SCasper.Dik@Sun.COM match = 1;
879*8822SCasper.Dik@Sun.COM break;
880*8822SCasper.Dik@Sun.COM }
881*8822SCasper.Dik@Sun.COM /*
882*8822SCasper.Dik@Sun.COM * Look for same device under different names.
883*8822SCasper.Dik@Sun.COM */
884*8822SCasper.Dik@Sun.COM if ((other == NULL) &&
885*8822SCasper.Dik@Sun.COM (psinfo->pr_ttydev == ttyp->tdev))
886*8822SCasper.Dik@Sun.COM other = ttyp->tname;
887*8822SCasper.Dik@Sun.COM }
888*8822SCasper.Dik@Sun.COM if (!match) {
889*8822SCasper.Dik@Sun.COM if (other == NULL)
890*8822SCasper.Dik@Sun.COM return (0);
891*8822SCasper.Dik@Sun.COM tp = other;
892*8822SCasper.Dik@Sun.COM }
893*8822SCasper.Dik@Sun.COM }
894*8822SCasper.Dik@Sun.COM
895*8822SCasper.Dik@Sun.COM if (lflg)
896*8822SCasper.Dik@Sun.COM (void) printf("%2x", psinfo->pr_flag & 0377);
897*8822SCasper.Dik@Sun.COM if (uflg) {
898*8822SCasper.Dik@Sun.COM if (!nflg) {
899*8822SCasper.Dik@Sun.COM struct passwd *pwd;
900*8822SCasper.Dik@Sun.COM
901*8822SCasper.Dik@Sun.COM if ((pwd = getpwuid(psinfo->pr_euid)) != NULL)
902*8822SCasper.Dik@Sun.COM /* USER */
903*8822SCasper.Dik@Sun.COM (void) printf("%-8.8s", pwd->pw_name);
904*8822SCasper.Dik@Sun.COM else
905*8822SCasper.Dik@Sun.COM /* UID */
906*8822SCasper.Dik@Sun.COM (void) printf(" %7.7d", (int)psinfo->pr_euid);
907*8822SCasper.Dik@Sun.COM } else {
908*8822SCasper.Dik@Sun.COM (void) printf(" %5d", (int)psinfo->pr_euid); /* UID */
909*8822SCasper.Dik@Sun.COM }
910*8822SCasper.Dik@Sun.COM } else if (lflg)
911*8822SCasper.Dik@Sun.COM (void) printf(" %5d", (int)psinfo->pr_euid); /* UID */
912*8822SCasper.Dik@Sun.COM
913*8822SCasper.Dik@Sun.COM (void) printf("%*d", pidwidth + 1, (int)psinfo->pr_pid); /* PID */
914*8822SCasper.Dik@Sun.COM if (lflg)
915*8822SCasper.Dik@Sun.COM (void) printf("%*d", pidwidth + 1,
916*8822SCasper.Dik@Sun.COM (int)psinfo->pr_ppid); /* PPID */
917*8822SCasper.Dik@Sun.COM if (lflg)
918*8822SCasper.Dik@Sun.COM (void) printf("%3d", psinfo->pr_lwp.pr_cpu & 0377); /* CP */
919*8822SCasper.Dik@Sun.COM if (uflg) {
920*8822SCasper.Dik@Sun.COM prtpct(psinfo->pr_pctcpu); /* %CPU */
921*8822SCasper.Dik@Sun.COM prtpct(psinfo->pr_pctmem); /* %MEM */
922*8822SCasper.Dik@Sun.COM }
923*8822SCasper.Dik@Sun.COM if (lflg) {
924*8822SCasper.Dik@Sun.COM (void) printf("%4d", psinfo->pr_lwp.pr_pri); /* PRI */
925*8822SCasper.Dik@Sun.COM (void) printf("%3d", psinfo->pr_lwp.pr_nice); /* NICE */
926*8822SCasper.Dik@Sun.COM }
927*8822SCasper.Dik@Sun.COM if (lflg || uflg) {
928*8822SCasper.Dik@Sun.COM if (psinfo->pr_flag & SSYS) /* SZ */
929*8822SCasper.Dik@Sun.COM (void) printf(" 0");
930*8822SCasper.Dik@Sun.COM else if (psinfo->pr_size)
931*8822SCasper.Dik@Sun.COM (void) printf("%5lu", (ulong_t)psinfo->pr_size);
932*8822SCasper.Dik@Sun.COM else
933*8822SCasper.Dik@Sun.COM (void) printf(" ?");
934*8822SCasper.Dik@Sun.COM if (psinfo->pr_flag & SSYS) /* RSS */
935*8822SCasper.Dik@Sun.COM (void) printf(" 0");
936*8822SCasper.Dik@Sun.COM else if (psinfo->pr_rssize)
937*8822SCasper.Dik@Sun.COM (void) printf("%5lu", (ulong_t)psinfo->pr_rssize);
938*8822SCasper.Dik@Sun.COM else
939*8822SCasper.Dik@Sun.COM (void) printf(" ?");
940*8822SCasper.Dik@Sun.COM }
941*8822SCasper.Dik@Sun.COM if (lflg) { /* WCHAN */
942*8822SCasper.Dik@Sun.COM if (psinfo->pr_lwp.pr_sname != 'S') {
943*8822SCasper.Dik@Sun.COM (void) printf(" ");
944*8822SCasper.Dik@Sun.COM } else if (psinfo->pr_lwp.pr_wchan) {
945*8822SCasper.Dik@Sun.COM (void) printf(" %+8.8lx",
946*8822SCasper.Dik@Sun.COM (ulong_t)psinfo->pr_lwp.pr_wchan);
947*8822SCasper.Dik@Sun.COM } else {
948*8822SCasper.Dik@Sun.COM (void) printf(" ?");
949*8822SCasper.Dik@Sun.COM }
950*8822SCasper.Dik@Sun.COM }
951*8822SCasper.Dik@Sun.COM if ((tplen = strlen(tp)) > 9)
952*8822SCasper.Dik@Sun.COM maxlen = twidth - tplen + 9;
953*8822SCasper.Dik@Sun.COM else
954*8822SCasper.Dik@Sun.COM maxlen = twidth;
955*8822SCasper.Dik@Sun.COM
956*8822SCasper.Dik@Sun.COM if (!lflg)
957*8822SCasper.Dik@Sun.COM (void) printf(" %-8.14s", tp); /* TTY */
958*8822SCasper.Dik@Sun.COM (void) printf(" %c", psinfo->pr_lwp.pr_sname); /* STATE */
959*8822SCasper.Dik@Sun.COM if (lflg)
960*8822SCasper.Dik@Sun.COM (void) printf(" %-8.14s", tp); /* TTY */
961*8822SCasper.Dik@Sun.COM if (uflg)
962*8822SCasper.Dik@Sun.COM prtime(psinfo->pr_start); /* START */
963*8822SCasper.Dik@Sun.COM
964*8822SCasper.Dik@Sun.COM /* time just for process */
965*8822SCasper.Dik@Sun.COM tm = psinfo->pr_time.tv_sec;
966*8822SCasper.Dik@Sun.COM if (Sflg) { /* calculate time for process and all reaped children */
967*8822SCasper.Dik@Sun.COM tm += psinfo->pr_ctime.tv_sec;
968*8822SCasper.Dik@Sun.COM if (psinfo->pr_time.tv_nsec + psinfo->pr_ctime.tv_nsec
969*8822SCasper.Dik@Sun.COM >= 1000000000)
970*8822SCasper.Dik@Sun.COM tm += 1;
971*8822SCasper.Dik@Sun.COM }
972*8822SCasper.Dik@Sun.COM
973*8822SCasper.Dik@Sun.COM (void) printf(" %2ld:%.2ld", tm / 60, tm % 60); /* TIME */
974*8822SCasper.Dik@Sun.COM
975*8822SCasper.Dik@Sun.COM if (vflg) {
976*8822SCasper.Dik@Sun.COM if (psinfo->pr_flag & SSYS) /* SZ */
977*8822SCasper.Dik@Sun.COM (void) printf(" 0");
978*8822SCasper.Dik@Sun.COM else if (psinfo->pr_size)
979*8822SCasper.Dik@Sun.COM (void) printf("%5lu", (ulong_t)psinfo->pr_size);
980*8822SCasper.Dik@Sun.COM else
981*8822SCasper.Dik@Sun.COM (void) printf(" ?");
982*8822SCasper.Dik@Sun.COM if (psinfo->pr_flag & SSYS) /* SZ */
983*8822SCasper.Dik@Sun.COM (void) printf(" 0");
984*8822SCasper.Dik@Sun.COM else if (psinfo->pr_rssize)
985*8822SCasper.Dik@Sun.COM (void) printf("%5lu", (ulong_t)psinfo->pr_rssize);
986*8822SCasper.Dik@Sun.COM else
987*8822SCasper.Dik@Sun.COM (void) printf(" ?");
988*8822SCasper.Dik@Sun.COM prtpct(psinfo->pr_pctcpu); /* %CPU */
989*8822SCasper.Dik@Sun.COM prtpct(psinfo->pr_pctmem); /* %MEM */
990*8822SCasper.Dik@Sun.COM }
991*8822SCasper.Dik@Sun.COM if (cflg) { /* CMD */
992*8822SCasper.Dik@Sun.COM wcnt = namencnt(psinfo->pr_fname, 16, maxlen);
993*8822SCasper.Dik@Sun.COM (void) printf(" %.*s", wcnt, psinfo->pr_fname);
994*8822SCasper.Dik@Sun.COM return (1);
995*8822SCasper.Dik@Sun.COM }
996*8822SCasper.Dik@Sun.COM /*
997*8822SCasper.Dik@Sun.COM * PRARGSZ == length of cmd arg string.
998*8822SCasper.Dik@Sun.COM */
999*8822SCasper.Dik@Sun.COM if (psargs == NULL) {
1000*8822SCasper.Dik@Sun.COM psa = &psinfo->pr_psargs[0];
1001*8822SCasper.Dik@Sun.COM i = PRARGSZ;
1002*8822SCasper.Dik@Sun.COM tp = &psinfo->pr_psargs[PRARGSZ];
1003*8822SCasper.Dik@Sun.COM } else {
1004*8822SCasper.Dik@Sun.COM psa = psargs;
1005*8822SCasper.Dik@Sun.COM i = strlen(psargs);
1006*8822SCasper.Dik@Sun.COM tp = psa + i;
1007*8822SCasper.Dik@Sun.COM }
1008*8822SCasper.Dik@Sun.COM
1009*8822SCasper.Dik@Sun.COM for (cp = psa; cp < tp; /* empty */) {
1010*8822SCasper.Dik@Sun.COM if (*cp == 0)
1011*8822SCasper.Dik@Sun.COM break;
1012*8822SCasper.Dik@Sun.COM length = mbtowc(&wchar, cp, MB_LEN_MAX);
1013*8822SCasper.Dik@Sun.COM if (length < 0 || !iswprint(wchar)) {
1014*8822SCasper.Dik@Sun.COM (void) printf(" [ %.16s ]", psinfo->pr_fname);
1015*8822SCasper.Dik@Sun.COM return (1);
1016*8822SCasper.Dik@Sun.COM }
1017*8822SCasper.Dik@Sun.COM cp += length;
1018*8822SCasper.Dik@Sun.COM }
1019*8822SCasper.Dik@Sun.COM wcnt = namencnt(psa, i, maxlen);
1020*8822SCasper.Dik@Sun.COM #if 0
1021*8822SCasper.Dik@Sun.COM /* dumps core on really long strings */
1022*8822SCasper.Dik@Sun.COM (void) printf(" %.*s", wcnt, psa);
1023*8822SCasper.Dik@Sun.COM #else
1024*8822SCasper.Dik@Sun.COM (void) putchar(' ');
1025*8822SCasper.Dik@Sun.COM (void) fwrite(psa, 1, wcnt, stdout);
1026*8822SCasper.Dik@Sun.COM #endif
1027*8822SCasper.Dik@Sun.COM return (1);
1028*8822SCasper.Dik@Sun.COM }
1029*8822SCasper.Dik@Sun.COM
1030*8822SCasper.Dik@Sun.COM /*
1031*8822SCasper.Dik@Sun.COM * Print starting time of process unless process started more than 24 hours
1032*8822SCasper.Dik@Sun.COM * ago, in which case the date is printed.
1033*8822SCasper.Dik@Sun.COM */
1034*8822SCasper.Dik@Sun.COM static void
prtime(timestruc_t st)1035*8822SCasper.Dik@Sun.COM prtime(timestruc_t st)
1036*8822SCasper.Dik@Sun.COM {
1037*8822SCasper.Dik@Sun.COM char sttim[26];
1038*8822SCasper.Dik@Sun.COM static time_t tim = 0L;
1039*8822SCasper.Dik@Sun.COM time_t starttime;
1040*8822SCasper.Dik@Sun.COM
1041*8822SCasper.Dik@Sun.COM if (tim == 0L)
1042*8822SCasper.Dik@Sun.COM tim = time((time_t *)0);
1043*8822SCasper.Dik@Sun.COM starttime = st.tv_sec;
1044*8822SCasper.Dik@Sun.COM if (tim - starttime > 24*60*60) {
1045*8822SCasper.Dik@Sun.COM (void) strftime(sttim, sizeof (sttim), "%b %d",
1046*8822SCasper.Dik@Sun.COM localtime(&starttime));
1047*8822SCasper.Dik@Sun.COM } else {
1048*8822SCasper.Dik@Sun.COM (void) strftime(sttim, sizeof (sttim), "%H:%M:%S",
1049*8822SCasper.Dik@Sun.COM localtime(&starttime));
1050*8822SCasper.Dik@Sun.COM }
1051*8822SCasper.Dik@Sun.COM (void) printf("%9.9s", sttim);
1052*8822SCasper.Dik@Sun.COM }
1053*8822SCasper.Dik@Sun.COM
1054*8822SCasper.Dik@Sun.COM static void
przom(psinfo_t * psinfo)1055*8822SCasper.Dik@Sun.COM przom(psinfo_t *psinfo)
1056*8822SCasper.Dik@Sun.COM {
1057*8822SCasper.Dik@Sun.COM long tm;
1058*8822SCasper.Dik@Sun.COM
1059*8822SCasper.Dik@Sun.COM if (lflg)
1060*8822SCasper.Dik@Sun.COM (void) printf("%2x", psinfo->pr_flag & 0377);
1061*8822SCasper.Dik@Sun.COM if (uflg) {
1062*8822SCasper.Dik@Sun.COM struct passwd *pwd;
1063*8822SCasper.Dik@Sun.COM
1064*8822SCasper.Dik@Sun.COM if ((pwd = getpwuid(psinfo->pr_euid)) != NULL)
1065*8822SCasper.Dik@Sun.COM (void) printf("%-8.8s", pwd->pw_name); /* USER */
1066*8822SCasper.Dik@Sun.COM else
1067*8822SCasper.Dik@Sun.COM (void) printf(" %7.7d", (int)psinfo->pr_euid); /* UID */
1068*8822SCasper.Dik@Sun.COM } else if (lflg)
1069*8822SCasper.Dik@Sun.COM (void) printf(" %5d", (int)psinfo->pr_euid); /* UID */
1070*8822SCasper.Dik@Sun.COM
1071*8822SCasper.Dik@Sun.COM (void) printf("%*d", pidwidth + 1, (int)psinfo->pr_pid); /* PID */
1072*8822SCasper.Dik@Sun.COM if (lflg)
1073*8822SCasper.Dik@Sun.COM (void) printf("%*d", pidwidth + 1,
1074*8822SCasper.Dik@Sun.COM (int)psinfo->pr_ppid); /* PPID */
1075*8822SCasper.Dik@Sun.COM if (lflg)
1076*8822SCasper.Dik@Sun.COM (void) printf(" 0"); /* CP */
1077*8822SCasper.Dik@Sun.COM if (uflg) {
1078*8822SCasper.Dik@Sun.COM prtpct(0); /* %CPU */
1079*8822SCasper.Dik@Sun.COM prtpct(0); /* %MEM */
1080*8822SCasper.Dik@Sun.COM }
1081*8822SCasper.Dik@Sun.COM if (lflg) {
1082*8822SCasper.Dik@Sun.COM (void) printf("%4d", psinfo->pr_lwp.pr_pri); /* PRI */
1083*8822SCasper.Dik@Sun.COM (void) printf(" "); /* NICE */
1084*8822SCasper.Dik@Sun.COM }
1085*8822SCasper.Dik@Sun.COM if (lflg || uflg) {
1086*8822SCasper.Dik@Sun.COM (void) printf(" 0"); /* SZ */
1087*8822SCasper.Dik@Sun.COM (void) printf(" 0"); /* RSS */
1088*8822SCasper.Dik@Sun.COM }
1089*8822SCasper.Dik@Sun.COM if (lflg)
1090*8822SCasper.Dik@Sun.COM (void) printf(" "); /* WCHAN */
1091*8822SCasper.Dik@Sun.COM (void) printf(" "); /* TTY */
1092*8822SCasper.Dik@Sun.COM (void) printf("%c", psinfo->pr_lwp.pr_sname); /* STATE */
1093*8822SCasper.Dik@Sun.COM if (uflg)
1094*8822SCasper.Dik@Sun.COM (void) printf(" "); /* START */
1095*8822SCasper.Dik@Sun.COM
1096*8822SCasper.Dik@Sun.COM /* time just for process */
1097*8822SCasper.Dik@Sun.COM tm = psinfo->pr_time.tv_sec;
1098*8822SCasper.Dik@Sun.COM if (Sflg) { /* calculate time for process and all reaped children */
1099*8822SCasper.Dik@Sun.COM tm += psinfo->pr_ctime.tv_sec;
1100*8822SCasper.Dik@Sun.COM if (psinfo->pr_time.tv_nsec + psinfo->pr_ctime.tv_nsec
1101*8822SCasper.Dik@Sun.COM >= 1000000000)
1102*8822SCasper.Dik@Sun.COM tm += 1;
1103*8822SCasper.Dik@Sun.COM }
1104*8822SCasper.Dik@Sun.COM (void) printf(" %2ld:%.2ld", tm / 60, tm % 60); /* TIME */
1105*8822SCasper.Dik@Sun.COM
1106*8822SCasper.Dik@Sun.COM if (vflg) {
1107*8822SCasper.Dik@Sun.COM (void) printf(" 0"); /* SZ */
1108*8822SCasper.Dik@Sun.COM (void) printf(" 0"); /* RSS */
1109*8822SCasper.Dik@Sun.COM prtpct(0); /* %CPU */
1110*8822SCasper.Dik@Sun.COM prtpct(0); /* %MEM */
1111*8822SCasper.Dik@Sun.COM }
1112*8822SCasper.Dik@Sun.COM (void) printf(" %.*s", maxlen, " <defunct>");
1113*8822SCasper.Dik@Sun.COM }
1114*8822SCasper.Dik@Sun.COM
1115*8822SCasper.Dik@Sun.COM /*
1116*8822SCasper.Dik@Sun.COM * Returns true iff string is all numeric.
1117*8822SCasper.Dik@Sun.COM */
1118*8822SCasper.Dik@Sun.COM static int
num(char * s)1119*8822SCasper.Dik@Sun.COM num(char *s)
1120*8822SCasper.Dik@Sun.COM {
1121*8822SCasper.Dik@Sun.COM int c;
1122*8822SCasper.Dik@Sun.COM
1123*8822SCasper.Dik@Sun.COM if (s == NULL)
1124*8822SCasper.Dik@Sun.COM return (0);
1125*8822SCasper.Dik@Sun.COM c = *s;
1126*8822SCasper.Dik@Sun.COM do {
1127*8822SCasper.Dik@Sun.COM if (!isdigit(c))
1128*8822SCasper.Dik@Sun.COM return (0);
1129*8822SCasper.Dik@Sun.COM } while ((c = *++s) != '\0');
1130*8822SCasper.Dik@Sun.COM return (1);
1131*8822SCasper.Dik@Sun.COM }
1132*8822SCasper.Dik@Sun.COM
1133*8822SCasper.Dik@Sun.COM /*
1134*8822SCasper.Dik@Sun.COM * Function to compute the number of printable bytes in a multibyte
1135*8822SCasper.Dik@Sun.COM * command string ("internationalization").
1136*8822SCasper.Dik@Sun.COM */
1137*8822SCasper.Dik@Sun.COM static int
namencnt(char * cmd,int eucsize,int scrsize)1138*8822SCasper.Dik@Sun.COM namencnt(char *cmd, int eucsize, int scrsize)
1139*8822SCasper.Dik@Sun.COM {
1140*8822SCasper.Dik@Sun.COM int eucwcnt = 0, scrwcnt = 0;
1141*8822SCasper.Dik@Sun.COM int neucsz, nscrsz;
1142*8822SCasper.Dik@Sun.COM wchar_t wchar;
1143*8822SCasper.Dik@Sun.COM
1144*8822SCasper.Dik@Sun.COM while (*cmd != '\0') {
1145*8822SCasper.Dik@Sun.COM if ((neucsz = mbtowc(&wchar, cmd, MB_LEN_MAX)) < 0)
1146*8822SCasper.Dik@Sun.COM return (8); /* default to use for illegal chars */
1147*8822SCasper.Dik@Sun.COM if ((nscrsz = scrwidth(wchar)) == 0)
1148*8822SCasper.Dik@Sun.COM return (8);
1149*8822SCasper.Dik@Sun.COM if (eucwcnt + neucsz > eucsize || scrwcnt + nscrsz > scrsize)
1150*8822SCasper.Dik@Sun.COM break;
1151*8822SCasper.Dik@Sun.COM eucwcnt += neucsz;
1152*8822SCasper.Dik@Sun.COM scrwcnt += nscrsz;
1153*8822SCasper.Dik@Sun.COM cmd += neucsz;
1154*8822SCasper.Dik@Sun.COM }
1155*8822SCasper.Dik@Sun.COM return (eucwcnt);
1156*8822SCasper.Dik@Sun.COM }
1157*8822SCasper.Dik@Sun.COM
1158*8822SCasper.Dik@Sun.COM static int
pscompare(const void * v1,const void * v2)1159*8822SCasper.Dik@Sun.COM pscompare(const void *v1, const void *v2)
1160*8822SCasper.Dik@Sun.COM {
1161*8822SCasper.Dik@Sun.COM const struct psent *p1 = v1;
1162*8822SCasper.Dik@Sun.COM const struct psent *p2 = v2;
1163*8822SCasper.Dik@Sun.COM int i;
1164*8822SCasper.Dik@Sun.COM
1165*8822SCasper.Dik@Sun.COM if (uflg)
1166*8822SCasper.Dik@Sun.COM i = p2->psinfo->pr_pctcpu - p1->psinfo->pr_pctcpu;
1167*8822SCasper.Dik@Sun.COM else if (vflg)
1168*8822SCasper.Dik@Sun.COM i = p2->psinfo->pr_rssize - p1->psinfo->pr_rssize;
1169*8822SCasper.Dik@Sun.COM else
1170*8822SCasper.Dik@Sun.COM i = p1->psinfo->pr_ttydev - p2->psinfo->pr_ttydev;
1171*8822SCasper.Dik@Sun.COM if (i == 0)
1172*8822SCasper.Dik@Sun.COM i = p1->psinfo->pr_pid - p2->psinfo->pr_pid;
1173*8822SCasper.Dik@Sun.COM return (i);
1174*8822SCasper.Dik@Sun.COM }
1175*8822SCasper.Dik@Sun.COM
1176*8822SCasper.Dik@Sun.COM static char *
err_string(int err)1177*8822SCasper.Dik@Sun.COM err_string(int err)
1178*8822SCasper.Dik@Sun.COM {
1179*8822SCasper.Dik@Sun.COM static char buf[32];
1180*8822SCasper.Dik@Sun.COM char *str = strerror(err);
1181*8822SCasper.Dik@Sun.COM
1182*8822SCasper.Dik@Sun.COM if (str == NULL)
1183*8822SCasper.Dik@Sun.COM (void) sprintf(str = buf, "Errno #%d", err);
1184*8822SCasper.Dik@Sun.COM
1185*8822SCasper.Dik@Sun.COM return (str);
1186*8822SCasper.Dik@Sun.COM }
1187