[comp.sources.unix] v10i061: SPS for BSD, Ultrix1.2, Sun3.x, NFS, Part02/03

rs@uunet.UU.NET (Rich Salz) (07/23/87)

Submitted-by: robert@hslrswi.UUCP (Robert Ward)
Posting-Number: Volume 10, Issue 61
Archive-name: sps/Part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 3)."
# Contents:  flagdecode.c getcmd.c globals2.c inittty.c needed.c
#   printproc.c sps.h waitingfor.c
# Wrapped by rs@uunet on Wed Jul 22 20:09:09 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f flagdecode.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"flagdecode.c\"
else
echo shar: Extracting \"flagdecode.c\" \(5436 characters\)
sed "s/^X//" >flagdecode.c <<'END_OF_flagdecode.c'
X# include       "sps.h"
X# include       "flags.h"
X
X/* FLAGDECODE - Looks at the argument list and sets various internal switches */
Xflagdecode ( argc, argv )
X
Xregister int                    argc ;
Xregister char                   **argv ;
X
X{
X	register char           *chp ;
X	union flaglist          *plist ;
X	union flaglist          *tlist ;
X	union flaglist          *ulist ;
X	static char             usage[] =
X	"sps - Unknown option %s\nUsage - sps [ -defgijkoqrsvwyABFNPSTUWZ ][ process|tty|user ] ...\n";
X	union flaglist          *getflgsp() ;
X	extern struct flags     Flg ;
X
X	plist = tlist = ulist = (union flaglist*)0 ;
X	for ( argv++ ; --argc ; argv++ )
X	{
X		chp = *argv ;
X		while ( *chp )
X			switch ( *chp++ )
X			{
X				case '-' :
X					/* Separation character */
X					continue ;
X				case 'd' :
X				case 'D' :
X					/* List disc orientated information */
X					Flg.flg_d = 1 ;
X					Flg.flg_v = 0 ;
X					continue ;
X				case 'e' :
X				case 'E' :
X					/* List environment strings */
X					Flg.flg_e = 1 ;
X					continue ;
X				case 'f' :
X					/* List the father's process id */
X					Flg.flg_f = 1 ;
X					continue ;
X				case 'g' :
X				case 'G' :
X					/* List the process group id */
X					Flg.flg_g = 1 ;
X					continue ;
X				case 'i' :
X				case 'I' :
X					/* Initialise (super-user only) */
X					Flg.flg_i = 1 ;
X					continue ;
X				case 'j' :
X				case 'J' :
X					/* The next argument specifies the
X					   name of the information file */
X					if ( argc <= 1 )
X						prexit(
X	      "sps - Name of an information file expected after `-j' flag\n" ) ;
X					argc-- ;
X					Flg.flg_j = *++argv ;
X					continue ;
X				case 'k' :
X				case 'K' :
X					/* Use a disc file such as /vmcore
X					   rather than /dev/{k}mem for
X					   accessing kernel data. The next
X					   argument specifies the file name. */
X					if ( argc <= 1 )
X						prexit(
X	       "sps - Name of a memory dump file expected after `-k' flag\n" ) ;
X					argc-- ;
X					Flg.flg_k = *++argv ;
X					Flg.flg_o = 1 ;
X					continue ;
X				case 'l' :
X				case 'v' :
X				case 'L' :
X				case 'V' :
X					/* Verbose output */
X					Flg.flg_d = 0 ;
X					Flg.flg_v = 1 ;
X					continue ;
X				case 'o' :
X				case 'O' :
X					/* Avoid looking at the swap device */
X					Flg.flg_o = 1 ;
X					continue ;
X				case 'q' :
X				case 'Q' :
X					/* Show only the user time, not the
X					   user + system times together. */
X					Flg.flg_q = 1 ;
X					continue ;
X				case 'r' :
X				case 'R' :
X					/* Repeat output every n seconds.
X					   The next argument specifies n which
X					   defaults to 5 if omitted. */
X					Flg.flg_r = 1 ;
X					if ( argc > 1 )
X					{
X						if ( **++argv >= '0'
X						&& **argv <= '9' )
X						{
X							argc-- ;
X							Flg.flg_rdelay
X							       = atoi( *argv ) ;
X							continue ;
X						}
X						argv-- ;
X					}
X					Flg.flg_rdelay = 0 ;
X					continue ;
X				case 's' :
X					/* Next argument specifies a symbol
X					   file rather than the default
X					   /vmunix. */
X					if ( argc <= 1 )
X						prexit(
X		    "sps - Name of a symbol file expected after `-s' flag\n" ) ;
X					argc-- ;
X					Flg.flg_s = *++argv ;
X					continue ;
X				case 'w' :
X					/* Wide output, exceeding 79 columns */
X					Flg.flg_w = 1 ;
X					continue ;
X				case 'y' :
X				case 'Y' :
X					/* List current tty information */
X					Flg.flg_y = 1 ;
X					continue ;
X				case 'a' :
X				case 'A' :
X					/* List all processes */
X					Flg.flg_AZ = 1 ;
X					Flg.flg_A = 1 ;
X					continue ;
X				case 'b' :
X				case 'B' :
X					/* List only busy processes */
X					Flg.flg_AZ = 1 ;
X					Flg.flg_B = 1 ;
X					continue ;
X				case 'F' :
X					/* List only foreground processes */
X					Flg.flg_AZ = 1 ;
X					Flg.flg_F = 1 ;
X					continue ;
X				case 'n' :
X				case 'N' :
X					/* No processes, just the summary line*/
X					Flg.flg_AZ = 1 ;
X					Flg.flg_N = 1 ;
X					continue ;
X				case 'p' :
X				case 'P' :
X					/* List only the given process ids */
X					Flg.flg_AZ = 1 ;
X					Flg.flg_P = 1 ;
X					if ( !plist )
X					   plist=Flg.flg_Plist=getflgsp( argc );
X					while ( argc > 1 )
X					{
X						if ( **++argv == '-' )
X						{
X							--argv ;
X							break ;
X						}
X						--argc ;
X						plist->f_chp = *argv ;
X						(++plist)->f_chp = (char*)0 ;
X					}
X					continue ;
X				case 'S' :
X					/* List only stopped processes */
X					Flg.flg_AZ = 1 ;
X					Flg.flg_S = 1 ;
X					continue ;
X				case 't' :
X				case 'T' :
X					/* List only processes attached to the
X					   specified terminals */
X					Flg.flg_AZ = 1 ;
X					Flg.flg_T = 1 ;
X					if ( !tlist )
X					   tlist=Flg.flg_Tlist=getflgsp( argc );
X					while ( argc > 1 )
X					{
X						if ( **++argv == '-' )
X						{
X							--argv ;
X							break ;
X						}
X						--argc ;
X						tlist->f_chp = *argv ;
X						(++tlist)->f_chp = (char*)0 ;
X					}
X					continue ;
X				case 'u' :
X				case 'U' :
X					/* List only processes belonging to the
X					   specified users */
X					Flg.flg_AZ = 1 ;
X					Flg.flg_U = 1 ;
X					if ( !ulist )
X					   ulist=Flg.flg_Ulist=getflgsp( argc );
X					while ( argc > 1 )
X					{
X						if ( **++argv == '-' )
X						{
X							--argv ;
X							break ;
X						}
X						--argc ;
X						ulist->f_chp = *argv ;
X						(++ulist)->f_chp = (char*)0 ;
X					}
X					continue ;
X				case 'W' :
X					/* List only waiting processes */
X					Flg.flg_AZ = 1 ;
X					Flg.flg_W = 1 ;
X					continue ;
X				case 'z' :
X				case 'Z' :
X					/* List only zombie processes */
X					Flg.flg_AZ = 1 ;
X					Flg.flg_Z = 1 ;
X					continue ;
X				default :
X					prexit( usage, *argv ) ;
X					/* NOTREACHED */
X			}
X	}
X}
END_OF_flagdecode.c
if test 5436 -ne `wc -c <flagdecode.c`; then
    echo shar: \"flagdecode.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f getcmd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"getcmd.c\"
