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

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

Send comments, suggestions, bug reports, bug fixes, etc. 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 initialise.c
cat > initialise.c << '---END-OF-initialise.c---'
# include	"sps.h"
# include	"flags.h"
# include	<pwd.h>
# include	<stdio.h>

/*
** INITIALISE - Called to reset the `Info' structure with new kernel
** addresses and user and tty information.
*/
initialise ()
{
	register FILE		*fd ;
	char			*fileinfo ;
	extern struct flags	Flg ;
	extern struct info	Info ;
	FILE			*fopen() ;

	fileinfo = Flg.flg_j ? Flg.flg_j : FILE_INFO ;
	/* Read kernel addresses */
	initsymbols() ;			
	/* Read user names */
	initusers() ;			
	(void)umask( ~0644 ) ;		
	if ( !(fd = fopen( fileinfo, "w" )) )
	{
		fprintf( stderr, "sps - Can't create info file %s", fileinfo ) ;
		sysperror() ;
	}
	/* Find tty addresses */
	inittty() ;			
	if ( fwrite( (char*)&Info, sizeof( struct info ), 1, fd ) != 1 )
	{
		fprintf( stderr, "sps - Can't write info file %s", fileinfo ) ;
		sysperror() ;
		exit( 1 ) ;
	}
	(void)fclose( fd ) ;
	printf( "sps is initialised\n" ) ;
}

/* INITUSERS - Read the passwd file and fill in the user name arrays */
initusers ()
{
	register struct passwd	*pw ;
	register struct hashtab	*hp ;
	struct passwd		*getpwent() ;
	char			*strncpy() ;
	struct hashtab		*hashuid(), *hashnext() ;

	while ( pw = getpwent() )
	{	/* For each user in the passwd file, first see if that uid
		   has been already allocated in the hash table. */
		if ( hp = hashuid( pw->pw_uid ) )
		{
			fprintf( stderr,
		   "sps - Names %s and %s conflict in passwd file for uid %d\n",
				hp->h_uname, pw->pw_name, pw->pw_uid ) ;
			continue ;
		}
		/* Try to find a free slot in the hash table and fill it. */
		if ( !(hp = hashnext( pw->pw_uid )) )
			prexit( "sps - Too many users in passwd file\n" ) ;
		hp->h_uid = pw->pw_uid ;
		(void)strncpy( hp->h_uname, pw->pw_name, UNAMELEN ) ;
	}
	(void)endpwent() ;
}
---END-OF-initialise.c---
echo Extracting initsymbols.c
cat > initsymbols.c << '---END-OF-initsymbols.c---'
# include	"sps.h"
# include	"flags.h"
# ifdef BSD42
# include	<sys/file.h>
# endif
# include	<nlist.h>
# include	<stdio.h>

