[net.sources] Reposting of SPS for 4.[12]bsd Vaxen - Shar 2 of 4

robert@hslrswi.UUCP (Robert Ward) (07/11/85)

Send comments, suggestions, bug fixes, bug reports to -

Robert Ward, Hasler AG, Abt. 34, Belpstrasse 23, CH-3000 Bern 14, Switzerland.
(... mcvax!cernvax!hslrswi!robert)

*******************************************************************************

This is a sh(1) archive.
In order to extract the contents of this shar, use an editor to place
the contents of this file from the dotted line onwards into a second,
temporary file. Then run sh on that second file.

--------------------------------- C U T --- H E R E ---------------------------
#! /bin/sh
echo Extracting filecount.c
cat > filecount.c << '---END-OF-filecount.c---'
# include	"sps.h"

/* FILECOUNT - Counts the # open files for the current process */
filecount ()
{
	register int		i ;
	register struct file	**f ;
	register int		count ;
	extern union userstate	User ;

	count = 0 ;
	for ( i = 0, f = User.u_us.u_ofile ; i < NOFILE ; i++ )
		if ( *f++ )
			count++ ;
	return ( count ) ;
}
---END-OF-filecount.c---
echo Extracting findtty.c
cat > findtty.c << '---END-OF-findtty.c---'
# include	"sps.h"
# include	<h/tty.h>

/* FINDTTY - Attempts to determine to which tty a process is connected */
struct ttyline	*findtty ( p )

register struct process		*p ;

{
	register struct ttyline	*lp ;
	extern struct info	Info ;
	extern struct ttyline	Notty ;
	extern union userstate	User ;

	if ( !p->pr_p.p_pgrp )
		return ( &Notty ) ;
	for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
		if ( lp->l_dev == User.u_us.u_ttyd )
			return ( lp ) ;
	return ( &Notty ) ;
}
---END-OF-findtty.c---
echo Extracting flagdecode.c
cat > flagdecode.c << '---END-OF-flagdecode.c---'
# include	"sps.h"
# include	"flags.h"

/* FLAGDECODE - Looks at the argument list and sets various internal switches */
flagdecode ( argc, argv )

register int			argc ;
register char			**argv ;

