v23i048: SPS, a PS replacement, Part02/04

Rich Salz rsalz at bbn.com
Tue Nov 27 06:05:40 AEST 1990


Submitted-by: Robert Ward <olsen!robert at uunet.uu.net>
Posting-number: Volume 23, Issue 48
Archive-name: sps2/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents:  flagdecode.c flags.h getupage.c globals2.c inittty.c
#   main.c needed.c openfiles.c sps.h stream.c
# Wrapped by rsalz at papaya.bbn.com on Mon Nov 26 14:03:22 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 2 (of 4)."'
if test -f 'flagdecode.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flagdecode.c'\"
else
  echo shar: Extracting \"'flagdecode.c'\" \(5627 characters\)
  sed "s/^X//" >'flagdecode.c' <<'END_OF_FILE'
X# ifndef lint
Xstatic char SccsId[] =  "@(#)flagdecode.c	1.1\t10/1/88" ;
X# endif
X
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 [ -dcefgijkoqrsvwyABFNPSTUWZ ][ 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 'c' :
X				case 'C' :
X					/* Print stored command, not args */
X					Flg.flg_c = 1 ;
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_FILE
  if test 5627 -ne `wc -c <'flagdecode.c'`; then
    echo shar: \"'flagdecode.c'\" unpacked with wrong size!
  fi
  # end of 'flagdecode.c'
fi
if test -f 'flags.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'flags.h'\"
else
  echo shar: Extracting \"'flags.h'\" \(2638 characters\)
  sed "s/^X//" >'flags.h' <<'END_OF_FILE'
X# ifndef lint
Xstatic char FlagsHId[] =  "@(#)flags.h	1.1\t10/1/88" ;
X# endif
X
X/* Structure holding information specified in the option list ... */
Xunion flaglist
X{
X	char                    *f_chp ;        /* Option specified as string */
X	int                     f_uid ;         /* Numerical user id */
X	int                     f_pid ;         /* Numerical process id */
X	struct ttyline          *f_ttyline ;    /* Specified tty */
X} ;
X
X/* Structure holding global information specifed by arg list options ... */
Xstruct flags
X{
X	int                     flg_c:1 ;       /* print command from upage */
X	int                     flg_d:1 ;       /* disc orientated output */
X	int                     flg_e:1 ;       /* print environment string */
X	int                     flg_f:1 ;       /* print process father # */
X	int                     flg_g:1 ;       /* print process group # */
X	int                     flg_i:1 ;       /* initialise sps */
X	char                    *flg_j ;        /* Use this as the info file */
X	char                    *flg_k ;        /* Use this as the {k}mem file*/
X	int                     flg_o:1 ;       /* avoid the swap device */
X	int                     flg_q:1 ;       /* show user time only */
X	int                     flg_r:1 ;       /* repeat output */
X	unsigned                flg_rdelay ;    /* ... with this much delay */
X	char                    *flg_s ;        /* Use this as the symbol file*/
X	int                     flg_v:1 ;       /* print verbose listing */
X	int                     flg_w:1 ;       /* print wide output */
X	int                     flg_y:1 ;       /* print tty information */
X	int                     flg_A:1 ;       /* print all processes */
X	int                     flg_B:1 ;       /* print busy processes */
X	int                     flg_F:1 ;       /* print foreground processes */
X	int                     flg_N:1 ;       /* print no processes */
X	int                     flg_P:1 ;       /* print specified process #'s*/
X	int                     flg_S:1 ;       /* print stopped processes */
X	int                     flg_T:1 ;       /* print procs for given ttys */
X	int                     flg_U:1 ;       /* print procs for given users*/
X	int                     flg_W:1 ;       /* print waiting processes */
X	int                     flg_Z:1 ;       /* print zombie processes */
X	int                     flg_AZ:1 ;      /* One of A to Z was specified*/
X	union flaglist          *flg_Plist ;    /* List of specified processes*/
X	union flaglist          *flg_Tlist ;    /* List of specified ttys */
X	union flaglist          *flg_Ulist ;    /* List of specified users */
X} ;
END_OF_FILE
  if test 2638 -ne `wc -c <'flags.h'`; then
    echo shar: \"'flags.h'\" unpacked with wrong size!
  fi
  # end of 'flags.h'
fi
if test -f 'getupage.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'getupage.c'\"
else
  echo shar: Extracting \"'getupage.c'\" \(4161 characters\)
  sed "s/^X//" >'getupage.c' <<'END_OF_FILE'
X# ifndef lint
Xstatic char SccsId[] =  "@(#)getupage.c	1.3\t8/2/90" ;
X# endif
X
X# include       "sps.h"
X# ifdef KVM
X#  include      <kvm.h>
X# else
X#  include      <h/vm.h>
X#  ifdef BSD42
X#  include	<machine/pte.h>
X#  else
X#  include      <h/pte.h>
X#  endif
X# endif
X# include       <stdio.h>
X
X/*
X** GETUPAGE - Reads the upage for the specified process as well as sufficient
X** page tables entries for reading the command arguments. The pte's are read
X** into the argument `ptetbl'. The upage is read into the external variable
X** `User'. This procedure returns 1 if the upage was successfully read.
X*/
X
X# ifndef KVM
X
X# define        usrpt           (Info.i_usrpt)
X
Xgetupage ( p, ptetbl )
X
Xregister struct process         *p ;
Xregister struct pte             *ptetbl ;
X
X{
X	register int            i ;
X	register int            ncl ;
X	struct pte              pte ;
X	extern struct info      Info ;
X	extern union userstate  User ;
X	extern int              Flmem, Flkmem, Flswap ;
X
X	/* If the process is not loaded, look for the upage on the swap device*/
X	if ( !(p->pr_p.p_flag & SLOAD) )
X	{                               
X# ifdef BSD42
X		swseek( (long)dtob( p->pr_p.p_swaddr ) ) ;
X# else BSD42
X		swseek( (long)ctob( p->pr_p.p_swaddr ) ) ;
X# endif BSD42
X# ifdef SUN
X		if ( read( Flswap, (char*)&User.u_us, sizeof( union userstate ))
X		!= sizeof( union userstate ) )
X# else SUN
X		if ( read( Flswap, (char*)&User.u_us, sizeof( struct user ) )
X		!= sizeof( struct user ) )
X# endif SUN
X		{
X			fprintf( stderr,
X				"sps - Can't read upage of process %d\n",
X			    p->pr_p.p_pid ) ;
X			return ( 0 ) ;
X		}
X		return ( 1 ) ;          
X	}                               
X	/* The process is loaded. Locate the process pte's by reading
X	   the pte of their base address from system virtual address space. */
X# ifdef DEC3100
X	/* This method of accessing the upage suffices on the DEC Station
X	   but only provides sufficient pte's to read the upage, leaving the
X	   command arguments inaccessible. */
X	memseek( Flkmem, (long)p->pr_p.p_addr ) ;
X	if ( read( Flkmem, (char*)ptetbl, (UPAGES+CLSIZE)*sizeof( struct pte ) )
X	!= (UPAGES+CLSIZE)*sizeof( struct pte ) )
X	{
X		fprintf( stderr, "sps - Can't read page table of process %d\n",
X			p->pr_p.p_pid ) ;
X		return ( 0 ) ;
X	}
X# else DEC3100
X	memseek( Flkmem, (long)&Info.i_usrptmap[ btokmx(p->pr_p.p_p0br)
X		+ p->pr_p.p_szpt-1 ] ) ;
X	if ( read( Flkmem, (char*)&pte, sizeof( struct pte ) )
X	!= sizeof( struct pte ) )
X	{
X		fprintf( stderr,
X		      "sps - Can't read indir pte for upage of process %d\n",
X		    p->pr_p.p_pid ) ;
X		return ( 0 ) ;
X	}                               
X	/* Now read the process' pte's from physical memory. We need to access
X	   sufficient pte's for the upage and for the command arguments. */
X	memseek( Flmem, (long)ctob( pte.pg_pfnum+1 )
X		- (UPAGES+CLSIZE)*sizeof( struct pte ) ) ;
X	if ( read( Flmem, (char*)ptetbl, (UPAGES+CLSIZE)*sizeof( struct pte ) )
X	!= (UPAGES+CLSIZE)*sizeof( struct pte ) )
X	{
X		fprintf( stderr, "sps - Can't read page table of process %d\n",
X			p->pr_p.p_pid ) ;
X		return ( 0 ) ;
X	}
X# endif DEC3100
X	/* Now we can read the pages belonging to the upage.
X	   Here we read in an entire click at one go. */
X	ncl = (sizeof( struct user ) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE) ;
X	while ( --ncl >= 0 )            
X	{                               
X		i = ncl * CLSIZE ;
X# ifdef DEC3100
X		memseek( Flmem, (long)ctob( ptetbl[ i ].pg_pfnum ) ) ;
X# else DEC3100
X		memseek( Flmem, (long)ctob( ptetbl[ CLSIZE+i ].pg_pfnum ) ) ;
X# endif DEC3100
X		if ( read( Flmem, User.u_pg[i], CLSIZE*NBPG ) != CLSIZE*NBPG )
X		{
X			fprintf( stderr,
X				"sps - Can't read page 0x%x of process %d\n",
X				ptetbl[ CLSIZE+i ].pg_pfnum, p->pr_p.p_pid ) ;
X			return ( 0 ) ;
X		}
X	}
X	return ( 1 ) ;
X}
X
X# else KVM
X
Xgetupage ( p )
X
Xregister struct process         *p ;
X
X{
X        struct user            *upage ;
X	extern union userstate  User ;
X	extern kvm_t           *Flkvm ;
X
X	if (upage = kvm_getu( Flkvm, &p->pr_p ) )
X	{
X	        bcopy( (char *)upage, User.u_pg[0], sizeof( struct user ) ) ;
X		return ( 1 ) ;
X	}
X	fprintf( stderr, "sps - Can't read upage of process %d\n",
X	    p->pr_p.p_pid ) ;
X	return ( 0 ) ;
X}
X
X# endif KVM
END_OF_FILE
  if test 4161 -ne `wc -c <'getupage.c'`; then
    echo shar: \"'getupage.c'\" unpacked with wrong size!
  fi
  # end of 'getupage.c'
fi
if test -f 'globals2.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'globals2.c'\"
else
  echo shar: Extracting \"'globals2.c'\" \(6807 characters\)
  sed "s/^X//" >'globals2.c' <<'END_OF_FILE'
X# ifndef lint
Xstatic char SccsId[] =  "@(#)globals2.c	1.2\t7/4/90" ;
X# endif
X
X# include       "sps.h"
X
X/* Read Only variables, global to the code of sps ... */
X
X/* Null ttyline device ... */
Xstruct ttyline                  Notty = { "  " } ;
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# ifdef ULTRIX20
X	{ "_gnode",     1,  (caddr_t*)&Info.i_inode0,   (char*)0        },
X	{ "_ngnode",    1,  (caddr_t*)&Info.i_ninode,   (char*)0        },
X# else
X#  ifndef SUNOS41
X	{ "_inode",     1,  (caddr_t*)&Info.i_inode0,   (char*)0        },
X#  endif SUNOS41
X	{ "_ninode",    1,  (caddr_t*)&Info.i_ninode,   (char*)0        },
X# endif ULTRIX20
X
X# ifndef SUNOS40
X	{ "_text",      1,  (caddr_t*)&Info.i_text0,    (char*)0        },
X	{ "_ntext",     1,  (caddr_t*)&Info.i_ntext,    (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	{ "_dmmin",     1,  (caddr_t*)&Info.i_dmmin,    (char*)0        },
X	{ "_dmmax",     1,  (caddr_t*)&Info.i_dmmax,    (char*)0        },
X# endif SUNOS40
X
X	{ "_cdevsw",    0,  (caddr_t*)&Info.i_cdevsw,   (char*)0        },
X# ifdef BSD42
X#  ifdef NFS
X#   ifndef NOQUOTA
X	{ "_dquot",     1,  (caddr_t*)&Info.i_quota0,   (char*)0        },
X	{ "_ndquot",    1,  (caddr_t*)&Info.i_nquota,   (char*)0        },
X#   endif NOQUOTA
X#  else 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	{ "_mbutl",     0,  (caddr_t*)&Info.i_mbutl,    (char*)0        },
X# else BSD42
X	{ "_hz",        1,  (caddr_t*)&Info.i_hz,       (char*)0        },
X# endif BSD42
X
X# ifdef CHAOS
X	{ "_Chconntab", 0,  &Info.i_Chconntab,          (char*)0        },
X# endif CHAOS
X
X# ifdef SUNOS40
X	{ "_maxmem",	1,  (caddr_t*)&Info.i_ecmx,	(char*)0	},
X	{ "_segvn_ops",	0,  (caddr_t*)&Info.i_segvn_ops,(char*)0	},
X	{ "_pty_softc",	0,  (caddr_t*)&Info.i_ptybase,	(char*)0	},
X	{ "_npty",	1,  (caddr_t*)&Info.i_npty,	(char*)0	},
X#  ifdef SUNOS41
X	{ "_strst",	0,  (caddr_t*)&Info.i_strst,	(char*)0	},
X	{ "_allstream",	1,  (caddr_t*)&Info.i_allstream, (char*)0	},
X#  else SUNOS41
X	{ "_streams",	0,  (caddr_t*)&Info.i_streams,	(char*)0	},
X	{ "_streamsNSTREAMS", 1, (caddr_t*)&Info.i_streamsNSTREAMS ,(char*)0 },
X#  endif SUNOS41
X	{ "_Sysbase",	1,  (caddr_t*)&Info.i_sysbase,	(char*)0	},
X# endif SUNOS40
X
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# ifdef SUNOS41
X	{ "_uunix",     0,  &Info.i_waitstate[8],       "pause"         },
X# else SUNOS41
X	{ "_u",         0,  &Info.i_waitstate[8],       "pause"         },
X# endif SUNOS41
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 CHAOS
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#  ifdef NFS
X	{ "_async_bufhead", 0,  &Info.i_waitstate[35],  "async"		},
X#  endif NFS
X# else SUN
X	{ "_async_bufhead", 0,  &Info.i_waitstate[14],  "async"		},
X	{ "_desktops",	0,  &Info.i_waitstate[15],	"dtops"		},
X# endif SUN
X# ifdef ULTRIX20
X	{ "_async_bufhead", 0,  &Info.i_waitstate[35],  "async"		},
X# endif ULTRIX20
X	{ (char*)0,     0,  (caddr_t*)0,                (char*)0        }
X} ;
END_OF_FILE
  if test 6807 -ne `wc -c <'globals2.c'`; then
    echo shar: \"'globals2.c'\" unpacked with wrong size!
  fi
  # end of 'globals2.c'
fi
if test -f 'inittty.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'inittty.c'\"
else
  echo shar: Extracting \"'inittty.c'\" \(3716 characters\)
  sed "s/^X//" >'inittty.c' <<'END_OF_FILE'
X# ifndef lint
Xstatic char SccsId[] =  "@(#)inittty.c	1.1\t10/1/88" ;
X# endif
X
X# include       "sps.h"
X# include       <h/conf.h>
X# include       <h/ioctl.h>
X# ifdef SUNOS40
X# include       <h/stream.h>
X# else
X# include       <h/tty.h>
X# endif
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# 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		if ( getkmem ( (long)&Info.i_cdevsw[ major( statbuf.st_rdev ) ]
X# ifdef SUNOS40
X			.d_str,
X# else
X			.d_ttys,
X# endif
X		(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# ifndef SUNOS40
X		lp->l_addr += (int)minor( statbuf.st_rdev ) ;
X# endif
X		lp++ ;
X	}
X# ifdef BSD42
X	(void)closedir( dfd ) ;
X# else
X	(void)fclose( dfd ) ;
X# endif
X}
END_OF_FILE
  if test 3716 -ne `wc -c <'inittty.c'`; then
    echo shar: \"'inittty.c'\" unpacked with wrong size!
  fi
  # end of 'inittty.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
  echo shar: Extracting \"'main.c'\" \(4246 characters\)
  sed "s/^X//" >'main.c' <<'END_OF_FILE'
X# ifndef lint
Xstatic char SccsId[] =  "@(#)main.c	1.1\t10/1/88" ;
X# endif
X
X# include       "sps.h"
X# include       "flags.h"
X# ifdef KVM
X# include       <kvm.h>
X# include       <fcntl.h>
X# endif KVM
X# ifndef SUNOS40
X# include       <h/text.h>
X# endif
X# include       <sys/stat.h>
X# include       <stdio.h>
X
X
X/* SPS - Show Process Status */
X
X/* J. R. Ward - Hasler AG, Bern, Switzerland		 - 24 May 1985 */
X/*				     			 - 26 Nov 1986 */
X/* J. R. Ward - Olsen & Associates, Zuerich, Switzerland -  1 Oct 1988 */
X/* <robert at olsen.uucp> */
X
X/* NFS additions and SunOS4.0 support by Alexander Dupuy
X   <dupuy at ncs.columbia.edu> and Charlie Kim <cck at cunixc.cc.columbia.edu>.
X   Ultrix 2.x support by Rob Lehman at CUCCA. */
X
Xmain ( argc,argv )
X
Xint                             argc ;
Xchar                            **argv ;
X
X{
X	register struct process *plist ;
X	register struct process *process ;
X# ifndef SUNOS40
X	register struct text    *text ;
X# endif
X	int                     flinfo ;
X	char			*fileinfo, *filesymbol ;
X	struct stat		sinfo, ssymbol ;
X# ifdef WARNPASSWD
X	struct stat		spasswd ;
X# endif
X	extern struct flags     Flg ;
X	extern struct info      Info ;
X# ifdef KVM
X	extern kvm_t           *Flkvm ;
X# else
X	extern int              Flmem ;
X	extern int              Flkmem ;
X	extern int              Flswap ;
X# endif
X	char                    *getcore() ;
X	struct process          *needed(), *mktree() ;
X
X	/* Renice as fast as possible for root only (Suggested by Jeff Mogul,
X	   gregorio!mogul) */
X	if ( !getuid() )
X		(void)nice( -40 ) ;
X	/* Decode the flag arguments */
X	flagdecode( argc, argv ) ;      
X	/* Determine the terminal width */
X	if ( !Flg.flg_w && !Flg.flg_N && !Flg.flg_i )
X		termwidth() ;
X	/* Open the cpu physical memory, kernel virtual memory and swap device*/
X# ifdef KVM
X	Flkvm = kvm_open( Flg.flg_s, Flg.flg_k, NULL, O_RDONLY, "sps" ) ;
X# else
X	if ( Flg.flg_k )
X	{
X		Flmem = openfile( Flg.flg_k ) ;
X		Flkmem = Flmem ;
X	}
X	else
X	{
X		Flmem = openfile( FILE_MEM ) ;
X		Flkmem = openfile( FILE_KMEM ) ;
X		if ( !Flg.flg_o )
X			Flswap = openfile( FILE_SWAP ) ;
X	}
X# endif
X	if ( Flg.flg_i )
X	{       /* -i flag for info file initialisation */
X		initialise() ;          
X		exit( 0 ) ;
X	}
X	/* Check that the information file is newer than the symbol and
X	   password files, suggested by gregorio!mogul */
X	fileinfo = Flg.flg_j ? Flg.flg_j : FILE_INFO ;
X	filesymbol = Flg.flg_s ? Flg.flg_s : FILE_SYMBOL ;
X	flinfo = openfile( fileinfo ) ;
X	(void)fstat( flinfo, &sinfo ) ;
X	if ( !stat( filesymbol, &ssymbol ) &&
X		sinfo.st_mtime < ssymbol.st_mtime )
X		fprintf( stderr,
X	       "sps - WARNING: Info file `%s' is older than symbol file `%s'\n",
X			fileinfo, filesymbol ) ;
X# ifdef WARNPASSWD
X	if ( !stat( FILE_PASSWD, &spasswd ) &&
X		sinfo.st_mtime < spasswd.st_mtime )
X		fprintf( stderr,
X	       "sps - WARNING: Info file `%s' is older than passwd file `%s'\n",
X			fileinfo, FILE_PASSWD ) ;
X# endif
X	/* Read the information file */
X	if ( read( flinfo, (char*)&Info, sizeof( struct info ) )
X	!= sizeof( struct info ) )
X	{
X		fprintf( stderr, "sps - Can't read info file `%s'", fileinfo ) ;
X		sysperror() ;
X	}
X	(void)close( flinfo ) ;
X	/* Find current tty status */
X	ttystatus() ;                   
X	/* Now that we know the available ttys, decode the flags */
X	flagsetup() ;                   
X	process = (struct process*)getcore(Info.i_nproc*sizeof(struct process));
X# ifndef SUNOS40
X	text = (struct text*)getcore( Info.i_ntext * sizeof( struct text ) ) ;
X# endif
X	do
X	{       /* Read current process status */
X# ifdef SUNOS40
X		readstatus( process ) ;
X		/* Select those processes to be listed */
X		plist = needed( process ) ;
X# else
X		readstatus( process, text ) ;
X		/* Select those processes to be listed */
X		plist = needed( process, text ) ;
X# endif
X		/* Form a tree of listed processes */
X		plist = mktree( process, plist ) ;
X		if ( !Flg.flg_N )
X		{       /* Print the processes */
X			prheader() ;
X			printall( plist, 0 ) ;
X		}
X		prsummary() ;
X		(void)fflush( stdout ) ;
X		if ( Flg.flg_r )        
X		{       /* If repeating, again get tty status */
X			ttystatus() ;
X			if ( Flg.flg_rdelay )
X# ifdef BSD42
X				sleep( Flg.flg_rdelay ) ;
X# else
X				sleep( (int)Flg.flg_rdelay ) ;
X# endif
X		}
X	} while ( Flg.flg_r ) ;
X	exit( 0 ) ;
X}
END_OF_FILE
  if test 4246 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
  fi
  # end of 'main.c'
fi
if test -f 'needed.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'needed.c'\"
else
  echo shar: Extracting \"'needed.c'\" \(5151 characters\)
  sed "s/^X//" >'needed.c' <<'END_OF_FILE'
X# ifndef lint
Xstatic char SccsId[] =  "@(#)needed.c	1.3\t7/4/90" ;
X# endif
X
X# include       "sps.h"
X# include       "flags.h"
X# ifndef SUNOS40
X# include       <h/text.h>
X# endif
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*/
X# ifdef SUNOS40
Xstruct process  *needed ( process )
X
Xregister struct process         *process ;
X
X# else
X
Xstruct process  *needed ( process, text )
X
Xregister struct process         *process ;
Xstruct text                     *text ;
X
X# endif
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# ifndef SUNOS40
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# endif
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( p ) ;
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# ifndef SUNOS40
X	register struct text    *tp ;
X# endif
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# if defined(OLDSTATS) || !defined(SUNOS40)
X	Summary.sm_ktotal += p->pr_p.p_dsize + p->pr_p.p_ssize ;
X# else
X	seg_count( p ) ;		/* count up process pages */
X	
X	Summary.sm_ktotal += p->pr_private + p->pr_shared ;
X# endif
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# ifdef SUNOS40
X	/* Ignore the idle processes */
X	if ( p->pr_p.p_pid == 3 || p->pr_p.p_pid == 4 )
X	    busy = 0 ;
X# endif SUNOS40
X	if ( busy )
X	{
X		Summary.sm_nbusy++ ;
X# if defined(OLDSTATS) || !defined(SUNOS40)
X		Summary.sm_kbusy += p->pr_p.p_dsize + p->pr_p.p_ssize ;
X# else
X		Summary.sm_kbusy += p->pr_private + p->pr_shared ;
X# endif
X	}
X# ifndef SUNOS40
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# endif
X}
END_OF_FILE
  if test 5151 -ne `wc -c <'needed.c'`; then
    echo shar: \"'needed.c'\" unpacked with wrong size!
  fi
  # end of 'needed.c'