/* INITSYMBOLS - Reads kmem values into the Info structure */
/*
** THIS CODE COPIES KMEM VALUES INTO THE INFO STRUCTURE ASSUMING THAT
** VALUES READ FROM THE KERNEL HAVE TYPE CADDR_T. THEREFORE, WE ARE
** MAKING THE DUBIOUS ASSUMPTION THAT INTS, POINTERS AND CADDR_T's
** HAVE IDENTICAL SIZES.
*/
initsymbols ()
{
	register struct nlist	*np ;
	register struct symbol	*s ;
	register struct nlist	*np0 ;
	char			*filesymbol ;
	extern int		Flkmem ;
	extern struct flags	Flg ;
	extern struct symbol	Symbollist[] ;
	extern struct info	Info ;
	char			*getcore() ;
	char			*strncpy() ;

	filesymbol = Flg.flg_s ? Flg.flg_s : FILE_SYMBOL ;
	/* Find the length of the symbol table */
	for ( s = Symbollist ; s->s_kname ; s++ )
		;
	/* Construct an nlist structure by copying names from the symbol table*/
	np0 = (struct nlist*)getcore( (s-Symbollist+1)*sizeof( struct nlist ) );
	for ( s = Symbollist, np = np0 ; s->s_kname ; s++, np++ )
	{					
		np->n_name = s->s_kname ;	
		np[1].n_name = (char*)0 ;	
		np->n_value = 0 ;
	}
# ifdef BSD42
	if ( access( filesymbol, R_OK ) < 0 )
# else
	if ( access( filesymbol, 4 ) < 0 )
# endif
	{
		fprintf( stderr, "sps - Can't open symbol file %s", filesymbol);
		sysperror() ;
	}
	/* Get kernel addresses */
	nlist( filesymbol, np0 ) ;		
	if ( np0[0].n_value == -1 )
	{
		fprintf( stderr, "sps - Can't read symbol file %s", filesymbol);
		sysperror() ;
	}
	for ( s = Symbollist, np = np0 ; s->s_kname ; s++, np++ )
	{					
		if ( !np->n_value )		
		{
			fprintf( stderr, "sps - Can't find symbol %s in %s",
				np->n_name, filesymbol ) ;
			/* Assume this error to be unimportant if the address
			   is only associated with a process wait state.
			   This may happen if the system has been configured
			   without a particular device. */
			fprintf( stderr, &Info.i_waitstate[ 0 ] <= s->s_info
				&& s->s_info < &Info.i_waitstate[ NWAITSTATE ]
				? " (error is not serious)\n"
				: " (ERROR MAY BE SERIOUS)\n" ) ;
			*s->s_info = (caddr_t)0 ;
			continue ;
		}
		/* If no indirection is required, just copy the obtained value
		   into the `Info' structure. */
		if ( !s->s_indirect )		
		{				
		/* DUBIOUS ASSUMPTION THAT KMEM VALUE HAS SIZE OF A CADDR_T */
			*s->s_info = (caddr_t)np->n_value ;
			continue ;		
		}				
		/* Otherwise one level of indirection is required. Using the
		   obtained address, look again in the kernel for the value */
		memseek( Flkmem, (long)np->n_value ) ;
		/* DUBIOUS ASSUMPTION THAT KMEM VALUE HAS SIZE OF A CADDR_T */
		(void)read( Flkmem, (char*)s->s_info, sizeof(caddr_t) ) ;
	}
	free( (char*)np0 ) ;
}
---END-OF-initsymbols.c---
echo Extracting inittty.c
cat > inittty.c << '---END-OF-inittty.c---'
# include	"sps.h"
# include	<h/conf.h>
# include	<h/tty.h>
# include	<sys/stat.h>
# include	<stdio.h>