{
	register char		*chp ;
	union flaglist		*plist ;
	union flaglist		*tlist ;
	union flaglist		*ulist ;
	static char		usage[] =
	"sps - Unknown option %s\nUsage - sps [ -defgijkoqrsvwyABFNPSTUWZ ][ process|tty|user ] ...\n";
	union flaglist		*getflgsp() ;
	extern struct flags	Flg ;

	plist = tlist = ulist = (union flaglist*)0 ;
	for ( argv++ ; --argc ; argv++ )
	{
		chp = *argv ;
		while ( *chp )
			switch ( *chp++ )
			{
				case '-' :
					/* Separation character */
					continue ;
				case 'd' :
				case 'D' :
					/* List disc orientated information */
					Flg.flg_d = 1 ;
					Flg.flg_v = 0 ;
					continue ;
				case 'e' :
				case 'E' :
					/* List environment strings */
					Flg.flg_e = 1 ;
					continue ;
				case 'f' :
					/* List the father's process id */
					Flg.flg_f = 1 ;
					continue ;
				case 'g' :
				case 'G' :
					/* List the process group id */
					Flg.flg_g = 1 ;
					continue ;
				case 'i' :
				case 'I' :
					/* Initialise (super-user only) */
					Flg.flg_i = 1 ;
					continue ;
				case 'j' :
				case 'J' :
					/* The next argument specifies the
					   name of the information file */
					if ( argc <= 1 )
						prexit(
	      "sps - Name of an information file expected after `-j' flag\n" ) ;
					argc-- ;
					Flg.flg_j = *++argv ;
					continue ;
				case 'k' :
				case 'K' :
					/* Use a disc file such as /vmcore
					   rather than /dev/{k}mem for
					   accessing kernel data. The next
					   argument specifies the file name. */
					if ( argc <= 1 )
						prexit(
	       "sps - Name of a memory dump file expected after `-k' flag\n" ) ;
					argc-- ;
					Flg.flg_k = *++argv ;
					Flg.flg_o = 1 ;
					continue ;
				case 'l' :
				case 'v' :
				case 'L' :
				case 'V' :
					/* Verbose output */
					Flg.flg_d = 0 ;
					Flg.flg_v = 1 ;
					continue ;
				case 'o' :
				case 'O' :
					/* Avoid looking at the swap device */
					Flg.flg_o = 1 ;
					continue ;
				case 'q' :
				case 'Q' :
					/* Show only the user time, not the
					   user + system times together. */
					Flg.flg_q = 1 ;
					continue ;
				case 'r' :
				case 'R' :
					/* Repeat output every n seconds.
					   The next argument specifies n which
					   defaults to 5 if omitted. */
					Flg.flg_r = 1 ;
					if ( argc > 1 )
					{
						if ( **++argv >= '0'
						&& **argv <= '9' )
						{
							argc-- ;
							Flg.flg_rdelay
							       = atoi( *argv ) ;
							continue ;
						}
						argv-- ;
					}
					Flg.flg_rdelay = 0 ;
					continue ;
				case 's' :
					/* Next argument specifies a symbol
					   file rather than the default
					   /vmunix. */
					if ( argc <= 1 )
						prexit(
		    "sps - Name of a symbol file expected after `-s' flag\n" ) ;
					argc-- ;
					Flg.flg_s = *++argv ;
					continue ;
				case 'w' :
					/* Wide output, exceeding 79 columns */
					Flg.flg_w = 1 ;
					continue ;
				case 'y' :
				case 'Y' :
					/* List current tty information */
					Flg.flg_y = 1 ;
					continue ;
				case 'a' :
				case 'A' :
					/* List all processes */
					Flg.flg_AZ = 1 ;
					Flg.flg_A = 1 ;
					continue ;
				case 'b' :
				case 'B' :
					/* List only busy processes */
					Flg.flg_AZ = 1 ;
					Flg.flg_B = 1 ;
					continue ;
				case 'F' :
					/* List only foreground processes */
					Flg.flg_AZ = 1 ;
					Flg.flg_F = 1 ;
					continue ;
				case 'n' :
				case 'N' :
					/* No processes, just the summary line*/
					Flg.flg_AZ = 1 ;
					Flg.flg_N = 1 ;
					continue ;
				case 'p' :
				case 'P' :
					/* List only the given process ids */
					Flg.flg_AZ = 1 ;
					Flg.flg_P = 1 ;
					if ( !plist )
					   plist=Flg.flg_Plist=getflgsp( argc );
					while ( argc > 1 )
					{
						if ( **++argv == '-' )
						{
							--argv ;
							break ;
						}
						--argc ;
						plist->f_chp = *argv ;
						(++plist)->f_chp = (char*)0 ;
					}
					continue ;
				case 'S' :
					/* List only stopped processes */
					Flg.flg_AZ = 1 ;
					Flg.flg_S = 1 ;
					continue ;
				case 't' :
				case 'T' :
					/* List only processes attached to the
					   specified terminals */
					Flg.flg_AZ = 1 ;
					Flg.flg_T = 1 ;
					if ( !tlist )
					   tlist=Flg.flg_Tlist=getflgsp( argc );
					while ( argc > 1 )
					{
						if ( **++argv == '-' )
						{
							--argv ;
							break ;
						}
						--argc ;
						tlist->f_chp = *argv ;
						(++tlist)->f_chp = (char*)0 ;
					}
					continue ;
				case 'u' :
				case 'U' :
					/* List only processes belonging to the
					   specified users */
					Flg.flg_AZ = 1 ;
					Flg.flg_U = 1 ;
					if ( !ulist )
					   ulist=Flg.flg_Ulist=getflgsp( argc );
					while ( argc > 1 )
					{
						if ( **++argv == '-' )
						{
							--argv ;
							break ;
						}
						--argc ;
						ulist->f_chp = *argv ;
						(++ulist)->f_chp = (char*)0 ;
					}
					continue ;
				case 'W' :
					/* List only waiting processes */
					Flg.flg_AZ = 1 ;
					Flg.flg_W = 1 ;
					continue ;
				case 'z' :
				case 'Z' :
					/* List only zombie processes */
					Flg.flg_AZ = 1 ;
					Flg.flg_Z = 1 ;
					continue ;
				default :
					prexit( usage, *argv ) ;
					/* NOTREACHED */
			}
	}
}
---END-OF-flagdecode.c---
echo Extracting flags.h
cat > flags.h << '---END-OF-flags.h---'
/* Structure holding information specified in the option list ... */
union flaglist
{
	char			*f_chp ;	/* Option specified as string */
	int			f_uid ;		/* Numerical user id */
	int			f_pid ;		/* Numerical process id */
	struct ttyline		*f_ttyline ;	/* Specified tty */
} ;