fi
if test -f 'openfiles.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'openfiles.c'\"
else
  echo shar: Extracting \"'openfiles.c'\" \(3718 characters\)
  sed "s/^X//" >'openfiles.c' <<'END_OF_FILE'
X# ifndef lint
Xstatic char SccsId[] =  "@(#)openfiles.c	1.1\t10/1/88" ;
X# endif
X
X# include       <stdio.h>
X# include       "sps.h"
X# include       "flags.h"
X# include       <varargs.h>
X# ifdef KVM
X# include       <kvm.h>
X# endif
X
X/* Miscellaneous procedures */
X
X/* OPENFILE - Opens the named file */
Xopenfile ( name )
X
Xchar                            *name ;
X
X{
X	register int            fd ;
X
X	if ( (fd = open( name, 0 )) >= 0 )
X		return ( fd ) ;
X	fprintf( stderr, "sps - Can't open %s", name ) ;
X	sysperror() ;
X	/* NOTREACHED */
X}
X
X# ifdef KVM
X
Xgetkmem ( addr, buf, bufsize )
X
Xlong                            addr ;
Xchar                            *buf ;
Xint                             bufsize ;
X{
X	extern kvm_t            *Flkvm ;
X
X	return( kvm_read( Flkvm, (long)addr, buf, bufsize ) ) ;
X}
X
X# else
X
Xgetkmem ( addr, buf, bufsize )
X
Xlong                            addr ;
Xchar                            *buf ;
Xint                             bufsize ;
X{
X	extern int              Flkmem ;
X
X	memseek( Flkmem, (long)addr ) ;
X	return( read( Flkmem, buf, bufsize ) ) ;
X}
X
X/* MEMSEEK - Seek on a special file */
Xmemseek ( fd, pos )
X
Xint                             fd ;
Xlong                            pos ;
X
X{
X	extern int              errno ;
X	extern struct flags     Flg ;
X	long                    lseek() ;
X
X	errno = 0 ;
X	if ( Flg.flg_k )
X# ifdef SUN
X		pos &= KERNELBASE - 1 ;
X# else
X		pos &= 0x7fffffff ;
X# endif
X	(void)lseek( fd, pos, 0 ) ;
X	if ( errno )
X	{
X		fprintf( stderr, "sps - Seek failed" ) ;
X		sysperror() ;
X	}
X}
X
X/* SWSEEK - Seek on the swap device */
Xswseek ( pos )
X
Xlong                            pos ;
X
X{
X	extern int              Flswap ;
X	extern int              errno ;
X	long                    lseek() ;
X
X	errno = 0 ;
X	(void)lseek( Flswap, pos, 0 ) ;
X	if ( errno )
X	{
X		fprintf( stderr, "sps - Seek failed" ) ;
X		sysperror() ;
X	}
X}
X
X# endif
X
X# ifdef lint
Xint                             errno ;
Xint                             sys_nerr ;
Xchar                            *sys_errlist[] ;
X# endif
X
X/* SYSPERROR - Reports a system defined error msg and then exits gracefully */
Xsysperror ()
X{
X	extern int              errno ;
X	extern int              sys_nerr ;
X	extern char             *sys_errlist[] ;
X
X	if ( 0 < errno && errno < sys_nerr )
X		fprintf( stderr, " : %s", sys_errlist[errno] ) ;
X	(void)fputc( '\n', stderr ) ;
X	exit( 1 ) ;
X}
X
X/* STRSAVE - Store a string in core for later use. */
Xchar    *strsave ( cp )
X
Xregister char                   *cp ;
X
X{
X	register char           *chp ;
X	char                    *getcore(), *strcpy() ;
X
X	chp = getcore( strlen( cp ) + 1 ) ;
X	(void)strcpy( chp, cp ) ;
X	return ( chp ) ;
X}
X
X/* GETCORE - Allocate and return a pointer to the asked for amount of core */
Xchar    *getcore ( size )
X
Xregister int                    size ;
X
X{
X	register char           *chp ;
X	char                    *malloc() ;
X
X	if ( chp = malloc( (unsigned)size ) )
X		return ( chp ) ;
X	fprintf( stderr, "sps - Out of core" ) ;
X	sysperror() ;
X	/* NOTREACHED */
X}
X
Xunion flaglist  *getflgsp ( argc )
X
Xregister int                    argc ;
X
X{
X	char                    *getcore() ;
X
X	return ( (union flaglist*)getcore( sizeof( union flaglist )*argc ) ) ;
X}
X
X/* PREXIT - Print an error message and exit */
X/* VARARGS */
X/* ARGSUSED */
Xprexit ( va_alist )
X
Xva_dcl
X
X{
X	char                    *fmt ;
X	va_list                  args ;
X
X	va_start( args ) ;
X	fmt = va_arg( args, char * ) ;
X
X	vfprintf( stderr, fmt, args ) ;
X	exit( 1 ) ;
X}
X
X# ifndef VPRINTF
X
Xint vfprintf ( filep, fmt, args )
X
XFILE	                        *filep ;
Xchar                            *fmt ;
Xva_list                          args ;
X
X{
X	_doprnt( fmt, args, filep ) ;	
X	return( ferror( filep ) ? EOF : 0 ) ;
X}
X
X# endif
END_OF_FILE
  if test 3718 -ne `wc -c <'openfiles.c'`; then
    echo shar: \"'openfiles.c'\" unpacked with wrong size!
  fi
  # end of 'openfiles.c'
