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