/* Structure holding global information specifed by arg list options ... */
struct flags
{
	int			flg_d:1 ;	/* disc orientated output */
	int			flg_e:1 ;	/* print environment string */
	int			flg_f:1 ;	/* print process father # */
	int			flg_g:1 ;	/* print process group # */
	int			flg_i:1 ;	/* initialise sps */
	char			*flg_j ;	/* Use this as the info file */
	char			*flg_k ;	/* Use this as the {k}mem file*/
	int			flg_o:1 ;	/* avoid the swap device */
	int			flg_q:1 ;	/* show user time only */
	int			flg_r:1 ;	/* repeat output */
	unsigned		flg_rdelay ;	/* ... with this much delay */
	char			*flg_s ;	/* Use this as the symbol file*/
	int			flg_v:1 ;	/* print verbose listing */
	int			flg_w:1 ;	/* print wide output */
	int			flg_y:1 ;	/* print tty information */
	int			flg_A:1 ;	/* print all processes */
	int			flg_B:1 ;	/* print busy processes */
	int			flg_F:1 ;	/* print foreground processes */
	int			flg_N:1 ;	/* print no processes */
	int			flg_P:1 ;	/* print specified process #'s*/
	int			flg_S:1 ;	/* print stopped processes */
	int			flg_T:1 ;	/* print procs for given ttys */
	int			flg_U:1 ;	/* print procs for given users*/
	int			flg_W:1 ;	/* print waiting processes */
	int			flg_Z:1 ;	/* print zombie processes */
	int			flg_AZ:1 ;	/* One of A to Z was specified*/
	union flaglist		*flg_Plist ;	/* List of specified processes*/
	union flaglist		*flg_Tlist ;	/* List of specified ttys */
	union flaglist		*flg_Ulist ;	/* List of specified users */
} ;
---END-OF-flags.h---
echo Extracting flagsetup.c
cat > flagsetup.c << '---END-OF-flagsetup.c---'
# include	"sps.h"
# include	"flags.h"
# include	<h/tty.h>