/* INITTTY - Initialise the tty part of the info structure */
inittty ()
{
	register struct ttyline	*lp ;
# ifdef BSD42
	register struct direct	*dp ;
	DIR			*dfd ;
# else
	struct direct		dir ;
	FILE			*dfd ;
# endif
	struct stat		statbuf ;
	static char		filedev[] = FILE_DEV ;
	extern struct info	Info ;
	extern int		Flkmem ;
# ifdef BSD42
	DIR			*opendir() ;
	struct direct		*readdir() ;
# else
	FILE			*fopen() ;
# endif

	lp = Info.i_ttyline ;
# ifdef BSD42
	if ( !(dfd = opendir( filedev )) )
# else
	if ( !(dfd = fopen( filedev, "r" )) )
# endif
		prexit( "Can't open %s\n", filedev ) ;
	if ( chdir( filedev ) < 0 )
		prexit( "sps - Can't chdir to %s\n", filedev ) ;
# ifdef BSD42
	/* Read all entries in the device directory, looking for ttys */
	while ( dp = readdir( dfd ) )
	{	/* Skip entries that do not match "tty" or "console" */
		if ( strncmp( "tty", dp->d_name, 3 )
		&&   strcmp( "console", dp->d_name ) )
			continue ;
		/* Skip "tty" itself */
		if ( dp->d_namlen == 3 )
			continue ;
# ifdef CHAOS
		/* Skip chaos ttys ; they are accessed during ttystatus() */
		if ( dp->d_namelen > 3 &&
		dp->d_name[ sizeof( "tty" ) - 1 ] == 'C' )
			continue ;
# endif
		if ( lp >= &Info.i_ttyline[ MAXTTYS ] )
			prexit( "sps - Too many ttys in %s\n", filedev ) ;
		/* Copy the tty name into the information entry */
		if ( !strcmp( dp->d_name, "console" ) )
		{
			lp->l_name[0] = 'c' ;
			lp->l_name[1] = 'o' ;
		}
		else
		{
			lp->l_name[0] = dp->d_name[3] ;
			lp->l_name[1] = dp->d_name[4] ;
		}
		/* Ensure that this tty is actually a valid character device */
		if ( stat( dp->d_name, &statbuf ) < 0 )
			continue ;
# else
	/* Read all entries in the device directory, looking for ttys */
	while ( fread( (char*)&dir, sizeof( struct direct ), 1, dfd ) == 1 )
	{	/* Skip entries that do not match "tty" or "console" */
		if ( strncmp( "tty", dir.d_name, 3 )
		&&   strcmp( "console", dir.d_name ) )
			continue ;
		/* Skip "tty" itself */
		if ( dir.d_name[3] == '\0' )
			continue ;
# ifdef CHAOS
		/* Skip chaos ttys ; they are accessed during ttystatus() */
		if ( dir.d_name[ sizeof( "tty" ) - 1 ] == 'C' )
			continue ;
# endif
		if ( lp >= &Info.i_ttyline[ MAXTTYS ] )
			prexit( "sps - Too many ttys in %s\n", filedev ) ;
		/* Copy the tty name into the information entry */
		if ( !strcmp( dir.d_name, "console" ) )
		{
			lp->l_name[0] = 'c' ;
			lp->l_name[1] = 'o' ;
		}
		else
		{
			lp->l_name[0] = dir.d_name[3] ;
			lp->l_name[1] = dir.d_name[4] ;
		}
		/* Ensure that this tty is actually a valid character device */
		if ( stat( dir.d_name, &statbuf ) < 0 )
			continue ;
# endif
		if ( (statbuf.st_mode & S_IFMT) != S_IFCHR )
			continue ;
		/* Find the device # of the tty and the address of its
		   associated struct tty in /dev/kmem. */
		lp->l_dev = statbuf.st_rdev ;
		memseek( Flkmem,
		     (long)&Info.i_cdevsw[ major( statbuf.st_rdev ) ].d_ttys ) ;
		if ( read( Flkmem, (char*)&lp->l_addr, sizeof( lp->l_addr ) )
		!= sizeof( lp->l_addr ) )
		{
			fprintf( stderr, "sps - Can't read struct tty for %s\n",
# ifdef BSD42
				dp->d_name ) ;
# else
				dir.d_name ) ;
# endif
			continue ;
		}
		lp->l_addr += (int)minor( statbuf.st_rdev ) ;
		lp++ ;
	}
# ifdef BSD42
	(void)closedir( dfd ) ;
# else
	(void)fclose( dfd ) ;
# endif
}
---END-OF-inittty.c---
echo Extracting main.c
cat > main.c << '---END-OF-main.c---'
# include	"sps.h"
# include	"flags.h"
# include	<h/text.h>
# include	<stdio.h>

/* SPS - Show Process Status */
/* J. R. Ward - Hasler AG Bern - 24 May 1985 */
main ( argc,argv )

int				argc ;
char				**argv ;

{
	register struct process	*plist ;
	register struct process	*process ;
	register struct text	*text ;
	int			flinfo ;
	extern struct flags	Flg ;
	extern struct info	Info ;
	extern int		Flmem ;
	extern int		Flkmem ;
	extern int		Flswap ;
	char			*getcore() ;
	struct process		*needed(), *mktree() ;

	/* Renice as fast as possible for root (Suggested by Gregorio!mogul) */
	if ( !getuid() )
		(void)nice( -40 ) ;
	/* Decode the flag arguments */
	flagdecode( argc, argv ) ;	
	/* Determine the terminal width */
	if ( !Flg.flg_w && !Flg.flg_N && !Flg.flg_i )
		termwidth() ;
	/* Open the cpu physical memory, kernel virtual memory and swap device*/
	if ( Flg.flg_k )
	{
		Flmem = openfile( Flg.flg_k ) ;
		Flkmem = Flmem ;
	}
	else
	{
		Flmem = openfile( FILE_MEM ) ;
		Flkmem = openfile( FILE_KMEM ) ;
		if ( !Flg.flg_o )
			Flswap = openfile( FILE_SWAP ) ;
	}
	if ( Flg.flg_i )
	{	/* -i flag for info file initialisation */
		initialise() ;		
		exit( 0 ) ;
	}
	/* Read the information file */
	flinfo = openfile( Flg.flg_j ? Flg.flg_j : FILE_INFO ) ;
	if ( read( flinfo, (char*)&Info, sizeof( struct info ) )
	!= sizeof( struct info ) )
	{
		fprintf( stderr, "sps - Can't read info file %s",
			Flg.flg_j ? Flg.flg_j : FILE_INFO ) ;
		sysperror() ;
	}
	(void)close( flinfo ) ;
	/* Find current tty status */
	ttystatus() ;			
	/* Now that we know the available ttys, decode the flags */
	flagsetup() ;			
	process = (struct process*)getcore(Info.i_nproc*sizeof(struct process));
	text = (struct text*)getcore( Info.i_ntext * sizeof( struct text ) ) ;
	do
	{	/* Read current process and text status */
		readstatus( process, text ) ;
		/* Select those processes to be listed */
		plist = needed( process, text ) ;
		/* Form a tree of listed processes */
		plist = mktree( process, plist ) ;
		if ( !Flg.flg_N )
		{	/* Print the processes */
			prheader() ;
			printall( plist, 0 ) ;
		}
		prsummary() ;
		(void)fflush( stdout ) ;
		if ( Flg.flg_r )	
		{	/* If repeating, again get tty status */
			ttystatus() ;
			if ( Flg.flg_rdelay )
# ifdef BSD42
				sleep( Flg.flg_rdelay ) ;
# else
				sleep( (int)Flg.flg_rdelay ) ;
# endif
		}
	} while ( Flg.flg_r ) ;
	exit( 0 ) ;
}
---END-OF-main.c---
echo Extracting mktree.c
cat > mktree.c << '---END-OF-mktree.c---'
# include	"sps.h"

