4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2012, Joyent, Inc. All rights reserved.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
41 * ps -- print things about processes.
52 #include <sys/types.h>
54 #include <sys/mkdev.h>
60 #include <sys/param.h>
61 #include <sys/ttold.h>
68 #include <priv_utils.h>
71 #define NTTYS 2 /* max ttys that can be specified with the -t option */
72 /* only one tty can be specified with SunOS ps */
73 #define SIZ 30 /* max processes that can be specified with -p and -g */
74 #define ARGSIZ 30 /* size of buffer holding args for -t, -p, -u options */
84 static int tplen
, maxlen
, twidth
;
86 static struct winsize win
;
88 static int retcode
= 1;
89 static int lflg
; /* long format */
90 static int uflg
; /* user-oriented output */
91 static int aflg
; /* Display all processes */
92 static int eflg
; /* Display environment as well as arguments */
93 static int gflg
; /* Display process group leaders */
94 static int tflg
; /* Processes running on specific terminals */
95 static int rflg
; /* Running processes only flag */
96 static int Sflg
; /* Accumulated time plus all reaped children */
97 static int xflg
; /* Include processes with no controlling tty */
98 static int cflg
; /* Display command name */
99 static int vflg
; /* Virtual memory-oriented output */
100 static int nflg
; /* Numerical output */
101 static int pflg
; /* Specific process id passed as argument */
102 static int Uflg
; /* Update private database, ups_data */
105 static char *gettty();
106 static char argbuf
[ARGSIZ
];
108 static char *p1
; /* points to successive option arguments */
110 static char stdbuf
[BUFSIZ
];
112 static int ndev
; /* number of devices */
113 static int maxdev
; /* number of devl structures allocated */
117 static struct devl
{ /* device list */
118 char dname
[DNSIZE
]; /* device name */
119 dev_t ddev
; /* device number */
125 } tty
[NTTYS
]; /* for t option */
127 static pid_t pidsave
;
130 static char *procdir
= "/proc"; /* standard /proc directory */
131 static void usage(); /* print usage message and quit */
132 static void getarg(void);
133 static void prtime(timestruc_t st
);
134 static void przom(psinfo_t
*psinfo
);
135 static int num(char *);
136 static int preadargs(int, psinfo_t
*, char *);
137 static int preadenvs(int, psinfo_t
*, char *);
138 static int prcom(int, psinfo_t
*, char *);
139 static int namencnt(char *, int, int);
140 static int pscompare(const void *, const void *);
141 static char *err_string(int);
143 extern int scrwidth(wchar_t); /* header file? */
146 ucbmain(int argc
, char **argv
)
148 psinfo_t info
; /* process information structure from /proc */
149 char *psargs
= NULL
; /* pointer to buffer for -w and -ww options */
150 char *svpsargs
= NULL
;
156 struct tty
*ttyp
= tty
;
160 pid_t pid
; /* pid: process id */
161 pid_t ppid
; /* ppid: parent process id */
167 struct dirent
*dentp
;
173 (void) setlocale(LC_ALL
, "");
178 * This program needs the proc_owner privilege
180 (void) __init_suid_priv(PU_CLEARLIMITSET
, PRIV_PROC_OWNER
,
184 * calculate width of pid fields based on configured MAXPID
185 * (must be at least 5 to retain output format compatibility)
187 maxpid
= (pid_t
)sysconf(_SC_MAXPID
);
189 while ((maxpid
/= 10) > 0)
191 pidwidth
= pidwidth
< 5 ? 5 : pidwidth
;
193 if (ioctl(1, TIOCGWINSZ
, &win
) == -1)
196 twidth
= (win
.ws_col
== 0 ? 80 : win
.ws_col
);
198 /* add the '-' for BSD compatibility */
200 if (argv
[1][0] != '-' && !isdigit(argv
[1][0])) {
201 len
= strlen(argv
[1]) + 2;
204 (void) snprintf(tmp
, len
, "%s%s", "-", argv
[1]);
210 setbuf(stdout
, stdbuf
);
211 while ((c
= getopt(argc
, argv
, "lcaengrSt:xuvwU")) != EOF
)
214 gflg
++; /* include process group leaders */
216 case 'c': /* display internal command name */
219 case 'r': /* restrict output to running processes */
222 case 'S': /* display time by process and all reaped children */
225 case 'x': /* process w/o controlling tty */
228 case 'l': /* long listing */
232 case 'u': /* user-oriented output */
236 case 'U': /* update private database ups_data */
239 case 'w': /* increase display width */
242 else /* second w option */
245 case 'v': /* display virtual memory format */
251 * display all processes except process group
252 * leaders and processes w/o controlling tty
258 /* Display environment along with aguments. */
261 case 'n': /* Display numerical output */
264 case 't': /* restrict output to named terminal */
271 do { /* only loop through once (NTTYS = 2) */
276 if ((p
= malloc(TSZ
+1)) == NULL
) {
277 (void) fprintf(stderr
,
283 if (isdigit(*parg
)) {
284 (void) strcpy(p
, "tty");
288 (void) strncat(p
, parg
, size
);
289 ttyp
->tdev
= PRNODEV
;
290 if (parg
&& *parg
== '?')
293 char nambuf
[TSZ
+6]; /* for /dev/+\0 */
295 (void) strcpy(nambuf
, "/dev/");
296 (void) strcat(nambuf
, p
);
297 if (stat64(nambuf
, &s
) == 0)
298 ttyp
->tdev
= s
.st_rdev
;
304 default: /* error on ? */
312 if (optind
+ 1 < argc
) { /* more than one additional argument */
313 (void) fprintf(stderr
, "ps: too many arguments\n");
318 * The -U option is obsolete. Attempts to use it cause ps to exit
319 * without printing anything.
324 if (optind
< argc
) { /* user specified a specific proc id */
330 (void) fprintf(stderr
,
331 "ps: %s is an invalid non-numeric argument for a process id\n", parg
);
334 pidsave
= (pid_t
)atol(parg
);
335 aflg
= rflg
= xflg
= 0;
342 /* allocate an initial guess for the number of processes */
344 psent
= malloc(entsize
* sizeof (struct psent
));
346 (void) fprintf(stderr
, "ps: no memory\n");
349 nent
= 0; /* no active entries yet */
353 " F UID%*s%*s %%C PRI NI SZ RSS "
354 "WCHAN S TT TIME COMMAND", pidwidth
+ 1, "PID",
355 pidwidth
+ 1, "PPID");
359 " UID%*s %%CPU %%MEM SZ RSS "
360 "TT S START TIME COMMAND",
361 pidwidth
+ 1, "PID");
364 "USER %*s %%CPU %%MEM SZ RSS "
365 "TT S START TIME COMMAND",
366 pidwidth
+ 1, "PID");
369 "%*s TT S TIME SIZE RSS %%CPU %%MEM "
370 "COMMAND", pidwidth
+ 1, "PID");
372 (void) sprintf(hdr
, "%*s TT S TIME COMMAND",
373 pidwidth
+ 1, "PID");
375 twidth
= twidth
- strlen(hdr
) + 6;
376 (void) printf("%s\n", hdr
);
378 if (twidth
> PRARGSZ
&& (psargs
= malloc(twidth
)) == NULL
) {
379 (void) fprintf(stderr
, "ps: no memory\n");
385 * Determine which processes to print info about by searching
386 * the /proc directory and looking at each process.
388 if ((dirp
= opendir(procdir
)) == NULL
) {
389 (void) fprintf(stderr
, "ps: cannot open PROC directory %s\n",
394 (void) strcpy(psname
, procdir
);
395 pdlen
= strlen(psname
);
396 psname
[pdlen
++] = '/';
398 /* for each active process --- */
399 while ((dentp
= readdir(dirp
)) != NULL
) {
400 int psfd
; /* file descriptor for /proc/nnnnn/psinfo */
401 int asfd
; /* file descriptor for /proc/nnnnn/as */
403 if (dentp
->d_name
[0] == '.') /* skip . and .. */
405 (void) strcpy(psname
+ pdlen
, dentp
->d_name
);
406 (void) strcpy(asname
, psname
);
407 (void) strcat(psname
, "/psinfo");
408 (void) strcat(asname
, "/as");
410 if ((psfd
= open(psname
, O_RDONLY
)) == -1)
413 if (psargs
!= NULL
|| eflg
) {
415 /* now we need the proc_owner privilege */
416 (void) __priv_bracket(PRIV_ON
);
418 asfd
= open(asname
, O_RDONLY
);
420 /* drop proc_owner privilege after open */
421 (void) __priv_bracket(PRIV_OFF
);
425 * Get the info structure for the process
427 if (read(psfd
, &info
, sizeof (info
)) != sizeof (info
)) {
433 if (saverr
== EAGAIN
)
435 if (saverr
!= ENOENT
)
436 (void) fprintf(stderr
, "ps: read() on %s: %s\n",
437 psname
, err_string(saverr
));
443 if (info
.pr_lwp
.pr_state
== 0) /* can't happen? */
448 /* Display only process from command line */
449 if (pflg
) { /* pid in arg list */
457 * Omit "uninteresting" processes unless 'g' option.
459 if ((ppid
== 1) && !(gflg
))
463 * Omit non-running processes for 'r' option
466 !(info
.pr_lwp
.pr_sname
== 'O' ||
467 info
.pr_lwp
.pr_sname
== 'R'))
470 if (!found
&& !tflg
&& !aflg
&& info
.pr_euid
!= my_uid
)
474 * Read the args for the -w and -ww cases
477 if ((psargs
!= NULL
&&
478 preadargs(asfd
, &info
, psargs
) == -1) ||
479 (eflg
&& preadenvs(asfd
, &info
, psargs
) == -1)) {
483 if (saverr
== EAGAIN
)
485 if (saverr
!= ENOENT
)
486 (void) fprintf(stderr
,
487 "ps: read() on %s: %s\n",
488 asname
, err_string(saverr
));
492 psargs
= info
.pr_psargs
;
495 if (nent
>= entsize
) {
497 psent
= (struct psent
*)realloc((char *)psent
,
498 entsize
* sizeof (struct psent
));
500 (void) fprintf(stderr
, "ps: no memory\n");
504 if ((psent
[nent
].psinfo
= malloc(sizeof (psinfo_t
)))
506 (void) fprintf(stderr
, "ps: no memory\n");
509 *psent
[nent
].psinfo
= info
;
511 psent
[nent
].psargs
= NULL
;
513 if ((psent
[nent
].psargs
= malloc(strlen(psargs
)+1))
515 (void) fprintf(stderr
, "ps: no memory\n");
518 (void) strcpy(psent
[nent
].psargs
, psargs
);
520 psent
[nent
].found
= found
;
528 /* revert to non-privileged user */
529 (void) __priv_relinquish();
531 (void) closedir(dirp
);
533 qsort((char *)psent
, nent
, sizeof (psent
[0]), pscompare
);
535 for (i
= 0; i
< nent
; i
++) {
536 struct psent
*pp
= &psent
[i
];
537 if (prcom(pp
->found
, pp
->psinfo
, pp
->psargs
)) {
547 usage() /* print usage message and quit */
549 static char usage1
[] = "ps [ -aceglnrSuUvwx ] [ -t term ] [ num ]";
551 (void) fprintf(stderr
, "usage: %s\n", usage1
);
556 * Read the process arguments from the process.
557 * This allows >PRARGSZ characters of arguments to be displayed but,
558 * unlike pr_psargs[], the process may have changed them.
562 preadargs(int pfd
, psinfo_t
*psinfo
, char *psargs
)
564 off_t argvoff
= (off_t
)psinfo
->pr_argv
;
574 caddr32_t argv32
[NARG
];
575 int is32
= (psinfo
->pr_dmodel
!= PR_MODEL_LP64
);
578 if (psinfo
->pr_nlwp
== 0 ||
579 strcmp(psinfo
->pr_lwp
.pr_clname
, "SYS") == 0)
582 (void) memset(psa
, 0, bsize
--);
587 (void) memset(argv
, 0, sizeof (argv
));
590 if ((i
= pread(pfd
, argv32
, sizeof (argv32
),
592 if (i
== 0 || errno
== EIO
)
596 for (i
= 0; i
< NARG
; i
++)
600 if ((i
= pread(pfd
, argv
, sizeof (argv
),
602 if (i
== 0 || errno
== EIO
)
608 if ((argoff
= argv
[narg
++]) == 0)
610 if (argoff
!= nextargoff
&&
611 (i
= pread(pfd
, psa
, bsize
, argoff
)) <= 0) {
612 if (i
== 0 || errno
== EIO
)
620 nextargoff
= argoff
+ len
+ 1;
622 argvoff
+= is32
? sizeof (caddr32_t
) : sizeof (caddr_t
);
624 argvoff
+= sizeof (caddr_t
);
627 while (psa
> psargs
&& isspace(*(psa
-1)))
632 if (strlen(psinfo
->pr_psargs
) > strlen(psargs
))
633 (void) strcpy(psargs
, psinfo
->pr_psargs
);
639 * Read environment variables from the process.
640 * Append them to psargs if there is room.
643 preadenvs(int pfd
, psinfo_t
*psinfo
, char *psargs
)
645 off_t envpoff
= (off_t
)psinfo
->pr_envp
;
656 caddr32_t envp32
[NARG
];
657 int is32
= (psinfo
->pr_dmodel
!= PR_MODEL_LP64
);
660 psainit
= psa
= (psargs
!= NULL
)? psargs
: psinfo
->pr_psargs
;
663 bsize
= twidth
- len
- 1;
665 if (bsize
<= 0 || psinfo
->pr_nlwp
== 0 ||
666 strcmp(psinfo
->pr_lwp
.pr_clname
, "SYS") == 0)
673 (void) memset(envp
, 0, sizeof (envp
));
676 if ((i
= pread(pfd
, envp32
, sizeof (envp32
),
678 if (i
== 0 || errno
== EIO
)
682 for (i
= 0; i
< NARG
; i
++)
686 if ((i
= pread(pfd
, envp
, sizeof (envp
),
688 if (i
== 0 || errno
== EIO
)
694 if ((envoff
= envp
[nenv
++]) == 0)
696 if (envoff
!= nextenvoff
&&
697 (i
= pread(pfd
, psa
+1, bsize
, envoff
)) <= 0) {
698 if (i
== 0 || errno
== EIO
)
706 nextenvoff
= envoff
+ len
+ 1;
708 envpoff
+= is32
? sizeof (caddr32_t
) : sizeof (caddr_t
);
710 envpoff
+= sizeof (caddr_t
);
713 while (psa
> psainit
&& isspace(*(psa
-1)))
721 * getarg() finds the next argument in list and copies arg into argbuf.
722 * p1 first pts to arg passed back from getopt routine. p1 is then
723 * bumped to next character that is not a comma or blank -- p1 NULL
724 * indicates end of list.
733 while ((c
= *p1
) != '\0' && (c
== ',' || isspace(c
)))
737 while ((c
= *p1
) != '\0' && c
!= ',' && !isspace(c
)) {
738 if (parga
< argbuf
+ ARGSIZ
- 1)
744 while ((c
= *p1
) != '\0' && (c
== ',' || isspace(c
)))
749 devlookup(dev_t ddev
)
754 for (dp
= devl
, i
= 0; i
< ndev
; dp
++, i
++) {
755 if (dp
->ddev
== ddev
)
762 devadd(char *name
, dev_t ddev
)
767 if (ndev
== maxdev
) {
769 devl
= realloc(devl
, maxdev
* sizeof (struct devl
));
771 (void) fprintf(stderr
,
772 "ps: not enough memory for %d devices\n", maxdev
);
780 (void) strcpy(dp
->dname
, "??");
785 /* Strip off /dev/ */
786 if (leng
< DNSIZE
+ 4)
787 (void) strcpy(dp
->dname
, &name
[5]);
789 start
= leng
- (DNSIZE
- 1);
791 for (i
= start
; i
< leng
&& name
[i
] != '/'; i
++)
794 (void) strlcpy(dp
->dname
, &name
[start
], DNSIZE
);
796 (void) strlcpy(dp
->dname
, &name
[i
+1], DNSIZE
);
802 * gettty returns the user's tty number or ? if none.
805 gettty(psinfo_t
*psinfo
)
807 extern char *_ttyname_dev(dev_t
, char *, size_t);
808 static zoneid_t zid
= -1;
809 char devname
[TTYNAME_MAX
];
815 if (psinfo
->pr_ttydev
== PRNODEV
|| psinfo
->pr_zoneid
!= zid
)
818 if ((retval
= devlookup(psinfo
->pr_ttydev
)) != NULL
)
821 retval
= _ttyname_dev(psinfo
->pr_ttydev
, devname
, sizeof (devname
));
823 return (devadd(retval
, psinfo
->pr_ttydev
));
827 * Print percent from 16-bit binary fraction [0 .. 1]
828 * Round up .01 to .1 to indicate some small percentage (the 0x7000 below).
833 uint_t value
= pct
; /* need 32 bits to compute with */
835 value
= ((value
* 1000) + 0x7000) >> 15; /* [0 .. 1000] */
836 (void) printf("%3u.%u", value
/ 10, value
% 10);
840 * Print info about the process.
843 prcom(int found
, psinfo_t
*psinfo
, char *psargs
)
854 * If process is zombie, call print routine and return.
856 if (psinfo
->pr_nlwp
== 0) {
866 * Get current terminal. If none ("?") and 'a' is set, don't print
867 * info. If 't' is set, check if term is in list of desired terminals
868 * and print it if it is.
873 if (*tp
== '?' && !found
&& !xflg
)
876 if (!(*tp
== '?' && aflg
) && tflg
&& !found
) {
879 for (ttyp
= tty
; ttyp
->tname
!= NULL
; ttyp
++) {
881 * Look for a name match
883 if (strcmp(tp
, ttyp
->tname
) == 0) {
888 * Look for same device under different names.
890 if ((other
== NULL
) &&
891 (psinfo
->pr_ttydev
== ttyp
->tdev
))
902 (void) printf("%2x", psinfo
->pr_flag
& 0377);
907 if ((pwd
= getpwuid(psinfo
->pr_euid
)) != NULL
)
909 (void) printf("%-8.8s", pwd
->pw_name
);
912 (void) printf(" %7.7d", (int)psinfo
->pr_euid
);
914 (void) printf(" %5d", (int)psinfo
->pr_euid
); /* UID */
917 (void) printf(" %5d", (int)psinfo
->pr_euid
); /* UID */
919 (void) printf("%*d", pidwidth
+ 1, (int)psinfo
->pr_pid
); /* PID */
921 (void) printf("%*d", pidwidth
+ 1,
922 (int)psinfo
->pr_ppid
); /* PPID */
924 (void) printf("%3d", psinfo
->pr_lwp
.pr_cpu
& 0377); /* CP */
926 prtpct(psinfo
->pr_pctcpu
); /* %CPU */
927 prtpct(psinfo
->pr_pctmem
); /* %MEM */
930 (void) printf("%4d", psinfo
->pr_lwp
.pr_pri
); /* PRI */
931 (void) printf("%3d", psinfo
->pr_lwp
.pr_nice
); /* NICE */
934 if (psinfo
->pr_flag
& SSYS
) /* SZ */
936 else if (psinfo
->pr_size
)
937 (void) printf(" %4lu", (ulong_t
)psinfo
->pr_size
);
940 if (psinfo
->pr_flag
& SSYS
) /* RSS */
942 else if (psinfo
->pr_rssize
)
943 (void) printf(" %4lu", (ulong_t
)psinfo
->pr_rssize
);
947 if (lflg
) { /* WCHAN */
948 if (psinfo
->pr_lwp
.pr_sname
!= 'S') {
950 } else if (psinfo
->pr_lwp
.pr_wchan
) {
951 (void) printf(" %+8.8lx",
952 (ulong_t
)psinfo
->pr_lwp
.pr_wchan
);
957 if ((tplen
= strlen(tp
)) > 9)
958 maxlen
= twidth
- tplen
+ 9;
963 (void) printf(" %-8.14s", tp
); /* TTY */
964 (void) printf(" %c", psinfo
->pr_lwp
.pr_sname
); /* STATE */
966 (void) printf(" %-8.14s", tp
); /* TTY */
968 prtime(psinfo
->pr_start
); /* START */
970 /* time just for process */
971 tm
= psinfo
->pr_time
.tv_sec
;
972 if (Sflg
) { /* calculate time for process and all reaped children */
973 tm
+= psinfo
->pr_ctime
.tv_sec
;
974 if (psinfo
->pr_time
.tv_nsec
+ psinfo
->pr_ctime
.tv_nsec
979 (void) printf(" %2ld:%.2ld", tm
/ 60, tm
% 60); /* TIME */
982 if (psinfo
->pr_flag
& SSYS
) /* SZ */
984 else if (psinfo
->pr_size
)
985 (void) printf("%5lu", (ulong_t
)psinfo
->pr_size
);
988 if (psinfo
->pr_flag
& SSYS
) /* SZ */
990 else if (psinfo
->pr_rssize
)
991 (void) printf("%5lu", (ulong_t
)psinfo
->pr_rssize
);
994 prtpct(psinfo
->pr_pctcpu
); /* %CPU */
995 prtpct(psinfo
->pr_pctmem
); /* %MEM */
997 if (cflg
) { /* CMD */
998 wcnt
= namencnt(psinfo
->pr_fname
, 16, maxlen
);
999 (void) printf(" %.*s", wcnt
, psinfo
->pr_fname
);
1003 * PRARGSZ == length of cmd arg string.
1005 if (psargs
== NULL
) {
1006 psa
= &psinfo
->pr_psargs
[0];
1008 tp
= &psinfo
->pr_psargs
[PRARGSZ
];
1015 for (cp
= psa
; cp
< tp
; /* empty */) {
1018 length
= mbtowc(&wchar
, cp
, MB_LEN_MAX
);
1019 if (length
< 0 || !iswprint(wchar
)) {
1020 (void) printf(" [ %.16s ]", psinfo
->pr_fname
);
1025 wcnt
= namencnt(psa
, i
, maxlen
);
1027 /* dumps core on really long strings */
1028 (void) printf(" %.*s", wcnt
, psa
);
1030 (void) putchar(' ');
1031 (void) fwrite(psa
, 1, wcnt
, stdout
);
1037 * Print starting time of process unless process started more than 24 hours
1038 * ago, in which case the date is printed.
1041 prtime(timestruc_t st
)
1044 static time_t tim
= 0L;
1048 tim
= time((time_t *)0);
1049 starttime
= st
.tv_sec
;
1050 if (tim
- starttime
> 24*60*60) {
1051 (void) strftime(sttim
, sizeof (sttim
), "%b %d",
1052 localtime(&starttime
));
1054 (void) strftime(sttim
, sizeof (sttim
), "%H:%M:%S",
1055 localtime(&starttime
));
1057 (void) printf("%9.9s", sttim
);
1061 przom(psinfo_t
*psinfo
)
1066 (void) printf("%2x", psinfo
->pr_flag
& 0377);
1070 if ((pwd
= getpwuid(psinfo
->pr_euid
)) != NULL
)
1071 (void) printf("%-8.8s", pwd
->pw_name
); /* USER */
1073 (void) printf(" %7.7d", (int)psinfo
->pr_euid
); /* UID */
1075 (void) printf(" %5d", (int)psinfo
->pr_euid
); /* UID */
1077 (void) printf("%*d", pidwidth
+ 1, (int)psinfo
->pr_pid
); /* PID */
1079 (void) printf("%*d", pidwidth
+ 1,
1080 (int)psinfo
->pr_ppid
); /* PPID */
1082 (void) printf(" 0"); /* CP */
1084 prtpct(0); /* %CPU */
1085 prtpct(0); /* %MEM */
1088 (void) printf("%4d", psinfo
->pr_lwp
.pr_pri
); /* PRI */
1089 (void) printf(" "); /* NICE */
1092 (void) printf(" 0"); /* SZ */
1093 (void) printf(" 0"); /* RSS */
1096 (void) printf(" "); /* WCHAN */
1097 (void) printf(" "); /* TTY */
1098 (void) printf("%c", psinfo
->pr_lwp
.pr_sname
); /* STATE */
1100 (void) printf(" "); /* START */
1102 /* time just for process */
1103 tm
= psinfo
->pr_time
.tv_sec
;
1104 if (Sflg
) { /* calculate time for process and all reaped children */
1105 tm
+= psinfo
->pr_ctime
.tv_sec
;
1106 if (psinfo
->pr_time
.tv_nsec
+ psinfo
->pr_ctime
.tv_nsec
1110 (void) printf(" %2ld:%.2ld", tm
/ 60, tm
% 60); /* TIME */
1113 (void) printf(" 0"); /* SZ */
1114 (void) printf(" 0"); /* RSS */
1115 prtpct(0); /* %CPU */
1116 prtpct(0); /* %MEM */
1118 (void) printf(" %.*s", maxlen
, " <defunct>");
1122 * Returns true iff string is all numeric.
1135 } while ((c
= *++s
) != '\0');
1140 * Function to compute the number of printable bytes in a multibyte
1141 * command string ("internationalization").
1144 namencnt(char *cmd
, int eucsize
, int scrsize
)
1146 int eucwcnt
= 0, scrwcnt
= 0;
1150 while (*cmd
!= '\0') {
1151 if ((neucsz
= mbtowc(&wchar
, cmd
, MB_LEN_MAX
)) < 0)
1152 return (8); /* default to use for illegal chars */
1153 if ((nscrsz
= scrwidth(wchar
)) == 0)
1155 if (eucwcnt
+ neucsz
> eucsize
|| scrwcnt
+ nscrsz
> scrsize
)
1165 pscompare(const void *v1
, const void *v2
)
1167 const struct psent
*p1
= v1
;
1168 const struct psent
*p2
= v2
;
1172 i
= p2
->psinfo
->pr_pctcpu
- p1
->psinfo
->pr_pctcpu
;
1174 i
= p2
->psinfo
->pr_rssize
- p1
->psinfo
->pr_rssize
;
1176 i
= p1
->psinfo
->pr_ttydev
- p2
->psinfo
->pr_ttydev
;
1178 i
= p1
->psinfo
->pr_pid
- p2
->psinfo
->pr_pid
;
1185 static char buf
[32];
1186 char *str
= strerror(err
);
1189 (void) sprintf(str
= buf
, "Errno #%d", err
);