/*
** FLAGSETUP - Replaces any users or processes specified by flagdecode()
** with numerical equivalents. The lists are terminated by negative values.
** or null pointers. Ttystatus() must have been previously called to
** initialise the Info structure with chaos tty values.
*/
flagsetup ()
{
	register union flaglist	*fp ;
	register char		*chp ;
	register int		i ;
	register struct ttyline	*lp ;
	int			found ;
	extern struct flags	Flg ;
	extern struct info	Info ;

	/* Look for specified users */
	if ( Flg.flg_U )		
	{
		if ( !Flg.flg_Ulist->f_chp )
			prexit( "sps - User name was expected after -u flag\n");
		for ( fp = Flg.flg_Ulist ; chp = fp->f_chp ; fp++ )
		{
			found = 0 ;
			for ( i = 0 ; i < MAXUSERID ; i++ )
				if ( !strncmp( chp, Info.i_hnames[i].h_uname,
					UNAMELEN ) )
				{
					fp->f_uid = Info.i_hnames[i].h_uid ;
					found = 1 ;
					break ;
				}
			if ( !found )
				prexit( "sps - Unknown user: %s\n", chp ) ;
		}
		fp->f_uid = -1 ;
	}
	/* Look for specified process ids */
	if ( Flg.flg_P )		
	{
		if ( !Flg.flg_Plist->f_chp )
			prexit(
			     "sps - Process id was expected after -p flag\n" ) ;
		for ( fp = Flg.flg_Plist ; chp = fp->f_chp ; fp++ )
		{
			if ( chp[0] < '0' || chp[0] > '9' )
				prexit( "sps - Bad process id: %s\n", chp ) ;
			fp->f_pid = atoi( chp ) ;
		}
		fp->f_pid = -1 ;
	}
	/* Look for specified ttys */
	if ( !Flg.flg_T )		
		return ;
	if ( !Flg.flg_Tlist->f_chp )
		prexit( "sps - Tty name was expected after -t flag\n" ) ;
	for ( fp = Flg.flg_Tlist ; chp = fp->f_chp ; fp++ )
	{	/* Under VMUNIX, all ttys have two character names.
		   Thus, a flag of the form `t 8' should be expanded to
		   become `t 08'. */
		if ( !chp[1] )
			chp[1] = chp[0], chp[0] = '0' ;
		found = 0 ;
		for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ )
			if ( !strncmp( chp, lp->l_name, 2 ) )
			{
				fp->f_ttyline = lp ;
				found = 1 ;
				break ;
			}
		if ( !found )
			prexit( "sps - Unknown tty name: %.2s\n", chp ) ;
	}
	fp->f_ttyline = (struct ttyline*)0 ;
}
---END-OF-flagsetup.c---
echo Extracting getcmd.c
cat > getcmd.c << '---END-OF-getcmd.c---'
# include	"sps.h"
# include	"flags.h"
# include	<h/vm.h>
# ifdef BSD42
# include	<vax/pte.h>
# else
# include	<h/pte.h>
# endif

/*
** GETCMD - Returns a character string read from a process' upage.
** This character string should represent the arguments to the current process.
*/
char	*getcmd ( p )

register struct process		*p ;

