2.9BSD/usr/src/cmd/ps/ps.c
char *sccsid = "%W%";
/*
* ps - process status
* This is the augmented UCB ps for 2.9BSD PDP-11 Unix (11/82).
* It is not very portable, using the phys sys call and
* knowing the format of an a.out symbol table.
* Examine and print certain things about processes
* Usage: ps [ acgklnrtuwxU# ] [ corefile [ swapfile [ system ] ] ]
*/
#include "whoami.h"
#include <sys/param.h>
#include <stdio.h>
#include <pwd.h>
#include <a.out.h>
#include <core.h>
#include <ctype.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/tty.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <psout.h>
#define equal !strcmp
#define exists(x) (stat ((x), &stbuf) == 0)
#define within(x,y,z) (((unsigned)(x) >= (y)) && ((unsigned)(x) < (z)))
#define round(x,y) ((long) ((((long) (x) + (long) (y) - 1L) / (long) (y)) * (long) (y)))
struct nlist nl[] = {
{ "_proc" , 0, 0},
#define X_PROC 0
{ "_swplo" , 0, 0},
#define X_SWPLO 1
{ "_nproc", 0, 0},
#define X_NPROC 2
{ "_hz", 0, 0},
#define X_HZ 3
0
};
#define NNAMESIZ (sizeof nl[0].n_name)
struct proc *mproc, proc [8];
struct user u;
struct stat stbuf;
int hz;
int chkpid = 0;
int aflg; /* -a: all processes, not just mine */
int cflg; /* -c: not complete listing of args, just comm. */
int gflg; /* -g: complete listing including group headers, etc */
int kflg; /* -k: read from core file instead of real memory */
int lflg; /* -l: long listing form */
int nflg; /* -n: numeric wchans */
int rflg; /* -r: raw output in style <psout.h> */
int uflg; /* -u: user name */
int wflg; /* -w[w]: wide terminal */
int xflg; /* -x: ALL processes, even those without ttys */
int Uflg; /* -U: update the private list */
char *tptr, *mytty;
char *nlistf, *uname;
int file;
off_t swplo;
int nproc;
off_t tell;
int nchans;
int ndev;
int nsyms;
int ismem;
#ifndef PSFILE
char *psdb = "/etc/psdatabase";
#else
char *psdb = PSFILE;
#endif
/*
* Structure for the unix wchan table
*/
struct wchan {
char cname [NNAMESIZ];
unsigned caddr;
};
struct wchan *wchanhd;
char *calloc (), *malloc (), *realloc ();
char *gettty (), *getptr (), *getchan ();
char *ttyname ();
int pscomp ();
int wchancomp ();
off_t lseek ();
#ifndef NUMDEV
#define NUMDEV 256
#endif
struct devl {
char dname[DIRSIZ];
dev_t dev;
} devl[NUMDEV];
struct map {
off_t b1, e1; off_t f1;
off_t b2, e2; off_t f2;
};
struct map datmap;
struct psout *outargs; /* info for first npr processes */
int npr; /* number of processes found so far */
int twidth; /* terminal width */
int cmdstart; /* starting position for command field */
char *memf; /* name of kernel memory file to use */
char *kmemf; /* name of physical memory file to use */
char *swapf; /* name of swap file to use */
char *nlistf; /* name of symbol table file to use */
int kmem, mem, swap;
extern char _sobuf[];
#ifdef TERMCAP
char *getenv ();
#endif
main (argc, argv)
char **argv;
{
int uid, euid, puid, nread;
register i, j;
char *ap;
register struct proc *procp;
#ifdef TERMCAP
char *termp, capbuf [1024];
#endif
#ifdef TERMCAP
if ((termp = getenv ("TERM")) != (char *) NULL)
if (tgetent (capbuf, termp) == 1)
twidth = tgetnum ("co");
else ;
else
#endif
twidth = 80;
setbuf (stdout, _sobuf);
argc--, argv++;
if (argc > 0) {
ap = argv [0];
while (*ap) switch (*ap++) {
case '-':
break;
case 'a':
aflg++;
break;
case 'c':
cflg++;
break;
case 'g':
gflg++;
break;
case 'k':
kflg++;
break;
case 'l':
lflg = 1;
break;
case 'n':
nflg++;
lflg = 1;
break;
case 'r':
rflg++;
break;
case 't':
if (*ap)
tptr = ap;
aflg++;
gflg++;
if (*tptr == '?')
xflg++;
while (*ap)
ap++;
break;
case 'u':
uflg = 1;
break;
case 'U':
Uflg++;
break;
case 'w':
if (twidth == 80)
twidth = 132;
else twidth = BUFSIZ;
wflg++;
break;
case 'x':
xflg++;
break;
default:
if (!isdigit (ap[-1]))
break;
chkpid = atoi (--ap);
*ap = '\0';
aflg++;
xflg++;
break;
}
}
openfiles (argc, argv);
getkvars (argc, argv);
if (kflg)
swplo = (off_t) 0;
uid = getuid ();
euid = geteuid ();
mytty = ttyname (0);
printhdr ();
for (i = 0; i < nproc; i += 8) {
j = nproc - i;
if (j > 8)
j = 8;
j *= sizeof (struct proc);
if ((nread = read (kmem, (char *) proc, j)) != j) {
cantread ("proc table", kmemf);
if (nread == -1)
break;
}
for (j = nread / sizeof (struct proc) - 1; j >= 0; j--) {
mproc = &proc[j];
procp = mproc;
/* skip processes that don't exist */
if (procp->p_stat == 0)
continue;
/* skip those without a tty unless -x */
if (procp->p_pgrp == 0 && xflg == 0)
continue;
/* skip group leaders on a tty unless -g, -x, or -t.. */
#ifdef MENLO_JCL
if (!tptr && !gflg && !xflg && procp->p_ppid == 1 && (procp->p_flag & SDETACH) == 0)
#else
if (!tptr && !gflg && !xflg && procp->p_pid == procp->p_pgrp)
#endif
continue;
/* -g also skips those where **argv is "-" - see savcom */
puid = procp->p_uid;
/* skip other peoples processes unless -a or a specific pid */
if ((uid != puid && euid != puid && aflg == 0) ||
(chkpid != 0 && chkpid != procp->p_pid))
continue;
if (savcom (puid))
npr++;
}
}
fixup (npr);
for (i = 0; i < npr; i++) {
#ifdef TERMCAP
register cmdwidth = twidth - cmdstart - 2;
#endif
register struct psout *a = &outargs[i];
if (rflg) {
if (write (1, (char *) a, sizeof (struct psout)) != sizeof (struct psout))
perror ("write");
continue;
}
else if (lflg)
lpr (a);
else if (uflg)
upr (a);
else spr (a);
#ifdef TERMCAP
if (cmdwidth < 0)
cmdwidth = 80 - cmdstart - 2;
#endif
if (a->o_stat == SZOMB)
#ifdef TERMCAP
printf ("%.*s", cmdwidth, " <defunct>");
#else
printf (" <defunct>");
#endif
else if (a->o_pid == 0)
#ifdef TERMCAP
printf ("%.*s", cmdwidth, " swapper");
#else
printf (" swapper");
#endif
else printf (" %.*s", twidth - cmdstart - 2, cflg ? a->o_comm : a->o_args);
putchar ('\n');
}
exit (!npr);
}
/*
* Getdev() changes directories so it should be
* called only after other necessary files have
* been opened.
*/
getdev ()
{
register FILE *df;
struct direct dbuf;
register struct direct *dirp = &dbuf;
if ((chdir ("/dev") < 0) || ((df = fopen (".", "r")) == NULL))
perrexit ("/dev");
while (fread ((char *) &dbuf, sizeof (dbuf), 1, df) == 1) {
if (dirp->d_ino == 0)
continue;
if (!exists (dirp->d_name))
continue;
if ((stbuf.st_mode&S_IFMT) != S_IFCHR)
continue;
strncpy (devl[ndev].dname, dirp->d_name, sizeof devl[ndev].dname);
devl[ndev].dev = stbuf.st_rdev;
ndev++;
}
fclose (df);
}
savcom (puid)
{
char *tp;
off_t addr;
#ifdef VIRUS_VFORK
off_t daddr, saddr;
#endif
register struct psout *a;
register struct proc *procp = mproc;
register struct user *up = &u;
long txtsiz, datsiz, stksiz;
int septxt;
if (procp->p_flag & SLOAD) {
addr = ctob ((off_t) procp->p_addr);
#ifdef VIRUS_VFORK
daddr = ctob ((off_t) procp->p_daddr);
saddr = ctob ((off_t) procp->p_saddr);
#endif
file = mem;
} else {
addr = (procp->p_addr + swplo) << 9;
#ifdef VIRUS_VFORK
daddr = (procp->p_daddr + swplo) << 9;
saddr = (procp->p_saddr + swplo) << 9;
#endif
file = swap;
}
if (pread (file, (char *) up, sizeof (u), addr) != sizeof (u))
return (0);
/* set up address maps for user pcs */
txtsiz = ctob (up->u_tsize);
datsiz = ctob (up->u_dsize);
stksiz = ctob (up->u_ssize);
septxt = up->u_sep;
datmap.b1 = (septxt ? 0 : round (txtsiz, TXTRNDSIZ));
datmap.e1 = datmap.b1 + datsiz;
#ifdef VIRUS_VFORK
datmap.f1 = daddr;
#else
datmap.f1 = ctob (USIZE) + addr;
#endif
datmap.b2 = stackbas (stksiz);
datmap.e2 = stacktop (stksiz);
#ifdef VIRUS_VFORK
datmap.f2 = saddr;
#else
datmap.f2 = ctob (USIZE) + (datmap.e1 - datmap.b1) + addr;
#endif
tp = gettty ();
if ((tptr && strcmp (tptr, tp)) || (strcmp (mytty, tp) && !aflg))
return (0);
a = &outargs[npr];
/* saving com starts here */
a->o_uid = puid;
a->o_pid = procp->p_pid;
a->o_flag = procp->p_flag;
a->o_ppid = procp->p_ppid;
a->o_cpu = procp->p_cpu;
a->o_pri = procp->p_pri;
a->o_nice = procp->p_nice;
a->o_addr0 = procp->p_addr;
#ifdef VIRUS_VFORK
a->o_size = ctod(procp->p_dsize + procp->p_ssize + USIZE);
#else
a->o_size = (procp->p_size + 7) >> 3;
#endif
a->o_wchan = procp->p_wchan;
a->o_pgrp = procp->p_pgrp;
strncpy (a->o_tty, tp, 8);
a->o_ttyd = tp[0] == '?' ? -1 : up->u_ttyd;
a->o_stat = procp->p_stat;
a->o_flag = procp->p_flag;
if (a->o_stat == SZOMB)
return (1);
a->o_utime = up->u_utime;
a->o_stime = up->u_stime;
a->o_cutime = up->u_cutime;
a->o_cstime = up->u_cstime;
a->o_sigs = (int)up->u_signal[SIGINT] + (int)up->u_signal[SIGQUIT];
a->o_uname[0] = 0;
strncpy (a->o_comm, up->u_comm, 14);
if (cflg)
return (1);
#ifdef VIRUS_VFORK
else return (getcmd (a, saddr));
#else
else return (getcmd (a, addr));
#endif
}
char *
gettty ()
{
register i;
register char *p;
if (u.u_ttyp == 0)
return ("?");
for (i = 0; i < ndev; i++) {
if (devl[i].dev == u.u_ttyd) {
p = devl[i].dname;
if (p[0] == 't' && p[1] == 't' && p[2] == 'y')
p += 3;
return (p);
}
}
return ("?");
}
char *
ttyname (fd)
{
register i;
register char *p;
struct stat statb;
if (fstat (fd, &statb))
return ("?");
for (i = 0; i < ndev; i++) {
if (devl[i].dev == statb.st_rdev) {
p = devl[i].dname;
if (p[0] == 't' && p[1] == 't' && p[2] == 'y')
p += 3;
return (p);
}
}
return ("?");
}
/*
* fixup figures out everybodys name and sorts into a nice order.
*/
fixup (np)
register np;
{
register i;
register struct passwd *pw;
struct passwd *getpwent ();
if (uflg) {
/*
* If we want names, traverse the password file. For each
* passwd entry, look for it in the processes.
* In case of multiple entries in /etc/passwd, we believe
* the first one (same thing ls does).
*/
while ((pw = getpwent ()) != (struct passwd *) NULL) {
for (i = 0; i < np; i++)
if (outargs[i].o_uid == pw->pw_uid) {
if (outargs[i].o_uname[0] == 0)
strcpy (outargs[i].o_uname, pw->pw_name);
}
}
}
qsort (outargs, np, sizeof (outargs[0]), pscomp);
}
pscomp (x1, x2)
register struct psout *x1, *x2;
{
register c;
c = (x1)->o_ttyd - (x2)->o_ttyd;
if (c == 0)
c = (x1)->o_pid - (x2)->o_pid;
return (c);
}
wchancomp (x1, x2)
register struct wchan *x1, *x2;
{
if (x1->caddr > x2->caddr)
return (1);
else if (x1->caddr == x2->caddr)
return (0);
else return (-1);
}
char *
getptr (adr)
char **adr;
{
char *ptr;
register char *p, *pa;
register i;
ptr = 0;
pa = (char *)adr;
p = (char *)&ptr;
for (i = 0; i < sizeof (ptr); i++)
*p++ = getbyte (pa++);
return (ptr);
}
getbyte (adr)
register char *adr;
{
register struct map *amap = &datmap;
char b;
off_t saddr;
if (!within (adr, amap->b1, amap->e1))
if (within (adr, amap->b2, amap->e2))
saddr = (unsigned) adr + amap->f2 - amap->b2;
else return (0);
else saddr = (unsigned) adr + amap->f1 - amap->b1;
if (lseek (file, saddr, 0) == (off_t) -1 || read (file, &b, 1) < 1)
return (0);
return ((unsigned) b);
}
/*
* pread is like read, but if it's /dev/mem we use the phys
* system call for speed. On systems without phys we have
* to use regular read.
*/
pread (fd, ptr, nbytes, loc)
char *ptr;
off_t loc;
{
register rc;
if (fd == mem && ismem) {
rc = phys (6, nbytes / 64 + 1, (short) (loc / 64));
if (rc >= 0) {
bmove (0140000, ptr, nbytes);
return (nbytes);
}
}
lseek (fd, loc, 0);
return (read (fd, ptr, nbytes));
}
addchan (name, caddr)
char *name;
unsigned caddr;
{
register nc = nchans;
register struct wchan *wp = wchanhd;
if (nc == 0)
wp = (struct wchan *) malloc (sizeof (struct wchan));
else wp = (struct wchan *) realloc (wp, sizeof (struct wchan) * (nc + 1));
if (wp == (struct wchan *) NULL)
err ("Too many symbols");
strncpy (wp[nc].cname, name, NNAMESIZ - 1);
wp[nc].cname[NNAMESIZ-1] = '\0';
wp[nc].caddr = caddr;
wchanhd = wp;
nchans++;
}
char *
getchan (chan)
register unsigned chan;
{
register i;
register char *prevsym;
prevsym = "";
if (chan)
for (i = 0; i < nchans; i++) {
if (wchanhd[i].caddr > chan)
return (prevsym);
prevsym = wchanhd[i].cname;
}
return (prevsym);
}
nlist (aout, tgt)
char *aout;
struct nlist *tgt;
{
register i;
register FILE *aaa;
register struct nlist *nnn;
int iii, nllen;
struct ovlhdr ovlbuf;
static struct nlist nbuf;
static struct exec hbuf;
off_t sa = (off_t) 0;
nllen = sizeof nl / sizeof (struct nlist);
if ((aaa = fopen (aout, "r")) == 0 )
perrexit (aout);
if (fread (&hbuf, sizeof hbuf, 1, aaa) != 1 )
err ("Invalid symbol table");
if (N_BADMAG (hbuf)) {
fprintf (stderr, "%s: not in object file format\n", aout);
exit (1);
}
if (hbuf.a_magic == A_MAGIC5 || hbuf.a_magic == A_MAGIC6) {
fread ((char *) &ovlbuf, 1, sizeof ovlbuf, aaa);
for (i = 0; i < NOVL; i++)
sa += (off_t) (ovlbuf.ov_siz)[i];
fseek (aaa, sa, 1);
}
sa = (off_t) hbuf.a_text + hbuf.a_data;
if ((hbuf.a_flag & 01) == 0)
sa *= (off_t) 2;
fseek (aaa, sa, 1);
nsyms = hbuf.a_syms / sizeof nbuf;
if (nsyms == 0) {
fprintf (stderr, "%s: no symbol table\n", aout);
exit (1);
}
while (--nsyms >= 0 && fread (&nbuf, sizeof (nbuf), 1, aaa) == 1 ) {
if (nbuf.n_name[0] != '_' )
continue;
iii = nbuf.n_type&(N_TYPE|N_EXT);
if ((nbuf.n_type&N_TYPE) != N_ABS && iii != (N_EXT|N_DATA) && iii != (N_EXT|N_BSS) )
continue;
if (!nflg)
addchan (nbuf.n_name+1, (unsigned) (nbuf.n_value));
if (nllen)
for (nnn = tgt; nnn->n_name[0] != '\0'; nnn++ )
if (!strncmp (nnn->n_name, nbuf.n_name, NNAMESIZ)) {
nnn->n_value = nbuf.n_value;
nnn->n_type = nbuf.n_type;
nllen--;
break;
}
}
fclose (aaa);
if (!nflg)
qsort (wchanhd, nchans, sizeof (struct wchan), wchancomp);
return (nllen == 0 ? 0 : -1);
}
err (msg)
char *msg;
{
fprintf (stderr, "%s\n", msg);
exit (1);
}
perrexit (msg)
char *msg;
{
perror (msg);
exit (1);
}
writepsdb (unixname)
char *unixname;
{
int nllen;
register FILE *fp;
setuid (getuid ());
if ((fp = fopen (psdb, "w")) == NULL)
perrexit (psdb);
else chmod (psdb, 0644);
nllen = sizeof nl / sizeof (struct nlist);
fwrite (unixname, strlen (unixname) + 1, 1, fp);
fwrite ((char *) &nllen, sizeof nllen, 1, fp);
fwrite ((char *) &ndev, sizeof ndev, 1, fp);
fwrite ((char *) &nchans, sizeof nchans, 1, fp);
fwrite ((char *) nl, sizeof (struct nlist), nllen, fp);
fwrite ((char *) devl, sizeof (struct devl), ndev, fp);
fwrite ((char *) wchanhd, sizeof (struct wchan), nchans, fp);
fclose (fp);
}
char *
readpsdb ()
{
int nllen;
register i;
register FILE *fp;
static char unamebuf [BUFSIZ];
char *p = unamebuf;
register struct wchan *ccc;
if ((fp = fopen (psdb, "r")) == NULL)
perrexit (psdb);
while ((*p= getc (fp)) != '\0')
p++;
fread (&nllen, sizeof nllen, 1, fp);
fread (&ndev, sizeof ndev, 1, fp);
fread (&nchans, sizeof nchans, 1, fp);
fread (nl, sizeof (struct nlist), nllen, fp);
fread (devl, sizeof (struct devl), ndev, fp);
if (!nflg)
if ((wchanhd = calloc (nchans, sizeof (struct wchan))) == (struct wchan *) NULL)
err ("Too many symbols");
else for (i = 0, ccc = wchanhd; i < nchans; i++) {
fread ((char *) ccc, sizeof (struct wchan), 1, fp);
ccc++;
}
return (unamebuf);
}
openfiles (argc, argv)
char **argv;
{
kmemf = "/dev/kmem";
if (kflg)
kmemf = argc > 1 ? argv[1] : "/usr/sys/core";
kmem = open (kmemf, 0);
if (kmem < 0)
perrexit (kmemf);
if (!kflg) {
memf = "/dev/mem";
ismem++;
}
else memf = kmemf;
mem = open (memf, 0);
if (mem < 0)
perrexit (memf);
swapf = argc > 2 ? argv[2] : "/dev/swap";
swap = open (swapf, 0);
if (swap < 0)
perrexit (swapf);
}
getkvars (argc, argv)
char **argv;
{
nlistf = argc > 3 ? argv[3] : "/unix";
if (Uflg) {
nlist (nlistf, nl);
getdev ();
writepsdb (nlistf);
exit (0);
}
else if (exists (psdb)) {
uname = readpsdb ();
if (!equal (uname, nlistf)) {
/*
* Let addchan() do the work.
*/
nchans = 0;
free ((char *) wchanhd);
nlist (nlistf, nl);
}
}
else nlist (nlistf, nl), getdev ();
/*
* Find base of swap
*/
lseek (kmem, (off_t) nl[X_SWPLO].n_value, 0);
if (read (kmem, (char *) &swplo, sizeof (swplo)) != sizeof (swplo))
cantread ("swplo", kmemf);
/*
* Find number of procs
*/
if (nl[X_NPROC].n_value) {
lseek (kmem, (off_t) nl[X_NPROC].n_value, 0);
if (read(kmem, (char *)&nproc, sizeof(nproc)) != sizeof(nproc)){
perror(kmemf);
exit(1);
}
} else {
fprintf(stderr, "nproc not in namelist\n");
exit(1);
}
outargs = (struct psout *)calloc(nproc, sizeof(struct psout));
if (outargs == (struct psout *)NULL) {
fprintf(stderr, "ps: not enough memory for saving info\n");
exit(1);
}
/*
* Find value of hz
*/
lseek (kmem, (off_t) nl[X_HZ].n_value, 0);
read (kmem, (char *) &hz, sizeof hz);
/*
* Locate proc table
*/
lseek (kmem, (off_t) nl[X_PROC].n_value, 0);
tell = (off_t) nl[X_PROC].n_value;
}
char *uhdr =
"USER PID NICE SZ TTY TIME";
upr (a)
register struct psout *a;
{
printf ("%-8.8s", a->o_uname);
printf ("%6u", a->o_pid);
printf ("%4d ", a->o_nice);
printf ("%4d", a->o_size);
ptty (a->o_tty);
ptime (a);
}
char *shdr =
" PID TTY TIME";
spr (a)
register struct psout *a;
{
printf ("%6u", a->o_pid);
ptty (a->o_tty);
ptime (a);
}
char *lhdr =
" F S UID PID PPID CPU PRI NICE ADDR SZ WCHAN TTY TIME";
lpr (a)
register struct psout *a;
{
printf ("%3o %c", 0377 & a->o_flag, "0SWRIZT"[a->o_stat]);
printf ("%6u", a->o_uid);
printf ("%6u", a->o_pid);
printf ("%6u%4d%4d%4d%7o", a->o_ppid, a->o_cpu&0377, a->o_pri, a->o_nice, a->o_addr0);
printf ("%4d", a->o_size);
if (nflg)
if (a->o_wchan)
printf ("%7o", a->o_wchan);
else printf (" ");
else printf (" %-6.6s", getchan (a->o_wchan));
ptty (a->o_tty);
ptime (a);
}
ptty (tp)
char *tp;
{
printf (" %-8.8s", tp);
}
ptime (a)
register struct psout *a;
{
time_t tm;
tm = (a->o_utime + a->o_stime + 30) / hz;
printf ("%3ld:", tm / 60);
tm %= 60;
printf (tm < 10 ? "0%ld" : "%ld", tm);
}
cantread (what, fromwhat)
char *what, *fromwhat;
{
fprintf (stderr, "ps: error reading %s from %s\n", what, fromwhat);
}
getcmd (a, addr)
off_t addr;
register struct psout *a;
{
/* amount of top of stack to examine for args */
#define ARGLIST (1024/sizeof(int))
register *ip;
register char *cp, *cp1;
char c;
char **ap;
int cc, nbad, abuf [ARGLIST];
a->o_args[0] = 0; /* in case of early return */
#ifdef VIRUS_VFORK
addr += ctob ((off_t) mproc->p_ssize) - ARGLIST*sizeof(int);
#else
addr += ctob ((off_t) mproc->p_size) - ARGLIST*sizeof(int);
#endif
/* look for sh special */
lseek (file, addr + ARGLIST*sizeof(int) - sizeof (char **), 0);
if (read (file, (char *) &ap, sizeof (char *)) != sizeof (char *))
return (1);
if (ap) {
char b[82];
char *bp = b;
while ((cp = getptr (ap++)) && cp && (bp < b+sizeof (a->o_args)) ) {
nbad = 0;
while ((c = getbyte (cp++)) && (bp < b+sizeof (a->o_args))) {
if (c<' ' || c > '~') {
if (nbad++ > 3)
break;
continue;
}
*bp++ = c;
}
*bp++ = ' ';
}
*bp++ = 0;
strcpy (a->o_args, b);
return (1);
}
if (pread (file, (char *) abuf, sizeof (abuf), addr) != sizeof (abuf))
return (1);
abuf[ARGLIST-1] = 0;
for (ip = &abuf[ARGLIST-2]; ip > abuf;) {
if (*--ip == -1 || *ip == 0) {
cp = (char *) (ip + 1);
if (*cp == '\0')
cp++;
nbad = 0;
for (cp1 = cp; cp1 < (char *) &abuf[ARGLIST]; cp1++) {
cc = *cp1 & 0177;
if (cc == 0)
*cp1 = ' ';
else if (cc < ' ' || cc > 0176) {
if (++nbad >= 5) {
*cp1++ = ' ';
break;
}
*cp1 = '?';
} else if (cc == '=') {
*cp1 = '\0';
while (cp1 > cp && *--cp1 != ' ')
*cp1 = '\0';
break;
}
}
while (*--cp1 == ' ')
*cp1 = 0;
strcpy (a->o_args, cp);
garbage:
cp = a->o_args;
if (cp[0] == '-' && cp[1] <= ' ' || cp[0] == '?' || cp[0] <= ' ') {
strcat (cp, " (");
strcat (cp, u.u_comm);
strcat (cp, ")");
}
cp[63] = 0; /* max room in psout is 64 chars */
if (xflg || gflg || tptr || cp[0] != '-')
return (1);
return (0);
}
}
goto garbage;
}
printhdr ()
{
register char *hdr;
#ifdef TERMCAP
register char *cmdstr = " COMMAND";
#endif
if (rflg)
return;
if (lflg && uflg)
err ("ps: specify only one of l and u");
hdr = lflg ? lhdr : (uflg ? uhdr : shdr);
cmdstart = strlen (hdr);
#ifdef TERMCAP
if (cmdstart + strlen (cmdstr) >= twidth)
cmdstr = " CMD";
printf ("%s%s\n", hdr, cmdstr);
#else
printf ("%s COMMAND\n", hdr);
#endif
fflush (stdout);
}