/*
** MKTREE - Sort the needed processes by subtree and at the top by user.
** This procedure takes a list of processes (as returned by needed())
** and returnes a pointer to a sorted list.
*/
struct process	*mktree ( process, plist )

struct process			*process ;
struct process			*plist ;

{
	register struct process	*p ;
	register struct process	*pp ;
	register struct process	*lp ;
	struct process		*op ;
	struct process		proot ;

	proot.pr_sibling = (struct process*)0 ;
	for ( p = plist ; p ; p = p->pr_plink )
	{
		if ( p->pr_pptr > &process[1] )
		{
			for ( pp = plist ; pp ; pp = pp->pr_plink )
			{
				if ( pp != p->pr_pptr )
					continue ;
				if ( lp = pp->pr_child )
				{	/* Does process have children ? */
					op = (struct process*)0 ;
					while (lp &&
					lp->pr_p.p_pid < p->pr_p.p_pid )
					{
						op = lp ;
						lp=lp->pr_sibling ;
					}
					if ( op )
					{
						p->pr_sibling = lp ;
						op->pr_sibling = p ;
						break ;
					}
				}	
				p->pr_sibling = lp ;
				pp->pr_child = p ;
				break ;
			}
			if ( pp )
				continue ;
		}
		/* We have a top level process, sort into top level list.
		   The top level is sorted firstly by user-id and then
		   by process-id. */
		lp = &proot ;
		pp = lp->pr_sibling ;
		while ( pp )
		{
			if ( p->pr_p.p_uid < pp->pr_p.p_uid )
				break ;
			if ( p->pr_p.p_uid == pp->pr_p.p_uid
			&& p->pr_p.p_pid < pp->pr_p.p_pid )
				break ;
			lp = pp, pp = pp->pr_sibling ;
		}
		p->pr_sibling = lp->pr_sibling ;
		lp->pr_sibling = p ;
	}
	return ( proot.pr_sibling ) ;
}
---END-OF-mktree.c---
echo Extracting needed.c
cat > needed.c << '---END-OF-needed.c---'
# include	"sps.h"
# include	"flags.h"
# include	<h/text.h>
# include	<stdio.h>

/*
** NEEDED - Determine which processes are needed for the printout
** and add these to a list of needed processes.
*/
struct process	*needed ( process, text )

register struct process		*process ;
struct text			*text ;

{
	register struct process	*p ;
	register struct process	*plist ;
	struct process		*lastp ;
	int			uid ;
	extern struct flags	Flg ;
	extern union userstate	User ;
	extern struct info	Info ;
	extern struct ttyline	Notty ;
	struct ttyline		*findtty() ;
	char			*getcmd() ;