{
	register int		*ip ;
	register char		*cp ;
	register char		*cp0 ;
	unsigned		nbad ;
	struct dblock		db ;
	struct pte		ptetbl[ UPAGES + CLSIZE ] ;
	union
	{
		char		a_argc[ CLSIZE * NBPG ] ;
		int		a_argi[ CLSIZE * NBPG / sizeof( int ) ] ;
	} argbuf ;
	extern struct flags	Flg ;
	extern union userstate	User ;
	extern int		Flmem, Flswap ;
	char			*strcat(), *strncpy(), *strsave() ;

	p->pr_csaved = 0 ;
	p->pr_upag = 0 ;
	if ( p->pr_p.p_stat == SZOMB )
		return ( "** Exit **" ) ;
	if ( !(p->pr_p.p_flag & SLOAD) && Flg.flg_o )
		return ( "** Swapped out **" ) ;
	/* Find the process' upage */
	if ( !getupage( p, ptetbl ) )		
		return ( "** No upage **" ) ;
	/* Is this a system process ? */
	if ( p->pr_p.p_flag & SSYS )		
		switch ( p->pr_p.p_pid )
		{
			case 0 :
				p->pr_upag = 1 ;
				return ( "Unix Swapper" ) ;
			case 2 :
				p->pr_upag = 1 ;
				return ( "Unix Pager" ) ;
			default :
				break ;
		}
	/* Look at the top of the upage to locate the command arguments.
	   The page is loaded if the process itself is loaded and the pte
	   contains is marked as valid. */
	if ( (p->pr_p.p_flag & SLOAD)
	&& !ptetbl[0].pg_fod && ptetbl[0].pg_pfnum )
	{	/* If the page is loaded, read the arguments from
		   physical memory. */
		memseek( Flmem, (long)ctob( ptetbl[0].pg_pfnum ) ) ;
		if ( read( Flmem, argbuf.a_argc, CLSIZE*NBPG ) != CLSIZE*NBPG )
			return ( "** Memory read error **" ) ;
	}
	else				
	{	/* Otherwise the page is on the swap device */
		vstodb( 0, CLSIZE, &User.u_us.u_smap, &db, 1 ) ;
# ifdef BSD42
		swseek( (long)dtob( db.db_base ) ) ;
# else
		swseek( (long)ctob( db.db_base ) ) ;
# endif
		if ( Flg.flg_o )
			return ( "** Swapped page **" ) ;
		if ( read( Flswap, argbuf.a_argc, CLSIZE*NBPG ) != CLSIZE*NBPG )
			return ( "** Swap device read error **" ) ;
	}
	/* Look down until the end of command arguments is found. */
	p->pr_upag = 1 ;
	p->pr_csaved = 1 ;
	ip = &argbuf.a_argi[ CLSIZE*NBPG / sizeof( int ) ] ;
	ip -= 2 ;
	while ( *--ip )
		if ( ip == &argbuf.a_argi[0] )
		{	/* If the command arguments cannot be accessed from
			   the user's memory space, get the command name from
			   the system's idea of what the name should be. */
			argbuf.a_argc[0] = '(' ;
			(void)strncpy( &argbuf.a_argc[1], User.u_us.u_comm,
				sizeof( User.u_us.u_comm ) ) ;
			(void)strcat( &argbuf.a_argc[0], ")" ) ;
			return ( strsave( argbuf.a_argc ) ) ;
		}
	/* Process the command arguments, looking for nulls and unprintable
	   characters. */
	cp0 = (char*)(ip + 1) ;
	if ( !*cp0 )			
		cp0++ ;			
	nbad = 0 ;			
	for ( cp = cp0 ; cp < &argbuf.a_argc[ CLSIZE*NBPG ] ; cp++ )
	{
		*cp &= 0177 ;
		if ( !*cp )		
		{	/* Replace nulls with spaces */
			*cp = ' ' ;
			continue ;
		}
		if ( *cp < ' ' || *cp == 0177 )
		{	/* Replace control characters with ?'s */
			if ( ++nbad > 5 )
			{
				*cp++ = ' ' ;
				break ;
			}
			*cp = '?' ;
			continue ;
		}
		if ( !Flg.flg_e && *cp == '=' )
		{	/* Break on an `=' if we are not interested in the
			   environment strings. */
			*cp = '\0' ;
			while ( cp > cp0 && *--cp != ' ' )
				*cp = '\0' ;
			break ;
		}
	}
	while ( *--cp == ' ' )
		*cp = '\0' ;
	return ( strsave( cp0 ) ) ;
}

/*
** VSTODB - Given a base/size pair in virtual swap area,
** return a physical base/size pair which is the
** (largest) initial, physically contiguous block.
/* This code is stolen from the kernel file /sys/sys/vm_drum.c.
*/
vstodb ( vsbase, vssize, dmp, dbp, rev )

register int			vsbase ;
register int			vssize;
struct dmap			*dmp ;
register struct dblock		*dbp ;
int				rev ;

{
	register int		blk ;
	register swblk_t	*ip ;
# ifdef BSD42
	extern struct info	Info ;
# endif

# ifdef BSD42
	blk = Info.i_dmmin ;
# else
	blk = DMMIN ;
# endif
	ip = dmp->dm_map ;
	while ( vsbase >= blk )
	{
		vsbase -= blk ;
# ifdef BSD42
		if ( blk < Info.i_dmmax )
# else
		if ( blk < DMMAX )
# endif
			blk *= 2 ;
		ip++ ;
	}
	dbp->db_size = vssize < blk - vsbase ? vssize : blk - vsbase ;
	dbp->db_base = *ip + (rev ? blk - (vsbase + dbp->db_size) : vsbase);
}
---END-OF-getcmd.c---
echo Extracting getupage.c
cat > getupage.c << '---END-OF-getupage.c---'
# include	"sps.h"
# include	<h/vm.h>
# ifdef BSD42
# include	<vax/pte.h>
# else
# include	<h/pte.h>
# endif
# include	<stdio.h>

/*
** GETUPAGE - Reads the upage for the specified process as well as sufficient
** page tables entries for reading the command arguments. The pte's are read
** into the argument `ptetbl'. The upage is read into the external variable
** `User'. This procedure returns 1 if the upage was successfully read.
*/

# define	usrpt		(Info.i_usrpt)

getupage ( p, ptetbl )

