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---