fi
if test -f 'sps.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sps.h'\"
else
  echo shar: Extracting \"'sps.h'\" \(6824 characters\)
  sed "s/^X//" >'sps.h' <<'END_OF_FILE'
X# ifndef lint
Xstatic char SpsHId[] =  "@(#)sps.h	1.3\t7/4/90" ;
X# endif
X
X# ifdef SUNOS40
X#  define KERNEL
X# endif SUNOS40
X# include	<h/param.h>
X# undef KERNEL
X# include	<h/dir.h>
X# include	<h/user.h>
X# include	<h/proc.h>
X
X# ifdef SUNOS40
X#  ifndef BSD43
X#   define BSD43
X# endif BSD43
X# endif SUNOS40
X
X/*
X** Maximum # of users to be considered. (Because user names are stored
X** in a hash table, this should probably be at least double the number
X** of actual users defined in /etc/passwd or by the Yellow Pages.)
X*/
X# define	MAXUSERS	100
X/* Maximum # ttys to be considered, plus 1 for the console ... */
X# define	MAXTTYS		97
X
X
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 NFS
X#  ifdef SUN
X#   define	NWAITSTATE	16
X#  else
X#   define	NWAITSTATE	36
X#  endif SUN
X# else NFS
X#  ifdef ULTRIX20
X#   define	NWAITSTATE	36
X#  else ULTRIX20
X#   define	NWAITSTATE	35
X#  endif ULTRIX20
X# endif NFS
X
X/* Convert clicks to kbytes ... */
X# ifndef PGSHIFT
X#  define	KBYTES( size )	((size) << 1)
X# else PGSHIFT
X#  if PGSHIFT > 10
X#   define        KBYTES( size )  ((size) << (PGSHIFT - 10))
X#  else
X#   define	KBYTES( size )	((size) >> (10 - PGSHIFT))
X#  endif
X# endif PGSHIFT
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	"/tmp/.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	char			l_name[2] ;	/* Tty character name */
X	unsigned short		l_pgrp ;	/* Tty process group */
X# ifdef SUNOS40
X	struct streamtab	*l_addr ;	/* Ptr to streamtab in kmem */
X	struct stdata		*l_stdata ;	/* Ptr to stdata at runtime */
X# else SUNOS40
X	struct tty		*l_addr ;	/* Ptr to tty struct in kmem */
X# endif SUNOS40
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# ifndef SUNOS40
X	struct text		*i_text0 ;	/* address of text table */
X# endif SUNOS40
X	int			i_ntext ;	/* length of text table */
X# ifdef ULTRIX20
X	struct gnode		*i_inode0 ;	/* address of inode table */
X# else ULTRIX20
X	struct inode		*i_inode0 ;	/* address of inode table */
X# endif ULTRIX20
X	int			i_ninode ;	/* length of inode table */
X	int			i_ecmx ;	/* max physical memory address*/
X# ifndef SUNOS40
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	struct pte		*i_usrptmap ;	/* page table map */
X	struct pte		*i_usrpt ;	/* page table map */
X# endif SUNOS40
X	struct cdevsw		*i_cdevsw ;	/* device switch to find ttys */
X# ifdef BSD42
X#  ifdef NFS
X	struct dquot		*i_quota0 ;	/* disc quota structures */
X#  else NFS
X	struct quota		*i_quota0 ;	/* disc quota structures */
X#  endif NFS
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 BSD42
X	int			i_hz ;		/* Clock rate */
X# endif BSD42
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[ MAXUSERS ] ;
X	/* Tty device info ... */
X	struct ttyline		i_ttyline[ MAXTTYS ] ;
X# ifdef SUNOS40
X	struct seg_ops		*i_segvn_ops ;	/* ptr to vnode segment ops */
X	struct pty		*i_ptybase ;
X	int			i_npty ;
X#  ifdef SUNOS41
X	struct strstat		*i_strst;
X	struct stdata		*i_allstream;
X#  else SUNOS41
X	struct stdata		*i_streams ;	/* streams list */
X	struct stdata		*i_streamsNSTREAMS ;
X#  endif SUNOS41
X	caddr_t			i_sysbase ;
X# endif SUNOS40
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 BSD42
X	struct vtimes		pr_vself ;	/* Read from upage for self */
X	struct vtimes		pr_vchild ;	/* ... and the children */
X# endif BSD42
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# ifdef SUNOS40
X	unsigned		pr_private ;	/* private pages */
X	unsigned		pr_shared ;	/* shared pages */
X# endif SUNOS40
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_FILE
  if test 6824 -ne `wc -c <'sps.h'`; then
    echo shar: \"'sps.h'\" unpacked with wrong size!
  fi
  # end of 'sps.h'
