/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2013 Gary Mills
*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* ps -- print things about processes.
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include <dirent.h>
#include <procfs.h>
#include <locale.h>
#include <wctype.h>
#include <wchar.h>
#include <libw.h>
#include <stdarg.h>
#include <project.h>
#include <zone.h>
#define min(a, b) ((a) > (b) ? (b) : (a))
#define max(a, b) ((a) < (b) ? (b) : (a))
/*
* Size of buffer holding args for t, p, s, g, u, U, G, z options.
* Set to ZONENAME_MAX, the minimum value needed to allow any
* zone to be specified.
*/
/* Structure for storing user or group info */
struct ugdata {
};
struct ughead {
};
};
struct field {
};
static int do_header = 0;
/* array of defined fields, in fname order */
struct def_field {
const char *fname;
const char *header;
int width;
int minwidth;
};
/* fname header width minwidth */
{ "user", "USER", 8, 8 },
{ "ruser", "RUSER", 8, 8 },
{ "group", "GROUP", 8, 8 },
{ "rgroup", "RGROUP", 8, 8 },
{ "uid", "UID", 5, 5 },
{ "ruid", "RUID", 5, 5 },
{ "gid", "GID", 5, 5 },
{ "rgid", "RGID", 5, 5 },
{ "pid", "PID", 5, 5 },
{ "ppid", "PPID", 5, 5 },
{ "pgid", "PGID", 5, 5 },
{ "sid", "SID", 5, 5 },
{ "psr", "PSR", 3, 2 },
{ "lwp", "LWP", 6, 2 },
{ "nlwp", "NLWP", 4, 2 },
{ "opri", "PRI", 3, 2 },
{ "pri", "PRI", 3, 2 },
{ "f", "F", 2, 2 },
{ "s", "S", 1, 1 },
{ "c", "C", 2, 2 },
{ "pcpu", "%CPU", 4, 4 },
{ "pmem", "%MEM", 4, 4 },
{ "osz", "SZ", 4, 4 },
{ "vsz", "VSZ", 4, 4 },
{ "rss", "RSS", 4, 4 },
{ "nice", "NI", 2, 2 },
{ "class", "CLS", 4, 2 },
{ "stime", "STIME", 8, 8 },
{ "etime", "ELAPSED", 11, 7 },
{ "time", "TIME", 11, 5 },
{ "tty", "TT", 7, 7 },
#ifdef _LP64
{ "addr", "ADDR", 16, 8 },
{ "wchan", "WCHAN", 16, 8 },
#else
{ "addr", "ADDR", 8, 8 },
{ "wchan", "WCHAN", 8, 8 },
#endif
{ "fname", "COMMAND", 8, 8 },
{ "comm", "COMMAND", 80, 8 },
{ "args", "COMMAND", 80, 80 },
{ "taskid", "TASKID", 5, 5 },
{ "projid", "PROJID", 5, 5 },
{ "project", "PROJECT", 8, 8 },
{ "pset", "PSET", 3, 3 },
{ "zone", "ZONE", 8, 8 },
{ "zoneid", "ZONEID", 5, 5 },
{ "ctid", "CTID", 5, 5 },
{ "lgrp", "LGRP", 4, 2 },
{ "dmodel", "DMODEL", 6, 6 },
};
static int lflg;
static int Aflg;
static int uflg;
static int Uflg;
static int Gflg;
static int aflg;
static int dflg;
static int Lflg;
static int Pflg;
static int Wflg;
static int yflg;
static int pflg;
static int fflg;
static int cflg;
static int jflg;
static int gflg;
static int sflg;
static int tflg;
static int zflg;
static int Zflg;
static int hflg;
static int Hflg;
static int errflg;
} *devl;
static struct tty {
char *tname;
static int ntty = 0;
/* Maximum possible lgroup ID value */
static int ngrpid = 0;
static int nsessid = 0;
static int nzoneid = 0;
static int kbytes_per_page;
static int pidwidth;
/*
* This constant defines the sentinal number of process IDs below which we
* only examine individual entries in /proc rather than scanning through
* /proc. This optimization is a huge win in the common case.
*/
static void usage(void);
static char *getarg(char **);
static char *parse_format(char *);
static void print_time(time_t, int);
static void add_ugentry(struct ughead *, char *);
static void prtime(timestruc_t, int, int);
static int namencnt(char *, int, int);
static char *err_string(int);
static int print_proc(char *pname);
extern int ucbmain(int, char **);
static int stdmain(int, char **);
int
{
const char *me;
/*
* The original two ps'es are linked in a single binary;
* We try to figure out which instance of ps the user wants to run.
* Traditionally, the UCB variant doesn't require the flag argument
* start with a "-". If the first argument doesn't start with a
* "-", we call "ucbmain".
* If there's a first argument and it starts with a "-", we check
* whether any of the options isn't acceptable to "ucbmain"; in that
* case we run "stdmain".
* If we can't tell from the options which main to call, we check
* the binary we are running. We default to "stdmain" but
* any mention in the executable name of "ucb" causes us to call
* ucbmain.
*/
}
me = getexecname();
else
}
static int
{
char *p;
char *p1;
char *parg;
int c;
int i;
int ret;
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
/*
* calculate width of pid fields based on configured MAXPID
* (must be at least 5 to retain output format compatibility)
*/
pidwidth = 1;
while ((id /= 10) > 0)
++pidwidth;
/*
* TRANSLATION_NOTE
* Specify the printf format with width and precision for
* the STIME field.
*/
if (len >= sizeof (loc_stime_str))
!= EOF)
switch (c) {
case 'H': /* Show home lgroups */
Hflg++;
break;
case 'h':
/*
*/
hflg++;
do {
int id;
/*
* Get all IDs in the list, verify for
* correctness and place in lgrps array.
*/
/* Convert string to integer */
/* Complain if ID didn't parse correctly */
if (ret != 0) {
pgerrflg++;
gettext("is an invalid "
"non-numeric argument"));
else
gettext("exceeds valid "
"range"));
gettext(" for -h option\n"));
continue;
}
/* Extend lgrps array if needed */
if (nlgrps == lgrps_size) {
/* Double the size of the lgrps array */
if (lgrps_size == 0)
lgrps_size = SIZ;
lgrps_size *= 2;
lgrps_size * sizeof (int));
}
/* place the id in the lgrps table */
} while (*p1);
break;
case 'l': /* long listing */
lflg++;
break;
case 'f': /* full listing */
fflg++;
break;
case 'j':
jflg++;
break;
case 'c':
/*
* Format output to reflect scheduler changes:
* high numbers for high priorities and don't
* print nice or p_cpu values. 'c' option only
* effective when used with 'l' or 'f' options.
*/
cflg++;
break;
case 'A': /* list every process */
case 'e': /* (obsolete) list every process */
Aflg++;
break;
case 'a':
/*
* Same as 'e' except no session group leaders
* and no non-terminal processes.
*/
aflg++;
break;
case 'd': /* same as e except no session leaders */
dflg++;
break;
case 'L': /* show lwps */
Lflg++;
break;
case 'P': /* show bound processor */
Pflg++;
break;
case 'W': /* truncate long names */
Wflg++;
break;
case 'y': /* omit F & ADDR, report RSS & SZ in Kby */
yflg++;
break;
case 'n': /* no longer needed; retain as no-op */
gettext("ps: warning: -n option ignored\n"));
break;
case 't': /* terminals */
tflg++;
do {
struct stat64 s;
/* zero the buffer before using it */
p[0] = '\0';
(void) strcpy(p, "tty");
size -= 3;
}
if ((ttysz *= 2) == 0)
}
} while (*p1);
break;
case 'p': /* proc ids */
pflg++;
do {
pgerrflg++;
gettext("is an invalid "
"non-numeric argument"));
else
gettext("exceeds valid "
"range"));
gettext(" for -p option\n"));
continue;
}
if ((pidsz *= 2) == 0)
}
} while (*p1);
break;
case 's': /* session */
sflg++;
do {
pgerrflg++;
gettext("is an invalid "
"non-numeric argument"));
else
gettext("exceeds valid "
"range"));
gettext(" for -s option\n"));
continue;
}
if ((sessidsz *= 2) == 0)
}
} while (*p1);
break;
case 'g': /* proc group */
gflg++;
do {
pgerrflg++;
gettext("is an invalid "
"non-numeric argument"));
else
gettext("exceeds valid "
"range"));
gettext(" for -g option\n"));
continue;
}
if ((grpidsz *= 2) == 0)
}
} while (*p1);
break;
case 'u': /* effective user name or number */
uflg++;
do {
} while (*p1);
break;
case 'U': /* real user name or number */
Uflg++;
do {
} while (*p1);
break;
case 'G': /* real group name or number */
Gflg++;
do {
} while (*p1);
break;
case 'o': /* output format */
p = optarg;
while ((p = parse_format(p)) != NULL)
;
break;
case 'z': /* zone name or number */
zflg++;
do {
pgerrflg++;
gettext("ps: unknown zone %s\n"),
parg);
continue;
}
if ((zoneidsz *= 2) == 0)
}
} while (*p1);
break;
case 'Z': /* show zone name */
Zflg++;
break;
default: /* error on ? */
errflg++;
break;
}
usage();
if (tflg)
/*
* If an appropriate option has not been specified, use the
* current terminal and effective uid as the default.
*/
int procfd;
char *name;
/* get our own controlling tty name using /proc */
gettext("ps: no controlling terminal\n"));
exit(1);
}
i = 0;
if (*name == '?') {
gettext("ps: can't find controlling terminal\n"));
exit(1);
}
if ((ttysz *= 2) == 0)
}
tflg++;
}
if (Aflg) {
}
tflg = 0;
i = 0; /* prepare to exit on name lookup errors */
if (i)
exit(1);
/* allocate a buffer for lwpsinfo structures */
lpbufsize = 4096;
gettext("ps: no memory\n"));
exit(1);
}
if (fields) { /* print user-specified header */
if (do_header) {
struct field *f;
if (f != fields)
(void) printf(" ");
switch (f->fname) {
case F_TTY:
(void) printf("%-*s",
break;
case F_FNAME:
case F_COMM:
case F_ARGS:
/*
* Print these headers full width
* unless they appear at the end.
*/
(void) printf("%-*s",
} else {
(void) printf("%s",
f->header);
}
break;
default:
(void) printf("%*s",
break;
}
}
(void) printf("\n");
}
} else { /* print standard header */
/*
* All fields before 'PID' are printed with a trailing space
* as a separator and that is how we print the headers too.
*/
if (lflg) {
if (yflg)
(void) printf("S ");
else
(void) printf(" F S ");
}
if (Zflg)
(void) printf(" ZONE ");
if (fflg) {
(void) printf(" UID ");
} else if (lflg)
(void) printf(" UID ");
if (jflg)
pidwidth, "SID");
if (Lflg)
(void) printf(" LWP");
if (Pflg)
(void) printf(" PSR");
(void) printf(" NLWP");
if (cflg)
(void) printf(" CLS PRI");
(void) printf(" C");
if (lflg)
(void) printf(" PRI NI");
}
if (lflg) {
if (yflg)
(void) printf(" RSS SZ WCHAN");
else
(void) printf(" ADDR SZ WCHAN");
}
if (fflg)
if (Hflg)
(void) printf(" LGRP");
if (Lflg)
(void) printf(" TTY LTIME CMD\n");
else
(void) printf(" TTY TIME CMD\n");
}
npid <= PTHRESHOLD) {
/*
* If we are looking at specific processes go straight
* to their /proc entries and don't scan /proc.
*/
int i;
for (i = 0; i < npid; i++) {
continue;
if (print_proc(pname) == 0)
retcode = 0;
}
} else {
/*
* Determine which processes to print info about by searching
* the /proc directory and looking at each process.
*/
gettext("ps: cannot open PROC directory %s\n"),
procdir);
exit(1);
}
/* for each active process --- */
continue;
retcode = 0;
}
}
return (retcode);
}
int
{
int pdlen;
int found;
return (1);
/* Process may have exited meanwhile. */
return (1);
}
/*
* Get the info structure for the process and close quickly.
*/
goto retry;
gettext("ps: read() on %s: %s\n"),
return (1);
}
found = 0;
return (1);
/*
* Omit session group leaders for 'a' and 'd' options.
*/
return (1);
found++;
found++; /* ppid in p option arg list */
found++; /* puid in u option arg list */
found++; /* puid in U option arg list */
#ifdef NOT_YET
found++; /* pgid in g option arg list */
#endif /* NOT_YET */
found++; /* pgid in G option arg list */
found++; /* grpid in g option arg list */
found++; /* sessid in s option arg list */
found++; /* zoneid in z option arg list */
found++; /* home lgroup in h option arg list */
return (1);
return (1);
return (1);
/*
* Get the info structures for the lwps.
*/
if (prsz == -1) {
goto retry;
gettext("ps: read() on %s: %s\n"),
return (1);
}
/*
* buffer overflow. Realloc new buffer.
* Error handling is done in Realloc().
*/
lpbufsize *= 2;
goto retry;
}
goto retry;
}
} else {
int nlwp = 0;
do {
/* LINTED improper alignment */
}
return (0);
}
static int
field_cmp(const void *l, const void *r)
{
}
static void
{
static char usage1[] =
"ps [ -aAdefHlcjLPWyZ ] [ -o format ] [ -t termlist ]";
static char usage2[] =
"\t[ -u userlist ] [ -U userlist ] [ -G grouplist ]";
static char usage3[] =
"\t[ -p proclist ] [ -g pgrplist ] [ -s sidlist ]";
static char usage4[] =
"\t[ -z zonelist ] [-h lgrplist]";
static char usage5[] =
" 'format' is one or more of:";
gettext("usage: %s\n%s\n%s\n%s\n%s"),
/*
* Now print out the possible output formats such that they neatly fit
* into eighty columns. Note that the fact that we are determining
* this output programmatically means that a gettext() is impossible --
* but it would be a mistake to localize the output formats anyway as
* they are tokens for input, not output themselves.
*/
for (i = 0; i < NFIELDS; i++) {
pos = 8;
}
}
exit(1);
}
/*
* getarg() finds the next argument in list and copies arg into argbuf.
* p1 first pts to arg passed back from getopt routine. p1 is then
* bumped to next character that is not a comma or blank -- p1 NULL
* indicates end of list.
*/
static char *
{
int c;
p1++;
*parga++ = c;
p1++;
}
*parga = '\0';
p1++;
return (argbuf);
}
/*
* parse_format() takes the argument to the -o option,
* sets up the next output field structure, and returns
* a pointer to any further output field specifier(s).
* As a side-effect, it increments errflg if encounters a format error.
*/
static char *
{
int c;
char *name;
int width = 0;
struct field *f;
arg++;
if (c == '\0')
return (NULL);
c = *arg;
*arg++ = '\0';
if (c == '=') {
char *s;
*s = '\0';
header++;
}
}
Lflg++;
break;
}
gettext("ps: unknown output format: -o %s\n"),
name);
errflg++;
return (arg);
}
gettext("ps: malloc() for output format failed, %s\n"),
err_string(errno));
exit(1);
}
if (width == 0)
if (*f->header != '\0')
do_header = 1;
fields = last_field = f;
else {
last_field->next = f;
last_field = f;
}
return (arg);
}
static char *
{
int i;
}
return (NULL);
}
static char *
{
}
}
/* Strip off /dev/ */
else {
;
if (i == leng)
else
}
}
/*
* gettty returns the user's tty number or ? if none.
*/
static char *
{
char *retval;
if (zid == -1)
return ("?");
return (retval);
}
/*
* Find the process's tty and return 1 if process is to be printed.
*/
static int
{
char *tp;
/* process is a zombie */
*tpp = "?";
return (0);
return (1);
}
/*
* Get current terminal. If none ("?") and 'a' is set, don't print
* info. If 't' is set, check if term is in list of desired terminals
* and print it if it is.
*/
return (0);
}
int match = 0;
/*
* Look for a name match
*/
match = 1;
break;
}
/*
* Look for same device under different names.
*/
}
/*
* found under a different name
*/
match = 1;
}
/*
* not found OR not matching euid
*/
return (0);
}
}
return (1);
}
/*
* Print info about the process.
*/
static void
{
char *cp;
long tm;
int bytesleft;
int zombie_lwp;
/*
* If process is zombie, call zombie print routine and return.
*/
else
return;
}
/*
* If user specified '-o format', print requested fields and return.
*/
return;
}
/*
* All fields before 'PID' are printed with a trailing space as a
* separator, rather than keeping track of which column is first. All
* other fields are printed with a leading space.
*/
if (lflg) {
if (!yflg)
}
if (Zflg) { /* ZONE */
sizeof (zonename)) < 0) {
(void) printf(" %6.6d%c ",
else
(void) printf(" %7.7d ",
} else {
else if (nw > 8)
else
}
}
if (fflg) { /* UID */
else if (nw > 8)
else
} else {
'*');
else
}
} else if (lflg) {
else
}
if (jflg) {
}
if (Lflg)
if (Pflg) {
(void) printf(" -");
else
}
if (cflg) {
if (zombie_lwp) /* CLS */
(void) printf(" ");
else
if (lflg) { /* PRI NI */
/*
* Print priorities the old way (lower numbers
* mean higher priority) and print nice value
* for time sharing procs.
*/
else
(void) printf(" %2.2s",
}
}
if (lflg) {
if (yflg) {
(void) printf(" 0");
(void) printf(" %5lu",
else
(void) printf(" ?");
(void) printf(" 0");
(void) printf(" %6lu",
else
(void) printf(" ?");
} else {
#ifndef _LP64
(void) printf(" %8lx",
else
#endif
(void) printf(" ?");
(void) printf(" 0");
(void) printf(" %6lu",
else
(void) printf(" ?");
}
(void) printf(" ");
#ifndef _LP64
(void) printf(" %8lx",
#endif
else
(void) printf(" ?");
}
if (fflg) { /* STIME */
if (Lflg)
else
}
if (Hflg) {
/* Display home lgroup */
}
if (Lflg) {
tm++;
} else {
tm++;
}
if (zombie_lwp) {
(void) printf(" <defunct>\n");
return;
}
if (!fflg) { /* CMD */
return;
}
/*
* PRARGSZ == length of cmd arg string.
*/
if (length == 0)
break;
if (length < 0)
length = 1;
*cp = '\0';
break;
}
/* omit the unprintable character */
length = 0;
}
}
}
/*
* Print percent from 16-bit binary fraction [0 .. 1]
* Round up .01 to .1 to indicate some small percentage (the 0x7000 below).
*/
static void
{
if (value >= 1000)
value = 999;
width = 2;
}
static void
{
if (tim < 0) {
return;
}
tim /= 60;
tim /= 60;
if (days > 0) {
} else if (hours > 0) {
} else {
}
}
static void
{
int bytesleft;
int wcnt;
char *cp;
int length;
int zombie_lwp;
switch (f->fname) {
case F_RUSER:
else
} else {
else
}
break;
case F_USER:
else
} else {
else
}
break;
case F_RGROUP:
else
break;
case F_GROUP:
else
break;
case F_RUID:
break;
case F_UID:
break;
case F_RGID:
break;
case F_GID:
break;
case F_PID:
break;
case F_PPID:
break;
case F_PGID:
break;
case F_SID:
break;
case F_PSR:
else
break;
case F_LWP:
break;
case F_NLWP:
break;
case F_OPRI:
if (zombie_lwp)
else
break;
case F_PRI:
if (zombie_lwp)
else
break;
case F_F:
mask = 0xffffffffUL;
if (width < 8)
break;
case F_S:
break;
case F_C:
if (zombie_lwp)
else
break;
case F_PCPU:
if (zombie_lwp)
else if (Lflg)
else
break;
case F_PMEM:
break;
case F_OSZ:
break;
case F_VSZ:
break;
case F_RSS:
break;
case F_NICE:
/* if pr_oldpri is zero, then this class has no nice */
if (zombie_lwp)
else
break;
case F_CLASS:
if (zombie_lwp)
else
break;
case F_STIME:
if (Lflg)
else
break;
case F_ETIME:
if (Lflg)
width);
else
break;
case F_TIME:
if (Lflg) {
cputime++;
} else {
cputime++;
}
break;
case F_TTY:
break;
case F_ADDR:
if (zombie_lwp)
else if (Lflg)
else
break;
case F_WCHAN:
else
break;
case F_FNAME:
/*
* Print full width unless this is the last output format.
*/
if (zombie_lwp) {
else
break;
}
else
break;
case F_COMM:
if (zombie_lwp) {
else
break;
}
if (csave) {
c = *csave;
*csave = '\0';
}
/* FALLTHROUGH */
case F_ARGS:
/*
* PRARGSZ == length of cmd arg string.
*/
if (zombie_lwp) {
break;
}
if (length == 0)
break;
if (length < 0)
length = 1;
*cp = '\0';
break;
}
/* omit the unprintable character */
length = 0;
}
}
/*
* Print full width unless this is the last format.
*/
else
*csave = c;
break;
case F_TASKID:
break;
case F_PROJID:
break;
case F_PROJECT:
{
else
} else {
else
}
}
break;
case F_PSET:
else
break;
case F_ZONEID:
break;
case F_ZONE:
{
sizeof (zonename)) < 0) {
else
} else {
zonename, '*');
else
}
}
break;
case F_CTID:
else
break;
case F_LGRP:
/* Display home lgroup */
break;
case F_DMODEL:
break;
}
}
static void
{
int wcnt;
switch (f->fname) {
case F_FNAME:
case F_COMM:
case F_ARGS:
/*
* Print full width unless this is the last output format.
*/
else
break;
case F_PSR:
case F_PCPU:
case F_PMEM:
case F_NICE:
case F_CLASS:
case F_STIME:
case F_ETIME:
case F_WCHAN:
case F_PSET:
break;
case F_OPRI:
case F_PRI:
case F_OSZ:
case F_VSZ:
case F_RSS:
break;
default:
break;
}
}
static void
{
struct field *f;
(void) printf(" ");
}
(void) printf("\n");
}
/*
* Returns 1 if arg is found in array arr, of length num; 0 otherwise.
*/
static int
{
int i;
for (i = 0; i < number; i++)
return (1);
return (0);
}
/*
* Add an entry (user, group) to the specified table.
*/
static void
{
}
}
static int
{
int i;
int fnd = 0;
/*
* Ask the name service for names.
*/
for (i = 0; i < n; i++) {
/*
* If name is numeric, ask for numeric id
*/
else
/*
* If found, enter found index into tbl array.
*/
continue;
}
fnd++;
}
return (n - fnd);
}
static int
{
int i;
int fnd = 0;
/*
* Ask the name service for names.
*/
for (i = 0; i < n; i++) {
/*
* If name is numeric, ask for numeric id
*/
else
/*
* If found, enter found index into tbl array.
*/
continue;
}
fnd++;
}
return (n - fnd);
}
/*
* Return 1 if puid is in table, otherwise 0.
*/
static int
{
int i;
for (i = 0; i < n; i++)
return (1);
return (0);
}
/*
* Print starting time of process unless process started more than 24 hours
* ago, in which case the date is printed. The date is printed in the form
* "MMM dd" if old format, else the blank is replaced with an '_' so
* it appears as a single word (for parseability).
*/
static void
{
starttime++;
/*
* TRANSLATION_NOTE
* This time format is used by STIME field when -f option
* is specified. Used for processes that begun more than
* 24 hours.
*/
/*
* TRANSLATION_NOTE
* This time format is used by STIME field when -o option
* is specified. Used for processes that begun more than
* 24 hours.
*/
} else {
/*
* TRANSLATION_NOTE
* This time format is used by STIME field when -f or -o option
* is specified. Used for processes that begun less than
* 24 hours.
*/
}
}
static void
{
long tm;
/*
* All fields before 'PID' are printed with a trailing space as a
* spearator, rather than keeping track of which column is first. All
* other fields are printed with a leading space.
*/
if (lflg) { /* F S */
if (!yflg)
}
if (Zflg) {
sizeof (zonename)) < 0) {
(void) printf(" %6.6d%c ",
else
(void) printf(" %7.7d ",
} else {
else if (nw > 8)
else
}
}
if (Hflg) {
/* Display home lgroup */
}
if (fflg) {
else if (nw > 8)
else
} else {
'*');
else
}
} else if (lflg) {
else
}
if (jflg) {
}
if (Lflg)
if (Pflg)
if (cflg) {
if (lflg)
(void) printf(" %3d %2s",
}
if (lflg) {
if (yflg) /* RSS SZ WCHAN */
else /* ADDR SZ WCHAN */
}
if (fflg) {
}
tm++;
(void) printf(" <defunct>\n");
}
/*
* Function to compute the number of printable bytes in a multibyte
* command string ("internationalization").
*/
static int
{
int len;
while (*cmd != '\0') {
len = MB_CUR_MAX;
return (8); /* default to use for illegal chars */
return (8);
break;
}
return (csiwcnt);
}
static char *
{
return (str);
}
/* If allocation fails, die */
static void *
{
exit(1);
}
return (ptr);
}
static time_t
{
seconds++;
seconds--;
return (seconds);
}
/*
* Returns the following:
*
* 0 No error
* EINVAL Invalid number
* ERANGE Value exceeds (min, max) range
*/
static int
{
char *q;
long number;
int error;
errno = 0;
if (errno != 0 || q == p || *q != '\0') {
/*
* strtol() can fail without setting errno, or it can
* set it to EINVAL or ERANGE. In the case errno is
* still zero, return EINVAL.
*/
}
} else {
error = 0;
}
return (error);
}
/*
* Returns the following:
*
* 0 No error
* EINVAL Invalid number
* ERANGE Value exceeds (min, max) range
*/
static int
{
char *q;
unsigned long number;
int error;
errno = 0;
if (errno != 0 || q == p || *q != '\0') {
/*
* strtoul() can fail without setting errno, or it can
* set it to EINVAL or ERANGE. In the case errno is
* still zero, return EINVAL.
*/
}
} else {
error = 0;
}
return (error);
}
static int
{
return (i - j);
}