else
echo shar: Extracting \"getcmd.c\" \(4980 characters\)
sed "s/^X//" >getcmd.c <<'END_OF_getcmd.c'
X# include       "sps.h"
X# include       "flags.h"
X# include       <h/vm.h>
X# ifdef BSD42
X# include	<machine/pte.h>
X# else
X# include       <h/pte.h>
X# endif
X
X/*
X** GETCMD - Returns a character string read from a process' upage.
X** This character string should represent the arguments to the current process.
X*/
Xchar    *getcmd ( p )
X
Xregister struct process         *p ;
X
X{
X	register int            *ip ;
X	register char           *cp ;
X	register char           *cp0 ;
X	unsigned                nbad ;
X	struct dblock           db ;
X	struct pte              ptetbl[ UPAGES + CLSIZE ] ;
X	union
X	{
X		char            a_argc[ CLSIZE * NBPG ] ;
X		int             a_argi[ CLSIZE * NBPG / sizeof( int ) ] ;
X	} argbuf ;
X	extern struct flags     Flg ;
X	extern union userstate  User ;
X	extern int              Flmem, Flswap ;
X	char                    *strcat(), *strncpy(), *strsave() ;
X
X	p->pr_csaved = 0 ;
X	p->pr_upag = 0 ;
X	if ( p->pr_p.p_stat == SZOMB )
X		return ( "** Exit **" ) ;
X	if ( !(p->pr_p.p_flag & SLOAD) && Flg.flg_o )
X		return ( "** Swapped out **" ) ;
X	/* Find the process' upage */
X	if ( !getupage( p, ptetbl ) )           
X		return ( "** No upage **" ) ;
X	/* Is this a system process ? */
X	if ( p->pr_p.p_flag & SSYS )            
X		switch ( p->pr_p.p_pid )
X		{
X			case 0 :
X				p->pr_upag = 1 ;
X				return ( "Unix Swapper" ) ;
X			case 2 :
X				p->pr_upag = 1 ;
X				return ( "Unix Pager" ) ;
X			default :
X				break ;
X		}
X	/* Fix by Alexander Dupuy <dupuy@amsterdam.columbia.edu> */
X	/* Check for lack of stack, jack! (Sun 3.0 biod's) */
X	if (User.u_us.u_ssize == 0)
X		goto getsysargs ;
X	/* Look at the top of the upage to locate the command arguments.
X	   The page is loaded if the process itself is loaded and the pte
X	   contains is marked as valid. */
X	if ( (p->pr_p.p_flag & SLOAD)
X	&& !ptetbl[0].pg_fod && ptetbl[0].pg_pfnum )
X	{       /* If the page is loaded, read the arguments from
X		   physical memory. */
X		memseek( Flmem, (long)ctob( ptetbl[0].pg_pfnum ) ) ;
X		if ( read( Flmem, argbuf.a_argc, CLSIZE*NBPG ) != CLSIZE*NBPG )
X			return ( "** Memory read error **" ) ;
X	}
X	else                            
X	{       /* Otherwise the page is on the swap device */
X		vstodb( 0, ctod( CLSIZE ), &User.u_us.u_smap, &db, 1 ) ;
X# ifdef BSD42
X		swseek( (long)dtob( db.db_base ) ) ;
X# else
X		swseek( (long)ctob( db.db_base ) ) ;
X# endif
X		if ( Flg.flg_o )
X			return ( "** Swapped page **" ) ;
X		if ( read( Flswap, argbuf.a_argc, CLSIZE*NBPG ) != CLSIZE*NBPG )
X			return ( "** Swap device read error **" ) ;
X	}
X	/* Look down until the end of command arguments is found. */
X	p->pr_upag = 1 ;
X	p->pr_csaved = 1 ;
X	ip = &argbuf.a_argi[ CLSIZE*NBPG / sizeof( int ) ] ;
X	ip -= 2 ;
X	while ( *--ip )
X		if ( ip == &argbuf.a_argi[0] )
X			goto getsysargs ;
X	/* Process the command arguments, looking for nulls and unprintable
X	   characters. */
X	cp0 = (char*)(ip + 1) ;
X	if ( !*cp0 )                    
X		cp0++ ;                 
X	if ( *cp0 )
X	{
X		nbad = 0 ;                      
X		for ( cp = cp0 ; cp < &argbuf.a_argc[ CLSIZE*NBPG ] ; cp++ )
X		{
X			*cp &= 0177 ;
X			if ( !*cp )             
X			{       /* Replace nulls with spaces */
X				*cp = ' ' ;
X				continue ;
X			}
X			if ( *cp < ' ' || *cp == 0177 )
X			{       /* Replace control characters with ?'s */
X				if ( ++nbad > 5 )
X				{
X					*cp++ = ' ' ;
X					break ;
X				}
X				*cp = '?' ;
X				continue ;
X			}
X			if ( !Flg.flg_e && *cp == '=' )
X			{       /* Break on an `=' if we are not interested
X				   in the environment strings. */
X				*cp = '\0' ;
X				while ( cp > cp0 && *--cp != ' ' )
X					*cp = '\0' ;
X				break ;
X			}
X		}
X		while ( *--cp == ' ' )
X			*cp = '\0' ;
X		return ( strsave( cp0 ) ) ;
X	}
Xgetsysargs :
X	/* If the command arguments cannot be accessed from the user's memory
X	   space, get the command name from the system's idea of what the
X	   name should be. */
X	argbuf.a_argc[0] = '(' ;
X	(void)strncpy( &argbuf.a_argc[1], User.u_us.u_comm,
X		sizeof( User.u_us.u_comm ) ) ;
X	(void)strcat( &argbuf.a_argc[0], ")" ) ;
X	return ( strsave( argbuf.a_argc ) ) ;
X}
X
X/*
X** VSTODB - Given a base/size pair in virtual swap area,
X** return a physical base/size pair which is the
X** (largest) initial, physically contiguous block.
X/* This code is stolen from the kernel file /sys/sys/vm_drum.c.
X*/
Xvstodb ( vsbase, vssize, dmp, dbp, rev )
X
Xregister int                    vsbase ;
Xregister int                    vssize;
Xstruct dmap                     *dmp ;
Xregister struct dblock          *dbp ;
Xint                             rev ;
X
X{
X	register int            blk ;
X	register swblk_t        *ip ;
X# ifdef BSD42
X	extern struct info      Info ;
X# endif
X
X# ifdef BSD42
X	blk = Info.i_dmmin ;
X# else
X	blk = DMMIN ;
X# endif
X	ip = dmp->dm_map ;
X	while ( vsbase >= blk )
X	{
X		vsbase -= blk ;
X# ifdef BSD42
X		if ( blk < Info.i_dmmax )
X# else
X		if ( blk < DMMAX )
X# endif
X			blk *= 2 ;
X		ip++ ;
X	}
X	dbp->db_size = vssize < blk - vsbase ? vssize : blk - vsbase ;
X	dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
X}
END_OF_getcmd.c
if test 4980 -ne `wc -c <getcmd.c`; then
    echo shar: \"getcmd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f globals2.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"globals2.c\"
