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