fi
if test -f 'stream.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'stream.c'\"
else
  echo shar: Extracting \"'stream.c'\" \(5425 characters\)
  sed "s/^X//" >'stream.c' <<'END_OF_FILE'
X# ifndef lint
Xstatic char SccsId[] =  "@(#)stream.c	1.2\t7/4/90" ;
X# endif
X
X# ifdef SUNOS40
X#  include		"sps.h"
X#  include		<h/stream.h>
X#  include		<h/vnode.h>
X#  ifdef SUNOS41
X#   include		<h/strstat.h>
X#  endif
X
Xstatic struct stdata    *pstreams ;
Xstatic struct stdata    *pstreamsNSTREAMS ;
X
Xinit_streams_tab()
X{
X	int			len ;
X	extern struct info	Info ;
X	register struct stdata	*s ;
X	struct vnode		*v ;
X	char			*getcore() ;
X
X	if ( pstreams )
X		/* reinitializing */
X		for ( s = pstreams ; s <= pstreamsNSTREAMS ; s++ )
X			if ( s->sd_vnode != 0 )
X				free( (char*)s->sd_vnode ) ;
X		free( (char*)pstreams ) ;
X#  ifdef SUNOS41
X	/*
X	 * In SunOS 4.1, the stream heads are in a linked list.  A
X	 * `struct strstat' contains the number of active streams; the
X	 * variable `allstream' points to an apparently random
X	 * position in a doubly linked `struct stdata' chain.
X	 *
X	 * To find all streams we'll have to scan the chain forwards
X	 * AND backwards from `allstream'.  `int going_forwards' below
X	 * tells which direction we are currently going.  Weird.
X	 *
X	 */
X
X	{
X		struct strstat		strst ;
X		int			n ;
X		long			addr ;
X		struct stdata		*this_stream ;
X		int			going_forwards = 1 ;
X    
X		if ( getkmem ((long) Info.i_strst, (char *) &strst,
X		    sizeof ( struct strstat )) != sizeof ( struct strstat ))
X			return 0 ;
X		len = strst.stream.use * sizeof( struct stdata ) ;
X		pstreams = (struct stdata *)getcore (len ) ;
X		addr = (long)Info.i_allstream ;
X		this_stream = pstreams ;
X		pstreamsNSTREAMS = pstreams - 1 ;
X		for (n = 0 ; n < strst.stream.use ; n++)
X		{
X			if ( getkmem ( addr, (char *) this_stream,
X			    sizeof ( struct stdata ))
X			    != sizeof ( struct stdata ))
X			{
X				/*
X				 * If we are following the `sd_next' chain we'll
X				 * have to start over from the stream pointed to
X				 * by Info.i_allstream and scan `sd_prev'
X				 * backwards.
X				 */
X				if ( going_forwards && n > 0 )
X				{
X					going_forwards = 0 ;
X					addr = (long) pstreams[0].sd_prev ;
X					n--;
X					continue ;
X				}
X				if ( pstreamsNSTREAMS < pstreams )
X					return 0 ;
X				break ;
X			}
X			addr = going_forwards ? (long) this_stream->sd_next :
X				(long) this_stream->sd_prev ;
X			this_stream++ ;
X			pstreamsNSTREAMS++ ;
X		}
X	}
X#  else SUNOS41
X	len = ((Info.i_streamsNSTREAMS - Info.i_streams) + 1)
X		* sizeof( struct stdata ) ;
X	pstreams = (struct stdata *)getcore( len ) ;
X	pstreamsNSTREAMS = pstreams + (len / sizeof( struct stdata ) ) ;
X	if ( getkmem( (long)Info.i_streams, (char *)pstreams, len ) != len )
X		return( 0 ) ;
X#  endif SUNOS41
X
X	for ( s = pstreams ; s <= pstreamsNSTREAMS ; s++ )
X		if ( s->sd_vnode != 0 )
X		{
X			if ( ( v = (struct vnode*)getcore( sizeof( *v ) ) )
X			&& getkmem( (long)s->sd_vnode, (char*)v, sizeof( *v ) )
X			== sizeof( *v ) )
X			{
X				s->sd_vnode = v ;
X				continue ;
X			}
X
X			s->sd_vnode = 0 ;
X		}
X	return( 1 ) ;
X}
X
X
X#  ifdef SUNOS41
Xstruct sess *find_session ( addr )
X
Xstruct sess			*addr ;
X
X{
X	/*
X	 * SunOS 4.1 seems to store controlling tty's in a "struct
X	 * sess" which is accessible as p->p_sessp.  Another layer
X	 * of indirection to wade through...
X	 *
X	 * To make this a tiny bit faster, I'll store sessions in a
X	 * linked list as I read them in with getkmem; subsequent
X	 * calls to find_session() check the cache.
X	 */
X
X	struct sps_sess {
X		struct sess		sess ;
X		struct sess		*addr ;
X		struct sps_sess		*next ;
X	};
X
X	static struct sps_sess		*sessions ; /* Cache of known sessions*/
X	register struct sps_sess	*s ;
X
X	/* Try to find the session in the cache */
X	for ( s = sessions ; s ; s = s->next )
X		if ( s->addr == addr )
X			return &s->sess ;
X	/* Not found; get it from kmem and put it in the cache */
X	s = (struct sps_sess *)getcore( sizeof ( struct sps_sess ) ) ;
X	if ( getkmem ((long) addr, (char *) &s->sess,
X		    sizeof ( struct sess )) != sizeof ( struct sess ) )
X		return 0 ;
X	s->addr = addr ;
X	s->next = sessions ;
X	sessions = s ;
X	return &s->sess ;
X}
X#  endif SUNOS41
X
Xstruct stdata *getstdata ( st, dev )
X
Xstruct streamtab                *st ;
Xdev_t                            dev ;
X
X{
X	register struct stdata  *s ;
X
X	for ( s = pstreams ; s <= pstreamsNSTREAMS ; s++ )
X		if ( s->sd_strtab == st && s->sd_vnode
X		&& s->sd_vnode->v_rdev == dev )
X			return( s ) ;
X	return( 0 ) ;
X}
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
Xchar *gettty ( lp, w )
X
Xregister struct ttyline         *lp ;
Xcaddr_t                         w ;
X
X{
X	struct stdata           *s ;
X	struct queue            *q ;
X	struct queue            qq[2] ;
X	char                    *cp = 0 ;
X
X	if ( ( s = lp->l_stdata ) == 0 )
X		return( 0 ) ;
X
X	q = s->sd_wrq ;		/* get write queue (only queue_t in stdata) */
X	do
X	{
X		if ( INRANGE( w, RD( q ), q ) )
X		{			/* check read queue */
X			cp = "rtty??" ;
X			break ;
X		}
X		if ( INRANGE( w, q, WR ( q ) ) )
X		{			/* check write queue */
X			cp = "wtty??" ;
X			break ;
X		}
X		/* check queue private data structures - useful??? */
X		if ( getkmem( (long)RD( q ), (char*)qq, sizeof( qq ) )
X		!= sizeof( qq ) )
X			break ;
X		if ( INRANGE( w, qq[0].q_ptr, qq[0].q_ptr + 1 ) )
X		{
X			cp = "r?ty??" ;
X		}
X		if ( INRANGE( w, qq[1].q_ptr, qq[1].q_ptr + 1 ) )
X		{
X			cp = "w?ty??" ;
X		}
X		q = qq[1].q_next ;
X	}
X	while ( q ) ;
X	if ( cp )
X	{
X		cp[4] = lp->l_name[0] ;
X		cp[5] = lp->l_name[1] ;
X		return( cp ) ;
X	}
X	return( 0 ) ;			/* chain down list? */
X}
X# endif SUNOS40
X
END_OF_FILE
  if test 5425 -ne `wc -c <'stream.c'`; then
    echo shar: \"'stream.c'\" unpacked with wrong size!
  fi
  # end of 'stream.c'
fi
echo shar: End of archive 2 \(of 4\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list