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