	plist = (struct process*)0 ;
	lastp = &process[ Info.i_nproc ] ;
	/* Normalise internal pointers from kernel addresses. For each kmem
	   address in the `proc' and `text' structures, we convert that
	   address for our own internal use. */
	for ( p = process ; p < lastp ; p++ )
	{				
		if ( !p->pr_p.p_stat )	
			continue ;
		/* Normalise internal text pointers */
		if ( p->pr_p.p_textp )
			p->pr_p.p_textp = &text[p->pr_p.p_textp - Info.i_text0];
		/* Normalise internal linked list of processes */
		p->pr_plink = p->pr_p.p_link ?
			&process[ p->pr_p.p_link  - Info.i_proc0 ] :
			(struct process*)0 ;
		/* Normalise internal parent pointers */
		p->pr_pptr = p->pr_p.p_pptr ?
			&process[ p->pr_p.p_pptr - Info.i_proc0 ] :
			(struct process*)0 ;
		/* Check for valid parent pointers */
		if ( !p->pr_pptr )
		{
			p->pr_pptr = process ;
			continue ;
		}
		if ( p->pr_pptr < process || p->pr_pptr >= lastp )
		{
			fprintf( stderr, "sps - process %d has bad pptr\n",
				p->pr_p.p_pid ) ;
			p->pr_pptr = process ;
		}
	}
	/* For each process, see if it is a candidate for selection.
	   If so, retrieve its command arguments and upage information. */
	uid = getuid() ;
	for ( p = process ; p < lastp ; p++ )
	{				
		if ( !p->pr_p.p_stat )
			continue ;
		/* Count processes and sizes */
		summarise( p ) ;
		/* Select the given processes. Bear in mind that selection
		   of processes based on the `F' and `T' flags must be
		   postponed until the upage is accessed. */
		if ( !Flg.flg_F && !Flg.flg_T && !selectproc( p, process, uid ))
			continue ;
		/* Try to find the process' command arguments. Accessing the
		   arguments also involves retrieving the upage. */
		p->pr_cmd = getcmd( p ) ;
		/* If the upage was found successfully, use this information */
		if ( p->pr_upag )	
		{
# ifdef BSD42
			p->pr_rself = User.u_us.u_ru ;
			p->pr_rchild = User.u_us.u_cru ;
# else
			p->pr_vself = User.u_us.u_vm ;
			p->pr_vchild = User.u_us.u_cvm ;
# endif
			p->pr_tty = findtty( p ) ;
			p->pr_files = filecount() ;
		}
		else
			p->pr_tty = &Notty ;
		/* Select on the basis of the `F' and `T' flags */
		if ( Flg.flg_F		
		&& !(p->pr_p.p_pgrp && p->pr_p.p_pgrp == p->pr_tty->l_pgrp) )
			continue ;
		if ( Flg.flg_T && !selecttty( p ) )
			continue ;
		/* Arrive here with a selected process. Add this to the
		   linked list of needed processes. */
		p->pr_plink = plist ;	
		plist = p ;
		p->pr_child = (struct process*)0 ;
		p->pr_sibling = (struct process*)0 ;
	}
	return ( plist ) ;
}

/* SUMMARISE - Summarises the given process into the `Summary' structure */
/*
** SHOULD ACCOUNT HERE FOR THE SIZE OF LOADED PAGE TABLES, BUT WE DON'T REALLY
** KNOW THEIR RESIDENT SIZES.
*/
summarise ( p )

register struct process		*p ;

{
	register struct text	*tp ;
	int			busy ;
	extern struct summary	Summary ;

	Summary.sm_ntotal++ ;
	if ( p->pr_p.p_stat == SZOMB )
		return ;
	/* Firstly, account for processes */
	Summary.sm_ktotal += p->pr_p.p_dsize + p->pr_p.p_ssize ;
	Summary.sm_kloaded += p->pr_p.p_rssize ;
	Summary.sm_kswapped += p->pr_p.p_swrss ;
	if ( p->pr_p.p_flag & SLOAD )
		Summary.sm_nloaded++ ;
	else
		Summary.sm_nswapped++ ;
	busy = (p->pr_p.p_stat == SRUN) || (p->pr_p.p_stat==SSLEEP
	     && (p->pr_p.p_pri<PZERO && p->pr_p.p_pid > MSPID) ) ;
	if ( busy )
	{
		Summary.sm_nbusy++ ;
		Summary.sm_kbusy += p->pr_p.p_dsize + p->pr_p.p_ssize ;
	}
	/* Now account for their texts */
	if ( !(tp = p->pr_p.p_textp) || !tp->x_count )
		return ;		
	Summary.sm_ktotal += tp->x_size ;
	Summary.sm_kloaded += tp->x_rssize ;
	Summary.sm_kswapped += tp->x_swrss ;
	if ( busy )
		Summary.sm_kbusy += tp->x_size ;
	tp->x_count = 0 ;
}
---END-OF-needed.c---
echo Extracting openfiles.c
cat > openfiles.c << '---END-OF-openfiles.c---'
# include	<stdio.h>
# include	"sps.h"
# include	"flags.h"

/* Miscellaneous procedures */

/* OPENFILE - Opens the named file */
openfile ( name )

char				*name ;

{
	register int		fd ;

	if ( (fd = open( name, 0 )) >= 0 )
		return ( fd ) ;
	fprintf( stderr, "sps - Can't open %s", name ) ;
	sysperror() ;
	/* NOTREACHED */
}

/* MEMSEEK - Seek on a special file */
memseek ( fd, pos )

int				fd ;
long				pos ;

{
	extern int		errno ;
	extern struct flags	Flg ;
	long			lseek() ;

	errno = 0 ;
	if ( Flg.flg_k )
		pos &= 0x7fffffff ;
	(void)lseek( fd, pos, 0 ) ;
	if ( errno )
	{
		fprintf( stderr, "sps - Seek failed" ) ;
		sysperror() ;
	}
}

/* SWSEEK - Seek on the swap device */
swseek ( pos )

long				pos ;

{
	extern int		Flswap ;
	extern int		errno ;
	long			lseek() ;

	errno = 0 ;
	(void)lseek( Flswap, pos, 0 ) ;
	if ( errno )
	{
		fprintf( stderr, "sps - Seek failed" ) ;
		sysperror() ;
	}
}

# ifdef	lint
int				errno ;
int				sys_nerr ;
char				*sys_errlist[] ;
# endif

/* SYSPERROR - Reports a system defined error msg and then exits gracefully */
sysperror ()
{
	extern int		errno ;
	extern int		sys_nerr ;
	extern char		*sys_errlist[] ;

	if ( 0 < errno && errno < sys_nerr )
		fprintf( stderr, " : %s", sys_errlist[errno] ) ;
	(void)fputc( '\n', stderr ) ;
	exit( 1 ) ;
}

/* STRSAVE - Store a string in core for later use. */
char	*strsave ( cp )

register char			*cp ;

{
	register char		*chp ;
	char			*getcore(), *strcpy() ;

	chp = getcore( strlen( cp ) + 1 ) ;
	(void)strcpy( chp, cp ) ;
	return ( chp ) ;
}

/* GETCORE - Allocate and return a pointer to the asked for amount of core */
char	*getcore ( size )

register int		 	size ;

{
	register char		*chp ;
	char			*malloc() ;

	if ( chp = malloc( (unsigned)size ) )
		return ( chp ) ;
	fprintf( stderr, "sps - Out of core" ) ;
	sysperror() ;
	/* NOTREACHED */
}

union flaglist	*getflgsp ( argc )

register int		 	argc ;

{
	char			*getcore() ;

	return ( (union flaglist*)getcore( sizeof( union flaglist )*argc ) ) ;
}

/* PREXIT - Print an error message and exit */
/* VARARGS1 */
/* ARGSUSED */
prexit ( fmt, args )

char				*fmt ;

{
	_doprnt( fmt, &args, stderr ) ;
	exit( 1 ) ;
}
---END-OF-openfiles.c---
echo Extracting percentmem.c
cat > percentmem.c << '---END-OF-percentmem.c---'
# include	"sps.h"
# include	<h/text.h>
# ifdef BSD42
# include	<vax/pte.h>
# else
# include	<h/pte.h>
# include	<h/vmparam.h>
# endif
# include	<h/vmmac.h>

/* PERCENTMEM - Returns the percentage of real memory used by this process */
double	percentmem ( p )

register struct process		*p ;

{
	register struct text	*tp ;
	int			szptudot ;
	double			fracmem ;
	extern struct info	Info ;

	tp = p->pr_p.p_textp ;
	if ( !(p->pr_p.p_flag & SLOAD) || !tp )
		return ( 0.0 ) ;
	szptudot = UPAGES + clrnd( ctopt( p->pr_p.p_dsize + p->pr_p.p_ssize ) );
	fracmem = ( (double)p->pr_p.p_rssize + szptudot ) / CLSIZE ;
	if ( tp->x_ccount )
		fracmem += ((double)tp->x_rssize)/CLSIZE/tp->x_ccount ;
	return ( 100.0 * fracmem / (double)Info.i_ecmx ) ;
}
---END-OF-percentmem.c---
echo Extracting prcmd.c
cat > prcmd.c << '---END-OF-prcmd.c---'
# include	"sps.h"
# include	"flags.h"

