* Copyright (c) 1990 The Regents of the University of California.
* %sccs.include.redist.c%
"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)ps.c 5.37 (Berkeley) %G%";
#include <sys/resource.h>
int eval
; /* exit value */
int termwidth
; /* width of screen (0 == infinity) */
int totwidth
; /* calculated width of requested variables */
static int needuser
, needcomm
;
enum sort
{ DEFAULT
, SORTMEM
, SORTCPU
} sortby
= DEFAULT
;
char dfmt
[] = "pid tt state time command";
char jfmt
[] = "user pid ppid pgid sess jobc state tt time command";
char lfmt
[] = "uid pid ppid cpu pri nice vsz rss wchan state tt time command";
char o2
[] = "tt state time command";
char ufmt
[] = "user pid %cpu %mem vsz rss tt state start time command";
"pid state time sl re pagein vsz rss lim tsiz trs %cpu %mem command";
register size_t nentries
;
int all
, ch
, flag
, fmt
, lineno
, pid
, prtheader
, uid
, what
, xflg
;
char *kludge_oldps_options();
if ((ioctl(STDOUT_FILENO
, TIOCGWINSZ
, (char *)&ws
) == -1 &&
ioctl(STDERR_FILENO
, TIOCGWINSZ
, (char *)&ws
) == -1 &&
ioctl(STDIN_FILENO
, TIOCGWINSZ
, (char *)&ws
) == -1) ||
termwidth
= ws
.ws_col
- 1;
argv
[1] = kludge_oldps_options(argv
[1]);
while ((ch
= getopt(argc
, argv
, "aCghjLlmO:o:p:rSTt:uvwx")) != EOF
)
prtheader
= ws
.ws_row
> 5 ? ws
.ws_row
: 22;
if ((optarg
= ttyname(STDIN_FILENO
)) == NULL
)
error("stdin: not a terminal");
char pathbuf
[MAXPATHLEN
];
if (strcmp(optarg
, "co") == 0)
(void) sprintf(ttypath
= pathbuf
, "%s%s",
if (stat(ttypath
, &stbuf
) == -1) {
"ps: %s: %s\n", ttypath
, strerror(errno
));
if (!S_ISCHR(stbuf
.st_mode
))
error("%s: not a terminal", ttypath
);
char *nlistf
, *memf
= NULL
, *swapf
= NULL
;
if (kvm_openfiles(nlistf
, memf
, swapf
) == -1)
error("kvm_openfiles: %s", kvm_geterr());
if (!all
&& ttydev
== NODEV
&& pid
== -1) /* XXX - should be cleaner */
* scan requested variables, noting what structures are needed,
* and adjusting header widths as appropiate.
} else if (ttydev
!= NODEV
) {
if ((nentries
= kvm_getprocs(what
, flag
)) == -1) {
(void) fprintf(stderr
, "ps: %s\n", kvm_geterr());
kinfo
= (KINFO
*)malloc(nentries
* sizeof(KINFO
));
(void)fprintf(stderr
, "ps: %s\n", strerror(ENOMEM
));
for (nentries
= 0; p
= kvm_nextproc(); ++nentries
) {
kinfo
[nentries
].ki_p
= p
;
kinfo
[nentries
].ki_e
= kvm_geteproc(p
);
saveuser(&kinfo
[nentries
]);
qsort((void *)kinfo
, nentries
, sizeof(KINFO
), pscomp
);
* for each proc, call each variable output function.
for (i
= lineno
= 0; i
< nentries
; i
++) {
if (xflg
== 0 && (kinfo
[i
].ki_e
->e_tdev
== NODEV
||
(kinfo
[i
].ki_p
->p_flag
& SCTTY
) == 0))
for (v
= vhead
; v
; v
= v
->next
) {
(*v
->oproc
)(&kinfo
[i
], v
);
if (prtheader
&& lineno
++ == prtheader
-4) {
for (v
= vhead
; v
; v
= v
->next
) {
totwidth
+= v
->width
+ 1; /* +1 for space */
register struct usave
*usp
;
register struct user
*up
;
if ((usp
= (struct usave
*)calloc(1, sizeof(struct usave
))) == NULL
) {
(void)fprintf(stderr
, "ps: %s\n", strerror(errno
));
* save arguments if needed
ki
->ki_args
= needcomm
? strdup(kvm_getargs(ki
->ki_p
, up
)) : NULL
;
usp
->u_start
= up
->u_stats
.p_start
;
usp
->u_ru
= up
->u_stats
.p_ru
;
usp
->u_cru
= up
->u_stats
.p_cru
;
usp
->u_procp
= up
->u_procp
;
usp
->u_start
= up
->u_start
;
usp
->u_acflag
= up
->u_acflag
;
#define VSIZE(k) ((k)->ki_e->e_vm.vm_dsize + (k)->ki_e->e_vm.vm_ssize + \
(k)->ki_e->e_vm.vm_tsize)
#define VSIZE(k) ((k)->ki_p->p_dsize + (k)->ki_p->p_ssize + (k)->ki_e->e_xsize)
return (getpcpu(k2
) - getpcpu(k1
));
return (VSIZE(k2
) - VSIZE(k1
));
i
= k1
->ki_e
->e_tdev
- k2
->ki_e
->e_tdev
;
i
= k1
->ki_p
->p_pid
- k2
->ki_p
->p_pid
;
* ICK (all for getopt), would rather hide the ugliness
* here than taint the main code.
* The old convention that 't' with no trailing tty arg means the users
* tty, is only supported if argv[1] doesn't begin with a '-'. This same
* feature is available with the option 'T', which takes no argument.
if ((newopts
= ns
= malloc(len
+ 2)) == NULL
) {
(void)fprintf(stderr
, "ps: %s\n", strerror(errno
));
*ns
++ = '-'; /* add option flag */
* if last letter is a 't' flag with no argument (in the context
* of the oldps options -- option string NOT starting with a '-' --
* then convert to 'T' (meaning *this* terminal, i.e. ttyname(0)).
if (*cp
== 't' && *s
!= '-')
* otherwise check for trailing number, which *may* be a
while (cp
>= s
&& isdigit(*cp
))
bcopy(s
, ns
, (size_t)(cp
- s
)); /* copy up to trailing number */
* if there's a trailing number, and not a preceding 'p' (pid) or
* 't' (tty) flag, then assume it's a pid and insert a 'p' flag.
if (isdigit(*cp
) && (cp
== s
|| cp
[-1] != 't' && cp
[-1] != 'p' &&
(cp
- 1 == s
|| cp
[-2] != 't')))
(void) strcpy(ns
, cp
); /* and append the number */
error(fmt
) char *fmt
; { (void) fputs(fmt
, stderr
); exit(1); /* NOTREACHED */ }
(void) fprintf(stderr
, "ps: ");
(void) vfprintf(stderr
, fmt
, ap
);
(void) fprintf(stderr
, "\n");
"usage:\tps [ -aChjlmrSsTuvwx ] [ -O|o fmt ] [ -p pid ] [ -t tty ] [ system ] [ core ] [ swap ]\n\t ps [ -L ]\n");