mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
Support more POSIX/SUSv3 options:
- Change `-p' to allow a list of process IDs, and `-t' to allow a list of terminal names, instead of only a single value for each. - Add the `-A' option of SUSv3, which is exactly the same as `-ax'. - Add the `-G gidlist' (group id). - Allow any of these "selector options" to be specified multiple times, and have `ps' keep adding to a given list -- instead of replacing the previously-specified values. - Fix interactions between selector-options, so that: "If any are specified, ... ps shall select the processes represented by the inclusive OR of all the selection-criteria options." (from SUSv3) - Add a `-X' option, which is the reverse of the `-x' option. - various minor improvements in parsing and error handling. This does not get us to match POSIX/SUSv3, but it gets us closer. The `-g pgidlist', `-R ruserlist' and `-s sidlist' options mentioned in freebsd-standards are still under debate, so they skipped for now. It should be true that this introduces no user-visible incompatible changes, except to support "new stuff" that was not supported before.
This commit is contained in:
parent
b2ae7ed72c
commit
a4c8a745a8
2 changed files with 587 additions and 194 deletions
61
bin/ps/ps.1
61
bin/ps/ps.1
|
|
@ -40,7 +40,11 @@
|
||||||
.Nd process status
|
.Nd process status
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl aCcefHhjlmrSTuvwxZ
|
.Op Fl aCcefHhjlmrSTuvwXxZ
|
||||||
|
.Oo Fl G Ar gid Ns Xo
|
||||||
|
.Op , Ns Ar gid Ns No ...
|
||||||
|
.Xc
|
||||||
|
.Oc
|
||||||
.Op Fl M Ar core
|
.Op Fl M Ar core
|
||||||
.Op Fl N Ar system
|
.Op Fl N Ar system
|
||||||
.Op Fl O Ar fmt
|
.Op Fl O Ar fmt
|
||||||
|
|
@ -49,7 +53,10 @@
|
||||||
.Op , Ns Ar pid Ns No ...
|
.Op , Ns Ar pid Ns No ...
|
||||||
.Xc
|
.Xc
|
||||||
.Oc
|
.Oc
|
||||||
.Op Fl t Ar tty
|
.Oo Fl t Ar tty Ns Xo
|
||||||
|
.Op , Ns Ar tty Ns No ...
|
||||||
|
.Xc
|
||||||
|
.Oc
|
||||||
.Oo Fl U Ar username Ns Xo
|
.Oo Fl U Ar username Ns Xo
|
||||||
.Op , Ns Ar username Ns No ...
|
.Op , Ns Ar username Ns No ...
|
||||||
.Xc
|
.Xc
|
||||||
|
|
@ -65,7 +72,19 @@ processes that have controlling terminals.
|
||||||
This information is sorted by controlling terminal, then by process
|
This information is sorted by controlling terminal, then by process
|
||||||
.Tn ID .
|
.Tn ID .
|
||||||
.Pp
|
.Pp
|
||||||
The information displayed is selected based on a set of keywords (see the
|
A different set of processes can be selected for display by using any
|
||||||
|
combination of the
|
||||||
|
.Fl a, G , p , T , t
|
||||||
|
and
|
||||||
|
.Fl U
|
||||||
|
options.
|
||||||
|
If more than one of these options are given, then
|
||||||
|
.Nm
|
||||||
|
will select all processes which are matched by at least one of the
|
||||||
|
given options.
|
||||||
|
.Pp
|
||||||
|
For the processes which have been selected for display, the information
|
||||||
|
to display is selected based on a set of keywords (see the
|
||||||
.Fl L
|
.Fl L
|
||||||
.Fl O
|
.Fl O
|
||||||
and
|
and
|
||||||
|
|
@ -86,6 +105,10 @@ The options are as follows:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
.It Fl a
|
.It Fl a
|
||||||
Display information about other users' processes as well as your own.
|
Display information about other users' processes as well as your own.
|
||||||
|
This will skip any processes which do not have a controlling teminal,
|
||||||
|
unless the
|
||||||
|
.Fl x
|
||||||
|
option is also specified.
|
||||||
This can be disabled by setting the
|
This can be disabled by setting the
|
||||||
.Va security.bsd.see_other_uids
|
.Va security.bsd.see_other_uids
|
||||||
sysctl to zero.
|
sysctl to zero.
|
||||||
|
|
@ -101,6 +124,10 @@ Display the environment as well.
|
||||||
.It Fl f
|
.It Fl f
|
||||||
Show commandline and environment information about swapped out processes.
|
Show commandline and environment information about swapped out processes.
|
||||||
This option is honored only if the uid of the user is 0.
|
This option is honored only if the uid of the user is 0.
|
||||||
|
.It Fl G
|
||||||
|
Display information about processes which are running with the specified
|
||||||
|
real group
|
||||||
|
.Tn ID(s) .
|
||||||
.It Fl H
|
.It Fl H
|
||||||
Show all of the
|
Show all of the
|
||||||
.Em kernel visible
|
.Em kernel visible
|
||||||
|
|
@ -147,7 +174,7 @@ Keywords may be appended with an equals (``='') sign and a string.
|
||||||
This causes the printed header to use the specified string instead of
|
This causes the printed header to use the specified string instead of
|
||||||
the standard header.
|
the standard header.
|
||||||
.It Fl p
|
.It Fl p
|
||||||
Display information associated with the specified process
|
Display information about processes which match the specified process
|
||||||
.Tn ID(s) .
|
.Tn ID(s) .
|
||||||
.It Fl r
|
.It Fl r
|
||||||
Sort by current cpu usage, instead of by process
|
Sort by current cpu usage, instead of by process
|
||||||
|
|
@ -160,7 +187,7 @@ Display information about processes attached to the device associated
|
||||||
with the standard input.
|
with the standard input.
|
||||||
.It Fl t
|
.It Fl t
|
||||||
Display information about processes attached to the specified terminal
|
Display information about processes attached to the specified terminal
|
||||||
device.
|
device(s).
|
||||||
.It Fl U
|
.It Fl U
|
||||||
Display the processes belonging to the specified
|
Display the processes belonging to the specified
|
||||||
.Ar username Ns (s) .
|
.Ar username Ns (s) .
|
||||||
|
|
@ -189,8 +216,22 @@ If the
|
||||||
option is specified more than once,
|
option is specified more than once,
|
||||||
.Nm
|
.Nm
|
||||||
will use as many columns as necessary without regard for your window size.
|
will use as many columns as necessary without regard for your window size.
|
||||||
|
.It Fl X
|
||||||
|
When displaying processes matched by other options, skip any processes
|
||||||
|
which do not have a controlling terminal.
|
||||||
.It Fl x
|
.It Fl x
|
||||||
Display information about processes without controlling terminals.
|
When displaying processes matched by other options, include processes
|
||||||
|
which do not have a controlling terminal.
|
||||||
|
This is the opposite of the
|
||||||
|
.Fl X
|
||||||
|
option.
|
||||||
|
If both
|
||||||
|
.Fl X
|
||||||
|
and
|
||||||
|
.Fl x
|
||||||
|
are specified in the same command, then
|
||||||
|
.Nm
|
||||||
|
will use the one which was specified last.
|
||||||
.It Fl Z
|
.It Fl Z
|
||||||
Add label to the list of keywords for which
|
Add label to the list of keywords for which
|
||||||
.Nm
|
.Nm
|
||||||
|
|
@ -542,6 +583,14 @@ the mount point of
|
||||||
.Xr pstat 8 ,
|
.Xr pstat 8 ,
|
||||||
.Xr sysctl 8 ,
|
.Xr sysctl 8 ,
|
||||||
.Xr mutex 9
|
.Xr mutex 9
|
||||||
|
.Sh STANDARDS
|
||||||
|
For historical reasons,
|
||||||
|
.Nm
|
||||||
|
utility under
|
||||||
|
.Fx
|
||||||
|
supports a different set of options from what is described by
|
||||||
|
.St -p1003.2 ,
|
||||||
|
and what is supported on non-BSD operating systems.
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
|
|
|
||||||
720
bin/ps/ps.c
720
bin/ps/ps.c
|
|
@ -29,6 +29,13 @@
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* SUCH DAMAGE.
|
||||||
|
* ------+---------+---------+-------- + --------+---------+---------+---------*
|
||||||
|
* Copyright (c) 2004 - Garance Alistair Drosehn <gad@FreeBSD.org>.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Significant modifications made to bring `ps' options somewhat closer
|
||||||
|
* to the standard for `ps' as described in SingleUnixSpec-v3.
|
||||||
|
* ------+---------+---------+-------- + --------+---------+---------+---------*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
|
|
@ -56,11 +63,13 @@ __FBSDID("$FreeBSD$");
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <grp.h>
|
||||||
#include <kvm.h>
|
#include <kvm.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -68,13 +77,15 @@ __FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include "ps.h"
|
#include "ps.h"
|
||||||
|
|
||||||
#define SEP ", \t" /* username separators */
|
#define W_SEP " \t" /* "Whitespace" list separators */
|
||||||
|
#define T_SEP "," /* "Terminate-element" list separators */
|
||||||
|
|
||||||
static KINFO *kinfo;
|
static KINFO *kinfo;
|
||||||
struct varent *vhead;
|
struct varent *vhead;
|
||||||
|
|
||||||
int eval; /* exit value */
|
int eval; /* exit value */
|
||||||
int cflag; /* -c */
|
int cflag; /* -c */
|
||||||
|
int optfatal; /* Fatal error parsing some list-option */
|
||||||
int rawcpu; /* -C */
|
int rawcpu; /* -C */
|
||||||
int sumrusage; /* -S */
|
int sumrusage; /* -S */
|
||||||
int termwidth; /* width of screen (0 == infinity) */
|
int termwidth; /* width of screen (0 == infinity) */
|
||||||
|
|
@ -82,6 +93,24 @@ int totwidth; /* calculated width of requested variables */
|
||||||
|
|
||||||
time_t now; /* current time(3) value */
|
time_t now; /* current time(3) value */
|
||||||
|
|
||||||
|
struct listinfo;
|
||||||
|
typedef int addelem_rtn(struct listinfo *_inf, const char *elem);
|
||||||
|
|
||||||
|
struct listinfo {
|
||||||
|
int count;
|
||||||
|
int maxcount;
|
||||||
|
int elemsize;
|
||||||
|
addelem_rtn *addelem;
|
||||||
|
const char *lname;
|
||||||
|
union {
|
||||||
|
gid_t *gids;
|
||||||
|
pid_t *pids;
|
||||||
|
dev_t *ttys;
|
||||||
|
uid_t *uids;
|
||||||
|
void *ptr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
static int needuser, needcomm, needenv;
|
static int needuser, needcomm, needenv;
|
||||||
#if defined(LAZY_PS)
|
#if defined(LAZY_PS)
|
||||||
static int forceuread=0;
|
static int forceuread=0;
|
||||||
|
|
@ -100,8 +129,15 @@ static void scanvars(void);
|
||||||
static void dynsizevars(KINFO *);
|
static void dynsizevars(KINFO *);
|
||||||
static void sizevars(void);
|
static void sizevars(void);
|
||||||
static void usage(void);
|
static void usage(void);
|
||||||
static pid_t *getpids(const char *, int *);
|
|
||||||
static uid_t *getuids(const char *, int *);
|
static int addelem_gid(struct listinfo *, const char *);
|
||||||
|
static int addelem_pid(struct listinfo *, const char *);
|
||||||
|
static int addelem_tty(struct listinfo *, const char *);
|
||||||
|
static int addelem_uid(struct listinfo *, const char *);
|
||||||
|
static void add_list(struct listinfo *, const char *);
|
||||||
|
static void *expand_list(struct listinfo *);
|
||||||
|
static void free_list(struct listinfo *);
|
||||||
|
static void init_list(struct listinfo *, addelem_rtn, int, const char *);
|
||||||
|
|
||||||
static char dfmt[] = "pid,tt,state,time,command";
|
static char dfmt[] = "pid,tt,state,time,command";
|
||||||
static char jfmt[] = "user,pid,ppid,pgid,jobc,state,tt,time,command";
|
static char jfmt[] = "user,pid,ppid,pgid,jobc,state,tt,time,command";
|
||||||
|
|
@ -115,23 +151,22 @@ static char Zfmt[] = "label";
|
||||||
static kvm_t *kd;
|
static kvm_t *kd;
|
||||||
|
|
||||||
#if defined(LAZY_PS)
|
#if defined(LAZY_PS)
|
||||||
#define PS_ARGS "aCcefgHhjLlM:mN:O:o:p:rSTt:U:uvwxZ"
|
#define PS_ARGS "AaCcefG:gHhjLlM:mN:O:o:p:rSTt:U:uvwXxZ"
|
||||||
#else
|
#else
|
||||||
#define PS_ARGS "aCcegHhjLlM:mN:O:o:p:rSTt:U:uvwxZ"
|
#define PS_ARGS "AaCceG:gHhjLlM:mN:O:o:p:rSTt:U:uvwXxZ"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
struct listinfo gidlist, pgrplist, pidlist;
|
||||||
|
struct listinfo ruidlist, sesslist, ttylist, uidlist;
|
||||||
struct kinfo_proc *kp;
|
struct kinfo_proc *kp;
|
||||||
struct varent *vent;
|
struct varent *vent;
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
dev_t ttydev;
|
int all, ch, dropgid, elem, flag, _fmt, i, lineno;
|
||||||
pid_t *pids;
|
int nentries, nocludge, nkept, nselectors;
|
||||||
uid_t *uids;
|
int prtheader, showthreads, wflag, what, xkeep, xkeep_implied;
|
||||||
int all, ch, dropgid, flag, _fmt, i, lineno;
|
|
||||||
int nentries, nocludge, noutput, npids, nuids, pid;
|
|
||||||
int prtheader, showthreads, uid, wflag, what, xflg;
|
|
||||||
char *cols;
|
char *cols;
|
||||||
char errbuf[_POSIX2_LINE_MAX];
|
char errbuf[_POSIX2_LINE_MAX];
|
||||||
const char *cp, *nlistf, *memf;
|
const char *cp, *nlistf, *memf;
|
||||||
|
|
@ -170,16 +205,32 @@ main(int argc, char *argv[])
|
||||||
argv[1] = kludge_oldps_options(argv[1]);
|
argv[1] = kludge_oldps_options(argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
all = _fmt = prtheader = wflag = xflg = 0;
|
xkeep = -1; /* Neither -x nor -X */
|
||||||
npids = nuids = 0;
|
all = _fmt = nselectors = prtheader = wflag = xkeep_implied = 0;
|
||||||
pids = uids = NULL;
|
init_list(&gidlist, addelem_gid, sizeof(gid_t), "group");
|
||||||
ttydev = NODEV;
|
init_list(&pgrplist, addelem_pid, sizeof(pid_t), "process group");
|
||||||
|
init_list(&pidlist, addelem_pid, sizeof(pid_t), "process id");
|
||||||
|
init_list(&ruidlist, addelem_uid, sizeof(uid_t), "ruser");
|
||||||
|
init_list(&sesslist, addelem_pid, sizeof(pid_t), "session id");
|
||||||
|
init_list(&ttylist, addelem_tty, sizeof(dev_t), "tty");
|
||||||
|
init_list(&uidlist, addelem_uid, sizeof(uid_t), "user");
|
||||||
dropgid = 0;
|
dropgid = 0;
|
||||||
|
optfatal = 0;
|
||||||
memf = nlistf = _PATH_DEVNULL;
|
memf = nlistf = _PATH_DEVNULL;
|
||||||
showthreads = 0;
|
showthreads = 0;
|
||||||
while ((ch = getopt(argc, argv, PS_ARGS)) != -1)
|
while ((ch = getopt(argc, argv, PS_ARGS)) != -1)
|
||||||
switch((char)ch) {
|
switch((char)ch) {
|
||||||
|
case 'A':
|
||||||
|
/*
|
||||||
|
* Exactly the same as `-ax'. This has been
|
||||||
|
* added for compatability with SUSv3, but for
|
||||||
|
* now it will not be described in the man page.
|
||||||
|
*/
|
||||||
|
nselectors++;
|
||||||
|
all = xkeep = 1;
|
||||||
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
|
nselectors++;
|
||||||
all = 1;
|
all = 1;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
|
|
@ -191,8 +242,24 @@ main(int argc, char *argv[])
|
||||||
case 'e': /* XXX set ufmt */
|
case 'e': /* XXX set ufmt */
|
||||||
needenv = 1;
|
needenv = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'G':
|
||||||
|
add_list(&gidlist, optarg);
|
||||||
|
xkeep_implied = 1;
|
||||||
|
nselectors++;
|
||||||
|
break;
|
||||||
|
#if 0
|
||||||
|
/* XXX - This SUSv3 option is still under debate. */
|
||||||
|
/* (it conflicts with the undocumented `-g' option) */
|
||||||
case 'g':
|
case 'g':
|
||||||
|
add_list(&pgrplist, optarg);
|
||||||
|
xkeep_implied = 1;
|
||||||
|
nselectors++;
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
case 'g':
|
||||||
|
/* Historical BSD-ish (from SunOS) option */
|
||||||
break; /* no-op */
|
break; /* no-op */
|
||||||
|
#endif
|
||||||
case 'H':
|
case 'H':
|
||||||
showthreads = KERN_PROC_INC_THREAD;
|
showthreads = KERN_PROC_INC_THREAD;
|
||||||
break;
|
break;
|
||||||
|
|
@ -241,40 +308,54 @@ main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'p':
|
case 'p':
|
||||||
pids = getpids(optarg, &npids);
|
add_list(&pidlist, optarg);
|
||||||
xflg = 1;
|
/*
|
||||||
|
* Note: `-p' does not *set* xkeep, but any values
|
||||||
|
* from pidlist are checked before xkeep is. That
|
||||||
|
* way they are always matched, even if the user
|
||||||
|
* specifies `-X'.
|
||||||
|
*/
|
||||||
|
nselectors++;
|
||||||
break;
|
break;
|
||||||
|
#if 0
|
||||||
|
/* XXX - This un-standard option is still under debate. */
|
||||||
|
case 'R':
|
||||||
|
/* This is what SUSv3 defines as the `-U' option. */
|
||||||
|
add_list(&ruidlist, optarg);
|
||||||
|
xkeep_implied = 1;
|
||||||
|
nselectors++;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case 'r':
|
case 'r':
|
||||||
sortby = SORTCPU;
|
sortby = SORTCPU;
|
||||||
break;
|
break;
|
||||||
case 'S':
|
case 'S':
|
||||||
sumrusage = 1;
|
sumrusage = 1;
|
||||||
break;
|
break;
|
||||||
|
#if 0
|
||||||
|
/* XXX - This non-standard option is still under debate. */
|
||||||
|
/* (it conflicts with `-s' in NetBSD) */
|
||||||
|
case 's':
|
||||||
|
/* As seen on Solaris, Linux, IRIX. */
|
||||||
|
add_list(&sesslist, optarg);
|
||||||
|
xkeep_implied = 1;
|
||||||
|
nselectors++;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case 'T':
|
case 'T':
|
||||||
if ((optarg = ttyname(STDIN_FILENO)) == NULL)
|
if ((optarg = ttyname(STDIN_FILENO)) == NULL)
|
||||||
errx(1, "stdin: not a terminal");
|
errx(1, "stdin: not a terminal");
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
case 't': {
|
case 't':
|
||||||
struct stat sb;
|
add_list(&ttylist, optarg);
|
||||||
char *ttypath, pathbuf[PATH_MAX];
|
xkeep_implied = 1;
|
||||||
|
nselectors++;
|
||||||
if (strcmp(optarg, "co") == 0)
|
|
||||||
ttypath = strdup(_PATH_CONSOLE);
|
|
||||||
else if (*optarg != '/')
|
|
||||||
(void)snprintf(ttypath = pathbuf,
|
|
||||||
sizeof(pathbuf), "%s%s", _PATH_TTY, optarg);
|
|
||||||
else
|
|
||||||
ttypath = optarg;
|
|
||||||
if (stat(ttypath, &sb) == -1)
|
|
||||||
err(1, "%s", ttypath);
|
|
||||||
if (!S_ISCHR(sb.st_mode))
|
|
||||||
errx(1, "%s: not a terminal", ttypath);
|
|
||||||
ttydev = sb.st_rdev;
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case 'U':
|
case 'U':
|
||||||
uids = getuids(optarg, &nuids);
|
/* This is what SUSv3 defines as the `-u' option. */
|
||||||
xflg++; /* XXX: intuitive? */
|
add_list(&uidlist, optarg);
|
||||||
|
xkeep_implied = 1;
|
||||||
|
nselectors++;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
parsefmt(ufmt, 0);
|
parsefmt(ufmt, 0);
|
||||||
|
|
@ -295,8 +376,22 @@ main(int argc, char *argv[])
|
||||||
termwidth = 131;
|
termwidth = 131;
|
||||||
wflag++;
|
wflag++;
|
||||||
break;
|
break;
|
||||||
|
case 'X':
|
||||||
|
/*
|
||||||
|
* Note that `-X' and `-x' are not standard "selector"
|
||||||
|
* options. For most selector-options, we check *all*
|
||||||
|
* processes to see if any are matched by the given
|
||||||
|
* value(s). After we have a set of all the matched
|
||||||
|
* processes, then `-X' and `-x' govern whether we
|
||||||
|
* modify that *matched* set for processes which do
|
||||||
|
* not have a controlling terminal. `-X' causes
|
||||||
|
* those processes to be deleted from the matched
|
||||||
|
* set, while `-x' causes them to be kept.
|
||||||
|
*/
|
||||||
|
xkeep = 0;
|
||||||
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
xflg = 1;
|
xkeep = 1;
|
||||||
break;
|
break;
|
||||||
case 'Z':
|
case 'Z':
|
||||||
parsefmt(Zfmt, 0);
|
parsefmt(Zfmt, 0);
|
||||||
|
|
@ -309,6 +404,12 @@ main(int argc, char *argv[])
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
|
if (optfatal)
|
||||||
|
exit(1); /* Error messages already printed */
|
||||||
|
|
||||||
|
if (xkeep < 0) /* Neither -X nor -x was specified */
|
||||||
|
xkeep = xkeep_implied;
|
||||||
|
|
||||||
#define BACKWARD_COMPATIBILITY
|
#define BACKWARD_COMPATIBILITY
|
||||||
#ifdef BACKWARD_COMPATIBILITY
|
#ifdef BACKWARD_COMPATIBILITY
|
||||||
if (*argv) {
|
if (*argv) {
|
||||||
|
|
@ -334,12 +435,13 @@ main(int argc, char *argv[])
|
||||||
if (!_fmt)
|
if (!_fmt)
|
||||||
parsefmt(dfmt, 0);
|
parsefmt(dfmt, 0);
|
||||||
|
|
||||||
/* XXX - should be cleaner */
|
if (nselectors == 0) {
|
||||||
if (!all && ttydev == NODEV && !npids && !nuids) {
|
uidlist.ptr = malloc(sizeof(uid_t));
|
||||||
if ((uids = malloc(sizeof (*uids))) == NULL)
|
if (uidlist.ptr == NULL)
|
||||||
errx(1, "malloc failed");
|
errx(1, "malloc failed");
|
||||||
nuids = 1;
|
nselectors = 1;
|
||||||
*uids = getuid();
|
uidlist.count = uidlist.maxcount = 1;
|
||||||
|
*uidlist.uids = getuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -347,37 +449,126 @@ main(int argc, char *argv[])
|
||||||
* and adjusting header widths as appropriate.
|
* and adjusting header widths as appropriate.
|
||||||
*/
|
*/
|
||||||
scanvars();
|
scanvars();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get proc list
|
* Get process list. If the user requested just one selector-
|
||||||
|
* option, then kvm_getprocs can be asked to return just those
|
||||||
|
* processes. Otherwise, have it return all processes, and
|
||||||
|
* then this routine will search that full list and select the
|
||||||
|
* processes which match any of the user's selector-options.
|
||||||
*/
|
*/
|
||||||
if (nuids == 1) {
|
what = showthreads != 0 ? KERN_PROC_ALL : KERN_PROC_PROC;
|
||||||
what = KERN_PROC_UID | showthreads;
|
flag = 0;
|
||||||
flag = *uids;
|
if (nselectors == 1) {
|
||||||
} else if (ttydev != NODEV) {
|
/* XXX - Apparently there's no KERN_PROC_GID flag. */
|
||||||
what = KERN_PROC_TTY | showthreads;
|
if (pgrplist.count == 1) {
|
||||||
flag = ttydev;
|
what = KERN_PROC_PGRP | showthreads;
|
||||||
} else if (npids == 1) {
|
flag = *pgrplist.pids;
|
||||||
what = KERN_PROC_PID | showthreads;
|
nselectors = 0;
|
||||||
flag = *pids;
|
} else if (pidlist.count == 1) {
|
||||||
} else {
|
what = KERN_PROC_PID | showthreads;
|
||||||
what = showthreads != 0 ? KERN_PROC_ALL : KERN_PROC_PROC;
|
flag = *pidlist.pids;
|
||||||
flag = 0;
|
nselectors = 0;
|
||||||
|
} else if (ruidlist.count == 1) {
|
||||||
|
what = KERN_PROC_RUID | showthreads;
|
||||||
|
flag = *ruidlist.uids;
|
||||||
|
nselectors = 0;
|
||||||
|
#if 0 /* XXX - KERN_PROC_SESSION causes error in kvm_getprocs? */
|
||||||
|
} else if (sesslist.count == 1) {
|
||||||
|
what = KERN_PROC_SESSION | showthreads;
|
||||||
|
flag = *sesslist.pids;
|
||||||
|
nselectors = 0;
|
||||||
|
#endif
|
||||||
|
} else if (ttylist.count == 1) {
|
||||||
|
what = KERN_PROC_TTY | showthreads;
|
||||||
|
flag = *ttylist.ttys;
|
||||||
|
nselectors = 0;
|
||||||
|
} else if (uidlist.count == 1) {
|
||||||
|
what = KERN_PROC_UID | showthreads;
|
||||||
|
flag = *uidlist.uids;
|
||||||
|
nselectors = 0;
|
||||||
|
} else if (all) {
|
||||||
|
/* No need for this routine to select processes. */
|
||||||
|
nselectors = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* select procs
|
* select procs
|
||||||
*/
|
*/
|
||||||
|
nentries = -1;
|
||||||
kp = kvm_getprocs(kd, what, flag, &nentries);
|
kp = kvm_getprocs(kd, what, flag, &nentries);
|
||||||
if ((kp == 0 && nentries != 0) || nentries < 0)
|
if ((kp == 0 && nentries != 0) || nentries < 0)
|
||||||
errx(1, "%s", kvm_geterr(kd));
|
errx(1, "%s", kvm_geterr(kd));
|
||||||
|
nkept = 0;
|
||||||
if (nentries > 0) {
|
if (nentries > 0) {
|
||||||
if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL)
|
if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL)
|
||||||
errx(1, "malloc failed");
|
errx(1, "malloc failed");
|
||||||
for (i = nentries; --i >= 0; ++kp) {
|
for (i = nentries; --i >= 0; ++kp) {
|
||||||
kinfo[i].ki_p = kp;
|
/*
|
||||||
|
* If the user specified multiple selection-criteria,
|
||||||
|
* then keep any process matched by the inclusive OR
|
||||||
|
* of all the selection-criteria given.
|
||||||
|
*/
|
||||||
|
if (pidlist.count > 0) {
|
||||||
|
for (elem = 0; elem < pidlist.count; elem++)
|
||||||
|
if (kp->ki_pid == pidlist.pids[elem])
|
||||||
|
goto keepit;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Note that we had to process pidlist before
|
||||||
|
* filtering out processes which do not have
|
||||||
|
* a controlling terminal.
|
||||||
|
*/
|
||||||
|
if (xkeep == 0) {
|
||||||
|
if ((kp->ki_tdev == NODEV ||
|
||||||
|
(kp->ki_flag & P_CONTROLT) == 0))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nselectors == 0)
|
||||||
|
goto keepit;
|
||||||
|
if (gidlist.count > 0) {
|
||||||
|
for (elem = 0; elem < gidlist.count; elem++)
|
||||||
|
if (kp->ki_rgid == gidlist.gids[elem])
|
||||||
|
goto keepit;
|
||||||
|
}
|
||||||
|
if (pgrplist.count > 0) {
|
||||||
|
for (elem = 0; elem < pgrplist.count; elem++)
|
||||||
|
if (kp->ki_pgid == pgrplist.pids[elem])
|
||||||
|
goto keepit;
|
||||||
|
}
|
||||||
|
if (ruidlist.count > 0) {
|
||||||
|
for (elem = 0; elem < ruidlist.count; elem++)
|
||||||
|
if (kp->ki_ruid == ruidlist.uids[elem])
|
||||||
|
goto keepit;
|
||||||
|
}
|
||||||
|
if (sesslist.count > 0) {
|
||||||
|
for (elem = 0; elem < sesslist.count; elem++)
|
||||||
|
if (kp->ki_sid == sesslist.pids[elem])
|
||||||
|
goto keepit;
|
||||||
|
}
|
||||||
|
if (ttylist.count > 0) {
|
||||||
|
for (elem = 0; elem < ttylist.count; elem++)
|
||||||
|
if (kp->ki_tdev == ttylist.ttys[elem])
|
||||||
|
goto keepit;
|
||||||
|
}
|
||||||
|
if (uidlist.count > 0) {
|
||||||
|
for (elem = 0; elem < uidlist.count; elem++)
|
||||||
|
if (kp->ki_uid == uidlist.uids[elem])
|
||||||
|
goto keepit;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* This process did not match any of the user's
|
||||||
|
* selector-options, so skip the process.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
|
||||||
|
keepit:
|
||||||
|
kinfo[nkept].ki_p = kp;
|
||||||
if (needuser)
|
if (needuser)
|
||||||
saveuser(&kinfo[i]);
|
saveuser(&kinfo[nkept]);
|
||||||
dynsizevars(&kinfo[i]);
|
dynsizevars(&kinfo[nkept]);
|
||||||
|
nkept++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -387,169 +578,321 @@ main(int argc, char *argv[])
|
||||||
* print header
|
* print header
|
||||||
*/
|
*/
|
||||||
printheader();
|
printheader();
|
||||||
if (nentries == 0)
|
if (nkept == 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sort proc list
|
* sort proc list
|
||||||
*/
|
*/
|
||||||
qsort(kinfo, nentries, sizeof(KINFO), pscomp);
|
qsort(kinfo, nkept, sizeof(KINFO), pscomp);
|
||||||
/*
|
/*
|
||||||
* for each proc, call each variable output function.
|
* For each process, call each variable output function.
|
||||||
*/
|
*/
|
||||||
noutput = 0;
|
for (i = lineno = 0; i < nkept; i++) {
|
||||||
for (i = lineno = 0; i < nentries; i++) {
|
|
||||||
if (xflg == 0 && ((&kinfo[i])->ki_p->ki_tdev == NODEV ||
|
|
||||||
((&kinfo[i])->ki_p->ki_flag & P_CONTROLT ) == 0))
|
|
||||||
continue;
|
|
||||||
if (npids > 1) {
|
|
||||||
for (pid = 0; pid < npids; pid++)
|
|
||||||
if ((&kinfo[i])->ki_p->ki_pid == pids[pid])
|
|
||||||
break;
|
|
||||||
if (pid == npids)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (nuids > 1) {
|
|
||||||
for (uid = 0; uid < nuids; uid++)
|
|
||||||
if ((&kinfo[i])->ki_p->ki_uid == uids[uid])
|
|
||||||
break;
|
|
||||||
if (uid == nuids)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (vent = vhead; vent; vent = vent->next) {
|
for (vent = vhead; vent; vent = vent->next) {
|
||||||
(vent->var->oproc)(&kinfo[i], vent);
|
(vent->var->oproc)(&kinfo[i], vent);
|
||||||
if (vent->next != NULL)
|
if (vent->next != NULL)
|
||||||
(void)putchar(' ');
|
(void)putchar(' ');
|
||||||
}
|
}
|
||||||
(void)putchar('\n');
|
(void)putchar('\n');
|
||||||
noutput++;
|
|
||||||
if (prtheader && lineno++ == prtheader - 4) {
|
if (prtheader && lineno++ == prtheader - 4) {
|
||||||
(void)putchar('\n');
|
(void)putchar('\n');
|
||||||
printheader();
|
printheader();
|
||||||
lineno = 0;
|
lineno = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pids != NULL)
|
free_list(&gidlist);
|
||||||
free(pids);
|
free_list(&pidlist);
|
||||||
if (uids != NULL)
|
free_list(&pgrplist);
|
||||||
free(uids);
|
free_list(&ruidlist);
|
||||||
|
free_list(&sesslist);
|
||||||
/* Check if '-p proclist' or '-u userlist' matched zero processes */
|
free_list(&ttylist);
|
||||||
if (noutput == 0)
|
free_list(&uidlist);
|
||||||
eval = 1;
|
|
||||||
|
|
||||||
exit(eval);
|
exit(eval);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BSD_PID_MAX 99999 /* Copy of PID_MAX from sys/proc.h */
|
static int
|
||||||
pid_t *
|
addelem_gid(struct listinfo *inf, const char *elem)
|
||||||
getpids(const char *arg, int *npids)
|
|
||||||
{
|
{
|
||||||
char copyarg[32];
|
struct group *grp;
|
||||||
char *copyp, *endp;
|
intmax_t ltemp;
|
||||||
pid_t *pids, *morepids;
|
const char *nameorID;
|
||||||
int alloc;
|
char *endp;
|
||||||
long tempid;
|
|
||||||
|
|
||||||
alloc = 0;
|
if (*elem == '\0' || strlen(elem) >= MAXLOGNAME) {
|
||||||
*npids = 0;
|
if (*elem == '\0')
|
||||||
pids = NULL;
|
warnx("Invalid (zero-length) %s name", inf->lname);
|
||||||
while (*arg != '\0') {
|
else
|
||||||
while (*arg != '\0' && strchr(SEP, *arg) != NULL)
|
warnx("%s name too long: %s", inf->lname, elem);
|
||||||
arg++;
|
optfatal = 1;
|
||||||
if (*arg == '\0' || strchr(SEP, *arg) != NULL)
|
return (0); /* Do not add this value */
|
||||||
tempid = 0;
|
|
||||||
else {
|
|
||||||
copyp = copyarg;
|
|
||||||
endp = copyarg + sizeof(copyarg) - 1;
|
|
||||||
while (*arg != '\0' && strchr(SEP, *arg) == NULL &&
|
|
||||||
copyp <= endp)
|
|
||||||
*copyp++ = *arg++;
|
|
||||||
if (copyp > endp) {
|
|
||||||
*endp = '\0';
|
|
||||||
tempid = -1;
|
|
||||||
while (*arg != '\0' &&
|
|
||||||
strchr(SEP, *arg) == NULL)
|
|
||||||
arg++;
|
|
||||||
} else {
|
|
||||||
*copyp = '\0';
|
|
||||||
errno = 0;
|
|
||||||
tempid = strtol(copyarg, &endp, 10);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Write warning messages for any values which
|
|
||||||
* would never be a valid process number.
|
|
||||||
*/
|
|
||||||
if (*endp != '\0' || tempid < 0 || copyarg == endp) {
|
|
||||||
warnx("invalid process number: %s", copyarg);
|
|
||||||
errno = ERANGE;
|
|
||||||
} else if (errno != 0 || tempid > BSD_PID_MAX) {
|
|
||||||
warnx("process number too large: %s", copyarg);
|
|
||||||
errno = ERANGE;
|
|
||||||
}
|
|
||||||
if (errno == ERANGE) {
|
|
||||||
/* Ignore this value from the given list. */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*npids >= alloc) {
|
|
||||||
alloc = (alloc + 1) << 1;
|
|
||||||
morepids = realloc(pids, alloc * sizeof (*pids));
|
|
||||||
if (morepids == NULL) {
|
|
||||||
free(pids);
|
|
||||||
errx(1, "realloc failed");
|
|
||||||
}
|
|
||||||
pids = morepids;
|
|
||||||
}
|
|
||||||
pids[(*npids)++] = tempid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!*npids)
|
/*
|
||||||
errx(1, "No valid process numbers specified");
|
* SUSv3 states that `ps -G grouplist' should match "real-group
|
||||||
|
* ID numbers", and does not mention group-names. I do want to
|
||||||
|
* also support group-names, so this tries for a group-id first,
|
||||||
|
* and only tries for a name if that doesn't work. This is the
|
||||||
|
* opposite order of what is done in addelem_uid(), but in
|
||||||
|
* practice the order would only matter for group-names which
|
||||||
|
* are all-numeric.
|
||||||
|
*/
|
||||||
|
grp = NULL;
|
||||||
|
nameorID = "named";
|
||||||
|
errno = 0;
|
||||||
|
ltemp = strtol(elem, &endp, 10);
|
||||||
|
if (errno == 0 && *endp == '\0' && ltemp >= 0 && ltemp <= GID_MAX) {
|
||||||
|
nameorID = "name or ID matches";
|
||||||
|
grp = getgrgid((gid_t)ltemp);
|
||||||
|
}
|
||||||
|
if (grp == NULL)
|
||||||
|
grp = getgrnam(elem);
|
||||||
|
if (grp == NULL) {
|
||||||
|
warnx("No %s %s '%s'", inf->lname, nameorID, elem);
|
||||||
|
optfatal = 1;
|
||||||
|
return (0); /* Do not add this value */
|
||||||
|
}
|
||||||
|
|
||||||
return (pids);
|
if (inf->count >= inf->maxcount)
|
||||||
|
expand_list(inf);
|
||||||
|
inf->gids[(inf->count)++] = grp->gr_gid;
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
uid_t *
|
#define BSD_PID_MAX 99999 /* Copy of PID_MAX from sys/proc.h */
|
||||||
getuids(const char *arg, int *nuids)
|
static int
|
||||||
|
addelem_pid(struct listinfo *inf, const char *elem)
|
||||||
{
|
{
|
||||||
char name[MAXLOGNAME];
|
long tempid;
|
||||||
struct passwd *pwd;
|
char *endp;
|
||||||
uid_t *uids, *moreuids;
|
|
||||||
int alloc;
|
|
||||||
size_t l;
|
|
||||||
|
|
||||||
|
if (*elem == '\0')
|
||||||
alloc = 0;
|
tempid = 0L;
|
||||||
*nuids = 0;
|
else {
|
||||||
uids = NULL;
|
errno = 0;
|
||||||
for (; (l = strcspn(arg, SEP)) > 0; arg += l + strspn(arg + l, SEP)) {
|
tempid = strtol(elem, &endp, 10);
|
||||||
if (l >= sizeof name) {
|
if (*endp != '\0' || tempid < 0 || elem == endp) {
|
||||||
warnx("%.*s: name too long", (int)l, arg);
|
warnx("Invalid %s: %s", inf->lname, elem);
|
||||||
continue;
|
errno = ERANGE;
|
||||||
|
} else if (errno != 0 || tempid > BSD_PID_MAX) {
|
||||||
|
warnx("%s too large: %s", inf->lname, elem);
|
||||||
|
errno = ERANGE;
|
||||||
}
|
}
|
||||||
strncpy(name, arg, l);
|
if (errno == ERANGE) {
|
||||||
name[l] = '\0';
|
optfatal = 1;
|
||||||
if ((pwd = getpwnam(name)) == NULL) {
|
return (0); /* Do not add this value */
|
||||||
warnx("%s: no such user", name);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (*nuids >= alloc) {
|
|
||||||
alloc = (alloc + 1) << 1;
|
|
||||||
moreuids = realloc(uids, alloc * sizeof (*uids));
|
|
||||||
if (moreuids == NULL) {
|
|
||||||
free(uids);
|
|
||||||
errx(1, "realloc failed");
|
|
||||||
}
|
|
||||||
uids = moreuids;
|
|
||||||
}
|
|
||||||
uids[(*nuids)++] = pwd->pw_uid;
|
|
||||||
}
|
}
|
||||||
endpwent();
|
|
||||||
|
|
||||||
if (!*nuids)
|
if (inf->count >= inf->maxcount)
|
||||||
errx(1, "No users specified");
|
expand_list(inf);
|
||||||
|
inf->pids[(inf->count)++] = tempid;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
#undef BSD_PID_MAX
|
||||||
|
|
||||||
return uids;
|
static int
|
||||||
|
addelem_tty(struct listinfo *inf, const char *elem)
|
||||||
|
{
|
||||||
|
char pathbuf[PATH_MAX];
|
||||||
|
struct stat sb;
|
||||||
|
const char *ttypath;
|
||||||
|
|
||||||
|
if (strcmp(elem, "co") == 0)
|
||||||
|
ttypath = strdup(_PATH_CONSOLE);
|
||||||
|
else if (*elem == '/')
|
||||||
|
ttypath = elem;
|
||||||
|
else {
|
||||||
|
strlcpy(pathbuf, _PATH_TTY, sizeof(pathbuf));
|
||||||
|
strlcat(pathbuf, elem, sizeof(pathbuf));
|
||||||
|
ttypath = pathbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stat(ttypath, &sb) == -1) {
|
||||||
|
warn("%s", ttypath);
|
||||||
|
optfatal = 1;
|
||||||
|
return (0); /* Do not add this value */
|
||||||
|
}
|
||||||
|
if (!S_ISCHR(sb.st_mode)) {
|
||||||
|
warn("%s: Not a terminal", ttypath);
|
||||||
|
optfatal = 1;
|
||||||
|
return (0); /* Do not add this value */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inf->count >= inf->maxcount)
|
||||||
|
expand_list(inf);
|
||||||
|
inf->ttys[(inf->count)++] = sb.st_rdev;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
addelem_uid(struct listinfo *inf, const char *elem)
|
||||||
|
{
|
||||||
|
struct passwd *pwd;
|
||||||
|
intmax_t ltemp;
|
||||||
|
char *endp;
|
||||||
|
|
||||||
|
if (*elem == '\0' || strlen(elem) >= MAXLOGNAME) {
|
||||||
|
if (*elem == '\0')
|
||||||
|
warnx("Invalid (zero-length) %s name", inf->lname);
|
||||||
|
else
|
||||||
|
warnx("%s name too long: %s", inf->lname, elem);
|
||||||
|
optfatal = 1;
|
||||||
|
return (0); /* Do not add this value */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX - In the following, should the warnings be fatal errors?
|
||||||
|
* Historically they have been warnings, but I expect errors
|
||||||
|
* would be more appropriate. A warning message might be
|
||||||
|
* missed in a long `ps' listing, and the user would not
|
||||||
|
* realize that they had mistyped a userid. Also, Solaris
|
||||||
|
* and Linux treat these as errors. On the other hand, I
|
||||||
|
* can imagine that some users *might* be used to the
|
||||||
|
* present behavior.
|
||||||
|
*/
|
||||||
|
pwd = getpwnam(elem);
|
||||||
|
if (pwd == NULL) {
|
||||||
|
errno = 0;
|
||||||
|
ltemp = strtol(elem, &endp, 10);
|
||||||
|
if (errno != 0 || *endp != '\0' || ltemp < 0 ||
|
||||||
|
ltemp > UID_MAX)
|
||||||
|
warnx("No %s named '%s'", inf->lname, elem);
|
||||||
|
else {
|
||||||
|
/* The string is all digits, so it might be a userID. */
|
||||||
|
pwd = getpwuid((uid_t)ltemp);
|
||||||
|
if (pwd == NULL)
|
||||||
|
warnx("No %s name or ID matches '%s'",
|
||||||
|
inf->lname, elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pwd == NULL) {
|
||||||
|
/* XXX: optfatal = 1; -- (see the above XXX) */
|
||||||
|
return (0); /* Do not add this value */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inf->count >= inf->maxcount)
|
||||||
|
expand_list(inf);
|
||||||
|
inf->uids[(inf->count)++] = pwd->pw_uid;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_list(struct listinfo *inf, const char *argp)
|
||||||
|
{
|
||||||
|
char elemcopy[PATH_MAX];
|
||||||
|
const char *savep;
|
||||||
|
char *cp, *endp;
|
||||||
|
int toolong;
|
||||||
|
|
||||||
|
while (*argp != '\0') {
|
||||||
|
while (*argp != '\0' && strchr(W_SEP, *argp) != NULL)
|
||||||
|
argp++;
|
||||||
|
savep = argp;
|
||||||
|
toolong = 0;
|
||||||
|
cp = elemcopy;
|
||||||
|
if (strchr(T_SEP, *argp) == NULL) {
|
||||||
|
endp = elemcopy + sizeof(elemcopy) - 1;
|
||||||
|
while (*argp != '\0' && cp <= endp &&
|
||||||
|
strchr(W_SEP T_SEP, *argp) == NULL)
|
||||||
|
*cp++ = *argp++;
|
||||||
|
if (cp > endp)
|
||||||
|
toolong = 1;
|
||||||
|
}
|
||||||
|
if (!toolong) {
|
||||||
|
*cp = '\0';
|
||||||
|
#ifndef ADD_PS_LISTRESET
|
||||||
|
/* This is how the standard expects lists to be handled. */
|
||||||
|
inf->addelem(inf, elemcopy);
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* This would add a simple non-standard-but-convienent feature.
|
||||||
|
*
|
||||||
|
* XXX - Adding this check increased the total size of `ps' by
|
||||||
|
* 3940 bytes on i386! That's 12% of the entire program!
|
||||||
|
* The `ps.o' file grew by only about 40 bytes, but the
|
||||||
|
* final (stripped) executable in /bin/ps grew by 12%.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* We now have a single element. Add it to the
|
||||||
|
* list, unless the element is ":". In that case,
|
||||||
|
* reset the list so previous entries are ignored.
|
||||||
|
*/
|
||||||
|
if (strcmp(elemcopy, ":") == 0)
|
||||||
|
inf->count = 0;
|
||||||
|
else
|
||||||
|
inf->addelem(inf, elemcopy);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* The string is too long to copy. Find the end
|
||||||
|
* of the string to print out the warning message.
|
||||||
|
*/
|
||||||
|
while (*argp != '\0' && strchr(W_SEP T_SEP,
|
||||||
|
*argp) == NULL)
|
||||||
|
argp++;
|
||||||
|
warnx("Value too long: %.*s", (int)(argp - savep),
|
||||||
|
savep);
|
||||||
|
optfatal = 1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Skip over any number of trailing whitespace characters,
|
||||||
|
* but only one (at most) trailing element-terminating
|
||||||
|
* character.
|
||||||
|
*/
|
||||||
|
while (*argp != '\0' && strchr(W_SEP, *argp) != NULL)
|
||||||
|
argp++;
|
||||||
|
if (*argp != '\0' && strchr(T_SEP, *argp) != NULL) {
|
||||||
|
argp++;
|
||||||
|
/* Catch case where string ended with a comma. */
|
||||||
|
if (*argp == '\0')
|
||||||
|
inf->addelem(inf, argp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
expand_list(struct listinfo *inf)
|
||||||
|
{
|
||||||
|
int newmax;
|
||||||
|
void *newlist;
|
||||||
|
|
||||||
|
newmax = (inf->maxcount + 1) << 1;
|
||||||
|
newlist = realloc(inf->ptr, newmax * inf->elemsize);
|
||||||
|
if (newlist == NULL) {
|
||||||
|
free(inf->ptr);
|
||||||
|
errx(1, "realloc to %d %ss failed", newmax,
|
||||||
|
inf->lname);
|
||||||
|
}
|
||||||
|
inf->maxcount = newmax;
|
||||||
|
inf->ptr = newlist;
|
||||||
|
|
||||||
|
return (newlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_list(struct listinfo *inf)
|
||||||
|
{
|
||||||
|
|
||||||
|
inf->count = inf->elemsize = inf->maxcount = 0;
|
||||||
|
if (inf->ptr != NULL)
|
||||||
|
free(inf->ptr);
|
||||||
|
inf->addelem = NULL;
|
||||||
|
inf->lname = NULL;
|
||||||
|
inf->ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_list(struct listinfo *inf, addelem_rtn artn, int elemsize,
|
||||||
|
const char *lname)
|
||||||
|
{
|
||||||
|
|
||||||
|
inf->count = inf->maxcount = 0;
|
||||||
|
inf->elemsize = elemsize;
|
||||||
|
inf->addelem = artn;
|
||||||
|
inf->lname = lname;
|
||||||
|
inf->ptr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VARENT *
|
VARENT *
|
||||||
|
|
@ -758,9 +1101,10 @@ static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
(void)fprintf(stderr, "%s\n%s\n%s\n",
|
(void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
|
||||||
"usage: ps [-aCHhjlmrSTuvwxZ] [-O|o fmt] [-p pid[,pid]] [-t tty]",
|
"usage: ps [-aCHhjlmrSTuvwXxZ] [-G gid[,gid]] [-O|o fmt]",
|
||||||
" [-U user[,user]] [-M core] [-N system]",
|
" [-p pid[,pid]] [-t tty[,tty]] [-U user[,user]]",
|
||||||
|
" [-M core] [-N system]",
|
||||||
" ps [-L]");
|
" ps [-L]");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue