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