|
|
coherent
/*
* Modifications copyright INETCO Systems Ltd.
*
* Print out process statuses.
*
* $Log: ps.c,v $
* Revision 1.1.1.1 2019/05/29 04:56:39 root
* coherent
*
* Revision 1.3 91/07/17 14:22:55 bin
* stevesf supplied as INETCO source because previous sources are of
* questionable origin... this one works
*
* Revision 1.2 89/06/12 15:15:22 src
* Bug: A directory at the end of the '/dev' directory would cause 'ps'
* to crash with the message "Cannot open <dir> in /dev".
* Fix: A stat was being done without the return code being checked. (ART)
*
* Revision 1.1 89/06/12 14:42:24 src
* Initial revision
*
* 88/02/15 Allan Cornish /usr/src/cmd/cmd/ps.c
* Kernel processes are now displayed regardless of -ax flags.
*
* 87/11/25 Allan Cornish /usr/src/cmd/cmd/ps.c
* Debug flag now -D. Drivers now displayed by -d flag.
*
* 87/11/12 Allan Cornish /usr/src/cmd/cmd/ps.c
* Modified to support Coherent 9.0 [protected mode] segmentation.
*
* 87/10/20 Allan Cornish /usr/src/cmd/cmd/ps.c
* Now extracts cmd name from u_comm field in uproc struct for kernel procs.
* Kernel processes only displayed if -d [debug] flag given.
*
* 87/09/28 Phil Selby /usr/src/cmd/cmd/ps.c
* Altered so that the terminal name rather than major and minor
* device number is printed out
*
* 84/08/21 Rec
* Added gflag for group identification.
*
* 84/07/16 Lauren Weinstein
* Initial version.
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/const.h>
#include <l.out.h>
#include <pwd.h>
#include <sys/proc.h>
#include <sys/sched.h>
#include <sys/dir.h>
#include <sys/seg.h>
#include <sys/stat.h>
#include <sys/uproc.h>
/*
* This is a kludge for the i8086 only and will be
* made to disappear when the segmentation (jproto)
* is thrown away.
*/
#undef SISTACK
#define SISTACK SIPDATA
/*
* Terminal information stored in memory for use by ps in TTY field
*/
struct handle {
dev_t dnum; /* device number */
char dname[DIRSIZ]; /* device name */
struct handle *nptr; /* pointer to next */
} *fptr, *lptr;
/*
* Maximum sizes.
*/
#define ARGSIZE 512
/*
* Functions to see if a pointer is in alloc space and to map a
* pointer from alloc space to this process.
*/
#define range(p) (p>=(char *)(aend) && p<(char *)(aend)+casize)
#define map(p) (&allp[(char *)p - (char *)aend])
/*
* For easy referencing.
*/
#define aprocq nl[0].n_value
#define autime nl[1].n_value
#define astime nl[2].n_value
#define aasize nl[3].n_value
#define aend nl[4].n_value
/*
* Variables.
*/
int aflag; /* All processes */
int dflag; /* Driver flag */
int dbflag; /* Debug flag */
int fflag; /* Print out all fields */
int gflag; /* Print out process groups */
int lflag; /* Long format */
int mflag; /* Print scheduling values */
int nflag; /* No header */
int rflag; /* Print out real sizes */
int tflag; /* Print times */
int wflag; /* Wide format */
int xflag; /* Get special processes */
dev_t ttdev; /* Terminal device */
/*
* Table for namelist.
*/
struct nlist nl[] ={
"procq_", 0, 0,
"utimer_", 0, 0,
"stimer_", 0, 0,
"asize_", 0, 0,
"end_", 0, 0,
""
};
/*
* Symbols.
*/
char *allp; /* Pointer to alloc space */
char *kfile; /* Kernel data memory file */
char *nfile; /* Namelist file */
char *mfile; /* Memory file */
char *dfile; /* Swap file */
char argp[ARGSIZE]; /* Arguments */
int kfd; /* Kernel memory file descriptor */
int mfd; /* Memory file descriptor */
int dfd; /* Swap file descriptor */
struct uproc u; /* User process area */
int cutime; /* Unsigned time */
PROC cprocq; /* Process queue header */
unsigned casize; /* Size of alloc area */
main(argc, argv)
char *argv[];
{
register int i;
register char *cp;
initialise();
for (i=1; i<argc; i++) {
for (cp=&argv[i][0]; *cp; cp++) {
switch (*cp) {
case '-':
continue;
case 'a':
aflag++;
continue;
case 'c':
if (++i >= argc)
usage();
nfile = argv[i];
continue;
case 'd':
dflag++;
continue;
case 'D':
dbflag++;
continue;
case 'f':
fflag++;
continue;
case 'g':
gflag++;
continue;
case 'k':
if (++i >= argc)
usage();
mfile = argv[i];
continue;
case 'l':
lflag++;
continue;
case 'm':
mflag++;
continue;
case 'n':
nflag++;
continue;
case 'r':
rflag++;
continue;
case 't':
tflag++;
continue;
case 'w':
wflag++;
continue;
case 'x':
xflag++;
continue;
default:
usage();
}
}
}
execute();
exit(0);
}
/*
* Initialise.
*/
initialise()
{
register char *cp;
aflag = 0;
gflag = 0;
lflag = 0;
mflag = 0;
nflag = 0;
xflag = 0;
nfile = "/coherent";
kfile = "/dev/kmem";
mfile = "/dev/mem";
dfile = "/dev/swap";
if ((cp=malloc(BUFSIZ)) != NULL)
setbuf(stdout, cp);
}
/*
* Print out usage.
*/
usage()
{
panic("Usage: ps [-][acdfgklmnrtwx]");
}
/*
* Print out information about processes.
*/
execute()
{
int c, l;
register PROC *pp1, *pp2;
nlist(nfile, nl);
if (nl[0].n_type == 0)
panic("Bad namelist file %s", nfile);
if ((mfd=open(mfile, 0)) < 0)
panic("Cannot open %s", mfile);
if ((kfd = open(kfile, 0)) < 0)
panic("Cannot open %s", kfile);
/*
* Open swap device if it exists
*/
dfd = open(dfile, 0);
kread((long)aasize, &casize, sizeof (casize));
kread((long)aprocq, &cprocq, sizeof (cprocq));
if ((allp=malloc(casize)) == NULL)
panic( "Out of core or invalid kernel specified" );
kread((long)aend, allp, casize);
kread((long)autime, &cutime, sizeof (cutime));
settdev();
fttys( "/dev"); /* load all the devices in dev */
l = 9;
if (dbflag)
l += 7;
if (gflag)
l += 6;
if (lflag)
l += 34;
if (mflag)
l += 26;
if (tflag)
l += 12;
if (nflag == 0) {
if (dbflag)
printf(" ");
printf("TTY PID");
if (gflag)
printf(" GROUP");
if (lflag)
printf(" PPID UID K F S EVENT");
if (mflag)
printf(" CVAL SVAL IVAL RVAL");
if (tflag)
printf(" UTIME STIME");
putchar('\n');
fflush(stdout);
}
pp1 = &cprocq;
while ((pp2=pp1->p_nback) != aprocq) {
if (range((char *)pp2) == 0)
panic("Fragmented list");
pp1 = (PROC *) map(pp2);
/*
* Kernel process - display only if '-d' argument given.
*/
if ( pp1->p_flags & PFKERN ) {
if ( dflag == 0 )
continue;
}
/*
* Unattached process - display only if '-x' argument given.
*/
else if ( pp1->p_ttdev == NODEV ) {
if ( xflag == 0 )
continue;
}
/*
* Attached to other terminal - display only if '-a' arg given.
*/
else if ( pp1->p_ttdev != ttdev ) {
if ( aflag == 0 )
continue;
}
if (dbflag)
printf("%06o ", pp2);
ptty(pp1);
printf(" %5d", pp1->p_pid);
if (gflag)
printf(" %5d", pp1->p_group);
if (lflag) {
printf(" %5d", pp1->p_ppid);
printf(" %8.8s", uname(pp1));
psize(pp1);
printf(" %4o", pp1->p_flags);
printf(" %c", c=state(pp1, pp2));
if (c == 'S')
printf(" %06o", pp1->p_event);
else {
if (fflag)
printf(" -");
else
printf(" ");
}
}
if (mflag) {
printf(" %5u", cval(pp1, pp2));
printf(" %5u", pp1->p_sval);
printf(" %6d", pp1->p_ival);
printf(" %6d", pp1->p_rval);
}
if (tflag) {
ptime(pp1->p_utime);
ptime(pp1->p_stime);
}
printf(" ");
printl(pp1, (wflag?132:80)-l-1);
putchar('\n');
fflush(stdout);
}
rttys(); /* release all alloced space */
}
/*
* Set our terminal device.
*/
settdev()
{
register PROC *pp1, *pp2;
register int p;
p = getpid();
pp1 = &cprocq;
while ((pp2=pp1->p_nforw) != aprocq) {
if (range((char *)pp2) == 0)
break;
pp1 = (PROC *) map(pp2);
if (pp1->p_pid == p) {
ttdev = pp1->p_ttdev;
return;
}
}
ttdev = NODEV;
}
/*
* Finds all special file in the specified directory (e.g. /dev)
*/
fttys( dirname)
char *dirname;
{
int filein; /* directory file descriptor */
struct stat sbuf; /* stat structure */
struct direct dbuf; /* directory buffer structure */
/* move to the appropriate directory and open file for reading */
chdir( dirname );
if( ( filein = open( ".", 0) ) < 0 ) {
fprintf( stderr, "Cannot open '%s' in /dev\n", dirname );
exit( 1 );
}
read( filein, &dbuf, sizeof(dbuf) ); /* read . */
read( filein, &dbuf, sizeof(dbuf) ); /* read .. */
while( read( filein, &dbuf, sizeof(dbuf) ) ) {
if( stat( dbuf.d_name, &sbuf ) < 0 )
continue;
if( sbuf.st_mode & S_IFCHR )
addname( dbuf.d_name, sbuf.st_rdev );
else if( sbuf.st_mode & S_IFDIR )
fttys( dbuf.d_name );
}
close( filein );
chdir( ".." );
}
/*
* Adds a name and and device number of type handle
*/
addname( devname, devnum )
char *devname;
dev_t devnum;
{
extern struct handle *fptr;
extern struct handle *lptr;
if( fptr == (struct handle *) NULL ) {
if( (fptr=(struct handle *) malloc( sizeof(struct handle))) ==
(struct handle *) NULL ) {
fprintf( stderr, "Out of memory\n");
exit( 1 );
}
fptr->nptr = (struct handle *) NULL;
strcpy( fptr->dname, devname);
fptr->dnum = devnum;
}
else {
lptr = fptr;
while( ( lptr->nptr != (struct handle *) NULL ) &&
( lptr->dnum != devnum ) ) lptr = lptr->nptr;
if( lptr->dnum == devnum )
return;
if( (lptr->nptr=(struct handle *)malloc(sizeof(struct handle)))
== (struct handle *) NULL ) {
fprintf( stderr, "Out of memory\n");
exit( 1 );
}
lptr = lptr->nptr;
lptr->nptr = (struct handle *) NULL;
strcpy( lptr->dname, devname);
lptr->dnum = devnum;
}
}
/*
* Release allocated space on exit (default action anyway)
*/
rttys()
{
/* release allocated space */
lptr = fptr;
while( lptr->nptr != (struct handle *) NULL ) {
fptr = lptr;
lptr = fptr->nptr;
free( fptr);
}
free( lptr);
}
/*
* Print the controlling terminal name. If not found it prints the
* major and minor device numbers. If no controlling terminal on the
* process than '--------' is printed.
*/
ptty( pp )
register PROC *pp;
{
register int d;
/* when supplied with a device number, look for the name
of the special file from the dev directory */
if( ( d = pp->p_ttdev ) == NODEV ) {
printf( "-------");
return;
}
lptr = fptr;
while( lptr->nptr != (struct handle *) NULL ) {
if( lptr->dnum == d ) {
printf( "%-7.7s", lptr->dname);
return;
}
lptr = lptr->nptr;
}
if( lptr->dnum == d ) {
printf( "%-7.7s", lptr->dname);
return;
}
printf( "%3d %3d", major( d ), minor( d ) );
return;
}
/*
* Given a process, return it's user name.
*/
uname(pp)
register PROC *pp;
{
static char name[8];
register struct passwd *pwp;
if ((pwp=getpwuid(pp->p_ruid)) != NULL)
return (pwp->pw_name);
sprintf(name, "%d", pp->p_ruid);
return (name);
}
/*
* Return the core value for a process.
*/
cval(pp1, pp2)
register PROC *pp1;
{
unsigned u;
register PROC *pp3, *pp4;
if (pp1->p_state == PSSLEEP) {
u = (cutime-pp1->p_lctim) * 1;
if (pp1->p_cval+u > pp1->p_cval)
return (pp1->p_cval+u);
return (-1);
}
u = 0;
pp3 = &cprocq;
while ((pp4=pp3->p_lforw) != aprocq) {
if (range((char *)pp4) == 0)
break;
pp3 = (PROC *) map(pp4);
u -= pp3->p_cval;
if (pp2 == pp4)
return (u);
}
if (pp1->p_pid == getpid())
return (pp1->p_cval);
return (0);
}
/*
* Return the size in K of the given process.
*/
psize(pp)
register PROC *pp;
{
long l;
register SEG *sp;
register int n;
l = 0;
for (n=0; n<NUSEG+1; n++) {
if (rflag == 0)
if (n==SIUSERP || n==SIAUXIL)
continue;
if ((sp=pp->p_segp[n]) == NULL)
continue;
if (range((char *)sp) == 0) {
printf(" ?K");
return;
}
sp = (SEG *) map(sp);
l += sp->s_size;
}
if (l != 0)
printf("%4ldK", l/1024);
else {
if (fflag)
printf(" -");
else
printf(" ");
}
}
/*
* Get the state of the process.
*/
state(pp1, pp2)
register PROC *pp1;
{
register int s;
s = pp1->p_state;
if (s == PSSLEEP) {
if (pp1->p_event == pp2)
return ('W');
if ((pp1->p_flags&PFSTOP) != 0)
return ('T');
return ('S');
}
if (s == PSRUN)
return ('R');
if (s == PSDEAD)
return ('Z');
return ('?');
}
/*
* Given a time in HZ, print it out.
*/
ptime(l)
long l;
{
register unsigned m;
if ((l=(l+HZ/2)/HZ) == 0) {
if (fflag)
printf(" -");
else
printf(" ");
return;
}
if ((m=l/60) >= 100) {
printf("%6d", m);
return;
}
printf(" %2d:%02d", m, (unsigned)l%60);
}
/*
* Print out the command line of a process.
*/
printl(pp, m)
register PROC *pp;
{
register char *cp;
register int c;
register int argc;
register int n;
if (pp->p_state == PSDEAD)
return;
if (pp->p_pid == 0) {
printf("<idle>");
return;
}
if (segread(pp->p_segp[SIUSERP], 0, &u, sizeof (u)) == 0)
return;
/*
* Handle kernel processes.
*/
if ( pp->p_flags & PFKERN ) {
printf("<%.*s>",sizeof(u.u_comm), u.u_comm[0] ? u.u_comm : "");
return;
}
n = segread(pp->p_segp[SISTACK], (u.u_argp-u.u_segl[SISTACK].sr_base),
argp, sizeof (argp));
if (n == 0)
return;
if ((argc=u.u_argc) <= 0)
return;
m -= 2;
cp = argp;
while (argc--) {
while ((c=*cp++) != '\0') {
if (!isascii(c) || !isprint(c))
return;
if (m-- == 0)
return;
putchar(c);
}
if (m-- == 0)
return;
if (argc != 0)
putchar(' ');
}
}
/*
* Given a segment pointer `sp' and an offset into the segment,
* `s', read `n' bytes from the segment into the buffer `bp'.
*/
segread(sp, s, bp, n)
SEG *sp;
vaddr_t s;
char *bp;
{
register SEG *sp1;
if (range((char *)sp) == 0)
return (0);
sp1 = (SEG *) map(sp);
if ((sp1->s_flags&SFCORE) != 0)
mread( sp1->s_paddr + s, bp, n );
else
if( dread( (long)sp1->s_daddr*BSIZE + s, bp, n ) < 0 )
return( 0 );
return (1);
}
/*
* Read `n' bytes into the buffer `bp' from kernel memory
* starting at seek position `s'.
*/
kread(s, bp, n)
long s;
{
lseek(kfd, (long)s, 0);
if (read(kfd, bp, n) != n)
panic("Kernel memory read error");
}
/*
* Read `n' bytes into the buffer `bp' from absolute memory
* starting at seek position `s'.
*/
mread(s, bp, n)
long s;
{
lseek(mfd, (long)s, 0);
if (read(mfd, bp, n) != n)
panic("Memory read error");
}
/*
* Read `n' bytes into the buffer `bp' from the swap file
* starting at seek position `s'.
*/
dread(s, bp, n)
long s;
{
/*
* If swap device exists go look at it
*/
if( dfd > 0 ) {
lseek(dfd, (long)s, 0);
if (read(dfd, bp, n) != n)
panic("Swap read error");
return( 1 );
}
return( 0 );
}
/*
* Print out an error message and exit.
*/
panic(a1)
char *a1;
{
fflush(stdout);
fprintf(stderr, "%r", &a1);
fprintf(stderr, "\n");
exit(1);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.