rs@uunet.UU.NET (Rich Salz) (07/23/87)
Submitted-by: robert@hslrswi.UUCP (Robert Ward) Posting-Number: Volume 10, Issue 62 Archive-name: sps/Part03 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 3)." # Contents: patches sps.man # Wrapped by rs@uunet on Wed Jul 22 20:09:12 1987 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f patches -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"patches\" else echo shar: Extracting \"patches\" \(26834 characters\) sed "s/^X//" >patches <<'END_OF_patches' Xdiff -b -c sps/Makefile.4.2 sps.old/Makefile.4.2 X*** sps/Makefile.4.2 Fri Dec 5 09:22:35 1986 X--- sps.old/Makefile.4.2 Wed Dec 17 13:57:20 1986 X*************** X*** 1,4 **** X! # Makefile for SPS (Vax 4.2BSD and Ultrix1.2 UNIX Version) X X PROG = sps X OBJS = filecount.o findtty.o flagdecode.o flagsetup.o \ X--- 1,4 ---- X! # Makefile for SPS (4.2BSD UNIX Version) X X PROG = sps X OBJS = filecount.o findtty.o flagdecode.o flagsetup.o \ X*************** X*** 11,17 **** X CC = cc X CFLAGS = -DBSD42 -I/sys X LIBS = -ltermlib X- DIRINSTALL = /bin X X all: $(PROG) X .c.o: X--- 11,16 ---- X*************** X*** 27,36 **** X X install: $(PROG) X strip $(PROG) X! mv $(PROG) $(DIRINSTALL)/$(PROG) X! /etc/chown root $(DIRINSTALL)/$(PROG) X! chgrp kmem $(DIRINSTALL)/$(PROG) X! chmod 2755 $(DIRINSTALL)/$(PROG) X X lint: X lint -x -b $(CFLAGS) *.c X--- 26,33 ---- X X install: $(PROG) X strip $(PROG) X! mv $(PROG) /bin/$(PROG) X! /etc/chown root /bin/$(PROG) X X lint: X lint -x -b $(CFLAGS) *.c XOnly in sps: Makefile.4.3 Xdiff -b -c sps/Makefile.sun sps.old/Makefile.sun X*** sps/Makefile.sun Tue Nov 25 11:34:08 1986 X--- sps.old/Makefile.sun Wed Dec 17 13:57:25 1986 X*************** X*** 1,4 **** X! # Makefile for SPS (Sun-2 and Sun-3, 4.2BSD UNIX Version) X X PROG = sps X OBJS = filecount.o findtty.o flagdecode.o flagsetup.o \ X--- 1,4 ---- X! # Makefile for SPS (Sun 4.2BSD UNIX Version) X X PROG = sps X OBJS = filecount.o findtty.o flagdecode.o flagsetup.o \ X*************** X*** 11,17 **** X CC = cc X CFLAGS = -DSUN -DBSD42 -I/sys X LIBS = -ltermlib X- DIRINSTALL = /bin X X all: $(PROG) X .c.o: X--- 11,16 ---- X*************** X*** 27,36 **** X X install: $(PROG) X strip $(PROG) X! mv $(PROG) $(DIRINSTALL)/$(PROG) X! /etc/chown root $(DIRINSTALL)/$(PROG) X! chgrp kmem $(DIRINSTALL)/$(PROG) X! chmod 2755 $(DIRINSTALL)/$(PROG) X X lint: X lint -x -b $(CFLAGS) *.c X--- 26,33 ---- X X install: $(PROG) X strip $(PROG) X! mv $(PROG) /bin/$(PROG) X! /etc/chown root /bin/$(PROG) X X lint: X lint -x -b $(CFLAGS) *.c Xdiff -b -c sps/findtty.c sps.old/findtty.c X*** sps/findtty.c Tue Nov 25 11:34:10 1986 X--- sps.old/findtty.c Wed Dec 17 13:57:30 1986 X*************** X*** 1,5 **** X # include "sps.h" X- # include <h/ioctl.h> X # include <h/tty.h> X X /* FINDTTY - Attempts to determine to which tty a process is connected */ X--- 1,4 ---- Xdiff -b -c sps/flagsetup.c sps.old/flagsetup.c X*** sps/flagsetup.c Tue Nov 25 11:34:12 1986 X--- sps.old/flagsetup.c Wed Dec 17 13:57:49 1986 X*************** X*** 1,6 **** X # include "sps.h" X # include "flags.h" X- # include <h/ioctl.h> X # include <h/tty.h> X X /* X--- 1,5 ---- Xdiff -b -c sps/globals2.c sps.old/globals2.c X*** sps/globals2.c Tue Nov 25 11:34:15 1986 X--- sps.old/globals2.c Wed Dec 17 13:58:26 1986 X*************** X*** 40,67 **** X { "_usrpt", 0, (caddr_t*)&Info.i_usrpt, (char*)0 }, X { "_cdevsw", 0, (caddr_t*)&Info.i_cdevsw, (char*)0 }, X # ifdef BSD42 X- # ifndef SUN X { "_quota", 1, (caddr_t*)&Info.i_quota0, (char*)0 }, X { "_nquota", 1, (caddr_t*)&Info.i_nquota, (char*)0 }, X- # endif SUN X { "_dmmin", 1, (caddr_t*)&Info.i_dmmin, (char*)0 }, X { "_dmmax", 1, (caddr_t*)&Info.i_dmmax, (char*)0 }, X { "_mbutl", 0, (caddr_t*)&Info.i_mbutl, (char*)0 }, X # else X { "_hz", 1, (caddr_t*)&Info.i_hz, (char*)0 }, X! # endif BSD42 X # ifdef CHAOS X { "_Chconntab", 0, &Info.i_Chconntab, (char*)0 }, X! # endif CHAOS X /* Kernel addresses associated with process wait states. X It is not important if some of these addresses are unresolved X at initialisation. */ X- # ifndef SUN X { "_fltab", 0, &Info.i_waitstate[0], "floppy" }, X { "_tu", 0, &Info.i_waitstate[1], "tu58" }, X- { "_lp_softc", 0, &Info.i_waitstate[3], "printr" }, X- # endif SUN X { "_bfreelist", 0, &Info.i_waitstate[2], "buffer" }, X { "_lbolt", 0, &Info.i_waitstate[4], "lbolt" }, X { "_runin", 0, &Info.i_waitstate[5], "runin" }, X { "_runout", 0, &Info.i_waitstate[6], "runout" }, X--- 40,63 ---- X { "_usrpt", 0, (caddr_t*)&Info.i_usrpt, (char*)0 }, X { "_cdevsw", 0, (caddr_t*)&Info.i_cdevsw, (char*)0 }, X # ifdef BSD42 X { "_quota", 1, (caddr_t*)&Info.i_quota0, (char*)0 }, X { "_nquota", 1, (caddr_t*)&Info.i_nquota, (char*)0 }, X { "_dmmin", 1, (caddr_t*)&Info.i_dmmin, (char*)0 }, X { "_dmmax", 1, (caddr_t*)&Info.i_dmmax, (char*)0 }, X { "_mbutl", 0, (caddr_t*)&Info.i_mbutl, (char*)0 }, X # else X { "_hz", 1, (caddr_t*)&Info.i_hz, (char*)0 }, X! # endif X # ifdef CHAOS X { "_Chconntab", 0, &Info.i_Chconntab, (char*)0 }, X! # endif X /* Kernel addresses associated with process wait states. X It is not important if some of these addresses are unresolved X at initialisation. */ X { "_fltab", 0, &Info.i_waitstate[0], "floppy" }, X { "_tu", 0, &Info.i_waitstate[1], "tu58" }, X { "_bfreelist", 0, &Info.i_waitstate[2], "buffer" }, X+ { "_lp_softc", 0, &Info.i_waitstate[3], "printr" }, 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*************** X*** 70,106 **** X { "_freemem", 0, &Info.i_waitstate[9], "freemm" }, X { "_kernelmap", 0, &Info.i_waitstate[10], "kermap" }, X { "_cwaiting", 0, &Info.i_waitstate[11], "cwait" }, X # ifdef BSD42 X! { "_selwait", 0, &Info.i_waitstate[12], "select" }, X! # endif BSD42 X # ifdef CHAOS X! { "_Chrfclist", 0, &Info.i_waitstate[13], "chrfc" }, X # endif X! # ifndef SUN X! { "_rhpbuf", 0, &Info.i_waitstate[14], "rhpbuf" }, X! { "_rhtbuf", 0, &Info.i_waitstate[15], "rhtbuf" }, X! { "_ridcbuf", 0, &Info.i_waitstate[16], "ridcbf" }, X! { "_rikbuf", 0, &Info.i_waitstate[17], "rikbuf" }, X! { "_rmtbuf", 0, &Info.i_waitstate[18], "rmtbuf" }, X! { "_rrkbuf", 0, &Info.i_waitstate[19], "rrkbuf" }, X! { "_rrlbuf", 0, &Info.i_waitstate[20], "rrlbuf" }, X! { "_rrxbuf", 0, &Info.i_waitstate[21], "rrxbuf" }, X! { "_rswbuf", 0, &Info.i_waitstate[22], "rswbuf" }, X! { "_rtmbuf", 0, &Info.i_waitstate[23], "rtmbuf" }, X! { "_rtsbuf", 0, &Info.i_waitstate[24], "rtsbuf" }, X! { "_rudbuf", 0, &Info.i_waitstate[25], "rudbuf" }, X! { "_rupbuf", 0, &Info.i_waitstate[26], "rupbuf" }, X! { "_rutbuf", 0, &Info.i_waitstate[27], "rutbuf" }, X! { "_rvabuf", 0, &Info.i_waitstate[28], "rvabuf" }, X! { "_rvpbuf", 0, &Info.i_waitstate[29], "rvpbuf" }, X! { "_chtbuf", 0, &Info.i_waitstate[30], "chtbuf" }, X! { "_cmtbuf", 0, &Info.i_waitstate[31], "cmtbuf" }, X! { "_ctmbuf", 0, &Info.i_waitstate[32], "ctmbuf" }, X! { "_ctsbuf", 0, &Info.i_waitstate[33], "ctsbuf" }, X! { "_cutbuf", 0, &Info.i_waitstate[34], "cutbuf" }, X! # else X! { "_async_bufhead", 0, &Info.i_waitstate[14], "async" }, X! { "_desktops", 0, &Info.i_waitstate[15], "dtops" }, X! # endif SUN X { (char*)0, 0, (caddr_t*)0, (char*)0 } X } ; X--- 66,100 ---- 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+ { "_rhpbuf", 0, &Info.i_waitstate[12], "rhpbuf" }, X+ { "_rhtbuf", 0, &Info.i_waitstate[13], "rhtbuf" }, X+ { "_ridcbuf", 0, &Info.i_waitstate[14], "ridcbf" }, X+ { "_rikbuf", 0, &Info.i_waitstate[15], "rikbuf" }, X+ { "_rmtbuf", 0, &Info.i_waitstate[16], "rmtbuf" }, X+ { "_rrkbuf", 0, &Info.i_waitstate[17], "rrkbuf" }, X+ { "_rrlbuf", 0, &Info.i_waitstate[18], "rrlbuf" }, X+ { "_rrxbuf", 0, &Info.i_waitstate[19], "rrxbuf" }, X+ { "_rswbuf", 0, &Info.i_waitstate[20], "rswbuf" }, X+ { "_rtmbuf", 0, &Info.i_waitstate[21], "rtmbuf" }, X+ { "_rtsbuf", 0, &Info.i_waitstate[22], "rtsbuf" }, X+ { "_rudbuf", 0, &Info.i_waitstate[23], "rudbuf" }, X+ { "_rupbuf", 0, &Info.i_waitstate[24], "rupbuf" }, X+ { "_rutbuf", 0, &Info.i_waitstate[25], "rutbuf" }, X+ { "_rvabuf", 0, &Info.i_waitstate[26], "rvabuf" }, X+ { "_rvpbuf", 0, &Info.i_waitstate[27], "rvpbuf" }, X+ { "_chtbuf", 0, &Info.i_waitstate[28], "chtbuf" }, X+ { "_cmtbuf", 0, &Info.i_waitstate[29], "cmtbuf" }, X+ { "_ctmbuf", 0, &Info.i_waitstate[30], "ctmbuf" }, X+ { "_ctsbuf", 0, &Info.i_waitstate[31], "ctsbuf" }, X+ { "_cutbuf", 0, &Info.i_waitstate[32], "cutbuf" }, X # ifdef BSD42 X! { "_selwait", 0, &Info.i_waitstate[33], "select" }, X! # endif X # ifdef CHAOS X! { "_Chrfclist", 0, &Info.i_waitstate[34], "chrfc" }, X # endif X! # ifdef SUN X! { "_async_bufhead", 0, &Info.i_waitstate[35], "async" }, X! # endif X { (char*)0, 0, (caddr_t*)0, (char*)0 } X } ; Xdiff -b -c sps/hashuid.c sps.old/hashuid.c X*** sps/hashuid.c Tue Nov 25 11:34:16 1986 X--- sps.old/hashuid.c Wed Dec 17 13:58:30 1986 X*************** X*** 1,8 **** X # include "sps.h" X X /* The hashing functions themselves ... */ X! # define HASHFN1( a ) (((unsigned)(a)*91 + 17) % MAXUSERID) X! # define HASHFN2( a ) (((unsigned)(a) + 47) % MAXUSERID) X X /* X ** HASHUID - Returns a pointer to a slot in the hash table that corresponds X--- 1,8 ---- X # include "sps.h" X X /* The hashing functions themselves ... */ X! # define HASHFN1( a ) (((a)*91 + 17) % MAXUSERID) X! # define HASHFN2( a ) (((a) + 47) % MAXUSERID) X X /* X ** HASHUID - Returns a pointer to a slot in the hash table that corresponds Xdiff -b -c sps/initsymbols.c sps.old/initsymbols.c X*** sps/initsymbols.c Fri Dec 5 09:47:23 1986 X--- sps.old/initsymbols.c Wed Dec 17 13:58:38 1986 X*************** X*** 48,54 **** X sysperror() ; X } X /* Get kernel addresses */ X! (void)nlist( filesymbol, np0 ) ; X if ( np0[0].n_value == -1 ) X { X fprintf( stderr, "sps - Can't read symbol file %s", filesymbol); X--- 48,54 ---- X sysperror() ; X } X /* Get kernel addresses */ X! nlist( filesymbol, np0 ) ; X if ( np0[0].n_value == -1 ) X { X fprintf( stderr, "sps - Can't read symbol file %s", filesymbol); Xdiff -b -c sps/inittty.c sps.old/inittty.c X*** sps/inittty.c Tue Nov 25 11:34:17 1986 X--- sps.old/inittty.c Wed Dec 17 13:58:48 1986 X*************** X*** 1,6 **** X # include "sps.h" X # include <h/conf.h> X- # include <h/ioctl.h> X # include <h/tty.h> X # include <sys/stat.h> X # include <stdio.h> X--- 1,5 ---- Xdiff -b -c sps/main.c sps.old/main.c X*** sps/main.c Tue Nov 25 11:34:18 1986 X--- sps.old/main.c Wed Dec 17 13:59:04 1986 X*************** X*** 1,14 **** X # include "sps.h" X # include "flags.h" X # include <h/text.h> X- # include <sys/stat.h> X # include <stdio.h> X X- X /* SPS - Show Process Status */ X! /* J. R. Ward - Hasler AG Bern, CH - 24 May 1985 */ X! /* 26 Nov 1986 */ X! X main ( argc,argv ) X X int argc ; X--- 1,10 ---- X # include "sps.h" X # include "flags.h" X # include <h/text.h> X # include <stdio.h> X X /* SPS - Show Process Status */ X! /* J. R. Ward - Hasler AG Bern - 24 May 1985 */ X main ( argc,argv ) X X int argc ; X*************** X*** 19,26 **** X register struct process *process ; X register struct text *text ; X int flinfo ; X- char *fileinfo, *filesymbol ; X- struct stat sinfo, ssymbol, spasswd ; X extern struct flags Flg ; X extern struct info Info ; X extern int Flmem ; X--- 15,20 ---- X*************** X*** 29,36 **** 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--- 23,29 ---- X char *getcore() ; X struct process *needed(), *mktree() ; X X! /* Renice as fast as possible for root (Suggested by Gregorio!mogul) */ X if ( !getuid() ) X (void)nice( -40 ) ; X /* Decode the flag arguments */ X*************** X*** 56,82 **** 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- 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 /* 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--- 49,61 ---- X initialise() ; X exit( 0 ) ; X } X /* Read the information file */ X+ flinfo = openfile( Flg.flg_j ? Flg.flg_j : FILE_INFO ) ; X if ( read( flinfo, (char*)&Info, sizeof( struct info ) ) X != sizeof( struct info ) ) X { X! fprintf( stderr, "sps - Can't read info file %s", X! Flg.flg_j ? Flg.flg_j : FILE_INFO ) ; X sysperror() ; X } X (void)close( flinfo ) ; Xdiff -b -c sps/printproc.c sps.old/printproc.c X*** sps/printproc.c Fri Dec 5 09:48:22 1986 X--- sps.old/printproc.c Wed Dec 17 13:59:53 1986 X*************** X*** 32,38 **** X p->pr_p.p_flag & SDETACH ? '_' : X # endif X p->pr_p.p_pgrp == p->pr_tty->l_pgrp ? '.' : ' ' ) ; X! hp = hashuid( (int)p->pr_p.p_uid ) ; X if ( !md ) X { /* If a top-level process, list the user name */ X if ( hp ) X--- 32,38 ---- X p->pr_p.p_flag & SDETACH ? '_' : X # endif X p->pr_p.p_pgrp == p->pr_tty->l_pgrp ? '.' : ' ' ) ; X! hp = hashuid( p->pr_p.p_uid ) ; X if ( !md ) X { /* If a top-level process, list the user name */ X if ( hp ) Xdiff -b -c sps/selectproc.c sps.old/selectproc.c X*** sps/selectproc.c Fri Dec 5 09:02:28 1986 X--- sps.old/selectproc.c Wed Dec 17 14:00:04 1986 X*************** X*** 1,8 **** X # include "sps.h" X # include "flags.h" X- # ifdef USELOGINUID X- # include <pwd.h> X- # endif USELOGINUID X X /* X ** SELECTPROC - Given a process structure, this procedure decides whether X--- 1,5 ---- X*************** X*** 17,28 **** X { X register union flaglist *fp ; X register struct process *pp ; X- #ifdef USELOGINUID X- char *username ; X- struct passwd *pw ; X- char *getlogin() ; X- struct passwd *getpwnam() ; X- #endif USELOGINUID X extern struct flags Flg ; X X /* Flg.flg_AZ is an internal flag set if one of flags `A' to `Z' X--- 14,19 ---- X*************** X*** 29,43 **** X was specified. If this is not set, a process is listed only X if it or one of its ancestors belongs to the invoking user. */ X if ( !Flg.flg_AZ ) X- { X- #ifdef USELOGINUID X- thisuid = (username = getlogin()) X- && (pw = getpwnam( username )) ? pw->pw_uid : getuid() ; X- #endif USELOGINUID X for ( pp = p ; pp > &process[1] ; pp = pp->pr_pptr ) X if ( thisuid == pp->pr_p.p_uid ) X return ( 1 ) ; X- } X if ( Flg.flg_A ) X return ( 1 ) ; X if ( Flg.flg_P ) X--- 20,28 ---- Xdiff -b -c sps/sps.h sps.old/sps.h X*** sps/sps.h Tue Nov 25 11:34:28 1986 X--- sps.old/sps.h Wed Dec 17 14:00:12 1986 X*************** X*** 9,25 **** X */ X # define MAXUSERID 100 X /* Maximum # ttys to be considered ... */ X! # define MAXTTYS 65 X /* Maximum user name length ... */ X # define UNAMELEN 8 X /* Maximum process-id not to be considered busy ... */ X # define MSPID 2 X /* # of wait states defined in the `struct info' ... */ X! # ifdef SUN X! # define NWAITSTATE 16 X! # else X! # define NWAITSTATE 35 X! # endif X X /* Convert clicks to kbytes ... */ X # ifdef SUN X--- 9,21 ---- X */ X # define MAXUSERID 100 X /* Maximum # ttys to be considered ... */ X! # define MAXTTYS 60 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! # define NWAITSTATE 36 X X /* Convert clicks to kbytes ... */ X # ifdef SUN X*************** X*** 35,41 **** X # define FILE_DEV "/dev" /* Directory of tty entries */ X # define FILE_SYMBOL "/vmunix" /* Symbol file for nlist() */ X # define FILE_INFO "/etc/spsinfo" /* Sps information file */ X- # define FILE_PASSWD "/etc/passwd" /* User database */ X X /* Structure to hold necessary information concerning a tty ... */ X struct ttyline X--- 31,36 ---- X*************** X*** 49,55 **** X /* Structure holding a single hash table entry ... */ X struct hashtab X { X! short h_uid ; /* Uid of user entry */ X char h_uname[ UNAMELEN ] ; /* Corresponding name */ X } ; X X--- 44,50 ---- X /* Structure holding a single hash table entry ... */ X struct hashtab X { X! unsigned short h_uid ; /* Uid of user entry */ X char h_uname[ UNAMELEN ] ; /* Corresponding name */ X } ; X Xdiff -b -c sps/termwidth.c sps.old/termwidth.c X*** sps/termwidth.c Thu Dec 11 10:42:33 1986 X--- sps.old/termwidth.c Wed Dec 17 14:00:17 1986 X*************** X*** 1,5 **** X- #include <sys/ioctl.h> X- X /* X ** TERMWIDTH - Sets the external variable `Termwidth' to the # of columns X ** on the terminal. X--- 1,3 ---- X*************** X*** 8,28 **** X { X register char *termtype ; X register int twidth ; X- #ifdef TIOCGWINSZ X- struct winsize w ; X- #endif X char buf[ 1025 ] ; X extern unsigned Termwidth ; X char *getenv() ; X X- #ifdef TIOCGWINSZ X- w.ws_col = 0 ; X- if ( !ioctl( 0, TIOCGWINSZ, &w ) && w.ws_col ) X- { X- Termwidth = w.ws_col ; X- return ; X- } X- #endif X Termwidth = 80 ; X if ( !(termtype = getenv( "TERM" )) ) X return ; X--- 6,15 ---- Xdiff -b -c sps/ttystatus.c sps.old/ttystatus.c X*** sps/ttystatus.c Tue Nov 25 11:34:28 1986 X--- sps.old/ttystatus.c Wed Dec 17 14:00:20 1986 X*************** X*** 1,7 **** X # include "sps.h" X # include "flags.h" X # include <stdio.h> X- # include <h/ioctl.h> X # include <h/tty.h> X # ifdef CHAOS X # include <chunix/chsys.h> X--- 1,6 ---- Xdiff -b -c sps/waitingfor.c sps.old/waitingfor.c X*** sps/waitingfor.c Fri Dec 5 11:23:05 1986 X--- sps.old/waitingfor.c Wed Dec 17 14:00:31 1986 X*************** X*** 1,4 **** X--- 1,5 ---- X # include "sps.h" X+ # include <h/tty.h> X # include <h/text.h> X # ifdef SUN X # include <h/vnode.h> X*************** X*** 5,22 **** X # include <ufs/inode.h> X # else X # include <h/inode.h> X! # endif SUN X! # include <h/ioctl.h> X! # include <h/tty.h> X # include <h/buf.h> X # ifdef BSD42 X- # ifndef SUN X # include <h/quota.h> X- # endif SUN X # include <h/mbuf.h> X # include <h/socket.h> X # include <h/socketvar.h> X! # endif BSD42 X X /* 1 if `w' is in the address range defined by `a1' and `a2' ... */ X # define INRANGE( w, a1, a2 ) \ X--- 6,19 ---- X # include <ufs/inode.h> X # else X # include <h/inode.h> X! # endif X # include <h/buf.h> X # ifdef BSD42 X # include <h/quota.h> X # include <h/mbuf.h> X # include <h/socket.h> X # include <h/socketvar.h> X! # endif X X /* 1 if `w' is in the address range defined by `a1' and `a2' ... */ X # define INRANGE( w, a1, a2 ) \ X*************** X*** 35,41 **** X # ifdef BSD42 X struct socket sc ; X # endif X- int rc ; X static char wbuf[ 8 ] ; X extern struct info Info ; X extern struct symbol Symbollist[] ; X--- 32,37 ---- X*************** X*** 59,75 **** X if ( INRANGE( w, Info.i_text0, &Info.i_text0[ Info.i_ntext ] ) ) X return ( "swtext" ) ; X # ifdef BSD42 X- # ifndef SUN X /* Waiting for an event associated with the quota system ? */ X if ( INRANGE( w, Info.i_quota0, &Info.i_quota0[ Info.i_nquota ] ) ) X return ( "quota" ) ; X! # endif SUN X! # endif BSD42 X /* Waiting for tty I/O ? If so, find which tty it is */ X for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ ) X if ( INRANGE( w, &lp->l_addr[0], &lp->l_addr[1] ) ) X { X! switch ( (int)w - (int)lp->l_addr ) X { X case (int)&((struct tty*)0)->t_rawq : X /* Read from a tty or slave pty */ X--- 55,69 ---- X if ( INRANGE( w, Info.i_text0, &Info.i_text0[ Info.i_ntext ] ) ) X return ( "swtext" ) ; X # ifdef BSD42 X /* Waiting for an event associated with the quota system ? */ X if ( INRANGE( w, Info.i_quota0, &Info.i_quota0[ Info.i_nquota ] ) ) X return ( "quota" ) ; X! # endif X /* Waiting for tty I/O ? If so, find which tty it is */ X for ( lp = Info.i_ttyline ; lp->l_name[0] ; lp++ ) X if ( INRANGE( w, &lp->l_addr[0], &lp->l_addr[1] ) ) X { X! switch ( w - (int)lp->l_addr ) X { X case (int)&((struct tty*)0)->t_rawq : X /* Read from a tty or slave pty */ X*************** X*** 111,117 **** X case (int)&((struct inode*)0)->i_shlockc : X /* Shared lock on this inode */ X return ( "shlock" ) ; X! # endif SUN X # else X case 1 : X return ( "wpipe" ) ; X--- 105,111 ---- X case (int)&((struct inode*)0)->i_shlockc : X /* Shared lock on this inode */ X return ( "shlock" ) ; X! # endif X # else X case 1 : X return ( "wpipe" ) ; X*************** X*** 119,125 **** X return ( "rpipe" ) ; X case (int)&((struct inode*)0)->i_un.i_group.g_datq : X return ( "rmux" ) ; X! # endif BSD42 X default : X /* Inode probably locked */ X return ( "inode" ) ; X--- 113,119 ---- X return ( "rpipe" ) ; X case (int)&((struct inode*)0)->i_un.i_group.g_datq : X return ( "rmux" ) ; X! # endif X default : X /* Inode probably locked */ X return ( "inode" ) ; X*************** X*** 132,146 **** X - (int)&((struct mbuf*)0)->m_dat[0] ) X { X case (int)&((struct socket*)0)->so_timeo : X! /* Socket timeout event - Guess why */ X! rc = getsocket( (struct socket*)(w X! - (int)&((struct socket*)0)->so_timeo), X! &sc ) ; X! return ( rc && (sc.so_state & SS_ISCONNECTING) X! ? "connct" X! : rc && ((sc.so_options & SO_ACCEPTCONN) X! && !sc.so_qlen) X! ? "accept" : "socket" ) ; X case (int)&((struct socket*)0)->so_rcv.sb_cc : X /* Read from an empty socket. Here we actually X attempt to determine whether the socket X--- 126,133 ---- X - (int)&((struct mbuf*)0)->m_dat[0] ) X { X case (int)&((struct socket*)0)->so_timeo : X! /* Socket timeout event */ X! return ( "socket" ) ; X case (int)&((struct socket*)0)->so_rcv.sb_cc : X /* Read from an empty socket. Here we actually X attempt to determine whether the socket X*************** X*** 151,166 **** X - (int)&((struct socket*)0)->so_rcv.sb_cc), X &sc ) X && sc.so_type == SOCK_STREAM X- #ifdef BSD43 X- && ((sc.so_state X- & (SS_ISCONNECTED|SS_CANTSENDMORE)) X- == (SS_ISCONNECTED|SS_CANTSENDMORE)) X- #else X && !sc.so_rcv.sb_hiwat X && !sc.so_rcv.sb_mbmax X && (sc.so_state X & (SS_ISCONNECTED|SS_CANTRCVMORE)) X- #endif BSD43 X ? "rpipe" : "rsockt" ) ; X case (int)&((struct socket*)0)->so_snd.sb_cc : X /* Write to a full socket. Again, we try X--- 138,147 ---- X*************** X*** 169,191 **** X return ( getsocket( (struct socket*)(w X - (int)&((struct socket*)0)->so_snd.sb_cc), X &sc ) X- #ifdef BSD43 X && sc.so_type == SOCK_STREAM X- && ((sc.so_state X- & (SS_ISCONNECTED|SS_CANTRCVMORE)) X- == (SS_ISCONNECTED|SS_CANTRCVMORE)) X- #else X && sc.so_rcv.sb_hiwat == 2048 X && sc.so_rcv.sb_mbmax == 4096 X && (sc.so_state X & (SS_ISCONNECTED|SS_CANTSENDMORE)) X- #endif BSD43 X ? "wpipe" : "wsockt" ) ; X default : X /* Other mbuf event */ X return ( "mbuf" ) ; X } X! # endif SUN X /* Look in the symbol table for known wait addresses. */ X for ( s = Symbollist ; s->s_kname ; s++ ) X if ( s->s_wait && w == *s->s_info ) X--- 150,166 ---- X return ( getsocket( (struct socket*)(w X - (int)&((struct socket*)0)->so_snd.sb_cc), X &sc ) X && sc.so_type == SOCK_STREAM X && sc.so_rcv.sb_hiwat == 2048 X && sc.so_rcv.sb_mbmax == 4096 X && (sc.so_state X & (SS_ISCONNECTED|SS_CANTSENDMORE)) X ? "wpipe" : "wsockt" ) ; X default : X /* Other mbuf event */ X return ( "mbuf" ) ; X } X! # endif X /* Look in the symbol table for known wait addresses. */ X for ( s = Symbollist ; s->s_kname ; s++ ) X if ( s->s_wait && w == *s->s_info ) X*************** X*** 196,202 **** X (void)sprintf( wbuf, "x%05x", w ) ; X # else X (void)sprintf( wbuf, "x%05x", w - 0x80000000 ) ; X! # endif SUN X return ( wbuf ) ; X } X X--- 171,177 ---- X (void)sprintf( wbuf, "x%05x", w ) ; X # else X (void)sprintf( wbuf, "x%05x", w - 0x80000000 ) ; X! # endif X return ( wbuf ) ; X } X X*************** X*** 217,220 **** X return ( read( Flkmem, (char*)s, sizeof( struct socket ) ) X == sizeof( struct socket ) ) ; X } X! # endif BSD42 X--- 192,195 ---- X return ( read( Flkmem, (char*)s, sizeof( struct socket ) ) X == sizeof( struct socket ) ) ; X } X! # endif X END_OF_patches if test 26834 -ne `wc -c <patches`; then echo shar: \"patches\" unpacked with wrong size! fi # end of overwriting check fi if test -f sps.man -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"sps.man\" else echo shar: Extracting \"sps.man\" \(14462 characters\) sed "s/^X//" >sps.man <<'END_OF_sps.man' X.if n .pl 66 X.TH SPS LOCAL X.SH NAME Xsps \ \ \-\ \ \ show process status X.SH SYNOPSIS X\fBsps\ \fP \ [ \fB-defgijkoqrslvwyABDFNPSTUWZ\fP ]\ \ [ X\fIprocess\ .\ \. | tty\ .\ \. | user\ .\ .\ .\fP ] X.SH DESCRIPTION X\fISps\fP reports information concerning system processes. XIt shows the current state of any process by Xlisting information such as ownership, CPU time usage, memory usage Xand disc activity. X.PP X\fISps\fP should be used in preference to \fIps\fP(1) Xas it is faster and the output is easier to understand. X.SH OPTIONS XBy default, \fIsps\fP prints basic information about one's own processes. XThe various options described below select other processes or make X\fIsps\fP more verbose. X.PP XUpper case options select processes to be described. XLower case options specify the format of the output. XFor instance, the options \fBBv\fP specify that \fIsps\fP Xshould list "busy" processes in a verbose format. XUnless there is any conflict, lower case options may be used Xinstead of upper case options, and vice versa. X.PP XThe following options specify the format of the listed output - X.TP 8 X\fB-d\fP XList output reflecting how each process affects the Xdisc and paging activity of the system. X.TP X\fB-e\fP XList the environment passed to each process. X.TP X\fB-f\fP XInclude the process-id of the parent of each process. X.TP X\fB-g\fP XInclude the process group of each process. X.TP X\fB-o\fP XAvoid looking at the swap device (\fB/dev/drum\fP). This tends to make \fIsps\fP Xrun faster, although no information concerning swapped processes Xcan be obtained. X.TP X\fB-q\fP XBy default, \fIsps\fP Xlists the sum of the user plus system times under the X\fITime\fP and \fIChild\fP fields. This option forces \fIsps\fP Xto list only the user times. X.TP X\fB-r\fP XRepeat the output indefinitely. XIf the next argument is numeric, \fIsps\fP repeats the output with that Xmany seconds delay between each repetition. XOtherwise the output is repeated with no delay. X.TP X\fB-l\fP X.br X.ns X.TP X\fB-v\fP XList additional information in a verbose format. See below. X.TP X\fB-w\fP XList output in a wide format. This option forces \fIsps\fP Xto print all the command arguments, even if doing so extends the output Xbeyond one line. X.TP X\fB-y\fP XShow the status of each terminal line. X.PP XThe following options specify which processes are to be described - X.TP 8 X\fB-A\fP XList all processes. X.TP X\fB-B\fP XList busy processes. A process is considered to be busy Xif it is immediately runnable or awaiting a fast event such as disc I/O. X.TP X\fB-D\fP XList detached processes. X.TP X\fB-F\fP XList foreground processes. X.TP X\fB-N\fP XShow no processes at all. Only the summary line is printed. X.TP X\fB-P\fP XList only processes whose identifiers are specified in the following arguments. X.TP X\fB-S\fP XList stopped processes. X.TP X\fB-T\fP XList only processes attached to the following specified terminals. X.TP X\fB-U\fP XList only processes belonging to the following specified users. X.TP X\fB-W\fP XList waiting processes. X.TP X\fB-Z\fP XList zomby (exiting) processes. X.PP XThe following are miscellaneous options - X.TP 8 X\fB-i\fP XInitialise \fIsps\fP. XThis is necessary if new users are added to the password file, Xor if a new version of UNIX is installed. XSps builds a new information file summarising pertinent information Xread from the password file (\fB/etc/passwd\fP), the executable kernel image X(\fB/vmunix\fP) and the directory of tty devices (\fB/dev\fP). XSee also the \fB-j\fP and \fB-s\fP options. X.TP X\fB-j\fP XSpecify an information file other than the default (\fB/etc/spsinfo\fP). XThe next argument is taken to be the name of a suitable information file. XIf the \fB-i\fP flag is also specified, \fIsps\fP builds a Xnew information file with the given name. XOtherwise, \fBsps\fP reads previously created summarising information Xfrom that file. X.TP X\fB-k\fP XUse a specific disc file rather than the default physical Xmemory (\fB/dev/mem\fP) Xand kernel virtual memory (\fB/dev/kmem\fP) files. The next argument is taken Xto be the name of a suitable memory dump file. XThis flag automatically sets the \fB-o\fP flag. X.TP X\fB-s\fP XThis option is used in conjunction with the \fB-i\fP option. XThe next argument is taken to be the name of a suitable kernel executable Xfile, rather than the default (\fB/vmunix\fP). X\fISps\fP looks at the symbol table of this file to determine Xthe virtual addresses of various kernel structures. X.SH OUTPUT X\fISps\fP produces output in the following fields - X.TP 8 X\fITy\fP XThe terminal identifier to which the process is attached. X.IP XIf this is followed by an underscore, the process is detached. XIf it is followed by a period, the process is running in the foreground. XOtherwise the process is running in the background but is still Xattached to a terminal. X.TP X\fIUser\fP XThe symbolic name of the process' effective user-id (see \fIexec\fP(2) Xand \fIsetuid\fP(2)). XThis name is defined by the system password file (\fB/etc/passwd\fP) Xwhen \fIsps\fP was last initialised. XOtherwise, an asterisk (*) or vertical bar (|) appearing in this Xcolumn denotes that the process is an immediate relative of the Xpreceding process. XA bar is listed, rather than an asterisk, if both processes belong Xto the same process group. XA user name is listed only if the effective user-id Xdiffers from that of the preceding process or if it is a top-level Xprocess (immediate offspring of process 1). X.TP X\fIProc#\fP XThe unique process identifier. X.TP X\fIPpid#\fP XThe process-id of the process' parent. X.TP X\fIPgrp#\fP XThe process group to which the process belongs. X.TP X\fICommand\fP XThe command arguments obtained from the process' own address space. X(If the command name appears in parentheses, \fIsps\fP Xwas unable to locate the arguments in user space and so reports Xthe system's idea of the command name.) X.PP XThe following additional fields are listed when \fIsps\fP Xis invoked with one of the \fB-l\fP or \fB-v\fP options - X.TP 8 X\fIStatus\fP XThe process' current state. XIf this field is listed in upper-case letters, the process is currently Xloaded in real memory space ; otherwise it has been swapped out. XThe status field may contain one of the following descriptions - X.RS 8 X.TP 16 X\fIrun\fP XThe process can be run immediately. X.TP X\fIstop\fP XThe process is stopped. See \fIsigvec\fP(2). X.TP X\fIexit\fP XThe process is a zomby. X.RE X.IP XAny other entry in the status field indicates the process is Xwaiting for some external event to occur. XThis is usually for one of the reasons listed below. X(If \fIsps\fP does not know why a process is waiting, it lists Xthe hexadecimal address of the process' wait channel, Xwith the initial 80000000 trimmed off.) XA process may be waiting for one of the following reasons - X.RS 8 X.TP 16 X\fIchild\fP XThe process is waiting for a child to terminate. See \fIwait\fP(2). X.TP X\fIpause\fP XWaiting for a signal to be received. See \fIsigpause\fP(2). X.TP X\fIswap\fP XWaiting for a page to be swapped in. X.TP X\fIrswbuf\fP XWaiting for a read from the swap device \fB/dev/drum.\fP X.TP X\fIdiscio\fP XWaiting for a disc read or write operation. X(Actually, this means that the process is waiting for an operation Xthrough the kernel's I/O buffering mechanism to complete, but \fIdiscio\fP Xis what is generally meant here). X.TP X\fIrpipe\fP X.br X.ns X.TP X\fIwpipe\fP XWaiting for a read from an empty pipe. Alternatively, the process Xis waiting to write to a full pipe. See \fIpipe\fP(2). X.TP X\fIrsockt\fP X.br X.ns X.TP X\fIwsockt\fP XWaiting for a read from an empty socket. XAlternatively, the process is waiting to write to a full socket (4.[2-]bsd only). X.TP X\fIaccept\fP XWaiting to accept a stream-based socket connection (4.[2-]bsd only). XSee \fIaccept\fP(2). X.TP X\fIconnct\fP XWaiting to establish a connection through a stream-based socket to a Xremote process (4.[2-]bsd only). See \fIconnect\fP(2). X.TP X\fIsocket\fP XWaiting for some other time-out event on a socket (4.[2-]bsd only). X.TP X\fIselect\fP XBlocked by a \fIselect\fP(2) system call (4.[2-]bsd only). X.TP X\fIrmux\fP XWaiting for a read from a multiplexor file (4.1bsd only). X.TP X\fIinode\fP XWaiting for an inode to be allocated or unlocked. X.TP X\fIexlock\fP X.br X.ns X.TP X\fIshlock\fP XWaiting for a file to become unlocked. See \fIflock\fP(2). X.TP X\fIrtty??\fP X.br X.ns X.TP X\fIwtty??\fP X.br X.ns X.TP X\fIotty??\fP XWaiting for a read or write to the specified terminal, or for the terminal Xto be switched on. See \fItty\fP(4). XAlternatively, waiting for a read or write to the Xspecified slave pty device. See \fIpty\fP(4). X.TP X\fIrpty??\fP X.br X.ns X.TP X\fIwpty??\fP XWaiting for a read or write to the specified master pty device. XSee \fIpty\fP(4). X.TP X\fIptrace\fP XThis is a parent process tracing its child. X.TP X\fIvfork\fP XThis is a vforking parent process waiting for its child to relinquish Xmemory resources. See \fIvfork\fP(2). X.TP X\fIfloppy\fP X.br X.ns X.TP X\fIprintr\fP X.br X.ns X.TP X\fIr??buf\fP XWaiting for the specified device to complete an I/O operation. X.RE X.TP 8 X\fIFl\fP XFlags associated with the current state of the process. XThese flags may be any of the following - X.RS 8 X.TP 16 X\fIU\fP XThe process is a UNIX system process. X.TP X\fIT\fP XThe process is being traced or debugged. X.TP X\fIV\fP XThe process is a child currently being vforked. See \fIvfork\fP(2). X.TP X\fII\fP XThe process is undergoing physical I/O. X.TP X\fIA\fP XThe system has detected, or the user has warned of Xanomalous paging behaviour. See \fIvadvise\fP(2). X.RE X.TP 8 X\fINice\fP XThe "niceness" of the process. See \fInice\fP(2). X.TP X\fIVirtual\fP XThe virtual memory size of the process in kilobytes. XThe first figure indicates the sum of the data and stack segments, Xthe second figure that of the text segment. X.TP X\fIResident\fP XThe resident memory size of the process in kilobytes, representing Xthe real memory devoted to the process. X.TP X\fI%M\fP XThe percentage of available real memory allocated to this process. X.TP X\fITime\fP XThe total CPU time accumulated by this process. X(This is the sum of the system plus user times, unless the \fB-q\fP Xflag is specified in which case only the user time is listed.) X.TP X\fIChild\fP XThe total CPU time accumulated by the process' children. X(This is the sum of the system plus user times, unless the \fB-q\fP Xflag is specified.) X.TP X\fI%C\fP XThe percentage of available CPU time devoted to the process. XThis figure is a decaying average, computed over the past second. X.PP XThe following fields are listed when \fIsps\fP is invoked with the X\fB-d\fP option - X.TP 8 X\fIFiles\fP XThe number of open files for this process. X.TP X\fIPageFaults\fP XThe number of major and minor page faults incurred by the process. X.TP X\fISwap\fP XThe number of swaps incurred by the process. X.TP X\fIBlockI/O\fP XThe number of block read or write operations performed Xon behalf of the process. X.TP X\fIKbytesecs\fP XThe integral of real memory usage over time. XThus, if a process uses 60 kilobytes of real memory for 3 seconds, Xthis figure is incremented by 180. X.PP XThe following fields are listed when \fIsps\fP is invoked with the X\fB-y\fP option - X.TP 8 X\fIDev\fP XThe major and minor device numbers of the terminal. X.TP X\fIAddr\fP XThe virtual address of the associated \fBstruct tty\fP in \fB/dev/kmem\fP. X.TP X\fIRawq\fP X.br X.ns X.TP X\fICanq\fP X.br X.ns X.TP X\fIOutq\fP XThe number of characters in the terminal I/O queues. XThese refer to the raw input queue, the canonical input queue Xand the output queue. X.TP X\fIPgrp\fP XThe process group associated with the terminal. X.PP XAfter listing the requested output, \fIsps\fP prints a summary line. XThis indicates the number and total virtual memory size of all processes, Xthe number and total virtual size of busy processes, Xthe number and real memory size of loaded processes Xand the number and real size of swapped processes. X.SH DIAGNOSTICS X\fISps\fP reports a self-explanatory message if it is given an Xinvalid argument list. XThe program also complains if it cannot find necessary system information. X.PP XAt initialisation, \fIsps\fP complains if it cannot find the addresses of Xrequisite system structures in the kernel symbol file. XThis is usually the case because the system is rarely configured to support Xall known devices. X\fISps\fP also complains if more than one user shares the same user-id Xin the password file (\fB/etc/passwd\fP). X.SH EXAMPLES X\fBsps vb\fP X.PP X\fISps\fP describes all busy processes in a verbose manner. X.PP X\fBsps dtg 9 h1 co\fP X.PP X\fISps\fP lists processes associated with terminals 9, h1 and the console. XThe output reflects the disc activity caused by these processes. XThe process group of each process is also included in the output. X.PP X\fBsps weu robert fred -r 2\fP X.PP X\fISps\fP reports processes belonging to the specified users. XIt lists the environment as well as all the command arguments in a wide format. XThe output is produced indefinitely, with a delay of two seconds between Xeach listing. X.PP X\fBsps is /vmunix.new\fP X.PP X\fISps\fP is initialised. It reads its symbol information from the Xspecified file. X.SH FILES X.ta 2.5i X.nf X/dev/console Console X/dev/tty?? Terminal and pty devices X/dev/kmem Kernel virtual memory X/dev/mem Physical memory X/dev/drum Paging and swap device X/etc/passwd Password file X/etc/spsinfo Information file X/vmunix Symbol file of /dev/kmem addresses X/etc/termcap To determine the output terminal width X.fi X.ta X.SH SEE ALSO X\fIiostat\fP(1), \fIkill\fP(1), \fIps\fP(1), X\fIvmstat\fP(1), \fIexec\fP(2), X\fIflock\fP(2), \fInice\fP(2), \fIpause\fP(2), \fIselect\fP(2), \fIsetuid\fP(2), X\fIsigvec\fP(2), \fIvadvise\fP(2), \fIvfork\fP(2), \fIwait\fP(2), X\fIpty\fP(4),\fItty\fP(4), \fIpstat\fP(8). X.SH AUTHORS XSeveral. In particular, J. E. Kulp and J. Robert Ward. X.LP XCurrently maintained by J. Robert Ward, \fB<robert@hslrswi.UUCP>\fP X.SH BUGS XBecause the system is continually changing, the information reported by X\fIsps\fP is only an approximation to reality. XIf invoked by root, \fIsps\fP renices itself to -20 in an attempt to run as Xfast as possible. X.PP X\fISps\fP recognises the sizes and addresses of internal kernel Xtables whenever it is invoked. However, it must be recompiled Xif major modifications are made to the kernel. X.PP X\fISps\fP does not list all the detailed information shown by \fIps\fP(1). XNor are all the options supported by \fIps\fP(1) available from \fIsps\fP. X.PP X\fISps\fP does not understand all the possible Xreasons why a process may be sleeping. X.PP XThe code of \fIsps\fP is inherently machine-dependent and non-portable. X.PP XThe number of options to \fIsps\fP is ridiculous. X END_OF_sps.man if test 14462 -ne `wc -c <sps.man`; then echo shar: \"sps.man\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 3 \(of 3\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 3 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Rich $alz "Anger is an energy" Cronus Project, BBN Labs rsalz@bbn.com Moderator, comp.sources.unix sources@uunet.uu.net