register struct process		*p ;
register struct pte		*ptetbl ;

{
	register int		i ;
	register int		ncl ;
	struct pte		pte ;
	extern struct info	Info ;
	extern union userstate	User ;
	extern int		Flmem, Flkmem, Flswap ;

	/* If the process is not loaded, look for the upage on the swap device*/
	if ( !(p->pr_p.p_flag & SLOAD) )
	{				
# ifdef BSD42
		swseek( (long)dtob( p->pr_p.p_swaddr ) ) ;
# else
		swseek( (long)ctob( p->pr_p.p_swaddr ) ) ;
# endif
		if ( read( Flswap, (char*)&User.u_us, sizeof( struct user ) )
		!= sizeof( struct user ) )
		{
			fprintf( stderr,
				"sps - Can't read upage of process %d\n",
			    p->pr_p.p_pid ) ;
			return ( 0 ) ;
		}
		return ( 1 ) ;		
	}				
	/* The process is loaded. Locate the process pte's by reading
	   the pte of their base address from system virtual address space. */
	memseek( Flkmem, (long)&Info.i_usrptmap[ btokmx(p->pr_p.p_p0br)
		+ p->pr_p.p_szpt-1 ] ) ;
	if ( read( Flkmem, (char*)&pte, sizeof( struct pte ) )
	!= sizeof( struct pte ) )
	{
		fprintf( stderr,
		      "sps - Can't read indir pte for upage of process %d\n",
		    p->pr_p.p_pid ) ;
		return ( 0 ) ;
	}				
	/* Now read the process' pte's from physical memory. We need to access
	   sufficient pte's for the upage and for the command arguments. */
	memseek( Flmem, (long)ctob( pte.pg_pfnum+1 )
		- (UPAGES+CLSIZE)*sizeof( struct pte ) ) ;
	if ( read( Flmem, (char*)ptetbl, (UPAGES+CLSIZE)*sizeof( struct pte ) )
	!= (UPAGES+CLSIZE)*sizeof( struct pte ) )
	{
		fprintf( stderr, "sps - Can't read page table of process %d\n",
			p->pr_p.p_pid ) ;
		return ( 0 ) ;
	}
	/* Now we can read the pages belonging to the upage.
	   Here we read in an entire click at one go. */
	ncl = (sizeof( struct user ) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE) ;
	while ( --ncl >= 0 )		
	{				
		i = ncl * CLSIZE ;
		memseek( Flmem, (long)ctob( ptetbl[ CLSIZE+i ].pg_pfnum ) ) ;
		if ( read( Flmem, User.u_pg[i], CLSIZE*NBPG ) != CLSIZE*NBPG )
		{
			fprintf( stderr,
				"sps - Can't read page 0x%x of process %d\n",
				ptetbl[ CLSIZE+i ].pg_pfnum, p->pr_p.p_pid ) ;
			return ( 0 ) ;
		}
	}
	return ( 1 ) ;
}
---END-OF-getupage.c---
echo Extracting globals1.c
cat > globals1.c << '---END-OF-globals1.c---'
# include	"sps.h"
# include	"flags.h"

/* Read/Write Variables global to the code of sps */

struct info			Info ;		/* Information structure */

struct flags			Flg ;		/* Flag options */

struct summary			Summary ;	/* Summary of processes */

union  userstate		User ;		/* Upage of one process */

int				Flmem, Flkmem, Flswap ;	/* File descriptors */

unsigned			Termwidth ;	/* Width of output device */

short				Lastpgrp ;	/* Last process pgrp printed */

short				Lastuid ;	/* Last process uid printed */
---END-OF-globals1.c---
echo Extracting globals2.c
cat > globals2.c << '---END-OF-globals2.c---'
# include	"sps.h"

/* Read Only variables, global to the code of sps ... */

/* Null ttyline device ... */
struct ttyline			Notty = { 0, 0, "  ", 0	} ;

