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