else
echo shar: Extracting \"globals2.c\" \(5375 characters\)
sed "s/^X//" >globals2.c <<'END_OF_globals2.c'
X# include       "sps.h"
X
X/* Read Only variables, global to the code of sps ... */
X
X/* Null ttyline device ... */
Xstruct ttyline                  Notty = { 0, 0, "  ", 0 } ;
X
X/*
X** The symbol table. For each address read from the kernel during
X** initialisation, this table shows the following:
X**      i.   the name of that symbol within the kernel ;
X**      ii.  whether an extra indirection is needed through the kernel,
X**           i.e. whether the value of that symbol should be obtained
X**           rather than its address.
X**      iii. where the obtained value/address is placed in the Info structure ;
X**      iv.  whether the obtained value is associated with a reason for
X**           a process wait state.
X*/
X/* The order of entries in this table is unimportant. */
X
Xextern struct info              Info ;
X
Xstruct symbol   Symbollist[] =
X{       
X	/* Kernel addresses required in order to access process,
X	   tty and upage information. All these addresses should be
X	   located in the symbol file during initialisation. */
X	{ "_proc",      1,  (caddr_t*)&Info.i_proc0,    (char*)0        },
X	{ "_nproc",     1,  (caddr_t*)&Info.i_nproc,    (char*)0        },
X	{ "_text",      1,  (caddr_t*)&Info.i_text0,    (char*)0        },
X	{ "_ntext",     1,  (caddr_t*)&Info.i_ntext,    (char*)0        },
X	{ "_inode",     1,  (caddr_t*)&Info.i_inode0,   (char*)0        },
X	{ "_ninode",    1,  (caddr_t*)&Info.i_ninode,   (char*)0        },
X	{ "_swbuf",     1,  (caddr_t*)&Info.i_swbuf0,   (char*)0        },
X	{ "_nswbuf",    1,  (caddr_t*)&Info.i_nswbuf,   (char*)0        },
X	{ "_buf",       1,  (caddr_t*)&Info.i_buf0,     (char*)0        },
X	{ "_nbuf",      1,  (caddr_t*)&Info.i_nbuf,     (char*)0        },
X	{ "_ecmx",      1,  (caddr_t*)&Info.i_ecmx,     (char*)0        },
X	{ "_Usrptmap",  0,  (caddr_t*)&Info.i_usrptmap, (char*)0        },
X	{ "_usrpt",     0,  (caddr_t*)&Info.i_usrpt,    (char*)0        },
X	{ "_cdevsw",    0,  (caddr_t*)&Info.i_cdevsw,   (char*)0        },
X# ifdef BSD42
X# ifndef NFS
X	{ "_quota",     1,  (caddr_t*)&Info.i_quota0,   (char*)0        },
X	{ "_nquota",    1,  (caddr_t*)&Info.i_nquota,   (char*)0        },
X# endif NFS
X	{ "_dmmin",     1,  (caddr_t*)&Info.i_dmmin,    (char*)0        },
X	{ "_dmmax",     1,  (caddr_t*)&Info.i_dmmax,    (char*)0        },
X	{ "_mbutl",     0,  (caddr_t*)&Info.i_mbutl,    (char*)0        },
X# else
X	{ "_hz",        1,  (caddr_t*)&Info.i_hz,       (char*)0        },
X# endif BSD42
X# ifdef CHAOS
X	{ "_Chconntab", 0,  &Info.i_Chconntab,          (char*)0        },
X# endif CHAOS
X	/* Kernel addresses associated with process wait states.
X	   It is not important if some of these addresses are unresolved
X	   at initialisation. */
X# ifndef SUN
X	{ "_fltab",     0,  &Info.i_waitstate[0],       "floppy"        },
X	{ "_tu",        0,  &Info.i_waitstate[1],       "tu58"          },
X	{ "_lp_softc",  0,  &Info.i_waitstate[3],       "printr"        },
X# endif SUN
X	{ "_bfreelist", 0,  &Info.i_waitstate[2],       "buffer"        },
X	{ "_lbolt",     0,  &Info.i_waitstate[4],       "lbolt"         },
X	{ "_runin",     0,  &Info.i_waitstate[5],       "runin"         },
X	{ "_runout",    0,  &Info.i_waitstate[6],       "runout"        },
X	{ "_ipc",       0,  &Info.i_waitstate[7],       "ptrace"        },
X	{ "_u",         0,  &Info.i_waitstate[8],       "pause"         },
X	{ "_freemem",   0,  &Info.i_waitstate[9],       "freemm"        },
X	{ "_kernelmap", 0,  &Info.i_waitstate[10],      "kermap"        },
X	{ "_cwaiting",  0,  &Info.i_waitstate[11],      "cwait"         },
X# ifdef BSD42
X	{ "_selwait",   0,  &Info.i_waitstate[12],      "select"        },
X# endif BSD42
X# ifdef CHAOS
X	{ "_Chrfclist", 0,  &Info.i_waitstate[13],      "chrfc"         },
X# endif
X# ifndef SUN
X	{ "_rhpbuf",    0,  &Info.i_waitstate[14],      "rhpbuf"        },
X	{ "_rhtbuf",    0,  &Info.i_waitstate[15],      "rhtbuf"        },
X	{ "_ridcbuf",   0,  &Info.i_waitstate[16],      "ridcbf"        },
X	{ "_rikbuf",    0,  &Info.i_waitstate[17],      "rikbuf"        },
X	{ "_rmtbuf",    0,  &Info.i_waitstate[18],      "rmtbuf"        },
X	{ "_rrkbuf",    0,  &Info.i_waitstate[19],      "rrkbuf"        },
X	{ "_rrlbuf",    0,  &Info.i_waitstate[20],      "rrlbuf"        },
X	{ "_rrxbuf",    0,  &Info.i_waitstate[21],      "rrxbuf"        },
X	{ "_rswbuf",    0,  &Info.i_waitstate[22],      "rswbuf"        },
X	{ "_rtmbuf",    0,  &Info.i_waitstate[23],      "rtmbuf"        },
X	{ "_rtsbuf",    0,  &Info.i_waitstate[24],      "rtsbuf"        },
X	{ "_rudbuf",    0,  &Info.i_waitstate[25],      "rudbuf"        },
X	{ "_rupbuf",    0,  &Info.i_waitstate[26],      "rupbuf"        },
X	{ "_rutbuf",    0,  &Info.i_waitstate[27],      "rutbuf"        },
X	{ "_rvabuf",    0,  &Info.i_waitstate[28],      "rvabuf"        },
X	{ "_rvpbuf",    0,  &Info.i_waitstate[29],      "rvpbuf"        },
X	{ "_chtbuf",    0,  &Info.i_waitstate[30],      "chtbuf"        },
X	{ "_cmtbuf",    0,  &Info.i_waitstate[31],      "cmtbuf"        },
X	{ "_ctmbuf",    0,  &Info.i_waitstate[32],      "ctmbuf"        },
X	{ "_ctsbuf",    0,  &Info.i_waitstate[33],      "ctsbuf"        },
X	{ "_cutbuf",    0,  &Info.i_waitstate[34],      "cutbuf"        },
X# else
X	{ "_async_bufhead", 0,  &Info.i_waitstate[14],  "async"		},
X	{ "_desktops",	0,  &Info.i_waitstate[15],	"dtops"		},
X# endif SUN
X	{ (char*)0,     0,  (caddr_t*)0,                (char*)0        }
X} ;
END_OF_globals2.c
if test 5375 -ne `wc -c <globals2.c`; then
    echo shar: \"globals2.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f inittty.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"inittty.c\"
else
echo shar: Extracting \"inittty.c\" \(3572 characters\)
sed "s/^X//" >inittty.c <<'END_OF_inittty.c'
X# include       "sps.h"
X# include       <h/conf.h>
X# include       <h/ioctl.h>
X# include       <h/tty.h>
X# include       <sys/stat.h>
X# include       <stdio.h>
X
X/* INITTTY - Initialise the tty part of the info structure */
Xinittty ()
X{
X	register struct ttyline *lp ;
X# ifdef BSD42
X	register struct direct  *dp ;
X	DIR                     *dfd ;
X# else
X	struct direct           dir ;
X	FILE                    *dfd ;
X# endif
X	struct stat             statbuf ;
X	static char             filedev[] = FILE_DEV ;
X	extern struct info      Info ;
X	extern int              Flkmem ;
X# ifdef BSD42
X	DIR                     *opendir() ;
X	struct direct           *readdir() ;
X# else
X	FILE                    *fopen() ;
X# endif
X
X	lp = Info.i_ttyline ;
X# ifdef BSD42
X	if ( !(dfd = opendir( filedev )) )
X# else
X	if ( !(dfd = fopen( filedev, "r" )) )
X# endif
X		prexit( "Can't open %s\n", filedev ) ;
X	if ( chdir( filedev ) < 0 )
X		prexit( "sps - Can't chdir to %s\n", filedev ) ;
X# ifdef BSD42
X	/* Read all entries in the device directory, looking for ttys */
X	while ( dp = readdir( dfd ) )
X	{       /* Skip entries that do not match "tty" or "console" */
X		if ( strncmp( "tty", dp->d_name, 3 )
X		&&   strcmp( "console", dp->d_name ) )
X			continue ;
X		/* Skip "tty" itself */
X		if ( dp->d_namlen == 3 )
X			continue ;
X# ifdef CHAOS
X		/* Skip chaos ttys ; they are accessed during ttystatus() */
X		if ( dp->d_namelen > 3 &&
X		dp->d_name[ sizeof( "tty" ) - 1 ] == 'C' )
X			continue ;
X# endif
X		if ( lp >= &Info.i_ttyline[ MAXTTYS ] )
X			prexit( "sps - Too many ttys in %s\n", filedev ) ;
X		/* Copy the tty name into the information entry */
X		if ( !strcmp( dp->d_name, "console" ) )
X		{
X			lp->l_name[0] = 'c' ;
X			lp->l_name[1] = 'o' ;
X		}
X		else
X		{
X			lp->l_name[0] = dp->d_name[3] ;
X			lp->l_name[1] = dp->d_name[4] ;
X		}
X		/* Ensure that this tty is actually a valid character device */
X		if ( stat( dp->d_name, &statbuf ) < 0 )
X			continue ;
X# else
X	/* Read all entries in the device directory, looking for ttys */
X	while ( fread( (char*)&dir, sizeof( struct direct ), 1, dfd ) == 1 )
X	{       /* Skip entries that do not match "tty" or "console" */
X		if ( strncmp( "tty", dir.d_name, 3 )
X		&&   strcmp( "console", dir.d_name ) )
X			continue ;
X		/* Skip "tty" itself */
X		if ( dir.d_name[3] == '\0' )
X			continue ;
X# ifdef CHAOS
X		/* Skip chaos ttys ; they are accessed during ttystatus() */
X		if ( dir.d_name[ sizeof( "tty" ) - 1 ] == 'C' )
X			continue ;
X# endif
X		if ( lp >= &Info.i_ttyline[ MAXTTYS ] )
X			prexit( "sps - Too many ttys in %s\n", filedev ) ;
X		/* Copy the tty name into the information entry */
X		if ( !strcmp( dir.d_name, "console" ) )
X		{
X			lp->l_name[0] = 'c' ;
X			lp->l_name[1] = 'o' ;
X		}
X		else
X		{
X			lp->l_name[0] = dir.d_name[3] ;
X			lp->l_name[1] = dir.d_name[4] ;
X		}
X		/* Ensure that this tty is actually a valid character device */
X		if ( stat( dir.d_name, &statbuf ) < 0 )
X			continue ;
X# endif
X		if ( (statbuf.st_mode & S_IFMT) != S_IFCHR )
X			continue ;
X		/* Find the device # of the tty and the address of its
X		   associated struct tty in /dev/kmem. */
X		lp->l_dev = statbuf.st_rdev ;
X		memseek( Flkmem,
X		     (long)&Info.i_cdevsw[ major( statbuf.st_rdev ) ].d_ttys ) ;
X		if ( read( Flkmem, (char*)&lp->l_addr, sizeof( lp->l_addr ) )
X		!= sizeof( lp->l_addr ) )
X		{
X			fprintf( stderr, "sps - Can't read struct tty for %s\n",
X# ifdef BSD42
X				dp->d_name ) ;
X# else
X				dir.d_name ) ;
X# endif
X			continue ;
X		}
X		lp->l_addr += (int)minor( statbuf.st_rdev ) ;
X		lp++ ;
X	}
X# ifdef BSD42
X	(void)closedir( dfd ) ;
X# else
X	(void)fclose( dfd ) ;
X# endif
X}
END_OF_inittty.c
if test 3572 -ne `wc -c <inittty.c`; then
    echo shar: \"inittty.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f needed.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"needed.c\"
else
echo shar: Extracting \"needed.c\" \(4455 characters\)
sed "s/^X//" >needed.c <<'END_OF_needed.c'
X# include       "sps.h"
X# include       "flags.h"
X# include       <h/text.h>
X# include       <stdio.h>
X
X/*
X** NEEDED - Determine which processes are needed for the printout
X** and add these to a list of needed processes.
X*/
Xstruct process  *needed ( process, text )
X
Xregister struct process         *process ;
Xstruct text                     *text ;
X
X{
X	register struct process *p ;
X	register struct process *plist ;
X	struct process          *lastp ;
X	int                     uid ;
X	extern struct flags     Flg ;
X	extern union userstate  User ;
X	extern struct info      Info ;
X	extern struct ttyline   Notty ;
X	struct ttyline          *findtty() ;
X	char                    *getcmd() ;
X
X	plist = (struct process*)0 ;
X	lastp = &process[ Info.i_nproc ] ;
X	/* Normalise internal pointers from kernel addresses. For each kmem
X	   address in the `proc' and `text' structures, we convert that
X	   address for our own internal use. */
X	for ( p = process ; p < lastp ; p++ )
X	{                               
X		if ( !p->pr_p.p_stat )  
X			continue ;
X		/* Normalise internal text pointers */
X		if ( p->pr_p.p_textp )
X			p->pr_p.p_textp = &text[p->pr_p.p_textp - Info.i_text0];
X		/* Normalise internal linked list of processes */
X		p->pr_plink = p->pr_p.p_link ?
X			&process[ p->pr_p.p_link  - Info.i_proc0 ] :
X			(struct process*)0 ;
X		/* Normalise internal parent pointers */
X		p->pr_pptr = p->pr_p.p_pptr ?
X			&process[ p->pr_p.p_pptr - Info.i_proc0 ] :
X			(struct process*)0 ;
X		/* Check for valid parent pointers */
X		if ( !p->pr_pptr )
X		{
X			p->pr_pptr = process ;
X			continue ;
X		}
X		if ( p->pr_pptr < process || p->pr_pptr >= lastp )
X		{
X			fprintf( stderr, "sps - process %d has bad pptr\n",
X				p->pr_p.p_pid ) ;
X			p->pr_pptr = process ;
X		}
X	}
X	/* For each process, see if it is a candidate for selection.
X	   If so, retrieve its command arguments and upage information. */
X	uid = getuid() ;
X	for ( p = process ; p < lastp ; p++ )
X	{                               
X		if ( !p->pr_p.p_stat )
X			continue ;
X		/* Count processes and sizes */
X		summarise( p ) ;
X		/* Select the given processes. Bear in mind that selection
X		   of processes based on the `F' and `T' flags must be
X		   postponed until the upage is accessed. */
X		if ( !Flg.flg_F && !Flg.flg_T && !selectproc( p, process, uid ))
X			continue ;
X		/* Try to find the process' command arguments. Accessing the
X		   arguments also involves retrieving the upage. */
X		p->pr_cmd = getcmd( p ) ;
X		/* If the upage was found successfully, use this information */
X		if ( p->pr_upag )       
X		{
X# ifdef BSD42
X			p->pr_rself = User.u_us.u_ru ;
X			p->pr_rchild = User.u_us.u_cru ;
X# else
X			p->pr_vself = User.u_us.u_vm ;
X			p->pr_vchild = User.u_us.u_cvm ;
X# endif
X			p->pr_tty = findtty( p ) ;
X			p->pr_files = filecount() ;
X		}
X		else
X			p->pr_tty = &Notty ;
X		/* Select on the basis of the `F' and `T' flags */
X		if ( Flg.flg_F          
X		&& !(p->pr_p.p_pgrp && p->pr_p.p_pgrp == p->pr_tty->l_pgrp) )
X			continue ;
X		if ( Flg.flg_T && !selecttty( p ) )
X			continue ;
X		/* Arrive here with a selected process. Add this to the
X		   linked list of needed processes. */
X		p->pr_plink = plist ;   
X		plist = p ;
X		p->pr_child = (struct process*)0 ;
X		p->pr_sibling = (struct process*)0 ;
X	}
X	return ( plist ) ;
X}
X
X/* SUMMARISE - Summarises the given process into the `Summary' structure */
X/*
X** SHOULD ACCOUNT HERE FOR THE SIZE OF LOADED PAGE TABLES, BUT WE DON'T REALLY
X** KNOW THEIR RESIDENT SIZES.
X*/
Xsummarise ( p )
X
Xregister struct process         *p ;
X
X{
X	register struct text    *tp ;
X	int                     busy ;
X	extern struct summary   Summary ;
X
X	Summary.sm_ntotal++ ;
X	if ( p->pr_p.p_stat == SZOMB )
X		return ;
X	/* Firstly, account for processes */
X	Summary.sm_ktotal += p->pr_p.p_dsize + p->pr_p.p_ssize ;
X	Summary.sm_kloaded += p->pr_p.p_rssize ;
X	Summary.sm_kswapped += p->pr_p.p_swrss ;
X	if ( p->pr_p.p_flag & SLOAD )
X		Summary.sm_nloaded++ ;
X	else
X		Summary.sm_nswapped++ ;
X	busy = (p->pr_p.p_stat == SRUN) || (p->pr_p.p_stat==SSLEEP
X	     && (p->pr_p.p_pri<PZERO && p->pr_p.p_pid > MSPID) ) ;
X	if ( busy )
X	{
X		Summary.sm_nbusy++ ;
X		Summary.sm_kbusy += p->pr_p.p_dsize + p->pr_p.p_ssize ;
X	}
X	/* Now account for their texts */
X	if ( !(tp = p->pr_p.p_textp) || !tp->x_count )
X		return ;                
X	Summary.sm_ktotal += tp->x_size ;
X	Summary.sm_kloaded += tp->x_rssize ;
X	Summary.sm_kswapped += tp->x_swrss ;
X	if ( busy )
X		Summary.sm_kbusy += tp->x_size ;
X	tp->x_count = 0 ;
X}
END_OF_needed.c
if test 4455 -ne `wc -c <needed.c`; then
    echo shar: \"needed.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f printproc.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"printproc.c\"
else
echo shar: Extracting \"printproc.c\" \(5849 characters\)
sed "s/^X//" >printproc.c <<'END_OF_printproc.c'
X# include       "sps.h"
X# include       "flags.h"
X# include       <h/text.h>
X
X/* PRINTPROC - Pretty print a process according to the switches. */
Xprintproc ( p, md )
X
Xregister struct process         *p ;            
Xint                             md ;            
X
X{
X	register char           *chp ;
X	register struct text    *tp ;
X	register struct hashtab *hp ;
X	char                    chbuf[10] ;
X	time_t                  time ;
X	time_t                  chtime ;
X# ifdef BSD42
X	time_t                  utime ;
X	time_t                  uchtime ;
X# endif
X	extern short            Lastuid, Lastpgrp ;
X	extern struct flags     Flg ;
X	char                    *waitingfor() ;
X	struct hashtab          *hashuid() ;
X	double                  percentmem() ;
X
X	/* List tty name and foreground/background/detached information */
X	printf( "%2.2s%c", p->pr_tty->l_name,
X		!p->pr_p.p_pgrp ? ' ' :
X# ifdef SDETACH
X		p->pr_p.p_flag & SDETACH ? '_' :
X# endif
X		p->pr_p.p_pgrp == p->pr_tty->l_pgrp ? '.' : ' ' ) ;
X	hp = hashuid( (int)p->pr_p.p_uid ) ;
X	if ( !md  )                             
X	{       /* If a top-level process, list the user name */
X		if ( hp )
X			printf( "%-8.8s ", hp->h_uname ) ;
X		else
X			printf( "user%-4.4d ", p->pr_p.p_uid ) ;
X	}
X	else                                    
X	{       /* Usually list an asterisk for a child process */
X		md = md > 8 ? 8 : md ;
X		printf( "%*s%c", md, "",
X			p->pr_p.p_pgrp == Lastpgrp ? '|' : '*' ) ;      
X		/* But beware of setuid processes */
X		md = 8 - md ;
X		if ( p->pr_p.p_uid == Lastuid )
X			printf( "%-*.*s", md, md, "" ) ;
X		else if ( hp )
X			printf( "%-*.*s", md, md, hp->h_uname ) ;
X		else
X		{
X			md -= 4 ;
X			printf( "user%-*.*d", md, md, p->pr_p.p_uid ) ;
X		}
X	}
X	Lastuid = p->pr_p.p_uid ;
X	Lastpgrp = p->pr_p.p_pgrp ;
X	if ( Flg.flg_d )                        
X	{       /* List disc I/O and paging information */
X		if ( !p->pr_upag || p->pr_p.p_stat == SZOMB )
X		{
X			prcmd( p, 49, -63 ) ;
X			return ;
X		}
X		printf( "%2d %8d+%8d %4d %8d %8D ",
X			p->pr_files,
X# ifdef BSD42
X			p->pr_rself.ru_majflt,
X			p->pr_rself.ru_minflt,
X			p->pr_rself.ru_nswap,
X			p->pr_rself.ru_inblock + p->pr_rself.ru_oublock,
X			KBYTES( p->pr_rself.ru_idrss + p->pr_rself.ru_isrss
X				+ p->pr_rself.ru_ixrss ) ) ;
X# else
X			p->pr_vself.vm_majflt,
X			p->pr_vself.vm_minflt,
X			p->pr_vself.vm_nswap,
X			p->pr_vself.vm_inblk + p->pr_vself.vm_oublk,
X			KBYTES( (p->pr_vself.vm_idsrss
X				+ p->pr_vself.vm_ixrss) / Info.i_hz ) ) ;
X# endif
X		prcmd( p, 5, -63 ) ;
X		return ;
X	}
X	if ( !Flg.flg_v )                       
X	{       /* Not verbose so just list command arguments */
X		prcmd( p, 5, -19 ) ;
X		return ;
X	}
X	/* Arrive here if being verbose ; list cpu information */
X	switch ( p->pr_p.p_stat )               
X	{                                       
X		case SSLEEP :
X		case SWAIT :
X		case SIDL :
X			/* Determine why a process should be in a wait state */
X			chp = waitingfor( p ) ;
X			break ;
X		case SRUN :
X			chp = "run" ;
X			break ;
X		case SZOMB :
X			chp = "exit" ;
X			break ;
X		case SSTOP :
X			chp = "stop" ;
X			break ;
X	}
X	/* If the process is loaded, list the status information in capitals */
X	printf( "%-6.6s ", p->pr_p.p_flag & SLOAD ?
X		(capitals( chp, chbuf ), chbuf) : chp ) ;
X	/* List process flags */
X	printf( "%c%c%c", p->pr_p.p_flag & SSYS ? 'U' :
X		p->pr_p.p_flag & STRC ? 'T' : ' ',
X		p->pr_p.p_flag & SVFORK ? 'V' :
X		p->pr_p.p_flag & SPHYSIO ? 'I' : ' ',
X		p->pr_p.p_flag & SUANOM ? 'A' : ' ' ) ;
X	/* List process niceness */
X	if ( p->pr_p.p_nice != NZERO )          
X		printf( "%3d ", p->pr_p.p_nice - NZERO ) ;
X	else
X		printf( "    " ) ;
X	if ( p->pr_p.p_stat == SZOMB )
X	{
X		prcmd( p, 41, -69 ) ;
X		return ;
X	}                                       
X	/* List process and text virtual sizes */
X	printf( "%4d", KBYTES( p->pr_p.p_dsize + p->pr_p.p_ssize ) ) ;
X	if ( tp = p->pr_p.p_textp )
X		printf( "+%3d ", KBYTES( tp->x_size ) ) ;
X	else
X		printf( "     " ) ;
X	/* List process and text real sizes */
X	printf( "%4d", KBYTES( p->pr_p.p_rssize ) ) ;
X	if ( tp )
X		printf( "+%3d %2.0f ", KBYTES( tp->x_rssize ),
X			percentmem( p ) );
X	else
X		printf( "        " ) ;
X	/* List information obtained from the upage. This includes the process
X	   times and command arguments. */
X	if ( !p->pr_upag )
X	{
X		prcmd( p, 20, -69 ) ;
X		return ;
X	}                                       
X	/* List process time information */
X# ifdef BSD42
X	time   = Flg.flg_q ? p->pr_rself.ru_utime.tv_sec :
X		 p->pr_rself.ru_utime.tv_sec + p->pr_rself.ru_stime.tv_sec ;
X	utime  = Flg.flg_q ? p->pr_rself.ru_utime.tv_usec :
X		 p->pr_rself.ru_utime.tv_usec + p->pr_rself.ru_stime.tv_usec ;
X	chtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_sec :
X		 p->pr_rchild.ru_utime.tv_sec + p->pr_rchild.ru_stime.tv_sec ;
X	uchtime = Flg.flg_q ? p->pr_rchild.ru_utime.tv_usec :
X		 p->pr_rchild.ru_utime.tv_usec + p->pr_rchild.ru_stime.tv_usec ;
X	prcpu( time, utime ) ;
X	if ( chtime != 0L )
X	{
X		printf( "+" ) ;
X		prcpu( chtime, uchtime ) ;
X	}
X# else
X	time   = Flg.flg_q ? p->pr_vself.vm_utime :
X		 p->pr_vself.vm_utime + p->pr_vself.vm_stime ;
X	chtime = Flg.flg_q ? p->pr_vchild.vm_utime :
X		 p->pr_vchild.vm_utime + p->pr_vchild.vm_stime ;
X	prcpu( time ) ;
X	if ( chtime != 0L )
X	{
X		printf( "+" ) ;
X		prcpu( chtime ) ;
X	}
X# endif
X	else
X		printf( "      " ) ;
X# ifdef BSD42
X	if ( time || utime )
X# else
X	if ( time )
X# endif
X# ifdef SUN
X		printf( " %2.0f ", (double)p->pr_p.p_pctcpu ) ;
X# else
X		printf( " %2.0f ", p->pr_p.p_pctcpu * 100.0 ) ;
X# endif
X	else
X		printf( "    " ) ;
X	/* Finally, list the process command arguments. */
X	prcmd( p, 5, -69 ) ;                    
X}
X
X/* CAPITALS - Converts letters in `chp' to upper-case in buffer `buf'. */
Xcapitals ( chp, buf )
X
Xregister char                   *chp ;
Xregister char                   *buf ;
X
X{
X	while ( *buf = *chp++ )
X	{
X		if ( 'a' <= *buf && *buf <= 'z' )
X			*buf -= 'a' - 'A' ;
X		buf++ ;
X	}
X}
END_OF_printproc.c
if test 5849 -ne `wc -c <printproc.c`; then
    echo shar: \"printproc.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sps.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sps.h\"
else
echo shar: Extracting \"sps.h\" \(5295 characters\)
sed "s/^X//" >sps.h <<'END_OF_sps.h'
X# include	<h/param.h>
X# include	<h/dir.h>
X# include	<h/user.h>
X# include	<h/proc.h>
X
X/*
X** Maximum # of users to be considered. (Should probably be
X** approximately double the # of users in /etc/passwd.)
X*/
X# define	MAXUSERID	100
X/* Maximum # ttys to be considered ... */
X# define	MAXTTYS		65
X/* Maximum user name length ... */
X# define	UNAMELEN	8
X/* Maximum process-id not to be considered busy ... */
X# define	MSPID		2
X/* # of wait states defined in the `struct info' ... */
X# ifdef SUN
X# define	NWAITSTATE	16
X# else
X# define	NWAITSTATE	35
X# endif
X
X/* Convert clicks to kbytes ... */
X# ifdef SUN
X# define	KBYTES( size )	((size) << 1)
X# else
X# define	KBYTES( size )	((size) >> (10 - PGSHIFT))
X# endif
X
X/* Standard files to be examined ... */
X# define	FILE_MEM	"/dev/mem"	/* System physical memory */
X# define	FILE_KMEM	"/dev/kmem"	/* Kernel virtual memory */
X# define	FILE_SWAP	"/dev/drum"	/* Swap/paging device */
X# define	FILE_DEV	"/dev"		/* Directory of tty entries */
X# define	FILE_SYMBOL	"/vmunix"	/* Symbol file for nlist() */
X# define	FILE_INFO	"/etc/spsinfo"	/* Sps information file */
X# define	FILE_PASSWD	"/etc/passwd"	/* User database */
X
X/* Structure to hold necessary information concerning a tty ... */
Xstruct ttyline
X{
X	struct tty		*l_addr ;	/* Ptr to tty struct in kmem */
X	unsigned short		l_pgrp ;	/* Tty process group */
X	char			l_name[2] ;	/* Tty character name */
X	dev_t			l_dev ;		/* Tty device # */
X} ;
X
X/* Structure holding a single hash table entry ... */
Xstruct hashtab
X{
X	short			h_uid ;		/* Uid of user entry */
X	char			h_uname[ UNAMELEN ] ; /* Corresponding name */
X} ;
X
X/*
X** Format of the standard information file maintained by sps.
X** This structure is filled in at initialisation time and then is read back
X** in whenever sps is invoked.
X** Note that the pointer variables in this structure refer to
X** kernel virtual addresses, not addresses within sps.
X** These variable are typed as such so that pointer arithmetic
X** on the kernel addresses will work correctly.
X*/
Xstruct info
X{	/* Kernel values determining process, tty and upage info ... */
X	struct proc		*i_proc0 ;	/* address of process table */
X	int			i_nproc ;	/* length of process table */
X	struct text		*i_text0 ;	/* address of text table */
X	int			i_ntext ;	/* length of text table */
X	struct inode		*i_inode0 ;	/* address of inode table */
X	int			i_ninode ;	/* length of inode table */
X	struct buf		*i_swbuf0 ;	/* address of swap buffers */
X	int			i_nswbuf ;	/* # swap buffers */
X	struct buf		*i_buf0 ;	/* address of i/o buffers */
X	int			i_nbuf ;	/* # i/o buffers */
X	int			i_ecmx ;	/* max physical memory address*/
X	struct pte		*i_usrptmap ;	/* page table map */
X	struct pte		*i_usrpt ;	/* page table map */
X	struct cdevsw		*i_cdevsw ;	/* device switch to find ttys */
X# ifdef BSD42
X	struct quota		*i_quota0 ;	/* disc quota structures */
X	int			i_nquota ;	/* # quota structures */
X	int			i_dmmin ;	/* The start of the disc map */
X	int			i_dmmax ;	/* The end of the disc map */
X	struct mbuf		*i_mbutl ;	/* Start of mbuf area */
X# else
X	int			i_hz ;		/* Clock rate */
X# endif
X# ifdef CHAOS
X	caddr_t			i_Chconntab ;	/* Chaos connection table */
X# endif
X	/* Kernel addresses are associated with process wait states ... */
X	caddr_t			i_waitstate[ NWAITSTATE ] ;
X	/* User names, stored in a hash table ... */
X	struct hashtab		i_hnames[ MAXUSERID ] ;
X	/* Tty device info ... */
X	struct ttyline		i_ttyline[ MAXTTYS ] ;
X} ;
X
X/*
X** The symbol structure cross-references values read from the kernel with
X** their place in the info structure, and if such a value is associated with
X** a process wait state or not.
X*/
Xstruct symbol
X{
X	char			*s_kname ;	/* Kernel symbol name */
X	char			s_indirect ;	/* Value requires indirection */
X	caddr_t			*s_info ;	/* Corresponding info address */
X	char			*s_wait ;	/* Reason for wait, if any */
X} ;
X
X/* The `user' structure obtained from /dev/mem or /dev/swap ... */
Xunion userstate
X{
X	struct user		u_us ;
X	char			u_pg[ UPAGES ][ NBPG ] ;
X} ;
X
X/* Information concerning each process filled from /dev/kmem ... */
Xstruct process
X{
X	struct proc		pr_p ;		/* struct proc from /dev/kmem */
X	struct process		*pr_plink ;	/* Normalised ptrs from above */
X	struct process		*pr_sibling ;	/* Ptr to sibling process */
X	struct process		*pr_child ;	/* Ptr to child process */
X	struct process		*pr_pptr ;	/* Ptr to parent process */
X# ifdef BSD42
X	struct rusage		pr_rself ;	/* Read from upage for self */
X	struct rusage		pr_rchild ;	/* ... and the children */
X# else
X	struct vtimes		pr_vself ;	/* Read from upage for self */
X	struct vtimes		pr_vchild ;	/* ... and the children */
X# endif
X	int			pr_files ;	/* # open files */
X	struct ttyline		*pr_tty ;	/* Associated tty information */
X	char			*pr_cmd ;	/* Command args, from upage */
X	int			pr_upag:1 ;	/* Upage was obtained */
X	int			pr_csaved:1 ;	/* Cmd args saved by malloc() */
X} ;
X
X/* Structure to hold summarising information ... */
Xstruct summary
X{
X	long			sm_ntotal ;	/* Total # processes */
X	long			sm_ktotal ;	/* Total virtual memory */
X	long			sm_nbusy ;	/* # busy processes */
X	long			sm_kbusy ;	/* Busy virtual memory */
X	long			sm_nloaded ;	/* # loaded processes */
X	long			sm_kloaded ;	/* Active resident memory */
X	long			sm_nswapped ;	/* # swapped processes */
X	long			sm_kswapped ;	/* Size totally swapped out */
X} ;
END_OF_sps.h
if test 5295 -ne `wc -c <sps.h`; then
    echo shar: \"sps.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f waitingfor.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"waitingfor.c\"
else
echo shar: Extracting \"waitingfor.c\" \(6584 characters\)
sed "s/^X//" >waitingfor.c <<'END_OF_waitingfor.c'
X# include       "sps.h"
X# include       <h/text.h>
X# ifdef NFS
X# include       <h/vnode.h>
X# include       <ufs/inode.h>
X# else
X# include       <h/inode.h>
X# endif NFS
X# include       <h/ioctl.h>
X# include       <h/tty.h>
X# include       <h/buf.h>
X# ifdef BSD42
X# ifndef NFS
X# include       <h/quota.h>
X# endif NFS
X# include       <h/mbuf.h>
X# include       <h/socket.h>
X# include       <h/socketvar.h>
X# endif BSD42
X
X/* 1 if `w' is in the address range defined by `a1' and `a2' ... */
X# define        INRANGE( w, a1, a2 ) \
X			( (caddr_t)(a1) <= (w) && (w) < (caddr_t)(a2) )
X
X/* NFS changes incorporated by Alexander Dupuy <dupuy@amsterdam.columbia.edu> */
X
X/* WAITINGFOR - Determine what a process is waiting for and describe it. */
Xchar    *waitingfor ( p )
X
Xstruct process                  *p ;
X
X{
X	register caddr_t        w ;
X	register struct ttyline *lp ;
X	register struct symbol  *s ;
X	register char           *cp ;
X# ifdef BSD42
X	struct socket           sc ;
X# endif
X	int			rc ;
X	static char             wbuf[ 8 ] ;
X	extern struct info      Info ;
X	extern struct symbol    Symbollist[] ;
X	char                    *sprintf() ;
X
X	w = p->pr_p.p_wchan ;
X	if ( !w )
X		return ( "null" ) ;
X	/* Waiting for a child process, alternatively in a vfork() ? */
X	if ( INRANGE( w, Info.i_proc0, &Info.i_proc0[ Info.i_nproc ] ) )
X		return ( p->pr_p.p_flag & SNOVM ? "vfork" : "child" ) ;
X	/* Waiting for a page to be brought in ? */
X	if ( INRANGE( w, Info.i_swbuf0, &Info.i_swbuf0[ Info.i_nswbuf ] ) )
X		return ( "swap" ) ;
X	/* Waiting for discio through a block device to complete ? */
X	if ( INRANGE( w, Info.i_buf0, &Info.i_buf0[ Info.i_nbuf ] ) )
X		/* SHOULD ACTUALLY READ AS "blkio" BUT "discio" IS WHAT
X		   IS GENERALLY MEANT HERE. */
X		return ( "discio" ) ;
X	/* Waiting for a text page to be brought in ? */
X	if ( INRANGE( w, Info.i_text0, &Info.i_text0[ Info.i_ntext ] ) )
X		return ( "swtext" ) ;
X# ifdef BSD42
X# ifndef NFS
X	/* Waiting for an event associated with the quota system ? */
X	if ( INRANGE( w, Info.i_quota0, &Info.i_quota0[ Info.i_nquota ] ) )
X		return ( "quota" ) ;
X# endif NFS
X# endif BSD42
X	/* Waiting for tty I/O ? If so, find which tty it is */
X	for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
X		if ( INRANGE( w, &lp->l_addr[0], &lp->l_addr[1] ) )
X		{
X			switch ( (int)w - (int)lp->l_addr )
X			{
X				case (int)&((struct tty*)0)->t_rawq :
X					/* Read from a tty or slave pty */
X					cp = "rtty??" ;
X					break ;
X				case (int)&((struct tty*)0)->t_outq :
X					/* Write to a tty or slave pty */
X					cp = "wtty??" ;
X					break ;
X				case (int)&((struct tty*)0)->t_state :
X					/* Tty not open */
X					cp = "otty??" ;
X					break ;
X				case (int)&((struct tty*)0)->t_outq.c_cf :
X					/* Read from a controller pty */
X					cp = "rpty??" ;
X					break ;
X				case (int)&((struct tty*)0)->t_rawq.c_cf :
X					/* Write to a controller pty */
X					cp = "wpty??" ;
X					break ;
X				default :
X					cp = "?tty??" ;
X					break ;
X			}
X			cp[4] = lp->l_name[0] ;
X			cp[5] = lp->l_name[1] ;
X			return ( cp ) ;
X		}
X	/* Waiting for an inode ? */
X	if ( INRANGE( w, Info.i_inode0, &Info.i_inode0[ Info.i_ninode ] ) )
X		switch ( ((int)w - (int)Info.i_inode0) % sizeof( struct inode ))
X		{
X# ifdef BSD42
X# ifndef NFS
X			case (int)&((struct inode*)0)->i_exlockc :
X				/* Exclusive lock on this inode */
X				return ( "exlock" ) ;
X			case (int)&((struct inode*)0)->i_shlockc :
X				/* Shared lock on this inode */
X				return ( "shlock" ) ;
X# endif NFS
X# else
X			case 1 :
X				return ( "wpipe" ) ;
X			case 2 :
X				return ( "rpipe" ) ;
X			case (int)&((struct inode*)0)->i_un.i_group.g_datq :
X				return ( "rmux" ) ;
X# endif BSD42
X			default :
X				/* Inode probably locked */
X				return ( "inode" ) ;
X		}
X# ifdef BSD42
X	/* Waiting for a structure inside an mbuf ? If so, try to find why */
X	if ( INRANGE( w, Info.i_mbutl,
X	&Info.i_mbutl[ NMBCLUSTERS * CLBYTES / sizeof( struct mbuf ) ] ) )
X		switch ( ((int)w - (int)Info.i_mbutl) % sizeof( struct mbuf )
X			- (int)&((struct mbuf*)0)->m_dat[0] )
X		{
X			case (int)&((struct socket*)0)->so_timeo :
X				/* Socket timeout event - Guess why */
X				rc = getsocket( (struct socket*)(w
X				    - (int)&((struct socket*)0)->so_timeo),
X						&sc ) ;
X				return ( rc && (sc.so_state & SS_ISCONNECTING)
X					? "connct" 
X					: rc && ((sc.so_options & SO_ACCEPTCONN)
X					  && !sc.so_qlen)
X					? "accept" : "socket" ) ;
X			case (int)&((struct socket*)0)->so_rcv.sb_cc :
X				/* Read from an empty socket. Here we actually
X				   attempt to determine whether the socket
X				   structure in question really does refer to
X				   a socket, or whether it is in fact a pipe
X				   in disguise. */
X				return ( getsocket( (struct socket*)(w
X				    - (int)&((struct socket*)0)->so_rcv.sb_cc),
X						&sc )
X					&& sc.so_type == SOCK_STREAM
X#ifdef BSD43
X					&& ((sc.so_state
X					    & (SS_ISCONNECTED|SS_CANTSENDMORE))
X					    == (SS_ISCONNECTED|SS_CANTSENDMORE))
X#else
X					&& !sc.so_rcv.sb_hiwat
X					&& !sc.so_rcv.sb_mbmax
X					&& (sc.so_state
X					    & (SS_ISCONNECTED|SS_CANTRCVMORE))
X#endif BSD43
X					? "rpipe" : "rsockt" ) ;
X			case (int)&((struct socket*)0)->so_snd.sb_cc :
X				/* Write to a full socket. Again, we try
X				   to determine whether or not this is a
X				   real socket or a pipe. */
X				return ( getsocket( (struct socket*)(w
X				    - (int)&((struct socket*)0)->so_snd.sb_cc),
X						&sc )
X#ifdef BSD43
X					&& sc.so_type == SOCK_STREAM
X					&& ((sc.so_state
X					    & (SS_ISCONNECTED|SS_CANTRCVMORE))
X					    == (SS_ISCONNECTED|SS_CANTRCVMORE))
X#else
X					&& sc.so_rcv.sb_hiwat == 2048
X					&& sc.so_rcv.sb_mbmax == 4096
X					&& (sc.so_state
X					    & (SS_ISCONNECTED|SS_CANTSENDMORE))
X#endif BSD43
X					? "wpipe" : "wsockt" ) ;
X			default :
X				/* Other mbuf event */
X				return ( "mbuf" ) ;
X		}
X# endif BSD42
X	/* Look in the symbol table for known wait addresses. */
X	for ( s = Symbollist ; s->s_kname ; s++ )
X		if ( s->s_wait && w == *s->s_info )
X			return ( s->s_wait ) ;  
X	/* No reason for the wait state has been found.
X	   Return the wait channel as a hexadecimal address. */
X# ifdef SUN
X	(void)sprintf( wbuf, "x%05x", w ) ;
X# else
X	(void)sprintf( wbuf, "x%05x", w - 0x80000000 ) ;
X# endif SUN
X	return ( wbuf ) ;
X}
X
X# ifdef BSD42
X/*
X** GETSOCKET - Reads a `struct socket' from the kernel virtual memory address
X** identified by `ks' into the buffer `s'.
X*/
Xgetsocket ( ks, s )
X
Xstruct socket                   *ks ;
Xstruct socket                   *s ;
X
X{
X	extern int              Flkmem ;
X
X	memseek( Flkmem, (long)ks ) ;
X	return ( read( Flkmem, (char*)s, sizeof( struct socket ) )
X		== sizeof( struct socket ) ) ;
X}
X# endif BSD42
END_OF_waitingfor.c
if test 6584 -ne `wc -c <waitingfor.c`; then
    echo shar: \"waitingfor.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 

Rich $alz			"Anger is an energy"
Cronus Project, BBN Labs	rsalz@bbn.com
Moderator, comp.sources.unix	sources@uunet.uu.net