/*
** The symbol table. For each address read from the kernel during
** initialisation, this table shows the following:
**	i.   the name of that symbol within the kernel ;
**	ii.  whether an extra indirection is needed through the kernel,
**	     i.e. whether the value of that symbol should be obtained
**	     rather than its address.
**	iii. where the obtained value/address is placed in the Info structure ;
**	iv.  whether the obtained value is associated with a reason for
**	     a process wait state.
*/
/* The order of entries in this table is unimportant. */

extern struct info		Info ;

struct symbol	Symbollist[] =
{	
	/* Kernel addresses required in order to access process,
	   tty and upage information. All these addresses should be
	   located in the symbol file during initialisation. */
	{ "_proc",	1,  (caddr_t*)&Info.i_proc0,	(char*)0	},
	{ "_nproc",	1,  (caddr_t*)&Info.i_nproc,	(char*)0	},
	{ "_text",	1,  (caddr_t*)&Info.i_text0,	(char*)0	},
	{ "_ntext",	1,  (caddr_t*)&Info.i_ntext,	(char*)0	},
	{ "_inode",	1,  (caddr_t*)&Info.i_inode0,	(char*)0	},
	{ "_ninode",	1,  (caddr_t*)&Info.i_ninode,	(char*)0	},
	{ "_swbuf",	1,  (caddr_t*)&Info.i_swbuf0,	(char*)0	},
	{ "_nswbuf",	1,  (caddr_t*)&Info.i_nswbuf,	(char*)0	},
	{ "_buf",	1,  (caddr_t*)&Info.i_buf0,	(char*)0	},
	{ "_nbuf",	1,  (caddr_t*)&Info.i_nbuf,	(char*)0	},
	{ "_ecmx",	1,  (caddr_t*)&Info.i_ecmx,	(char*)0	},
	{ "_Usrptmap",	0,  (caddr_t*)&Info.i_usrptmap,	(char*)0	},
	{ "_usrpt",	0,  (caddr_t*)&Info.i_usrpt,	(char*)0	},
	{ "_cdevsw",	0,  (caddr_t*)&Info.i_cdevsw,	(char*)0	},
# ifdef BSD42
	{ "_quota",	1,  (caddr_t*)&Info.i_quota0,	(char*)0	},
	{ "_nquota",	1,  (caddr_t*)&Info.i_nquota,	(char*)0	},
	{ "_dmmin",	1,  (caddr_t*)&Info.i_dmmin,	(char*)0	},
	{ "_dmmax",	1,  (caddr_t*)&Info.i_dmmax,	(char*)0	},
	{ "_mbutl",	0,  (caddr_t*)&Info.i_mbutl,	(char*)0	},
# else
	{ "_hz",	1,  (caddr_t*)&Info.i_hz,	(char*)0	},
# endif
# ifdef CHAOS
	{ "_Chconntab",	0,  &Info.i_Chconntab,		(char*)0	},
# endif
	/* Kernel addresses associated with process wait states.
	   It is not important if some of these addresses are unresolved
	   at initialisation. */
	{ "_fltab",	0,  &Info.i_waitstate[0],	"floppy"	},
	{ "_tu",	0,  &Info.i_waitstate[1],	"tu58"		},
	{ "_bfreelist",	0,  &Info.i_waitstate[2],	"buffer"	},
	{ "_lp_softc",	0,  &Info.i_waitstate[3],	"printr"	},
	{ "_lbolt",	0,  &Info.i_waitstate[4],	"lbolt"		},
	{ "_runin",	0,  &Info.i_waitstate[5],	"runin"		},
	{ "_runout",	0,  &Info.i_waitstate[6],	"runout"	},
	{ "_ipc",	0,  &Info.i_waitstate[7],	"ptrace"	},
	{ "_u",		0,  &Info.i_waitstate[8],	"pause"		},
	{ "_freemem",	0,  &Info.i_waitstate[9],	"freemm"	},
	{ "_kernelmap",	0,  &Info.i_waitstate[10],	"kermap"	},
	{ "_cwaiting",	0,  &Info.i_waitstate[11],	"cwait"		},
	{ "_rhpbuf",	0,  &Info.i_waitstate[12],	"rhpbuf"	},
	{ "_rhtbuf",	0,  &Info.i_waitstate[13],	"rhtbuf"	},
	{ "_ridcbuf",	0,  &Info.i_waitstate[14],	"ridcbf"	},
	{ "_rikbuf",	0,  &Info.i_waitstate[15],	"rikbuf"	},
	{ "_rmtbuf",	0,  &Info.i_waitstate[16],	"rmtbuf"	},
	{ "_rrkbuf",	0,  &Info.i_waitstate[17],	"rrkbuf"	},
	{ "_rrlbuf",	0,  &Info.i_waitstate[18],	"rrlbuf"	},
	{ "_rrxbuf",	0,  &Info.i_waitstate[19],	"rrxbuf"	},
	{ "_rswbuf",	0,  &Info.i_waitstate[20],	"rswbuf"	},
	{ "_rtmbuf",	0,  &Info.i_waitstate[21],	"rtmbuf"	},
	{ "_rtsbuf",	0,  &Info.i_waitstate[22],	"rtsbuf"	},
	{ "_rudbuf",	0,  &Info.i_waitstate[23],	"rudbuf"	},
	{ "_rupbuf",	0,  &Info.i_waitstate[24],	"rupbuf"	},
	{ "_rutbuf",	0,  &Info.i_waitstate[25],	"rutbuf"	},
	{ "_rvabuf",	0,  &Info.i_waitstate[26],	"rvabuf"	},
	{ "_rvpbuf",	0,  &Info.i_waitstate[27],	"rvpbuf"	},
	{ "_chtbuf",	0,  &Info.i_waitstate[28],	"chtbuf"	},
	{ "_cmtbuf",	0,  &Info.i_waitstate[29],	"cmtbuf"	},
	{ "_ctmbuf",	0,  &Info.i_waitstate[30],	"ctmbuf"	},
	{ "_ctsbuf",	0,  &Info.i_waitstate[31],	"ctsbuf"	},
	{ "_cutbuf",	0,  &Info.i_waitstate[32],	"cutbuf"	},
# ifdef BSD42
	{ "_selwait",	0,  &Info.i_waitstate[33],	"select"	},
# endif
# ifdef CHAOS
	{ "_Chrfclist",	0,  &Info.i_waitstate[34],	"chrfc"		},
# endif
	{ (char*)0,	0,  (caddr_t*)0,		(char*)0	}
} ;
---END-OF-globals2.c---
echo Extracting hashuid.c
cat > hashuid.c << '---END-OF-hashuid.c---'
# include	"sps.h"