/* PRCMD - Prints the command arguments according to the switches */
prcmd ( p, lpad, width )

register struct process		*p ;
int				lpad ;
int				width ;

{
	extern struct flags	Flg ;
	extern unsigned		Termwidth ;

	printf( "%*d ", lpad, p->pr_p.p_pid ) ;
	if ( Flg.flg_f )
	{
		printf( "%5d ", p->pr_p.p_ppid ) ;
		width -= 6 ;
	}
	if ( Flg.flg_g )
	{
		printf( "%5d ", p->pr_p.p_pgrp ) ;
		width -= 6 ;
	}
	width += Termwidth ;
	if ( Flg.flg_w )
		printf( "%s\n", p->pr_cmd ) ;
	else if ( width > 0 )
		printf( "%-.*s\n", width, p->pr_cmd ) ;
	if ( p->pr_csaved )
		free( p->pr_cmd ) ;
}
---END-OF-prcmd.c---
echo Extracting prcpu.c
cat > prcpu.c << '---END-OF-prcpu.c---'
# include	"sps.h"

# ifdef BSD42

/* PRCPU - Print cpu time */
prcpu ( time, utime )

register time_t			time ;
time_t				utime ;

{
	time += utime / 1000000 ;
	utime %= 1000000 ;
	if ( time < 0L || time > 1000L*60L*60L )
	{	/* Assume more than 1000 hours is in error */
		printf( "     " ) ;	
		return ;
	}
	if ( time < 60L*10L )
	{	/* Less than 10 minutes */
		printf( "%3d.%1d", (int)time, (int)utime/100000 ) ;
		return ;
	}
	/* If less than 10 hours, print as minutes */
	if ( time < 60L*60L*10L )		
		printf( "%3D M", time/60L ) ;
	else
		printf( "%3D H", time/60L/60L ) ;
}

# else

/* PRCPU - Print cpu time */
prcpu ( time )

register time_t			time ;

{
	extern struct info	Info ;

	if ( time < 0L || time > Info.i_hz*1000L*60L*60L )
	{	/* Assume more than 1000 hours is in error */
		printf( "     " ) ;	
		return ;
	}
	if ( time < Info.i_hz*60L*10L )
	{	/* Less than 10 minutes */
		printf( "%3D.%1D", time/Info.i_hz,
			(time % Info.i_hz / (Info.i_hz/10L)) ) ;
		return ;
	}
	/* If less than 10 hours, print as minutes */
	time /= Info.i_hz ;
	if ( time < 60L*60L*10L )		
		printf( "%3D M", time/60L ) ;
	else
		printf( "%3D H", time/60L/60L ) ;
}

# endif
---END-OF-prcpu.c---
echo Extracting prheader.c
cat > prheader.c << '---END-OF-prheader.c---'
# include	"sps.h"
# include	"flags.h"

/* PRHEADER - Print a header according to the switches */
prheader ()
{
	extern struct flags	Flg ;

	printf( "Ty User    %s Proc#", Flg.flg_v ?
		" Status Fl Nice Virtual Resident %M  Time Child %C" :
		Flg.flg_d ?
		"  Files    PageFaults Swap BlockI/O Kbytsecs" : "" ) ;
	if ( Flg.flg_f )
		printf( " Ppid#" ) ;
	if ( Flg.flg_g )
		printf( " Pgrp#" ) ;
	printf( " Command\n" ) ;
}
---END-OF-prheader.c---
echo Extracting printall.c
cat > printall.c << '---END-OF-printall.c---'
# include	<stdio.h>
# include	"sps.h"

/* PRINTALL - Recursively print the process tree. */
printall ( p, md )

register struct process		*p ;
register int			md ;

{
	while ( p )
	{	/* Print this process */
		printproc( p, md ) ;	
		(void)fflush( stdout ) ;
		/* Print child processes */
		printall( p->pr_child, md+1 ) ;
		/* Print brother processes */
		p = p->pr_sibling ;	
	}
}
---END-OF-printall.c---