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 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 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 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 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 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 * 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 * 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 * 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 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 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 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 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 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 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 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 * 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