/* The hashing functions themselves ... */
# define	HASHFN1( a )		(((a)*91 + 17) % MAXUSERID)
# define	HASHFN2( a )		(((a) + 47) % MAXUSERID)

/*
** HASHUID - Returns a pointer to a slot in the hash table that corresponds
** to the hash table entry for `uid'. It returns a null pointer if there is
** no such slot.
*/
struct hashtab	*hashuid ( uid )

int				uid ;

{
	register struct hashtab	*hp ;
	register int		i ;
	register int		j ;
	extern struct info	Info ;

	j = HASHFN1( uid ) ;
	for ( i = 0 ; i < MAXUSERID ; i++ )
	{
		hp = &Info.i_hnames[ j ] ;
		if ( !hp->h_uname[0] )
			return ( (struct hashtab*)0 ) ;
		if ( hp->h_uid == uid )
			return ( hp ) ;
		j = HASHFN2( j ) ;
	}
	return ( (struct hashtab*)0 ) ;
}

/*
** HASHNEXT - Returns a pointer to the next slot in the hash table that
** may be use for storing information for `uid'. It returns a null pointer
** if there are no more free slots available.
*/
struct hashtab	*hashnext ( uid )

int				uid ;

{
	register struct hashtab	*hp ;
	register int		i ;
	register int		j ;
	extern struct info	Info ;

	j = HASHFN1( uid ) ;
	for ( i = 0 ; i < MAXUSERID ; i++ )
	{
		hp = &Info.i_hnames[ j ] ;
		if ( !hp->h_uname[0] )
			return ( hp ) ;
		j = HASHFN2( j ) ;
	}
	return ( (struct hashtab*)0 ) ;
}
---END-OF-hashuid.c---