Path: utzoo!utgpu!cs.utexas.edu!uunet!stanford.edu!rutgers!cmcl2!kramden.acf.nyu.edu!brnstnd From: brnstnd@kramden.acf.nyu.edu (Dan Bernstein) Newsgroups: alt.sources Subject: kstuff 0.18 (part 2/6) Message-ID: <5890:May704:31:1091@kramden.acf.nyu.edu> Date: 7 May 91 04:31:10 GMT Followup-To: alt.sources.d Organization: IR Lines: 2550 #! /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 'BLURB' <<'END_OF_FILE' Xkstuff includes a whole bunch of stuff related to reading the kernel, Xincluding pff, a more portable, improved version of ofiles/fstat. Of Xlong-term interest are the many kernel-reading libraries---you might Xnever have to open kmem again. Also here is an updated release of my Xauthd server and authuser client RFC 931 implementation, and as an extra Xbonus you get findinode, a user-level reverse namei for BSD systems with Xndbm. I stole a few pieces of code from various versions of ofiles (as Xindicated in the source). Everything else here is public-domain. X XAt various times various parts of kstuff have been run under each of Xthese systems: SunOS 4.0.3, SunOS 4.1, Ultrix 2.2, Ultrix 4.1, BSD X4.3-Tahoe, Convex UNIX 9.0, Dynix 3.0.17. If you're interested in Xporting these programs or libraries to other BSD variants, get in touch Xwith me. If you're brave enough to attempt a System V port, good luck. X XThis is kstuff 0.18. Keep in mind that it's alpha software---it's not Xsupposed to work, and if it happens to compile and install without a Xhitch on your machine, you should be happy. When you post constructive Xcriticism of kstuff to alt.sources.d, remember that I don't consider the Xpackage finished. You shouldn't be complaining that the package doesn't Xdo something. You should be explaining your needs and showing how kstuff X1.00 could fulfill them. X X---Dan Bernstein, brnstnd@nyu.edu END_OF_FILE if test 1394 -ne `wc -c <'BLURB'`; then echo shar: \"'BLURB'\" unpacked with wrong size! fi # end of 'BLURB' fi if test -f 'FORMLETTER' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'FORMLETTER'\" else echo shar: Extracting \"'FORMLETTER'\" \(621 characters\) sed "s/^X//" >'FORMLETTER' <<'END_OF_FILE' XTo: brnstnd@nyu.edu XFrom: XDate: X XPackage: kstuff 0.18 XObtained from (e.g., uunet.uu.net): XObtained by (e.g., ftp): X X1. Machine architecture (e.g., Sun 4/280): X2. Operating system (e.g., SunOS 4.1): X3. OS vendor (e.g., Sun): X4. Does load work on your machine (yes/no)? X5. Does pff work on your machine so far (yes/no)? X6. Does authd work on your machine so far (yes/no)? X7. What are CC, CCOPTS, LIBS, GETULIBS, and MACHOPTS in your Makefile? X CC= X CCOPTS= X LIBS= X GETULIBS= X MACHOPTS= X X8. Describe any problems you've had with kstuff. X X X9. Any further questions, comments, or suggestions? X X XYour name: END_OF_FILE if test 621 -ne `wc -c <'FORMLETTER'`; then echo shar: \"'FORMLETTER'\" unpacked with wrong size! fi # end of 'FORMLETTER' fi if test -f 'auread.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'auread.c'\" else echo shar: Extracting \"'auread.c'\" \(1579 characters\) sed "s/^X//" >'auread.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X#include X#include X#include "auread.h" X#include "structsockaddrin.h" X Xint readport(port,term) Xchar *port; /* must have MAXNUMLEN characters available */ Xchar term; X{ X int ch; X int loop; X int portlen; X X portlen = loop = 0; X while ((ch = getchar()) != term) X { X if (ch == EOF) X return -1; X if (isascii(ch) && isdigit(ch)) X port[portlen++] = ch; X if (portlen == MAXNUMLEN) X return -1; X if ((++loop) > LOOPMAX) X return -1; X } X port[portlen] = 0; X return 0; X} X Xint readlr(localport,remoteport,loc4,rem4,lp,rp) Xchar *localport; Xchar *remoteport; Xint *loc4; Xint *rem4; Xint *lp; Xint *rp; X{ X struct sockaddr_in sa; X int salen; X X if (readport(localport,',') == -1) X return -1; X if (readport(remoteport,'\n') == -1) X return -1; X *lp = atoi(localport); X *rp = atoi(remoteport); X X salen = sizeof(sa); X if (getpeername(0,&sa,&salen) == -1) X return -1; X rem4[0] = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[0]; X rem4[1] = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[1]; X rem4[2] = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[2]; X rem4[3] = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[3]; X X salen = sizeof(sa); X if (getsockname(0,&sa,&salen) == -1) X return -1; X loc4[0] = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[0]; X loc4[1] = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[1]; X loc4[2] = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[2]; X loc4[3] = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[3]; X X return 0; X} END_OF_FILE if test 1579 -ne `wc -c <'auread.c'`; then echo shar: \"'auread.c'\" unpacked with wrong size! fi # end of 'auread.c' fi if test -f 'authd.8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'authd.8'\" else echo shar: Extracting \"'authd.8'\" \(1532 characters\) sed "s/^X//" >'authd.8' <<'END_OF_FILE' X.TH authd 8 X.SH NAME Xauthd \- Authentication Server daemon X.SH SYNTAX Xauthd X.SH DESCRIPTION X.I authd Xis a daemon implementing the XRFC 931 Authentication Server protocol. XIt should be invoked by a network server, Xsuch as X.I attachport(1) Xor X.I inetd(8), Xfor connections to TCP port 113 (auth). X.PP XThe client host Xgives X.I authd Xtwo numbers separated by a comma. X.I authd Xinterprets the numbers as TCP port numbers Xfor the local and remote sides respectively Xof a TCP connection between this host and the client host. XIt returns a line of the form X.EX Xlocalport, remoteport: USERID: UNIX: username X.EE Xwhere username Xis the name of the user on this side of Xthe specified connection. XIf X.I authd Xdoes not have an authentication entry for that connection, Xit returns a line of the form X.EX Xlocalport, remoteport: ERROR: UNKNOWN-ERROR. X.EE X.PP X.SH DIAGNOSTICS X.TP XNone. X.SH BUGS XNone known. X.SH VERSION Xauthd version 3.5 alpha, May 1, 1991. X.SH AUTHOR XPlaced into the public domain by Daniel J. Bernstein. XPartially inspired by code written by Vic Abell for ofiles. X.SH REFERENCES XThe authentication server is more secure than passwords Xin some ways, but less secure than passwords in many ways. X(It's certainly better than no password at all---e.g., for Xmail or news.) XIt is not the final solution. XFor an excellent discussion of security problems within Xthe TCP/IP protocol suite, see XSteve Bellovin's article X``Security Problems in the TCP/IP Protocol Suite.'' X.SH "SEE ALSO" Xauthtcp(1), Xattachport(1), Xauthuser(3), Xtcp(4), Xinetd(8) END_OF_FILE if test 1532 -ne `wc -c <'authd.8'`; then echo shar: \"'authd.8'\" unpacked with wrong size! fi # end of 'authd.8' fi if test -f 'boottime.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'boottime.c'\" else echo shar: Extracting \"'boottime.c'\" \(1577 characters\) sed "s/^X//" >'boottime.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* getboottime() returns the time that the system wwas booted. It */ X/* returns 0 on error. */ X X/* boottimeinit() does optional initialization to cooperate with other */ X/* libraries that use nlistlist. boottimeinit returns -1 on error. */ X X/* boottimestrerr is a strerrfun for use with the strerr library. */ X X#include "boottime.h" X#include "kmem.h" X#include "nlistlist.h" X#include "strerr.h" X X#define BOOTTIMENLIST "_boottime" X Xstatic int btinit = 0; X Xstatic long boottime; Xstatic short bttype; Xstatic unsigned long btvalue; Xstatic int boottimeerrno = 0; X Xstatic struct strerrtab e[] = { X { 0, "boottime error 0", 0 } X#define BT_INIT 1 X, { BT_INIT, "cannot init boottime: ", nliststrerr } X#define BT_NLIST 2 X, { BT_NLIST, "cannot nlist: ", nliststrerr } X#define BT_NLISTFOUND 3 X, { BT_NLISTFOUND, BOOTTIMENLIST, nlistnotin } X#define BT_KMEM 4 X, { BT_KMEM, "cannot read boottime: ", kmemstrerr } X} ; X Xchar *boottimestrerr(ke) Xstrerrfun *ke; X{ X *ke = 0; X return strerrtaberr(ke,boottimeerrno,e,sizeof(e)/sizeof(*e),"unknown boottime error"); X} X Xint boottimeinit() X{ X if (nlistadd(BOOTTIMENLIST,&bttype,&btvalue) == -1) X RETERN(-1,boottimeerrno,BT_INIT) X btinit = 1; X return 0; X} X Xlong getboottime() X{ X if (!btinit) X if (boottimeinit() == -1) X return 0; X if (bttype == -1) X if (nlistdo() == -1) X RETERN(0,boottimeerrno,BT_NLIST) X if (!bttype) X RETERN(0,boottimeerrno,BT_NLISTFOUND) X if (kmemcpy((char *) &boottime,(char *) btvalue,sizeof(boottime)) == -1) X RETERN(0,boottimeerrno,BT_KMEM) X return boottime; X} END_OF_FILE if test 1577 -ne `wc -c <'boottime.c'`; then echo shar: \"'boottime.c'\" unpacked with wrong size! fi # end of 'boottime.c' fi if test -f 'confuofile.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'confuofile.h'\" else echo shar: Extracting \"'confuofile.h'\" \(579 characters\) sed "s/^X//" >'confuofile.h' <<'END_OF_FILE' X#ifndef CONF_UOFILE_H X#define CONF_UOFILE_H X X#include "confopalf.h" X#include "confodofe.h" X X#ifdef DYNIX X#ifdef ODOFE X#define UOFILE(u,n) ((u)->u_lofile[0].of_file) X#define NUOFILE(u) ((u)->u_nofile) X#else X#define UOFILE(u,n) ((u)->u_lofile[n].of_file) X#define NUOFILE(u) ((u)->u_nofile) X#endif X#else X#ifdef CONVEX X#define UOFILE(u,n) ((u)->u_fd[n].ofile) X#define NUOFILE(u) NOFILE X#else X#ifdef OPALF X#define UOFILE(u,n) ((u)->u_ofile[n]) X#define NUOFILE(u) ((u)->u_lastfile + 1) X#else X#define UOFILE(u,n) ((u)->u_ofile[n]) X#define NUOFILE(u) NOFILE X#endif X#endif X#endif X X#endif END_OF_FILE if test 579 -ne `wc -c <'confuofile.h'`; then echo shar: \"'confuofile.h'\" unpacked with wrong size! fi # end of 'confuofile.h' fi if test -f 'findinode/INSTALL' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'findinode/INSTALL'\" else echo shar: Extracting \"'findinode/INSTALL'\" \(1581 characters\) sed "s/^X//" >'findinode/INSTALL' <<'END_OF_FILE' X#!/bin/sh X X# Change mode to 0700 if you don't want normal users to have access to X# these utilities. XMODE=04755 XOWNER=root XINSTALL="install -c" XPROGINSTALL="$INSTALL -o $OWNER -m $MODE" XSYSINSTALL="$INSTALL -o $OWNER -m 0700" XMANINSTALL="$INSTALL -o $OWNER -m 0444" X X# Directories. XFIDDIR="`head -1 FIDDIR`" X X# Programs. XFINDINODE=/bin/findinode XUPDATEFID=/etc/updatefid XFSUPDATEFID=/etc/fsupdatefid X X# Man pages. XMFINDINODE=/usr/man/man1/findinode.1 XMUPDATEFID=/usr/man/man8/updatefid.8 X Xecho "Each action will be printed before it is run. Press return to proceed." X Xecho "1. Install findinode and updatefid." Xecho "! $PROGINSTALL findinode $FINDINODE: " | tr -d '\012' Xread line Xeval "$PROGINSTALL" findinode "$FINDINODE" X Xecho "! $SYSINSTALL updatefid $UPDATEFID: " | tr -d '\012' Xread line Xeval "$SYSINSTALL" updatefid "$UPDATEFID" X Xecho "! $SYSINSTALL fsupdatefid $FSUPDATEFID: " | tr -d '\012' Xread line Xeval "$SYSINSTALL" fsupdatefid "$FSUPDATEFID" X Xecho "2. Make the man pages available." Xecho "! $MANINSTALL findinode.1 $MFINDINODE: " | tr -d '\012' Xread line Xeval "$MANINSTALL" findinode.1 "$MFINDINODE" X Xecho "! $MANINSTALL updatefid.8 $MUPDATEFID: " | tr -d '\012' Xread line Xeval "$MANINSTALL" updatefid.8 "$MUPDATEFID" X Xecho "3. Make the database directory." Xecho "! mkdir $FIDDIR: " | tr -d '\012' Xread line Xmkdir "$FIDDIR" X Xecho "4. Start fsupdatefid running now to build the database." Xecho "! $FSUPDATEFID &: " | tr -d '\012' Xread line X( eval "$FDUPDATEFID" ) & X Xecho "5. Start fsupdatefid in /etc/rc.local." Xecho "I'll leave this step to you. That's it!" X Xexit 0 END_OF_FILE if test 1581 -ne `wc -c <'findinode/INSTALL'`; then echo shar: \"'findinode/INSTALL'\" unpacked with wrong size! fi chmod +x 'findinode/INSTALL' # end of 'findinode/INSTALL' fi if test -f 'findinode/Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'findinode/Makefile'\" else echo shar: Extracting \"'findinode/Makefile'\" \(1154 characters\) sed "s/^X//" >'findinode/Makefile' <<'END_OF_FILE' XCC=cc XCCOPTS=-g X Xall: updatefid findinode X Xshar: findinode.shar X Xupdatefid: fid.o updatefid.o X $(CC) $(CCOPTS) -o updatefid fid.o updatefid.o X Xfindinode: fid.o findinode.o X $(CC) $(CCOPTS) -o findinode fid.o findinode.o X Xfid.o: fid.c fid.h X @echo "$(CC) $(CCOPTS) -c fid.c -DDBLOCK=\\\"`head -1 FIDDIR`/+fidlock\\\" -DDBFILES=\\\"`head -1 FIDDIR`/+fidfiles\\\" -DDBDIRS=\\\"`head -1 FIDDIR`/+fiddirs\\\" -DDBDIRTIMES=\\\"`head -1 FIDDIR`/+fiddirtimes\\\" -DDBF2D=\\\"`head -1 FIDDIR`/+fidf2d\\\" -DDBD2F=\\\"`head -1 FIDDIR`/+fidd2f\\\"" X @eval "$(CC) $(CCOPTS) -c fid.c -DDBLOCK=\\\"`head -1 FIDDIR`/+fidlock\\\" -DDBFILES=\\\"`head -1 FIDDIR`/+fidfiles\\\" -DDBDIRS=\\\"`head -1 FIDDIR`/+fiddirs\\\" -DDBDIRTIMES=\\\"`head -1 FIDDIR`/+fiddirtimes\\\" -DDBF2D=\\\"`head -1 FIDDIR`/+fidf2d\\\" -DDBD2F=\\\"`head -1 FIDDIR`/+fidd2f\\\"" X Xupdatefid.o: updatefid.c fid.h X $(CC) $(CCOPTS) -c updatefid.c X Xfindinode.o: findinode.c fid.h X $(CC) $(CCOPTS) -c findinode.c X Xinstall: X @echo 'Run INSTALL from a root shell.' X Xclean: X rm findinode.o updatefid.o fid.o findinode updatefid X Xfindinode.shar: X shar `cat FILES` > findinode.shar X chmod 400 findinode.shar END_OF_FILE if test 1154 -ne `wc -c <'findinode/Makefile'`; then echo shar: \"'findinode/Makefile'\" unpacked with wrong size! fi # end of 'findinode/Makefile' fi if test -f 'findinode/fid.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'findinode/fid.h'\" else echo shar: Extracting \"'findinode/fid.h'\" \(749 characters\) sed "s/^X//" >'findinode/fid.h' <<'END_OF_FILE' X#ifndef FID_H X#define FID_H X X/* XXX: structure passing throughout */ Xstruct node { unsigned long i; unsigned long d; } ; Xstruct dnode { unsigned long i; unsigned long d; } ; Xstruct nodenum { struct node x; int n; } ; Xstruct dnodenum { struct dnode x; int n; } ; X Xextern int fidinit(); X Xextern int fidlock(); Xextern int fidunlock(); X Xextern int fidfilesput(); Xextern int fidfilesdel(); Xextern int fidfilesget(); Xextern int fiddirsput(); Xextern int fiddirsdel(); Xextern int fiddirsget(); Xextern int fiddirtimesput(); Xextern int fiddirtimesdel(); Xextern long fiddirtimesget(); Xextern int fidf2dput(); Xextern int fidf2ddel(); Xextern struct dnodenum fidf2dget(); Xextern int fidd2fput(); Xextern int fidd2fdel(); Xextern struct nodenum fidd2fget(); X X#endif END_OF_FILE if test 749 -ne `wc -c <'findinode/fid.h'`; then echo shar: \"'findinode/fid.h'\" unpacked with wrong size! fi # end of 'findinode/fid.h' fi if test -f 'getfcred.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'getfcred.c'\" else echo shar: Extracting \"'getfcred.c'\" \(1175 characters\) sed "s/^X//" >'getfcred.c' <<'END_OF_FILE' X/* History: X5/3/91 DJB modified to have safe behavior under !HAVE_UCRED X5/1/91 DJB baseline public domain X*/ X X/* X Xstruct ucred *getfcred(f) struct file *f; returns the user credentials Xfor open file f (in user memory). Note that on machines without struct Xucred, all open file descriptions are considered to be owned by root. X Xgetfcredstrerr is a strerrfun for getfcred(). X X*/ X X#include "structfile.h" X#include "structucred.h" X#include "getfcred.h" X#include "kmem.h" X#include "strerr.h" X#include "conffcredptr.h" X#include "confhaveucred.h" X Xstatic int getfcrederrno = 0; X Xstatic struct strerrtab e[] = { X { 0, "getfcred error 0", 0 } X#define GF_KMEM 1 X, { GF_KMEM, "cannot get file credentials: ", kmemstrerr } X} ; X Xchar *getfcredstrerr(ke) Xstrerrfun *ke; X{ X return strerrtaberr(ke,getfcrederrno,e,sizeof(e)/sizeof(*e),"unknown getfcred error"); X} X Xstatic struct ucred uc; X Xstruct ucred *getfcred(f) Xstruct file *f; X{ X#ifndef HAVE_UCRED X uc.uid = -1; uc.gid = -1; /*XXX*/ X return &uc; X#else X#ifdef FCRED_ISNOT_POINTER X return &(f->f_cred); X#else X if (kmemcpy((char *) &uc,(char *) f->f_cred,sizeof(uc)) == -1) X RETERN(0,getfcrederrno,GF_KMEM) X return &uc; X#endif X#endif X} END_OF_FILE if test 1175 -ne `wc -c <'getfcred.c'`; then echo shar: \"'getfcred.c'\" unpacked with wrong size! fi # end of 'getfcred.c' fi if test -f 'getnode.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'getnode.h'\" else echo shar: Extracting \"'getnode.h'\" \(696 characters\) sed "s/^X//" >'getnode.h' <<'END_OF_FILE' X#ifndef GETNODE_H X#define GETNODE_H X X#include "confdevt.h" X X/* don't give me any crap about one statement per line. */ X/* this is a lot more readable on half a page than on two. */ X X/* names can be 0 for not found. */ X X#define NODE_ID_INO 0 X#define NODE_ID_DEV 1 X#define NODE_ID_FIFOINO 2 X#define NODE_ID_FIFO 3 X Xstruct nodebuf X { X char *type; /* e.g., chr, blk, reg */ X int flagdev; /* one of the NODE_ID settings */ X union X { X /* XXX for inum/dev types here */ X struct { unsigned inum; unsigned DEV_T dev; char *name; int flagnfs; } ino; X struct { int maj; int min; char *name; } dev; X } X id; /* inode or device */ X } X; X Xextern int getnode(); Xextern int getnodeinit(); X X#endif END_OF_FILE if test 696 -ne `wc -c <'getnode.h'`; then echo shar: \"'getnode.h'\" unpacked with wrong size! fi # end of 'getnode.h' fi if test -f 'getpcred.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'getpcred.c'\" else echo shar: Extracting \"'getpcred.c'\" \(1368 characters\) sed "s/^X//" >'getpcred.c' <<'END_OF_FILE' X/* History: X5/3/91 DJB added reasonable behavior on !HAVE_UCRED X5/1/91 DJB baseline public domain X*/ X X/* X Xstruct ucred *getpcred(p) struct proc *p; returns the user credentials Xfor process p (in user memory). Note that on machines without struct Xproc, all processes are considered to have XXX root credentials. X Xgetpcredstrerr is a strerrfun for getpcred(). X X*/ X X#include "structfile.h" X#include "structucred.h" X#include "structproc.h" X#include "getpcred.h" X#include "kmem.h" X#include "strerr.h" X#include "confpcredinproc.h" X#include "confpcredunderproc.h" X#include "confhaveucred.h" X Xstatic int getpcrederrno = 0; X Xstatic struct strerrtab e[] = { X { 0, "getpcred error 0", 0 } X#define GP_KMEM 1 X, { GP_KMEM, "cannot get process credentials: ", kmemstrerr } X} ; X Xchar *getpcredstrerr(ke) Xstrerrfun *ke; X{ X return strerrtaberr(ke,getpcrederrno,e,sizeof(e)/sizeof(*e),"unknown getpcred error"); X} X Xstatic struct ucred uc; X Xstruct ucred *getpcred(p,u) Xstruct proc *p; Xstruct user *u; X{ X#ifndef HAVE_UCRED X uc.uid = p->p_uid; X return &uc; X#else X#ifdef PCRED_IN_PROC X return &(p->p_cred); X#else X#ifdef PCRED_UNDER_PROC X if (kmemcpy((char *) &uc,(char *) p->p_cred,sizeof(uc)) == -1) X RETERN(0,getpcrederrno,GP_KMEM) X return &uc; X#else X if (kmemcpy((char *) &uc,(char *) u->u_cred,sizeof(uc)) == -1) X RETERN(0,getpcrederrno,GP_KMEM) X return &uc; X#endif X#endif X#endif X} END_OF_FILE if test 1368 -ne `wc -c <'getpcred.c'`; then echo shar: \"'getpcred.c'\" unpacked with wrong size! fi # end of 'getpcred.c' fi if test -f 'getvmseg.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'getvmseg.c'\" else echo shar: Extracting \"'getvmseg.c'\" \(1515 characters\) sed "s/^X//" >'getvmseg.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline XOriginally stolen from Dupuy ofiles. X*/ X X/* X XXXX: Don't ask me what this does; I dunno nuthin' bout no mmaps, bro. X X*/ X X#include "structproc.h" X#include "vmstuff.h" X#include "getvmseg.h" X#include "structxnode.h" X#include "kmem.h" X#include "confhavevmseg.h" X Xint vmsegmax; X X#ifndef HAVE_VMSEG Xstatic struct vnode *result = 0; X Xstruct vnode **getvmseg(p) Xstruct proc *p; X{ X vmsegmax = 1; X return &result; X} X Xint seginit() X{ X ; X} X X#else X X#define SEGNLIST "_segvn_ops" X#define MAXSEGS 256 X Xstatic int init = 0; Xstatic unsigned long nlsegvnv; Xstatic short nlsegvnt; X Xint seginit() X{ X nlistadd(SEGNLIST,&nlsegvnt,&nlsegvnv); X init = 1; X return 0; X} X Xstruct vnode **getvmseg(p) Xstruct proc *p; X{ X static struct vnode *segvns[MAXSEGS]; X struct as as; X struct seg seg; X struct seg *s; X register int segn; X union gseg X { X struct segvn_data segvn; X struct segdev_data segdev; X struct segmap_data segmap; X } X gseg; X X segvns[0] = 0; X if (!(p->p_as)) X return segvns; X X if (!init) X seginit(); X if (nlsegvnt == -1) X nlistdo(); X X kmemcpy((char *) &as,(char *) p->p_as,sizeof(as)); X X segn = 0; X X for (s = as.a_segs;;s = seg.s_next) X { X kmemcpy((char *) &seg,(char *) s,sizeof(seg)); X kmemcpy((char *) &gseg,(char *) seg.s_data,sizeof(gseg)); X if ((unsigned long) seg.s_ops == nlsegvnv X &&gseg.segvn.vp X &&!gseg.segvn.amp) X segvns[segn++] = gseg.segvn.vp; X if (s == as.a_seglast || segn == MAXSEGS) X { X vmsegmax = segn; X return segvns; X } X } X} X X#endif END_OF_FILE if test 1515 -ne `wc -c <'getvmseg.c'`; then echo shar: \"'getvmseg.c'\" unpacked with wrong size! fi # end of 'getvmseg.c' fi if test -f 'groupname.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'groupname.c'\" else echo shar: Extracting \"'groupname.c'\" \(1171 characters\) sed "s/^X//" >'groupname.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain. todo: cache groups. X*/ X X/* X Xint gid2groupname(gid,gnp) int gid; char **gnp; looks up group gid and Xpoints *gnp to the name for that group (possibly stored in a static area Xinterfering with getgrgid()). If gid does not have a system name, Xgid2groupname() uses gid in decimal as the name and returns 1. Normally Xit returns 0. X Xint groupname2gid(gn,gid); char *gn; int *gid; looks up group name gn Xand sets *gid to the number of that group. If gn is entirely numeric it Xsimply sets *gid to that number are returns 1. Otherwise it returns 0. XIf gn is not numeric and not a system group name, groupname2gid returns X-1 and leaves *gid alone. X X*/ X X#include X#include "groupname.h" X#include "numeric.h" X Xint gid2groupname(gid,gnp) Xint gid; Xchar **gnp; X{ X struct group *gr; X static char gn[20]; X X if (gr = getgrgid(gid)) X { X *gnp = gr->gr_name; X return 0; X } X sprintf(gn,"%d",gid); X *gnp = gn; X return 1; X} X Xint groupname2gid(gn,gid) Xchar *gn; Xint *gid; X{ X struct group *gr; X X if (numeric(gn)) X { X *gid = atoi(gn); X return 1; X } X gr = getgrnam(gn); X if (!gr) X return -1; /*XXX*/ X *gid = gr->gr_gid; X return 0; X} END_OF_FILE if test 1171 -ne `wc -c <'groupname.c'`; then echo shar: \"'groupname.c'\" unpacked with wrong size! fi # end of 'groupname.c' fi if test -f 'inpcblist.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'inpcblist.c'\" else echo shar: Extracting \"'inpcblist.c'\" \(1642 characters\) sed "s/^X//" >'inpcblist.c' <<'END_OF_FILE' X/* History: X5/3/91 DJB unhid inperrno X5/1/91 DJB baseline public domain X*/ X X#include "inpcblist.h" X#include "structinpcb.h" X#include "kmem.h" X#include "nlistlist.h" X#include "strerr.h" X#include "conftcpnlist.h" X Xint inperrno = 0; Xstatic int inpinit = 0; Xstatic struct inpcb inp; Xstruct inpcb *inpcbloc = 0; Xstatic short intype; Xstatic unsigned long invalue; X Xchar *inpcbliststrerr(ke) Xstrerrfun *ke; X{ X *ke = 0; X switch(inperrno) X { X case 0: X return "inpcblist error 0"; X#define INP_INIT 1 X case INP_INIT: X *ke = nliststrerr; X return "cannot init inpcblit: "; X#define INP_NLIST 2 X case INP_NLIST: X *ke = nliststrerr; X return "cannot nlist: "; X#define INP_NLFOUND 3 X case INP_NLFOUND: X *ke = nlistnotin; X return TCPNLIST; X#define INP_KMEM 4 X case INP_KMEM: X *ke = kmemstrerr; X return "cannot read inpcb: "; X default: X return "unknown inpcblist error"; X } X} X Xint inpcblistinit() X{ X if (nlistadd(TCPNLIST,&intype,&invalue) == -1) X RETERN(-1,inperrno,INP_INIT) X inpinit = 1; X return 0; X} X Xstruct inpcb *nextinpcb(inpcb) Xstruct inpcb *inpcb; X{ X if (!inpcb) X { X if (!inpinit) X if (inpcblistinit() == -1) X return 0; X if (intype == -1) X if (nlistdo() == -1) X RETERN(0,inperrno,INP_NLIST) X if (!intype) X RETERN(0,inperrno,INP_NLFOUND) X if (kmemcpy((char *) &inp,(char *) invalue,sizeof(inp)) == -1) X RETERN(0,inperrno,INP_KMEM) X inpcb = &inp; X } X inpcbloc = inpcb->inp_next; X if ((char *) inpcbloc == (char *) invalue) X RETERN(0,inperrno,0) X if (kmemcpy((char *) &inp,(char *) inpcbloc,sizeof(inp)) == -1) X RETERN(0,inperrno,INP_KMEM) X return &inp; X} END_OF_FILE if test 1642 -ne `wc -c <'inpcblist.c'`; then echo shar: \"'inpcblist.c'\" unpacked with wrong size! fi # end of 'inpcblist.c' fi if test -f 'load.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'load.1'\" else echo shar: Extracting \"'load.1'\" \(914 characters\) sed "s/^X//" >'load.1' <<'END_OF_FILE' X.TH load 1 X.SH NAME Xload \- show boot time, current time, number of users, and load X.SH SYNTAX Xload X.SH DESCRIPTION X.I load Xprints one line in the following format: X.EX XMay 1 03:03:57, booted Apr 25 22:04:05, 9 users, load 1.16 1.02 1.00 X.EE XThe first date is the current time (actually characters X5 through 19 of the format returned by X.I ctime). XThe second is when the system was booted. XThe number of users is the number of lines shown in utmp. XThe three decimal numbers are the one-minute, five-minute, Xand fifteen-minute load averages. X X.I load Xis faster than X.I uptime Xand has an easier-to-parse format. X.PP X.SH DIAGNOSTICS XVarious errors if the boot time, current load average, or /etc/utmp Xcannot be read. In this case X.I load Xexits with exit value 1. X.SH BUGS XNone known. X.SH VERSION Xload 0.17 alpha, May 1, 1991. X.SH AUTHOR XPlaced into the public domain by Daniel J. Bernstein. X.SH "SEE ALSO" Xuptime(1) END_OF_FILE if test 914 -ne `wc -c <'load.1'`; then echo shar: \"'load.1'\" unpacked with wrong size! fi # end of 'load.1' fi if test -f 'load.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'load.c'\" else echo shar: Extracting \"'load.c'\" \(1206 characters\) sed "s/^X//" >'load.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X#include X#include X#include X#include "avenrun.h" X#include "boottime.h" X#include "strerr.h" X X#ifndef UTMP_FILE X#define UTMP_FILE "/etc/utmp" X#endif X Xstatic char progname[] = "load"; X Xmain() X{ X double *av; X long now; X long boottime; X FILE *fi; X struct utmp ut; X int numusers; X X if (avenruninit() == -1) X { fprintf(stderr,"%s: %s\n",progname,strerr(avenrunstrerr)); exit(1); } X if (boottimeinit() == -1) X { fprintf(stderr,"%s: %s\n",progname,strerr(boottimestrerr)); exit(1); } X X if (!(av = getavenrun())) X { fprintf(stderr,"%s: %s\n",progname,strerr(avenrunstrerr)); exit(1); } X if (!(boottime = getboottime())) X { fprintf(stderr,"%s: %s\n",progname,strerr(boottimestrerr)); exit(1); } X X if (!(fi = fopen(UTMP_FILE,"r"))) X { fprintf(stderr,"%s: cannot open %s",progname,UTMP_FILE); exit(1); } X numusers = 0; X while (fread((char *) &ut,sizeof(ut),1,fi)) X if (*ut.ut_name) X ++numusers; X /* don't bother closing fi */ X X (void) time(&now); X X printf("%15.15s, ",ctime(&now) + 4); X printf("booted %15.15s, %d users, load %.2f %.2f %.2f\n" X ,ctime(&boottime) + 4 X ,numusers X ,av[0] X ,av[1] X ,av[2] X ); X exit(0); X} END_OF_FILE if test 1206 -ne `wc -c <'load.c'`; then echo shar: \"'load.c'\" unpacked with wrong size! fi # end of 'load.c' fi if test -f 'mmem.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mmem.c'\" else echo shar: Extracting \"'mmem.c'\" \(1461 characters\) sed "s/^X//" >'mmem.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X XSee kmem.c for documentation. X X*/ X X#include X#include X#include "mmem.h" X#include "strerr.h" X X#define MMEM "/dev/mem" X X#define LSEEKFROMSTART 0 X Xstatic int mmemfd = -1; Xstatic int mmemerrno = 0; X Xstatic char *mmemerrprk(ke) strerrfun *ke; { *ke = strerrsys; return MMEM; } X Xchar *mmemstrerr(ke) Xstrerrfun *ke; X{ X *ke = 0; X switch(mmemerrno) X { X case 0: X return "mem error 0"; X#define MMEM_OPEN 1 X case MMEM_OPEN: X *ke = mmemerrprk; X return "cannot open "; X#define MMEM_LSEEK 2 X case MMEM_LSEEK: X *ke = strerrsys; X return "cannot lseek mem"; X#define MMEM_READ 3 X case MMEM_READ: X *ke = strerrsys; X return "cannot read mem"; X#define MMEM_READZERO 4 X case MMEM_READZERO: X return "mem read 0 bytes"; X default: X return "unknown mem error"; X } X} X Xint mmeminit() X{ X mmemfd = open(MMEM,O_RDONLY); X if (mmemfd == -1) X RETERN(-1,mmemerrno,MMEM_OPEN) X return 0; X} X Xint mmemcpy(buf,pos,n) Xchar *buf; Xchar *pos; Xint n; X{ X int r; X X if (!n) X return 0; X if (mmemfd == -1) X if (mmeminit() == -1) X return -1; X if (lseek(mmemfd,(long) pos,LSEEKFROMSTART) == -1) X RETERN(-1,mmemerrno,MMEM_LSEEK) X while ((r = read(mmemfd,buf,n)) < n) X if (r == -1) X RETERN(-1,mmemerrno,MMEM_READ) X else if (r == 0) /* XXX: this can never happen */ X RETERN(-1,mmemerrno,MMEM_READZERO) X else X { X buf += r; X n -= r; X } X return 0; X} END_OF_FILE if test 1461 -ne `wc -c <'mmem.c'`; then echo shar: \"'mmem.c'\" unpacked with wrong size! fi # end of 'mmem.c' fi if test -f 'portname.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'portname.c'\" else echo shar: Extracting \"'portname.c'\" \(700 characters\) sed "s/^X//" >'portname.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X XSee groupname.c for documentation. X X*/ X X#include "portname.h" X#include "numeric.h" X#include X X/* XXX: is getservby{port,name}(blah,0) standard? does it make sense here? */ X X/* XXX: cache */ X Xint port2portname(port,pop) Xint port; Xchar **pop; X{ X struct servent *se; X static char po[20]; X X if (se = getservbyport(port,0)) X { X *pop = se->s_name; X return 0; X } X sprintf(po,"%d",port); X *pop = po; X return 1; X} X Xint portname2port(po,port) Xchar *po; Xint *port; X{ X struct servent *se; X X if (numeric(po)) X { X *port = atoi(po); X return 1; X } X se = getservbyname(po,0); X if (!se) X return -1; /*XXX*/ X *port = se->s_port; X return 0; X} END_OF_FILE if test 700 -ne `wc -c <'portname.c'`; then echo shar: \"'portname.c'\" unpacked with wrong size! fi # end of 'portname.c' fi if test -f 'printfamily.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'printfamily.c'\" else echo shar: Extracting \"'printfamily.c'\" \(1534 characters\) sed "s/^X//" >'printfamily.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X Xchar *printfamily(family) int family; returns a string representation of Xthe given address family, or 0 if the family is unrecognized. The string Xreturned might not be malloced but will not be overwritten on separate Xcalls. X X*/ X X#include "structsocket.h" X#include "printfamily.h" X Xchar *printfamily(family) Xint family; X{ X switch(family) X { X#ifdef AF_UNSPEC X case AF_UNSPEC: return "unspec"; X#endif X#ifdef AF_UNIX X case AF_UNIX: return "unix"; X#endif X#ifdef AF_INET X case AF_INET: return "internet"; X#endif X#ifdef AF_IMPLINK X case AF_IMPLINK: return "implink"; X#endif X#ifdef AF_PUP X case AF_PUP: return "pup"; X#endif X#ifdef AF_CHAOS X case AF_CHAOS: return "chaos"; X#endif X#ifdef AF_NS X case AF_NS: return "ns"; X#endif X#ifdef AF_NBS X case AF_NBS: return "nbs"; X#endif X#ifdef AF_ECMA X case AF_ECMA: return "ecma"; X#endif X#ifdef AF_DATAKIT X case AF_DATAKIT: return "datakit"; X#endif X#ifdef AF_CCITT X case AF_CCITT: return "ccitt"; X#endif X#ifdef AF_SNA X case AF_SNA: return "sna"; X#endif X#ifdef AF_DECnet X case AF_DECnet: return "decnet"; X#endif X#ifdef AF_DLI X case AF_DLI: return "dli"; X#endif X#ifdef AF_LAT X case AF_LAT: return "lat"; X#endif X#ifdef AF_HYLINK X case AF_HYLINK: return "hylink"; X#endif X#ifdef AF_APPLETALK X case AF_APPLETALK: return "appletalk"; X#endif X#ifdef AF_BSC X case AF_BSC: return "bsc"; X#endif X#ifdef AF_DSS X case AF_DSS: return "dss"; X#endif X#ifdef AF_OSI X case AF_OSI: return "osi"; X#endif X default: return 0; X } X} END_OF_FILE if test 1534 -ne `wc -c <'printfamily.c'`; then echo shar: \"'printfamily.c'\" unpacked with wrong size! fi # end of 'printfamily.c' fi if test -f 'printfflag.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'printfflag.c'\" else echo shar: Extracting \"'printfflag.c'\" \(1253 characters\) sed "s/^X//" >'printfflag.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X Xchar *printfflag(f,style) struct file *f; int style; returns a string Xrepresentation of the file flag, f->f_flag (with f in user memory), in Xthe given style. Known styles, and examples with a RDWR | NDELAY file: Xstyle 0 produces "rwn", style 1 produces "rwn ", style 2 produces X"rw n ", style 4 produces "rw-n-----". Nonzero styles will always Xproduce 9-character outputs. The returned string is stored in a static Xarea that will be overwritten on each call. X X*/ X X#include X#include "structfile.h" X#include "printfflag.h" X Xstatic char result[15]; X Xchar *printfflag(f,style) Xstruct file *f; Xint style; X{ X int fflag; X int pos; X X if (style) X for (pos = 0;pos < sizeof(result);++pos) X result[pos] = ((style == 4) ? '-' : ' '); X pos = 0; X X fflag = f->f_flag; X#define FFLAG(F,X,P) \ Xif (fflag & F) { result[(style < 2) ? pos++ : P] = X; fflag &= ~F; } X X FFLAG(FREAD,'r',0) X FFLAG(FWRITE,'w',1) X FFLAG(FAPPEND,'a',2) X FFLAG(FNDELAY,'n',3) X FFLAG(FMARK,'m',4) X FFLAG(FASYNC,'y',5) X FFLAG(FSHLOCK,'s',6) X FFLAG(FEXLOCK,'e',7) X FFLAG(fflag,'?',8) X X /* omitted FDEFER---not a user-level flag, I don't think */ X X if (style) X result[9] = 0; X else X result[pos] = 0; X X return result; X} END_OF_FILE if test 1253 -ne `wc -c <'printfflag.c'`; then echo shar: \"'printfflag.c'\" unpacked with wrong size! fi # end of 'printfflag.c' fi if test -f 'printftype.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'printftype.c'\" else echo shar: Extracting \"'printftype.c'\" \(1081 characters\) sed "s/^X//" >'printftype.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X Xchar *printftype(f) struct file *f; returns a single-character string Xrepresentation of f->f_type (with f in user memory). In particular: "I" Xif f is a filesystem node, "S" if f is a socket, "N" if f is a named Xpipe or port with semantics similar to POSIX fifos; "P" if f is a pipe X(note that in some systems, pipes are implemented on top of sockets); X"p" if f refers to a process, typically for the debugger. printftype Xreturns "?" if it does not recognize f->f_type. X X*/ X X#include "structxnode.h" X#include "structfile.h" X#include "printftype.h" X Xchar *printftype(f) Xstruct file *f; X{ X if (f->f_type == DTYPE_INODE) return "I"; X if (f->f_type == DTYPE_SOCKET) return "S"; X#ifdef DTYPE_PORT X if (f->f_type == DTYPE_PORT) return "N"; X#endif X#ifdef DTYPE_PIPE X if (f->f_type == DTYPE_PIPE) return "P"; X#endif X#ifdef DTYPE_PROCESS X if (f->f_type == DTYPE_PROCESS) return "p"; X#endif X#ifdef DTYPE_KRPC X if (f->f_type == DTYPE_KRPC) return "k"; X#endif X#ifdef DTYPE_SPU X if (f->f_type == DTYPE_SPU) return "u"; X#endif X return "?"; X} END_OF_FILE if test 1081 -ne `wc -c <'printftype.c'`; then echo shar: \"'printftype.c'\" unpacked with wrong size! fi # end of 'printftype.c' fi if test -f 'printprotoinet.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'printprotoinet.c'\" else echo shar: Extracting \"'printprotoinet.c'\" \(1107 characters\) sed "s/^X//" >'printprotoinet.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X Xchar *printprotoinet(proto) int proto; returns a string representation Xof the given Internet protocol, or 0 if the protocol is unrecognized. XThe string returned might not be malloced but will not be overwritten on Xseparate calls. X X*/ X X#include "structsockaddrin.h" X#include "printprotoinet.h" X Xchar *printprotoinet(proto) Xint proto; X{ X switch(proto) X { X#ifdef IPPROTO_TCP X case IPPROTO_TCP: return "tcp"; X#endif X#ifdef IPPROTO_UDP X case IPPROTO_UDP: return "udp"; X#endif X#ifdef IPPROTO_IP X case IPPROTO_IP: return "ip"; X#endif X#ifdef IPPROTO_ICMP X case IPPROTO_ICMP: return "icmp"; X#endif X#ifdef IPPROTO_IGMP X case IPPROTO_IGMP: return "igmp"; X#endif X#ifdef IPPROTO_GGP X case IPPROTO_GGP: return "ggp"; X#endif X#ifdef IPPROTO_EGP X case IPPROTO_EGP: return "egp"; X#endif X#ifdef IPPROTO_PUP X case IPPROTO_PUP: return "pup"; X#endif X#ifdef IPPROTO_IDP X case IPPROTO_IDP: return "idp"; X#endif X#ifdef IPPROTO_ND X case IPPROTO_ND: return "nd"; X#endif X#ifdef IPPROTO_RAW X case IPPROTO_RAW: return "raw"; X#endif X default: return 0; X } X} END_OF_FILE if test 1107 -ne `wc -c <'printprotoinet.c'`; then echo shar: \"'printprotoinet.c'\" unpacked with wrong size! fi # end of 'printprotoinet.c' fi if test -f 'printrlimits.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'printrlimits.c'\" else echo shar: Extracting \"'printrlimits.c'\" \(1506 characters\) sed "s/^X//" >'printrlimits.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X Xchar *printrlimits(rl) struct rlimit *rl; returns a string representing Xvarious information about rlimit array rl. Not well defined. X X*/ X X#include X#include X#include X#include X#include X#include "printrlimits.h" X Xstatic char result[500]; X X/* XXX: print anything other than max? */ X Xchar *printrlimits(rl) Xstruct rlimit *rl; X{ X char *t; X X t = result; X X#ifdef RLIMIT_CPU X if (rl[RLIMIT_CPU].rlim_max == RLIM_INFINITY) sprintf(t,"cpu inf "); X else sprintf(t,"cpu %8d ",rl[RLIMIT_CPU].rlim_max); X t += strlen(t); X#endif X#ifdef RLIMIT_FSIZE X if (rl[RLIMIT_FSIZE].rlim_max == RLIM_INFINITY) sprintf(t,"file inf "); X else sprintf(t,"fsize %8d ",rl[RLIMIT_FSIZE].rlim_max); X t += strlen(t); X#endif X#ifdef RLIMIT_DATA X if (rl[RLIMIT_DATA].rlim_max == RLIM_INFINITY) sprintf(t,"data inf "); X else sprintf(t,"data %8d ",rl[RLIMIT_DATA].rlim_max); X t += strlen(t); X#endif X#ifdef RLIMIT_STACK X if (rl[RLIMIT_STACK].rlim_max == RLIM_INFINITY) sprintf(t,"stack inf "); X else sprintf(t,"stack %8d ",rl[RLIMIT_STACK].rlim_max); X t += strlen(t); X#endif X#ifdef RLIMIT_CORE X if (rl[RLIMIT_CORE].rlim_max == RLIM_INFINITY) sprintf(t,"core inf "); X else sprintf(t,"core %8d ",rl[RLIMIT_CORE].rlim_max); X t += strlen(t); X#endif X#ifdef RLIMIT_RSS X if (rl[RLIMIT_RSS].rlim_max == RLIM_INFINITY) sprintf(t,"mem inf "); X else sprintf(t,"rss %8d ",rl[RLIMIT_RSS].rlim_max); X t += strlen(t); X#endif X X return result; X} END_OF_FILE if test 1506 -ne `wc -c <'printrlimits.c'`; then echo shar: \"'printrlimits.c'\" unpacked with wrong size! fi # end of 'printrlimits.c' fi if test -f 'printrusage.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'printrusage.c'\" else echo shar: Extracting \"'printrusage.c'\" \(1440 characters\) sed "s/^X//" >'printrusage.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X Xchar *printrusage(ru) struct rusage *ru; returns a string representation Xof practically everything about ru. Not well defined. X X*/ X X#include X#include X#include X#include X#include X#include "printrusage.h" X Xstatic char result[500]; X X#define hz 30 /*XXX*/ X Xchar *printrusage(ru) Xstruct rusage *ru; X{ X char *t; X long ticks; X X t = result; X sprintf(t,"%d.%02.2du ",ru->ru_utime.tv_sec,ru->ru_utime.tv_usec/10000); X t += strlen(t); X sprintf(t,"%d.%02.2ds ",ru->ru_stime.tv_sec,ru->ru_stime.tv_usec/10000); X t += strlen(t); X X /* XXX: ru_maxrss? ru_isrss? */ X /* XXX: maybe we should print total, not average, rss here? */ X ticks = hz * (ru->ru_utime.tv_sec + ru->ru_stime.tv_sec) X + hz * (ru->ru_utime.tv_usec + ru->ru_stime.tv_usec) / 1000000; X /* Note that most BSD code will dump if ticks == 0. */ X sprintf(t,"%ld+%ldk " X ,!ticks ? 0 : (ru->ru_ixrss/ticks) X ,!ticks ? 0 : (ru->ru_idrss/ticks) X ); X t += strlen(t); X X sprintf(t,"%ld+%ldio ",ru->ru_inblock,ru->ru_oublock); X t += strlen(t); X X /* XXX: ru_minflt? (``pr'') */ X sprintf(t,"%ldpf+%ldw ",ru->ru_majflt,ru->ru_nswap); X t += strlen(t); X X /* X sprintf(t,"%ld+%ldmsg ",ru->ru_msgsnd,ru->ru_msgrcv); X t += strlen(t); X */ X X sprintf(t,"%ld+%ldcsw ",ru->ru_nvcsw,ru->ru_nivcsw); X t += strlen(t); X X sprintf(t,"%ldsig",ru->ru_nsignals); X t += strlen(t); X X return result; X} END_OF_FILE if test 1440 -ne `wc -c <'printrusage.c'`; then echo shar: \"'printrusage.c'\" unpacked with wrong size! fi # end of 'printrusage.c' fi if test -f 'printsocktype.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'printsocktype.c'\" else echo shar: Extracting \"'printsocktype.c'\" \(581 characters\) sed "s/^X//" >'printsocktype.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X Xchar *printsocktype(t) int t; returns a string representation of the Xgiven socket type, or 0 if the type is unrecognized. The string returned Xmight not be malloced but will not be overwritten on separate calls. X X*/ X X#include "structsocket.h" X#include "printsocktype.h" X Xchar *printsocktype(t) Xint t; X{ X switch(t) X { X case SOCK_STREAM: return "stream"; X case SOCK_DGRAM: return "dgram"; X case SOCK_RAW: return "raw"; X case SOCK_RDM: return "rdm"; X case SOCK_SEQPACKET: return "seqpacket"; X default: return 0; X } X} END_OF_FILE if test 581 -ne `wc -c <'printsocktype.c'`; then echo shar: \"'printsocktype.c'\" unpacked with wrong size! fi # end of 'printsocktype.c' fi if test -f 'revnamei.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'revnamei.c'\" else echo shar: Extracting \"'revnamei.c'\" \(1572 characters\) sed "s/^X//" >'revnamei.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X#include "revnamei.h" X X/* XXX: closing? wait()? etc. */ X Xstatic int fdfidread = -1; Xstatic int fdfidwrite = -1; X Xrevnameiinit() X{ X int pio[2]; X int pii[2]; X X pipe(pio); X pipe(pii); X X#ifdef NO_FINDINODE X switch(-1) X#else X switch(fork()) X#endif X { X case -1: /*XXX*/ X fdfidwrite = pii[1]; X fdfidread = pio[0]; X close(pii[0]); X close(pio[1]); X break; X case 0: X close(pii[1]); X close(pio[0]); X dup2(pii[0],0); X dup2(pio[1],1); X execlp("findinode","findinode","-A",(char *) 0); X exit(1); X default: X fdfidwrite = pii[1]; X fdfidread = pio[0]; X close(pii[0]); X close(pio[1]); X break; X } X} X Xrevnamei(ino,dev) Xunsigned long ino; Xunsigned long dev; X{ X if (fdfidwrite == -1) X revnameiinit(); X if (fdfidwrite != -1) X { X char buf[50]; X int r; X int out; X int i; X sprintf(buf,"%lu %lx\n",ino,dev); X write(fdfidwrite,buf,strlen(buf)); X /* XXX: worry about blocking? not if findinode works */ X out = 0; X while ((r = read(fdfidread,buf,30)) != -1) X { X if (!r) X { X /* EOF, child must have died or never started up */ X close(fdfidwrite); X close(fdfidread); X fdfidread = fdfidwrite = -1; X break; X } X for (i = 0;i < r;++i) X { X if (buf[i] == '\n') X goto breakbreak; X if (out == 2) X putchar(buf[i]); X else X { X if (out == 1) X if (buf[i] == ' ') X out = 2; X else X out = 0; X if (!out) X if (buf[i] == ':') X out = 1; X } X } X } X breakbreak: ; X } X} END_OF_FILE if test 1572 -ne `wc -c <'revnamei.c'`; then echo shar: \"'revnamei.c'\" unpacked with wrong size! fi # end of 'revnamei.c' fi if test -f 'rpcnfs.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rpcnfs.h'\" else echo shar: Extracting \"'rpcnfs.h'\" \(739 characters\) sed "s/^X//" >'rpcnfs.h' <<'END_OF_FILE' X#ifndef RPCNFS_H /*XXX this entire include file*/ X#define RPCNFS_H X X#include X#ifndef ITIMER_REAL X#include X#endif X#include X X#include "confnfs.h" X#include "confconvexrpcnfs.h" X#include "confultrixrpcnfs.h" X#ifdef CONVEXRPCNFS X#include X#include X#endif X#ifdef ULTRIXRPCNFS X#include X#include /* dorks */ X#include "structsockaddrin.h" /* dorks */ X#ifndef NFS_RETRIES X#include X#include X#endif X#include X#include X#else X#ifdef NFS X#include X#include X#include X#include X#include "structxnode.h" /* sigh */ X#include X#endif X#endif X X#endif END_OF_FILE if test 739 -ne `wc -c <'rpcnfs.h'`; then echo shar: \"'rpcnfs.h'\" unpacked with wrong size! fi # end of 'rpcnfs.h' fi if test -f 'smem.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'smem.c'\" else echo shar: Extracting \"'smem.c'\" \(1467 characters\) sed "s/^X//" >'smem.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X XSee kmem.c for documentation. X X*/ X X#include X#include X#include "smem.h" X#include "strerr.h" X X#define SMEM "/dev/drum" X X#define LSEEKFROMSTART 0 X Xstatic int smemfd = -1; Xstatic int smemerrno = 0; X Xstatic char *smemerrprk(ke) strerrfun *ke; { *ke = strerrsys; return SMEM; } X Xchar *smemstrerr(ke) Xstrerrfun *ke; X{ X *ke = 0; X switch(smemerrno) X { X case 0: X return "drum error 0"; X#define SMEM_OPEN 1 X case SMEM_OPEN: X *ke = smemerrprk; X return "cannot open "; X#define SMEM_LSEEK 2 X case SMEM_LSEEK: X *ke = strerrsys; X return "cannot lseek drum"; X#define SMEM_READ 3 X case SMEM_READ: X *ke = strerrsys; X return "cannot read drum"; X#define SMEM_READZERO 4 X case SMEM_READZERO: X return "drum read 0 bytes"; X default: X return "unknown drum error"; X } X} X Xint smeminit() X{ X smemfd = open(SMEM,O_RDONLY); X if (smemfd == -1) X RETERN(-1,smemerrno,SMEM_OPEN) X return 0; X} X Xint smemcpy(buf,pos,n) Xchar *buf; Xchar *pos; Xint n; X{ X int r; X X if (!n) X return 0; X if (smemfd == -1) X if (smeminit() == -1) X return -1; X if (lseek(smemfd,(long) pos,LSEEKFROMSTART) == -1) X RETERN(-1,smemerrno,SMEM_LSEEK) X while ((r = read(smemfd,buf,n)) < n) X if (r == -1) X RETERN(-1,smemerrno,SMEM_READ) X else if (r == 0) /* XXX: this can never happen */ X RETERN(-1,smemerrno,SMEM_READZERO) X else X { X buf += r; X n -= r; X } X return 0; X} END_OF_FILE if test 1467 -ne `wc -c <'smem.c'`; then echo shar: \"'smem.c'\" unpacked with wrong size! fi # end of 'smem.c' fi if test -f 'stattimeout.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'stattimeout.c'\" else echo shar: Extracting \"'stattimeout.c'\" \(948 characters\) sed "s/^X//" >'stattimeout.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline X3/15/91 DJB Extracted into separate library, added timeout arg XStolen from safe_stat in Dupuy ofiles. X*/ X X/* XXX: There are all sorts of race conditions here. DJB */ X X#include X#include X#include X#include X#include Xextern int errno; Xstatic jmp_buf jmpbuf; X X/* ARGSUSED */ Xstatic int wakeup() X{ X (void) alarm(0); X (void) signal(SIGALRM,SIG_IGN); X longjmp(jmpbuf,1); X} X Xint stattimeout(path,buf,timeout) Xchar *path; Xstruct stat *buf; Xint timeout; X{ X int err; X static int saveerrno; X X if (!timeout) X return stat(path,buf); X X saveerrno = errno; X if (setjmp(jmpbuf)) X { X (void) alarm(0); X (void) signal(SIGALRM,SIG_IGN); X errno = ETIMEDOUT; X return -1; X } X (void) signal(SIGALRM,wakeup); X (void) alarm(timeout); X err = stat(path,buf); X if (err) X saveerrno = errno; X (void) alarm(0); X (void) signal(SIGALRM,SIG_IGN); X errno = saveerrno; X return err; X} END_OF_FILE if test 948 -ne `wc -c <'stattimeout.c'`; then echo shar: \"'stattimeout.c'\" unpacked with wrong size! fi # end of 'stattimeout.c' fi if test -f 'structfile.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'structfile.h'\" else echo shar: Extracting \"'structfile.h'\" \(1256 characters\) sed "s/^X//" >'structfile.h' <<'END_OF_FILE' X#ifndef STRUCT_FILE_H X#define STRUCT_FILE_H X X/* On any supported system, you can #include "structfile.h" any number */ X/* of times safely to get a complete definition of struct file. */ X X/* On an optimal system, this file would contain solely: */ X/* #include */ X X#include "confconvexsysfile.h" X#include "confetcconfhfileh.h" X#include X#include /* ultrix lock_t dorks */ X#define KERNEL X#ifdef ETCCONFHFILEH X#include "/etc/conf/h/file.h" X#else X#ifdef CONVEXSYSFILE X#include /* fer cryin' out loud... */ X#ifndef FHLOCAL X#include /* idiots */ X#endif X#endif X#include X#endif X#undef KERNEL X#include "confodofe.h" X#ifdef ODOFE X/* XXX X * This is from sys/user.h. It's ifdef KERNEL, though, and defining X * KERNEL for user.h breaks other things. X * Open-file table extension object structure. X */ Xstruct ofile_ext { X struct ofile_ext *oe_next; /* list of unused entries */ X short oe_nofile; /* # ofile entries */ X short oe_refcnt; /* # proc's sharing this ext */ X short oe_ccount; /* # sharing proc's in memory */ X swblk_t oe_swaddr; /* disk address when swapped */ X sema_t oe_mutex; /* misc mutex */ X struct ofile *oe_ofile; /* array of open files */ X}; X#endif X X#endif END_OF_FILE if test 1256 -ne `wc -c <'structfile.h'`; then echo shar: \"'structfile.h'\" unpacked with wrong size! fi # end of 'structfile.h' fi if test -f 'structinpcb.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'structinpcb.h'\" else echo shar: Extracting \"'structinpcb.h'\" \(581 characters\) sed "s/^X//" >'structinpcb.h' <<'END_OF_FILE' X#ifndef STRUCT_INPCB_H X#define STRUCT_INPCB_H X X/* On an optimal system, this file would contain solely: */ X/* #include */ X X#include "structsocket.h" /* sigh... dynix */ X#include "confsyncsema.h" X#include X#ifndef SOCK_STREAM X#include X#endif X#ifdef SYNCSEMA X#include X#include X#ifndef MSIZE X#include /* dorks */ X#endif X#endif X#ifndef RTF_UP X#include X#endif X#ifndef IPPROTO_TCP X#include X#endif X#include /* XXX: any way to bracket this? */ X X#endif END_OF_FILE if test 581 -ne `wc -c <'structinpcb.h'`; then echo shar: \"'structinpcb.h'\" unpacked with wrong size! fi # end of 'structinpcb.h' fi if test -f 'structmtab.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'structmtab.h'\" else echo shar: Extracting \"'structmtab.h'\" \(746 characters\) sed "s/^X//" >'structmtab.h' <<'END_OF_FILE' X#ifndef STRUCT_MTAB_H X#define STRUCT_MTAB_H X X#include "confmntent.h" X#include "confmntult.h" X#ifdef MNTENT X#ifndef FILE X#include X#endif X#include X#else X#ifdef MNTULT X#include X#include X#undef m_path /* dorks */ X#endif X#include X#ifndef MNTMAXSTR X#define MNTMAXSTR (sizeof ((struct mtab *)0)->m_path) X/* A big problem here is that Ultrix 4.1, at least, defines m_path in two */ X/* DIFFERENT ways in sys/mount.h and mtab.h. Dorks. Fortunately, they */ X/* do define MNTMAXSTR in nfs/nfs_clnt.h, so we arrange to include that */ X/* whenever this file is used. A better solution would be to bomb DEC. */ X#endif X#define mntent mtab X#define mnt_dir m_path X#define mnt_fsname m_dname X#endif X X#endif END_OF_FILE if test 746 -ne `wc -c <'structmtab.h'`; then echo shar: \"'structmtab.h'\" unpacked with wrong size! fi # end of 'structmtab.h' fi if test -f 'structpte.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'structpte.h'\" else echo shar: Extracting \"'structpte.h'\" \(624 characters\) sed "s/^X//" >'structpte.h' <<'END_OF_FILE' X#ifndef STRUCT_PTE_H X#define STRUCT_PTE_H X X#include "confneedartospte.h" X#ifdef NEED_ARTOS_PTE_H X#include X#include X#define ctob PAGEtoBYTES X/*XXX: usrpt? */ X#define Usrptma Sysmap X#define btokmx(b) (((caddr_t)(b) - (caddr_t)SYSBASE) / ZS_PAGESIZE) X#define p_p0br p_p0b /* XXX: belongs in structproc */ X#define p_szpt p_szst /* XXX: belongs in structproc */ X#undef MIN X#undef MAX X#undef NBPG X#undef PGOFSET X#undef PGSHIFT X#include X#define NPTEPG (NBPG/sizeof(long)) X#define dtob(x) ((x) << 10) X#include X#else X#include /* PG_V? PG_TYPE? */ X#endif X X#endif END_OF_FILE if test 624 -ne `wc -c <'structpte.h'`; then echo shar: \"'structpte.h'\" unpacked with wrong size! fi # end of 'structpte.h' fi if test -f 'structxnode.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'structxnode.h'\" else echo shar: Extracting \"'structxnode.h'\" \(1328 characters\) sed "s/^X//" >'structxnode.h' <<'END_OF_FILE' X#ifndef STRUCT_XNODE_H X#define STRUCT_XNODE_H X X/* In an optimal system, this file would consist of solely: */ X/* #include */ X X#include X#ifndef ITIMER_REAL X#include X#endif X#include X X#include "confnfs.h" X#include "confgnode.h" X#include "confconvexfilegarbage.h" X#ifdef CONVEXFILEGARBAGE /* This is almost embarassing. */ X#include X#ifndef FHLOCAL X#include X#endif X#define KERNEL X#include X#include X#undef KERNEL X#include X#include X#include X#include X#endif X#ifdef GNODE X#include X#define Xnode gnode X#define unp_Xnode unp_inode X#define x_Xptr x_gptr X#ifdef NFS X#ifndef bool_t /*XXXX*/ X#include X#endif X#include /* dorks */ X#ifndef NFS_RETRIES X#include X#include X#endif X#endif X#else X#ifndef NFS X#define Xnode inode X#define unp_Xnode unp_inode X#define x_Xptr x_iptr X#endif X#ifdef NFS X#include X#define Xnode vnode X#define unp_Xnode unp_vnode X#define x_Xptr x_vptr X#define DTYPE_INODE DTYPE_VNODE X#define KERNEL /*XXX: dynix */ X#include X#undef KERNEL X#if defined(S_IFIFO) && defined(GET_FIFOS) X#include X#endif X#else X#include X#endif X#endif X#endif END_OF_FILE if test 1328 -ne `wc -c <'structxnode.h'`; then echo shar: \"'structxnode.h'\" unpacked with wrong size! fi # end of 'structxnode.h' fi if test -f 'tcpuid.8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tcpuid.8'\" else echo shar: Extracting \"'tcpuid.8'\" \(618 characters\) sed "s/^X//" >'tcpuid.8' <<'END_OF_FILE' X.TH tcpuid 8 X.SH NAME Xtcpuid \- show the user id that created a network connection X.SH SYNTAX Xtcpuid X.I rem.ote.in.addr X.I remport X.I loc.al.in.addr X.I locport X.SH DESCRIPTION X.I tcpuid Xprints the numeric user id of Xthe user who created Xthe network connection specified by its arguments. X.PP X.SH DIAGNOSTICS X.TP XLots, none of which should happen if the specified Xconnection is valid. X.SH BUGS XNone known. X.SH VERSION Xtcpuid version 3.5 alpha, May 1, 1991. X.SH AUTHOR XPlaced into the public domain by Daniel J. Bernstein. XPartially inspired by code written by Vic Abell for ofiles. X.SH "SEE ALSO" Xauthd(8), Xtcpuname(8) END_OF_FILE if test 618 -ne `wc -c <'tcpuid.8'`; then echo shar: \"'tcpuid.8'\" unpacked with wrong size! fi # end of 'tcpuid.8' fi if test -f 'tcpuname.8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tcpuname.8'\" else echo shar: Extracting \"'tcpuname.8'\" \(615 characters\) sed "s/^X//" >'tcpuname.8' <<'END_OF_FILE' X.TH tcpuname 8 X.SH NAME Xtcpuname \- show the user name that created a network connection X.SH SYNTAX Xtcpuname X.I rem.ote.in.addr X.I remport X.I loc.al.in.addr X.I locport X.SH DESCRIPTION X.I tcpuname Xprints the username of Xthe user who created Xthe network connection specified by its arguments. X.PP X.SH DIAGNOSTICS X.TP XLots, none of which should happen if the specified Xconnection is valid. X.SH BUGS XNone known. X.SH VERSION Xtcpuname version 3.5, May 1, 1991. X.SH AUTHOR XPlaced into the public domain by Daniel J. Bernstein. XPartially inspired by code written by Vic Abell for ofiles. X.SH "SEE ALSO" Xauthd(8), Xtcpuid(8) END_OF_FILE if test 615 -ne `wc -c <'tcpuname.8'`; then echo shar: \"'tcpuname.8'\" unpacked with wrong size! fi # end of 'tcpuname.8' fi if test -f 'username.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'username.c'\" else echo shar: Extracting \"'username.c'\" \(593 characters\) sed "s/^X//" >'username.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline public domain X*/ X X/* X XSee groupname.c for documentation. X X*/ X X#include X#include "username.h" X#include "numeric.h" X X/*XXX: cache */ X Xint uid2username(uid,unp) Xint uid; Xchar **unp; X{ X struct passwd *pw; X static char un[20]; X X if (pw = getpwuid(uid)) X { X *unp = pw->pw_name; X return 0; X } X sprintf(un,"%d",uid); X *unp = un; X return 1; X} X Xint username2uid(un,uid) Xchar *un; Xint *uid; X{ X struct passwd *pw; X X if (numeric(un)) X { X *uid = atoi(un); X return 1; X } X pw = getpwnam(un); X if (!pw) X return -1; /*XXX*/ X *uid = pw->pw_uid; X return 0; X} END_OF_FILE if test 593 -ne `wc -c <'username.c'`; then echo shar: \"'username.c'\" unpacked with wrong size! fi # end of 'username.c' fi if test -f 'virtype.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'virtype.c'\" else echo shar: Extracting \"'virtype.c'\" \(1674 characters\) sed "s/^X//" >'virtype.c' <<'END_OF_FILE' X/* History: X5/1/91 DJB baseline XDerived from Dupuy ofiles. X*/ X X#include X#include X#include "structxnode.h" X#include "rpcnfs.h" X#include "virtype.h" X Xstatic char *regular = "reg"; Xstatic char *directory = "dir"; Xstatic char *block = "blk"; Xstatic char *character = "chr"; Xstatic char *symbolic = "sym"; Xstatic char *unixsocket = "sck"; X#ifdef S_IFIFO Xstatic char *fifo = "pip"; X#endif X X#ifdef V_TYPE Xstatic char *none = "non"; Xstatic char *badvtype = "bad"; Xstatic char *unknownvtype = "unk"; X Xchar *vtype(type) Xenum vtype type; X{ X switch(type) X { X case VNON: return none; X case VREG: return regular; X case VDIR: return directory; X case VBLK: return block; X case VCHR: return character; X case VLNK: return symbolic; X case VSOCK: return unixsocket; X case VBAD: return badvtype; X#ifdef S_IFIFO X case VFIFO: return fifo; X#endif X default: return unknownvtype; X } X} X X#endif X X#ifdef R_TYPE Xstatic char *unknownrnode = "unk"; X Xchar *rtype(type) Xenum nfsftype type; X{ X switch(type) X { X case NFNON: return none; X case NFREG: return regular; X case NFDIR: return directory; X case NFBLK: return block; X case NFCHR: return character; X case NFLNK: return symbolic; X default: return unknownrnode; X } X} X X#endif X X#ifdef I_TYPE Xstatic char *unknownitype = "unk"; X Xchar *itype(mode) Xunsigned mode; X{ X switch(mode & S_IFMT) X { X case S_IFREG: return regular; X case S_IFDIR: return directory; X case S_IFBLK: return block; X case S_IFCHR: return character; X case S_IFLNK: return symbolic; X case S_IFSOCK: return unixsocket; X#ifdef S_IFIFO X case S_IFIFO: return fifo; X#endif X default: return unknownitype; X } X} X#endif END_OF_FILE if test 1674 -ne `wc -c <'virtype.c'`; then echo shar: \"'virtype.c'\" unpacked with wrong size! fi # end of 'virtype.c' fi echo shar: End of archive 2 \(of 6\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 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