Makefile 444 0 0 6462 5330355775 5467 # # Copyright (c) 1986 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 4.13 (Berkeley) 5/15/86 # # This makefile is designed to be run as: # make build # make installsrc # The `make build' will compile and install the libraries # before building the rest of the sources. The `make installsrc' # will then install the remaining binaries. # # It can also be run in the more conventional way: # make # make install # The `make' will compile everything without installing anything. # The `make install' will then install everything. Note however # that all the binaries will have been loaded with the old libraries. # # C library options: passed to libc makefile. # See lib/libc/Makefile for explanation. # NOTE: The method of hostname lookup (hosts file or nameserver) is no # longer selected here. Make sure to edit lib/libc/Makefile to set # HOSTLOOKUP # DFLMON must be either mon.o or gmon.o. # DEFS may include -DLIBC_SCCS, -DSYSLIBC_SCCS, both, or neither. # DFLMON=mon.o DEFS= LIBCDEFS= DFLMON=${DFLMON} DEFS="${DEFS}" # global flags # SRC_MFLAGS are used on makes in command source directories, # but not in library or compiler directories that will be installed # for use in compiling everything else. # DESTDIR= CFLAGS= -O SRC_MFLAGS = -k # Programs that live in subdirectories, and have makefiles of their own. # LIBDIR= lib usr.lib SRCDIR= bin etc games local new ucb usr.bin man all: ${LIBDIR} ${SRCDIR} lib: FRC cd lib/libc; make ${MFLAGS} ${LIBCDEFS} cd lib; make ${MFLAGS} ccom cpp c2 usr.lib ${SRCDIR}: FRC cd $@; make ${MFLAGS} ${SRC_MFLAGS} build: buildlib ${SRCDIR} buildlib: FRC @echo installing /usr/include # cd include; make ${MFLAGS} DESTDIR=${DESTDIR} install @echo @echo compiling libc.a cd lib/libc; make ${MFLAGS} ${LIBCDEFS} @echo installing /lib/libc.a cd lib/libc; make ${MFLAGS} DESTDIR=${DESTDIR} install @echo @echo compiling C compiler cd lib; make ${MFLAGS} ccom cpp c2 @echo installing C compiler cd lib/ccom; make ${MFLAGS} DESTDIR=${DESTDIR} install cd lib/cpp; make ${MFLAGS} DESTDIR=${DESTDIR} install cd lib/c2; make ${MFLAGS} DESTDIR=${DESTDIR} install cd lib; make ${MFLAGS} clean @echo @echo re-compiling libc.a cd lib/libc; make ${MFLAGS} ${LIBCDEFS} @echo re-installing /lib/libc.a cd lib/libc; make ${MFLAGS} DESTDIR=${DESTDIR} install @echo @echo re-compiling C compiler cd lib; make ${MFLAGS} ccom cpp c2 @echo re-installing C compiler cd lib/ccom; make ${MFLAGS} DESTDIR=${DESTDIR} install cd lib/cpp; make ${MFLAGS} DESTDIR=${DESTDIR} install cd lib/c2; make ${MFLAGS} DESTDIR=${DESTDIR} install @echo @echo compiling usr.lib cd usr.lib; make ${MFLAGS} ${SRC_MFLAGS} @echo installing /usr/lib cd usr.lib; make ${MFLAGS} ${SRC_MFLAGS} DESTDIR=${DESTDIR} install FRC: install: -for i in ${LIBDIR} ${SRCDIR}; do \ (cd $$i; \ make ${MFLAGS} ${SRC_MFLAGS} DESTDIR=${DESTDIR} install); \ done installsrc: -for i in ${SRCDIR}; do \ (cd $$i; \ make ${MFLAGS} ${SRC_MFLAGS} DESTDIR=${DESTDIR} install); \ done tags: for i in include lib usr.lib; do \ (cd $$i; make ${MFLAGS} TAGSFILE=../tags tags); \ done sort -u +0 -1 -o tags tags clean: rm -f a.out core *.s *.o for i in ${LIBDIR} ${SRCDIR}; do (cd $$i; make -k ${MFLAGS} clean); done asm.sed 444 0 12 65 4026501266 5245 s,asm.sed.pdp 4.1 82/10/06,asm.sed.pdp 4.1 82/10/06, alifornia. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 4.13 (Berkeley) 5/15/86 # # This makefile is designed to be run as: # make build # make installsrc # The `make build' will compile and install the libraries # before building the rest of the sources. The `make installsrc' # will then install the remaining binaries. # # It can also be run in the more conventiasm.sed.pdp 444 0 12 65 4026501240 6017 s,asm.sed.pdp 4.1 82/10/06,asm.sed.pdp 4.1 82/10/06, alifornia. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 4.13 (Berkeley) 5/15/86 # # This makefile is designed to be run as: # make build # make installsrc # The `make build' will compile and install the libraries # before building the rest of the sources. The `make installsrc' # will then install the remaining binaries. # # It can also be run in the more conventiasm.sed.vax 444 0 12 4254 4026501256 6105 s,asm.sed.vax 4.1 82/10/06,asm.sed.vax 4.1 82/10/06, s/calls $0,_spl0/mfpr $18,r0\ mtpr $0,$18/ s/calls $0,_spl1/mfpr $18,r0\ mtpr $0,$18/ s/calls $0,_splnet/mfpr $18,r0\ mtpr $0xc,$18/ s/calls $0,_spl4/mfpr $18,r0\ mtpr $0x14,$18/ s/calls r[0-9]*,_spl4/mfpr $18,r0\ mtpr $0x14,$18/ s/calls $0,_spl5/mfpr $18,r0\ mtpr $0x15,$18/ s/calls r[0-9]*,_spl5/mfpr $18,r0\ mtpr $0x15,$18/ s/calls $0,_spl6/mfpr $18,r0\ mtpr $0x18,$18/ s/calls r[0-9]*,_spl6/mfpr $18,r0\ mtpr $0x18,$18/ s/calls $0,_spl7/mfpr $18,r0\ mtpr $0x1f,$18/ s/calls $1,_splx/mfpr $18,r0\ mtpr (sp)+,$18/ s/calls $1,_mfpr/mfpr (sp)+,r0/ s/calls $2,_mtpr/mtpr 4(sp),(sp)\ addl2 $8,sp/ s/calls $1,_resume/ashl $9,(sp)+,r0 \ movpsl -(sp) \ jsb _Resume/ s/calls $3,_bcmp/cmpc3 8(sp),*(sp),*4(sp)\ addl2 $12,sp/ s/calls $3,_bcopy/movc3 8(sp),*(sp),*4(sp)\ addl2 $12,sp/ s/calls $2,_bzero/movc5 $0,(r0),$0,4(sp),*(sp)\ addl2 $8,sp/ s/calls $3,_copyin/jsb _Copyin\ addl2 $12,sp/ s/calls $3,_copyout/jsb _Copyout\ addl2 $12,sp/ s/calls $1,_fubyte/movl (sp)+,r0 \ jsb _Fubyte/ s/calls $1,_fuibyte/movl (sp)+,r0 \ jsb _Fubyte/ s/calls $1,_fuword/movl (sp)+,r0 \ jsb _Fuword/ s/calls $1,_fuiword/movl (sp)+,r0 \ jsb _Fuword/ s/calls $2,_subyte/movl (sp)+,r0 \ movl (sp)+,r1 \ jsb _Subyte/ s/calls $2,_suibyte/movl (sp)+,r0 \ movl (sp)+,r1 \ jsb _Subyte/ s/calls $2,_suword/movl (sp)+,r0 \ movl (sp)+,r1 \ jsb _Suword/ s/calls $2,_suiword/movl (sp)+,r0 \ movl (sp)+,r1 \ jsb _Suword/ s/calls $1,_setrq/movl (sp)+,r0 \ jsb _Setrq/ s/calls $1,_remrq/movl (sp)+,r0 \ jsb _Remrq/ s/calls $0,_swtch/movpsl -(sp)\ jsb _Swtch/ s/calls $1,_ffs/ffs $0,$32,(sp)+,r0 \ bneq 1f \ mnegl $1,r0 \ 1: \ incl r0/ s/calls $1,_htons/rotl $8,(sp),r0\ movb 1(sp),r0\ movzwl r0,r0\ addl2 $4,sp/ s/calls $1,_ntohs/rotl $8,(sp),r0\ movb 1(sp),r0\ movzwl r0,r0\ addl2 $4,sp/ s/calls $1,_htonl/rotl $-8,(sp),r0\ insv r0,$16,$8,r0\ movb 3(sp),r0\ addl2 $4,sp/ s/calls $1,_ntohl/rotl $-8,(sp),r0\ insv r0,$16,$8,r0\ movb 3(sp),r0\ addl2 $4,sp/ s/calls $2,__insque/insque *(sp)+,*(sp)+/ s/calls $1,__remque/remque *(sp)+,r0/ s/calls $2,__queue/movl (sp)+,r0\ movl (sp)+,r1\ insque r1,*4(r0)/ s/calls $1,__dequeue/movl (sp)+,r0\ remque *(r0),r0/ GS} DESTDIR=${DESTDIR} install cd lib; make ${MFLAGS} clean @echo @echo re-compiling libc.a cd lib/libc; make ${MFLAGS} ${LIBCDEFS} @echo re-installing /lib/libc.a cd lib/libc; make ${MFLAGS} DESTDIR=${DESTDIR} install @echo @echo re-compiling C compiler cd lib; make ${MFLAGS} ccom cpp c2 @echo re-installing C compiler cd lib/cbin/ 755 0 12 0 6024734457 4526 bin/adb/ 755 0 12 0 6024535733 5250 bin/adb/Makefile 644 0 12 1634 5515444322 6776 DESTDIR= CFLAGS= -O -DNUM_SYMS_CACHE=50 LDFLAGS= SEPFLAG= -i CFILES= access.c command.c expr.c findfn.c format.c input.c main.c message.c \ opset.c output.c pcs.c print.c runpcs.c setup.c sym.c OFILES= access.o command.o expr.o findfn.o format.o input.o main.o message.o \ opset.o output.o pcs.o print.o runpcs.o setup.o sym.o adb: ${OFILES} ${CC} ${SEPFLAG} ${LDFLAGS} -o adb ${OFILES} install: adb install -s adb ${DESTDIR}/bin clean: -rm -f adb ${OFILES} print: @ls -l | pr @pr -f Makefile *.h ${CFILES} lint: lint -haxc -I. ${CFILES} access.o: defs.h access.c command.o: defs.h command.c expr.o: defs.h expr.c findfn.o: defs.h findfn.c format.o: defs.h format.c input.o: defs.h input.c main.o: defs.h main.c message.o: defs.h message.c opset.o: defs.h opset.c output.o: defs.h output.c pcs.o: defs.h pcs.c print.o: defs.h print.c runpcs.o: defs.h runpcs.c setup.o: defs.h setup.c sym.o: defs.h sym.c n/jsb _Copyin\ addl2 $12,sp/ s/calls $3,_copyout/jsb _Copyout\ addl2 $12,sp/ s/calls $1,_fubyte/mobin/adb/READ_ME 644 0 12 6460 5510642612 6354 The makefile can be adjusted to make a version of adb for nonseparate I/D machines. Change the -DNUM_VM_PAGES value to something like 6 to 8, this will use less real memory (and cause adb to run a bit slower) and allow adb to run on a non-split I/D machine. Changes for overlaid processes are intended to work in the most obvious way and are: 1. There is an additional map for an overlay (430 or 431) object file, described by the triple (bo,eo,fo). bo is initialized on startup, and the others are changed on setting an overlay. This is done automatically if there is an appropriate corefile or when a traced subprocess stops, and can be done manually (described below). 2. There are two additional internal variables set for overlay objects. The variable o is the sum of the overlay sizes. c is the current overlay number. It is set automatically as described above, and can be changed manually (#>c). This changes the overlay map (eo and fo) to map in the named overlay. This affects only adb's mapping. 3. Although the variable c controls the overlay map, the "register" variable "ov" reflects the overlay actually mapped when the process stopped (or dumped core). This value is shown as "ov" in the register list ($r). It may also be used as other register variables, in the "<" and ">" commands. In the latter case, this actually causes the kernel to remap the subprocess, and the correct overlay must be mapped to restart the process. NOTE: the kernel routine procxmt must support overlay changes for this to work. The (1982) 2bsd distribution includes the necessary changes. 4. For text symbols in overlaid objects, the default symbol used to find "name" is "~name" rather than "_name". This means that the actual subroutine, rather than its thunk, is found. To examine a thunk, use "_name" explicitly. 5. In the overlaid segment, only symbols in the current overlay (c) are used in symbolic addresses. In order to find these overlay numbers, the new version of (ov)ld must be used. The reason for this is that the previous version of ovld put the overlay number only in symbols for thunks, not in local text symbols. 6. In order to support breakpoints in overlaid segments, the strategy used by adb has been changed slightly. Breakpoints are written into the subprocess immediately when a ":b" command is executed, and deleted immediately with ":d". Changes to support overlaid kernels: 1. The user's saved registers are in different places in the kernel stack. They are found relative to the entry u.u_ar0 in the core file if there is one, with offsets from and . If there is no core file,a default is used. This default is defined as UAR0 in defs.h. ******* UAR0 should be checked whenever the user structure changes. 2. There is a new command-line flag, -k, which sets things appropriately for the kernel. It sets the mapping of the core file appropriately for 407, 411 and 430 kernels, and changes the debugger's idea of saved register locations. Thus, $r will print the register values saved by dump, and $c will use the saved r5 from low core. In addition, a number of minor bugs have been fixed. Mike Karels ucbvax!virus!mike Department of Molecular Biology University of California, Berkeley e bin/adb/access.c 644 0 12 5444 5511075032 6740 #include "defs.h" MSG ODDADR; MSG BADDAT; MSG BADTXT; MAP txtmap; MAP datmap; int wtflag; char *errflg; int pid; struct ovlhdr ovlseg; long ovloff[]; char curov; int overlay; long var[]; extern int errno; static within(); /* file handling and access routines */ put(adr,space,value) long adr; { acces(WT,adr,space,value); } u_int get(adr, space) long adr; { return(acces(RD,adr,space,0)); } u_int chkget(n, space) long n; { register int w; w = get(n, space); chkerr(); return(w); } acces(mode,adr,space,value) long adr; { int w, w1, pmode, rd, file; BKPTR bkptr, scanbkpt(); rd = mode==RD; IF space == NSP THEN return(0); FI IF pid /* tracing on? */ THEN IF (adr&01) ANDF !rd THEN error(ODDADR); FI pmode = (space&DSP?(rd?RDUSER:WDUSER):(rd?RIUSER:WIUSER)); if (bkptr=scanbkpt((u_int)adr)) { if (rd) { return(bkptr->ins); } else { bkptr->ins = value; return(0); } } w = ptrace(pmode, pid, shorten(adr&~01), value); IF adr&01 THEN w1 = ptrace(pmode, pid, shorten(adr+1), value); w = (w>>8)&LOBYTE | (w1<<8); FI IF errno THEN errflg = (space&DSP ? BADDAT : BADTXT); FI return(w); FI w = 0; IF mode==WT ANDF wtflag==0 THEN error("not in write mode"); FI IF !chkmap(&adr,space) THEN return(0); FI file = (space&DSP ? datmap.ufd : txtmap.ufd); if (lseek(file,adr, 0) == -1L || (rd ? read(file,&w,2) : write(file,&value,2)) < 1) errflg = (space & DSP ? BADDAT : BADTXT); return(w); } chkmap(adr,space) register long *adr; register int space; { register MAPPTR amap; amap=((space&DSP?&datmap:&txtmap)); switch(space&(ISP|DSP|STAR)) { case ISP: IF within(*adr, amap->b1, amap->e1) THEN *adr += (amap->f1) - (amap->b1); break; ELIF within(*adr, amap->bo, amap->eo) THEN *adr += (amap->fo) - (amap->bo); break; FI /* falls through */ case ISP+STAR: IF within(*adr, amap->b2, amap->e2) THEN *adr += (amap->f2) - (amap->b2); break; ELSE goto err; FI case DSP: IF within(*adr, amap->b1, amap->e1) THEN *adr += (amap->f1) - (amap->b1); break; FI /* falls through */ case DSP+STAR: IF within(*adr, amap->b2, amap->e2) THEN *adr += (amap->f2) - (amap->b2); break; FI /* falls through */ default: err: errflg = (space&DSP ? BADDAT: BADTXT); return(0); } return(1); } setovmap(ovno) char ovno; { register MAPPTR amap; if ((!overlay) || (ovno < 0) || (ovno > NOVL)) return; amap = &txtmap; IF ovno == 0 THEN amap->eo = amap->bo; amap->fo = 0; ELSE amap->eo = amap->bo + ovlseg.ov_siz[ovno-1]; amap->fo = ovloff[ovno-1]; FI var[VARC] = curov = ovno; if (pid) choverlay(ovno); } static within(adr,lbd,ubd) long adr, lbd, ubd; { return(adr>=lbd && adrb2); ELSE mp = &(smap->b1); FI WHILE fcount-- ANDF expr(0) DO *(mp)++ = expv; OD IF rdc()=='?' THEN smap->ufd=fsym; ELIF lastc == '/' THEN smap->ufd=fcor; ELSE lp--; FI } break; case 'L': longpr=TRUE; case 'l': /*search for exp*/ IF eqcom THEN error(BADEQ); FI dotinc=2; savdot=dot; expr(1); locval=expv; IF expr(0) THEN locmsk=expv; ELSE locmsk = -1L; FI LOOP w=leng(get(dot,itype)); IF longpr THEN w=itol(w,get(inkdot(2),itype)); FI IF errflg ORF mkfault ORF (w&locmsk)==locval THEN break; FI dot=inkdot(dotinc); POOL IF errflg THEN dot=savdot; errflg=NOMATCH; FI psymoff(dot,ptype,""); break; case 'W': longpr=TRUE; case 'w': IF eqcom THEN error(BADEQ); FI wformat[0]=lastc; expr(1); REP savdot=dot; psymoff(dot,ptype,":%16t"); exform(1,wformat,itype,ptype); errflg=0; dot=savdot; IF longpr THEN put(dot,itype,expv); FI put((longpr?inkdot(2):dot),itype,shorten(expv)); savdot=dot; printf("=%8t"); exform(1,wformat,itype,ptype); printc(EOR); PER expr(0) ANDF errflg==0 DONE dot=savdot; chkerr(); break; default: lp--; getformat(eqcom ? eqformat : stformat); IF !eqcom THEN IF symov ANDF symov!=curov ANDF ptype == ISYM ANDF dot>=txtmap.bo THEN setovmap(symov); var[VARC]=symov; FI IF *stformat!='a' THEN psymoff(dot,ptype,":%16t"); FI FI scanform(cntval,(eqcom?eqformat:stformat),itype,ptype); } break; case '>': lastcom=0; savc=rdc(); IF (regptr=getreg(savc)) != NOREG THEN uar0[regptr]=shorten(dot); ptrace(WUREGS,pid,(int)&uar0[regptr]-(int)&corhdr, uar0[regptr]); IF (uar0+regptr) == &(((U*)corhdr)->u_ovdata.uo_curov) THEN var[VARC]=dot; setovmap((char)dot); FI ELIF (modifier=varchk(savc)) != -1 THEN var[modifier]=dot; IF modifier == VARC THEN setovmap((char)dot); FI ELSE error(BADVAR); FI break; case '!': lastcom=0; unox(); break; case '$': lastcom=0; printtrace(nextchar()); break; case ':': IF !executing THEN executing=TRUE; subpcs(nextchar()); executing=FALSE; lastcom=0; FI break; case 0: printf("%s\n", myname); break; default: error(BADCOM); } flushbuf(); PER rdc()==';' DONE IF buf THEN lp=savlp; ELSE lp--; FI return(adrflg ANDF dot!=0); } bin/adb/defs.h 644 0 12 10556 5515417562 6461 /* * * UNIX debugger - common definitions * * Layout of a.out file (fsym): * * This has changed over time - see a.out.h, sys/exec.h and nlist.h * for the current a.out definition and format. */ #include #include #include #include #include #include #define MAXSYMLEN 32 #define MAXCOM 64 #define MAXARG 32 #define LINSIZ 512 #define BEGIN { #define END } #define IF if( #define THEN ){ #define ELSE } else { #define ELIF } else if ( #define FI } #define FOR for( #define WHILE while( #define DO ){ #define OD } #define REP do{ #define PER }while( #define DONE ); #define LOOP for(;;){ #define POOL } #define ANDF && #define ORF || #define LPRMODE "%Q" #define OFFMODE "+%o" /* * This is the memory resident portion of a symbol. The only difference * between this and a 'nlist' entry is the size of the string offset By * restricting the string table to be less than 64kb we save 2 bytes per * symbol - approximately 7.5kb of D space in the case of /unix's symbol * table. In practice this restriction is unlikely to be reached since * even the kernel's symbol table of ~28kb only has a strings table of 21kb. */ struct SYMbol { u_short value; char type; char ovno; u_short soff; /* low order of string table offset */ }; #define SYMTYPE(symflag) (( symflag>=041 || (symflag>=02 && symflag<=04))\ ? ((symflag&07)>=3 ? DSYM : (symflag&07))\ : NSYM) typedef char MSG[]; typedef struct map MAP; typedef MAP *MAPPTR; typedef struct bkpt BKPT; typedef BKPT *BKPTR; typedef struct user U; /* file address maps */ struct map { long b1; long e1; long f1; long bo; long eo; long fo; long b2; long e2; long f2; int ufd; }; struct bkpt { int loc; int ins; int count; int initcnt; char flag; char ovly; char comm[MAXCOM]; BKPT *nxtbkpt; }; typedef struct reglist REGLIST; typedef REGLIST *REGPTR; struct reglist { char *rname; int roffs; }; struct Sfp { int fpsr; float Sfr[6]; }; struct Lfp { int fpsr; double Lfr[6]; }; /* * Internal variables --- * They are addressed by name. (e.g. (`0'-`9', `a'-`b')) * thus there can only be 36 of them. */ #define VARB 11 #define VARC 12 /* current overlay number */ #define VARD 13 #define VARE 14 #define VARM 22 #define VARO 24 /* overlay text segment addition */ #define VARS 28 #define VART 29 #define RD 0 #define WT 1 #define NSP 0 #define ISP 1 #define DSP 2 #define STAR 4 #define DSYM 7 #define ISYM 2 #define ASYM 1 #define NSYM 0 #define ESYM 0177 #define BKPTSET 1 #define BKPTEXEC 2 #define BPT 03 #define FD 0200 #define SETTRC 0 #define RDUSER 2 #define RIUSER 1 #define WDUSER 5 #define WIUSER 4 #define RUREGS 3 #define WUREGS 6 #define CONTIN 7 #define SINGLE 9 #define EXIT 8 #define FROFF ((int)&(((U*)0)->u_fps)) #define FRLEN 25 #define FRMAX 6 #define NOREG 32767 /* impossible return from getreg() */ #define NREG 9 /* 8 regs + PS from kernel stack */ /* * UAR0 is the value used for subprocesses when there is no core file. * If it doesn't correspond to reality, use pstat -u on a core file to * get uar0, subtract 0140000, and divide by 2 (sizeof int). */ #define UAR0 (&corhdr[ctob(USIZE)/sizeof(u_int) - 3]) /* default address of r0 (u.u_ar0) */ #define KR0 (0300/2) /* location of r0 in kernel dump */ #define KR1 (KR0+1) #define KR2 (KR0+2) #define KR3 (KR0+3) #define KR4 (KR0+4) #define KR5 (KR0+5) #define KSP (KR0+6) #define KA6 (KR0+7) /* saved ka6 in kernel dump */ #define MAXOFF 255 #define MAXPOS 80 #define MAXLIN 128 #define TRUE (-1) #define FALSE 0 #define LOBYTE 0377 #define HIBYTE 0177400 #define STRIP 0177 #define SP ' ' #define TB '\t' #define EOR '\n' #define QUOTE 0200 #define EVEN (~1) /* long to ints and back (puns) */ union { int I[2]; long L; } itolws; #define leng(a) ((long)((unsigned)(a))) #define shorten(a) ((int)(a)) #define itol(a,b) (itolws.I[0]=(a), itolws.I[1]=(b), itolws.L) /* result type declarations */ long inkdot(); struct SYMbol *lookupsym(); struct SYMbol *symget(); u_int get(), chkget(); char *exform(); char *cache_sym(), *no_cache_sym(); long round(); BKPTR scanbkpt(); struct sgttyb adbtty, usrtty; jmp_buf erradb; extern off_t lseek(); bin/adb/expr.c 644 0 12 13201 5515441317 6472 #include "defs.h" #include MSG BADSYM; MSG BADVAR; MSG BADKET; MSG BADSYN; MSG NOCFN; MSG NOADR; MSG BADLOC; extern struct SYMbol *symbol, *cache_by_string(); int lastframe; int kernel; int savlastf; long savframe; char svlastov; int savpc; int callpc; char *lp; int octal; char *errflg; long localval; static char isymbol[MAXSYMLEN + 2]; char lastc; u_int *uar0; u_int corhdr[]; char curov, startov, lastsymov; int overlay; long dot; long ditto; int dotinc; long var[]; long expv; expr(a) { /* term | term dyadic expr | */ int rc; long lhs; lastsymov = 0; rdc(); lp--; rc=term(a); WHILE rc DO lhs = expv; switch (readchar()) { case '+': term(a|1); expv += lhs; break; case '-': term(a|1); expv = lhs - expv; break; case '#': term(a|1); expv = round(lhs,expv); break; case '*': term(a|1); expv *= lhs; break; case '%': term(a|1); expv = lhs/expv; break; case '&': term(a|1); expv &= lhs; break; case '|': term(a|1); expv |= lhs; break; case ')': IF (a&2)==0 THEN error(BADKET); FI default: lp--; return(rc); } OD return(rc); } term(a) { /* item | monadic item | (expr) | */ switch (readchar()) { case '*': term(a|1); expv=chkget(expv,DSP); return(1); case '@': term(a|1); expv=chkget(expv,ISP); return(1); case '-': term(a|1); expv = -expv; return(1); case '~': term(a|1); expv = ~expv; return(1); case '(': expr(2); IF *lp!=')' THEN error(BADSYN); ELSE lp++; return(1); FI default: lp--; return(item(a)); } } item(a) { /* name [ . local ] | number | . | ^ | value; lastsymov=symp->ovno; FI lp--; ELIF isdigit(lastc) ORF (hex=TRUE, lastc=='#' ANDF isxdigit(readchar())) THEN expv = 0; base = (lastc == '0' ORF octal ? 8 : (hex ? 16 : 10)); WHILE (hex ? isxdigit(lastc) : isdigit(lastc)) DO expv *= base; IF (d=convdig(lastc))>=base THEN error(BADSYN); FI expv += d; readchar(); IF expv==0 ANDF (lastc=='x' ORF lastc=='X') THEN hex=TRUE; base=16; readchar(); FI OD IF lastc=='.' ANDF (base==10 ORF expv==0) ANDF !hex THEN real.r=expv; frpt=0; base=10; WHILE isdigit(readchar()) DO real.r *= base; frpt++; real.r += lastc-'0'; OD WHILE frpt-- DO real.r /= base; OD expv = real.i; FI lp--; ELIF lastc=='.' THEN readchar(); IF symchar(0) THEN savov = curov; curov = svlastov; lastframe=savlastf; callpc=savpc; findroutine(savframe); chkloc(savframe); if(overlay) setovmap(savov); ELSE expv=dot; FI lp--; ELIF lastc=='"' THEN expv=ditto; ELIF lastc=='+' THEN expv=inkdot(dotinc); ELIF lastc=='^' THEN expv=inkdot(-dotinc); ELIF lastc=='<' THEN savc=rdc(); IF (regptr=getreg(savc)) != NOREG THEN expv=uar0[regptr]; ELIF (base=varchk(savc)) != -1 THEN expv=var[base]; ELSE error(BADVAR); FI ELIF lastc=='\'' THEN d=4; expv=0; WHILE quotchar() DO IF d-- THEN IF d==1 THEN expv <<=16; FI expv |= ((d&1)?lastc:lastc<<8); ELSE error(BADSYN); FI OD ELIF a THEN error(NOADR); ELSE lp--; return(0); FI return(1); } /* service routines for expression reading */ readsym() { register char *p; p = isymbol; REP IF p < &isymbol[MAXSYMLEN] THEN *p++ = lastc; FI readchar(); PER symchar(1) DONE *p++ = 0; } struct SYMbol * lookupsym(symstr) char *symstr; { register struct SYMbol *symp, *sc; symset(); while (symp = symget()) { if (overlay && (symp->type == ISYM)) { if (sc = cache_by_string(symstr, 1)) return(sc); if (eqsym(no_cache_sym(symp), symstr,'~')) break; } else { if (sc = cache_by_string(symstr, 0)) return(sc); if (eqsym(no_cache_sym(symp), symstr,'_')) break; } } /* * We did not enter anything into the cache (no sense inserting hundreds * of symbols which didn't match) while examining the (entire) symbol table. * Now that we have a match put it into the cache (doing a lookup on it is * the easiest way). */ if (symp) (void)cache_sym(symp); return(symp); } convdig(c) char c; { IF isdigit(c) THEN return(c-'0'); ELIF isxdigit(c) THEN return(c-'a'+10); ELSE return(17); FI } symchar(dig) { IF lastc=='\\' THEN readchar(); return(TRUE); FI return( isalpha(lastc) ORF lastc=='_' ORF dig ANDF isdigit(lastc) ); } varchk(name) { IF isdigit(name) THEN return(name-'0'); FI IF isalpha(name) THEN return((name&037)-1+10); FI return(-1); } chkloc(frame) long frame; { readsym(); REP IF localsym(frame)==0 THEN error(BADLOC); FI expv=localval; PER !eqsym(cache_sym(symbol), isymbol,'~') DONE } eqsym(s1, s2, c) register char *s1, *s2; char c; { if (!strcmp(s1, s2)) return(TRUE); else if (*s1++ == c) return(!strcmp(s1, s2)); return(FALSE); } bin/adb/findfn.c 644 0 12 2621 5515142577 6752 #include "defs.h" MSG NOCFN; int callpc; char localok; extern struct SYMbol *symbol; char *errflg; char curov; int overlay; long var[36]; findroutine(cframe) long cframe; { register int narg, inst; int lastpc, back2; char v; char savov, curovl; v=FALSE; localok=FALSE; lastpc=callpc; if(overlay) { /* * Save the previous overlay. Don't restore it, * so that the next call will have the correct previous * overlay. The caller must save and restor the original * overlay if needed. */ savov = curov; curovl=get(cframe-2, DSP); setovmap(curovl); } callpc=get(cframe+2, DSP); back2=get(leng(callpc-2), ISP); IF (inst=get(leng(callpc-4), ISP)) == 04737 /* jsr pc,*$... */ THEN narg = 1; ELIF (inst&~077)==04700 /* jsr pc,... */ THEN narg=0; v=(inst!=04767); ELIF (back2&~077)==04700 THEN narg=0; v=TRUE; ELSE errflg=NOCFN; return(0); FI if (overlay) setovmap(savov); /* previous overlay, for findsym */ if (findsym((v ? lastpc : ((inst==04767?callpc:0) + back2)),ISYM) == -1 && !v) symbol = NULL; else localok=TRUE; if (overlay) setovmap(curovl); inst = get(leng(callpc), ISP); IF inst == 062706 /* add $n,sp */ THEN narg += get(leng(callpc+2), ISP)/2; return(narg); FI if (inst == 05726 || inst == 010026) /* tst (sp)+ or mov r0,(sp)+ */ return(narg+1); IF inst == 022626 /* cmp (sp)+,(sp)+ */ THEN return(narg+2); FI return(narg); } lastc=='.' THEN frame=(kernel?corhdr[KR5]:uar0[R5])&EVEN; lastframe=0; callpc=kernel?(-2):uar0[PC]; if bin/adb/format.c 644 0 12 11117 5515142744 7012 #include "defs.h" #include MSG BADMOD; MSG NOFORK; MSG ADWRAP; extern struct SYMbol *symbol; int mkfault; char *lp; char *printptr, printbuf[]; int maxoff; int sigint; int sigqit; char *errflg; char lastc; long dot; int dotinc; long var[]; scanform(icount,ifp,itype,ptype) long icount; char *ifp; { char *fp; char modifier; int fcount, init=1; long savdot; WHILE icount DO fp=ifp; IF init==0 ANDF findsym(shorten(dot),ptype)==0 ANDF maxoff THEN printf("\n%s:%16t", cache_sym(symbol)); FI savdot=dot; init=0; /*now loop over format*/ WHILE *fp ANDF errflg==0 DO IF isdigit(modifier = *fp) THEN fcount=0; WHILE isdigit(modifier = *fp++) DO fcount *= 10; fcount += modifier-'0'; OD fp--; ELSE fcount=1; FI IF *fp==0 THEN break; FI fp=exform(fcount,fp,itype,ptype); OD dotinc=dot-savdot; dot=savdot; IF errflg THEN IF icount<0 THEN errflg=0; break; ELSE error(errflg); FI FI IF --icount THEN dot=inkdot(dotinc); FI IF mkfault THEN error((char *)0); FI OD } char * exform(fcount,ifp,itype,ptype) int fcount; char *ifp; int itype, ptype; { /* execute single format item `fcount' times * sets `dotinc' and moves `dot' * returns address of next format item */ u_int w; long savdot, wx; char *fp; char c, modifier, longpr; struct { long sa; int sb,sc; } fw; WHILE fcount>0 DO fp = ifp; c = *fp; longpr=(c>='A')&(c<='Z')|(c=='f'); IF itype==NSP ORF *fp=='a' THEN wx=dot; w=dot; ELSE w=get(dot,itype); IF longpr THEN wx=itol(w,get(inkdot(2),itype)); ELSE wx=w; FI FI IF c=='F' THEN fw.sb=get(inkdot(4),itype); fw.sc=get(inkdot(6),itype); FI IF errflg THEN return(fp); FI IF mkfault THEN error((char *)0); FI var[0]=wx; modifier = *fp++; dotinc=(longpr?4:2);; if (!(printptr - printbuf) && modifier != 'a') printf("%16m"); switch(modifier) { case SP: case TB: break; case 't': case 'T': printf("%T",fcount); return(fp); case 'r': case 'R': printf("%M",fcount); return(fp); case 'a': psymoff(dot,ptype,":%16t"); dotinc=0; break; case 'p': psymoff(var[0],ptype,"%16t"); break; case 'u': printf("%-8u",w); break; case 'U': printf("%-16U",wx); break; case 'c': case 'C': IF modifier=='C' THEN printesc(w&LOBYTE); ELSE printc(w&LOBYTE); FI dotinc=1; break; case 'b': case 'B': printf("%-8o", w&LOBYTE); dotinc=1; break; case 's': case 'S': savdot=dot; dotinc=1; WHILE (c=get(dot,itype)&LOBYTE) ANDF errflg==0 DO dot=inkdot(1); IF modifier == 'S' THEN printesc(c); ELSE printc(c); FI endline(); OD dotinc=dot-savdot+1; dot=savdot; break; case 'x': printf("%-8x",w); break; case 'X': printf("%-16X", wx); break; case 'Y': printf("%-24Y", wx); break; case 'q': printf("%-8q", w); break; case 'Q': printf("%-16Q", wx); break; case 'o': case 'w': printf("%-8o", w); break; case 'O': case 'W': printf("%-16O", wx); break; case 'i': printins(itype,w); printc(EOR); break; case 'd': printf("%-8d", w); break; case 'D': printf("%-16D", wx); break; case 'f': *(double *)&fw = 0.0; fw.sa = wx; printf("%-16.9f", *(double *)&fw); dotinc=4; break; case 'F': fw.sa = wx; printf("%-32.18F", *(double *)&fw); dotinc=8; break; case 'n': case 'N': printc('\n'); dotinc=0; break; case '"': dotinc=0; WHILE *fp != '"' ANDF *fp DO printc(*fp++); OD IF *fp THEN fp++; FI break; case '^': dot=inkdot(-dotinc*fcount); return(fp); case '+': dot=inkdot(fcount); return(fp); case '-': dot=inkdot(-fcount); return(fp); default: error(BADMOD); } IF itype!=NSP THEN dot=inkdot(dotinc); FI fcount--; endline(); OD return(fp); } unox() { int rc, status, unixpid; char *argp = lp; WHILE lastc!=EOR DO rdc(); OD IF (unixpid=fork())==0 THEN signal(SIGINT,sigint); signal(SIGQUIT,sigqit); *lp=0; execl("/bin/sh", "sh", "-c", argp, 0); exit(16); ELIF unixpid == -1 THEN error(NOFORK); ELSE signal(SIGINT,SIG_IGN); WHILE (rc = wait(&status)) != unixpid ANDF rc != -1 DONE signal(SIGINT,sigint); printc('!'); lp--; FI } printesc(c) { c &= STRIP; IF c'~' ORF c=='@' THEN printf("@%c",(c=='@' ? '@' : c^0140)); ELSE printc(c); FI } long inkdot(incr) { long newdot; newdot=dot+incr; IF (dot ^ newdot) >> 24 THEN error(ADWRAP); FI return(newdot); } digit(readchar()) DO real.r *= base; frpt++; real.r += lastc-'0'; OD WHILE frpt-- DO real.r /= base; OD expv = real.i; FI lp--; ELIF lastc=='.' THEN readchar(); IF symchar(0) THEN savov = curov; curov = svlastov; lastframe=savlastf; callpc=savpc; findroutine(savframe); chkloc(savframe); if(overlay) setovmap(savov); ELSE expv=dot; FI lp--; ELIF lastc=='"' THEN expv=ditto; ELbin/adb/input.c 644 0 12 1756 5511075243 6644 #include "defs.h" int mkfault; char line[LINSIZ]; int infile; char *lp; char lastc = EOR; int eof; /* input routines */ eol(c) char c; { return(c==EOR || c==';'); } rdc() { REP readchar(); PER lastc==SP ORF lastc==TB DONE return(lastc); } readchar() { IF eof THEN lastc = '\0'; ELSE IF lp==0 THEN lp=line; REP eof = read(infile,lp,1)==0; IF mkfault THEN error((char *)0); FI PER eof==0 ANDF *lp++!=EOR DONE *lp=0; lp=line; FI IF lastc = *lp THEN lp++; FI FI return(lastc); } nextchar() { IF eol(rdc()) THEN lp--; return(0); ELSE return(lastc); FI } quotchar() { IF readchar()=='\\' THEN return(readchar()); ELIF lastc=='\'' THEN return(0); ELSE return(lastc); FI } getformat(deformat) char *deformat; { register char *fptr; register int quote; fptr=deformat; quote=FALSE; WHILE (quote ? readchar()!=EOR : !eol(readchar())) DO IF (*fptr++ = lastc)=='"' THEN quote = ~quote; FI OD lp--; IF fptr!=deformat THEN *fptr++ = '\0'; FI } intf("%-16Q", wx);bin/adb/main.c 644 0 12 5025 5515171261 6423 #include "defs.h" MSG NOEOR; char *myname; /* program name */ int argcount; int mkfault; int executing; int infile; char *lp; int maxoff; int maxpos; int (*sigint)(); int (*sigqit)(); int wtflag; int kernel; long maxfile; long maxstor; long txtsiz; long datsiz; long datbas; long stksiz; long ovlsiz; int overlay; char *errflg; int exitflg; int magic; long entrypt; char lastc; int eof; int lastcom; long var[36]; char *symfil; char *corfil; char *printptr; char *Ipath = "/usr/lib/adb"; long round(a,b) long a, b; { long w; w = ((a+b-1)/b)*b; return(w); } /* error handling */ chkerr() { IF errflg ORF mkfault THEN error(errflg); FI } error(n) char *n; { errflg=n; iclose(0, 1); oclose(); longjmp(erradb,1); } fault(a) { signal(a,fault); lseek(infile,0L,2); mkfault++; } /* set up files and initial address mappings */ main(argc, argv) register char **argv; int argc; { short mynamelen; /* length of program name */ maxfile = 1L << 24; maxstor = 1L << 16; if (isatty(0)) myname = *argv; else myname = "adb"; mynamelen = strlen(myname); gtty(0,&adbtty); gtty(0,&usrtty); WHILE argc>1 DO IF !strcmp("-w",argv[1]) THEN wtflag=2; argc--; argv++; continue; ELIF !strcmp("-k",argv[1]) THEN kernel++; argc--; argv++; continue; ELIF !strcmp("-I",argv[1]) THEN Ipath = argv[2]; argc -= 2; argv += 2; continue; ELSE break; FI OD IF argc>1 THEN symfil = argv[1]; FI IF argc>2 THEN corfil = argv[2]; FI argcount=argc; setsym(); setcor(); /* set up variables for user */ maxoff=MAXOFF; maxpos=MAXPOS; var[VARB] = datbas; var[VARD] = datsiz; var[VARE] = entrypt; var[VARM] = magic; var[VARS] = stksiz; var[VART] = txtsiz; /* if text overlay, enter total overlay area size */ IF overlay THEN var[VARO] = ovlsiz; FI IF (sigint=signal(SIGINT,SIG_IGN))!=SIG_IGN THEN sigint=fault; signal(SIGINT,fault); FI sigqit=signal(SIGQUIT,SIG_IGN); siginterrupt(SIGINT, 1); siginterrupt(SIGQUIT, 1); setjmp(erradb); IF executing THEN delbp(); FI executing=FALSE; LOOP flushbuf(); IF errflg THEN printf("%s\n",errflg); exitflg=(int)errflg; errflg=0; FI IF mkfault THEN mkfault=0; printc(EOR); printf("%s\n", myname); FI IF myname ANDF !infile THEN write(1,myname,mynamelen); write(1,"> ",2); FI lp=0; rdc(); lp--; IF eof THEN IF infile THEN iclose(-1, 0); eof=0; longjmp(erradb,1); ELSE done(); FI ELSE exitflg=0; FI command(0,lastcom); IF lp ANDF lastc!=EOR THEN error(NOEOR); FI POOL } done() { endpcs(); exit(exitflg); } ^ newdot) >> 24 THEN error(ADWRAP); FI return(newdot); } digit(readchar()) DO real.r *= base; frpt++; real.r += lastc-'0'; OD WHILE frpt-- DO real.r /= base; OD expv = real.i; FI lp--; ELIF lastc=='.' THEN readchar(); IF symchar(0) THEN savov = curov; curov = svlastov; lastframe=savlastf; callpc=savpc; findroutine(savframe); chkloc(savframe); if(overlay) setovmap(savov); ELSE expv=dot; FI lp--; ELIF lastc=='"' THEN expv=ditto; ELbin/adb/message.c 644 0 12 1767 5510733457 7142 #include "defs.h" MSG BADMOD = "bad modifier"; MSG BADCOM = "bad command"; MSG BADSYM = "symbol not found"; MSG BADLOC = "automatic variable not found"; MSG NOCFN = "c routine not found"; MSG NOMATCH = "cannot locate value"; MSG NOBKPT = "no breakpoint set"; MSG BADKET = "unexpected ')'"; MSG NOADR = "address expected"; MSG NOPCS = "no process"; MSG BADVAR = "bad variable"; MSG BADTXT = "text address not found"; MSG BADDAT = "data address not found"; MSG ODDADR = "odd address"; MSG EXBKPT = "too many breakpoints"; MSG A68BAD = "bad a68 frame"; MSG A68LNK = "bad a68 link"; MSG ADWRAP = "address wrap around"; MSG BADEQ = "unexpected `='"; MSG BADWAIT = "wait error: process disappeared!"; MSG ENDPCS = "process terminated"; MSG NOFORK = "try again"; MSG BADSYN = "syntax error"; MSG NOEOR = "newline expected"; MSG SZBKPT = "bkpt: command too long"; MSG LONGFIL = "filename too long"; MSG NOTOPEN = "cannot open"; MSG TOODEEP = "$<< nesting too deep"; 16; if bin/adb/opset.c 644 0 12 21402 5753603067 6656 #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)opset.c 2.2 (2.11BSD GTE) 1995/05/08"; #endif #include "defs.h" char *errflg; long dot; int dotinc; long var[]; MAP datmap; #undef SINGLE /* instruction printing */ #define DOUBLE 0 #define DOUBLW 1 #define SINGLE 2 #define SINGLW 3 #define REVERS 4 #define BRANCH 5 #define NOADDR 6 #define DFAULT 7 #define TRAP 8 #define SYS 9 #define SOB 10 #define JMP 11 #define JSR 12 struct optab { int mask; int val; int itype; char *iname; } optab[] = { 0107777, 0010000, DOUBLE, "mov", 0107777, 0020000, DOUBLE, "cmp", 0107777, 0030000, DOUBLE, "bit", 0107777, 0040000, DOUBLE, "bic", 0107777, 0050000, DOUBLE, "bis", 0007777, 0060000, DOUBLW, "add", 0007777, 0160000, DOUBLW, "sub", 0100077, 0005000, SINGLE, "clr", 0100077, 0005100, SINGLE, "com", 0100077, 0005200, SINGLE, "inc", 0100077, 0005300, SINGLE, "dec", 0100077, 0005400, SINGLE, "neg", 0100077, 0005500, SINGLE, "adc", 0100077, 0005600, SINGLE, "sbc", 0100077, 0005700, SINGLE, "tst", 0100077, 0006000, SINGLE, "ror", 0100077, 0006100, SINGLE, "rol", 0100077, 0006200, SINGLE, "asr", 0100077, 0006300, SINGLE, "asl", 0000077, 0000100, JMP, "jmp", 0000077, 0000300, SINGLE, "swab", 0000077, 0170100, SINGLW, "ldfps", 0000077, 0170200, SINGLW, "stfps", 0000077, 0170300, SINGLW, "stst", 0000077, 0170400, SINGLW, "clrf", 0000077, 0170500, SINGLW, "tstf", 0000077, 0170600, SINGLW, "absf", 0000077, 0170700, SINGLW, "negf", 0000077, 0006700, SINGLW, "sxt", 0000077, 0006600, SINGLW, "mtpi", 0000077, 0106600, SINGLW, "mtpd", 0000077, 0006500, SINGLW, "mfpi", 0000077, 0106500, SINGLW, "mfpd", 0000077, 0106700, SINGLW, "mfps", 0000077, 0106400, SINGLW, "mtps", 0000777, 0070000, REVERS, "mul", 0000777, 0071000, REVERS, "div", 0000777, 0072000, REVERS, "ash", 0000777, 0073000, REVERS, "ashc", LOBYTE, 0000400, BRANCH, "br", LOBYTE, 0001000, BRANCH, "bne", LOBYTE, 0001400, BRANCH, "beq", LOBYTE, 0002000, BRANCH, "bge", LOBYTE, 0002400, BRANCH, "blt", LOBYTE, 0003000, BRANCH, "bgt", LOBYTE, 0003400, BRANCH, "ble", LOBYTE, 0100000, BRANCH, "bpl", LOBYTE, 0100400, BRANCH, "bmi", LOBYTE, 0101000, BRANCH, "bhi", LOBYTE, 0101400, BRANCH, "blos", LOBYTE, 0102000, BRANCH, "bvc", LOBYTE, 0102400, BRANCH, "bvs", LOBYTE, 0103000, BRANCH, "bcc", LOBYTE, 0103400, BRANCH, "bcs", 0000000, 0000000, NOADDR, "halt", 0000000, 0000001, NOADDR, "wait", 0000000, 0000002, NOADDR, "rti", 0000000, 0000003, NOADDR, "bpt", 0000000, 0000004, NOADDR, "iot", 0000000, 0000005, NOADDR, "reset", 0000000, 0000006, NOADDR, "rtt", LOBYTE, 0171000, REVERS, "mulf", LOBYTE, 0171400, REVERS, "modf", LOBYTE, 0172000, REVERS, "addf", LOBYTE, 0172400, REVERS, "movf", LOBYTE, 0173000, REVERS, "subf", LOBYTE, 0173400, REVERS, "cmpf", LOBYTE, 0174000, DOUBLW, "movf", LOBYTE, 0174400, REVERS, "divf", LOBYTE, 0175000, DOUBLW, "movei", LOBYTE, 0175400, DOUBLW, "movfi", LOBYTE, 0176000, DOUBLW, "movfo", LOBYTE, 0176400, REVERS, "movie", LOBYTE, 0177000, REVERS, "movif", LOBYTE, 0177400, REVERS, "movof", 0000000, 0170000, NOADDR, "cfcc", 0000000, 0170001, NOADDR, "setf", 0000000, 0170002, NOADDR, "seti", 0000000, 0170011, NOADDR, "setd", 0000000, 0170012, NOADDR, "setl", 0000000, 0000007, NOADDR, "mfpt", 0000077, 0007000, JMP, "csm", 0000077, 0007300, SINGLW, "wrtlck", 0000077, 0007200, SINGLW, "tstset", 0000777, 0004000, JSR, "jsr", 0000777, 0074000, DOUBLE, "xor", 0000007, 0000200, SINGLE, "rts", 0000017, 0000240, DFAULT, "cflg", 0000017, 0000260, DFAULT, "sflg", LOBYTE, 0104000, TRAP, "emt", LOBYTE, 0104400, SYS, "sys", 0000077, 0006400, TRAP, "mark", 0000777, 0077000, SOB, "sob", 0000007, 0000230, DFAULT, "spl", 0177777, 0000000, DFAULT, "", }; char *systab[] = { "old indir", /* 0 */ "exit", "fork", "read", "write", "open", "close", "wait4", "creat", "link", "unlink", /* 10 */ "execv", "chdir", "fchdir", "mknod", "chmod", "chown", "chflags", "fchflags", "lseek", "getpid", /* 20 */ "mount", "umount", "__sysctl", "getuid", "geteuid", /* 25 */ "ptrace", "getppid", NULL, /* 28 - old fstat */ NULL, /* 29 - old pause */ NULL, /* 30 - old utime */ NULL, /* 31 - old stty */ NULL, /* 32 - old gtty */ "access", NULL, /* 34 - old nice */ NULL, /* 35 - old ftime */ "sync", "kill", "stat", NULL, /* 39 - old setpgrp */ "lstat", "dup", "pipe", NULL, /* 43 - old times */ "profil", NULL, /* 45 - unused */ NULL, /* 46 - old setgid */ "getgid", "getegid", NULL, /* 49 - unused */ NULL, /* 50 - unused */ "acct", "phys", "lock", "ioctl", "reboot", NULL, /* 56 - old mpxchan */ "symlink", "readlink", "execve", "umask", "chroot", "fstat", NULL, /* 63 - unused */ "getpagesize", NULL, /* 65 - mremap */ "vfork", NULL, /* 67 - old vread */ NULL, /* 68 - old vwrite */ "sbrk", NULL, /* 70 - old sstk */ NULL, /* 71 - mmap */ NULL, /* 72 - old vadvise */ NULL, /* 73 - munmap */ NULL, /* 74 - mprotect */ NULL, /* 75 - madvise */ "vhangup", NULL, /* 77 - old vlimit */ NULL, /* 78 - mincore */ "getgroups", "setgroups", "getpgrp", "setpgrp", "setitimer", "old wait", NULL, /* 85 - 4.3 swapon */ "getitimer", "gethostname", "sethostname", "getdtablesize", "dup2", NULL, /* 91 - unused */ "fcntl", "select", NULL, /* 94 - unused */ "fsync", "setpriority", "socket", "connect", "accept", "getpriority", "send", "recv", /* 102 - recv */ "sigreturn", "bind", "setsockopt", "listen", NULL, /* 107 - old vtimes */ "sigvec", "sigblock", "sigsetmask", "sigpause", "sigstack", "recvmsg", "sendmsg", NULL, /* 115 - 4.3 vtrace */ "gettimeofday", "getrusage", "getsockopt", NULL, /* 119 - old resuba */ "readv", "writev", "settimeofday", "fchown", "fchmod", "recvfrom", "setreuid", "setregid", "rename", "truncate", "ftruncate", "flock", NULL, /* 132 - unused */ "sendto", "shutdown", "socketpair", "mkdir", "rmdir", "utimes", NULL, /* 139 - 4.2 sigreturn */ "adjtime", "getpeername", "gethostid", "sethostid", "getrlimit", "setrlimit", "killpg", NULL, /* 147 - unused */ "setquota", "quota", "getsockname", /* * 2.11BSD special calls */ NULL, /* 151 - old rtp */ "nostk", "fetchi", "ucall", "fperr", "gldav", }; #define NUMSYSCALLS (sizeof (systab) / sizeof (char *)) char *regname[] = { "r0", "r1", "r2", "r3", "r4", "r5", "sp", "pc"}; u_int type, space, incp; printins(idsp,ins) register int ins; { int byte; register struct optab *p; type=DSYM; space=idsp; incp=2; FOR p=optab;; p++ DO IF (ins & ~p->mask) == p->val THEN break; FI OD printf(p->iname); byte=ins&0100000; ins &= p->mask; switch (p->itype) { case JMP: type=ISYM; case SINGLE: IF byte THEN printc('b'); FI case SINGLW: paddr("%8t",ins); break; case REVERS: doubl(ins&077,(ins>>6)&07); break; case JSR: type=ISYM; case DOUBLE: IF byte THEN printc('b'); FI case DOUBLW: doubl(ins>>6,ins); case NOADDR: break; case SOB: paddr("%8t",(ins>>6)&07); branch(",",-(ins&077)); break; case BRANCH: branch("%8t",ins); break; case SYS: if (ins < NUMSYSCALLS && systab[ins]) printf("%8t%s", systab[ins]); else printf("%8t%d", ins); break; case TRAP: case DFAULT: default: printf("%8t%o", ins); } dotinc=incp; } doubl(a,b) { paddr("%8t",a); paddr(",",b); } branch(s,ins) char *s; register int ins; { printf(s); IF ins&0200 THEN ins |= 0177400; FI ins = shorten(dot) + (ins<<1) + 2; psymoff(leng(ins),ISYM,""); } paddr(s, a) char *s; register int a; { register int r; var[2]=var[1]; r = a&07; a &= 070; printf(s); IF r==7 ANDF a&020 THEN IF a&010 THEN printc('*'); FI IF a&040 THEN IF space==NSP THEN printc('?'); ELSE var[1]=chkget(inkdot(incp),space) + shorten(inkdot(incp+2)); psymoff(var[1],(a&010?DSYM:type),""); FI ELSE printc('$'); IF space==NSP THEN printc('?'); ELSE var[1]=chkget(inkdot(incp), space); psymoff(var[1], (a&010?type:NSYM), ""); FI FI incp += 2; return; FI r = (int)regname[r]; switch (a) { /* r */ case 000: printf(r); return; /* (r) */ case 010: printf("(%s)", r); return; /* *(r)+ */ case 030: printc('*'); /* (r)+ */ case 020: printf("(%s)+", r); return; /* *-(r) */ case 050: printc('*'); /* -(r) */ case 040: printf("-(%s)", r); return; /* *x(r) */ case 070: printc('*'); /* x(r) */ case 060: IF space==NSP THEN printc('?'); ELSE var[1]=chkget(inkdot(incp), space); psymoff(var[1], (a==070?type:NSYM), ""); FI incp += 2; printf("(%s)", r); return; } } bin/adb/output.c 644 0 12 13041 5515144706 7060 #include "defs.h" int mkfault; int infile; int outfile = 1; int maxpos; char printbuf[MAXLIN]; char *printptr = printbuf; char *digitptr; MSG TOODEEP; long var[]; printc(c) char c; { char d; char *q; int posn, tabs, p; IF mkfault THEN return; ELIF (*printptr=c)==EOR THEN tabs=0; posn=0; q=printbuf; FOR p=0; p0 DO *q++=TB; tabs--; OD WHILE posn>0 DO *q++=SP; posn--; OD *q++=d; FI OD *q++=EOR; write(outfile,printbuf,q-printbuf); printptr=printbuf; ELIF c==TB THEN *printptr++=SP; WHILE (printptr-printbuf)&7 DO *printptr++=SP; OD ELIF c THEN printptr++; FI IF printptr >= &printbuf[MAXLIN-9] THEN write(outfile, printbuf, printptr-printbuf); printptr = printbuf; FI } flushbuf() { IF printptr!=printbuf THEN printc(EOR); FI } /*VARARGS*/ printf(fmat,a1) char *fmat; char **a1; { char *fptr, *s; int *vptr; long *dptr; double *rptr; int width, prec; char c, adj; int x, decpt, n; long lx; char digits[64]; char *ecvt(); fptr = fmat; vptr = (int *)&a1; WHILE c = *fptr++ DO IF c!='%' THEN printc(c); ELSE IF *fptr=='-' THEN adj='l'; fptr++; ELSE adj='r'; FI width=convert(&fptr); if (*fptr == '*') { width = *vptr++; fptr++; } if (*fptr == '.') { fptr++; prec = convert(&fptr); if (*fptr == '*') { prec = *vptr++; fptr++; } } else prec = -1; digitptr=digits; dptr=(long *)(rptr=(double *)vptr); lx = *dptr; x = *vptr++; s=0; switch (c = *fptr++) { case 'd': case 'u': printnum(x,c,10); break; case 'o': printoct(0,x,0); break; case 'q': lx=x; printoct(lx,-1); break; case 'x': printdbl(0,x,c,16); break; case 'Y': printdate(lx); vptr++; break; case 'D': case 'U': printdbl(lx,c,10); vptr++; break; case 'O': printoct(lx,0); vptr++; break; case 'Q': printoct(lx,-1); vptr++; break; case 'X': printdbl(lx,'x',16); vptr++; break; case 'c': printc(x); break; case 's': s=(char *)x; break; case 'f': case 'F': vptr += 7; s=ecvt(*rptr, prec, &decpt, &n); *digitptr++=(n?'-':'+'); *digitptr++ = (decpt<=0 ? '0' : *s++); IF decpt>0 THEN decpt--; FI *digitptr++ = '.'; WHILE *s ANDF prec-- DO *digitptr++ = *s++; OD WHILE *--digitptr=='0' DONE digitptr += (digitptr-digits>=3 ? 1 : 2); IF decpt THEN *digitptr++ = 'e'; printnum(decpt,'d',10); FI s=0; prec = -1; break; case 'm': vptr--; break; case 'M': width=x; break; case 'T': case 't': IF c=='T' THEN width=x; ELSE vptr--; FI IF width THEN width -= ((printptr - printbuf) % width); FI break; default: printc(c); vptr--; } IF s==0 THEN *digitptr=0; s=digits; FI n = strlen(s); n=(prec=0 ? prec : n); width -= n; IF adj=='r' THEN WHILE width-- > 0 DO printc(SP); OD FI WHILE n-- DO printc(*s++); OD WHILE width-- > 0 DO printc(SP); OD digitptr=digits; FI OD } printdate(tvec) long tvec; { register int i; register char *timeptr; extern char *ctime(); timeptr = ctime(&tvec); FOR i=20; i<24; i++ DO *digitptr++ = *(timeptr+i); OD FOR i=3; i<19; i++ DO *digitptr++ = *(timeptr+i); OD } convert(cp) register char **cp; { register char c; int n = 0; WHILE ((c = *(*cp)++)>='0') ANDF (c<='9') DO n=n*10+c-'0'; OD (*cp)--; return(n); } printnum(n,fmat,base) register int n; { register char k; register int *dptr; int digs[15]; dptr=digs; IF n<0 ANDF fmat=='d' THEN n = -n; *digitptr++ = '-'; FI WHILE n DO *dptr++ = ((u_int)n)%base; n=((u_int)n)/base; OD IF dptr==digs THEN *dptr++=0; FI WHILE dptr!=digs DO k = *--dptr; *digitptr++ = (k+(k<=9 ? '0' : 'a'-10)); OD } printoct(o,s) long o; int s; { int i; long po = o; char digs[12]; IF s THEN IF po<0 THEN po = -po; *digitptr++='-'; ELSE IF s>0 THEN *digitptr++='+'; FI FI FI FOR i=0;i<=11;i++ DO digs[i] = po&7; po >>= 3; OD digs[10] &= 03; digs[11]=0; FOR i=11;i>=0;i-- DO IF digs[i] THEN break; FI OD FOR i++;i>=0;i-- DO *digitptr++=digs[i]+'0'; OD } printdbl(lx,ly,fmat,base) int lx, ly; char fmat; int base; { int digs[20], *dptr; char k; double f ,g; long q; dptr=digs; IF fmat!='D' THEN f=leng(lx); f *= itol(1,0); f += leng(ly); IF fmat=='x' THEN *digitptr++='#'; FI ELSE f=itol(lx,ly); IF f<0 THEN *digitptr++='-'; f = -f; FI FI WHILE f DO q=f/base; g=q; *dptr++ = f-g*base; f=q; OD IF dptr==digs THEN *dptr++=0; FI WHILE dptr!=digs DO k = *--dptr; *digitptr++ = (k+(k<=9 ? '0' : 'a'-10)); OD } #define MAXIFD 5 struct { int fd; long r9; } istack[MAXIFD]; int ifiledepth; iclose(stack, err) { IF err THEN IF infile THEN close(infile); infile=0; FI WHILE --ifiledepth >= 0 DO IF istack[ifiledepth].fd THEN close(istack[ifiledepth].fd); infile=0; FI OD ifiledepth = 0; ELIF stack == 0 THEN IF infile THEN close(infile); infile=0; FI ELIF stack > 0 THEN IF ifiledepth >= MAXIFD THEN error(TOODEEP); FI istack[ifiledepth].fd = infile; istack[ifiledepth].r9 = var[9]; ifiledepth++; infile = 0; ELSE IF infile THEN close(infile); infile=0; FI IF ifiledepth > 0 THEN infile = istack[--ifiledepth].fd; var[9] = istack[ifiledepth].r9; FI FI } oclose() { IF outfile!=1 THEN flushbuf(); close(outfile); outfile=1; FI } endline() { if ((printptr - printbuf) >= maxpos) printc('\n'); } /* 75 - madvise */ "vhangup", NULL, /* 77 - old vlimit */ NULL, /* 78 - mincore */ "getgroups", "setgroups", "getpgrp", "setpgrp", "setitimer", "old wait", NULL, /* 85 - 4.3 swapon */ "getitimer", "gethostname", "sethostname", "getdtablesize", "dup2", NULL, /* 91 - unused */ "fcntl", "select", NULL, /* 94 - unused */ "fsync", "setpriority", "socket", "connect", "accept", "getpriority", "send", "recv", /* 102 - recv */ "sigreturn", bin/adb/pcs.c 644 0 12 4374 5511074614 6272 #include "defs.h" MSG NOBKPT; MSG SZBKPT; MSG EXBKPT; MSG NOPCS; MSG BADMOD; /* breakpoints */ BKPTR bkpthead; char *lp; char lastc; u_int corhdr[ctob(USIZE)/sizeof(u_int)]; MAP txtmap; int signo; long dot; int pid; long cntval; long loopcnt; int overlay; char curov, symov; /* sub process control */ subpcs(modif) { register int check; int execsig, runmode; register BKPTR bkptr; char *comptr; execsig=0; loopcnt=cntval; switch(modif) { /* delete breakpoint */ case 'd': case 'D': if (symov && symov!=curov) setovmap(symov); IF (bkptr=scanbkpt(shorten(dot))) THEN bkptr->flag=0; if (pid) del1bp(bkptr); return; ELSE error(NOBKPT); FI /* set breakpoint */ case 'b': case 'B': if (symov && symov!=curov) setovmap(symov); IF (bkptr=scanbkpt(shorten(dot))) THEN bkptr->flag=0; if (pid) del1bp(bkptr); FI FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt DO IF bkptr->flag == 0 THEN break; FI OD IF bkptr==0 THEN IF (bkptr=(BKPTR)malloc(sizeof *bkptr)) == (BKPTR)NULL THEN error(SZBKPT); ELSE bkptr->nxtbkpt=bkpthead; bkpthead=bkptr; FI FI bkptr->loc = dot; bkptr->initcnt = bkptr->count = cntval; bkptr->flag = BKPTSET; if (overlay && dot>txtmap.bo) bkptr->ovly = symov ? symov : curov; else bkptr->ovly = 0; /* base seg */ check=MAXCOM-1; comptr=bkptr->comm; rdc(); lp--; REP *comptr++ = readchar(); PER check-- ANDF lastc!=EOR DONE *comptr=0; lp--; IF check THEN if (pid) set1bp(bkptr); return; ELSE error(EXBKPT); FI /* exit */ case 'k' :case 'K': IF pid THEN printf("%d: killed", pid); endpcs(); return; FI error(NOPCS); /* run program */ case 'r': case 'R': endpcs(); setup(); setbp(); runmode=CONTIN; break; /* single step */ case 's': case 'S': runmode=SINGLE; IF pid THEN execsig=getsig(signo); ELSE setup(); loopcnt--; FI break; /* continue with optional signal */ case 'c': case 'C': case 0: IF pid==0 THEN error(NOPCS); FI runmode=CONTIN; execsig=getsig(signo); break; default: error(BADMOD); } IF loopcnt>0 ANDF runpcs(runmode, execsig) THEN printf("breakpoint%16t"); ELSE printf("stopped at%16t"); FI printpc(); } th THEN width -= ((printptr - printbuf) % width); FI break; default: printc(c); vptr--; } IF s==0 THEN *digitptr=0; s=digits; FI n = strlen(s); n=(prec=0 ? prec : n); width -= n; IF adj=='r' THEN WHILE width-- bin/adb/print.c 644 0 12 20065 5515174243 6657 #include "defs.h" #include MSG LONGFIL; MSG NOTOPEN; MSG A68BAD; MSG A68LNK; MSG BADMOD; MAP txtmap; MAP datmap; char curov; int overlay; extern struct SYMbol *symbol; int lastframe; int kernel; int callpc; int infile; int outfile; char *lp; int maxoff; int maxpos; int octal; long localval; BKPTR bkpthead; static char frnames[] = { 0, 3, 4, 5, 1, 2 }; char lastc; u_int corhdr[]; u_int *uar0; int fcor; char *errflg; int signo; long dot; long var[]; char *symfil; char *corfil; int pid; long adrval; int adrflg; long cntval; int cntflg; int overlay; REGLIST reglist [] = { "ps", RPS, "pc", PC, "sp", R6, "r5", R5, "r4", R4, "r3", R3, "r2", R2, "r1", R1, "r0", R0 }; REGLIST kregs[] = { "sp", KSP, "r5", KR5, "r4", KR4, "r3", KR3, "r2", KR2, "r1", KR1, "r0", KR0 }; /* general printing routines ($) */ printtrace(modif) { int narg, i, stat, name, limit; u_int dynam; register BKPTR bkptr; char hi, lo; int word, stack; char *comptr; long argp, frame, link; register struct SYMbol *symp; char savov; IF cntflg==0 THEN cntval = -1; FI switch (modif) { case '<': IF cntval == 0 THEN WHILE readchar() != EOR DO OD lp--; break; FI IF rdc() == '<' THEN stack = 1; ELSE stack = 0; lp--; FI /* fall thru ... */ case '>': { char file[64]; char Ifile[128]; extern char *Ipath; int index; index=0; IF rdc()!=EOR THEN REP file[index++]=lastc; IF index>=63 THEN error(LONGFIL); FI PER readchar()!=EOR DONE file[index]=0; IF modif=='<' THEN IF Ipath THEN strcpy(Ifile, Ipath); strcat(Ifile, "/"); strcat(Ifile, file); FI IF strcmp(file, "-") != 0 THEN iclose(stack, 0); infile=open(file,0); IF infile<0 THEN infile = open(Ifile, 0); FI ELSE lseek(infile, 0L, 0); FI IF infile<0 THEN infile=0; error(NOTOPEN); ELSE IF cntflg THEN var[9] = cntval; ELSE var[9] = 1; FI FI ELSE oclose(); outfile = open(file, O_CREAT|O_WRONLY, 0644); lseek(outfile,0L,2); FI ELSE IF modif == '<' THEN iclose(-1, 0); ELSE oclose(); FI FI lp--; } break; case 'o': octal = TRUE; break; case 'd': octal = FALSE; break; case 'q': case 'Q': case '%': done(); case 'w': case 'W': maxpos=(adrflg?adrval:MAXPOS); break; case 's': case 'S': maxoff=(adrflg?adrval:MAXOFF); break; case 'v': printf("variables\n"); FOR i=0;i<=35;i++ DO IF var[i] THEN printc((i<=9 ? '0' : 'a'-10) + i); printf(" = %Q\n",var[i]); FI OD break; case 'm': case 'M': printmap("? map",&txtmap); printmap("/ map",&datmap); break; case 0: case '?': IF pid THEN printf("pcs id = %d\n",pid); ELSE printf("no process\n"); FI sigprint(); flushbuf(); case 'r': case 'R': printregs(); return; case 'f': case 'F': printfregs(modif=='F'); return; case 'c': case 'C': frame=(adrflg?adrval:(kernel?corhdr[KR5]:uar0[R5]))&EVEN; lastframe=0; savov = curov; callpc=(adrflg?get(frame+2,DSP):(kernel?(-2):uar0[PC])); WHILE cntval-- DO chkerr(); printf("%07O: ", frame); /* Add frame address info */ narg = findroutine(frame); printf("%s(", cache_sym(symbol)); argp = frame+4; IF --narg >= 0 THEN printf("%o", get(argp, DSP)); FI WHILE --narg >= 0 DO argp += 2; printf(",%o", get(argp, DSP)); OD /* Add return-PC info. Force printout of * symbol+offset (never just a number! ) by using * max possible offset. Overlay has already been set * properly by findfn. */ printf(") from "); { int savmaxoff = maxoff; maxoff = ((unsigned)-1)>>1; psymoff((long)callpc,ISYM,""); maxoff = savmaxoff; } printc('\n'); IF modif=='C' THEN WHILE localsym(frame) DO word=get(localval,DSP); printf("%8t%s:%10t", cache_sym(symbol)); IF errflg THEN printf("?\n"); errflg=0; ELSE printf("%o\n",word); FI OD FI lastframe=frame; frame=get(frame, DSP)&EVEN; IF kernel? ((u_int)frame>((u_int)0140000+ctob(USIZE))): (frame==0) THEN break; FI OD if (overlay) setovmap(savov); break; /*print externals*/ case 'e': case 'E': symset(); WHILE (symp=symget()) DO chkerr(); IF (symp->type == N_EXT|N_DATA) || (symp->type== N_EXT|N_BSS) THEN printf("%s:%12t%o\n", no_cache_sym(symp), get(leng(symp->value),DSP)); FI OD break; case 'a': case 'A': frame=(adrflg ? adrval : uar0[R4]); WHILE cntval-- DO chkerr(); stat=get(frame,DSP); dynam=get(frame+2,DSP); link=get(frame+4,DSP); IF modif=='A' THEN printf("%8O:%8t%-8o,%-8o,%-8o",frame,stat,dynam,link); FI IF stat==1 THEN break; FI IF errflg THEN error(A68BAD); FI IF get(link-4,ISP)!=04767 THEN IF get(link-2,ISP)!=04775 THEN error(A68LNK); ELSE /*compute entry point of routine*/ printf(" ? "); FI ELSE printf("%8t"); valpr(name=shorten(link)+get(link-2,ISP),ISYM); name=get(leng(name-2),ISP); printf("%8t\""); limit=8; REP word=get(leng(name),DSP); name += 2; lo=word&LOBYTE; hi=(word>>8)&LOBYTE; printc(lo); printc(hi); PER lo ANDF hi ANDF limit-- DONE printc('"'); FI limit=4; i=6; printf("%24targs:%8t"); WHILE limit-- DO printf("%8t%o",get(frame+i,DSP)); i += 2; OD printc(EOR); frame=dynam; OD errflg=0; flushbuf(); break; /*set default c frame*/ /*print breakpoints*/ case 'b': case 'B': printf("breakpoints\ncount%8tbkpt%24tcommand\n"); savov = curov; FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt DO IF bkptr->flag THEN printf("%-8.8d",bkptr->count); curov = bkptr->ovly; psymoff(leng(bkptr->loc),ISYM,"%24t"); comptr=bkptr->comm; WHILE *comptr DO printc(*comptr++); OD FI OD curov = savov; break; default: error(BADMOD); } } printmap(s,amap) char *s; MAP *amap; { int file; file=amap->ufd; printf("%s%12t`%s'\n",s,(file<0 ? "-" : (file==fcor ? corfil : symfil))); printf("b1 = %-16Q",amap->b1); printf("e1 = %-16Q",amap->e1); printf("f1 = %-16Q",amap->f1); IF amap->bo THEN printf("\n\t{ bo = %-16Q",amap->bo); printf("eo = %-16Q",amap->eo); printf("fo = %-16Q}",amap->fo); FI printf("\nb2 = %-16Q",amap->b2); printf("e2 = %-16Q",amap->e2); printf("f2 = %-16Q",amap->f2); printc(EOR); } printfregs(longpr) { register int i; double f; struct Lfp *pfp; pfp = (struct Lfp *)&((U*)corhdr)->u_fps.u_fpsr; printf("fpsr\t%o\n", pfp->fpsr); FOR i=0; iu_fps.u_fpsr&FD ORF longpr /* long mode */ THEN f = pfp->Lfr[frnames[i]]; ELSE f = ((struct Sfp *)pfp)->Sfr[frnames[i]]; FI printf("fr%-8d%-32.18f\n", i, f); OD } printregs() { register REGPTR p; int v; IF kernel THEN FOR p=kregs; p<&kregs[7]; p++ DO printf("%s%8t%o%8t", p->rname, v=corhdr[p->roffs]); valpr(v,DSYM); printc(EOR); OD ELSE FOR p=reglist; p < ®list[NREG]; p++ DO printf("%s%8t%o%8t", p->rname, v=uar0[p->roffs]); valpr(v,(p->roffs==PC?ISYM:DSYM)); printc(EOR); OD IF overlay THEN setovmap(((U *)corhdr)->u_ovdata.uo_curov); var[VARC] = curov; printf("ov%8t%o\n", curov); FI printpc(); FI } getreg(regnam) { register REGPTR p; register char *regptr; char regnxt; IF kernel THEN return(NOREG); FI /* not supported */ regnxt=readchar(); FOR p=reglist; p<®list[NREG]; p++ DO regptr=p->rname; IF (regnam == *regptr++) ANDF (regnxt == *regptr) THEN return(p->roffs); FI OD IF regnam == 'o' && regnxt == 'v' THEN return((u_int *)&(((U *)corhdr)->u_ovdata.uo_curov) - uar0); FI lp--; return(NOREG); } printpc() { dot=uar0[PC]; psymoff(dot,ISYM,":%16t"); printins(ISP,chkget(dot,ISP)); printc(EOR); } sigprint() { extern char *sys_siglist[]; /* signal list */ if (signo >= 0 && signo < NSIG) printf("%s",sys_siglist[signo]); else printf("unknown signal %d",signo); } ase SOB: paddr("%8t",(ins>>6)&07); branch(",",-(ins&077)); break; case BRANCH: branch("%8t",ins); break; case SYS: if (ins < NUMSYSCALLS && systab[ins]) printf("%8t%s", systab[ins]); else printf("%8t%d", ins); break; case TRAP: case DFAULT: default: printf("%8t%o", ins); } dotinc=incp; } doubl(a,b) { paddr("%8t",a); paddr(",",b); } branch(s,ins) char *s; register int ins; { printf(s); IF ins&020bin/adb/runpcs.c 644 0 12 12407 5515156171 7036 #include "defs.h" #include MSG NOFORK; MSG ENDPCS; MSG BADWAIT; char *lp; int sigint; int sigqit; BKPTR bkpthead; REGLIST reglist[]; char lastc; u_int corhdr[]; u_int *uar0; int overlay; char curov; int fcor; int fsym; char *errflg; int signo; long dot; char *symfil; int wtflag; int pid; long expv; int adrflg; long loopcnt; long var[]; int userpc=1; extern int errno; /* service routines for sub process control */ getsig(sig) { return(expr(0) ? shorten(expv) : sig); } runpcs(runmode, execsig) { int rc; register BKPTR bkpt; IF adrflg THEN userpc=shorten(dot); FI if (overlay) choverlay(((U*)corhdr)->u_ovdata.uo_curov); printf("%s: running\n", symfil); WHILE (loopcnt--)>0 DO #ifdef DEBUG printf("\ncontinue %d %d\n",userpc,execsig); #endif stty(0,&usrtty); ptrace(runmode,pid,userpc,execsig); bpwait(); chkerr(); readregs(); /*look for bkpt*/ IF signo==0 ANDF (bkpt=scanbkpt(uar0[PC]-2)) THEN /*stopped at bkpt*/ userpc=uar0[PC]=bkpt->loc; IF bkpt->flag==BKPTEXEC ORF ((bkpt->flag=BKPTEXEC, command(bkpt->comm,':')) ANDF --bkpt->count) THEN execbkpt(bkpt); execsig=0; loopcnt++; userpc=1; ELSE bkpt->count=bkpt->initcnt; rc=1; FI ELSE rc=0; execsig=signo; userpc=1; FI OD return(rc); } endpcs() { register BKPTR bkptr; IF pid THEN ptrace(EXIT,pid,0,0); pid=0; userpc=1; FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt DO IF bkptr->flag THEN bkptr->flag=BKPTSET; FI OD FI } setup() { close(fsym); fsym = -1; IF (pid = fork()) == 0 THEN ptrace(SETTRC,0,0,0); signal(SIGINT,sigint); signal(SIGQUIT,sigqit); doexec(); exit(0); ELIF pid == -1 THEN error(NOFORK); ELSE bpwait(); readregs(); lp[0]=EOR; lp[1]=0; fsym=open(symfil,wtflag); IF errflg THEN printf("%s: cannot execute\n",symfil); endpcs(); error((char *)0); FI FI } execbkpt(bkptr) BKPTR bkptr; { int bkptloc; #ifdef DEBUG printf("exbkpt: %d\n",bkptr->count); #endif bkptloc = bkptr->loc; ptrace(WIUSER,pid,bkptloc,bkptr->ins); stty(0,&usrtty); ptrace(SINGLE,pid,bkptloc,0); bpwait(); chkerr(); ptrace(WIUSER,pid,bkptloc,BPT); bkptr->flag=BKPTSET; } doexec() { char *argl[MAXARG]; char args[LINSIZ]; char *p, **ap, *filnam; ap=argl; p=args; *ap++=symfil; REP IF rdc()==EOR THEN break; FI /* * If we find an argument beginning with a `<' or a `>', open * the following file name for input and output, respectively * and back the argument collocation pointer, p, back up. */ *ap = p; WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB DO *p++=lastc; readchar(); OD *p++=0; filnam = *ap+1; IF **ap=='<' THEN close(0); IF open(filnam,0)<0 THEN printf("%s: cannot open\n",filnam); exit(0); FI p = *ap; ELIF **ap=='>' THEN close(1); IF open(filnam, O_CREAT|O_WRONLY, 0666)<0 THEN printf("%s: cannot create\n",filnam); exit(0); FI p = *ap; ELSE ap++; FI PER lastc!=EOR DONE *ap++=0; execv(symfil, argl); } BKPTR scanbkpt(adr) { register BKPTR bkptr; FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt DO IF bkptr->flag ANDF bkptr->loc==adr ANDF (bkptr->ovly == 0 || bkptr->ovly==curov) THEN break; FI OD return(bkptr); } delbp() { register BKPTR bkptr; FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt DO IF bkptr->flag THEN del1bp(bkptr); FI OD } del1bp(bkptr) BKPTR bkptr; { if (bkptr->ovly) choverlay(bkptr->ovly); ptrace(WIUSER,pid,bkptr->loc,bkptr->ins); } /* change overlay in subprocess */ choverlay(ovno) char ovno; { errno = 0; if (overlay && pid && ovno>0 && ovno<=NOVL) ptrace(WUREGS,pid,&(((U*)0)->u_ovdata.uo_curov),ovno); IF errno THEN printf("cannot change to overlay %d\n", ovno); FI } setbp() { register BKPTR bkptr; FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt DO IF bkptr->flag THEN set1bp(bkptr); FI OD } set1bp(bkptr) BKPTR bkptr; { register int a; a = bkptr->loc; if (bkptr->ovly) choverlay(bkptr->ovly); bkptr->ins = ptrace(RIUSER, pid, a, 0); ptrace(WIUSER, pid, a, BPT); IF errno THEN printf("cannot set breakpoint: "); psymoff(leng(bkptr->loc),ISYM,"\n"); FI } bpwait() { register int w; int stat; signal(SIGINT, SIG_IGN); WHILE (w = wait(&stat))!=pid ANDF w != -1 DONE signal(SIGINT,sigint); gtty(0,&usrtty); stty(0,&adbtty); IF w == -1 THEN pid=0; errflg=BADWAIT; ELIF (stat & 0177) != 0177 THEN IF signo = stat&0177 THEN sigprint(); FI IF stat&0200 THEN printf(" - core dumped"); close(fcor); setcor(); FI pid=0; errflg=ENDPCS; ELSE signo = stat>>8; IF signo!=SIGTRAP THEN sigprint(); ELSE signo=0; FI flushbuf(); FI } readregs() { /*get REG values from pcs*/ register int i; char ovno; FOR i=0; iu_ovdata.uo_curov),0); var[VARC] = ovno; ((U *)corhdr)->u_ovdata.uo_curov = ovno; setovmap(ovno); FI /* REALing poINT */ FOR i=FROFF; itype == N_EXT|N_DATA) || (symp->type== N_EXT|N_BSS) THEN printf("%s:%12t%o\n", no_cache_symbin/adb/setup.c 644 0 12 10612 5511074273 6656 #include "defs.h" #include MAP txtmap; MAP datmap; int wtflag; int kernel; int fcor; int fsym; long maxfile; long maxstor; long txtsiz; long datsiz; long bss; long datbas; long stksiz; char *errflg; int magic; long entrypt; long var[]; int argcount; int signo; u_int corhdr[ctob(USIZE)/sizeof(u_int)]; u_int *uar0 = UAR0; char *symfil = "a.out"; char *corfil = "core"; struct ovlhdr ovlseg; long ovlsiz; long ovloff[NOVL+1]; char startov; int overlay; off_t symoff, stroff; setsym() { struct xexec hdr; int ovly; bzero(&txtmap, sizeof (txtmap)); fsym=getfile(symfil,1); txtmap.ufd=fsym; if (read(fsym, &hdr, sizeof (hdr)) >= (int)sizeof (hdr.e)) { magic= hdr.e.a_magic; txtsiz = hdr.e.a_text; datsiz = hdr.e.a_data; bss = hdr.e.a_bss; entrypt = hdr.e.a_entry; txtmap.f1 = N_TXTOFF(hdr.e); symoff = N_SYMOFF(hdr); stroff = N_STROFF(hdr); switch (magic) { case 0407: txtmap.e1 = txtmap.e2 = txtsiz+datsiz; txtmap.f2 = txtmap.f1; break; case 0410: txtmap.e1 = txtsiz; txtmap.b2 = round(txtsiz, TXTRNDSIZ); txtmap.e2 = txtmap.b2+datsiz; txtmap.f2 = txtsiz + txtmap.f1; break; case 0405: case 0411: txtmap.e1 = txtsiz; txtmap.e2 = datsiz; txtmap.f2 = txtsiz + txtmap.f1; break; case 0430: case 0431: ovlseg = hdr.o; txtmap.e1 = txtsiz; txtmap.bo = round(txtsiz, TXTRNDSIZ); FOR ovly = 0; ovly < NOVL; ovly++ DO ovloff[ovly] = ovlsiz + txtsiz + txtmap.f1; ovlsiz += ovlseg.ov_siz[ovly]; OD IF magic == 0430 THEN txtmap.b2 = round(txtmap.bo+(long)ovlseg.max_ovl, TXTRNDSIZ); FI txtmap.f2 = txtmap.f1 + txtsiz+ovlsiz; txtmap.e2 = txtmap.b2 + datsiz; overlay = 1; break; default: magic = 0; txtsiz = 0; datsiz = 0; bss = 0; entrypt = 0; } datbas = txtmap.b2; symINI(&hdr); } IF magic==0 THEN txtmap.e1=maxfile; FI } setcor() { fcor=getfile(corfil,2); datmap.ufd=fcor; IF read(fcor, corhdr, sizeof corhdr)==sizeof corhdr THEN IF !kernel THEN txtsiz = ((U*)corhdr)->u_tsize << 6; datsiz = ((U*)corhdr)->u_dsize << 6; stksiz = ((U*)corhdr)->u_ssize << 6; datmap.f1 = ctob(USIZE); datmap.b2 = maxstor-stksiz; datmap.e2 = maxstor; ELSE datsiz = round(datsiz+bss,64L); stksiz = (long) ctob(USIZE); datmap.f1 = 0; datmap.b2 = 0140000L; datmap.e2 = 0140000L + ctob(USIZE); FI switch (magic) { case 0407: datmap.b1 = 0; datmap.e1 = txtsiz+datsiz; IF kernel THEN datmap.f2 = (long)corhdr[KA6] * 0100L; ELSE datmap.f2 = ctob(USIZE)+txtsiz+datsiz; FI break; case 0410: datmap.b1 = round(txtsiz, TXTRNDSIZ); datmap.e1 = datmap.b1+datsiz; datmap.f2 = datsiz+ctob(USIZE); break; case 0405: case 0411: case 0431: datmap.b1 = 0; datmap.e1 = datsiz; IF kernel THEN datmap.f2 = (long)corhdr[KA6] * 0100L; ELSE datmap.f2 = datsiz+ctob(USIZE); FI break; case 0430: datmap.b1 = round(round(txtsiz, TXTRNDSIZ)+ovlseg.max_ovl, TXTRNDSIZ); datmap.e1 = datmap.b1+datsiz; IF kernel THEN datmap.b1 = 0; datmap.f2 = (long)corhdr[KA6] * 0100L; ELSE datmap.f2 = datsiz+ctob(USIZE); FI break; default: magic = 0; datmap.b1 = 0; datmap.e1 = maxfile; datmap.f1 = 0; datmap.b2 = 0; datmap.e2 = 0; datmap.f2 = 0; } datbas = datmap.b1; if (!kernel && magic) { /* * Note that we can no longer compare the magic * number of the core against that of the object * since the user structure no longer contains * the exec header ... */ register u_int *ar0; ar0 = (u_int *)(((U *)corhdr)->u_ar0); if (ar0 > (u_int *)0140000 && ar0 < (u_int *)(0140000 + ctob(USIZE)) && !((unsigned)ar0&01)) uar0 = (u_int *)&corhdr[ar0-(u_int *)0140000]; if (overlay) { startov = ((U *)corhdr)->u_ovdata.uo_curov; var[VARC] = (long)startov; setovmap(startov); } /* else dig out __ovno if overlaid? */ } ELSE datmap.e1 = maxfile; FI } getfile(filnam,cnt) char *filnam; int cnt; { register int f; IF strcmp("-",filnam) THEN f = open(filnam,wtflag); IF f < 0 ANDF argcount>cnt THEN IF wtflag THEN f = open(filnam, O_CREAT|O_TRUNC|wtflag,644); FI IF f < 0 THEN printf("cannot open `%s'\n", filnam); FI FI ELSE f = -1; FI return(f); } s:%8t"); WHILE limit-- DO printf("%8t%o",get(frame+i,DSP)); i += 2; OD printc(EOR); frame=dynam; bin/adb/sym.c 644 0 12 14613 5516361713 6336 #include #include "defs.h" #include #include struct SYMbol *symbol; char localok; int lastframe; u_int maxoff; long maxstor; MAP txtmap; char curov; int overlay; long localval; char *errflg; u_int findsym(); struct SYMcache { char *name; int used; struct SYMbol *syment; }; #ifndef NUM_SYMS_CACHE #define NUM_SYMS_CACHE 50 #endif static struct SYMcache symcache[NUM_SYMS_CACHE]; static struct SYMcache *endcache = &symcache[NUM_SYMS_CACHE]; static struct SYMbol *symtab; static FILE *strfp; static int symcnt; static int symnum; static char *sgets(); extern char *myname, *symfil, *strdup(); extern off_t symoff, stroff; /* symbol table and file handling service routines */ valpr(v,idsp) { u_int d; d = findsym(v,idsp); IF d < maxoff THEN printf("%s", cache_sym(symbol)); IF d THEN printf(OFFMODE, d); FI FI } localsym(cframe) long cframe; { int symflg; WHILE symget() && localok && (symflg= (int)symbol->type) != N_FN && *no_cache_sym(symbol) != '~' DO IF symflg>=2 ANDF symflg<=4 THEN localval=symbol->value; return(TRUE); ELIF symflg==1 THEN localval=leng(shorten(cframe)+symbol->value); return(TRUE); ELIF symflg==20 ANDF lastframe THEN localval=leng(lastframe+2*symbol->value - (overlay?12:10)); return(TRUE); FI OD return(FALSE); } psymoff(v,type,s) long v; int type; char *s; { u_int w; w = findsym(shorten(v),type); IF w >= maxoff THEN printf(LPRMODE,v); ELSE printf("%s", cache_sym(symbol)); IF w THEN printf(OFFMODE,w); FI FI printf(s); } u_int findsym(svalue,type) u_int svalue; int type; { long diff, value, symval; register struct SYMbol *sp; struct SYMbol *symsav; int i; char ov = 0; if (txtmap.bo && type==ISYM && svalue>=txtmap.bo) ov=curov; value = svalue; diff = 0377777L; if (type != NSYM && symnum) { for (i = 0, sp = symtab; diff && i < symnum; i++, sp++) { if (SYMTYPE(sp->type) == type && (!ov || ov == sp->ovno)) { symval = leng(sp->value); if ((value - symval) < diff && value >= symval) { diff = value - symval; symsav = sp; } } } } if (symsav) symcnt = symsav - symtab; symbol = symsav; return(shorten(diff)); } /* sequential search through table */ symset() { symcnt = -1; } struct SYMbol * symget() { if (symcnt >= symnum || !symnum) return(NULL); symcnt++; symbol = &symtab[symcnt]; return(symbol); } /* * This only _looks_ expensive ;-) The extra scan over the symbol * table allows us to cut down the amount of memory needed. This is * where symbols with string table offsets over 64kb are excluded. Also, * a late addition to the program excludes register symbols - the assembler * generates *lots* of them and they're useless to us. */ symINI(ex) struct exec *ex; { register struct SYMbol *sp; register FILE *fp; struct nlist sym; int i, nused, globals_only = 0; fp = fopen(symfil, "r"); strfp = fp; if (!fp) return; fcntl(fileno(fp), F_SETFD, 1); symnum = ex->a_syms / sizeof (sym); fseek(fp, symoff, L_SET); nused = 0; for (i = 0; i < symnum; i++) { fread(&sym, sizeof (sym), 1, fp); if (sym.n_type == N_REG) continue; if (sym.n_un.n_strx >= 0200000L) printf("symbol %d string offset > 64k - ignored\n",i); else nused++; } fseek(fp, symoff, L_SET); symtab = (struct SYMbol *)malloc(nused * sizeof (struct SYMbol)); if (!symtab) { globals_only = 1; nused = 0; for (symcnt = 0; symcnt < symnum; symcnt++) { fread(&sym, 1, sizeof (sym), fp); if (sym.n_type == N_REG) continue; if ((sym.n_type & N_EXT) == 0) continue; if (sym.n_un.n_strx >= 0200000L) continue; nused++; } symtab = (struct SYMbol *)malloc(nused * sizeof(struct SYMbol)); if (!symtab) { printf("%s: no memory for symbols\n", myname); symnum = 0; return; } } fseek(fp, symoff, L_SET); sp = symtab; for (symcnt = 0; symcnt < symnum; symcnt++) { fread(&sym, 1, sizeof (sym), fp); if (sym.n_type == N_REG) continue; if (globals_only && !(sym.n_type & N_EXT)) continue; if (sym.n_un.n_strx >= 0200000L) continue; sp->value = sym.n_value; sp->ovno = sym.n_ovly; sp->type = sym.n_type; sp->soff = shorten(sym.n_un.n_strx); sp++; } symnum = nused; #ifdef debug printf("%d symbols loaded\n", nused); #endif if (globals_only) printf("%s: could only do global symbols\n", myname); symset(); return(0); } /* * Look in the cache for a symbol in memory. If it is not found use * the least recently used entry in the cache and update it with the * symbol name. */ char * cache_sym(symp) register struct SYMbol *symp; { register struct SYMcache *sc = symcache; struct SYMcache *current; int lru; if (!symp) return("?"); for (current = NULL, lru = 30000 ; sc < endcache; sc++) { if (sc->syment == symp) { sc->used++; if (sc->used >= 30000) sc->used = 10000; return(sc->name); } if (sc->used < lru) { lru = sc->used; current = sc; } } sc = current; if (sc->name) free(sc->name); sc->used = 1; sc->syment = symp; sc->name = strdup(sgets(symp->soff)); return(sc->name); } /* * We take a look in the cache but do not update the cache on a miss. * This is done when scanning thru the symbol table (printing all externals * for example) for large numbers of symbols which probably won't be * used again any time soon. */ char * no_cache_sym(symp) register struct SYMbol *symp; { register struct SYMcache *sc = symcache; if (!symp) return("?"); for ( ; sc < endcache; sc++) { if (sc == symp) { sc->used++; if (sc->used >= 30000) sc->used = 10000; return(sc->name); } } return(sgets(symp->soff)); } /* * Looks in the cache for a match by string value rather than string * file offset. */ struct SYMbol * cache_by_string(str, ovsym) char *str; int ovsym; { register struct SYMcache *sc; for (sc = symcache; sc < endcache; sc++) { if (!sc->name) continue; if (eqsym(sc->name, str, ovsym ? '~' : '_')) break; } if (sc < endcache) { sc->used++; if (sc->used > 30000) sc->used = 10000; return(sc->syment); } return(0); } static char * sgets(soff) u_short soff; { static char symname[MAXSYMLEN + 2]; register char *buf = symname; int c; register int i; fseek(strfp, stroff + soff, L_SET); for (i = 0; i < MAXSYMLEN; i++) { c = getc(strfp); *buf++ = c; if (c == '\0') break; } *buf = '\0'; return(symname); } >b2); printf("e2 = %-16Q",amap->e2); printf("f2 = %-16Q",amap->f2); printc(EOR); } printfregs(longpr) { registerbin/awk/ 755 0 12 0 6024535746 5310 bin/awk/b.c 444 0 12 25300 4013202620 5752 #ifndef lint static char sccsid[] = "@(#)b.c 4.2 8/11/83"; #endif #include "awk.def" #include "stdio.h" #include "awk.h" extern node *op2(); extern struct fa *cgotofn(); #define MAXLIN 256 #define NCHARS 128 #define NSTATES 256 #define type(v) v->nobj #define left(v) v->narg[0] #define right(v) v->narg[1] #define parent(v) v->nnext #define LEAF case CCL: case NCCL: case CHAR: case DOT: #define UNARY case FINAL: case STAR: case PLUS: case QUEST: /* encoding in tree nodes: leaf (CCL, NCCL, CHAR, DOT): left is index, right contains value or pointer to value unary (FINAL, STAR, PLUS, QUEST): left is child, right is null binary (CAT, OR): left and right are children parent contains pointer to parent */ struct fa { int cch; struct fa *st; }; int *state[NSTATES]; int *foll[MAXLIN]; char chars[MAXLIN]; int setvec[MAXLIN]; node *point[MAXLIN]; int setcnt; int line; struct fa *makedfa(p) /* returns dfa for tree pointed to by p */ node *p; { node *p1; struct fa *fap; p1 = op2(CAT, op2(STAR, op2(DOT, (node *) 0, (node *) 0), (node *) 0), p); /* put DOT STAR in front of reg. exp. */ p1 = op2(FINAL, p1, (node *) 0); /* install FINAL node */ line = 0; penter(p1); /* enter parent pointers and leaf indices */ point[line] = p1; /* FINAL node */ setvec[0] = 1; /* for initial DOT STAR */ cfoll(p1); /* set up follow sets */ fap = cgotofn(); freetr(p1); /* add this when alloc works */ return(fap); } penter(p) /* set up parent pointers and leaf indices */ node *p; { switch(type(p)) { LEAF left(p) = (node *) line; point[line++] = p; break; UNARY penter(left(p)); parent(left(p)) = p; break; case CAT: case OR: penter(left(p)); penter(right(p)); parent(left(p)) = p; parent(right(p)) = p; break; default: error(FATAL, "unknown type %d in penter\n", type(p)); break; } } freetr(p) /* free parse tree and follow sets */ node *p; { switch(type(p)) { LEAF xfree(foll[(int) left(p)]); xfree(p); break; UNARY freetr(left(p)); xfree(p); break; case CAT: case OR: freetr(left(p)); freetr(right(p)); xfree(p); break; default: error(FATAL, "unknown type %d in freetr", type(p)); break; } } char *cclenter(p) register char *p; { register i, c; char *op; op = p; i = 0; while ((c = *p++) != 0) { if (c == '-' && i > 0 && chars[i-1] != 0) { if (*p != 0) { c = chars[i-1]; while (c < *p) { if (i >= MAXLIN) overflo(); chars[i++] = ++c; } p++; continue; } } if (i >= MAXLIN) overflo(); chars[i++] = c; } chars[i++] = '\0'; dprintf("cclenter: in = |%s|, out = |%s|\n", op, chars, NULL); xfree(op); return(tostring(chars)); } overflo() { error(FATAL, "regular expression too long\n"); } cfoll(v) /* enter follow set of each leaf of vertex v into foll[leaf] */ register node *v; { register i; int prev; int *add(); switch(type(v)) { LEAF setcnt = 0; for (i=1; i<=line; i++) setvec[i] = 0; follow(v); if (notin(foll, ( (int) left(v))-1, &prev)) { foll[(int) left(v)] = add(setcnt); } else foll[ (int) left(v)] = foll[prev]; break; UNARY cfoll(left(v)); break; case CAT: case OR: cfoll(left(v)); cfoll(right(v)); break; default: error(FATAL, "unknown type %d in cfoll", type(v)); } } first(p) /* collects initially active leaves of p into setvec */ register node *p; /* returns 0 or 1 depending on whether p matches empty string */ { register b; switch(type(p)) { LEAF if (setvec[(int) left(p)] != 1) { setvec[(int) left(p)] = 1; setcnt++; } if (type(p) == CCL && (*(char *) right(p)) == '\0') return(0); /* empty CCL */ else return(1); case FINAL: case PLUS: if (first(left(p)) == 0) return(0); return(1); case STAR: case QUEST: first(left(p)); return(0); case CAT: if (first(left(p)) == 0 && first(right(p)) == 0) return(0); return(1); case OR: b = first(right(p)); if (first(left(p)) == 0 || b == 0) return(0); return(1); } error(FATAL, "unknown type %d in first\n", type(p)); return(-1); } follow(v) node *v; /* collects leaves that can follow v into setvec */ { node *p; if (type(v) == FINAL) return; p = parent(v); switch (type(p)) { case STAR: case PLUS: first(v); follow(p); return; case OR: case QUEST: follow(p); return; case CAT: if (v == left(p)) { /* v is left child of p */ if (first(right(p)) == 0) { follow(p); return; } } else /* v is right child */ follow(p); return; case FINAL: if (setvec[line] != 1) { setvec[line] = 1; setcnt++; } return; } } member(c, s) /* is c in s? */ register char c, *s; { while (*s) if (c == *s++) return(1); return(0); } notin(array, n, prev) /* is setvec in array[0] thru array[n]? */ int **array; int *prev; { register i, j; int *ptr; for (i=0; i<=n; i++) { ptr = array[i]; if (*ptr == setcnt) { for (j=0; j < setcnt; j++) if (setvec[*(++ptr)] != 1) goto nxt; *prev = i; return(0); } nxt: ; } return(1); } int *add(n) { /* remember setvec */ int *ptr, *p; register i; if ((p = ptr = (int *) malloc((n+1)*sizeof(int))) == NULL) overflo(); *ptr = n; dprintf("add(%d)\n", n, NULL, NULL); for (i=1; i <= line; i++) if (setvec[i] == 1) { *(++ptr) = i; dprintf(" ptr = %o, *ptr = %d, i = %d\n", ptr, *ptr, i); } dprintf("\n", NULL, NULL, NULL); return(p); } struct fa *cgotofn() { register i, k; register int *ptr; char c; char *p; node *cp; int j, n, s, ind, numtrans; int finflg; int curpos, num, prev; struct fa *where[NSTATES]; int fatab[257]; struct fa *pfa; char index[MAXLIN]; char iposns[MAXLIN]; int sposns[MAXLIN]; int spmax, spinit; char symbol[NCHARS]; char isyms[NCHARS]; char ssyms[NCHARS]; int ssmax, ssinit; for (i=0; i<=line; i++) index[i] = iposns[i] = setvec[i] = 0; for (i=0; i= NSTATES) { dprintf("cgotofn: notin; state = %d, n = %d\n", state, n, NULL); overflo(); } state[++n] = add(setcnt); dprintf(" delta(%d,%o) = %d", s,c,n); dprintf(", ind = %d\n", ind+1, NULL, NULL); fatab[++ind] = c; fatab[++ind] = n; numtrans++; } else { if (prev != 0) { dprintf(" delta(%d,%o) = %d", s,c,prev); dprintf(", ind = %d\n", ind+1, NULL, NULL); fatab[++ind] = c; fatab[++ind] = prev; numtrans++; } } } tenter: if ((pfa = (struct fa *) malloc((numtrans + 1) * sizeof(struct fa))) == NULL) overflo(); where[s] = pfa; if (finflg) pfa->cch = -1; /* s is a final state */ else pfa->cch = numtrans; pfa->st = 0; for (i=1, pfa += 1; i<=numtrans; i++, pfa++) { pfa->cch = fatab[2*i-1]; pfa->st = (struct fa *) fatab[2*i]; } } for (i=0; i<=n; i++) { xfree(state[i]); /* free state[i] */ pfa = where[i]; pfa->st = where[0]; dprintf("state %d: (%o)\n", i, pfa, NULL); dprintf(" numtrans = %d, default = %o\n", pfa->cch, pfa->st, NULL); for (k=1; k<=pfa->cch; k++) { (pfa+k)->st = where[ (int) (pfa+k)->st]; dprintf(" char = %o, nextstate = %o\n",(pfa+k)->cch, (pfa+k)->st, NULL); } } pfa = where[0]; if ((num = pfa->cch) < 0) return(where[0]); for (pfa += num; num; num--, pfa--) if (pfa->cch == HAT) { return(pfa->st); } return(where[0]); } match(pfa, p) register struct fa *pfa; register char *p; { register count; char c; if (p == 0) return(0); if (pfa->cch == 1) { /* fast test for first character, if possible */ c = (++pfa)->cch; do if (c == *p) { p++; pfa = pfa->st; goto adv; } while (*p++ != 0); return(0); } adv: if ((count = pfa->cch) < 0) return(1); do { for (pfa += count; count; count--, pfa--) if (pfa->cch == *p) { break; } pfa = pfa->st; if ((count = pfa->cch) < 0) return(1); } while(*p++ != 0); return(0); } if (ins < NUMSYSCALLS && systab[ins]) printf("%8t%s", systab[ins]); else printf("%8t%d", ins); break; case TRAP: case DFAULT: default: printf("%8t%o", ins); } dotinc=incp; } doubl(a,b) { paddr("%8t",a); paddr(",",b); } branch(s,ins) char *s; register int ins; { printf(s); IF ins&020bin/awk/freeze.c 444 0 12 1130 4013202620 6764 #ifndef lint static char sccsid[] = "@(#)freeze.c 4.2 8/11/83"; #endif #include "stdio.h" freeze(s) char *s; { int fd; unsigned int *len; len = (unsigned int *)sbrk(0); if((fd = creat(s, 0666)) < 0) { perror(s); return(1); } write(fd, &len, sizeof(len)); write(fd, (char *)0, len); close(fd); return(0); } thaw(s) char *s; { int fd; unsigned int *len; if(*s == 0) { fprintf(stderr, "empty restore file\n"); return(1); } if((fd = open(s, 0)) < 0) { perror(s); return(1); } read(fd, &len, sizeof(len)); (void) brk(len); read(fd, (char *)0, len); close(fd); return(0); } etvec */ { node *p; if (type(v) == FINAL) return; p = parent(v); switch (type(p)) { case STAR: case PLUS: first(v); follow(p); return; case OR: case QUEST: follow(p); return; case CAT: if (v == left(p)) { /* v is left child of p */ if (first(right(p)) == 0) { follow(p); return; } } else /* v is right child */ follow(p); return; case FINAL: if (setvebin/awk/test.a 444 0 12 35366 4013202620 6523 ! t.0 307335954 9 3 100664 23 ` {i = i+1; print i, NR} t.1.x 307335954 9 3 100664 32 ` {i="count" $1 $2; print i , $0} t.2.x 307335954 9 3 100664 31 ` {i=2; j=$3; $1=i;print i,j,$1} t.3 307335954 9 3 100664 23 ` $1 == "5" || $1 == "4" t.3.x 307335954 9 3 100664 50 ` { x = $1 while (x > 1) { print x x = x / 10 } } t.4 307335954 9 3 100664 21 ` $1 ~ /5/ || $1 ~ /4/ t.4.x 307335954 9 3 100664 18 ` {i=$(1); print i} t.5.x 307335954 9 3 100664 28 ` {$(1) = "xxx"; print $1,$0} t.6 307335954 9 3 100664 76 ` /a|b|c/ { i = $1 print while (i >= 1) { print " ", i i = i / 10 } } t.6.x 307335955 9 3 100664 14 ` {print NF,$0} t.6a 307335955 9 3 100664 64 ` /a|b|c/ { print for (i = $1; i >= 1; ) print " ", i /= 10 } t.6b 307335955 9 3 100664 65 ` /a|b|c/ { print for (i = $1; (i /= 10)>= 1; ) print " ", i } t.8.x 307335955 9 3 100664 15 ` {$2=$1; print} t.a 307335955 9 3 100666 130 ` {if (amount[$2] "" == "") item[num++] = $2; amount[$2] += $1 } END {for (i=0; i $1 t.coerce 307335957 9 3 100664 47 ` END { print i, NR if (i < NR) print i, NR } t.comment 307335957 9 3 100664 112 ` # this is a comment line # so is this /#/ { print "this one has a # in it: " $0 # comment print "again:" $0 } t.comment1 307335957 9 3 100664 88 ` #comment # BEGIN { x = 1 } /abc/ { print $0 } #comment END { print NR } #comment t.contin 307335957 9 3 100664 130 ` { for (i = 1; i <= NF; i++) { if ($i ~ /^[0-9]+$/) continue; print $i, " is non-numeric" next } print $0, "is all numeric" } t.count 307335957 9 3 100664 17 ` END { print NR } t.cum 307335957 9 3 100664 38 ` {i = i + $1; print i} END { print i } t.d.x 307335958 9 3 100664 43 ` BEGIN {FS=":" ; OFS=":"} {print NF " ",$0} t.e 307335958 9 3 100664 23 ` $1 < 10 || $2 ~ /bwk/ t.else 307335958 9 3 100664 46 ` { if($1>1000) print "yes" else print "no" } t.exit 307335958 9 3 100664 32 ` { print } $1 < 5000 { exit NR } t.f 307335958 9 3 100664 15 ` {print $2, $1} t.f.x 307335958 9 3 100664 26 ` $1>0 {print $1, sqrt($1)} t.f0 307335959 9 3 100664 20 ` $1 ~ /x/ {print $0} t.f1 307335959 9 3 100664 16 ` {$1 = 1; print} t.f2 307335959 9 3 100664 19 ` {$1 = 1; print $0} t.f3 307335959 9 3 100664 17 ` {$1 = NR; print} t.f4 307335959 9 3 100664 20 ` {$1 = NR; print $0} t.for 307335959 9 3 100664 39 ` { for (i=1; i<=NF; i++) print i, $i } t.for1 307335959 9 3 100664 68 ` { i = 1 for (;;) { if (i > NF) next print i, $i i++ } } t.for2 307335960 9 3 100664 61 ` { for (i=1;;i++) { if (i > NF) next print i, $i } } t.format4 307335985 9 3 100664 127 ` BEGIN { text=sprintf ("%125s", "x") print length (text) print text xxx=substr (text,1,105) print length (xxx) print xxx exit } t.func 307335960 9 3 100664 73 ` { print $1, length($1), log($1), sqrt($1), int(sqrt($1)), exp($1 % 10) } t.getline 307335984 9 3 100666 117 ` { x = $1 for (i = 1; i <= 3; i++) if (getline) x = x " " $1 print x x = "" } END { if (x != "") print x } t.i.x 307335960 9 3 100664 52 ` {i=i+log($1); print i,log($1)} END {print exp(i),i} t.if 307335960 9 3 100664 21 ` {if($1 || $2) print} t.in 307335960 9 3 100664 98 ` BEGIN { x["apple"] = 1; x["orange"] = 2; x["lemon"] = 3; for (i in x) print i, x[i] exit } t.in1 307335960 9 3 100664 126 ` { if (amount[$2] == "") name[++n] = $2 amount[$2] += $1 } END { for (i in name) print i, name[i], amount[name[i]] } t.in2 307335960 9 3 100664 68 ` { x[substr($2, 1, 1)] += $1 } END { for (i in x) print i, x[i] } t.in3 307335960 9 3 100664 83 ` { x[NR] = $0 } END { for (i in x) if (x[i] ~ /shen/) break print i, x[i] } t.incr 307335960 9 3 100664 52 ` { ++i; --j; k++; l-- } END { print NR, i, j, k, l } t.incr2 307335960 9 3 100664 56 ` { s = 0 for (i=1; i <= NF; ) s += $(i++) print s } t.incr3 307335960 9 3 100664 58 ` { s = 0 for (i=1; i <= NF; s += $(i++)) ; print s } t.index 307335960 9 3 100664 144 ` { n = length d = 0 for (i = 1; i <= n; i++) if ((k = index($0, substr($0, i))) != i) d = 1 if (d) print $0, "has duplicate letters" } t.j.x 307335961 9 3 100664 55 ` {i=i+sqrt($1); print i,sqrt($1)} END {print sqrt(i),i} t.longstr 307335984 9 3 100666 137 ` BEGIN{ x = "111111111122222222233333333334444444444555555555566666666667777777777888888888899999999990000000000" printf "%s\n", x exit } t.makef 307335961 9 3 100664 30 ` {$3 = 2*$1; print $1, $2, $3} t.match 307335961 9 3 100664 15 ` $2 ~ /ava|bwk/ t.max 307335961 9 3 100664 58 ` length > max { max = length; x = $0} END { print max, x } t.mod 307335961 9 3 100664 12 ` NR % 2 == 1 t.monotone 307335961 9 3 100664 112 ` /^a?b?c?d?e?f?g?h?i?j?k?l?m?n?o?p?q?r?s?t?u?v?w?x?y?z?$|^z?y?x?w?v?u?t?s?r?q?p?o?n?m?l?k?j?i?h?g?f?e?d?c?b?a?$/ t.nameval 307335961 9 3 100664 132 ` { if (amount[$2] == "") name[++n] = $2 amount[$2] += $1 } END { for (i = 1; i <= n; i++) print name[i], amount[name[i]] } t.next 307335961 9 3 100664 29 ` $1 > 5000 { next } { print } t.not 307335961 9 3 100664 55 ` $2 !~ /ava|bwk/ !($1 < 2000) !($2 ~ /bwk/) !$2 ~ /bwk/ t.ofmt 307335961 9 3 100664 34 ` BEGIN {OFMT="%.5g"} {print $1+0} t.ofs 307335961 9 3 100664 67 ` BEGIN { OFS = " %% "; ORS = "##" } { print $1, $2; print "#x\n" } t.pipe 307335962 9 3 100664 54 ` BEGIN {print "read /usr/bwk/awk/t.pipe" | "mail bwk"} t.pp 307335962 9 3 100664 8 ` /a/,/b/ t.pp1 307335962 9 3 100664 87 ` /bwk/,/bwk/ { print $2, $1 } /ava/,/ava/ { print $2, $1 } /pjw/,/pjw/ { print $2, $1 } t.pp2 307335962 9 3 100664 99 ` /bwk/,/scj/ { print "1: ", $0 } /bwk/, /bsb/ { print "2: ", $0 } /mel/, /doug/ { print "3: ", $0 } t.printf 307335962 9 3 100664 82 ` { printf "%%: %s ... %s \t", $2, $1 x = sprintf "%8d %10.10s", $1, $2 print x } t.quote 307335962 9 3 100664 21 ` {print "\"" $1 "\""} t.re1 307335962 9 3 100664 98 ` /[a-cg-j1-3]/ { print $0 " matches /[a-cg-j1-3]/" } /[^aeiou]/ { print $0 " matches /[^aeiou]/" } t.rec 307335962 9 3 100664 19 ` { print sqrt($1) } t.redir 307335962 9 3 100664 55 ` $1%2==1 {print >"oddtemp"} $1%2==0 {print >"eventemp"} t.roff 307335962 9 3 100664 251 ` NF > 0 { for (i = 1; i <= NF; i++) { n = length($i) if (n + olen >= 60) { print oline olen = n oline = $i } else { oline = oline " " $i olen += n } } } NF == 0 { print oline olen = 0 } END { if (olen > 0) print oline } t.sep 307335962 9 3 100664 90 ` BEGIN { FS = "1"; print "field separator is", FS } NF>1 { print $0 " has " NF " fields" } t.seqno 307335962 9 3 100664 15 ` {print NR, $0} t.split 307335962 9 3 100664 64 ` BEGIN { z = "stuff" } { split ($0, x); print x[3], x[2], x[1] } t.split2 307335962 9 3 100664 36 ` { split ($0, x); print x[2], x[1] } t.split9 307334948 9 3 100666 145 ` { n = split ($0, x, FS) if (n != NF) print "botch at ", NR, n, NF for (i=1; i<=n; i++) if ($i != x[i]) print "diff at ", i, x[i], $i } t.split9a 307336346 9 3 100666 164 ` BEGIN { FS = "a" } { n = split ($0, x, FS) if (n != NF) print "botch at ", NR, n, NF for (i=1; i<=n; i++) if ($i != x[i]) print "diff at ", i, x[i], $i } t.stately 307335962 9 3 100664 159 ` /^(al|ak|az|ar|ca|co|ct|de|fl|ga|hi|io|il|in|ia|ks|ky|la|me|md|ma|mi|mn|ms|mo|mt|nb|nv|nh|nj|nm|ny|nc|nd|oh|ok|or|pa|ri|sc|sd|tn|tx|ut|vt|va|wa|wv|wi|-|wy)*$/ t.strcmp 307335963 9 3 100664 42 ` $2 >= "ava" && $2 <= "bwk" || $2 >= "pjw" t.strcmp1 307335963 9 3 100664 52 ` $1 != 1 && $1 != 2 && $1 != 3 && $1 != 4 && $1 != 5 t.substr 307335963 9 3 100664 61 ` substr($2, 1, 1) ~ /[abc]/ substr($2, length($2)) !~ /[a-z]/ t.time 307335963 9 3 100664 96 ` BEGIN { FS = "-" } /ing$/ { n++ s += length($NF) print } END { print n, s, s/n >"glop" } t.vf 307335983 9 3 100664 44 ` BEGIN { i = 1 } {print $(i+i)} {print $(1)} t.vf1 307335983 9 3 100664 66 ` { print i = 1 while (i <= NF) { print " " $i i = i + 1 } } t.vf3 307335984 9 3 100664 36 ` BEGIN { i=1; j=2 } {$i = $j; print} t.x 307335984 9 3 100664 4 ` /x/ Compare 308460881 9 1 100777 165 ` for i do echo $i: awk -f $i foo >junk1 a.out -f $i foo >junk2 if cmp -s junk1 junk2 then echo $i: good else echo $i: BAD fi diff -b junk1 junk2 | ind done testall 307336168 9 3 100777 27 ` Compare t.* >test.out 2>&1 t.null0 312829527 9 1 100666 397 ` BEGIN { FS = ":" } { if (a) print "a", a if (b == 0) print "b", b if ( c == "0") print "c", c if (d == "") print "d", d if (e == 1-1) print "e", e } $1 == 0 {print "$1 = 0"} $1 == "0" {print "$1 = quoted 0"} $1 == "" {print "$1 = null string"} $5 == 0 {print "$5 = 0"} $5 == "0" {print "$5 = quoted 0"} $5 == "" {print "$5 = null string"} $1 == $3 {print "$1 = $3"} $5 == $6 {print "$5 = $6"} test.data 323961880 9 3 100666 1429 ` /dev/rrp3: 17379 mel 16693 bwk 16116 ken 15713 srb 11895 lem 10409 scj 10252 rhm 9853 shen 9748 a68 9492 sif 9190 pjw 8912 nls 8895 dmr 8491 cda 8372 bs 8252 llc 7450 mb 7360 ava 7273 jrv 7080 bin 7063 greg 6567 dict 6462 lck 6291 rje 6211 lwf 5671 dave 5373 jhc 5220 agf 5167 doug 5007 valerie 3963 jca 3895 bbs 3796 moh 3481 xchar 3200 tbl 2845 s 2774 tgs 2641 met 2566 jck 2511 port 2479 sue 2127 root 1989 bsb 1989 jeg 1933 eag 1801 pdj 1590 tpc 1385 cvw 1370 rwm 1316 avg 1205 eg 1194 jam 1153 dl 1150 lgm 1031 cmb 1018 jwr 950 gdb 931 marc 898 usg 865 ggr 822 daemon 803 mihalis 700 honey 624 tad 559 acs 541 uucp 523 raf 495 adh 456 kec 414 craig 386 donmac 375 jj 348 ravi 344 drw 327 stars 288 mrg 272 jcb 263 ralph 253 tom 251 sjb 248 haight 224 sharon 222 chuck 213 dsj 201 bill 184 god 176 sys 166 meh 163 jon 144 dan 143 fox 123 dale 116 kab 95 buz 80 asc 79 jas 79 trt 64 wsb 62 dwh 56 ktf 54 lr 47 dlc 45 dls 45 jwf 44 mash 43 ars 43 vgl 37 jfo 32 rab 31 pd 29 jns 25 spm 22 rob 15 egb 10 hm 10 mhb 6 aed 6 cpb 5 evp 4 ber 4 men 4 mitch 3 ast 3 jfr 3 lax 3 nel 2 blue 2 jfk 2 njas 1 122sec 1 ddwar 1 gopi 1 jk 1 learn 1 low 1 nac 1 sidor t i } t.d.x 307335958 9 3 100664 43 ` BEGIN {FS=":" ; OFS=":"} {print NF " ",$0} t.e 307335958 9 3 100664 23 ` $1 < 10 || $2 ~ /bwk/ t.else 307335958 9 3 100664 46 ` { if($1>1000bin/awk/lib.c 444 0 12 14137 4013202621 6306 #ifndef lint static char sccsid[] = "@(#)lib.c 4.4 9/17/84"; #endif #include "stdio.h" #include "awk.def" #include "awk.h" #include "ctype.h" FILE *infile = NULL; char *file; #define RECSIZE (5 * 512) char record[RECSIZE]; char fields[RECSIZE]; char EMPTY[] = ""; #define MAXFLD 100 int donefld; /* 1 = implies rec broken into fields */ int donerec; /* 1 = record is valid (no flds have changed) */ int mustfld; /* 1 = NF seen, so always break*/ #define FINIT {EMPTY, EMPTY, 0.0, FLD|STR} cell fldtab[MAXFLD] = { /*room for fields */ { "$record", record, 0.0, STR|FLD}, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT, FINIT }; int maxfld = 0; /* last used field */ getrec() { register char *rr; extern int svargc; extern char **svargv; register c, sep; dprintf("**RS=%o, **FS=%o\n", **RS, **FS, NULL); donefld = 0; donerec = 1; record[0] = 0; while (svargc > 0) { dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL); if (infile == NULL) { /* have to open a new file */ if (member('=', *svargv)) { /* it's a var=value argument */ setclvar(*svargv); svargv++; svargc--; continue; } *FILENAME = file = *svargv; dprintf("opening file %s\n", file, NULL, NULL); if (*file == '-') infile = stdin; else if ((infile = fopen(file, "r")) == NULL) error(FATAL, "can't open %s", file); } if ((sep = **RS) == 0) sep = '\n'; for (rr = record; ; ) { for (; (c=getc(infile)) != sep && c != EOF; *rr++ = c) ; if (**RS == sep || c == EOF) break; if ((c = getc(infile)) == '\n' || c == EOF) /* 2 in a row */ break; *rr++ = '\n'; *rr++ = c; } if (rr > record+RECSIZE) error(FATAL, "record `%.20s...' too long", record); *rr = 0; if (mustfld) fldbld(); if (c != EOF || rr > record) { /* normal record */ recloc->tval &= ~NUM; recloc->tval |= STR; ++nrloc->fval; nrloc->tval &= ~STR; nrloc->tval |= NUM; return(1); } /* EOF arrived on this file; set up next */ if (infile != stdin) fclose(infile); infile = NULL; svargc--; svargv++; } return(0); /* true end of file */ } setclvar(s) /* set var=value from s */ char *s; { char *p; cell *q; for (p=s; *p != '='; p++) ; *p++ = 0; q = setsymtab(s, tostring(p), 0.0, STR, symtab); setsval(q, p); dprintf("command line set %s to |%s|\n", s, p, NULL); } fldbld() { register char *r, *fr, sep; int i, j; r = record; fr = fields; i = 0; /* number of fields accumulated here */ if ((sep = **FS) == ' ') for (i = 0; ; ) { while (*r == ' ' || *r == '\t' || *r == '\n') r++; if (*r == 0) break; i++; if (i >= MAXFLD) error(FATAL, "record `%.20s...' has too many fields", record); if (!(fldtab[i].tval&FLD)) strfree(fldtab[i].sval); fldtab[i].sval = fr; fldtab[i].tval = FLD | STR; do *fr++ = *r++; while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0'); *fr++ = 0; } else if (*r != 0) /* if 0, it's a null field */ for (;;) { i++; if (i >= MAXFLD) error(FATAL, "record `%.20s...' has too many fields", record); if (!(fldtab[i].tval&FLD)) strfree(fldtab[i].sval); fldtab[i].sval = fr; fldtab[i].tval = FLD | STR; while (*r != sep && *r != '\n' && *r != '\0') /* \n always a separator */ *fr++ = *r++; *fr++ = 0; if (*r++ == 0) break; } *fr = 0; for (j=MAXFLD-1; j>i; j--) { /* clean out junk from previous record */ if (!(fldtab[j].tval&FLD)) strfree(fldtab[j].sval); fldtab[j].tval = STR | FLD; fldtab[j].sval = EMPTY; } maxfld = i; donefld = 1; for(i=1; i<=maxfld; i++) if(isnumber(fldtab[i].sval)) { fldtab[i].fval = atof(fldtab[i].sval); fldtab[i].tval |= NUM; } setfval(lookup("NF", symtab, 0), (awkfloat) maxfld); if (dbg) for (i = 0; i <= maxfld; i++) printf("field %d: |%s|\n", i, fldtab[i].sval); } recbld() { int i; register char *r, *p; if (donefld == 0 || donerec == 1) return; r = record; for (i = 1; i <= *NF; i++) { p = getsval(&fldtab[i]); while (*r++ = *p++) ; *(r-1) = **OFS; } *(r-1) = '\0'; dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL); recloc->tval = STR | FLD; dprintf("in recbld FS=%o, recloc=%o\n", **FS, recloc, NULL); if (r > record+RECSIZE) error(FATAL, "built giant record `%.20s...'", record); dprintf("recbld = |%s|\n", record, NULL, NULL); } cell *fieldadr(n) { if (n >= MAXFLD) error(FATAL, "trying to access field %d", n); return(&fldtab[n]); } int errorflag = 0; yyerror(s) char *s; { fprintf(stderr, "awk: %s near line %d\n", s, lineno); errorflag = 2; } error(f, s, a1, a2, a3, a4, a5, a6, a7) { fprintf(stderr, "awk: "); fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7); fprintf(stderr, "\n"); if (NR && *NR > 0) fprintf(stderr, " record number %g\n", *NR); if (f) exit(2); } PUTS(s) char *s; { dprintf("%s\n", s, NULL, NULL); } #define MAXEXPON 38 /* maximum exponenet for fp number */ isnumber(s) register char *s; { register d1, d2; int point; char *es; if (s == NULL) return (0); d1 = d2 = point = 0; while (*s == ' ' || *s == '\t' || *s == '\n') s++; if (*s == '\0') return(0); /* empty stuff isn't number */ if (*s == '+' || *s == '-') s++; if (!isdigit(*s) && *s != '.') return(0); if (isdigit(*s)) { do { d1++; s++; } while (isdigit(*s)); } if(d1 >= MAXEXPON) return(0); /* too many digits to convert */ if (*s == '.') { point++; s++; } if (isdigit(*s)) { d2++; do { s++; } while (isdigit(*s)); } if (!(d1 || point && d2)) return(0); if (*s == 'e' || *s == 'E') { s++; if (*s == '+' || *s == '-') s++; if (!isdigit(*s)) return(0); es = s; do { s++; } while (isdigit(*s)); if (s - es > 2) return(0); else if (s - es == 2 && 10 * (*es-'0') + *(es+1)-'0' >= MAXEXPON) return(0); } while (*s == ' ' || *s == '\t' || *s == '\n') s++; if (*s == '\0') return(1); else return(0); } /* isnumber(s) char *s; {return(0);} */ = 0; donerec = 1; record[0] = 0; while (svargc > 0) { dprintf("svargc=%d, *svargv=%s\n", svargc, *svargv, NULL); if (infile == NULL) { /* have to open a new file */ if (member('=', *svargv)) { /* it's a var=value argument */ setclvar(*svargv); svargv++; svargc--; continue; } *FILENAME = file = *svargv; dprintf("opening file %s\n", file, NULL, NULL); if (*file == '-') infilbin/awk/README 444 0 12 5636 4013202621 6240 CHANGES as of July 12: 1. \ddd allowed in regular expressions. 2. exit causes the expression to to be the status return upon completion. 3. a new builtin called "getline" causes the next input line to be read immediately. Fields, NR, etc., are all set, but you are left at exactly the same place in the awk program. Getline returns 0 for end of file; 1 for a normal record. CHANGES SINCE MEMO: Update to TM of Sept 1, 1978: 1. A new form of for loop for (i in array) statement is now available. It provides a way to walk along the members of an array, most usefully for associative arrays with non-numeric subscripts. Elements are accessed in an unpredictable order, so don't count on anything. Futhermore, havoc ensues if elements are created during this operation, or if the index variable is fiddled. 2. index(s1, s2) returns the position in s1 where s2 first occurs, or 0 if it doesn't. 3. Multi-line records are now supported more conveniently. If the record separator is null RS = "" then a blank line terminates a record, and newline is a default field separator, along with blank and tab. 4. The syntax of split has been changed. n = split(str, arrayname, sep) splits the string str into the array using the separator sep (a single character). If no sep field is given, FS is used instead. The elements are array[1] ... array[n]; n is the function value. 5. some minor bugs have been fixed. IMPLEMENTATION NOTES: Things to watch out for when trying to make awk: 1. The yacc -d business creates a new file y.tab.h with the yacc #defines in it. this is compared to awk.h on each successive compile, and major recompilation is done only if the files differ. (This permits editing the grammar file without causing everything in sight to be recompiled, so long as the definitions don't change.) 2. The program proc.c is compiled into proc, which is used to create proctab.c. proctab.c is the table of function pointers used by run to actually execute things. Don't try to load proc.c with the other .c files; it also contains a "main()". 3. Awk uses structure assignment. Be sure your version of the C compiler has it. 4. The loader flag -lm is used to fetch the standard math library on the Research system. It is more likely that you will want to use -lS on yours. run.c also includes "math.h", which contains sensible definitions for log(), sqrt(), etc. If you don't have this include file, comment the line out, and all will be well anyway. 5. The basic sequence of events (in case make doesn't seem to do the job) is yacc -d awk.g.y cc -O -c y.tab.c mv y.tab.o awk.g.o lex awk.lx.l cc -O -c lex.yy.c mv lex.yy.o awk.lx.o cc -O -c b.c cc -O -c main.c e - proctab.c cc -O -c proctab.c cc -i -O awk.g.o awk.lx.o b.o main.o token.o tran.o lib.o run.o parse.o proctab.o -lm elds", record); if (!(fldtab[i].tval&FLD)) strfree(fldtab[i].sval); fldtab[i].sval = fr;bin/awk/EXPLAIN 444 0 12 5146 4013202621 6377 Nov 30, 1979: Awk has been modified yet again, in an attempt to make its behavior more rational and predictable in the areas of initialization, comparison, and type coercion. Herewith what we believe the current truth to be: 1. Each variable and field can potentially be a string or a number or both at any time. When a variable is set by the assignment v = expr its type is set to that of expr. (This includes +=, ++, etc.) An arithmetic expression is of type number, a concatenation is of type string, and so on. If the assignment is a simple copy, as in v1 = v2 then the type of v1 becomes that of v2. 2. In comparisons, if both operands are numeric, the comparison is made numerically. Otherwise, operands are coerced to string if necessary, and the comparison is made on strings. 3. The type of any expression can be coerced to numeric by subterfuges (kludges?) such as expr + 0 and to string by expr "" (i.e., concatenation with a null string). 4. Uninitialized variables have the numeric value 0 and the string value "". Accordingly, if x is uninitialized, if (x) ... is false, and if (!x) ... if (x == 0) ... if (x == "") ... are all true. But note that if (x == "0") ... is false. 5. The type of a field is determined by context when possible; for example, $1++ clearly implies that $1 is to be numeric, and $1 = $1 "," $2 implies that $1 and $2 are both to be strings. Coercion will be done as needed. In contexts where types cannot be reliably determined, e.g., if ($1 == $2) ... the type of each field is determined on input by inspection. All fields are strings; in addition, each field that contains only a number (in the sense of Fortran, say) is also considered numeric. This ensures (for better or worse) that the test if ($1 == $2) ... will succeed on the inputs 0 0.0 100 1e2 +100 100 1e-3 1e-3 and fail on the inputs (null) 0 (null) 0.0 2E-518 6E-427 as we believe it should. Fields which are explicitly null have the string value ""; they are not numeric. Non-existent fields (i.e., fields past NF) are treated this way too. As it is for fields, so it is for array elements created by split(...). 6. There is no warranty of merchantability nor any warranty of fitness for a particular purpose nor any other warranty, either express or implied, as to the accuracy of the enclosed materials or as to their suitability for any particular purpose. Accordingly, the AWK Development Task Force assumes no responsibility for their use by the recipient. Further, the Task Force assumes no obligation to furnish any assistance of any kind whatsoever, or to furnish any additional information or documentation. awk.lx.o cc -O -c b.c cc -O -c main.c e - proctab.c cc -O -c proctab.c cc -i -O awk.g.o awk.lx.o b.o main.o token.o tran.o lib.o run.o parse.o proctab.o -lm elds", record); if (!(fldtab[i].tval&FLD)) strfree(fldtab[i].sval); fldtab[i].sval = fr;bin/awk/tokenscript 444 0 12 170 4013202621 7614 e y.tab.h 1,$s/# *define *// 1,$s/^/"/ 1,$s/ /", / 1,$s/$/,/ w! temp e token.c /= *{$/+1,/^};$/-1d -r temp w! token.c q  tokenscripttaÊawk.g.yipÉawk.defipÈmain.cipÇparse.cipÆproc.cipÅMakefilepÄ run.cÃawk.lx.lpÂtoken.cpÁôtran.cpbin/awk/awk.g.y 444 0 12 20262 4013202621 6571 /* awk.g.y 4.1 82/05/07 */ %token FIRSTTOKEN /*must be first*/ %token FINAL FATAL %token LT LE GT GE EQ NE %token MATCH NOTMATCH %token APPEND %token ADD MINUS MULT DIVIDE MOD UMINUS %token ASSIGN ADDEQ SUBEQ MULTEQ DIVEQ MODEQ %token JUMP %token XBEGIN XEND %token NL %token PRINT PRINTF SPRINTF SPLIT %token IF ELSE WHILE FOR IN NEXT EXIT BREAK CONTINUE %token PROGRAM PASTAT PASTAT2 %right ASGNOP %left BOR %left AND %left NOT %left NUMBER VAR ARRAY FNCN SUBSTR LSUBSTR INDEX %left GETLINE %nonassoc RELOP MATCHOP %left OR %left STRING DOT CCL NCCL CHAR %left '(' '^' '$' %left CAT %left '+' '-' %left '*' '/' '%' %left STAR PLUS QUEST %left POSTINCR PREINCR POSTDECR PREDECR INCR DECR %left FIELD INDIRECT %token LASTTOKEN /* has to be last */ %{ #include "awk.def" #ifndef DEBUG # define PUTS(x) #endif %} %% program: begin pa_stats end { if (errorflag==0) winner = (node *)stat3(PROGRAM, $1, $2, $3); } | error { yyclearin; yyerror("bailing out"); } ; begin: XBEGIN '{' stat_list '}' { PUTS("XBEGIN list"); $$ = $3; } | begin NL | { PUTS("empty XBEGIN"); $$ = (hack)nullstat; } ; end: XEND '{' stat_list '}' { PUTS("XEND list"); $$ = $3; } | end NL | { PUTS("empty END"); $$ = (hack)nullstat; } ; compound_conditional: conditional BOR conditional { PUTS("cond||cond"); $$ = op2(BOR, $1, $3); } | conditional AND conditional { PUTS("cond&&cond"); $$ = op2(AND, $1, $3); } | NOT conditional { PUTS("!cond"); $$ = op1(NOT, $2); } | '(' compound_conditional ')' { $$ = $2; } ; compound_pattern: pattern BOR pattern { PUTS("pat||pat"); $$ = op2(BOR, $1, $3); } | pattern AND pattern { PUTS("pat&&pat"); $$ = op2(AND, $1, $3); } | NOT pattern { PUTS("!pat"); $$ = op1(NOT, $2); } | '(' compound_pattern ')' { $$ = $2; } ; conditional: expr { PUTS("expr"); $$ = op2(NE, $1, valtonode(lookup("$zero&null", symtab, 0), CCON)); } | rel_expr { PUTS("relexpr"); } | lex_expr { PUTS("lexexpr"); } | compound_conditional { PUTS("compcond"); } ; else: ELSE optNL { PUTS("else"); } ; field: FIELD { PUTS("field"); $$ = valtonode($1, CFLD); } | INDIRECT term { PUTS("ind field"); $$ = op1(INDIRECT, $2); } ; if: IF '(' conditional ')' optNL { PUTS("if(cond)"); $$ = $3; } ; lex_expr: expr MATCHOP regular_expr { PUTS("expr~re"); $$ = op2($2, $1, makedfa($3)); } | '(' lex_expr ')' { PUTS("(lex_expr)"); $$ = $2; } ; var: NUMBER {PUTS("number"); $$ = valtonode($1, CCON); } | STRING { PUTS("string"); $$ = valtonode($1, CCON); } | VAR { PUTS("var"); $$ = valtonode($1, CVAR); } | VAR '[' expr ']' { PUTS("array[]"); $$ = op2(ARRAY, $1, $3); } | field ; term: var | GETLINE { PUTS("getline"); $$ = op1(GETLINE, 0); } | FNCN { PUTS("func"); $$ = op2(FNCN, $1, valtonode(lookup("$record", symtab, 0), CFLD)); } | FNCN '(' ')' { PUTS("func()"); $$ = op2(FNCN, $1, valtonode(lookup("$record", symtab, 0), CFLD)); } | FNCN '(' expr ')' { PUTS("func(expr)"); $$ = op2(FNCN, $1, $3); } | SPRINTF print_list { PUTS("sprintf"); $$ = op1($1, $2); } | SUBSTR '(' expr ',' expr ',' expr ')' { PUTS("substr(e,e,e)"); $$ = op3(SUBSTR, $3, $5, $7); } | SUBSTR '(' expr ',' expr ')' { PUTS("substr(e,e,e)"); $$ = op3(SUBSTR, $3, $5, nullstat); } | SPLIT '(' expr ',' VAR ',' expr ')' { PUTS("split(e,e,e)"); $$ = op3(SPLIT, $3, $5, $7); } | SPLIT '(' expr ',' VAR ')' { PUTS("split(e,e,e)"); $$ = op3(SPLIT, $3, $5, nullstat); } | INDEX '(' expr ',' expr ')' { PUTS("index(e,e)"); $$ = op2(INDEX, $3, $5); } | '(' expr ')' {PUTS("(expr)"); $$ = $2; } | term '+' term { PUTS("t+t"); $$ = op2(ADD, $1, $3); } | term '-' term { PUTS("t-t"); $$ = op2(MINUS, $1, $3); } | term '*' term { PUTS("t*t"); $$ = op2(MULT, $1, $3); } | term '/' term { PUTS("t/t"); $$ = op2(DIVIDE, $1, $3); } | term '%' term { PUTS("t%t"); $$ = op2(MOD, $1, $3); } | '-' term %prec QUEST { PUTS("-term"); $$ = op1(UMINUS, $2); } | '+' term %prec QUEST { PUTS("+term"); $$ = $2; } | INCR var { PUTS("++var"); $$ = op1(PREINCR, $2); } | DECR var { PUTS("--var"); $$ = op1(PREDECR, $2); } | var INCR { PUTS("var++"); $$= op1(POSTINCR, $1); } | var DECR { PUTS("var--"); $$= op1(POSTDECR, $1); } ; expr: term { PUTS("term"); } | expr term { PUTS("expr term"); $$ = op2(CAT, $1, $2); } | var ASGNOP expr { PUTS("var=expr"); $$ = stat2($2, $1, $3); } ; optNL: NL | ; pa_stat: pattern { PUTS("pattern"); $$ = stat2(PASTAT, $1, genprint()); } | pattern '{' stat_list '}' { PUTS("pattern {...}"); $$ = stat2(PASTAT, $1, $3); } | pattern ',' pattern { PUTS("srch,srch"); $$ = pa2stat($1, $3, genprint()); } | pattern ',' pattern '{' stat_list '}' { PUTS("srch, srch {...}"); $$ = pa2stat($1, $3, $5); } | '{' stat_list '}' { PUTS("null pattern {...}"); $$ = stat2(PASTAT, nullstat, $2); } ; pa_stats: pa_stats pa_stat st { PUTS("pa_stats pa_stat"); $$ = linkum($1, $2); } | { PUTS("null pa_stat"); $$ = (hack)nullstat; } | pa_stats pa_stat {PUTS("pa_stats pa_stat"); $$ = linkum($1, $2); } ; pattern: regular_expr { PUTS("regex"); $$ = op2(MATCH, valtonode(lookup("$record", symtab, 0), CFLD), makedfa($1)); } | rel_expr { PUTS("relexpr"); } | lex_expr { PUTS("lexexpr"); } | compound_pattern { PUTS("comp pat"); } ; print_list: expr { PUTS("expr"); } | pe_list { PUTS("pe_list"); } | { PUTS("null print_list"); $$ = valtonode(lookup("$record", symtab, 0), CFLD); } ; pe_list: expr ',' expr {$$ = linkum($1, $3); } | pe_list ',' expr {$$ = linkum($1, $3); } | '(' pe_list ')' {$$ = $2; } ; redir: RELOP | '|' ; regular_expr: '/' { startreg(); } r '/' { PUTS("/r/"); $$ = $3; } ; r: CHAR { PUTS("regex CHAR"); $$ = op2(CHAR, (node *) 0, $1); } | DOT { PUTS("regex DOT"); $$ = op2(DOT, (node *) 0, (node *) 0); } | CCL { PUTS("regex CCL"); $$ = op2(CCL, (node *) 0, cclenter($1)); } | NCCL { PUTS("regex NCCL"); $$ = op2(NCCL, (node *) 0, cclenter($1)); } | '^' { PUTS("regex ^"); $$ = op2(CHAR, (node *) 0, HAT); } | '$' { PUTS("regex $"); $$ = op2(CHAR, (node *) 0 ,(node *) 0); } | r OR r { PUTS("regex OR"); $$ = op2(OR, $1, $3); } | r r %prec CAT { PUTS("regex CAT"); $$ = op2(CAT, $1, $2); } | r STAR { PUTS("regex STAR"); $$ = op2(STAR, $1, (node *) 0); } | r PLUS { PUTS("regex PLUS"); $$ = op2(PLUS, $1, (node *) 0); } | r QUEST { PUTS("regex QUEST"); $$ = op2(QUEST, $1, (node *) 0); } | '(' r ')' { PUTS("(regex)"); $$ = $2; } ; rel_expr: expr RELOP expr { PUTS("expr relop expr"); $$ = op2($2, $1, $3); } | '(' rel_expr ')' { PUTS("(relexpr)"); $$ = $2; } ; st: NL | ';' ; simple_stat: PRINT print_list redir expr { PUTS("print>stat"); $$ = stat3($1, $2, $3, $4); } | PRINT print_list { PUTS("print list"); $$ = stat3($1, $2, nullstat, nullstat); } | PRINTF print_list redir expr { PUTS("printf>stat"); $$ = stat3($1, $2, $3, $4); } | PRINTF print_list { PUTS("printf list"); $$ = stat3($1, $2, nullstat, nullstat); } | expr { PUTS("expr"); $$ = exptostat($1); } | { PUTS("null simple statement"); $$ = (hack)nullstat; } | error { yyclearin; yyerror("illegal statement"); } ; statement: simple_stat st { PUTS("simple stat"); } | if statement { PUTS("if stat"); $$ = stat3(IF, $1, $2, nullstat); } | if statement else statement { PUTS("if-else stat"); $$ = stat3(IF, $1, $2, $4); } | while statement { PUTS("while stat"); $$ = stat2(WHILE, $1, $2); } | for { PUTS("for stat"); } | NEXT st { PUTS("next"); $$ = stat1(NEXT, 0); } | EXIT st { PUTS("exit"); $$ = stat1(EXIT, 0); } | EXIT expr st { PUTS("exit"); $$ = stat1(EXIT, $2); } | BREAK st { PUTS("break"); $$ = stat1(BREAK, 0); } | CONTINUE st { PUTS("continue"); $$ = stat1(CONTINUE, 0); } | '{' stat_list '}' { PUTS("{statlist}"); $$ = $2; } ; stat_list: stat_list statement { PUTS("stat_list stat"); $$ = linkum($1, $2); } | { PUTS("null stat list"); $$ = (hack)nullstat; } ; while: WHILE '(' conditional ')' optNL { PUTS("while(cond)"); $$ = $3; } ; for: FOR '(' simple_stat ';' conditional ';' simple_stat ')' optNL statement { PUTS("for(e;e;e)"); $$ = stat4(FOR, $3, $5, $7, $10); } | FOR '(' simple_stat ';' ';' simple_stat ')' optNL statement { PUTS("for(e;e;e)"); $$ = stat4(FOR, $3, nullstat, $6, $9); } | FOR '(' VAR IN VAR ')' optNL statement { PUTS("for(v in v)"); $$ = stat3(IN, $3, $5, $8); } ; %% 9 3 100664 132 ` { if (amount[$2] == "") name[++n] = $2 amount[$2] += $1 } END { for (i = 1; i <= n; i++) print name[i], amount[name[i]] } t.next 307335961 9 3 100664 29 ` $1 > 5000 { next } { print } t.not 307335961 9 3 100664 55 ` $2 !~ /ava|bwk/ !($1bin/awk/awk.def 444 0 12 6373 4013202621 6621 /* awk.def 4.3 83/12/09 */ #define hack int #define AWKFLOAT float #define xfree(a) { if(a!=NULL) { yfree(a); a=NULL;} } #define strfree(a) { if(a!=NULL && a!=EMPTY) { yfree(a);} a=EMPTY; } #define yfree free #define isnull(x) ((x) == EMPTY || (x) == NULL) #ifdef DEBUG # define dprintf if(dbg)printf #else # define dprintf(x1, x2, x3, x4) #endif typedef AWKFLOAT awkfloat; extern char **FS; extern char **RS; extern char **ORS; extern char **OFS; extern char **OFMT; extern awkfloat *NR; extern awkfloat *NF; extern char **FILENAME; extern char record[]; extern char EMPTY[]; extern int dbg; extern int lineno; extern int errorflag; extern int donefld; /* 1 if record broken into fields */ extern int donerec; /* 1 if record is valid (no fld has changed */ typedef struct val { /* general value during processing */ char *nval; /* name, for variables only */ char *sval; /* string value */ awkfloat fval; /* value as number */ unsigned tval; /* type info */ struct val *nextval; /* ptr to next if chained */ } cell; extern cell *symtab[]; cell *setsymtab(), *lookup(), **makesymtab(); extern cell *recloc; /* location of input record */ extern cell *nrloc; /* NR */ extern cell *nfloc; /* NF */ #define STR 01 /* string value is valid */ #define NUM 02 /* number value is valid */ #define FLD 04 /* FLD means don't free string space */ #define CON 010 /* this is a constant */ #define ARR 020 /* this is an array */ awkfloat setfval(), getfval(); char *setsval(), *getsval(); char *tostring(), *tokname(), *malloc(); double log(), sqrt(), exp(), atof(); /* function types */ #define FLENGTH 1 #define FSQRT 2 #define FEXP 3 #define FLOG 4 #define FINT 5 typedef struct { char otype; char osub; cell *optr; } obj; #define BOTCH 1 struct nd { char ntype; char subtype; struct nd *nnext; int nobj; struct nd *narg[BOTCH]; /* C won't take a zero length array */ }; typedef struct nd node; extern node *winner; extern node *nullstat; /* otypes */ #define OCELL 0 #define OEXPR 1 #define OBOOL 2 #define OJUMP 3 /* cell subtypes */ #define CTEMP 4 #define CNAME 3 #define CVAR 2 #define CFLD 1 #define CCON 0 /* bool subtypes */ #define BTRUE 1 #define BFALSE 2 /* jump subtypes */ #define JEXIT 1 #define JNEXT 2 #define JBREAK 3 #define JCONT 4 /* node types */ #define NVALUE 1 #define NSTAT 2 #define NEXPR 3 #define NPA2 4 extern obj (*proctab[])(); extern obj true, false; extern int pairstack[], paircnt; #define cantexec(n) (n->ntype == NVALUE) #define notlegal(n) (n <= FIRSTTOKEN || n >= LASTTOKEN || proctab[n-FIRSTTOKEN]== nullproc) #define isexpr(n) (n->ntype == NEXPR) #define isjump(n) (n.otype == OJUMP) #define isexit(n) (n.otype == OJUMP && n.osub == JEXIT) #define isbreak(n) (n.otype == OJUMP && n.osub == JBREAK) #define iscont(n) (n.otype == OJUMP && n.osub == JCONT) #define isnext(n) (n.otype == OJUMP && n.osub == JNEXT) #define isstr(n) (n.optr->tval & STR) #define istrue(n) (n.otype == OBOOL && n.osub == BTRUE) #define istemp(n) (n.otype == OCELL && n.osub == CTEMP) #define isfld(n) (!donefld && n.osub==CFLD && n.otype==OCELL && n.optr->nval==EMPTY) #define isrec(n) (donefld && n.osub==CFLD && n.otype==OCELL && n.optr->nval!=EMPTY) obj nullproc(); obj relop(); #define MAXSYM 50 #define HAT 0177 /* matches ^ in regular expr */ /* watch out for mach dep */ = op2($2, $1, makedfa($3)); } | '(' lex_expr ')' { PUTS("(lex_expr)"); $$ = $2; } ; var: NUMBER {PUTS("number"); $$ = valtonode($1, CCON); } | STRING { PUTS("string"); $$ = valtonode($1, CCON); } | VAR { PUTS("var"); $$ = valtonode($1, CVAR); } | VARbin/awk/main.c 444 0 12 4407 4013202622 6444 #ifndef lint static char sccsid[] = "@(#)main.c 4.4 (Berkeley) 12/8/84"; #endif #include "stdio.h" #include "ctype.h" #include "awk.def" #include "awk.h" #define TOLOWER(c) (isupper(c) ? tolower(c) : c) /* ugh!!! */ int dbg = 0; int ldbg = 0; int svflg = 0; int rstflg = 0; int svargc; char **svargv, **xargv; extern FILE *yyin; /* lex input file */ char *lexprog; /* points to program argument if it exists */ extern errorflag; /* non-zero if any syntax errors; set by yyerror */ int filefd, symnum, ansfd; char *filelist; extern int maxsym, errno; main(argc, argv) int argc; char *argv[]; { if (argc == 1) error(FATAL, "Usage: awk [-f source | 'cmds'] [files]"); syminit(); while (argc > 1) { argc--; argv++; /* this nonsense is because gcos argument handling */ /* folds -F into -f. accordingly, one checks the next /* character after f to see if it's -f file or -Fx. */ if (argv[0][0] == '-' && TOLOWER(argv[0][1]) == 'f' && argv[0][2] == '\0') { yyin = fopen(argv[1], "r"); if (yyin == NULL) error(FATAL, "can't open %s", argv[1]); argc--; argv++; break; } else if (argv[0][0] == '-' && TOLOWER(argv[0][1]) == 'f') { /* set field sep */ if (argv[0][2] == 't') /* special case for tab */ **FS = '\t'; else **FS = argv[0][2]; continue; } else if (argv[0][0] != '-') { dprintf("cmds=|%s|\n", argv[0], NULL, NULL); yyin = NULL; lexprog = argv[0]; argv[0] = argv[-1]; /* need this space */ break; } else if (strcmp("-d", argv[0])==0) { dbg = 1; } else if (strcmp("-l", argv[0])==0) { ldbg = 1; } else if(strcmp("-S", argv[0]) == 0) { svflg = 1; } else if(strncmp("-R", argv[0], 2) == 0) { if(thaw(argv[0] + 2) == 0) rstflg = 1; else { fprintf(stderr, "not restored\n"); exit(1); } } } if (argc <= 1) { argv[0][0] = '-'; argv[0][1] = '\0'; argc++; argv--; } svargc = --argc; svargv = ++argv; dprintf("svargc=%d svargv[0]=%s\n", svargc, svargv[0], NULL); *FILENAME = *svargv; /* initial file name */ if(rstflg == 0) yyparse(); dprintf("errorflag=%d\n", errorflag, NULL, NULL); if (errorflag) exit(errorflag); if(svflg) { svflg = 0; if(freeze("awk.out") != 0) fprintf(stderr, "not saved\n"); exit(0); } run(); exit(errorflag); } yywrap() { return(1); } , makedfa($3)); } | '(' lex_expr ')' { PUTS("(lex_expr)"); $$ = $2; } ; var: NUMBER {PUTS("number"); $$ = valtonode($1, CCON); } | STRING { PUTS("string"); $$ = valtonode($1, CCON); } | VAR { PUTS("var"); $$ = valtonode($1, CVAR); } | VARbin/awk/parse.c 444 0 12 4524 4013202622 6632 #ifndef lint static char sccsid[] = "@(#)parse.c 4.2 8/11/83"; #endif #include "awk.def" #include "awk.h" #include "stdio.h" node *ALLOC(n) { register node *x; x = (node *) malloc(sizeof(node) + (n-1)*sizeof(node *)); if (x == NULL) error(FATAL, "out of space in ALLOC"); return(x); } node *exptostat(a) node *a; { a->ntype = NSTAT; return(a); } node *nullstat; node *node0(a) { register node *x; x=ALLOC(0); x->nnext = NULL; x->nobj=a; return(x); } node *node1(a,b) node *b; { register node *x; x=ALLOC(1); x->nnext = NULL; x->nobj=a; x->narg[0]=b; return(x); } node *node2(a,b,c) node *b, *c; { register node *x; x = ALLOC(2); x->nnext = NULL; x->nobj = a; x->narg[0] = b; x->narg[1] = c; return(x); } node *node3(a,b,c,d) node *b, *c, *d; { register node *x; x = ALLOC(3); x->nnext = NULL; x->nobj = a; x->narg[0] = b; x->narg[1] = c; x->narg[2] = d; return(x); } node *node4(a,b,c,d,e) node *b, *c, *d, *e; { register node *x; x = ALLOC(4); x->nnext = NULL; x->nobj = a; x->narg[0] = b; x->narg[1] = c; x->narg[2] = d; x->narg[3] = e; return(x); } node *stat3(a,b,c,d) node *b, *c, *d; { register node *x; x = node3(a,b,c,d); x->ntype = NSTAT; return(x); } node *op2(a,b,c) node *b, *c; { register node *x; x = node2(a,b,c); x->ntype = NEXPR; return(x); } node *op1(a,b) node *b; { register node *x; x = node1(a,b); x->ntype = NEXPR; return(x); } node *stat1(a,b) node *b; { register node *x; x = node1(a,b); x->ntype = NSTAT; return(x); } node *op3(a,b,c,d) node *b, *c, *d; { register node *x; x = node3(a,b,c,d); x->ntype = NEXPR; return(x); } node *stat2(a,b,c) node *b, *c; { register node *x; x = node2(a,b,c); x->ntype = NSTAT; return(x); } node *stat4(a,b,c,d,e) node *b, *c, *d, *e; { register node *x; x = node4(a,b,c,d,e); x->ntype = NSTAT; return(x); } node *valtonode(a, b) cell *a; { register node *x; x = node0(a); x->ntype = NVALUE; x->subtype = b; return(x); } node *pa2stat(a,b,c) node *a, *b, *c; { register node *x; x = node3(paircnt++, a, b, c); x->ntype = NPA2; return(x); } node *linkum(a,b) node *a, *b; { register node *c; if(a == NULL) return(b); else if(b == NULL) return(a); for(c=a; c->nnext != NULL; c=c->nnext); c->nnext = b; return(a); } node *genprint() { register node *x; x = stat2(PRINT,valtonode(lookup("$record", symtab, 0), CFLD), nullstat); return(x); } r: NUMBER {PUTS("number"); $$ = valtonode($1, CCON); } | STRING { PUTS("string"); $$ = valtonode($1, CCON); } | VAR { PUTS("var"); $$ = valtonode($1, CVAR); } | VARbin/awk/proc.c 444 0 12 4530 4013202622 6460 #ifndef lint static char sccsid[] = "@(#)proc.c 4.3 8/11/83"; #endif #include "awk.h" #define NULL 0 struct xx { int token; char *name; char *pname; } proc[] = { { PROGRAM, "program", NULL}, { BOR, "boolop", " || "}, { AND, "boolop", " && "}, { NOT, "boolop", " !"}, { NE, "relop", " != "}, { EQ, "relop", " == "}, { LE, "relop", " <= "}, { LT, "relop", " < "}, { GE, "relop", " >= "}, { GT, "relop", " > "}, { ARRAY, "array", NULL}, { INDIRECT, "indirect", "$("}, { SUBSTR, "substr", "substr"}, { INDEX, "sindex", "sindex"}, { SPRINTF, "asprintf", "sprintf "}, { ADD, "arith", " + "}, { MINUS, "arith", " - "}, { MULT, "arith", " * "}, { DIVIDE, "arith", " / "}, { MOD, "arith", " % "}, { UMINUS, "arith", " -"}, { PREINCR, "incrdecr", "++"}, { POSTINCR, "incrdecr", "++"}, { PREDECR, "incrdecr", "--"}, { POSTDECR, "incrdecr", "--"}, { CAT, "cat", " "}, { PASTAT, "pastat", NULL}, { PASTAT2, "dopa2", NULL}, { MATCH, "matchop", " ~ "}, { NOTMATCH, "matchop", " !~ "}, { PRINTF, "aprintf", "printf"}, { PRINT, "print", "print"}, { SPLIT, "split", "split"}, { ASSIGN, "assign", " = "}, { ADDEQ, "assign", " += "}, { SUBEQ, "assign", " -= "}, { MULTEQ, "assign", " *= "}, { DIVEQ, "assign", " /= "}, { MODEQ, "assign", " %= "}, { IF, "ifstat", "if("}, { WHILE, "whilestat", "while("}, { FOR, "forstat", "for("}, { IN, "instat", "instat"}, { NEXT, "jump", "next"}, { EXIT, "jump", "exit"}, { BREAK, "jump", "break"}, { CONTINUE, "jump", "continue"}, { FNCN, "fncn", "fncn"}, { GETLINE, "getline", "getline"}, { 0, ""}, }; #define SIZE LASTTOKEN - FIRSTTOKEN char *table[SIZE]; char *names[SIZE]; main() { struct xx *p; int i; printf("#include \"awk.def\"\n"); printf("obj nullproc();\n"); for(p=proc;p->token!=0;p++) if(p==proc || strcmp(p->name, (p-1)->name)) printf("extern obj %s();\n",p->name); for(p=proc;p->token!=0;p++) table[p->token-FIRSTTOKEN]=p->name; printf("obj (*proctab[%d])() = {\n", SIZE); for(i=0;itoken!=0; p++) names[p->token-FIRSTTOKEN] = p->pname; for(i=0; intype = NEXPR; return(x); } node *stat1(a,b) node *b; { register node *x; x = node1(a,b); x->ntype = NSTAT; return(x); } node *op3(a,b,c,d) node *b, *c, bin/awk/Makefile 444 0 12 2143 5326557236 7035 # Makefile 4.3 86/05/15 # CFLAGS=-O YFLAGS=-d SEPFLAG=-i FILES=awk.lx.o b.o main.o token.o tran.o lib.o run.o parse.o proctab.o freeze.o SOURCE=awk.def awk.g.y awk.lx.l b.c lib.c main.c parse.c \ proc.c freeze.c\ run.c token.c tran.c awk: $(FILES) awk.g.o cc $(CFLAGS) $(SEPFLAG) awk.g.o $(FILES) -lm -o awk y.tab.h: awk.g.o awk.h: y.tab.h -cmp -s y.tab.h awk.h || cp y.tab.h awk.h $(FILES): awk.h awk.def token.c: awk.h ex - proctab.c proc: awk.h proc.o token.o cc -o proc proc.o token.o clean: -rm -f *.o t.* *temp* *.out *junk* y.tab.* awk.h proc proctab.c awk yacc* diffs: -for i in $(SOURCE); do echo $$i:; diff $$i /usr/src/cmd/awk | ind; done ntf("char *printname[%d] = {\n", SIZE); for(p=proc; p->token!=0; p++) names[p->token-FIRSTTOKEN] = p->pname; for(i=0; intype = NEXPR; return(x); } node *stat1(a,b) node *b; { register node *x; x = node1(a,b); x->ntype = NSTAT; return(x); } node *op3(a,b,c,d) node *b, *c, bin/awk/run.c 444 0 12 35230 4013202622 6342 #ifndef lint static char sccsid[] = "@(#)run.c 4.5 12/4/84"; #endif #include "awk.def" #include "math.h" #include "awk.h" #include "stdio.h" #define RECSIZE BUFSIZ #define FILENUM 10 struct { FILE *fp; int type; char *fname; } files[FILENUM]; FILE *popen(); extern obj execute(), nodetoobj(), fieldel(), dopa2(), gettemp(); #define PA2NUM 29 int pairstack[PA2NUM], paircnt; node *winner = (node *)NULL; #define MAXTMP 20 cell tmps[MAXTMP]; static cell nullval ={EMPTY,EMPTY,0.0,NUM,0}; obj true ={ OBOOL, BTRUE, 0 }; obj false ={ OBOOL, BFALSE, 0 }; run() { register int i; execute(winner); /* Wait for children to complete if output to a pipe. */ for (i=0; innext) { if (cantexec(a)) return(nodetoobj(a)); if (a->ntype==NPA2) proc=dopa2; else { if (notlegal(a->nobj)) error(FATAL, "illegal statement %o", a); proc = proctab[a->nobj-FIRSTTOKEN]; } x = (*proc)(a->narg,a->nobj); if (isfld(x)) fldbld(); if (isexpr(a)) return(x); /* a statement, goto next statement */ if (isjump(x)) return(x); if (a->nnext == (node *)NULL) return(x); tempfree(x); } } obj program(a, n) node **a; { obj x; if (a[0] != NULL) { x = execute(a[0]); if (isexit(x)) return(true); if (isjump(x)) error(FATAL, "unexpected break, continue or next"); tempfree(x); } while (getrec()) { x = execute(a[1]); if (isexit(x)) break; tempfree(x); } tempfree(x); if (a[2] != NULL) { x = execute(a[2]); if (isbreak(x) || isnext(x) || iscont(x)) error(FATAL, "unexpected break, continue or next"); tempfree(x); } return(true); } obj getline() { obj x; x = gettemp(); setfval(x.optr, (awkfloat) getrec()); return(x); } obj array(a,n) node **a; { obj x, y; extern obj arrayel(); x = execute(a[1]); y = arrayel(a[0], x); tempfree(x); return(y); } obj arrayel(a,b) node *a; obj b; { char *s; cell *x; int i; obj y; s = getsval(b.optr); x = (cell *) a; if (!(x->tval&ARR)) { strfree(x->sval); x->tval &= ~STR; x->tval |= ARR; x->sval = (char *) makesymtab(); } y.optr = setsymtab(s, tostring(""), 0.0, STR|NUM, x->sval); y.otype = OCELL; y.osub = CVAR; return(y); } obj matchop(a,n) node **a; { obj x; char *s; int i; x = execute(a[0]); if (isstr(x)) s = x.optr->sval; else s = getsval(x.optr); tempfree(x); i = match(a[1], s); if (n==MATCH && i==1 || n==NOTMATCH && i==0) return(true); else return(false); } obj boolop(a,n) node **a; { obj x, y; int i; x = execute(a[0]); i = istrue(x); tempfree(x); switch (n) { default: error(FATAL, "unknown boolean operator %d", n); case BOR: if (i) return(true); y = execute(a[1]); i = istrue(y); tempfree(y); if (i) return(true); else return(false); case AND: if ( !i ) return(false); y = execute(a[1]); i = istrue(y); tempfree(y); if (i) return(true); else return(false); case NOT: if (i) return(false); else return(true); } } obj relop(a,n) node **a; { int i; obj x, y; awkfloat j; x = execute(a[0]); y = execute(a[1]); if (x.optr->tval&NUM && y.optr->tval&NUM) { j = x.optr->fval - y.optr->fval; i = j<0? -1: (j>0? 1: 0); } else { i = strcmp(getsval(x.optr), getsval(y.optr)); } tempfree(x); tempfree(y); switch (n) { default: error(FATAL, "unknown relational operator %d", n); case LT: if (i<0) return(true); else return(false); case LE: if (i<=0) return(true); else return(false); case NE: if (i!=0) return(true); else return(false); case EQ: if (i==0) return(true); else return(false); case GE: if (i>=0) return(true); else return(false); case GT: if (i>0) return(true); else return(false); } } tempfree(a) obj a; { if (!istemp(a)) return; strfree(a.optr->sval); a.optr->tval = 0; } obj gettemp() { int i; obj x; for (i=0; i k) m = k; tempfree(x); if (a[2] != nullstat) { x = execute(a[2]); n = getfval(x.optr); tempfree(x); } else n = k - 1; if (n < 0) n = 0; else if (n > k - m) n = k - m; dprintf("substr: m=%d, n=%d, s=%s\n", m, n, s); x = gettemp(); temp = s[n+m-1]; /* with thanks to John Linderman */ s[n+m-1] = '\0'; setsval(x.optr, s + m - 1); s[n+m-1] = temp; return(x); } obj sindex(a, nnn) node **a; { obj x; char *s1, *s2, *p1, *p2, *q; x = execute(a[0]); s1 = getsval(x.optr); tempfree(x); x = execute(a[1]); s2 = getsval(x.optr); tempfree(x); x = gettemp(); for (p1 = s1; *p1 != '\0'; p1++) { for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++) ; if (*p2 == '\0') { setfval(x.optr, (awkfloat) (p1 - s1 + 1)); /* origin 1 */ return(x); } } setfval(x.optr, 0.0); return(x); } char *format(s,a) char *s; node *a; { char *buf, *p, fmt[200], *t, *os; obj x; int flag = 0; awkfloat xf; os = s; p = buf = (char *)malloc(RECSIZE); while (*s) { if (*s != '%') { *p++ = *s++; continue; } if (*(s+1) == '%') { *p++ = '%'; s += 2; continue; } for (t=fmt; (*t++ = *s) != '\0'; s++) if (*s >= 'a' && *s <= 'z' && *s != 'l') break; *t = '\0'; if (t >= fmt + sizeof(fmt)) error(FATAL, "format item %.20s... too long", os); switch (*s) { case 'f': case 'e': case 'g': flag = 1; break; case 'd': flag = 2; if(*(s-1) == 'l') break; *(t-1) = 'l'; *t = 'd'; *++t = '\0'; break; case 'o': case 'x': flag = *(s-1)=='l' ? 2 : 3; break; case 'c': flag = 3; break; case 's': flag = 4; break; default: flag = 0; break; } if (flag == 0) { sprintf(p, "%s", fmt); p += strlen(p); continue; } if (a == NULL) error(FATAL, "not enough arguments in printf(%s)", os); x = execute(a); a = a->nnext; if (flag != 4) /* watch out for converting to numbers! */ xf = getfval(x.optr); if (flag==1) sprintf(p, fmt, xf); else if (flag==2) sprintf(p, fmt, (long)xf); else if (flag==3) sprintf(p, fmt, (int)xf); else if (flag==4) sprintf(p, fmt, x.optr->sval==NULL ? "" : getsval(x.optr)); tempfree(x); p += strlen(p); s++; } *p = '\0'; return(buf); } obj asprintf(a,n) node **a; { obj x; node *y; char *s; y = a[0]->nnext; x = execute(a[0]); s = format(getsval(x.optr), y); tempfree(x); x = gettemp(); x.optr->sval = s; x.optr->tval = STR; return(x); } obj arith(a,n) node **a; { awkfloat i,j; obj x,y,z; x = execute(a[0]); i = getfval(x.optr); tempfree(x); if (n != UMINUS) { y = execute(a[1]); j = getfval(y.optr); tempfree(y); } z = gettemp(); switch (n) { default: error(FATAL, "illegal arithmetic operator %d", n); case ADD: i += j; break; case MINUS: i -= j; break; case MULT: i *= j; break; case DIVIDE: if (j == 0) error(FATAL, "division by zero"); i /= j; break; case MOD: if (j == 0) error(FATAL, "division by zero"); i = i - j*(long)(i/j); break; case UMINUS: i = -i; break; } setfval(z.optr, i); return(z); } obj incrdecr(a, n) node **a; { obj x, z; int k; awkfloat xf; x = execute(a[0]); xf = getfval(x.optr); k = (n == PREINCR || n == POSTINCR) ? 1 : -1; if (n == PREINCR || n == PREDECR) { setfval(x.optr, xf + k); return(x); } z = gettemp(); setfval(z.optr, xf); setfval(x.optr, xf + k); tempfree(x); return(z); } obj assign(a,n) node **a; { obj x, y; awkfloat xf, yf; x = execute(a[0]); y = execute(a[1]); if (n == ASSIGN) { /* ordinary assignment */ if ((y.optr->tval & (STR|NUM)) == (STR|NUM)) { setsval(x.optr, y.optr->sval); x.optr->fval = y.optr->fval; x.optr->tval |= NUM; } else if (y.optr->tval & STR) setsval(x.optr, y.optr->sval); else if (y.optr->tval & NUM) setfval(x.optr, y.optr->fval); tempfree(y); return(x); } xf = getfval(x.optr); yf = getfval(y.optr); switch (n) { case ADDEQ: xf += yf; break; case SUBEQ: xf -= yf; break; case MULTEQ: xf *= yf; break; case DIVEQ: if (yf == 0) error(FATAL, "division by zero"); xf /= yf; break; case MODEQ: if (yf == 0) error(FATAL, "division by zero"); xf = xf - yf*(long)(xf/yf); break; default: error(FATAL, "illegal assignment operator %d", n); break; } tempfree(y); setfval(x.optr, xf); return(x); } obj cat(a,q) node **a; { obj x,y,z; int n1, n2; char *s; x = execute(a[0]); y = execute(a[1]); getsval(x.optr); getsval(y.optr); n1 = strlen(x.optr->sval); n2 = strlen(y.optr->sval); s = (char *) malloc(n1 + n2 + 1); strcpy(s, x.optr->sval); strcpy(s+n1, y.optr->sval); tempfree(y); z = gettemp(); z.optr->sval = s; z.optr->tval = STR; tempfree(x); return(z); } obj pastat(a,n) node **a; { obj x; if (a[0]==nullstat) x = true; else x = execute(a[0]); if (istrue(x)) { tempfree(x); x = execute(a[1]); } return(x); } obj dopa2(a,n) node **a; { obj x; if (pairstack[n]==0) { x = execute(a[0]); if (istrue(x)) pairstack[n] = 1; tempfree(x); } if (pairstack[n] == 1) { x = execute(a[1]); if (istrue(x)) pairstack[n] = 0; tempfree(x); x = execute(a[2]); return(x); } return(false); } obj aprintf(a,n) node **a; { obj x; x = asprintf(a,n); if (a[1]==NULL) { printf("%s", x.optr->sval); tempfree(x); return(true); } redirprint(x.optr->sval, (int)a[1], a[2]); return(x); } obj split(a,nnn) node **a; { obj x; cell *ap; register char *s, *p; char *t, temp, num[5]; register int sep; int n, flag; x = execute(a[0]); s = getsval(x.optr); tempfree(x); if (a[2] == nullstat) sep = **FS; else { x = execute(a[2]); sep = getsval(x.optr)[0]; tempfree(x); } ap = (cell *) a[1]; freesymtab(ap); dprintf("split: s=|%s|, a=%s, sep=|%c|\n", s, ap->nval, sep); ap->tval &= ~STR; ap->tval |= ARR; ap->sval = (char *) makesymtab(); n = 0; if (sep == ' ') for (n = 0; ; ) { while (*s == ' ' || *s == '\t' || *s == '\n') s++; if (*s == 0) break; n++; t = s; do s++; while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0'); temp = *s; *s = '\0'; sprintf(num, "%d", n); if (isnumber(t)) setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval); else setsymtab(num, tostring(t), 0.0, STR, ap->sval); *s = temp; if (*s != 0) s++; } else if (*s != 0) for (;;) { n++; t = s; while (*s != sep && *s != '\n' && *s != '\0') s++; temp = *s; *s = '\0'; sprintf(num, "%d", n); if (isnumber(t)) setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval); else setsymtab(num, tostring(t), 0.0, STR, ap->sval); *s = temp; if (*s++ == 0) break; } x = gettemp(); x.optr->tval = NUM; x.optr->fval = n; return(x); } obj ifstat(a,n) node **a; { obj x; x = execute(a[0]); if (istrue(x)) { tempfree(x); x = execute(a[1]); } else if (a[2] != nullstat) { tempfree(x); x = execute(a[2]); } return(x); } obj whilestat(a,n) node **a; { obj x; for (;;) { x = execute(a[0]); if (!istrue(x)) return(x); tempfree(x); x = execute(a[1]); if (isbreak(x)) { x = true; return(x); } if (isnext(x) || isexit(x)) return(x); tempfree(x); } } obj forstat(a,n) node **a; { obj x; tempfree(execute(a[0])); for (;;) { if (a[1]!=nullstat) { x = execute(a[1]); if (!istrue(x)) return(x); else tempfree(x); } x = execute(a[3]); if (isbreak(x)) { /* turn off break */ x = true; return(x); } if (isnext(x) || isexit(x)) return(x); tempfree(x); tempfree(execute(a[2])); } } obj instat(a, n) node **a; { cell *vp, *arrayp, *cp, **tp; obj x; int i; vp = (cell *) a[0]; arrayp = (cell *) a[1]; if (!(arrayp->tval & ARR)) error(FATAL, "%s is not an array", arrayp->nval); tp = (cell **) arrayp->sval; for (i = 0; i < MAXSYM; i++) { /* this routine knows too much */ for (cp = tp[i]; cp != NULL; cp = cp->nextval) { setsval(vp, cp->nval); x = execute(a[2]); if (isbreak(x)) { x = true; return(x); } if (isnext(x) || isexit(x)) return(x); tempfree(x); } } return (true); } obj jump(a,n) node **a; { obj x, y; x.otype = OJUMP; switch (n) { default: error(FATAL, "illegal jump type %d", n); break; case EXIT: if (a[0] != 0) { y = execute(a[0]); errorflag = getfval(y.optr); } x.osub = JEXIT; break; case NEXT: x.osub = JNEXT; break; case BREAK: x.osub = JBREAK; break; case CONTINUE: x.osub = JCONT; break; } return(x); } obj fncn(a,n) node **a; { obj x; awkfloat u; int t; t = (int) a[0]; x = execute(a[1]); if (t == FLENGTH) u = (awkfloat) strlen(getsval(x.optr)); else if (t == FLOG) u = log(getfval(x.optr)); else if (t == FINT) u = (awkfloat) (long) getfval(x.optr); else if (t == FEXP) u = exp(getfval(x.optr)); else if (t == FSQRT) u = sqrt(getfval(x.optr)); else error(FATAL, "illegal function type %d", t); tempfree(x); x = gettemp(); setfval(x.optr, u); return(x); } obj print(a,n) node **a; { register node *x; obj y; char s[RECSIZE]; s[0] = '\0'; for (x=a[0]; x!=NULL; x=x->nnext) { y = execute(x); strcat(s, getsval(y.optr)); tempfree(y); if (x->nnext==NULL) strcat(s, *ORS); else strcat(s, *OFS); } if (strlen(s) >= RECSIZE) error(FATAL, "string %.20s ... too long to print", s); if (a[1]==nullstat) { printf("%s", s); return(true); } redirprint(s, (int)a[1], a[2]); return(false); } obj nullproc() {} obj nodetoobj(a) node *a; { obj x; x.optr = (cell *) a->nobj; x.otype = OCELL; x.osub = a->subtype; if (isfld(x)) fldbld(); return(x); } redirprint(s, a, b) char *s; node *b; { register int i; obj x; x = execute(b); getsval(x.optr); for (i=0; isval, files[i].fname) == 0) goto doit; for (i=0; i= FILENUM) error(FATAL, "too many output files %d", i); if (a == '|') /* a pipe! */ files[i].fp = popen(x.optr->sval, "w"); else if (a == APPEND) files[i].fp = fopen(x.optr->sval, "a"); else files[i].fp = fopen(x.optr->sval, "w"); if (files[i].fp == NULL) error(FATAL, "can't open file %s", x.optr->sval); files[i].fname = tostring(x.optr->sval); files[i].type = a; doit: fprintf(files[i].fp, "%s", s); #ifndef gcos fflush(files[i].fp); /* in case someone is waiting for the output */ #endif tempfree(x); } 961 9 3 100664 67 ` BEGIN { OFS = " %% "; ORS = "##" } { print $1, $2; print "#x\n" } t.pipe 307335962 9 3 100664 54 ` BEGIN {print "read /usr/bwk/awk/t.pipe" | "mail bwk"} t.pp 307335962 9 3 100664 8 ` /a/,/b/ t.pp1 307335962 9 3 100664 87 ` /bwk/,/bwk/ bin/awk/awk.lx.l 444 0 12 12111 4013202623 6745 /* awk.lx.l 4.3 84/12/08 */ %Start A str chc sc reg comment %{ #include "awk.h" #include "awk.def" #undef input /* defeat lex */ extern int yylval; extern int mustfld; extern int ldbg; int lineno = 1; #define RETURN(x) {if (ldbg) ptoken(x); return(x); } #define CADD cbuf[clen++]=yytext[0]; if(clen>=CBUFLEN-1) {yyerror("string too long", cbuf); BEGIN A;} #define CBUFLEN 150 char cbuf[CBUFLEN]; int clen, cflag; %} A [a-zA-Z_] B [a-zA-Z0-9_] D [0-9] WS [ \t] %% switch (yybgin-yysvec-1) { /* witchcraft */ case 0: BEGIN A; break; case sc: BEGIN A; RETURN('}'); } ^\n lineno++; ^{WS}*#.*\n lineno++; /* strip comment lines */ {WS} ; "\\"\n lineno++; "||" RETURN(BOR); BEGIN RETURN(XBEGIN); END RETURN(XEND); PROGEND RETURN(EOF); "&&" RETURN(AND); "!" RETURN(NOT); "!=" { yylval = NE; RETURN(RELOP); } "~" { yylval = MATCH; RETURN(MATCHOP); } "!~" { yylval = NOTMATCH; RETURN(MATCHOP); } "<" { yylval = LT; RETURN(RELOP); } "<=" { yylval = LE; RETURN(RELOP); } "==" { yylval = EQ; RETURN(RELOP); } ">=" { yylval = GE; RETURN(RELOP); } ">" { yylval = GT; RETURN(RELOP); } ">>" { yylval = APPEND; RETURN(RELOP); } "++" { yylval = INCR; RETURN(INCR); } "--" { yylval = DECR; RETURN(DECR); } "+=" { yylval = ADDEQ; RETURN(ASGNOP); } "-=" { yylval = SUBEQ; RETURN(ASGNOP); } "*=" { yylval = MULTEQ; RETURN(ASGNOP); } "/=" { yylval = DIVEQ; RETURN(ASGNOP); } "%=" { yylval = MODEQ; RETURN(ASGNOP); } "=" { yylval = ASSIGN; RETURN(ASGNOP); } "$"{D}+ { if (atoi(yytext+1)==0) { yylval = (hack)lookup("$record", symtab, 0); RETURN(STRING); } else { yylval = fieldadr(atoi(yytext+1)); RETURN(FIELD); } } "$"{WS}* { RETURN(INDIRECT); } NF { mustfld=1; yylval = (hack)setsymtab(yytext, EMPTY, 0.0, NUM, symtab); RETURN(VAR); } ({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)? { yylval = (hack)setsymtab(yytext, EMPTY, atof(yytext), CON|NUM, symtab); RETURN(NUMBER); } "}"{WS}*\n { BEGIN sc; lineno++; RETURN(';'); } "}" { BEGIN sc; RETURN(';'); } ;\n { lineno++; RETURN(';'); } \n { lineno++; RETURN(NL); } while RETURN(WHILE); for RETURN(FOR); if RETURN(IF); else RETURN(ELSE); next RETURN(NEXT); exit RETURN(EXIT); break RETURN(BREAK); continue RETURN(CONTINUE); print { yylval = PRINT; RETURN(PRINT); } printf { yylval = PRINTF; RETURN(PRINTF); } sprintf { yylval = SPRINTF; RETURN(SPRINTF); } split { yylval = SPLIT; RETURN(SPLIT); } substr RETURN(SUBSTR); index RETURN(INDEX); in RETURN(IN); getline RETURN(GETLINE); length { yylval = FLENGTH; RETURN(FNCN); } log { yylval = FLOG; RETURN(FNCN); } int { yylval = FINT; RETURN(FNCN); } exp { yylval = FEXP; RETURN(FNCN); } sqrt { yylval = FSQRT; RETURN(FNCN); } {A}{B}* { yylval = (hack)setsymtab(yytext, tostring(""), 0.0, STR|NUM, symtab); RETURN(VAR); } \" { BEGIN str; clen=0; } # { BEGIN comment; } \n { BEGIN A; lineno++; RETURN(NL); } . ; . { yylval = yytext[0]; RETURN(yytext[0]); } "[" { BEGIN chc; clen=0; cflag=0; } "[^" { BEGIN chc; clen=0; cflag=1; } "?" RETURN(QUEST); "+" RETURN(PLUS); "*" RETURN(STAR); "|" RETURN(OR); "." RETURN(DOT); "(" RETURN('('); ")" RETURN(')'); "^" RETURN('^'); "$" RETURN('$'); \\{D}{D}{D} { sscanf(yytext+1, "%o", &yylval); RETURN(CHAR); } \\. { if (yytext[1]=='n') yylval = '\n'; else if (yytext[1] == 't') yylval = '\t'; else yylval = yytext[1]; RETURN(CHAR); } "/" { BEGIN A; unput('/'); } \n { yyerror("newline in regular expression"); lineno++; BEGIN A; } . { yylval = yytext[0]; RETURN(CHAR); } \" { char *s; BEGIN A; cbuf[clen]=0; s = tostring(cbuf); cbuf[clen] = ' '; cbuf[++clen] = 0; yylval = (hack)setsymtab(cbuf, s, 0.0, CON|STR, symtab); RETURN(STRING); } \n { yyerror("newline in string"); lineno++; BEGIN A; } "\\\"" { cbuf[clen++]='"'; } "\\"n { cbuf[clen++]='\n'; } "\\"t { cbuf[clen++]='\t'; } "\\\\" { cbuf[clen++]='\\'; } . { CADD; } "\\""]" { cbuf[clen++]=']'; } "]" { BEGIN reg; cbuf[clen]=0; yylval = (hack)tostring(cbuf); if (cflag==0) { RETURN(CCL); } else { RETURN(NCCL); } } \n { yyerror("newline in character class"); lineno++; BEGIN A; } . { CADD; } %% input() { register c; extern char *lexprog; if (yysptr > yysbuf) c = U(*--yysptr); else if (yyin == NULL) c = *lexprog++; else c = getc(yyin); if (c == '\n') yylineno++; else if (c == EOF) c = 0; return(c); } startreg() { BEGIN reg; } ptoken(n) { extern struct tok { char *tnm; int yval; } tok[]; extern char yytext[]; extern int yylval; printf("lex:"); if (n < 128) { printf(" %c\n",n); return; } if (n <= 256 || n >= LASTTOKEN) { printf("? %o\n",n); return; } printf(" %s",tok[n-257].tnm); switch (n) { case RELOP: case MATCHOP: case ASGNOP: case STRING: case FIELD: case VAR: case NUMBER: case FNCN: printf(" (%s)", yytext); break; case CHAR: printf(" (%o)", yylval); break; } putchar('\n'); } else setsymtab(num, tostring(t), 0.0, STR, ap->sval); *s = temp; if (*s != 0) s++; } else if (*s != 0) for (;;) { n++; t = s; while (*s != sep && *s != '\n' && *s != '\0') s++; temp = *s; *s = '\0'; sprintf(num, "%d", n); if (isnumber(t)) setsymtab(num, tostring(t), atof(t), STR|NUM, ap->sval); else setsymtab(num, tostring(t), 0.0, STR, ap->sval); *s = temp; if (*s++ == 0)bin/awk/token.c 444 0 12 2431 6024247726 6655 #ifndef lint static char sccsid[] = "@(#)token.c 4.3 (Berkeley) 12/8/84"; #endif #include "awk.h" struct tok { char *tnm; int yval; } tok[] = { "FIRSTTOKEN", 257, "FINAL", 258, "FATAL", 259, "LT", 260, "LE", 261, "GT", 262, "GE", 263, "EQ", 264, "NE", 265, "MATCH", 266, "NOTMATCH", 267, "APPEND", 268, "ADD", 269, "MINUS", 270, "MULT", 271, "DIVIDE", 272, "MOD", 273, "UMINUS", 274, "ASSIGN", 275, "ADDEQ", 276, "SUBEQ", 277, "MULTEQ", 278, "DIVEQ", 279, "MODEQ", 280, "JUMP", 281, "XBEGIN", 282, "XEND", 283, "NL", 284, "PRINT", 285, "PRINTF", 286, "SPRINTF", 287, "SPLIT", 288, "IF", 289, "ELSE", 290, "WHILE", 291, "FOR", 292, "IN", 293, "NEXT", 294, "EXIT", 295, "BREAK", 296, "CONTINUE", 297, "PROGRAM", 298, "PASTAT", 299, "PASTAT2", 300, "ASGNOP", 301, "BOR", 302, "AND", 303, "NOT", 304, "NUMBER", 305, "VAR", 306, "ARRAY", 307, "FNCN", 308, "SUBSTR", 309, "LSUBSTR", 310, "INDEX", 311, "GETLINE", 312, "RELOP", 313, "MATCHOP", 314, "OR", 315, "STRING", 316, "DOT", 317, "CCL", 318, "NCCL", 319, "CHAR", 320, "CAT", 321, "STAR", 322, "PLUS", 323, "QUEST", 324, "POSTINCR", 325, "PREINCR", 326, "POSTDECR", 327, "PREDECR", 328, "INCR", 329, "DECR", 330, "FIELD", 331, "INDIRECT", 332, "LASTTOKEN", 333, }; char *tokname(n) { if (n<=256 || n >= LASTTOKEN) n = 257; return(tok[n-257].tnm); } etsymtab(yytext, EMPTY, 0.0, NUM, symtab); RETURN(VAR); } ({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)? { yylval = (hack)setsymtab(yytext, EMPTY, atof(yytext), CON|NUM, symtab); RETURN(NUMBER); } "}"{WS}*\n { BEGIN sc; linenbin/awk/tran.c 444 0 12 13162 4013202623 6503 #ifndef lint static char sccsid[] = "@(#)tran.c 4.4 12/9/83"; #endif #include "stdio.h" #include "awk.def" #include "awk.h" cell *symtab[MAXSYM]; /* symbol table pointers */ char **FS; /* initial field sep */ char **RS; /* initial record sep */ char **OFS; /* output field sep */ char **ORS; /* output record sep */ char **OFMT; /*output format for numbers*/ awkfloat *NF; /* number of fields in current record */ awkfloat *NR; /* number of current record */ char **FILENAME; /* current filename argument */ cell *recloc; /* location of record */ cell *nrloc; /* NR */ cell *nfloc; /* NF */ syminit() { setsymtab("0", tostring("0"), 0.0, NUM|STR|CON|FLD, symtab); /* this one is used for if(x)... tests: */ setsymtab("$zero&null", tostring(""), 0.0, NUM|STR|CON|FLD, symtab); recloc = setsymtab("$record", record, 0.0, STR|FLD, symtab); dprintf("recloc %o lookup %o\n", recloc, lookup("$record", symtab, 0), NULL); FS = &setsymtab("FS", tostring(" "), 0.0, STR|FLD, symtab)->sval; RS = &setsymtab("RS", tostring("\n"), 0.0, STR|FLD, symtab)->sval; OFS = &setsymtab("OFS", tostring(" "), 0.0, STR|FLD, symtab)->sval; ORS = &setsymtab("ORS", tostring("\n"), 0.0, STR|FLD, symtab)->sval; OFMT = &setsymtab("OFMT", tostring("%.6g"), 0.0, STR|FLD, symtab)->sval; FILENAME = &setsymtab("FILENAME", EMPTY, 0.0, STR|FLD, symtab)->sval; nfloc = setsymtab("NF", EMPTY, 0.0, NUM, symtab); NF = &nfloc->fval; nrloc = setsymtab("NR", EMPTY, 0.0, NUM, symtab); NR = &nrloc->fval; } cell **makesymtab() { int i; cell **cp; cp = (cell **) malloc(MAXSYM * sizeof(cell *)); if (cp == NULL) error(FATAL, "out of space in makesymtab"); for (i = 0; i < MAXSYM; i++) cp[i] = 0; return(cp); } freesymtab(ap) /* free symbol table */ cell *ap; { cell *cp, **tp; int i; if (!(ap->tval & ARR)) return; tp = (cell **) ap->sval; for (i = 0; i < MAXSYM; i++) { for (cp = tp[i]; cp != NULL; cp = cp->nextval) { strfree(cp->nval); strfree(cp->sval); free(cp); } } xfree(tp); } cell *setsymtab(n, s, f, t, tab) char *n, *s; awkfloat f; unsigned t; cell **tab; { register h; register cell *p; cell *lookup(); if (n != NULL && (p = lookup(n, tab, 0)) != NULL) { if (s != EMPTY ) xfree(s); /* careful here */ dprintf("setsymtab found %o: %s", p, p->nval, NULL); dprintf(" %s %g %o\n", p->sval, p->fval, p->tval); return(p); } p = (cell *) malloc(sizeof(cell)); if (p == NULL) error(FATAL, "symbol table overflow at %s", n); p->nval = tostring(n); p->sval = s; p->fval = f; p->tval = t; h = hash(n); p->nextval = tab[h]; tab[h] = p; dprintf("setsymtab set %o: %s", p, p->nval, NULL); dprintf(" %s %g %o\n", p->sval, p->fval, p->tval); return(p); } hash(s) /* form hash value for string s */ register unsigned char *s; { register int hashval; for (hashval = 0; *s != '\0'; ) hashval += *s++; return(hashval % MAXSYM); } cell *lookup(s, tab, flag) /* look for s in tab, flag must match*/ register char *s; cell **tab; { register cell *p; for (p = tab[hash(s)]; p != NULL; p = p->nextval) if (strcmp(s, p->nval) == 0 && (flag == 0 || flag == p->tval)) return(p); /* found it */ return(NULL); /* not found */ } awkfloat setfval(vp, f) register cell *vp; awkfloat f; { dprintf("setfval: %o %g\n", vp, f, NULL); checkval(vp); if (vp == recloc) error(FATAL, "can't set $0"); vp->tval &= ~STR; /* mark string invalid */ vp->tval |= NUM; /* mark number ok */ if ((vp->tval & FLD) && isnull(vp->nval)) donerec = 0; return(vp->fval = f); } char *setsval(vp, s) register cell *vp; char *s; { dprintf("setsval: %o %s\n", vp, s, NULL); checkval(vp); if (vp == recloc) error(FATAL, "can't set $0"); vp->tval &= ~NUM; vp->tval |= STR; if ((vp->tval & FLD) && isnull(vp->nval)) donerec = 0; if (!(vp->tval&FLD)) strfree(vp->sval); vp->tval &= ~FLD; return(vp->sval = tostring(s)); } awkfloat getfval(vp) register cell *vp; { if (vp->sval == record && donerec == 0) recbld(); dprintf("getfval: %o", vp, NULL, NULL); checkval(vp); if ((vp->tval & NUM) == 0) { /* the problem is to make non-numeric things */ /* have unlikely numeric variables, so that */ /* $1 == $2 comparisons sort of make sense when */ /* one or the other is numeric */ if (isnumber(vp->sval)) { vp->fval = atof(vp->sval); if (!(vp->tval & CON)) /* don't change type of a constant */ vp->tval |= NUM; } else vp->fval = 0.0; /* not a very good idea */ } dprintf(" %g\n", vp->fval, NULL, NULL); return(vp->fval); } char *getsval(vp) register cell *vp; { char s[100]; if (vp->sval == record && donerec == 0) recbld(); dprintf("getsval: %o", vp, NULL, NULL); checkval(vp); if ((vp->tval & STR) == 0) { if (!(vp->tval&FLD)) strfree(vp->sval); if ((long)vp->fval==vp->fval) sprintf(s, "%.20g", vp->fval); else sprintf(s, *OFMT, vp->fval); vp->sval = tostring(s); vp->tval &= ~FLD; vp->tval |= STR; } dprintf(" %s\n", vp->sval, NULL, NULL); return(vp->sval); } checkval(vp) register cell *vp; { if (vp->tval & ARR) error(FATAL, "illegal reference to array %s", vp->nval); if ((vp->tval & (NUM | STR)) == 0) error(FATAL, "funny variable %o: %s %s %g %o", vp, vp->nval, vp->sval, vp->fval, vp->tval); } char *tostring(s) register char *s; { register char *p; if (s==NULL){ p = malloc(1); if (p == NULL) error(FATAL, "out of space in tostring on %s", s); *p = '\0'; } else { p = malloc(strlen(s)+1); if (p == NULL) error(FATAL, "out of space in tostring on %s", s); strcpy(p, s); } return(p); } #ifndef yfree yfree(a) char *a; { printf("%o\n", a); free(a); } #endif #ifdef malloc #undef malloc char *ymalloc(u) unsigned u; { char *p; p = malloc(u); printf("%o %o\n", u, p); return(p); } #endif ineno++; BEGIN A; } . { yylval = yytext[0]; RETURN(CHAR); } \" { char *s; BEGIN A; cbuf[clen]=0; s = tostring(cbuf); cbuf[clen] = ' '; cbuf[++clen] = 0; yylval = (hack)setsymtab(cbuf, s, 0.0, CON|STR, symtab); RETURN(STRING); } \n { yyerror("newline in string"); lineno++; BEGIN A; } "\\\"" { cbuf[clen++]='"'; } "\\"n { cbuf[clen++]='\n'; } "\\"t { cbbin/tp/ 755 0 12 0 6024536012 5134 bin/tp/Makefile 444 0 12 321 4015050057 6631 # @(#)Makefile 4.1 12/18/82 CFLAGS=-O SEPFLAG= -i h = tp.h tp_defs.h o = tp0.o tp1.o tp2.o tp3.o tp : $o $(CC) ${SEPFLAG} -o tp $o $o : $h install : tp install -s tp ${DESTDIR}/bin clean : rm -f *.o bin/tp/tp.h 444 0 12 2747 4013202624 6020 /* @(#)tp.h 4.2 6/28/84 */ /* c-version of tp?.s * * M. Ferentz * August 1976 * * revised July 1977 BTL */ #define MDIRENT 496 /* must be zero mod 8 */ #define DIRSZ sizeof(struct dent) #define MAPSIZE 4096 #define MAPMASK 07777 #define NAMELEN 32 #define BSIZE 512 #define TCSIZ 578 #define TCDIRS 192 #define MTSIZ 32767 #define TPB (BSIZE/sizeof(struct tent)) #define OK 0100000 #define BRKINCR 512 #define tapeblk &tpentry[0] #define tapeb &tpentry[0] struct tent { /* Structure of a tape directory block */ char pathnam[NAMELEN]; short mode; char uid; char gid; char spare; char size0; unsigned short size1; long time; unsigned short tapea; /* tape address */ short unused[8]; short cksum; } tpentry[TPB]; struct dent { /* in core version of tent with "unused" removed * and pathname replaced by pointer to same in a * packed area (nameblock). */ char *d_namep; int d_mode; int d_uid; int d_gid; long d_size; long d_time; int d_tapea; } dir[MDIRENT]; char map[MAPSIZE]; char name[NAMELEN]; char name1[NAMELEN]; extern char mt[]; extern char tc[]; char *tname; extern char mheader[]; extern char theader[]; int narg, rnarg; char **parg; int wseeka,rseeka; int tapsiz; int fio; short ndirent, ndentb; struct dent *edir; struct dent *lastd; /* for improvement */ char *sbrk(); char *strcpy(); long lseek(); int (*command)(); extern int flags; #define flc 0001 #define fli 0004 #define flm 0010 #define flu 0020 #define flv 0040 #define flw 0100 #define fls 0200 ake non-numeric things */bin/tp/tp_defs.h 444 0 12 255 4013202624 6771 /* @(#)tp_defs.h 4.1 12/18/82 */ char mt[] = "/dev/rmt0"; char tc[] = "/dev/tapx"; int flags = flu; char mheader[] = "/usr/mdec/mboot"; char theader[] = "/usr/mdec/tboot"; bin/tp/tp0.c 444 0 12 153 4013202624 6040 #ifndef lint static char sccsid[] = "@(#)tp0.c 4.1 12/18/82"; #endif #include "tp.h" #include "tp_defs.h" .c¹œtp3.cbin/tp/tp1.c 444 0 12 5621 4013202624 6066 #ifndef lint static char sccsid[] = "@(#)tp1.c 4.2 6/28/84"; #endif #include "tp.h" main(argc,argv) char **argv; { register char c,*ptr; extern cmd(), cmr(),cmx(), cmt(); tname = tc; command = cmr; if ((narg = rnarg = argc) < 2) narg = 2; else { ptr = argv[1]; /* get first argument */ parg = &argv[2]; /* pointer to second argument */ while (c = *ptr++) switch(c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': tc[8] = c; mt[8] = c; continue; case 'f': tname = *parg++; flags |= flm; narg--; rnarg--; continue; case 'c': flags |= flc; continue; case 'd': setcom(cmd); continue; case 'i': flags |= fli; continue; case 'm': tname = mt; flags |= flm; continue; case 'r': flags &= ~flu; setcom(cmr); continue; case 's': flags |= fls; continue; case 't': setcom(cmt); continue; case 'u': flags |= flu; setcom(cmr); continue; case 'v': flags |= flv; continue; case 'w': flags |= flw; continue; case 'x': setcom(cmx); continue; default: useerr(); } } optap(); (*command)(); } optap() { extern cmr(); if ((flags & flm) == 0) { /* DECTAPE */ tapsiz = TCSIZ; ndirent = TCDIRS; fio =open(tc,2); } else { /* MAGTAPE */ tapsiz = MTSIZ; ndirent = MDIRENT; if(command == cmr) { fio = open(tname,1); if (fio < 0) fio = creat(tname,0666); } else fio = open(tname,0); } if (fio < 0) { printf("Tape open error\n"); done(); } ndentb = ndirent/TPB; edir = &dir[ndirent]; } setcom(newcom) int (*newcom)(); { extern cmr(); if (command != cmr) useerr(); command = newcom; } useerr() { printf("Bad usage\n"); done(); } /* /* COMMANDS */ cmd() { extern delete(); if (flags & (flm|flc)) useerr(); if (narg <= 2) useerr(); rddir(); gettape(delete); wrdir(); check(); } cmr() { if (flags & (flc|flm)) clrdir(); else rddir(); getfiles(); update(); check(); } cmt() { extern taboc(); if (flags & (flc|flw)) useerr(); rddir(); if (flags & flv) printf(" mode uid gid tapa size date time name\n"); gettape(taboc); check(); } cmx() { extern extract(); if (flags & (flc)) useerr(); rddir(); gettape(extract); done(); } check() { usage(); done(); } done() { printf("End\n"); exit(0); } encode(pname,dptr) /* pname points to the pathname * dptr points to the dir entry */ char *pname; struct dent *dptr; { register char *np; register n; extern char *malloc(); if((n=strlen(pname)) > NAMELEN) { printf("Pathname too long - %s\nFile ignored\n",pname); clrent(dptr); } else { dptr->d_namep = np = malloc(n + 1); if (np == 0) { printf("Out of core\n"); done(); } strcpy(np, pname); } } decode(pname,dptr) /* dptr points to the dir entry * name is placed in pname[] */ char *pname; struct dent *dptr; { strcpy(pname, dptr->d_namep); } { if (vp->tval & ARR) error(FATAL, "illegal reference to array %s", vp->nval); if ((vp->tval & (NUM | STR))bin/tp/tp2.c 444 0 12 15117 4013202624 6110 #ifndef lint static char sccsid[] = "@(#)tp2.c 4.1 12/18/82"; #endif #include "tp.h" #include #include #include #include struct stat statb; clrdir() { register j, *p; j = ndirent * (DIRSZ/sizeof(int)); p = (int *)dir; do (*p++ = 0); while (--j); lastd = 0; } clrent(ptr) struct dent *ptr; { register *p, j; p = (int *)ptr; j = DIRSZ/sizeof(int); do *p++ = 0; while (--j); if (++ptr == lastd) do { if (--lastd < dir) { lastd = 0; return; } } while (lastd->d_namep == 0); } rddir() { register struct tent *tp; register struct dent *p1; struct dent *dptr; struct tent *tptr; int count, i, sum; short reg, *sp; sum = 0; clrdir(); rseek(0); tread(); /* Read the bootstrap block */ if ((tpentry[TPB-1].cksum != 0) && (flags & flm)) { ndirent = tpentry[TPB-1].cksum; if(flags & fls) swab((char *)&ndirent, (char *)&ndirent, sizeof(ndirent)); if(ndirent < 0 || ndirent > MDIRENT) ndirent = MDIRENT; ndentb = ndirent/TPB; } dptr = &dir[0]; count = ndirent; do { if ((count % TPB) == 0) { /* next block */ tread(); tptr = &tpentry[0]; } if(flags & fls) swab((char *)tptr, (char *)tptr, sizeof(*tptr)); sp = (short *)tptr; reg = 0; for(i=0;ipathnam[0] != '\0') { lastd = p1; encode(tp->pathnam,p1); p1->d_mode = tp->mode; p1->d_uid = tp->uid; p1->d_gid = tp->gid; p1->d_size = (((long)tp->size0&0377L)<<16)+(tp->size1&0177777L); p1->d_time = tp->time; p1->d_tapea = tp->tapea; } } ++tptr; /* bump to next tent */ (dptr++)->d_mode &= ~OK; } while (--count); if(sum != 0) if(flags & (fls|fli)) { printf("Directory checksum\n"); if ((flags & fli) == 0) done(); } else { flags |= fls; rddir(); printf("Warning: swabbing required\n"); return; } bitmap(); } wrdir() { register struct tent *tp; register struct dent *dp; struct dent *dptr; int count, i; short reg, *sp; wseek(0); if (flags & flm) reg = open(mheader,0); else reg = open(theader,0); if (reg >= 0) { read(reg,(char *)tapeb,BSIZE); close(reg); if(flags & fls) swab((char *)&ndirent, (char *)&tpentry[TPB-1].cksum, sizeof(ndirent)); else tpentry[TPB-1].cksum = ndirent; } else printf("\7\7\7Warning: cannot read prototype boot block.\n"); dptr = &dir[0]; count = ndirent; for (;;) { twrite(); if (count == 0) return; tp = &tpentry[0]; do { dp = dptr++; /* dptr set to next entry */ if (dp->d_namep) { decode(tp->pathnam,dp); tp->mode = dp->d_mode; tp->uid = dp->d_uid; tp->gid = dp->d_gid; tp->time = dp->d_time; tp->size0 = dp->d_size >> 16; tp->size1 = dp->d_size; tp->tapea = dp->d_tapea; if(flags & fls) { swabdir(tp); swab((char *)tp, (char *)tp, sizeof(*tp)); } reg = 0; sp = (short *)tp; for(i=0;i 25 && b) { lseek(fio, (long)(b-1)*BSIZE, 0); /* seek previous block */ read(fio, (char *)&wseeka, 1); /* read next block */ } wseeka = b; if (lseek(fio, (long)b*BSIZE, 0) < 0) seekerr(); } seekerr() { printf("Tape seek error\n"); done(); } verify(key) { register c; if ((flags & (flw | flv)) == 0) return(0); repeat: printf("%c %s ", key, name); if ((flags & flw) == 0) { printf("\n"); return(0); } c = getchar(); if (c == 'n' && getchar() == '\n') done(); if (c == '\n') return(-1); if (c == 'y' && getchar() == '\n') return(0); while (getchar() != '\n'); goto repeat; } getfiles() { if ((narg -= 2) == 0) { strcpy(name, "."); callout(); } else while (--narg >= 0) { strcpy(name, *parg++); callout(); } } expand() { register char *p0, *save0; int n; register DIR *dirp; struct direct *dirent; if ((dirp = opendir(name)) == NULL) fserr(); for (;;) { dirent = readdir(dirp); if (dirent == NULL) { closedir(dirp); return; } if (dirent->d_ino == 0) /* null entry */ continue; p0 = name; if (dirent->d_name[0] == '.') /* don't save .xxxx */ continue; while (*p0++); save0 = --p0; /* save loc of \0 */ if (p0[-1] != '/') *p0++ = '/'; strcpy(p0, dirent->d_name); callout(); *save0 = 0; /* restore */ } } fserr() { printf("%s -- Cannot open file\n", name); done(); } callout() { register struct dent *d; register char *ptr1, *ptr0; struct dent *empty; int mode; if (stat(name,&statb) < 0) fserr(); mode = statb.st_mode; if ((mode &= S_IFMT) != 0) { if (mode == S_IFDIR) /* directory */ expand(); if(mode != S_IFREG) return; } /* when we reach here we have recursed until we found * an ordinary file. Now we look for it in "dir". */ empty = 0; d = &dir[0]; do { if (d->d_namep == 0) { /* empty directory slot */ if (empty == 0) /* remember the first one */ empty = d; continue; } decode(name1,d); ptr0 = name; ptr1 = name1; do if (*ptr0++ != *ptr1) goto cont; while (*ptr1++); /* veritably the same name */ if (flags & flu) { /* check the times */ if (d->d_time >= statb.st_mtime) return; } if (verify('r') < 0) return; goto copydir; cont: continue; } while (++d <= lastd); /* name not found in directory */ if ((d = empty) == 0) { d = lastd +1; if (d >= edir) { printf("Directory overflow\n"); done(); } } if (verify('a') < 0) return; if (d > lastd) lastd = d; encode(name,d); copydir: d->d_mode = statb.st_mode | OK; d->d_uid = statb.st_uid; d->d_gid = statb.st_gid; d->d_size = statb.st_size; d->d_time = statb.st_mtime; ; } swabdir(tp) register struct tent *tp; { swab((char *)tp, (char *)tp, sizeof(*tp)); swab(tp->pathnam, tp->pathnam, NAMELEN); swab((char *)&tp->uid, (char *)&tp->uid, 4); /* uid,gid,spare,size0 */ } cute(a[0]); errorflag = getfval(y.optr); } x.osub = JEXIT; break; case NEXT: x.osub = JNEXT; break; case BREAK: x.osub = JBREAK; break; case CONTINUE: x.osub = JCONT; break; } return(x); } obj fncn(a,n) node **a; { obj x; awkfloat u; int t; t = (int) a[0]; x = execute(a[1]); if (t == FLENGTH) u = (awkfloat) strlen(getsval(x.optr)); else if (t == FLOG) u = log(getfval(x.optr)); else if (t ==bin/tp/tp3.c 444 0 12 11232 4013202624 6103 #ifndef lint static char sccsid[] = "@(#)tp3.c 4.1 12/18/82"; #endif #include "tp.h" gettape(how) int (*how)(); { register char *ptr0, *ptr1; register struct dent *d; int count; do { d = &dir[0]; count = 0; do { if (d->d_namep == 0) continue; decode(name,d); if (rnarg > 2) { ptr0 = name; ptr1 = *parg; while (*ptr1) if (*ptr0++ != *ptr1++) goto cont; if (*ptr0 && *ptr0 != '/') goto cont; } (*how)(d); /* delete, extract, or taboc */ ++count; cont: continue; } while (++d <= lastd); if (count == 0 && rnarg > 2) printf("%s not found\n", *parg); ++parg; } while (--narg > 2); } delete(dd) struct dent *dd; { if (verify('d') >= 0) clrent(dd); } update() { register struct dent *d; register b, last; int first, size; bitmap(); d = &dir[0]; do { if(d->d_namep == 0 || (d->d_mode&OK) == 0) continue; if (d->d_size == 0) continue; /* find a place on the tape for this file */ size = (d->d_size+BSIZE-1)/BSIZE; first = ndentb; toosmall: ++first; if ((last = first + size) >= tapsiz) maperr(); for (b = first; b < last; ++b) if (map[(b>>3) & MAPMASK] & (1<<(b&7))) { first = b; goto toosmall; }; d->d_tapea = first; setmap(d); } while (++d <= lastd); wrdir(); update1(); } update1() { register struct dent *d, *id; register index; int f; for (;;) { d = &dir[0]; index = MTSIZ; id = 0; do { /* find new dent with lowest tape address */ if(d->d_namep == 0 || (d->d_mode&OK) == 0) continue; if (d->d_tapea < index) { index = d->d_tapea; id = d; } } while (++d <= lastd); if ((d = id) == 0) return; d->d_mode &= ~OK; /* change from new to old */ if (d->d_size == 0) continue; decode(name,d); wseek(index); if ((f = open(name,0)) < 0) { printf("Can't open %s\n", name); continue; } for (index = d->d_size/BSIZE; index != 0; --index) { if (read(f,(char *)tapeb,BSIZE) != BSIZE) phserr(); twrite(); } if (index = d->d_size % BSIZE) { if (read(f,(char *)tapeb,index) != index) phserr(); twrite(); } if (read(f,(char *)tapeb,1) != 0) phserr(); close(f); } } phserr() { printf("%s -- Phase error \n", name); } bitmap() /* place old files in the map */ { register char *m; register count; register struct dent *d; for(m=map;m<&map[MAPSIZE];) *m++ = 0; count = ndirent; d = dir; do { if(d->d_namep != 0 && (d->d_mode&OK) == 0 && d->d_size != 0) setmap(d); d++; } while (--count); } setmap(d) register struct dent *d; { unsigned c, block; char bit; int i; c = d->d_size/BSIZE; if (d->d_size % BSIZE) c++; block = d->d_tapea; if ((c += block) >= tapsiz) maperr(); do { bit = 1 << (block & 7); i = (block>>3) & MAPMASK; if (bit & map[i]) maperr(); map[i] |= bit; } while (++block < c); } maperr() { printf("Tape overflow\n"); done(); } usage() { register reg,count; int nused, nentr, nfree; static lused; bitmap(); for(count=0,nentr=0;count= tapsiz) { printf("Tape overflow\n"); done(); } if (map[(reg>>3) & MAPMASK] & (1 << (reg&7))) { nused++; lused = reg; } else { if (flags & flm) break; nfree++; } reg++; } while (--count); printf("%4d entries\n%4d used\n", nentr, nused); if ((flags & flm)==0) printf("%4d free\n", nfree); printf("%4d last\n", lused); } taboc(dd) struct dent *dd; { register mode; register *m; register char *s; int count, *localtime(); char work[20]; if (flags & flv) { mode = dd->d_mode; s = &work[19]; *s = 0; for (count = 3; count; --count) { if (mode&1) *--s = 'x'; else *--s = '-'; if (mode&2) *--s = 'w'; else *--s = '-'; if (mode&4) *--s = 'r'; else *--s = '-'; mode >>= 3; } if (mode&4) s[2] = 's'; if (mode&2) s[5] = 's'; printf("%s%4d%4d%5d%9D ",s,dd->d_uid, dd->d_gid,dd->d_tapea,dd->d_size); m = localtime(&dd->d_time); printf("%2d/%2d/%2d %2d:%2d ",m[5],m[4]+1,m[3],m[2],m[1]); } printf("%s\n", name); } extract(d) register struct dent *d; { register count, id; if (d->d_size==0) return; if (verify('x') < 0) return; rseek(d->d_tapea); unlink(name); if ((id = creat(name,d->d_mode)) < 0) printf("%s -- create error\n", name); count = d->d_size/BSIZE; while (count--) { tread(); if (write(id, (char *)tapeb, BSIZE) != BSIZE) goto ng; } if (count = d->d_size % BSIZE) { tread(); if (write(id, (char *)tapeb, count) != count) { ng: printf("%s -- write error\n", name); close(id); return; } } close(id); chown(name,d->d_uid & 0377, d->d_gid&0377); } p = opendir(name)) == NULL) fserr(); for (;;) { dirent = readdir(dirp); if (dirent == NULL) { closedir(dirp); return; } if (dirent->d_ino == 0) /* null entry */ continue; p0 = name; if (dirent->d_name[0] == '.') /* don't save .xxxx */ continue; while (*p0++); save0 = --p0; /* save loc of \0 */ if (p0[-1] != '/') *p0++ = bin/sh/ 755 0 12 0 6024536005 5125 bin/sh/args.c 444 0 12 4354 3525214645 6324 #ifndef lint static char sccsid[] = "@(#)args.c 4.4 7/31/85"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" PROC STRING *copyargs(); LOCAL DOLPTR dolh; CHAR flagadr[10]; CHAR flagchar[] = { 'x', 'n', 'v', 't', 's', 'i', 'e', 'r', 'k', 'u', 0 }; INT flagval[] = { execpr, noexec, readpr, oneflg, stdflg, intflg, errflg, rshflg, keyflg, setflg, 0 }; /* ======== option handling ======== */ INT options(argc,argv) STRING *argv; INT argc; { REG STRING cp; REG STRING *argp=argv; REG STRING flagc; STRING flagp; IF argc>1 ANDF *argp[1]=='-' THEN cp=argp[1]; flags &= ~(execpr|readpr); WHILE *++cp DO flagc=flagchar; WHILE *flagc ANDF *flagc != *cp DO flagc++ OD IF *cp == *flagc THEN flags |= flagval[flagc-flagchar]; ELIF *cp=='c' ANDF argc>2 ANDF comdiv==0 THEN comdiv=argp[2]; argp[1]=argp[0]; argp++; argc--; ELSE failed(argv[1],badopt); FI OD argp[1]=argp[0]; argc--; FI /* set up $- */ flagc=flagchar; flagp=flagadr; WHILE *flagc DO IF flags&flagval[flagc-flagchar] THEN *flagp++ = *flagc; FI flagc++; OD *flagp++=0; return(argc); } VOID setargs(argi) STRING argi[]; { /* count args */ REG STRING *argp=argi; REG INT argn=0; WHILE Rcheat(*argp++)!=ENDARGS DO argn++ OD /* free old ones unless on for loop chain */ freeargs(dolh); dolh=copyargs(argi,argn); /* sets dolv */ assnum(&dolladr,dolc=argn-1); } freeargs(blk) DOLPTR blk; { REG STRING *argp; REG DOLPTR argr=0; REG DOLPTR argblk; IF argblk=blk THEN argr = argblk->dolnxt; IF (--argblk->doluse)==0 THEN FOR argp=argblk->dolarg; Rcheat(*argp)!=ENDARGS; argp++ DO free(*argp) OD free(argblk); FI FI return(argr); } LOCAL STRING * copyargs(from, n) STRING from[]; { REG STRING * np=alloc(sizeof(STRING*)*n+3*BYTESPERWORD); REG STRING * fp=from; REG STRING * pp=np; np->doluse=1; /* use count */ np=np->dolarg; dolv=np; WHILE n-- DO *np++ = make(*fp++) OD *np++ = ENDARGS; return(pp); } clearup() { /* force `for' $* lists to go away */ WHILE argfor=freeargs(argfor) DONE /* clean up io files */ WHILE pop() DONE } DOLPTR useargs() { IF dolh THEN dolh->doluse++; dolh->dolnxt=argfor; return(argfor=dolh); ELSE return(0); FI } er count; register struct dent *d; for(m=map;m<&map[MAPSIZE];) *m++ = 0; count = ndirent; d = dir; do { if(d->d_namep != 0 && (d->d_mode&OK) == 0 && d->d_size != 0) setmap(d); d++; } while (--count); } setmap(d) register struct dent *d; { unsigned c, block;bin/sh/blok.c 444 0 12 3772 3146337626 6326 #ifndef lint static char sccsid[] = "@(#)blok.c 4.2 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" /* * storage allocator * (circular first fit strategy) */ #define BUSY 01 #define busy(x) (Rcheat((x)->word)&BUSY) POS brkincr=BRKINCR; BLKPTR blokp; /*current search pointer*/ BLKPTR bloktop=BLK(end); /*top of arena (last blok)*/ ADDRESS alloc(nbytes) POS nbytes; { REG POS rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD); LOOP INT c=0; REG BLKPTR p = blokp; REG BLKPTR q; REP IF !busy(p) THEN WHILE !busy(q = p->word) DO p->word = q->word OD IF ADR(q)-ADR(p) >= rbytes THEN blokp = BLK(ADR(p)+rbytes); IF q > blokp THEN blokp->word = p->word; FI p->word=BLK(Rcheat(blokp)|BUSY); return(ADR(p+1)); FI FI q = p; p = BLK(Rcheat(p->word)&~BUSY); PER p>q ORF (c++)==0 DONE addblok(rbytes); POOL } VOID addblok(reqd) POS reqd; { IF stakbas!=staktop THEN REG STKPTR rndstak; REG BLKPTR blokstak; pushstak(0); rndstak=round(staktop,BYTESPERWORD); blokstak=BLK(stakbas)-1; blokstak->word=stakbsy; stakbsy=blokstak; bloktop->word=BLK(Rcheat(rndstak)|BUSY); bloktop=BLK(rndstak); FI reqd += brkincr; reqd &= ~(brkincr-1); blokp=bloktop; bloktop=bloktop->word=BLK(Rcheat(bloktop)+reqd); bloktop->word=BLK(ADR(end)+1); BEGIN REG STKPTR stakadr=STK(bloktop+2); staktop=movstr(stakbot,stakadr); stakbas=stakbot=stakadr; END } VOID free(ap) BLKPTR ap; { REG BLKPTR p; IF (p=ap) ANDF pword) &= ~BUSY; FI } #ifdef DEBUG chkbptr(ptr) BLKPTR ptr; { INT exf=0; REG BLKPTR p = end; REG BLKPTR q; INT us=0, un=0; LOOP q = Rcheat(p->word)&~BUSY; IF p==ptr THEN exf++ FI IF qbloktop THEN abort(3) FI IF p==bloktop THEN break FI IF busy(p) THEN us += q-p; ELSE un += q-p; FI IF p>=q THEN abort(4) FI p=q; POOL IF exf==0 THEN abort(1) FI prn(un); prc(SP); prn(us); prc(NL); } #endif DOLPTbin/sh/brkincr.h 444 0 12 111 2731034225 6762 /* brkincr.h 4.1 82/05/07 */ #define BRKINCR 01000 #define BRKMAX 04000 cr.h´ builtin.c³ cmd.c²ctype.cc±ctype.hc°defs.hc¯ dup.h®error.cc­expand.c¬fault.c« io.c.ªmacro.c©main.c¨mode.h§ msg.c¦name.c¥name.h¤print.c£ service.c¢setbrk.c¡stak.cc stak.hcŸstring.cž sym.h timeout.hœword.c.h› xec.cšMakefile™$mac.hbin/sh/builtin.c 444 0 12 140 3146337627 7010 #ifndef lint static char sccsid[] = "@(#)builtin.c 4.2 8/11/83"; #endif builtin() {return(0);} cmd.c²ctype.cc±ctype.hc°defs.hc¯ dup.h®error.cc­expand.c¬fault.c« io.c.ªmacro.c©main.c¨mode.h§ msg.c¦name.c¥name.h¤print.c£ service.c¢setbrk.c¡stak.cc stak.hcŸstring.cž sym.h timeout.hœword.c.h› xec.cšMakefile™$mac.hbin/sh/cmd.c 444 0 12 14130 3146337632 6145 #ifndef lint static char sccsid[] = "@(#)cmd.c 4.2 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" #include "sym.h" PROC IOPTR inout(); PROC VOID chkword(); PROC VOID chksym(); PROC TREPTR term(); PROC TREPTR makelist(); PROC TREPTR list(); PROC REGPTR syncase(); PROC TREPTR item(); PROC VOID skipnl(); PROC VOID prsym(); PROC VOID synbad(); /* ======== command line decoding ========*/ TREPTR makefork(flgs, i) INT flgs; TREPTR i; { REG TREPTR t; t=getstak(FORKTYPE); t->forktyp=flgs|TFORK; t->forktre=i; t->forkio=0; return(t); } LOCAL TREPTR makelist(type,i,r) INT type; TREPTR i, r; { REG TREPTR t; IF i==0 ORF r==0 THEN synbad(); ELSE t = getstak(LSTTYPE); t->lsttyp = type; t->lstlef = i; t->lstrit = r; FI return(t); } /* * cmd * empty * list * list & [ cmd ] * list [ ; cmd ] */ TREPTR cmd(sym,flg) REG INT sym; INT flg; { REG TREPTR i, e; i = list(flg); IF wdval==NL THEN IF flg&NLFLG THEN wdval=';'; chkpr(NL); FI ELIF i==0 ANDF (flg&MTFLG)==0 THEN synbad(); FI SWITCH wdval IN case '&': IF i THEN i = makefork(FINT|FPRS|FAMP, i); ELSE synbad(); FI case ';': IF e=cmd(sym,flg|MTFLG) THEN i=makelist(TLST, i, e); FI break; case EOFSYM: IF sym==NL THEN break; FI default: IF sym THEN chksym(sym); FI ENDSW return(i); } /* * list * term * list && term * list || term */ LOCAL TREPTR list(flg) { REG TREPTR r; REG INT b; r = term(flg); WHILE r ANDF ((b=(wdval==ANDFSYM)) ORF wdval==ORFSYM) DO r = makelist((b ? TAND : TORF), r, term(NLFLG)); OD return(r); } /* * term * item * item |^ term */ LOCAL TREPTR term(flg) { REG TREPTR t; reserv++; IF flg&NLFLG THEN skipnl(); ELSE word(); FI IF (t=item(TRUE)) ANDF (wdval=='^' ORF wdval=='|') THEN return(makelist(TFIL, makefork(FPOU,t), makefork(FPIN|FPCL,term(NLFLG)))); ELSE return(t); FI } LOCAL REGPTR syncase(esym) REG INT esym; { skipnl(); IF wdval==esym THEN return(0); ELSE REG REGPTR r=getstak(REGTYPE); r->regptr=0; LOOP wdarg->argnxt=r->regptr; r->regptr=wdarg; IF wdval ORF ( word()!=')' ANDF wdval!='|' ) THEN synbad(); FI IF wdval=='|' THEN word(); ELSE break; FI POOL r->regcom=cmd(0,NLFLG|MTFLG); IF wdval==ECSYM THEN r->regnxt=syncase(esym); ELSE chksym(esym); r->regnxt=0; FI return(r); FI } /* * item * * ( cmd ) [ < in ] [ > out ] * word word* [ < in ] [ > out ] * if ... then ... else ... fi * for ... while ... do ... done * case ... in ... esac * begin ... end */ LOCAL TREPTR item(flag) BOOL flag; { REG TREPTR t; REG IOPTR io; IF flag THEN io=inout((IOPTR)0); ELSE io=0; FI SWITCH wdval IN case CASYM: BEGIN t=getstak(SWTYPE); chkword(); t->swarg=wdarg->argval; skipnl(); chksym(INSYM|BRSYM); t->swlst=syncase(wdval==INSYM?ESSYM:KTSYM); t->swtyp=TSW; break; END case IFSYM: BEGIN REG INT w; t=getstak(IFTYPE); t->iftyp=TIF; t->iftre=cmd(THSYM,NLFLG); t->thtre=cmd(ELSYM|FISYM|EFSYM,NLFLG); t->eltre=((w=wdval)==ELSYM ? cmd(FISYM,NLFLG) : (w==EFSYM ? (wdval=IFSYM, item(0)) : 0)); IF w==EFSYM THEN return(t) FI break; END case FORSYM: BEGIN t=getstak(FORTYPE); t->fortyp=TFOR; t->forlst=0; chkword(); t->fornam=wdarg->argval; IF skipnl()==INSYM THEN chkword(); t->forlst=item(0); IF wdval!=NL ANDF wdval!=';' THEN synbad(); FI chkpr(wdval); skipnl(); FI chksym(DOSYM|BRSYM); t->fortre=cmd(wdval==DOSYM?ODSYM:KTSYM,NLFLG); break; END case WHSYM: case UNSYM: BEGIN t=getstak(WHTYPE); t->whtyp=(wdval==WHSYM ? TWH : TUN); t->whtre = cmd(DOSYM,NLFLG); t->dotre = cmd(ODSYM,NLFLG); break; END case BRSYM: t=cmd(KTSYM,NLFLG); break; case '(': BEGIN REG PARPTR p; p=getstak(PARTYPE); p->partre=cmd(')',NLFLG); p->partyp=TPAR; t=makefork(0,p); break; END default: IF io==0 THEN return(0); FI case 0: BEGIN REG ARGPTR argp; REG ARGPTR *argtail; REG ARGPTR *argset=0; INT keywd=1; t=getstak(COMTYPE); t->comio=io; /*initial io chain*/ argtail = &(t->comarg); WHILE wdval==0 DO argp = wdarg; IF wdset ANDF keywd THEN argp->argnxt=argset; argset=argp; ELSE *argtail=argp; argtail = &(argp->argnxt); keywd=flags&keyflg; FI word(); IF flag THEN t->comio=inout(t->comio); FI OD t->comtyp=TCOM; t->comset=argset; *argtail=0; return(t); END ENDSW reserv++; word(); IF io=inout(io) THEN t=makefork(0,t); t->treio=io; FI return(t); } LOCAL VOID skipnl() { WHILE (reserv++, word()==NL) DO chkpr(NL) OD return(wdval); } LOCAL IOPTR inout(lastio) IOPTR lastio; { REG INT iof; REG IOPTR iop; REG CHAR c; iof=wdnum; SWITCH wdval IN case DOCSYM: iof |= IODOC; break; case APPSYM: case '>': IF wdnum==0 THEN iof |= 1 FI iof |= IOPUT; IF wdval==APPSYM THEN iof |= IOAPP; break; FI case '<': IF (c=nextc(0))=='&' THEN iof |= IOMOV; ELIF c=='>' THEN iof |= IORDW; ELSE peekc=c|MARK; FI break; default: return(lastio); ENDSW chkword(); iop=getstak(IOTYPE); iop->ioname=wdarg->argval; iop->iofile=iof; IF iof&IODOC THEN iop->iolst=iopend; iopend=iop; FI word(); iop->ionxt=inout(lastio); return(iop); } LOCAL VOID chkword() { IF word() THEN synbad(); FI } LOCAL VOID chksym(sym) { REG INT x = sym&wdval; IF ((x&SYMFLG) ? x : sym) != wdval THEN synbad(); FI } LOCAL VOID prsym(sym) { IF sym&SYMFLG THEN REG SYSPTR sp=reserved; WHILE sp->sysval ANDF sp->sysval!=sym DO sp++ OD prs(sp->sysnam); ELIF sym==EOFSYM THEN prs(endoffile); ELSE IF sym&SYMREP THEN prc(sym) FI IF sym==NL THEN prs("newline"); ELSE prc(sym); FI FI } LOCAL VOID synbad() { prp(); prs(synmsg); IF (flags&ttyflg)==0 THEN prs(atline); prn(standin->flin); FI prs(colon); prc(LQ); IF wdval THEN prsym(wdval); ELSE prs(wdarg->argval); FI prc(RQ); prs(unexpected); newline(); exitsh(SYNBAD); } * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" #include "sym.h" PROC IOPTR inout(); PROC VOID chkword(); PROC VOID chksym(); PROC TREPTR term(); PROC TREPTR makelist(); PROC TREPTR list(); PROC REGPTR syncase(); PROC TREPTR item(); PROC VOID skipnl(); PROC VOID prsym(); PROC VOID synbad(); /* ======== command line decoding ========*/ TREPTR makefork(flgs, i) INT flgs; TREPTR i; { bin/sh/ctype.c 444 0 12 3676 4001650061 6504 #ifndef lint static char sccsid[] = "@(#)ctype.c 4.2 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" char _ctype1[] = { /* 000 001 002 003 004 005 006 007 */ _EOF, 0, 0, 0, 0, 0, 0, 0, /* bs ht nl vt np cr so si */ 0, _TAB, _EOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* sp ! " # $ % & ' */ _SPC, 0, _DQU, 0, _DOL1, 0, _AMP, 0, /* ( ) * + , - . / */ _BRA, _KET, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 8 9 : ; < = > ? */ 0, 0, 0, _SEM, _LT, 0, _GT, 0, /* @ A B C D E F G */ 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */ 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */ 0, 0, 0, 0, 0, 0, 0, 0, /* X Y Z [ \ ] ^ _ */ 0, 0, 0, 0, _BSL, 0, _HAT, 0, /* ` a b c d e f g */ _LQU, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */ 0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */ 0, 0, 0, 0, 0, 0, 0, 0, /* x y z { | } ~ del */ 0, 0, 0, 0, _BAR, 0, 0, 0 }; char _ctype2[] = { /* 000 001 002 003 004 005 006 007 */ 0, 0, 0, 0, 0, 0, 0, 0, /* bs ht nl vt np cr so si */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* sp ! " # $ % & ' */ 0, _PCS, 0, _NUM, _DOL2, 0, 0, 0, /* ( ) * + , - . / */ 0, 0, _AST, _PLS, 0, _MIN, 0, 0, /* 0 1 2 3 4 5 6 7 */ _DIG, _DIG, _DIG, _DIG, _DIG, _DIG, _DIG, _DIG, /* 8 9 : ; < = > ? */ _DIG, _DIG, 0, 0, 0, _EQ, 0, _QU, /* @ A B C D E F G */ _AT, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, /* H I J K L M N O */ _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, /* P Q R S T U V W */ _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, _UPC, /* X Y Z [ \ ] ^ _ */ _UPC, _UPC, _UPC, _SQB, 0, 0, 0, _UPC, /* ` a b c d e f g */ 0, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, /* h i j k l m n o */ _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, /* p q r s t u v w */ _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, _LPC, /* x y z { | } ~ del */ _LPC, _LPC, _LPC, _CBR, 0, _CKT, 0, 0 }; ym) REG INT esym; { skipnl(); IF wdval==esym THEN return(0); bin/sh/ctype.h 444 0 12 4416 2731034226 6511 /* ctype.h 4.1 82/05/07 */ # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ /* table 1 */ #define T_SUB 01 #define T_MET 02 #define T_SPC 04 #define T_DIP 010 #define T_EOF 020 #define T_EOR 040 #define T_QOT 0100 #define T_ESC 0200 /* table 2 */ #define T_BRC 01 #define T_DEF 02 #define T_AST 04 #define T_DIG 010 #define T_FNG 020 #define T_SHN 040 #define T_IDC 0100 #define T_SET 0200 /* for single chars */ #define _TAB (T_SPC) #define _SPC (T_SPC) #define _UPC (T_IDC) #define _LPC (T_IDC) #define _DIG (T_DIG) #define _EOF (T_EOF) #define _EOR (T_EOR) #define _BAR (T_DIP) #define _HAT (T_MET) #define _BRA (T_MET) #define _KET (T_MET) #define _SQB (T_FNG) #define _AMP (T_DIP) #define _SEM (T_DIP) #define _LT (T_DIP) #define _GT (T_DIP) #define _LQU (T_QOT|T_ESC) #define _BSL (T_ESC) #define _DQU (T_QOT) #define _DOL1 (T_SUB|T_ESC) #define _CBR T_BRC #define _CKT T_DEF #define _AST (T_AST|T_FNG) #define _EQ (T_DEF) #define _MIN (T_DEF|T_SHN) #define _PCS (T_SHN) #define _NUM (T_SHN) #define _DOL2 (T_SHN) #define _PLS (T_DEF|T_SET) #define _AT (T_AST) #define _QU (T_DEF|T_FNG|T_SHN) /* abbreviations for tests */ #define _IDCH (T_IDC|T_DIG) #define _META (T_SPC|T_DIP|T_MET|T_EOR) char _ctype1[]; /* nb these args are not call by value !!!! */ #define space(c) (((c)"E)==0 ANDF _ctype1[c]&(T_SPC)) #define eofmeta(c) (((c)"E)==0 ANDF _ctype1[c]&(_META|T_EOF)) #define qotchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_QOT)) #define eolchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_EOR|T_EOF)) #define dipchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_DIP)) #define subchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_SUB|T_QOT)) #define escchar(c) (((c)"E)==0 ANDF _ctype1[c]&(T_ESC)) char _ctype2[]; #define digit(c) (((c)"E)==0 ANDF _ctype2[c]&(T_DIG)) #define fngchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_FNG)) #define dolchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_AST|T_BRC|T_DIG|T_IDC|T_SHN)) #define defchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_DEF)) #define setchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_SET)) #define digchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_AST|T_DIG)) #define letter(c) (((c)"E)==0 ANDF _ctype2[c]&(T_IDC)) #define alphanum(c) (((c)"E)==0 ANDF _ctype2[c]&(_IDCH)) #define astchar(c) (((c)"E)==0 ANDF _ctype2[c]&(T_AST)) r->regcom=cmd(0,NLFLG|MTFLG); IF wdval==ECSYM THEN r->regnxt=syncase(esym); ELSE chksym(esym); r->regnxt=0; FI return(r); FI } /* * item * * ( cmd ) [ < in ] [ > out ] * word word* [ < in ] [ > out ] * if ... then ... elsbin/sh/defs.h 444 0 12 11064 3447444017 6333 /* defs.h 4.4 85/03/19 */ # /* * UNIX shell */ /* error exits from various parts of shell */ #define ERROR 1 #define SYNBAD 2 #define SIGFAIL 3 #define SIGFLG 0200 /* command tree */ #define FPRS 020 #define FINT 040 #define FAMP 0100 #define FPIN 0400 #define FPOU 01000 #define FPCL 02000 #define FCMD 04000 #define COMMSK 017 #define TCOM 0 #define TPAR 1 #define TFIL 2 #define TLST 3 #define TIF 4 #define TWH 5 #define TUN 6 #define TSW 7 #define TAND 8 #define TORF 9 #define TFORK 10 #define TFOR 11 /* execute table */ #define SYSSET 1 #define SYSCD 2 #define SYSEXEC 3 #define SYSLOGIN 4 #define SYSTRAP 5 #define SYSEXIT 6 #define SYSSHFT 7 #define SYSWAIT 8 #define SYSCONT 9 #define SYSBREAK 10 #define SYSEVAL 11 #define SYSDOT 12 #define SYSRDONLY 13 #define SYSTIMES 14 #define SYSXPORT 15 #define SYSNULL 16 #define SYSREAD 17 #define SYSTST 18 #define SYSUMASK 19 /* used for input and output of shell */ #define INIO 10 #define OTIO 11 /*io nodes*/ #define USERIO 10 #define IOUFD 15 #define IODOC 16 #define IOPUT 32 #define IOAPP 64 #define IOMOV 128 #define IORDW 256 #define INPIPE 0 #define OTPIPE 1 /* arg list terminator */ #define ENDARGS 0 #include "mac.h" #include "mode.h" #include "name.h" /* result type declarations */ #define alloc malloc ADDRESS alloc(); VOID addblok(); STRING make(); STRING movstr(); TREPTR cmd(); TREPTR makefork(); NAMPTR lookup(); VOID setname(); VOID setargs(); DOLPTR useargs(); REAL expr(); STRING catpath(); STRING getpath(); STRING *scan(); STRING mactrim(); STRING macro(); STRING execs(); VOID await(); VOID post(); STRING copyto(); VOID exname(); STRING staknam(); VOID printnam(); VOID printflg(); VOID prs(); VOID prc(); VOID setupenv(); STRING *setenv(); #define attrib(n,f) (n->namflg |= f) #define round(a,b) (((int)((ADR(a)+b)-1))&~((b)-1)) #define closepipe(x) (close(x[INPIPE]), close(x[OTPIPE])) #define eq(a,b) (cf(a,b)==0) #define max(a,b) ((a)>(b)?(a):(b)) #define assert(x) ; /* temp files and io */ UFD output; INT ioset; IOPTR iotemp; /* files to be deleted sometime */ IOPTR iopend; /* documents waiting to be read at NL */ /* substitution */ INT dolc; STRING *dolv; DOLPTR argfor; ARGPTR gchain; /* stack */ #define BLK(x) ((BLKPTR)(x)) #define BYT(x) ((BYTPTR)(x)) #define STK(x) ((STKPTR)(x)) #define ADR(x) ((char*)(x)) /* stak stuff */ #include "stak.h" /* string constants */ MSG atline; MSG readmsg; MSG colon; MSG minus; MSG nullstr; MSG sptbnl; MSG unexpected; MSG endoffile; MSG synmsg; /* name tree and words */ SYSTAB reserved; INT wdval; INT wdnum; ARGPTR wdarg; INT wdset; BOOL reserv; /* prompting */ MSG stdprompt; MSG supprompt; MSG profile; /* built in names */ NAMNOD fngnod; NAMNOD ifsnod; NAMNOD homenod; NAMNOD mailnod; NAMNOD pathnod; NAMNOD ps1nod; NAMNOD ps2nod; /* special names */ MSG flagadr; STRING cmdadr; STRING exitadr; STRING dolladr; STRING pcsadr; STRING pidadr; MSG defpath; /* names always present */ MSG mailname; MSG homename; MSG pathname; MSG fngname; MSG ifsname; MSG ps1name; MSG ps2name; /* transput */ CHAR tmpout[]; STRING tmpnam; INT serial; #define TMPNAM 7 FILE standin; #define input (standin->fdes) #define eof (standin->feof) INT peekc; STRING comdiv; MSG devnull; /* flags */ #define noexec 01 #define intflg 02 #define prompt 04 #define setflg 010 #define errflg 020 #define ttyflg 040 #define forked 0100 #define oneflg 0200 #define rshflg 0400 #define waiting 01000 #define stdflg 02000 #define execpr 04000 #define readpr 010000 #define keyflg 020000 #define batchflg 040000 INT flags; /* error exits from various parts of shell */ #include jmp_buf subshell; jmp_buf errshell; jmp_buf INTbuf; /* fault handling */ #include "brkincr.h" POS brkincr; #define MINTRAP 0 #define MAXTRAP 32 #define INTR 2 #define QUIT 3 #define MEMF 11 #define ALARM 14 #define KILL 15 #define TRAPSET 2 #define SIGSET 4 #define SIGMOD 8 VOID fault(); BOOL trapnote; STRING trapcom[]; BOOL trapflg[]; BOOL trapjmp[]; /* name tree and words */ STRING *environ; CHAR numbuf[]; MSG export; MSG readonly; /* execflgs */ INT exitval; BOOL execbrk; INT loopcnt; INT breakcnt; /* messages */ MSG mailmsg; MSG coredump; MSG badopt; MSG badparam; MSG badsub; MSG nospace; MSG notfound; MSG badtrap; MSG baddir; MSG badshift; MSG illegal; MSG restricted; MSG execpmsg; MSG notid; MSG wtfailed; MSG badcreate; MSG piperr; MSG badopen; MSG badnum; MSG arglist; MSG txtbsy; MSG toobig; MSG badexec; MSG notfound; MSG badfile; address end[]; #include "ctype.h" 128 #define IORDW 256 #define INPIPE 0 #define OTPIPE 1 /* arg list terminator */ #define ENDARGS 0 #include "mac.h" #include "mode.h" #include "name.h" /* result type declarations */ #define alloc malloc ADDRESS alloc(); VOID addblok(); STRING make(); STRING movstr(); TREPTR cmd(); TREPTR makefork(); NAMPTR lookup(); VOID setname(); VOID setargs(); DOLPTR useargs(); REAL expr(); STRING catpath(); STRING getpath(); STRING *scan(); STRINGbin/sh/dup.h 444 0 12 173 2731034227 6132 /* dup.h 4.1 82/05/07 */ # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #define DUPFLG 0100 ctype.hc°defs.hc¯ dup.h®error.cc­expand.c¬fault.c« io.c.ªmacro.c©main.c¨mode.h§ msg.c¦name.c¥name.h¤print.c£ service.c¢setbrk.c¡stak.cc stak.hcŸstring.cž sym.h timeout.hœword.c.h› xec.cšMakefile™$mac.hbin/sh/error.c 444 0 12 2214 3146337636 6517 #ifndef lint static char sccsid[] = "@(#)error.c 4.2 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" /* ======== error handling ======== */ exitset() { assnum(&exitadr,exitval); } sigchk() { /* Find out if it is time to go away. * `trapnote' is set to SIGSET when fault is seen and * no trap has been set. */ IF trapnote&SIGSET THEN exitsh(SIGFAIL); FI } failed(s1,s2) STRING s1, s2; { prp(); prs(s1); IF s2 THEN prs(colon); prs(s2); FI newline(); exitsh(ERROR); } error(s) STRING s; { failed(s,NIL); } exitsh(xno) INT xno; { /* Arrive here from `FATAL' errors * a) exit command, * b) default trap, * c) fault with no trap set. * * Action is to return to command level or exit. */ exitval=xno; IF (flags & (forked|errflg|ttyflg)) != ttyflg THEN done(); ELSE clearup(); longjmp(errshell,1); FI } done() { REG STRING t; IF t=trapcom[0] THEN trapcom[0]=0; /*should free but not long */ execexp(t,0); FI rmtemp(0); exit(exitval); } rmtemp(base) IOPTR base; { WHILE iotemp>base DO unlink(iotemp->ioname); iotemp=iotemp->iolst; OD } ine ENDARGS 0 #include "mac.h" #include "mode.h" #include "name.h" /* result type declarations */ #define alloc malloc ADDRESS alloc(); VOID addblok(); STRING make(); STRING movstr(); TREPTR cmd(); TREPTR makefork(); NAMPTR lookup(); VOID setname(); VOID setargs(); DOLPTR useargs(); REAL expr(); STRING catpath(); STRING getpath(); STRING *scan(); STRINGbin/sh/expand.c 444 0 12 5732 3146337641 6651 #ifndef lint static char sccsid[] = "@(#)expand.c 4.5 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" #include #include #include /* globals (file name generation) * * "*" in params matches r.e ".*" * "?" in params matches r.e. "." * "[...]" in params matches character class * "[...a-z...]" in params matches a through z. * */ PROC VOID addg(); INT expand(as,rflg) STRING as; { INT count; DIR *dirf; BOOL dir=0; STRING rescan = 0; REG STRING s, cs; ARGPTR schain = gchain; struct direct *dp; STATBUF statb; IF trapnote&SIGSET THEN return(0); FI s=cs=as; /* check for meta chars */ BEGIN REG BOOL slash; slash=0; WHILE !fngchar(*cs) DO IF *cs++==0 THEN IF rflg ANDF slash THEN break; ELSE return(0) FI ELIF *cs=='/' THEN slash++; FI OD END LOOP IF cs==s THEN s=nullstr; break; ELIF *--cs == '/' THEN *cs=0; IF s==cs THEN s="/" FI break; FI POOL IF stat(s,&statb)>=0 ANDF (statb.st_mode&S_IFMT)==S_IFDIR ANDF (dirf=opendir(s)) != NULL THEN dir++; FI count=0; IF *cs==0 THEN *cs++=0200 FI IF dir THEN /* check for rescan */ REG STRING rs; rs=cs; REP IF *rs=='/' THEN rescan=rs; *rs=0; gchain=0 FI PER *rs++ DONE IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI WHILE (trapnote&SIGSET) == 0 ANDF (dp = readdir(dirf)) != NULL DO IF (*dp->d_name=='.' ANDF *cs!='.') THEN continue; FI IF gmatch(dp->d_name, cs) THEN addg(s,dp->d_name,rescan); count++; FI OD closedir(dirf); trapjmp[INTR] = 0; IF rescan THEN REG ARGPTR rchain; rchain=gchain; gchain=schain; IF count THEN count=0; WHILE rchain DO count += expand(rchain->argval,1); rchain=rchain->argnxt; OD FI *rescan='/'; FI FI BEGIN REG CHAR c; s=as; WHILE c = *s DO *s++=(c&STRIP?c:'/') OD END return(count); } gmatch(s, p) REG STRING s, p; { REG INT scc; CHAR c; IF scc = *s++ THEN IF (scc &= STRIP)==0 THEN scc=0200; FI FI SWITCH c = *p++ IN case '[': {BOOL ok; INT lc; ok=0; lc=077777; WHILE c = *p++ DO IF c==']' THEN return(ok?gmatch(s,p):0); ELIF c==MINUS THEN IF lc<=scc ANDF scc<=(*p++) THEN ok++ FI ELSE IF scc==(lc=(c&STRIP)) THEN ok++ FI FI OD return(0); } default: IF (c&STRIP)!=scc THEN return(0) FI case '?': return(scc?gmatch(s,p):0); case '*': IF *p==0 THEN return(1) FI --s; WHILE *s DO IF gmatch(s++,p) THEN return(1) FI OD return(0); case 0: return(scc==0); ENDSW } LOCAL VOID addg(as1,as2,as3) STRING as1, as2, as3; { REG STRING s1, s2; REG INT c; s2 = locstak()+BYTESPERWORD; s1=as1; WHILE c = *s1++ DO IF (c &= STRIP)==0 THEN *s2++='/'; break; FI *s2++=c; OD s1=as2; WHILE *s2 = *s1++ DO s2++ OD IF s1=as3 THEN *s2++='/'; WHILE *s2++ = *++s1 DONE FI makearg(endstak(s2)); } makearg(args) REG STRING args; { args->argnxt=gchain; gchain=args; } MSG homename; MSG pathname; MSG fngbin/sh/fault.c 444 0 12 2754 3146337643 6510 #ifndef lint static char sccsid[] = "@(#)fault.c 4.3 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" STRING trapcom[MAXTRAP]; BOOL trapflg[MAXTRAP]; BOOL trapjmp[MAXTRAP]; /* ======== fault handling routines ======== */ VOID fault(sig) REG INT sig; { REG INT flag; IF sig==MEMF THEN IF setbrk(brkincr) == -1 THEN error(nospace); FI ELIF sig==ALARM THEN IF flags&waiting THEN done(); FI ELSE flag = (trapcom[sig] ? TRAPSET : SIGSET); trapnote |= flag; trapflg[sig] |= flag; FI IF trapjmp[sig] ANDF sig==INTR THEN trapjmp[sig] = 0; longjmp(INTbuf, 1); FI } stdsigs() { ignsig(QUIT); getsig(INTR); getsig(MEMF); getsig(ALARM); } ignsig(n) { REG INT s, i; IF (s=signal(i=n,1)&01)==0 THEN trapflg[i] |= SIGMOD; FI return(s); } getsig(n) { REG INT i; IF trapflg[i=n]&SIGMOD ORF ignsig(i)==0 THEN signal(i,fault); FI } oldsigs() { REG INT i; REG STRING t; i=MAXTRAP; WHILE i-- DO t=trapcom[i]; IF t==0 ORF *t THEN clrsig(i); FI trapflg[i]=0; OD trapnote=0; } clrsig(i) INT i; { free(trapcom[i]); trapcom[i]=0; IF trapflg[i]&SIGMOD THEN signal(i,fault); trapflg[i] &= ~SIGMOD; FI } chktrap() { /* check for traps */ REG INT i=MAXTRAP; REG STRING t; trapnote &= ~TRAPSET; WHILE --i DO IF trapflg[i]&TRAPSET THEN trapflg[i] &= ~TRAPSET; IF t=trapcom[i] THEN INT savxit=exitval; execexp(t,0); exitval=savxit; exitset(); FI FI OD } ->d_name, cs) THEbin/sh/io.c 444 0 12 3564 3447443025 6000 #ifndef lint static char sccsid[] = "@(#)io.c 4.3 3/19/85"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" /* ======== input output and file copying ======== */ initf(fd) UFD fd; { REG FILE f=standin; f->fdes=fd; f->fsiz=((flags&(oneflg|ttyflg))==0 ? BUFSIZ : 1); f->fnxt=f->fend=f->fbuf; f->feval=0; f->flin=1; f->feof=FALSE; } estabf(s) REG STRING s; { REG FILE f; (f=standin)->fdes = -1; f->fend=length(s)+(f->fnxt=s); f->flin=1; return(f->feof=(s==0)); } push(af) FILE af; { REG FILE f; (f=af)->fstak=standin; f->feof=0; f->feval=0; standin=f; } pop() { REG FILE f; IF (f=standin)->fstak THEN IF f->fdes>=0 THEN close(f->fdes) FI standin=f->fstak; return(TRUE); ELSE return(FALSE); FI } chkpipe(pv) INT *pv; { IF pipe(pv)<0 ORF pv[INPIPE]<0 ORF pv[OTPIPE]<0 THEN error(piperr); FI } chkopen(idf) STRING idf; { REG INT rc; IF (rc=open(idf,0))<0 THEN failed(idf,badopen); ELSE return(rc); FI } rename(f1,f2) REG INT f1, f2; { IF f1!=f2 THEN dup2(f1, f2); close(f1); IF f2==0 THEN ioset|=1 FI FI } create(s) STRING s; { REG INT rc; IF (rc=creat(s,0666))<0 THEN failed(s,badcreate); ELSE return(rc); FI } tmpfil() { itos(serial++); movstr(numbuf,tmpnam); return(create(tmpout)); } /* set by trim */ BOOL nosubst; copy(ioparg) IOPTR ioparg; { CHAR c, *ends; REG CHAR *cline, *clinep; INT fd; REG IOPTR iop; IF iop=ioparg THEN copy(iop->iolst); ends=mactrim(iop->ioname); IF nosubst THEN iop->iofile &= ~IODOC FI fd=tmpfil(); iop->ioname=cpystak(tmpout); iop->iolst=iotemp; iotemp=iop; cline=locstak(); LOOP clinep=cline; chkpr(NL); WHILE (c = (nosubst ? readc() : nextc(*ends)), !eolchar(c)) DO *clinep++ = c OD *clinep=0; IF eof ORF eq(cline,ends) THEN break FI *clinep++=NL; write(fd,cline,clinep-cline); POOL close(fd); FI } ++=(c&STRIP?c:'/') OD END return(count); } gmatch(s, p) REG STRING s, p; { REG INT scc; CHAR c; IF scc = *s++ THEN IF (scc &= STRbin/sh/macro.c 444 0 12 10065 3146337650 6506 #ifndef lint static char sccsid[] = "@(#)macro.c 4.3 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" #include "sym.h" LOCAL CHAR quote; /* used locally */ LOCAL CHAR quoted; /* used locally */ LOCAL STRING copyto(endch) REG CHAR endch; { REG CHAR c; WHILE (c=getch(endch))!=endch ANDF c DO pushstak(c|quote) OD zerostak(); IF c!=endch THEN error(badsub) FI } LOCAL skipto(endch) REG CHAR endch; { /* skip chars up to } */ REG CHAR c; WHILE (c=readc()) ANDF c!=endch DO SWITCH c IN case SQUOTE: skipto(SQUOTE); break; case DQUOTE: skipto(DQUOTE); break; case DOLLAR: IF readc()==BRACE THEN skipto('}'); FI ENDSW OD IF c!=endch THEN error(badsub) FI } LOCAL getch(endch) CHAR endch; { REG CHAR d; retry: d=readc(); IF !subchar(d) THEN return(d); FI IF d==DOLLAR THEN REG INT c; IF (c=readc(), dolchar(c)) THEN NAMPTR n=NIL; INT dolg=0; BOOL bra; REG STRING argp, v; CHAR idb[2]; STRING id=idb; IF bra=(c==BRACE) THEN c=readc() FI IF letter(c) THEN argp=relstak(); WHILE alphanum(c) DO pushstak(c); c=readc() OD zerostak(); n=lookup(absstak(argp)); setstak(argp); v = n->namval; id = n->namid; peekc = c|MARK;; ELIF digchar(c) THEN *id=c; idb[1]=0; IF astchar(c) THEN dolg=1; c='1'; FI c -= '0'; v=((c==0) ? cmdadr : (c<=dolc) ? dolv[c] : (dolg=0)); ELIF c=='$' THEN v=pidadr; ELIF c=='!' THEN v=pcsadr; ELIF c=='#' THEN v=dolladr; ELIF c=='?' THEN v=exitadr; ELIF c=='-' THEN v=flagadr; ELIF bra THEN error(badsub); ELSE goto retry; FI c = readc(); IF !defchar(c) ANDF bra THEN error(badsub); FI argp=0; IF bra THEN IF c!='}' THEN argp=relstak(); IF (v==0)NEQ(setchar(c)) THEN copyto('}'); ELSE skipto('}'); FI argp=absstak(argp); FI ELSE peekc = c|MARK; c = 0; FI IF v THEN IF c!='+' THEN LOOP WHILE c = *v++ DO pushstak(c|quote); OD IF dolg==0 ORF (++dolg>dolc) THEN break; ELSE v=dolv[dolg]; pushstak(SP|(*id=='*' ? quote : 0)); FI POOL FI ELIF argp THEN IF c=='?' THEN failed(id,*argp?argp:badparam); ELIF c=='=' THEN IF n THEN assign(n,argp); ELSE error(badsub); FI FI ELIF flags&setflg THEN failed(id,badparam); FI goto retry; ELSE peekc=c|MARK; FI ELIF d==endch THEN return(d); ELIF d==SQUOTE THEN comsubst(); goto retry; ELIF d==DQUOTE THEN quoted++; quote^=QUOTE; goto retry; FI return(d); } STRING macro(as) STRING as; { /* Strip "" and do $ substitution * Leaves result on top of stack */ REG BOOL savqu =quoted; REG CHAR savq = quote; FILEHDR fb; push(&fb); estabf(as); usestak(); quote=0; quoted=0; copyto(0); pop(); IF quoted ANDF (stakbot==staktop) THEN pushstak(QUOTE) FI quote=savq; quoted=savqu; return(fixstak()); } LOCAL comsubst() { /* command substn */ FILEBLK cb; REG CHAR d; REG STKPTR savptr = fixstak(); usestak(); WHILE (d=readc())!=SQUOTE ANDF d DO pushstak(d) OD BEGIN REG STRING argc; trim(argc=fixstak()); push(&cb); estabf(argc); END BEGIN REG TREPTR t = makefork(FPOU,cmd(EOFSYM,MTFLG|NLFLG)); INT pv[2]; /* this is done like this so that the pipe * is open only when needed */ chkpipe(pv); initf(pv[INPIPE]); execute(t, 0, 0, pv); close(pv[OTPIPE]); END tdystak(savptr); staktop=movstr(savptr,stakbot); WHILE d=readc() DO locstak(); pushstak(d|quote) OD await(0); WHILE stakbot!=staktop DO IF (*--staktop&STRIP)!=NL THEN ++staktop; break; FI OD pop(); } #define CPYSIZ 512 subst(in,ot) INT in, ot; { REG CHAR c; FILEBLK fb; REG INT count=CPYSIZ; push(&fb); initf(in); /* DQUOTE used to stop it from quoting */ WHILE c=(getch(DQUOTE)&STRIP) DO pushstak(c); IF --count == 0 THEN flush(ot); count=CPYSIZ; FI OD flush(ot); pop(); } LOCAL flush(ot) { write(ot,stakbot,staktop-stakbot); IF flags&execpr THEN write(output,stakbot,staktop-stakbot) FI staktop=stakbot; } 0); FI case 0: BEGIN REG ARGPTR argp; REG ARGPTR *argtail; REG ARGPTR *argset=0; INT keywd=1; t=getstak(COMTYPE); t->comio=io; /*initial io chain*/ argtail = &(t->comarg); WHILE wdval==0 DO argp = wdarg; IF wdset ANDF keywd THEN argp->argnxt=argset; argset=argp; ELSE *argtail=argp; argtail = &(argp->argnxt); keywd=flags&keyflg; FI word(); IF flag THEN t->comio=inout(t->comio); bin/sh/main.c 444 0 12 6254 3562015617 6314 #ifndef lint static char sccsid[] = "@(#)main.c 4.3 3/19/85"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" #include "sym.h" #include "timeout.h" #include #include #include #include UFD output = 2; LOCAL BOOL beenhere = FALSE; CHAR tmpout[20] = "/tmp/sh-"; FILEBLK stdfile; FILE standin = &stdfile; #ifdef stupid #include #endif PROC VOID exfile(); main(c, v) INT c; STRING v[]; { REG INT rflag=ttyflg; /* initialise storage allocation */ stdsigs(); setbrk(BRKINCR); addblok((POS)0); /* set names from userenv */ setupenv(); /* look for restricted */ /* IF c>0 ANDF any('r', *v) THEN rflag=0 FI */ /* look for options */ dolc=options(c,v); IF dolc<2 THEN flags |= stdflg FI IF (flags&stdflg)==0 THEN dolc--; FI dolv=v+c-dolc; dolc--; /* return here for shell file execution */ setjmp(subshell); /* number of positional parameters */ assnum(&dolladr,dolc); cmdadr=dolv[0]; /* set pidname */ assnum(&pidadr, getpid()); /* set up temp file names */ settmp(); /* default ifs */ dfault(&ifsnod, sptbnl); IF (beenhere++)==FALSE THEN /* ? profile */ IF *cmdadr=='-' ANDF (input=pathopen(nullstr, profile))>=0 THEN exfile(rflag); flags &= ~ttyflg; FI IF rflag==0 THEN flags |= rshflg FI /* open input file if specified */ IF comdiv THEN estabf(comdiv); input = -1; ELSE input=((flags&stdflg) ? 0 : chkopen(cmdadr)); comdiv--; FI #ifdef stupid ELSE *execargs=dolv; /* for `ps' cmd */ #endif FI exfile(0); done(); } LOCAL VOID exfile(prof) BOOL prof; { REG L_INT mailtime = 0; REG INT userid; struct stat statb; /* move input */ IF input>0 THEN Ldup(input,INIO); input=INIO; FI /* move output to safe place */ IF output==2 THEN Ldup(dup(2),OTIO); output=OTIO; FI userid=getuid(); /* decide whether interactive */ IF (flags&intflg) ORF ((flags&oneflg)==0 ANDF gtty(output,&statb)==0 ANDF gtty(input,&statb)==0) THEN dfault(&ps1nod, (userid?stdprompt:supprompt)); dfault(&ps2nod, readmsg); flags |= ttyflg|prompt; ignsig(KILL); /* { #include signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN); signal(SIGTSTP, SIG_IGN); } */ ELSE flags |= prof; flags &= ~prompt; FI IF setjmp(errshell) ANDF prof THEN close(input); return; FI /* error return here */ loopcnt=breakcnt=peekc=0; iopend=0; IF input>=0 THEN initf(input) FI /* command loop */ LOOP tdystak(0); stakchk(); /* may reduce sbrk */ exitset(); IF (flags&prompt) ANDF standin->fstak==0 ANDF !eof THEN IF mailnod.namval ANDF stat(mailnod.namval,&statb)>=0 ANDF statb.st_size ANDF (statb.st_mtime != mailtime) ANDF mailtime THEN prs(mailmsg) FI mailtime=statb.st_mtime; prs(ps1nod.namval); FI trapnote=0; peekc=readc(); IF eof THEN return; FI execute(cmd(NL,MTFLG),0); eof |= (flags&oneflg); POOL } chkpr(eor) char eor; { IF (flags&prompt) ANDF standin->fstak==0 ANDF eor==NL THEN prs(ps2nod.namval); FI } settmp() { itos(getpid()); serial=0; tmpnam=movstr(numbuf,&tmpout[TMPNAM]); } Ldup(fa, fb) REG INT fa, fb; { dup2(fa, fb); close(fa); ioctl(fb, FIOCLEX, 0); } N /* ? profile */ IF *cmdadr=='-' ANDF (input=pathopen(nullstr, profile))>=0 THEN exfile(rflag); flags &= ~ttyflg; FI IF rflag==0 THEN flags |= rshflg FI /* open input file if specified */ IF comdiv THEN estabf(comdiv); input = -1; ELSE input=((flags&stdflg) ? 0 : chkopen(cmdadr)); comdiv--; FI #ifdef stupid Ebin/sh/mode.h 444 0 12 6244 2731034232 6307 /* mode.h 4.1 82/05/07 */ # /* * UNIX shell */ #define BYTESPERWORD (sizeof(char *)) TYPE char CHAR; TYPE char BOOL; TYPE int UFD; TYPE int INT; TYPE float REAL; TYPE char *ADDRESS; TYPE long int L_INT; TYPE int VOID; TYPE unsigned POS; TYPE char *STRING; TYPE char MSG[]; TYPE int PIPE[]; TYPE char *STKPTR; TYPE char *BYTPTR; STRUCT stat STATBUF; /* defined in /usr/sys/stat.h */ STRUCT blk *BLKPTR; STRUCT fileblk FILEBLK; STRUCT filehdr FILEHDR; STRUCT fileblk *FILE; STRUCT trenod *TREPTR; STRUCT forknod *FORKPTR; STRUCT comnod *COMPTR; STRUCT swnod *SWPTR; STRUCT regnod *REGPTR; STRUCT parnod *PARPTR; STRUCT ifnod *IFPTR; STRUCT whnod *WHPTR; STRUCT fornod *FORPTR; STRUCT lstnod *LSTPTR; STRUCT argnod *ARGPTR; STRUCT dolnod *DOLPTR; STRUCT ionod *IOPTR; STRUCT namnod NAMNOD; STRUCT namnod *NAMPTR; STRUCT sysnod SYSNOD; STRUCT sysnod *SYSPTR; STRUCT sysnod SYSTAB[]; #define NIL ((char*)0) /* the following nonsense is required * because casts turn an Lvalue * into an Rvalue so two cheats * are necessary, one for each context. */ union { int _cheat;}; #define Lcheat(a) ((a)._cheat) #define Rcheat(a) ((int)(a)) /* address puns for storage allocation */ UNION { FORKPTR _forkptr; COMPTR _comptr; PARPTR _parptr; IFPTR _ifptr; WHPTR _whptr; FORPTR _forptr; LSTPTR _lstptr; BLKPTR _blkptr; NAMPTR _namptr; BYTPTR _bytptr; } address; /* for functions that do not return values */ /* struct void {INT vvvvvvvv;}; */ /* heap storage */ struct blk { BLKPTR word; }; #define BUFSIZ 64 struct fileblk { UFD fdes; POS flin; BOOL feof; CHAR fsiz; STRING fnxt; STRING fend; STRING *feval; FILE fstak; CHAR fbuf[BUFSIZ]; }; /* for files not used with file descriptors */ struct filehdr { UFD fdes; POS flin; BOOL feof; CHAR fsiz; STRING fnxt; STRING fend; STRING *feval; FILE fstak; CHAR _fbuf[1]; }; struct sysnod { STRING sysnam; INT sysval; }; /* this node is a proforma for those that follow */ struct trenod { INT tretyp; IOPTR treio; }; /* dummy for access only */ struct argnod { ARGPTR argnxt; CHAR argval[1]; }; struct dolnod { DOLPTR dolnxt; INT doluse; CHAR dolarg[1]; }; struct forknod { INT forktyp; IOPTR forkio; TREPTR forktre; }; struct comnod { INT comtyp; IOPTR comio; ARGPTR comarg; ARGPTR comset; }; struct ifnod { INT iftyp; TREPTR iftre; TREPTR thtre; TREPTR eltre; }; struct whnod { INT whtyp; TREPTR whtre; TREPTR dotre; }; struct fornod { INT fortyp; TREPTR fortre; STRING fornam; COMPTR forlst; }; struct swnod { INT swtyp; STRING swarg; REGPTR swlst; }; struct regnod { ARGPTR regptr; TREPTR regcom; REGPTR regnxt; }; struct parnod { INT partyp; TREPTR partre; }; struct lstnod { INT lsttyp; TREPTR lstlef; TREPTR lstrit; }; struct ionod { INT iofile; STRING ioname; IOPTR ionxt; IOPTR iolst; }; #define FORKTYPE (sizeof(struct forknod)) #define COMTYPE (sizeof(struct comnod)) #define IFTYPE (sizeof(struct ifnod)) #define WHTYPE (sizeof(struct whnod)) #define FORTYPE (sizeof(struct fornod)) #define SWTYPE (sizeof(struct swnod)) #define REGTYPE (sizeof(struct regnod)) #define PARTYPE (sizeof(struct parnod)) #define LSTTYPE (sizeof(struct lstnod)) #define IOTYPE (sizeof(struct ionod)) GIN REG TREPTR t = makefork(FPOU,cmd(EOFSYM,MTFLG|NLFLG)); INT pv[2]; /* this is done like this so that the pipe * is open only when needed */ chkpipe(pv); initf(pv[INPIPE]); execute(t, 0, 0, pv); close(pv[OTPIPE]); END tdystak(savptr); staktop=movstr(savptr,stakbot); WHILE d=readc() DO locstak(); pushstbin/sh/msg.c 444 0 12 6127 4001650300 6134 #ifndef lint static char sccsid[] = "@(#)msg.c 4.4 5/22/85"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" #include "sym.h" MSG version = "\nVERSION sys137 DATE 1978 Nov 6 14:29:22\n"; /* error messages */ MSG badopt = "bad option(s)"; MSG mailmsg = "you have mail\n"; MSG nospace = "no space"; MSG synmsg = "syntax error"; MSG badnum = "bad number"; MSG badparam = "parameter not set"; MSG badsub = "bad substitution"; MSG badcreate = "cannot create"; MSG illegal = "illegal io"; MSG restricted = "restricted"; MSG piperr = "cannot make pipe"; MSG badopen = "cannot open"; MSG coredump = " - core dumped"; MSG arglist = "arg list too long"; MSG txtbsy = "text busy"; MSG toobig = "too big"; MSG badexec = "cannot execute"; MSG notfound = "not found"; MSG badfile = "bad file number"; MSG badshift = "cannot shift"; MSG baddir = "bad directory"; MSG badtrap = "bad trap"; MSG wtfailed = "is read only"; MSG notid = "is not an identifier"; /* built in names */ MSG pathname = "PATH"; MSG homename = "HOME"; MSG mailname = "MAIL"; MSG fngname = "FILEMATCH"; MSG ifsname = "IFS"; MSG ps1name = "PS1"; MSG ps2name = "PS2"; /* string constants */ MSG nullstr = ""; MSG sptbnl = " \t\n"; MSG defpath = ":/bin:/usr/bin"; MSG colon = ": "; MSG minus = "-"; MSG endoffile = "end of file"; MSG unexpected = " unexpected"; MSG atline = " at line "; MSG devnull = "/dev/null"; MSG execpmsg = "+ "; MSG readmsg = "> "; MSG stdprompt = "$ "; MSG supprompt = "# "; MSG profile = ".profile"; /* tables */ SYSTAB reserved = { {"in", INSYM}, {"esac", ESSYM}, {"case", CASYM}, {"for", FORSYM}, {"done", ODSYM}, {"if", IFSYM}, {"while", WHSYM}, {"do", DOSYM}, {"then", THSYM}, {"else", ELSYM}, {"elif", EFSYM}, {"fi", FISYM}, {"until", UNSYM}, { "{", BRSYM}, { "}", KTSYM}, {0, 0}, }; STRING sysmsg[] = { 0, "Hangup", 0, /* Interrupt */ "Quit", "Illegal instruction", "Trace/BPT trap", "IOT trap", "EMT trap", "Floating exception", "Killed", "Bus error", "Memory fault", "Bad system call", 0, /* Broken pipe */ "Alarm call", "Terminated", "Urgent condition", "Stopped", "Stopped from terminal", "Continued", "Child terminated", "Stopped on terminal input", "Stopped on terminal output", "Asynchronous I/O", "Exceeded cpu time limit", "Exceeded file size limit", "Virtual time alarm", "Profiling time alarm", "Window changed", "Signal 29", "User defined signal 1", "User defined signal 2", "Signal 32", }; INT num_sysmsg = (sizeof sysmsg / sizeof sysmsg[0]); MSG export = "export"; MSG readonly = "readonly"; SYSTAB commands = { {"cd", SYSCD}, {"read", SYSREAD}, /* {"[", SYSTST}, */ {"set", SYSSET}, {":", SYSNULL}, {"trap", SYSTRAP}, {"login", SYSLOGIN}, {"wait", SYSWAIT}, {"eval", SYSEVAL}, {".", SYSDOT}, {readonly, SYSRDONLY}, {export, SYSXPORT}, {"chdir", SYSCD}, {"break", SYSBREAK}, {"continue", SYSCONT}, {"shift", SYSSHFT}, {"exit", SYSEXIT}, {"exec", SYSEXEC}, {"times", SYSTIMES}, {"umask", SYSUMASK}, {0, 0}, }; fine LSTTYPE (sizeof(struct lstnod)) #define IOTYPE (sizeof(struct ionod)) GIN REG TREPTR t = makefork(FPOU,cmd(EOFSYM,MTFLG|NLFLG)); INT pv[2]; /* this is done like this so that the pipe * is open only when needed */ chkpipe(pv); initf(pv[INPIPE]); execute(t, 0, 0, pv); close(pv[OTPIPE]); END tdystak(savptr); staktop=movstr(savptr,stakbot); WHILE d=readc() DO locstak(); pushstbin/sh/name.c 444 0 12 11364 3565235365 6335 #ifndef lint static char sccsid[] = "@(#)name.c 4.4 10/31/85"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" PROC BOOL chkid(); NAMNOD ps2nod = { NIL, NIL, ps2name}, fngnod = { NIL, NIL, fngname}, pathnod = { NIL, NIL, pathname}, ifsnod = { NIL, NIL, ifsname}, ps1nod = { &pathnod, &ps2nod, ps1name}, homenod = { &fngnod, &ifsnod, homename}, mailnod = { &homenod, &ps1nod, mailname}; NAMPTR namep = &mailnod; /* ======== variable and string handling ======== */ syslook(w,syswds) STRING w; SYSTAB syswds; { REG CHAR first; REG STRING s; REG SYSPTR syscan; syscan=syswds; first = *w; WHILE s=syscan->sysnam DO IF first == *s ANDF eq(w,s) THEN return(syscan->sysval); FI syscan++; OD return(0); } setlist(arg,xp) REG ARGPTR arg; INT xp; { WHILE arg DO REG STRING s=mactrim(arg->argval); setname(s, xp); arg=arg->argnxt; IF flags&execpr THEN prs(s); IF arg THEN blank(); ELSE newline(); FI FI OD } VOID setname(argi, xp) STRING argi; INT xp; { REG STRING argscan=argi; REG NAMPTR n; IF letter(*argscan) THEN WHILE alphanum(*argscan) DO argscan++ OD IF *argscan=='=' THEN *argscan = 0; n=lookup(argi); *argscan++ = '='; attrib(n, xp); IF xp&N_ENVNAM THEN /* * Importing IFS can be very dangerous */ IF !bcmp(argi, "IFS=", sizeof("IFS=") - 1) THEN int uid; IF (uid = getuid())!=geteuid() ORF !uid THEN return; FI FI n->namenv = n->namval = argscan; ELSE assign(n, argscan); FI return; FI FI failed(argi,notid); } replace(a, v) REG STRING *a; STRING v; { free(*a); *a=make(v); } dfault(n,v) NAMPTR n; STRING v; { IF n->namval==0 THEN assign(n,v) FI } assign(n,v) NAMPTR n; STRING v; { IF n->namflg&N_RDONLY THEN failed(n->namid,wtfailed); ELSE replace(&n->namval,v); FI } INT readvar(names) STRING *names; { FILEBLK fb; REG FILE f = &fb; REG CHAR c; REG INT rc=0; NAMPTR n=lookup(*names++); /* done now to avoid storage mess */ STKPTR rel=relstak(); push(f); initf(dup(0)); IF lseek(0,0L,1)==-1 THEN f->fsiz=1; FI LOOP c=nextc(0); IF (*names ANDF any(c, ifsnod.namval)) ORF eolchar(c) THEN zerostak(); assign(n,absstak(rel)); setstak(rel); IF *names THEN n=lookup(*names++); ELSE n=0; FI IF eolchar(c) THEN break; FI ELSE pushstak(c); FI POOL WHILE n DO assign(n, nullstr); IF *names THEN n=lookup(*names++); ELSE n=0; FI OD IF eof THEN rc=1 FI lseek(0, (long)(f->fnxt-f->fend), 1); pop(); return(rc); } assnum(p, i) STRING *p; INT i; { itos(i); replace(p,numbuf); } STRING make(v) STRING v; { REG STRING p; IF v THEN movstr(v,p=alloc(length(v))); return(p); ELSE return(0); FI } NAMPTR lookup(nam) REG STRING nam; { REG NAMPTR nscan=namep; REG NAMPTR *prev; INT LR; IF !chkid(nam) THEN failed(nam,notid); FI WHILE nscan DO IF (LR=cf(nam,nscan->namid))==0 THEN return(nscan); ELIF LR<0 THEN prev = &(nscan->namlft); ELSE prev = &(nscan->namrgt); FI nscan = *prev; OD /* add name node */ nscan=alloc(sizeof *nscan); nscan->namlft=nscan->namrgt=NIL; nscan->namid=make(nam); nscan->namval=0; nscan->namflg=N_DEFAULT; nscan->namenv=0; return(*prev = nscan); } LOCAL BOOL chkid(nam) STRING nam; { REG CHAR * cp=nam; IF !letter(*cp) THEN return(FALSE); ELSE WHILE *++cp DO IF !alphanum(*cp) THEN return(FALSE); FI OD FI return(TRUE); } LOCAL VOID (*namfn)(); namscan(fn) VOID (*fn)(); { namfn=fn; namwalk(namep); } LOCAL VOID namwalk(np) REG NAMPTR np; { IF np THEN namwalk(np->namlft); (*namfn)(np); namwalk(np->namrgt); FI } VOID printnam(n) NAMPTR n; { REG STRING s; sigchk(); IF s=n->namval THEN prs(n->namid); prc('='); prs(s); newline(); FI } LOCAL STRING staknam(n) REG NAMPTR n; { REG STRING p; p=movstr(n->namid,staktop); p=movstr("=",p); p=movstr(n->namval,p); return(getstak(p+1-ADR(stakbot))); } VOID exname(n) REG NAMPTR n; { IF n->namflg&N_EXPORT THEN free(n->namenv); n->namenv = make(n->namval); ELSE free(n->namval); n->namval = make(n->namenv); FI } VOID printflg(n) REG NAMPTR n; { IF n->namflg&N_EXPORT THEN prs(export); blank(); FI IF n->namflg&N_RDONLY THEN prs(readonly); blank(); FI IF n->namflg&(N_EXPORT|N_RDONLY) THEN prs(n->namid); newline(); FI } VOID setupenv() { REG STRING *e=environ; WHILE *e DO setname(*e++, N_ENVNAM) OD } LOCAL INT namec; VOID countnam(n) NAMPTR n; { namec++; } LOCAL STRING *argnam; VOID pushnam(n) NAMPTR n; { IF n->namval THEN *argnam++ = staknam(n); FI } STRING *setenv() { REG STRING *er; namec=0; namscan(countnam); argnam = er = getstak(namec*BYTESPERWORD+BYTESPERWORD); namscan(pushnam); *argnam++ = 0; return(er); } pr(NL) OD return(wdval); } LOCAL IOPTR inout(lastio) IOPTR lastio; { REG INT iof; REG IOPTR iop; REG CHAR c; iof=wdnum; SWITCH wdval IN case DOCSYM: iof |= IODOC; break; case APPSYM: case '>': IF wdnum==0 THEN iof |= 1 FI iof |= IOPUbin/sh/name.h 444 0 12 522 2731034233 6255 /* name.h 4.1 82/05/07 */ # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #define N_RDONLY 0100000 #define N_EXPORT 0040000 #define N_ENVNAM 0020000 #define N_ENVPOS 0007777 #define N_DEFAULT 0 struct namnod { NAMPTR namlft; NAMPTR namrgt; STRING namid; STRING namval; STRING namenv; INT namflg; }; service.c¢setbrk.c¡stak.cc stak.hcŸstring.cž sym.h timeout.hœword.c.h› xec.cšMakefile™$mac.hbin/sh/print.c 444 0 12 2173 3146337664 6527 #ifndef lint static char sccsid[] = "@(#)print.c 4.2 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" CHAR numbuf[6]; /* printing and io conversion */ newline() { prc(NL); } blank() { prc(SP); } prp() { IF (flags&prompt)==0 ANDF cmdadr THEN prs(cmdadr); prs(colon); FI } VOID prs(as) STRING as; { REG STRING s; IF s=as THEN write(output,s,length(s)-1); FI } VOID prc(c) CHAR c; { IF c THEN write(output,&c,1); FI } prt(t) L_INT t; { REG INT hr, min, sec; t += 30; t /= 60; sec=t%60; t /= 60; min=t%60; IF hr=t/60 THEN prn(hr); prc('h'); FI prn(min); prc('m'); prn(sec); prc('s'); } prn(n) INT n; { itos(n); prs(numbuf); } itos(n) { REG char *abuf; REG POS a, i; INT pr, d; abuf=numbuf; pr=FALSE; a=n; FOR i=10000; i!=1; i/=10 DO IF (pr |= (d=a/i)) THEN *abuf++=d+'0' FI a %= i; OD *abuf++=a+'0'; *abuf++=0; } stoi(icp) STRING icp; { REG CHAR *cp = icp; REG INT r = 0; REG CHAR c; WHILE (c = *cp, digit(c)) ANDF c ANDF r>=0 DO r = r*10 + c - '0'; cp++ OD IF r<0 ORF cp==icp THEN failed(icp,badnum); ELSE return(r); FI } ) THEN WHILE alphanum(*argscan) DO argscan++ OD IF *argscan=='=' THEN *argscan = 0; n=lookup(argi); *argscan++ = '='; attrib(n, xp); IF xp&N_ENVNAM THEN /* * Importing IFS can be very dangerous */ IF !bcmp(argi, "IFS=", sizeof("IFS=") - 1) THEN int uid; IF (uid = getuid())!=geteuid() ORF !uid THEN return; FI FI bin/sh/service.c 444 0 12 14470 5672226144 7052 #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)service.c 4.4.1 12/9/94"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" #include PROC VOID gsort(); #define ARGMK 01 INT errno; STRING sysmsg[]; INT num_sysmsg; /* fault handling */ #define ENOMEM 12 #define ENOEXEC 8 #define E2BIG 7 #define ENOENT 2 #define ETXTBSY 26 /* service routines for `execute' */ VOID initio(iop) IOPTR iop; { REG STRING ion; REG INT iof, fd; IF iop THEN iof=iop->iofile; ion=mactrim(iop->ioname); IF *ion ANDF (flags&noexec)==0 THEN IF iof&IODOC THEN subst(chkopen(ion),(fd=tmpfil())); close(fd); fd=chkopen(tmpout); unlink(tmpout); ELIF iof&IOMOV THEN IF eq(minus,ion) THEN fd = -1; close(iof&IOUFD); ELIF (fd=stoi(ion))>=USERIO THEN failed(ion,badfile); ELSE fd=dup(fd); FI ELIF (iof&IOPUT)==0 THEN fd=chkopen(ion); ELIF flags&rshflg THEN failed(ion,restricted); ELIF iof&IOAPP ANDF (fd=open(ion,O_WRONLY|O_APPEND))>=0 THEN ; ELSE fd=create(ion); FI IF fd>=0 THEN rename(fd,iof&IOUFD); FI FI initio(iop->ionxt); FI } STRING getpath(s) STRING s; { REG STRING path; IF any('/',s) THEN IF flags&rshflg THEN failed(s, restricted); ELSE return(nullstr); FI ELIF (path = pathnod.namval)==0 THEN return(defpath); ELSE return(cpystak(path)); FI } INT pathopen(path, name) REG STRING path, name; { REG UFD f; REP path=catpath(path,name); PER (f=open(curstak(), O_RDONLY))<0 ANDF path DONE return(f); } STRING catpath(path,name) REG STRING path; STRING name; { /* leaves result on top of stack */ REG STRING scanp = path, argp = locstak(); WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD IF scanp!=path THEN *argp++='/' FI IF *scanp==COLON THEN scanp++ FI path=(*scanp ? scanp : 0); scanp=name; WHILE (*argp++ = *scanp++) DONE return(path); } LOCAL STRING xecmsg; LOCAL STRING *xecenv; VOID execa(at) STRING at[]; { REG STRING path; REG STRING *t = at; IF (flags&noexec)==0 THEN xecmsg=notfound; path=getpath(*t); namscan(exname); xecenv=setenv(); WHILE path=execs(path,t) DONE failed(*t,xecmsg); FI } LOCAL STRING execs(ap,t) STRING ap; REG STRING t[]; { REG STRING p, prefix; prefix=catpath(ap,t[0]); trim(p=curstak()); sigchk(); execve(p, &t[0] ,xecenv); SWITCH errno IN case ENOEXEC: flags=0; comdiv=0; ioset=0; clearup(); /* remove open files and for loop junk */ IF input THEN close(input) FI close(output); output=2; input=chkopen(p); /* band aid to get csh... 2/26/79 */ { char c; if (!isatty(input)) { read(input, &c, 1); if (c == '#') gocsh(t, p, xecenv); lseek(input, (long) 0, 0); } } /* set up new args */ setargs(t); longjmp(subshell,1); case ENOMEM: failed(p,toobig); case E2BIG: failed(p,arglist); case ETXTBSY: failed(p,txtbsy); default: xecmsg=badexec; case ENOENT: return(prefix); ENDSW } gocsh(t, cp, xecenv) register char **t, *cp, **xecenv; { char **newt[1000]; register char **p; register int i; for (i = 0; t[i]; i++) newt[i+1] = t[i]; newt[i+1] = 0; newt[0] = "/bin/csh"; newt[1] = cp; execve("/bin/csh", newt, xecenv); } /* for processes to be waited for */ #define MAXP 20 LOCAL INT pwlist[MAXP]; LOCAL INT pwc; postclr() { REG INT *pw = pwlist; WHILE pw <= &pwlist[pwc] DO *pw++ = 0 OD pwc=0; } VOID post(pcsid) INT pcsid; { REG INT *pw = pwlist; IF pcsid THEN WHILE *pw DO pw++ OD IF pwc >= MAXP-1 THEN pw--; ELSE pwc++; FI *pw = pcsid; FI } VOID await(i) INT i; { INT rc=0, wx=0; INT w; INT ipwc = pwc; post(i); WHILE pwc DO REG INT p; REG INT sig; INT w_hi; BEGIN REG INT *pw=pwlist; IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; p=wait(&w); ELSE p = -1; FI trapjmp[INTR] = 0; WHILE pw <= &pwlist[ipwc] DO IF *pw==p THEN *pw=0; pwc--; ELSE pw++; FI OD END IF p == -1 THEN continue FI w_hi = (w>>8)&LOBYTE; IF sig = w&0177 THEN IF sig == 0177 /* ptrace! return */ THEN prs("ptrace: "); sig = w_hi; FI IF sig < num_sysmsg ANDF sysmsg[sig] THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI prs(sysmsg[sig]); IF w&0200 THEN prs(coredump) FI FI newline(); FI IF rc==0 THEN rc = (sig ? sig|SIGFLG : w_hi); FI wx |= w; OD IF wx ANDF flags&errflg THEN exitsh(rc); FI exitval=rc; exitset(); } BOOL nosubst; trim(at) STRING at; { REG STRING p; REG CHAR c; REG CHAR q=0; IF p=at THEN WHILE c = *p DO *p++=c&STRIP; q |= c OD FI nosubst=q"E; } STRING mactrim(s) STRING s; { REG STRING t=macro(s); trim(t); return(t); } STRING *scan(argn) INT argn; { REG ARGPTR argp = Rcheat(gchain)&~ARGMK; REG STRING *comargn, *comargm; comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS; WHILE argp DO *--comargn = argp->argval; IF argp = argp->argnxt THEN trim(*comargn); FI IF argp==0 ORF Rcheat(argp)&ARGMK THEN gsort(comargn,comargm); comargm = comargn; FI /* Lcheat(argp) &= ~ARGMK; */ argp = Rcheat(argp)&~ARGMK; OD return(comargn); } LOCAL VOID gsort(from,to) STRING from[], to[]; { INT k, m, n; REG INT i, j; IF (n=to-from)<=1 THEN return FI FOR j=1; j<=n; j*=2 DONE FOR m=2*j-1; m/=2; DO k=n-m; FOR j=0; j=0; i-=m DO REG STRING *fromi; fromi = &from[i]; IF cf(fromi[m],fromi[0])>0 THEN break; ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s; FI OD OD OD } /* Argument list generation */ INT getarg(ac) COMPTR ac; { REG ARGPTR argp; REG INT count=0; REG COMPTR c; IF c=ac THEN argp=c->comarg; WHILE argp DO count += split(macro(argp->argval)); argp=argp->argnxt; OD FI return(count); } LOCAL INT split(s) REG STRING s; { REG STRING argp; REG INT c; INT count=0; LOOP sigchk(); argp=locstak()+BYTESPERWORD; WHILE (c = *s++, !any(c,ifsnod.namval) && c) DO *argp++ = c OD IF argp==staktop+BYTESPERWORD THEN IF c THEN continue; ELSE return(count); FI ELIF c==0 THEN s--; FI IF c=expand((argp=endstak(argp))->argval,0) THEN count += c; ELSE /* assign(&fngnod, argp->argval); */ makearg(argp); count++; FI Lcheat(gchain) |= ARGMK; POOL } o; { REG INT iof; REG IOPTR iop; REG CHAR c; iof=wdnum; SWITCH wdval IN case DOCSYM: iof |= IODOC; break; case APPSYM: case '>': IF wdnum==0 THEN iof |= 1 FI iof |= IOPUbin/sh/setbrk.c 444 0 12 357 3146337671 6645 #ifndef lint static char sccsid[] = "@(#)setbrk.c 4.2 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" setbrk(incr) { REG BYTPTR a=sbrk(incr); brkend=a+incr; return(a); } ©main.c¨mode.h§ msg.c¦name.c¥name.h¤print.c£ service.c¢setbrk.c¡stak.cc stak.hcŸstring.cž sym.h timeout.hœword.c.h› xec.cšMakefile™$mac.hbin/sh/stak.c 444 0 12 2367 3146337673 6342 #ifndef lint static char sccsid[] = "@(#)stak.c 4.2 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" STKPTR stakbot=nullstr; /* ======== storage allocation ======== */ STKPTR getstak(asize) INT asize; { /* allocate requested stack */ REG STKPTR oldstak; REG INT size; size=round(asize,BYTESPERWORD); oldstak=stakbot; staktop = stakbot += size; return(oldstak); } STKPTR locstak() { /* set up stack for local use * should be followed by `endstak' */ IF brkend-stakbotADR(x) DO free(stakbsy); stakbsy = stakbsy->word; OD staktop=stakbot=max(ADR(x),ADR(stakbas)); rmtemp(x); } stakchk() { IF (brkend-stakbas)>BRKINCR+BRKINCR THEN setbrk(-BRKINCR); FI } STKPTR cpystak(x) STKPTR x; { return(endstak(movstr(x,locstak()))); } setargs(t); longjmp(subshell,1); case ENOMEM: failed(p,toobig); case E2BIG: failed(p,arglist); case ETXTBSY: failed(p,txtbsy); default: xecmsg=badexec; case ENOENT: return(prefix); ENDSW } gocsh(t, cp, xecenv) register cbin/sh/stak.h 444 0 12 3124 2731034234 6321 /* stak.h 4.1 82/05/07 */ # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ /* To use stack as temporary workspace across * possible storage allocation (eg name lookup) * a) get ptr from `relstak' * b) can now use `pushstak' * c) then reset with `setstak' * d) `absstak' gives real address if needed */ #define relstak() (staktop-stakbot) #define absstak(x) (stakbot+Rcheat(x)) #define setstak(x) (staktop=absstak(x)) #define pushstak(c) (*staktop++=(c)) #define zerostak() (*staktop=0) /* Used to address an item left on the top of * the stack (very temporary) */ #define curstak() (staktop) /* `usestak' before `pushstak' then `fixstak' * These routines are safe against heap * being allocated. */ #define usestak() {locstak();} /* for local use only since it hands * out a real address for the stack top */ STKPTR locstak(); /* Will allocate the item being used and return its * address (safe now). */ #define fixstak() endstak(staktop) /* For use after `locstak' to hand back * new stack top and then allocate item */ STKPTR endstak(); /* Copy a string onto the stack and * allocate the space. */ STKPTR cpystak(); /* Allocate given ammount of stack space */ STKPTR getstak(); /* A chain of ptrs of stack blocks that * have become covered by heap allocation. * `tdystak' will return them to the heap. */ BLKPTR stakbsy; /* Base of the entire stack */ STKPTR stakbas; /* Top of entire stack */ STKPTR brkend; /* Base of current item */ STKPTR stakbot; /* Top of current item */ STKPTR staktop; /* Used with tdystak */ STKPTR savstak(); aboratories * */ /* To use stack as temporary workspace across * possible storage allocation (eg name lookup) * a) get ptr from `relstak' * b) can now use `pushstak' * c) then reset with `setstak' * d) `absstak' gives real address if needed */ #define relstak() (staktop-stakbot) #define absstak(x) (stakbot+Rcheat(x)) #define setstak(x) (staktop=absstak(x)) #define pushstak(c) (*staktop++=(c)) #define zerostak()bin/sh/string.c 444 0 12 1222 3146337674 6674 #ifndef lint static char sccsid[] = "@(#)string.c 4.2 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" /* ======== general purpose string handling ======== */ STRING movstr(a,b) REG STRING a, b; { WHILE *b++ = *a++ DONE return(--b); } INT any(c,s) REG CHAR c; STRING s; { REG CHAR d; WHILE d = *s++ DO IF d==c THEN return(TRUE); FI OD return(FALSE); } INT cf(s1, s2) REG STRING s1, s2; { WHILE *s1++ == *s2 DO IF *s2++==0 THEN return(0); FI OD return(*--s1 - *s2); } INT length(as) STRING as; { REG STRING s; IF s=as THEN WHILE *s++ DONE FI return(s-as); } pushstak' then `fixstak' * These routines are safe against heap * being allocated. */ #define usestak() {locstak();} /* for local use only since it hands * out a real address for the stack top */ STKPTR locstak(); /* Will allocate the item being used and return its * address (safe now). */ #define fixstak() endstak(staktop) /* For use after `locstak' bin/sh/sym.h 444 0 12 1425 2731034234 6171 /* sym.h 4.1 82/05/07 */ # /* * UNIX shell */ /* symbols for parsing */ #define DOSYM 0405 #define FISYM 0420 #define EFSYM 0422 #define ELSYM 0421 #define INSYM 0412 #define BRSYM 0406 #define KTSYM 0450 #define THSYM 0444 #define ODSYM 0441 #define ESSYM 0442 #define IFSYM 0436 #define FORSYM 0435 #define WHSYM 0433 #define UNSYM 0427 #define CASYM 0417 #define SYMREP 04000 #define ECSYM (SYMREP|';') #define ANDFSYM (SYMREP|'&') #define ORFSYM (SYMREP|'|') #define APPSYM (SYMREP|'>') #define DOCSYM (SYMREP|'<') #define EOFSYM 02000 #define SYMFLG 0400 /* arg to `cmd' */ #define NLFLG 1 #define MTFLG 2 /* for peekc */ #define MARK 0100000 /* odd chars */ #define DQUOTE '"' #define SQUOTE '`' #define LITERAL '\'' #define DOLLAR '$' #define ESCAPE '\\' #define BRACE '{' cal use only since it hands * out a real address for the stack top */ STKPTR locstak(); /* Will allocate the item being used and return its * address (safe now). */ #define fixstak() endstak(staktop) /* For use after `locstak' bin/sh/timeout.h 444 0 12 200 2731034235 7016 /* timeout.h 4.1 82/05/07 */ # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #define TIMEOUT 2400 ctype.hc°defs.hc¯ dup.h®error.cc­expand.c¬fault.c« io.c.ªmacro.c©main.c¨mode.h§ msg.c¦name.c¥name.h¤print.c£ service.c¢setbrk.c¡stak.cc stak.hcŸstring.cž sym.h timeout.hœword.c.h› xec.cšMakefile™$mac.hbin/sh/word.c 444 0 12 5040 3565232774 6343 #ifndef lint static char sccsid[] = "@(#)word.c 4.6 10/31/85"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" #include "sym.h" /* ======== character handling for command lines ========*/ word() { REG CHAR c, d; REG CHAR *argp=locstak()+BYTESPERWORD; INT alpha=1; wdnum=0; wdset=0; WHILE (c=nextc(0), space(c)) DONE IF c=='#' ANDF ((flags&prompt)==0 ORF ((flags&ttyflg) ANDF standin->fstak!=0)) THEN WHILE (c=readc()) ANDF c!=NL DONE FI IF !eofmeta(c) THEN REP IF c==LITERAL THEN *argp++=(DQUOTE); WHILE (c=readc()) ANDF c!=LITERAL DO *argp++=(c|QUOTE); chkpr(c) OD *argp++=(DQUOTE); ELSE *argp++=(c); IF c=='=' THEN wdset |= alpha FI IF !alphanum(c) THEN alpha=0 FI IF qotchar(c) THEN d=c; WHILE (*argp++=(c=nextc(d))) ANDF c!=d DO chkpr(c) OD FI FI PER (c=nextc(0), !eofmeta(c)) DONE argp=endstak(argp); IF !letter(argp->argval[0]) THEN wdset=0 FI peekc=c|MARK; IF argp->argval[1]==0 ANDF (d=argp->argval[0], digit(d)) ANDF (c=='>' ORF c=='<') THEN word(); wdnum=d-'0'; ELSE /*check for reserved words*/ IF reserv==FALSE ORF (wdval=syslook(argp->argval,reserved))==0 THEN wdarg=argp; wdval=0; FI FI ELIF dipchar(c) THEN IF (d=nextc(0))==c THEN wdval = c|SYMREP; ELSE peekc = d|MARK; wdval = c; FI ELSE IF (wdval=c)==EOF THEN wdval=EOFSYM; FI IF iopend ANDF eolchar(c) THEN copy(iopend); iopend=0; FI FI reserv=FALSE; return(wdval); } nextc(quote) CHAR quote; { REG CHAR c, d; IF (d=readc())==ESCAPE THEN IF (c=readc())==NL THEN chkpr(NL); d=nextc(quote); ELIF quote ANDF c!=quote ANDF !escchar(c) THEN peekc=c|MARK; ELSE d = c|QUOTE; FI FI return(d); } readc() { REG CHAR c; REG INT len; REG FILE f; retry: IF peekc THEN c=peekc; peekc=0; ELIF (f=standin, f->fnxt!=f->fend) THEN IF (c = *f->fnxt++)==0 THEN IF f->feval THEN IF estabf(*f->feval++) THEN c=EOF; ELSE c=SP; FI ELSE goto retry; /* = c=readc(); */ FI FI IF flags&readpr ANDF standin->fstak==0 THEN prc(c) FI IF c==NL THEN f->flin++ FI ELIF f->feof ORF f->fdes<0 THEN c=EOF; f->feof++; ELIF (len=readb())<=0 THEN close(f->fdes); f->fdes = -1; c=EOF; f->feof++; ELSE f->fend = (f->fnxt = f->fbuf)+len; goto retry; FI return(c); } LOCAL readb() { REG FILE f=standin; REG INT len; IF setjmp(INTbuf) == 0 THEN trapjmp[INTR] = 1; FI REP IF trapnote&SIGSET THEN newline(); sigchk() FI PER (len=read(f->fdes,f->fbuf,f->fsiz))<0 ANDF trapnote DONE trapjmp[INTR] = 0; return(len); } 0177 THEN IF sig == 0177 /* ptrace! return */ THEN prs("ptrace: "); sig = w_hi; FI IF sig < num_sysmsg ANDF sysmsg[sig] THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI prs(sysmsg[sig]); IF w&0200 THEN prs(coredump) FI FI newline(); FI IF rc==0 THEN rc = (sig ? sig|SIGFLG : w_hi); FI wx |= w; OD IF wx ANDF flags&errflg THEN exitsh(rc); FI exitval=rc; exitset(); } BOOL nosubst; trim(at) STRING at; {bin/sh/xec.c 444 0 12 20347 4001647360 6161 #ifndef lint static char sccsid[] = "@(#)xec.c 4.3 8/11/83"; #endif # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #include "defs.h" #include "sym.h" LOCAL INT parent; SYSTAB commands; /* ======== command execution ========*/ execute(argt, execflg, pf1, pf2) TREPTR argt; INT *pf1, *pf2; { /* `stakbot' is preserved by this routine */ REG TREPTR t; STKPTR sav=savstak(); sigchk(); IF (t=argt) ANDF execbrk==0 THEN REG INT treeflgs; INT oldexit, type; REG STRING *com; treeflgs = t->tretyp; type = treeflgs&COMMSK; oldexit=exitval; exitval=0; SWITCH type IN case TCOM: BEGIN STRING a1; INT argn, internal; ARGPTR schain=gchain; IOPTR io=t->treio; gchain=0; argn = getarg(t); com=scan(argn); a1=com[1]; gchain=schain; IF argn==0 ORF (internal=syslook(com[0],commands)) THEN setlist(t->comset, 0); FI IF argn ANDF (flags&noexec)==0 THEN /* print command if execpr */ IF flags&execpr THEN argn=0; prs(execpmsg); WHILE com[argn]!=ENDARGS DO prs(com[argn++]); blank() OD newline(); FI SWITCH internal IN case SYSDOT: IF a1 THEN REG INT f; IF (f=pathopen(getpath(a1), a1)) < 0 THEN failed(a1,notfound); ELSE execexp(0,f); FI FI break; case SYSTIMES: { L_INT t[4]; times(t); prt(t[2]); blank(); prt(t[3]); newline(); } break; case SYSEXIT: exitsh(a1?stoi(a1):oldexit); case SYSNULL: io=0; break; case SYSCONT: execbrk = -loopcnt; break; case SYSBREAK: IF (execbrk=loopcnt) ANDF a1 THEN breakcnt=stoi(a1); FI break; case SYSTRAP: IF a1 THEN BOOL clear; IF (clear=digit(*a1))==0 THEN ++com; FI WHILE *++com DO INT i; IF (i=stoi(*com))>=MAXTRAP ORF i1 THEN setargs(com+argn-argc); FI ELIF t->comset==0 THEN /*scan name chain and print*/ namscan(printnam); FI break; case SYSRDONLY: exitval=N_RDONLY; case SYSXPORT: IF exitval==0 THEN exitval=N_EXPORT; FI IF a1 THEN WHILE *++com DO attrib(lookup(*com), exitval) OD ELSE namscan(printflg); FI exitval=0; break; case SYSEVAL: IF a1 THEN execexp(a1,&com[2]); FI break; case SYSUMASK: if (a1) { int c, i; i = 0; while ((c = *a1++) >= '0' && c <= '7') i = (i << 3) + c - '0'; umask(i); } else { int i, j; umask(i = umask(0)); prc('0'); for (j = 6; j >= 0; j -= 3) prc(((i>>j)&07) + '0'); newline(); } break; default: internal=builtin(argn,com); ENDSW IF internal THEN IF io THEN error(illegal) FI chktrap(); break; FI ELIF t->treio==0 THEN break; FI END case TFORK: IF execflg ANDF (treeflgs&(FAMP|FPOU))==0 THEN parent=0; ELSE WHILE (parent=fork()) == -1 DO sigchk(); alarm(10); pause() OD FI IF parent THEN /* This is the parent branch of fork; */ /* it may or may not wait for the child. */ IF treeflgs&FPRS ANDF flags&ttyflg THEN prn(parent); newline(); FI IF treeflgs&FPCL THEN closepipe(pf1) FI IF (treeflgs&(FAMP|FPOU))==0 THEN await(parent); ELIF (treeflgs&FAMP)==0 THEN post(parent); ELSE assnum(&pcsadr, parent); FI chktrap(); break; ELSE /* this is the forked branch (child) of execute */ flags |= forked; iotemp=0; postclr(); settmp(); /* Turn off INTR and QUIT if `FINT' */ /* Reset ramaining signals to parent */ /* except for those `lost' by trap */ oldsigs(); IF treeflgs&FINT THEN signal(INTR,1); signal(QUIT,1); FI /* pipe in or out */ IF treeflgs&FPIN THEN rename(pf1[INPIPE],0); close(pf1[OTPIPE]); FI IF treeflgs&FPOU THEN rename(pf2[OTPIPE],1); close(pf2[INPIPE]); FI /* default std input for & */ IF treeflgs&FINT ANDF ioset==0 THEN rename(chkopen(devnull),0); FI /* io redirection */ initio(t->treio); IF type!=TCOM THEN execute(t->forktre,1); ELIF com[0]!=ENDARGS THEN setlist(t->comset,N_EXPORT); execa(com); FI done(); FI case TPAR: rename(dup(2),output); execute(t->partre,execflg); done(); case TFIL: BEGIN INT pv[2]; chkpipe(pv); IF execute(t->lstlef, 0, pf1, pv)==0 THEN execute(t->lstrit, execflg, pv, pf2); ELSE closepipe(pv); FI END break; case TLST: execute(t->lstlef,0); execute(t->lstrit,execflg); break; case TAND: IF execute(t->lstlef,0)==0 THEN execute(t->lstrit,execflg); FI break; case TORF: IF execute(t->lstlef,0)!=0 THEN execute(t->lstrit,execflg); FI break; case TFOR: BEGIN NAMPTR n = lookup(t->fornam); STRING *args; DOLPTR argsav=0; IF t->forlst==0 THEN args=dolv+1; argsav=useargs(); ELSE ARGPTR schain=gchain; gchain=0; trim((args=scan(getarg(t->forlst)))[0]); gchain=schain; FI loopcnt++; WHILE *args!=ENDARGS ANDF execbrk==0 DO assign(n,*args++); execute(t->fortre,0); IF execbrk<0 THEN execbrk=0 FI OD IF breakcnt THEN breakcnt-- FI execbrk=breakcnt; loopcnt--; argfor=freeargs(argsav); END break; case TWH: case TUN: BEGIN INT i=0; loopcnt++; WHILE execbrk==0 ANDF (execute(t->whtre,0)==0)==(type==TWH) DO i=execute(t->dotre,0); IF execbrk<0 THEN execbrk=0 FI OD IF breakcnt THEN breakcnt-- FI execbrk=breakcnt; loopcnt--; exitval=i; END break; case TIF: IF execute(t->iftre,0)==0 THEN execute(t->thtre,execflg); ELSE execute(t->eltre,execflg); FI break; case TSW: BEGIN REG STRING r = mactrim(t->swarg); t=t->swlst; WHILE t DO ARGPTR rex=t->regptr; WHILE rex DO REG STRING s; IF gmatch(r,s=macro(rex->argval)) ORF (trim(s), eq(r,s)) THEN execute(t->regcom,0); t=0; break; ELSE rex=rex->argnxt; FI OD IF t THEN t=t->regnxt FI OD END break; ENDSW exitset(); FI sigchk(); tdystak(sav); return(exitval); } execexp(s,f) STRING s; UFD f; { FILEBLK fb; push(&fb); IF s THEN estabf(s); fb.feval=f; ELIF f>=0 THEN initf(f); FI execute(cmd(NL, NLFLG|MTFLG),0); pop(); } k; case CONTINUE: x.osub = JCONT; break; } return(x); } obj fncn(a,n) node **a; { obj x; awkfloat u; int t; t = (int) a[0]; x = execute(a[1]); if (t == FLENGTH) u = (awkfloat) strlen(getsval(x.optr)); else if (t == FLOG) u = log(getfval(x.optr)); else if (t ==bin/sh/Makefile 444 0 12 744 5326557243 6650 # Makefile 4.5 83/07/01 # CFLAGS = -O -w SEPFLAG= -i all: sh cp: sh cp sh /bin/sh rm sh *.o cmp: sh cmp sh /bin/sh rm sh *.o sh: setbrk.o sh: builtin.o blok.o stak.o sh: cmd.o fault.o main.o sh: word.o string.o name.o args.o sh: xec.o service.o error.o io.o sh: print.o macro.o expand.o sh: ctype.o msg.o blok.o: brkincr.h fault.o: brkincr.h main.o: brkincr.h stak.o: brkincr.h sh: cc ${SEPFLAG} -o sh *.o install: all install -s sh $(DESTDIR)/bin clean: rm -f sh *.o ™$mac.hbin/sh/mac.h 444 0 12 1556 5326557244 6144 /* mac.h 4.2 82/12/24 */ # /* * UNIX shell * * S. R. Bourne * Bell Telephone Laboratories * */ #define LOCAL static #define PROC extern #define TYPE typedef #define STRUCT TYPE struct #define UNION TYPE union #define REG register #define IF if( #define THEN ){ #define ELSE } else { #define ELIF } else if ( #define FI ;} #define BEGIN { #define END } #define SWITCH switch( #define IN ){ #define ENDSW } #define FOR for( #define WHILE while( #define DO ){ #define OD ;} #define REP do{ #define PER }while( #undef DONE #define DONE ); #define LOOP for(;;){ #define POOL } #define SKIP ; #define DIV / #define REM % #define NEQ ^ #define ANDF && #define ORF || #define TRUE (-1) #define FALSE 0 #define LOBYTE 0377 #define STRIP 0177 #define QUOTE 0200 #define EOF 0 #define NL '\n' #define SP ' ' #define LQ '`' #define RQ '\'' #define MINUS '-' #define COLON ':' case SYSLOGIN: flags |= forked; oldsigs(); execa(com); done(); case SYSCD: IF flags&rshflg THEN failed(com[0],restbin/csh/ 755 0 12 0 6024535757 5305 bin/csh/Makefile 444 0 12 6035 5551453415 7026 # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley Software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.3.1 (2.11BSD GTE) 4/9/94 # # C Shell with process control; VM/UNIX VAX Makefile # Bill Joy UC Berkeley; Jim Kulp IIASA, Austria # # To profile, put -DPROF in DEFS and -pg in CFLAGS, and recompile. DEFS= -DTELL -DVFORK -DFILEC CFLAGS= $(DEFS) -O SEPFLAG=-i XSTR= /usr/ucb/xstr AS= as RM= -rm CXREF= /usr/ucb/cxref VGRIND= /usr/ucb/vgrind CTAGS= /usr/ucb/ctags LIBES= /lib/libc.a SCCS= sccs CPP= /lib/cpp SED= sed BASE= alloc11.o doprnt11.o printf.o sh.char.o sh.dir.o sh.dol.o \ sh.err.o sh.exp.o sh.file.o sh.func.o sh.glob.o sh.hist.o \ sh.init.o sh.lex.o sh.misc.o sh.parse.o sh.print.o sh.proc.o sh.sem.o \ sh.set.o OV1= sh.o sh.exec.o sh.time.o OBJS= ${BASE} ${OV1} LIBOBJS= ndbm.o getpwent.o # Special massaging of C files for sharing of strings .c.o: ${CC} -E ${CFLAGS} $*.c | ${XSTR} -c - ${CC} -c ${CFLAGS} x.c mv -f x.o $*.o rm -f x.c # strings.o must be last since it can change when previous files compile csh: ${OBJS} strings.o ar x /lib/libc.a ${LIBOBJS} rm -f csh /bin/ld ${SEPFLAG} /lib/crt0.o ${BASE} \ -Z ${OV1} \ -Z ${LIBOBJS} \ -Y strings.o -o csh ${LIBES}; .DEFAULT: ${SCCS} get $< # need an old doprnt, whose output we can trap doprnt11.o: doprnt11.s ${CPP} doprnt11.s | ${SED} '/^#/d' | ${AS} -o doprnt11.o strings.o: strings ${XSTR} ${CC} -c xs.c mv -f xs.o strings.o rm -f xs.c lint: lint -z ${DEFS} sh*.c alloc.c print: @pr READ_ME @pr Makefile Makefile.* @(size -l a.out; size *.o) | pr -h SIZES @${CXREF} sh*.c | pr -h XREF @ls -l | pr @pr sh*.h [a-rt-z]*.h sh*.c alloc.c vprint: @pr -l84 READ_ME TODO @pr -l84 Makefile Makefile.* @(size -l a.out; size *.o) | pr -l84 -h SIZES @${CXREF} sh*.c | pr -l84 -h XREF @ls -l | pr -l84 @${CXREF} sh*.c | pr -l84 -h XREF @pr -l84 sh*.h [a-rt-z]*.h sh*.c alloc.c vgrind: @cp /dev/null index @-mkdir grind for i in *.h; do ${VGRIND} -t -h "C Shell" $$i >grind/$$i.t; done for i in *.c; do ${VGRIND} -t -h "C Shell" $$i >grind/$$i.t; done ${VGRIND} -t -x -h Index index >grind/index.t install: csh install -s csh ${DESTDIR}/bin/csh clean: ${RM} -f a.out strings x.c xs.c csh errs ${RM} -f *.o ${RM} -rf vgrind tags: ${CTAGS} -t *.h sh*.c sh.o: sh.h sh.local.h sh.char.h sh.char.o: sh.char.h sh.dir.o: sh.h sh.local.h sh.dir.h sh.dol.o: sh.h sh.local.h sh.char.h sh.err.o: sh.h sh.local.h sh.char.h sh.exec.o: sh.h sh.local.h sh.char.h sh.exp.o: sh.h sh.local.h sh.char.h sh.file.o: sh.h sh.local.h sh.char.h sh.func.o: sh.h sh.local.h sh.char.h sh.glob.o: sh.h sh.local.h sh.char.h sh.hist.o: sh.h sh.local.h sh.char.h sh.init.o: sh.local.h sh.lex.o: sh.h sh.local.h sh.char.h sh.misc.o: sh.h sh.local.h sh.char.h sh.parse.o: sh.h sh.local.h sh.char.h sh.print.o: sh.h sh.local.h sh.char.h sh.proc.o: sh.h sh.local.h sh.dir.h sh.proc.h sh.char.h sh.sem.o: sh.h sh.local.h sh.proc.h sh.char.h sh.set.o: sh.h sh.local.h sh.char.h sh.time.o: sh.h sh.local.h sh.char.h tin(argn,com); ENDSW IF internal THEN IF io THEN error(illegal) FI chktrap(); break; FI ELIF t->treio==0 THEN break; FI END case TFORK: IF execflg ANDF (treeflgs&(FAMP|FPOU))==0 THEN parent=0; ELSE WHILE (parent=fork()) == -1 DO sigchk(); alarm(10); pause() OD FI IF parent THEN /* This is the parent branch of fork; */ /* it may or may not wait for the child. */ IF treeflgs&FPRS ANDF flags&ttyflg Tbin/csh/alloc.c 444 0 12 23061 5057637444 6651 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) /* From "@(#)malloc.c 5.5 (Berkeley) 2/25/86"; */ static char *sccsid = "@(#)alloc.c 5.3 (Berkeley) 3/29/86"; #endif /* * malloc.c (Caltech) 2/21/82 * Chris Kingsley, kingsley@cit-20. * * This is a very fast storage allocator. It allocates blocks of a small * number of different sizes, and keeps free lists of each size. Blocks that * don't exactly fit are passed up to the next larger size. In this * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long. * This is designed for use in a virtual memory environment. */ #include #define NULL 0 /* * The overhead on a block is at least 4 bytes. When free, this space * contains a pointer to the next free block, and the bottom two bits must * be zero. When in use, the first byte is set to MAGIC, and the second * byte is the size index. The remaining bytes are for alignment. * If range checking is enabled then a second word holds the size of the * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC). * The order of elements is critical: ov_magic must overlay the low order * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern. */ union overhead { union overhead *ov_next; /* when free */ struct { u_char ovu_magic; /* magic number */ u_char ovu_index; /* bucket # */ #ifdef RCHECK u_short ovu_rmagic; /* range magic number */ u_int ovu_size; /* actual block size */ #endif } ovu; #define ov_magic ovu.ovu_magic #define ov_index ovu.ovu_index #define ov_rmagic ovu.ovu_rmagic #define ov_size ovu.ovu_size }; #define MAGIC 0xef /* magic # on accounting info */ #define RMAGIC 0x5555 /* magic # on range info */ #ifdef RCHECK #define RSLOP sizeof (u_short) #else #define RSLOP 0 #endif /* * nextf[i] is the pointer to the next free block of size 2^(i+3). The * smallest allocatable block is 8 bytes. The overhead information * precedes the data area returned to the user. */ #define NBUCKETS 30 static union overhead *nextf[NBUCKETS]; extern char *sbrk(); static int pagesz; /* page size */ static int pagebucket; /* page size bucket */ /* * nmalloc[i] is the difference between the number of mallocs and frees * for a given block size. */ static u_int nmalloc[NBUCKETS]; #if defined(DEBUG) || defined(RCHECK) #define ASSERT(p) if (!(p)) botch("p") static botch(s) char *s; { printf("\r\nassertion botched: %s\r\n", s); abort(); } #else #define ASSERT(p) #endif char * malloc(nbytes) unsigned nbytes; { register union overhead *op; register int bucket; register unsigned amt, n; /* * First time malloc is called, setup page size and * align break pointer so all data will be page aligned. */ if (pagesz == 0) { pagesz = n = getpagesize(); op = (union overhead *)sbrk(0); n = n - sizeof (*op) - ((int)op & (n - 1)); if (n < 0) n += pagesz; if (n) { if (sbrk(n) == (char *)-1) return (NULL); } bucket = 0; amt = 8; while (pagesz > amt) { amt <<= 1; bucket++; } pagebucket = bucket; } /* * Convert amount of memory requested into closest block size * stored in hash buckets which satisfies request. * Account for space used per block for accounting. */ if (nbytes <= (n = pagesz - sizeof (*op) - RSLOP)) { #ifndef RCHECK amt = 8; /* size of first bucket */ bucket = 0; #else amt = 16; /* size of first bucket */ bucket = 1; #endif n = -(sizeof (*op) + RSLOP); } else { amt = pagesz; bucket = pagebucket; } while (nbytes > amt + n) { amt <<= 1; if (amt == 0) return (NULL); bucket++; } /* * If nothing in hash bucket right now, * request more memory from the system. */ if ((op = nextf[bucket]) == NULL) { morecore(bucket); if ((op = nextf[bucket]) == NULL) return (NULL); } /* remove from linked list */ nextf[bucket] = op->ov_next; op->ov_magic = MAGIC; op->ov_index = bucket; nmalloc[bucket]++; #ifdef RCHECK /* * Record allocated size of block and * bound space with magic numbers. */ op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); op->ov_rmagic = RMAGIC; *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; #endif return ((char *)(op + 1)); } /* * Allocate more memory to the indicated bucket. */ morecore(bucket) int bucket; { register union overhead *op; register int sz; /* size of desired block */ int amt; /* amount to allocate */ int nblks; /* how many blocks we get */ /* * sbrk_size <= 0 only for big, FLUFFY, requests (about * 2^30 bytes on a VAX, I think) or for a negative arg. */ sz = 1 << (bucket + 3); #ifdef DEBUG ASSERT(sz > 0); #else if (sz <= 0) return; #endif if (sz < pagesz) { amt = pagesz; nblks = amt / sz; } else { amt = sz + pagesz; nblks = 1; } op = (union overhead *)sbrk(amt); /* no more room! */ if ((int)op == -1) return; /* * Add new memory allocated to that on * free list for this hash bucket. */ nextf[bucket] = op; while (--nblks > 0) { op->ov_next = (union overhead *)((caddr_t)op + sz); op = (union overhead *)((caddr_t)op + sz); } } free(cp) char *cp; { register int size; register union overhead *op; if (cp == NULL) return; op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); /* * The following botch is because csh tries to free a free block * when processing the =~ or !~ operators. -- layer@ucbmonet */ #ifdef CSHbotch /* was DEBUG */ ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ #else if (op->ov_magic != MAGIC) return; /* sanity */ #endif #ifdef RCHECK ASSERT(op->ov_rmagic == RMAGIC); ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); #endif size = op->ov_index; ASSERT(size < NBUCKETS); op->ov_next = nextf[size]; /* also clobbers ov_magic */ nextf[size] = op; nmalloc[size]--; } /* * When a program attempts "storage compaction" as mentioned in the * old malloc man page, it realloc's an already freed block. Usually * this is the last block it freed; occasionally it might be farther * back. We have to search all the free lists for the block in order * to determine its bucket: 1st we make one pass thru the lists * checking only the first block in each; if that fails we search * ``realloc_srchlen'' blocks in each list for a match (the variable * is extern so the caller can modify it). If that fails we just copy * however many bytes was given to realloc() and hope it's not huge. */ int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ char * realloc(cp, nbytes) char *cp; unsigned nbytes; { register u_int onb, i; union overhead *op; char *res; int was_alloced = 0; if (cp == NULL) return (malloc(nbytes)); op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); if (op->ov_magic == MAGIC) { was_alloced++; i = op->ov_index; } else { /* * Already free, doing "compaction". * * Search for the old block of memory on the * free list. First, check the most common * case (last element free'd), then (this failing) * the last ``realloc_srchlen'' items free'd. * If all lookups fail, then assume the size of * the memory block being realloc'd is the * largest possible (so that all "nbytes" of new * memory are copied into). Note that this could cause * a memory fault if the old area was tiny, and the moon * is gibbous. However, that is very unlikely. */ if ((i = findbucket(op, 1)) < 0 && (i = findbucket(op, realloc_srchlen)) < 0) i = NBUCKETS; } onb = 1 << (i + 3); if (onb < pagesz) onb -= sizeof (*op) + RSLOP; else onb += pagesz - sizeof (*op) - RSLOP; /* avoid the copy if same size block */ if (was_alloced) { if (i) { i = 1 << (i + 2); if (i < pagesz) i -= sizeof (*op) + RSLOP; else i += pagesz - sizeof (*op) - RSLOP; } if (nbytes <= onb && nbytes > i) { #ifdef RCHECK op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; #endif return(cp); } else free(cp); } if ((res = malloc(nbytes)) == NULL) return (NULL); if (cp != res) /* common optimization if "compacting" */ bcopy(cp, res, (nbytes < onb) ? nbytes : onb); return (res); } /* * Search ``srchlen'' elements of each free list for a block whose * header starts at ``freep''. If srchlen is -1 search the whole list. * Return bucket number, or -1 if not found. */ static findbucket(freep, srchlen) union overhead *freep; int srchlen; { register union overhead *p; register int i, j; for (i = 0; i < NBUCKETS; i++) { j = 0; for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { if (p == freep) return (i); j++; } } return (-1); } /* * mstats - print out statistics about malloc * * Prints two lines of numbers, one showing the length of the free list * for each size category, the second showing the number of mallocs - * frees for each size category. */ showall(s) char **s; { register int i, j; register union overhead *p; int totfree = 0, totused = 0; if (s[1]) printf("Memory allocation statistics %s\nfree:", s[1]); for (i = 0; i < NBUCKETS; i++) { for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) ; if (s[1]) printf(" %d", j); totfree += j * (1 << (i + 3)); } if (s[1]) printf("\nused:"); for (i = 0; i < NBUCKETS; i++) { if (s[1]) printf(" %d", nmalloc[i]); totused += nmalloc[i] * (1 << (i + 3)); } if (s[1]) printf("\n"); printf("Total in use: %d, total free: %d\n", totused, totfree); } #ifdef RCHECK /* * Record allocated size of block and * bound space with magic numbers. */ op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); op->ov_rmagic = RMAGIC; *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; #endif return ((char *)(op + 1)); } /* * Allocate more memory to the indicated bucket. */ morecore(bucket) int bucket; { register union overhead *op; register int sz; /* size of desired block */ int amt; /* amounbin/csh/sh.print.c 444 0 12 2600 5057640400 7262 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.print.c 5.2 (Berkeley) 6/6/85"; #endif #include "sh.h" #include /* * C Shell */ psecs(l) long l; { register int i; i = l / 3600; if (i) { printf("%d:", i); i = l % 3600; p2dig(i / 60); goto minsec; } i = l; printf("%d", i / 60); minsec: i %= 60; printf(":"); p2dig(i); } p2dig(i) register int i; { printf("%d%d", i / 10, i % 10); } char linbuf[128]; char *linp = linbuf; putchar(c) register int c; { if ((c & QUOTE) == 0 && (c == 0177 || c < ' ' && c != '\t' && c != '\n')) { putchar('^'); if (c == 0177) c = '?'; else c |= 'A' - 1; } c &= TRIM; *linp++ = c; if (c == '\n' || linp >= &linbuf[sizeof linbuf - 2]) flush(); } draino() { linp = linbuf; } flush() { register int unit; int lmode; if (linp == linbuf) return; if (haderr) unit = didfds ? 2 : SHDIAG; else unit = didfds ? 1 : SHOUT; #ifdef TIOCLGET if (didfds == 0 && ioctl(unit, TIOCLGET, (char *)&lmode) == 0 && lmode&LFLUSHO) { lmode = LFLUSHO; (void) ioctl(unit, TIOCLBIC, (char *)&lmode); (void) write(unit, "\n", 1); } #endif (void) write(unit, linbuf, linp - linbuf); linp = linbuf; } ic == MAGIC) { was_alloced++; i = op->ov_index; } else { /* * Already free, doing "compaction". * * Search for tbin/csh/sh.time.c 444 0 12 7633 5514435446 7111 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.time.c 5.4.1 (2.11BSD GTE) 12/31/93"; #endif #include "sh.h" /* * C Shell - routines handling process timing and niceing */ settimes() { struct rusage ruch; (void) gettimeofday(&time0, (struct timezone *)0); (void) getrusage(RUSAGE_SELF, &ru0); (void) getrusage(RUSAGE_CHILDREN, &ruch); ruadd(&ru0, &ruch); } /* * dotime is only called if it is truly a builtin function and not a * prefix to another command */ dotime() { struct timeval timedol; struct rusage ru1, ruch; (void) getrusage(RUSAGE_SELF, &ru1); (void) getrusage(RUSAGE_CHILDREN, &ruch); ruadd(&ru1, &ruch); (void) gettimeofday(&timedol, (struct timezone *)0); prusage(&ru0, &ru1, &timedol, &time0); } /* * donice is only called when it on the line by itself or with a +- value */ donice(v) register char **v; { register char *cp; int nval; v++, cp = *v++; if (cp == 0) nval = 4; else if (*v == 0 && any(cp[0], "+-")) nval = getn(cp); (void) setpriority(PRIO_PROCESS, 0, nval); } ruadd(ru, ru2) register struct rusage *ru, *ru2; { register long *lp, *lp2; register int cnt; tvadd(&ru->ru_utime, &ru2->ru_utime); tvadd(&ru->ru_stime, &ru2->ru_stime); if (ru2->ru_maxrss > ru->ru_maxrss) ru->ru_maxrss = ru2->ru_maxrss; cnt = &ru->ru_last - &ru->ru_first + 1; lp = &ru->ru_first; lp2 = &ru2->ru_first; do *lp++ += *lp2++; while (--cnt > 0); } prusage(r0, r1, e, b) register struct rusage *r0, *r1; struct timeval *e, *b; { register time_t t = (r1->ru_utime.tv_sec-r0->ru_utime.tv_sec)*100+ (r1->ru_utime.tv_usec-r0->ru_utime.tv_usec)/10000+ (r1->ru_stime.tv_sec-r0->ru_stime.tv_sec)*100+ (r1->ru_stime.tv_usec-r0->ru_stime.tv_usec)/10000; register char *cp; register long i; register struct varent *vp = adrof("time"); long ms = (e->tv_sec-b->tv_sec)*100 + (e->tv_usec-b->tv_usec)/10000; #ifdef pdp11 cp = "%Uu %Ss %E %P %I+%Oio %Vov %Wsw"; #else cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww"; #endif if (vp && vp->vec[0] && vp->vec[1]) cp = vp->vec[1]; for (; *cp; cp++) if (*cp != '%') putchar(*cp); else if (cp[1]) switch(*++cp) { case 'U': pdeltat(&r1->ru_utime, &r0->ru_utime); break; case 'S': pdeltat(&r1->ru_stime, &r0->ru_stime); break; case 'E': psecs(ms / 100); break; case 'P': printf("%d%%", (int) (t*100 / ((ms ? ms : 1)))); break; #ifdef pdp11 case 'V': printf("%ld", r1->ru_ovly - r0->ru_ovly); break; #endif case 'W': i = r1->ru_nswap - r0->ru_nswap; printf("%ld", i); break; case 'X': printf("%ld", t == 0 ? 0L : (r1->ru_ixrss-r0->ru_ixrss)/t); break; case 'D': printf("%ld", t == 0 ? 0L : (r1->ru_idrss+r1->ru_isrss-(r0->ru_idrss+r0->ru_isrss))/t); break; case 'K': printf("%ld", t == 0 ? 0L : ((r1->ru_ixrss+r1->ru_isrss+r1->ru_idrss) - (r0->ru_ixrss+r0->ru_idrss+r0->ru_isrss))/t); break; case 'M': printf("%ld", r1->ru_maxrss/2); break; case 'F': printf("%ld", r1->ru_majflt-r0->ru_majflt); break; case 'R': printf("%ld", r1->ru_minflt-r0->ru_minflt); break; case 'I': printf("%ld", r1->ru_inblock-r0->ru_inblock); break; case 'O': printf("%ld", r1->ru_oublock-r0->ru_oublock); break; } putchar('\n'); } pdeltat(t1, t0) struct timeval *t1, *t0; { struct timeval td; tvsub(&td, t1, t0); printf("%ld.%01ld", td.tv_sec, td.tv_usec/100000); } tvadd(tsum, t0) struct timeval *tsum, *t0; { tsum->tv_sec += t0->tv_sec; tsum->tv_usec += t0->tv_usec; if (tsum->tv_usec > 1000000) tsum->tv_sec++, tsum->tv_usec -= 1000000; } tvsub(tdiff, t1, t0) struct timeval *tdiff, *t1, *t0; { tdiff->tv_sec = t1->tv_sec - t0->tv_sec; tdiff->tv_usec = t1->tv_usec - t0->tv_usec; if (tdiff->tv_usec < 0) tdiff->tv_sec--, tdiff->tv_usec += 1000000; } ru1, &timedol, &time0); } /* * donice is only called when it on the line by itself or with a +- valbin/csh/sh.exec.c 444 0 12 15726 5057640003 7106 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.exec.c 5.2 (Berkeley) 6/6/85"; #endif #include "sh.h" #include /* * C shell */ /* * System level search and execute of a command. * We look in each directory for the specified command name. * If the name contains a '/' then we execute only the full path name. * If there is no search path then we execute only full path names. */ /* * As we search for the command we note the first non-trivial error * message for presentation to the user. This allows us often * to show that a file has the wrong mode/no access when the file * is not in the last component of the search path, so we must * go on after first detecting the error. */ char *exerr; /* Execution error message */ char *expath; /* Path for exerr */ /* * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used * to hash execs. If it is allocated (havhash true), then to tell * whether ``name'' is (possibly) present in the i'th component * of the variable path, you look at the bit in xhash indexed by * hash(hashname("name"), i). This is setup automatically * after .login is executed, and recomputed whenever ``path'' is * changed. * The two part hash function is designed to let texec() call the * more expensive hashname() only once and the simple hash() several * times (once for each path component checked). * Byte size is assumed to be 8. */ #define HSHSIZ 8192 /* 1k bytes */ #define HSHMASK (HSHSIZ - 1) #define HSHMUL 243 char xhash[HSHSIZ / 8]; #define hash(a, b) ((a) * HSHMUL + (b) & HSHMASK) #define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7)) /* bit test */ #define bis(h, b) ((h)[(b) >> 3] |= 1 << ((b) & 7)) /* bit set */ #ifdef VFORK int hits, misses; #endif /* Dummy search path for just absolute search when no path */ char *justabs[] = { "", 0 }; doexec(t) register struct command *t; { char *sav; register char *dp, **pv, **av; register struct varent *v; bool slash = any('/', t->t_dcom[0]); int hashval, hashval1, i; char *blk[2]; /* * Glob the command name. If this does anything, then we * will execute the command only relative to ".". One special * case: if there is no PATH, then we execute only commands * which start with '/'. */ dp = globone(t->t_dcom[0]); sav = t->t_dcom[0]; exerr = 0; expath = t->t_dcom[0] = dp; xfree(sav); v = adrof("path"); if (v == 0 && expath[0] != '/') pexerr(); slash |= gflag; /* * Glob the argument list, if necessary. * Otherwise trim off the quote bits. */ gflag = 0; av = &t->t_dcom[1]; tglob(av); if (gflag) { av = glob(av); if (av == 0) error("No match"); } blk[0] = t->t_dcom[0]; blk[1] = 0; av = blkspl(blk, av); #ifdef VFORK Vav = av; #endif trim(av); xechoit(av); /* Echo command if -x */ /* * Since all internal file descriptors are set to close on exec, * we don't need to close them explicitly here. Just reorient * ourselves for error messages. */ SHIN = 0; SHOUT = 1; SHDIAG = 2; OLDSTD = 0; /* * We must do this AFTER any possible forking (like `foo` * in glob) so that this shell can still do subprocesses. */ (void) sigsetmask(0L); /* * If no path, no words in path, or a / in the filename * then restrict the command search. */ if (v == 0 || v->vec[0] == 0 || slash) pv = justabs; else pv = v->vec; sav = strspl("/", *av); /* / command name for postpending */ #ifdef VFORK Vsav = sav; #endif if (havhash) hashval = hashname(*av); i = 0; #ifdef VFORK hits++; #endif do { if (!slash && pv[0][0] == '/' && havhash) { hashval1 = hash(hashval, i); if (!bit(xhash, hashval1)) goto cont; } if (pv[0][0] == 0 || eq(pv[0], ".")) /* don't make ./xxx */ texec(*av, av); else { dp = strspl(*pv, sav); #ifdef VFORK Vdp = dp; #endif texec(dp, av); #ifdef VFORK Vdp = 0; #endif xfree(dp); } #ifdef VFORK misses++; #endif cont: pv++; i++; } while (*pv); #ifdef VFORK hits--; #endif #ifdef VFORK Vsav = 0; Vav = 0; #endif xfree(sav); xfree((char *)av); pexerr(); } pexerr() { /* Couldn't find the damn thing */ setname(expath); /* xfree(expath); */ if (exerr) bferr(exerr); bferr("Command not found"); } /* * Execute command f, arg list t. * Record error message if not found. * Also do shell scripts here. */ texec(f, t) char *f; register char **t; { register struct varent *v; register char **vp; extern char *sys_errlist[]; char *lastsh[2]; execv(f, t); switch (errno) { case ENOEXEC: /* * If there is an alias for shell, then * put the words of the alias in front of the * argument list replacing the command name. * Note no interpretation of the words at this point. */ v = adrof1("shell", &aliases); if (v == 0) { #ifdef OTHERSH register int ff = open(f, 0); char ch; #endif vp = lastsh; vp[0] = adrof("shell") ? value("shell") : SHELLPATH; vp[1] = (char *) NULL; #ifdef OTHERSH if (ff != -1 && read(ff, &ch, 1) == 1 && ch != '#') vp[0] = OTHERSH; (void) close(ff); #endif } else vp = v->vec; t[0] = f; t = blkspl(vp, t); /* Splice up the new arglst */ f = *t; xfree((char *)t); execv(f, t); /* The sky is falling, the sky is falling! */ case ENOMEM: Perror(f); case ENOENT: break; default: if (exerr == 0) { exerr = sys_errlist[errno]; expath = savestr(f); } } } /*ARGSUSED*/ execash(t, kp) char **t; register struct command *kp; { rechist(); (void) signal(SIGINT, parintr); (void) signal(SIGQUIT, parintr); (void) signal(SIGTERM, parterm); /* if doexec loses, screw */ lshift(kp->t_dcom, 1); exiterr++; doexec(kp); /*NOTREACHED*/ } xechoit(t) char **t; { if (adrof("echo")) { flush(); haderr = 1; blkpr(t), putchar('\n'); haderr = 0; } } /*VARARGS0*//*ARGSUSED*/ dohash() { struct stat stb; DIR *dirp; register struct direct *dp; register int cnt; int i = 0; struct varent *v = adrof("path"); char **pv; int hashval; havhash = 1; for (cnt = 0; cnt < sizeof xhash; cnt++) xhash[cnt] = 0; if (v == 0) return; for (pv = v->vec; *pv; pv++, i++) { if (pv[0][0] != '/') continue; dirp = opendir(*pv); if (dirp == NULL) continue; if (fstat(dirp->dd_fd, &stb) < 0 || !isdir(stb)) { closedir(dirp); continue; } while ((dp = readdir(dirp)) != NULL) { if (dp->d_ino == 0) continue; if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || dp->d_name[1] == '.' && dp->d_name[2] == '\0')) continue; hashval = hash(hashname(dp->d_name), i); bis(xhash, hashval); } closedir(dirp); } } dounhash() { havhash = 0; } #ifdef VFORK hashstat() { if (hits+misses) printf("%d hits, %d misses, %d%%\n", hits, misses, (int)(100L * hits / (hits + misses))); } #endif /* * Hash a command name. */ hashname(cp) register char *cp; { register long h = 0; while (*cp) h = hash(h, *cp++); return ((int) h); } u = log(getfval(x.optr)); else if (t ==bin/csh/sh.hist.c 444 0 12 4627 5057640200 7106 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.hist.c 5.2 (Berkeley) 6/6/85"; #endif #include "sh.h" /* * C shell */ savehist(sp) struct wordent *sp; { register struct Hist *hp, *np; register int histlen = 0; char *cp; /* throw away null lines */ if (sp->next->word[0] == '\n') return; cp = value("history"); if (*cp) { register char *p = cp; while (*p) { if (!digit(*p)) { histlen = 0; break; } histlen = histlen * 10 + *p++ - '0'; } } for (hp = &Histlist; np = hp->Hnext;) if (eventno - np->Href >= histlen || histlen == 0) hp->Hnext = np->Hnext, hfree(np); else hp = np; (void) enthist(++eventno, sp, 1); } struct Hist * enthist(event, lp, docopy) int event; register struct wordent *lp; bool docopy; { register struct Hist *np; np = (struct Hist *) xalloc(sizeof *np); np->Hnum = np->Href = event; if (docopy) copylex(&np->Hlex, lp); else { np->Hlex.next = lp->next; lp->next->prev = &np->Hlex; np->Hlex.prev = lp->prev; lp->prev->next = &np->Hlex; } np->Hnext = Histlist.Hnext; Histlist.Hnext = np; return (np); } hfree(hp) register struct Hist *hp; { freelex(&hp->Hlex); xfree((char *)hp); } dohist(vp) char **vp; { int n, rflg = 0, hflg = 0; if (getn(value("history")) == 0) return; if (setintr) (void) sigsetmask(sigblock(0L) & ~sigmask(SIGINT)); while (*++vp && **vp == '-') { char *vp2 = *vp; while (*++vp2) switch (*vp2) { case 'h': hflg++; break; case 'r': rflg++; break; case '-': /* ignore multiple '-'s */ break; default: printf("Unknown flag: -%c\n", *vp2); error("Usage: history [-rh] [# number of events]"); } } if (*vp) n = getn(*vp); else { n = getn(value("history")); } dohist1(Histlist.Hnext, &n, rflg, hflg); } dohist1(hp, np, rflg, hflg) struct Hist *hp; int *np, rflg, hflg; { bool print = (*np) > 0; top: if (hp == 0) return; (*np)--; hp->Href++; if (rflg == 0) { dohist1(hp->Hnext, np, rflg, hflg); if (print) phist(hp, hflg); return; } if (*np >= 0) phist(hp, hflg); hp = hp->Hnext; goto top; } phist(hp, hflg) register struct Hist *hp; int hflg; { if (hflg == 0) printf("%6d\t", hp->Hnum); prlex(&hp->Hlex); } sh function is designed to let texec() call the * more expensive hashname() only once and the simple hasbin/csh/sh.local.h 444 0 12 2741 4013203114 7217 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sh.local.h 5.2 (Berkeley) 6/6/85 */ /* * This file defines certain local parameters * A symbol should be defined in Makefile for local conditional * compilation, e.g. IIASA or ERNIE, to be tested here and elsewhere. */ /* * Fundamental definitions which may vary from system to system. * * BUFSIZ The i/o buffering size; also limits word size * SHELLPATH Where the shell will live; initalizes $shell * MAILINTVL How often to mailcheck; more often is more expensive * OTHERSH Shell for scripts which don't start with # */ #define BUFSIZ 1024 /* default buffer size */ #define SHELLPATH "/bin/csh" #define OTHERSH "/bin/sh" #define FORKSLEEP 10 /* delay loop on non-interactive fork failure */ #define MAILINTVL 600 /* 10 minutes */ /* * The shell moves std in/out/diag and the old std input away from units * 0, 1, and 2 so that it is easy to set up these standards for invoked * commands. */ #define FSHTTY 15 /* /dev/tty when manip pgrps */ #define FSHIN 16 /* Preferred desc for shell input */ #define FSHOUT 17 /* ... shell output */ #define FSHDIAG 18 /* ... shell diagnostics */ #define FOLDSTD 19 /* ... old std input */ #ifdef IIASA #undef OTHERSH #endif #ifdef vax #define copy(to, from, size) bcopy(from, to, size) #endif #ifdef PROF #define exit(n) done(n) #endif () only once and the simple hasbin/csh/sh.proc.c 444 0 12 55557 5057640432 7141 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.proc.c 5.5 (Berkeley) 5/13/86"; #endif #include "sh.h" #include "sh.dir.h" #include "sh.proc.h" #include #include /* * C Shell - functions that manage processes, handling hanging, termination */ #define BIGINDEX 9 /* largest desirable job index */ /* * pchild - called at interrupt level by the SIGCHLD signal * indicating that at least one child has terminated or stopped * thus at least one wait system call will definitely return a * childs status. Top level routines (like pwait) must be sure * to mask interrupts when playing with the proclist data structures! */ pchild() { register struct process *pp; register struct process *fp; register int pid; union wait w; int jobflags; struct rusage ru; loop: pid = wait3(&w, (setintr ? WNOHANG|WUNTRACED:WNOHANG), &ru); if (pid <= 0) { if (errno == EINTR) { errno = 0; goto loop; } pnoprocesses = pid == -1; return; } for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) if (pid == pp->p_pid) goto found; goto loop; found: if (pid == atoi(value("child"))) unsetv("child"); pp->p_flags &= ~(PRUNNING|PSTOPPED|PREPORTED); if (WIFSTOPPED(w)) { pp->p_flags |= PSTOPPED; pp->p_reason = w.w_stopsig; } else { if (pp->p_flags & (PTIME|PPTIME) || adrof("time")) (void) gettimeofday(&pp->p_etime, (struct timezone *)0); pp->p_rusage = ru; if (WIFSIGNALED(w)) { if (w.w_termsig == SIGINT) pp->p_flags |= PINTERRUPTED; else pp->p_flags |= PSIGNALED; if (w.w_coredump) pp->p_flags |= PDUMPED; pp->p_reason = w.w_termsig; } else { pp->p_reason = w.w_retcode; if (pp->p_reason != 0) pp->p_flags |= PAEXITED; else pp->p_flags |= PNEXITED; } } jobflags = 0; fp = pp; do { if ((fp->p_flags & (PPTIME|PRUNNING|PSTOPPED)) == 0 && !child && adrof("time") && fp->p_rusage.ru_utime.tv_sec+fp->p_rusage.ru_stime.tv_sec >= atoi(value("time"))) fp->p_flags |= PTIME; jobflags |= fp->p_flags; } while ((fp = fp->p_friends) != pp); pp->p_flags &= ~PFOREGND; if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { pp->p_flags &= ~PPTIME; pp->p_flags |= PTIME; } if ((jobflags & (PRUNNING|PREPORTED)) == 0) { fp = pp; do { if (fp->p_flags&PSTOPPED) fp->p_flags |= PREPORTED; } while((fp = fp->p_friends) != pp); while(fp->p_pid != fp->p_jobid) fp = fp->p_friends; if (jobflags&PSTOPPED) { if (pcurrent && pcurrent != fp) pprevious = pcurrent; pcurrent = fp; } else pclrcurr(fp); if (jobflags&PFOREGND) { if (jobflags & (PSIGNALED|PSTOPPED|PPTIME) || #ifdef IIASA jobflags & PAEXITED || #endif !eq(dcwd->di_name, fp->p_cwd->di_name)) { ; /* print in pjwait */ } /* else if ((jobflags & (PTIME|PSTOPPED)) == PTIME) ptprint(fp); */ } else { if (jobflags&PNOTIFY || adrof("notify")) { printf("\215\n"); (void) pprint(pp, NUMBER|NAME|REASON); if ((jobflags&PSTOPPED) == 0) pflush(pp); } else { fp->p_flags |= PNEEDNOTE; neednote++; } } } goto loop; } pnote() { register struct process *pp; int flags; long omask; neednote = 0; for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) { if (pp->p_flags & PNEEDNOTE) { omask = sigblock(sigmask(SIGCHLD)); pp->p_flags &= ~PNEEDNOTE; flags = pprint(pp, NUMBER|NAME|REASON); if ((flags&(PRUNNING|PSTOPPED)) == 0) pflush(pp); (void) sigsetmask(omask); } } } /* * pwait - wait for current job to terminate, maintaining integrity * of current and previous job indicators. */ pwait() { register struct process *fp, *pp; long omask; /* * Here's where dead procs get flushed. */ omask = sigblock(sigmask(SIGCHLD)); for (pp = (fp = &proclist)->p_next; pp != PNULL; pp = (fp = pp)->p_next) if (pp->p_pid == 0) { fp->p_next = pp->p_next; xfree(pp->p_command); if (pp->p_cwd && --pp->p_cwd->di_count == 0) if (pp->p_cwd->di_next == 0) dfree(pp->p_cwd); xfree((char *)pp); pp = fp; } (void) sigsetmask(omask); pjwait(pcurrjob); } /* * pjwait - wait for a job to finish or become stopped * It is assumed to be in the foreground state (PFOREGND) */ pjwait(pp) register struct process *pp; { register struct process *fp; int jobflags, reason; long omask; while (pp->p_pid != pp->p_jobid) pp = pp->p_friends; fp = pp; do { if ((fp->p_flags&(PFOREGND|PRUNNING)) == PRUNNING) printf("BUG: waiting for background job!\n"); } while ((fp = fp->p_friends) != pp); /* * Now keep pausing as long as we are not interrupted (SIGINT), * and the target process, or any of its friends, are running */ fp = pp; omask = sigblock(sigmask(SIGCHLD)); for (;;) { jobflags = 0; do jobflags |= fp->p_flags; while ((fp = (fp->p_friends)) != pp); if ((jobflags & PRUNNING) == 0) break; sigpause(sigblock(0L) &~ sigmask(SIGCHLD)); } (void) sigsetmask(omask); if (tpgrp > 0) /* get tty back */ (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp); if ((jobflags&(PSIGNALED|PSTOPPED|PTIME)) || !eq(dcwd->di_name, fp->p_cwd->di_name)) { if (jobflags&PSTOPPED) printf("\n"); (void) pprint(pp, AREASON|SHELLDIR); } if ((jobflags&(PINTERRUPTED|PSTOPPED)) && setintr && (!gointr || !eq(gointr, "-"))) { if ((jobflags & PSTOPPED) == 0) pflush(pp); pintr1(0); /*NOTREACHED*/ } reason = 0; fp = pp; do { if (fp->p_reason) reason = fp->p_flags & (PSIGNALED|PINTERRUPTED) ? fp->p_reason | QUOTE : fp->p_reason; } while ((fp = fp->p_friends) != pp); set("status", putn(reason)); if (reason && exiterr) exitstat(); pflush(pp); } /* * dowait - wait for all processes to finish */ dowait() { register struct process *pp; long omask; pjobs++; omask = sigblock(sigmask(SIGCHLD)); loop: for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_pid && /* pp->p_pid == pp->p_jobid && */ pp->p_flags&PRUNNING) { sigpause(0L); goto loop; } (void) sigsetmask(omask); pjobs = 0; } /* * pflushall - flush all jobs from list (e.g. at fork()) */ pflushall() { register struct process *pp; for (pp = proclist.p_next; pp != PNULL; pp = pp->p_next) if (pp->p_pid) pflush(pp); } /* * pflush - flag all process structures in the same job as the * the argument process for deletion. The actual free of the * space is not done here since pflush is called at interrupt level. */ pflush(pp) register struct process *pp; { register struct process *np; register int index; if (pp->p_pid == 0) { printf("BUG: process flushed twice"); return; } while (pp->p_pid != pp->p_jobid) pp = pp->p_friends; pclrcurr(pp); if (pp == pcurrjob) pcurrjob = 0; index = pp->p_index; np = pp; do { np->p_index = np->p_pid = 0; np->p_flags &= ~PNEEDNOTE; } while ((np = np->p_friends) != pp); if (index == pmaxindex) { for (np = proclist.p_next, index = 0; np; np = np->p_next) if (np->p_index > index) index = np->p_index; pmaxindex = index; } } /* * pclrcurr - make sure the given job is not the current or previous job; * pp MUST be the job leader */ pclrcurr(pp) register struct process *pp; { if (pp == pcurrent) if (pprevious != PNULL) { pcurrent = pprevious; pprevious = pgetcurr(pp); } else { pcurrent = pgetcurr(pp); pprevious = pgetcurr(pp); } else if (pp == pprevious) pprevious = pgetcurr(pp); } /* +4 here is 1 for '\0', 1 ea for << >& >> */ char command[PMAXLEN+4]; int cmdlen; char *cmdp; /* * palloc - allocate a process structure and fill it up. * an important assumption is made that the process is running. */ palloc(pid, t) int pid; register struct command *t; { register struct process *pp; int i; pp = (struct process *)calloc(1, sizeof(struct process)); pp->p_pid = pid; pp->p_flags = t->t_dflg & FAND ? PRUNNING : PRUNNING|PFOREGND; if (t->t_dflg & FTIME) pp->p_flags |= PPTIME; cmdp = command; cmdlen = 0; padd(t); *cmdp++ = 0; if (t->t_dflg & FPOU) { pp->p_flags |= PPOU; if (t->t_dflg & FDIAG) pp->p_flags |= PDIAG; } pp->p_command = savestr(command); if (pcurrjob) { struct process *fp; /* careful here with interrupt level */ pp->p_cwd = 0; pp->p_index = pcurrjob->p_index; pp->p_friends = pcurrjob; pp->p_jobid = pcurrjob->p_pid; for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends) ; fp->p_friends = pp; } else { pcurrjob = pp; pp->p_jobid = pid; pp->p_friends = pp; pp->p_cwd = dcwd; dcwd->di_count++; if (pmaxindex < BIGINDEX) pp->p_index = ++pmaxindex; else { struct process *np; for (i = 1; ; i++) { for (np = proclist.p_next; np; np = np->p_next) if (np->p_index == i) goto tryagain; pp->p_index = i; if (i > pmaxindex) pmaxindex = i; break; tryagain:; } } if (pcurrent == PNULL) pcurrent = pp; else if (pprevious == PNULL) pprevious = pp; } pp->p_next = proclist.p_next; proclist.p_next = pp; (void) gettimeofday(&pp->p_btime, (struct timezone *)0); } padd(t) register struct command *t; { char **argp; if (t == 0) return; switch (t->t_dtyp) { case TPAR: pads("( "); padd(t->t_dspr); pads(" )"); break; case TCOM: for (argp = t->t_dcom; *argp; argp++) { pads(*argp); if (argp[1]) pads(" "); } break; case TOR: case TAND: case TFIL: case TLST: padd(t->t_dcar); switch (t->t_dtyp) { case TOR: pads(" || "); break; case TAND: pads(" && "); break; case TFIL: pads(" | "); break; case TLST: pads("; "); break; } padd(t->t_dcdr); return; } if ((t->t_dflg & FPIN) == 0 && t->t_dlef) { pads((t->t_dflg & FHERE) ? " << " : " < "); pads(t->t_dlef); } if ((t->t_dflg & FPOU) == 0 && t->t_drit) { pads((t->t_dflg & FCAT) ? " >>" : " >"); if (t->t_dflg & FDIAG) pads("&"); pads(" "); pads(t->t_drit); } } pads(cp) char *cp; { register int i = strlen(cp); if (cmdlen >= PMAXLEN) return; if (cmdlen + i >= PMAXLEN) { (void) strcpy(cmdp, " ..."); cmdlen = PMAXLEN; cmdp += 4; return; } (void) strcpy(cmdp, cp); cmdp += i; cmdlen += i; } /* * psavejob - temporarily save the current job on a one level stack * so another job can be created. Used for { } in exp6 * and `` in globbing. */ psavejob() { pholdjob = pcurrjob; pcurrjob = PNULL; } /* * prestjob - opposite of psavejob. This may be missed if we are interrupted * somewhere, but pendjob cleans up anyway. */ prestjob() { pcurrjob = pholdjob; pholdjob = PNULL; } /* * pendjob - indicate that a job (set of commands) has been completed * or is about to begin. */ pendjob() { register struct process *pp, *tp; if (pcurrjob && (pcurrjob->p_flags&(PFOREGND|PSTOPPED)) == 0) { pp = pcurrjob; while (pp->p_pid != pp->p_jobid) pp = pp->p_friends; printf("[%d]", pp->p_index); tp = pp; do { printf(" %d", pp->p_pid); pp = pp->p_friends; } while (pp != tp); printf("\n"); } pholdjob = pcurrjob = 0; } /* * pprint - print a job */ pprint(pp, flag) register struct process *pp; { register status, reason; struct process *tp; extern char *linp, linbuf[]; int jobflags, pstatus; char *format; while (pp->p_pid != pp->p_jobid) pp = pp->p_friends; if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { pp->p_flags &= ~PPTIME; pp->p_flags |= PTIME; } tp = pp; status = reason = -1; jobflags = 0; do { jobflags |= pp->p_flags; pstatus = pp->p_flags & PALLSTATES; if (tp != pp && linp != linbuf && !(flag&FANCY) && (pstatus == status && pp->p_reason == reason || !(flag&REASON))) printf(" "); else { if (tp != pp && linp != linbuf) printf("\n"); if(flag&NUMBER) if (pp == tp) printf("[%d]%s %c ", pp->p_index, pp->p_index < 10 ? " " : "", pp==pcurrent ? '+' : (pp == pprevious ? '-' : ' ')); else printf(" "); if (flag&FANCY) printf("%5d ", pp->p_pid); if (flag&(REASON|AREASON)) { if (flag&NAME) format = "%-21s"; else format = "%s"; if (pstatus == status) if (pp->p_reason == reason) { printf(format, ""); goto prcomd; } else reason = pp->p_reason; else { status = pstatus; reason = pp->p_reason; } switch (status) { case PRUNNING: printf(format, "Running "); break; case PINTERRUPTED: case PSTOPPED: case PSIGNALED: if ((flag&(REASON|AREASON)) && reason != SIGINT && reason != SIGPIPE) printf(format, mesg[pp->p_reason].pname); break; case PNEXITED: case PAEXITED: if (flag & REASON) if (pp->p_reason) printf("Exit %-16d", pp->p_reason); else printf(format, "Done"); break; default: printf("BUG: status=%-9o", status); } } } prcomd: if (flag&NAME) { printf("%s", pp->p_command); if (pp->p_flags & PPOU) printf(" |"); if (pp->p_flags & PDIAG) printf("&"); } if (flag&(REASON|AREASON) && pp->p_flags&PDUMPED) printf(" (core dumped)"); if (tp == pp->p_friends) { if (flag&ERSAND) printf(" &"); if (flag&JOBDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) { printf(" (wd: "); dtildepr(value("home"), tp->p_cwd->di_name); printf(")"); } } if (pp->p_flags&PPTIME && !(status&(PSTOPPED|PRUNNING))) { if (linp != linbuf) printf("\n\t"); { static struct rusage zru; prusage(&zru, &pp->p_rusage, &pp->p_etime, &pp->p_btime); } } if (tp == pp->p_friends) { if (linp != linbuf) printf("\n"); if (flag&SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) { printf("(wd now: "); dtildepr(value("home"), dcwd->di_name); printf(")\n"); } } } while ((pp = pp->p_friends) != tp); if (jobflags&PTIME && (jobflags&(PSTOPPED|PRUNNING)) == 0) { if (jobflags & NUMBER) printf(" "); ptprint(tp); } return (jobflags); } ptprint(tp) register struct process *tp; { struct timeval tetime, diff; static struct timeval ztime; struct rusage ru; static struct rusage zru; register struct process *pp = tp; ru = zru; tetime = ztime; do { ruadd(&ru, &pp->p_rusage); tvsub(&diff, &pp->p_etime, &pp->p_btime); if (timercmp(&diff, &tetime, >)) tetime = diff; } while ((pp = pp->p_friends) != tp); prusage(&zru, &ru, &tetime, &ztime); } /* * dojobs - print all jobs */ dojobs(v) char **v; { register struct process *pp; register int flag = NUMBER|NAME|REASON; int i; if (chkstop) chkstop = 2; if (*++v) { if (v[1] || !eq(*v, "-l")) error("Usage: jobs [ -l ]"); flag |= FANCY|JOBDIR; } for (i = 1; i <= pmaxindex; i++) for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_index == i && pp->p_pid == pp->p_jobid) { pp->p_flags &= ~PNEEDNOTE; if (!(pprint(pp, flag) & (PRUNNING|PSTOPPED))) pflush(pp); break; } } /* * dofg - builtin - put the job into the foreground */ dofg(v) char **v; { register struct process *pp; okpcntl(); ++v; do { pp = pfind(*v); pstart(pp, 1); pjwait(pp); } while (*v && *++v); } /* * %... - builtin - put the job into the foreground */ dofg1(v) char **v; { register struct process *pp; okpcntl(); pp = pfind(v[0]); pstart(pp, 1); pjwait(pp); } /* * dobg - builtin - put the job into the background */ dobg(v) char **v; { register struct process *pp; okpcntl(); ++v; do { pp = pfind(*v); pstart(pp, 0); } while (*v && *++v); } /* * %... & - builtin - put the job into the background */ dobg1(v) char **v; { register struct process *pp; pp = pfind(v[0]); pstart(pp, 0); } /* * dostop - builtin - stop the job */ dostop(v) char **v; { pkill(++v, SIGSTOP); } /* * dokill - builtin - superset of kill (1) */ dokill(v) char **v; { register int signum; register char *name; v++; if (v[0] && v[0][0] == '-') { if (v[0][1] == 'l') { for (signum = 1; signum <= NSIG; signum++) { if (name = mesg[signum].iname) printf("%s ", name); if (signum == 16) putchar('\n'); } putchar('\n'); return; } if (digit(v[0][1])) { signum = atoi(v[0]+1); if (signum < 0 || signum > NSIG) bferr("Bad signal number"); } else { name = &v[0][1]; for (signum = 1; signum <= NSIG; signum++) if (mesg[signum].iname && eq(name, mesg[signum].iname)) goto gotsig; setname(name); bferr("Unknown signal; kill -l lists signals"); } gotsig: v++; } else signum = SIGTERM; pkill(v, signum); } pkill(v, signum) char **v; int signum; { register struct process *pp, *np; register int jobflags = 0; int pid, err = 0; long omask; char *cp; extern char *sys_errlist[]; omask = sigmask(SIGCHLD); if (setintr) omask |= sigmask(SIGINT); omask = sigblock(omask) & ~omask; while (*v) { cp = globone(*v); if (*cp == '%') { np = pp = pfind(cp); do jobflags |= np->p_flags; while ((np = np->p_friends) != pp); switch (signum) { case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: if ((jobflags & PRUNNING) == 0) { printf("%s: Already stopped\n", cp); err++; goto cont; } } if (killpg(pp->p_jobid, signum) < 0) { printf("%s: ", cp); printf("%s\n", sys_errlist[errno]); err++; } if (signum == SIGTERM || signum == SIGHUP) (void) killpg(pp->p_jobid, SIGCONT); } else if (!(digit(*cp) || *cp == '-')) bferr("Arguments should be jobs or process id's"); else { pid = atoi(cp); if (kill(pid, signum) < 0) { printf("%d: ", pid); printf("%s\n", sys_errlist[errno]); err++; goto cont; } if (signum == SIGTERM || signum == SIGHUP) (void) kill(pid, SIGCONT); } cont: xfree(cp); v++; } (void) sigsetmask(omask); if (err) error(NOSTR); } /* * pstart - start the job in foreground/background */ pstart(pp, foregnd) register struct process *pp; int foregnd; { register struct process *np; int jobflags = 0; long omask; omask = sigblock(sigmask(SIGCHLD)); np = pp; do { jobflags |= np->p_flags; if (np->p_flags&(PRUNNING|PSTOPPED)) { np->p_flags |= PRUNNING; np->p_flags &= ~PSTOPPED; if (foregnd) np->p_flags |= PFOREGND; else np->p_flags &= ~PFOREGND; } } while((np = np->p_friends) != pp); if (!foregnd) pclrcurr(pp); (void) pprint(pp, foregnd ? NAME|JOBDIR : NUMBER|NAME|AMPERSAND); if (foregnd) (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pp->p_jobid); if (jobflags&PSTOPPED) (void) killpg(pp->p_jobid, SIGCONT); (void) sigsetmask(omask); } panystop(neednl) { register struct process *pp; chkstop = 2; for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_flags & PSTOPPED) error("\nThere are stopped jobs" + 1 - neednl); } struct process * pfind(cp) char *cp; { register struct process *pp, *np; if (cp == 0 || cp[1] == 0 || eq(cp, "%%") || eq(cp, "%+")) { if (pcurrent == PNULL) bferr("No current job"); return (pcurrent); } if (eq(cp, "%-") || eq(cp, "%#")) { if (pprevious == PNULL) bferr("No previous job"); return (pprevious); } if (digit(cp[1])) { int index = atoi(cp+1); for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_index == index && pp->p_pid == pp->p_jobid) return (pp); bferr("No such job"); } np = PNULL; for (pp = proclist.p_next; pp; pp = pp->p_next) if (pp->p_pid == pp->p_jobid) { if (cp[1] == '?') { register char *dp; for (dp = pp->p_command; *dp; dp++) { if (*dp != cp[2]) continue; if (prefix(cp+2, dp)) goto match; } } else if (prefix(cp+1, pp->p_command)) { match: if (np) bferr("Ambiguous"); np = pp; } } if (np) return (np); if (cp[1] == '?') bferr("No job matches pattern"); else bferr("No such job"); /*NOTREACHED*/ } /* * pgetcurr - find most recent job that is not pp, preferably stopped */ struct process * pgetcurr(pp) register struct process *pp; { register struct process *np; register struct process *xp = PNULL; for (np = proclist.p_next; np; np = np->p_next) if (np != pcurrent && np != pp && np->p_pid && np->p_pid == np->p_jobid) { if (np->p_flags & PSTOPPED) return (np); if (xp == PNULL) xp = np; } return (xp); } /* * donotify - flag the job so as to report termination asynchronously */ donotify(v) char **v; { register struct process *pp; pp = pfind(*++v); pp->p_flags |= PNOTIFY; } /* * Do the fork and whatever should be done in the child side that * should not be done if we are not forking at all (like for simple builtin's) * Also do everything that needs any signals fiddled with in the parent side * * Wanttty tells whether process and/or tty pgrps are to be manipulated: * -1: leave tty alone; inherit pgrp from parent * 0: already have tty; manipulate process pgrps only * 1: want to claim tty; manipulate process and tty pgrps * It is usually just the value of tpgrp. */ pfork(t, wanttty) struct command *t; /* command we are forking for */ int wanttty; { register int pid; bool ignint = 0; int pgrp; long omask; /* * A child will be uninterruptible only under very special * conditions. Remember that the semantics of '&' is * implemented by disconnecting the process from the tty so * signals do not need to ignored just for '&'. * Thus signals are set to default action for children unless: * we have had an "onintr -" (then specifically ignored) * we are not playing with signals (inherit action) */ if (setintr) ignint = (tpgrp == -1 && (t->t_dflg&FINT)) || (gointr && eq(gointr, "-")); /* * Hold SIGCHLD until we have the process installed in our table. */ omask = sigblock(sigmask(SIGCHLD)); while ((pid = fork()) < 0) if (setintr == 0) sleep(FORKSLEEP); else { (void) sigsetmask(omask); error("No more processes"); } if (pid == 0) { settimes(); pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); pflushall(); pcurrjob = PNULL; child++; if (setintr) { setintr = 0; /* until I think otherwise */ /* * Children just get blown away on SIGINT, SIGQUIT * unless "onintr -" seen. */ (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL); (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); if (wanttty >= 0) { /* make stoppable */ (void) signal(SIGTSTP, SIG_DFL); (void) signal(SIGTTIN, SIG_DFL); (void) signal(SIGTTOU, SIG_DFL); } (void) signal(SIGTERM, parterm); } else if (tpgrp == -1 && (t->t_dflg&FINT)) { (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); } if (wanttty > 0) (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pgrp); if (wanttty >= 0 && tpgrp >= 0) (void) setpgrp(0, pgrp); if (tpgrp > 0) tpgrp = 0; /* gave tty away */ /* * Nohup and nice apply only to TCOM's but it would be * nice (?!?) if you could say "nohup (foo;bar)" * Then the parser would have to know about nice/nohup/time */ if (t->t_dflg & FNOHUP) (void) signal(SIGHUP, SIG_IGN); if (t->t_dflg & FNICE) (void) setpriority(PRIO_PROCESS, 0, t->t_nice); } else { palloc(pid, t); (void) sigsetmask(omask); } return (pid); } okpcntl() { if (tpgrp == -1) error("No job control in this shell"); if (tpgrp == 0) error("No job control in subshells"); } lag&(REASON|AREASON) && pp->p_flags&PDUMPED) printf(" (core dumped)"); if (tp == pp->p_friends) { if (flag&ERSAND) printf(" &"); bin/csh/doprnt.c 444 0 12 30272 5057637534 7067 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) .ascii "@(#)doprnt.c 5.2 (Berkeley) 6/6/85" #endif # C library -- conversions .globl __doprnt .globl __strout #define flags r10 #define literb 0 #define liter 1 #define ndfndb 0 #define ndfnd 1 #define ljustb 1 #define ljust 2 #define zfillb 2 #define zfill 4 #define precb 3 #define prec 8 #define psignb 4 #define psign 16 #define gflagb 5 #define gflag 32 #define width r9 #define ndigit r8 #define fdesc -4(fp) #define exp -8(fp) #define sign -9(fp) .set one,010 # 1.0 in floating immediate .set ch.zer,'0 # cpp doesn't like single appostrophes .align 1 __doprnt: .word 0xfc0 # uses r11-r6 subl2 $128,sp movl 4(ap),r11 # addr of format string movl 12(ap),fdesc # output FILE ptr movl 8(ap),ap # addr of first arg loop: movl r11,r0 # current point in format bicl2 $liter,flags # no literal characters yet L1: movb (r11)+,width # next character of format beql L2 # end of format string cmpb width,$'% beql L2 # warning character bisl2 $liter,flags # literal character jbr L1 L2: blbc flags,L3 # bbc $literb,flags,L3 # no literals in format pushl fdesc # file pointer pushl $0 # no left/right adjust pushl r0 # addr subl3 r0,r11,r1 # length subl3 $1,r1,-(sp) # % or null not part of literal calls $4,__strout # dump the literal L3: blbs width,L4 # % is odd; end of format? ret # yes # htab overlaps last 16 characters of ftab ftab: .byte 0, 0, 0,'c,'d,'e,'f,'g, 0, 0, 0,'+,'l,'-,'.,'o htab: .byte '0,'1,'2,'3,'4,'5,'6,'7,'8,'9,'a,'b,'c,'d,'e,'f L4: movl sp,r5 # reset output buffer pointer clrq r9 # width; flags ljustb,ndfndb,zfillb L4a: movzbl (r11)+,r0 # supposed format extzv $0,$5,r0,r1 # bottom 5 bits L4b: cmpb r0,ftab[r1] # good enough? jneq L6 # no L4c: casel r1,$3,$22 # yes L5: .word charac-L5 # c .word decimal-L5 # d .word scien-L5 # e .word float-L5 # f .word general-L5 # g .word L6-L5 # h .word L6-L5 # i .word L6-L5 # j .word plus-L5 # + .word longorunsg-L5 # l .word minus-L5 # - .word dot-L5 # . .word octal-L5 # o .word gnum0-L5 # 0 .word gnum-L5 # 1 .word gnum-L5 # 2 .word gnum-L5 # 3 .word gnum-L5 # 4 .word gnum-L5 # 5 .word gnum-L5 # 6 .word gnum-L5 # 7 .word gnum-L5 # 8 .word gnum-L5 # 9 L6: jbcs $5,r0,L4b # capitals same as small cmpb r0,$'s jeql string cmpb r0,$'x jeql hex cmpb r0,$'u jeql unsigned cmpb r0,$'r jeql remote movzbl -1(r11),r0 # orginal "format" character cmpb r0,$'* jeql indir L9: movb r0,(r5)+ # print the unfound character jbr prbuf nulstr: .byte '(,'n,'u,'l,'l,'),0 string: movl ndigit,r0 jbs $precb,flags,L20 # max length was specified mnegl $1,r0 # default max length L20: movl (ap)+,r2 # addr first byte bneq L21 movab nulstr,r2 L21: locc $0,r0,(r2) # find the zero at the end movl r1,r5 # addr last byte +1 movl r2,r1 # addr first byte jbr prstr longorunsg: movb (r11)+,r0 cmpb r0,$'o jeql loct cmpb r0,$'x jeql lhex cmpb r0,$'d jeql long cmpb r0,$'u jeql lunsigned decl r11 jbr unsigned loct: octal: movl $30,r2 # init position movl $3,r3 # field width movl $10,r4 # result length -1 jbr L10 lhex: hex: movl $28,r2 # init position movl $4,r3 # field width movl $7,r4 # result length -1 L10: mnegl r3,r6 # increment clrl r1 movl (ap)+,r0 # fetch arg L11: extzv r2,r3,r0,r1 # pull out a digit movb htab[r1],(r5)+ # convert to character L12: acbl $0,r6,r2,L11 # continue until done clrb (r5) # flag end skpc $'0,r4,(sp) # skip over leading zeroes jbr prstr patdec: # editpc pattern for decimal printing .byte 0xA9 # eo$float 9 .byte 0x01 # eo$end_float .byte 0x91 # eo$move 1 .byte 0 # eo$end long: decimal: cvtlp (ap)+,$10,(sp) # 10 digits max L14: editpc $10,(sp),patdec,8(sp) # ascii at 8(sp); r5=end+1 skpc $' ,$10,8(sp) # skip leading blanks; r1=first prstr: # r1=addr first byte; r5=addr last byte +1 cvtbl $' ,-(sp) # blank fill jbc $zfillb,flags,L15 cvtbl $'0,(sp) # zero fill L15: pushl fdesc # FILE subl2 r1,r5 # r5=actual length=end+1-first subl3 r5,width,r0 # if >0, how much to fill bgeq L24 clrl r0 # no fill L24: jbs $ljustb,flags,L25 mnegl r0,r0 L25: pushl r0 # fill count pushl r1 # addr first byte pushl r5 # length calls $5,__strout jbr loop pone: .byte 0x1C # packed 1 unsigned: lunsigned: extzv $1,$31,(ap),r0 # right shift logical 1 bit cvtlp r0,$10,(sp) # convert [n/2] to packed movp $10,(sp),8(sp) # copy packed addp4 $10,8(sp),$10,(sp) # 2*[n/2] in packed, at (sp) blbc (ap)+,L14 # n was even addp4 $1,pone,$10,(sp) # n was odd jbr L14 charac: movl $4,r0 # chars per word L18: movb (ap)+,(r5)+ # transfer char bneq L19 decl r5 # omit null characters L19: sobgtr r0,L18 prbuf: movl sp,r1 # addr first byte jbr prstr plus: bisl2 $psign,flags # always print sign for floats jbr L4a minus: bisl2 $ljust,flags # left justification, please jbr L4a gnum0: jbs $ndfndb,flags,gnum jbs $precb,flags,gnump # ignore when reading precision bisl2 $zfill,flags # leading zero fill, please gnum: jbs $precb,flags,gnump moval (width)[width],width # width *= 5; movaw -ch.zer(r0)[width],width # width = 2*witdh + r0 - '0'; jbr gnumd gnump: moval (ndigit)[ndigit],ndigit # ndigit *= 5; movaw -ch.zer(r0)[ndigit],ndigit # ndigit = 2*ndigit + r0 - '0'; gnumd: bisl2 $ndfnd,flags # digit seen jbr L4a dot: clrl ndigit # start on the precision bisl2 $prec,flags bicl2 $ndfnd,flags jbr L4a indir: movl (ap)+,ndigit # width specified by parameter jbr gnumd remote: movl (ap)+,ap movl (ap)+,r11 jbr loop float: bsbw fltcvt fltg: jbs $ndfndb,flags,float1 movl $6,ndigit # default # digits to right of decpt. float1: addl3 exp,ndigit,r7 movl r7,r6 # for later "underflow" checking bgeq fxplrd clrl r7 # poor programmer planning fxplrd: cmpl r7,$31 # expressible in packed decimal? bleq fnarro # yes movl $31,r7 fnarro: subl3 $17,r7,r0 # where to round ashp r0,$17,(sp),$5,r7,16(sp) # do it bvc fnovfl # band-aid for microcode error (spurious overflow) clrl r0 # assume even length result jlbc r7,fleven # right movl $4,r0 # odd length result fleven: cmpv r0,$4,16(sp),$0 # top digit zero iff true overflow bneq fnovfl # end band-aid aobleq $0,r6,fnovfl # if "underflow" then jump movl r7,r0 incl exp incl r7 ashp r0,$1,pone,$0,r7,16(sp) ashl $-1,r7,r0 # displ to last byte bisb2 sign,16(sp)[r0] # insert sign fnovfl: movc3 $4,patsci,(sp) clrl r6 # # digits moved so far movl exp,r0 bleq fexpng bsbb patmov # digits to left of decpt. fexpng: tstl ndigit jeql fnodp movc3 $2,fpatdp,(r3) tstl exp bgeq fxppos addl3 exp,ndigit,r6 bgeq flfakl clrl r6 # it's all fill flfakl: subl3 r6,$31,r6 # fake length for patmov flfill: movc3 $2,fpatzf,(r3) # zero fill to right of dec.pt fxppos: movl ndigit,r0 bsbb patmov fnodp: sobgeq r6,fledit # must move at least 1 digit movl $31,r6 # none moved; fake it aobleq $1,ndigit,flfill # with a one-character zero fill fledit: editpc r7,16(sp),(sp),32(sp) jbr prflt patexp: .byte 0x03 # eo$set_signif .byte 0x44,'e # eo$insert 'e .byte 0x42,'+ # eo$load_plus '+ .byte 0x04 # eo$store_sign .byte 0x92 # eo$move 2 .byte 0 # eo$end patsci: .byte 0x42,'+ # eo$load_plus '+ .byte 0x03 # eo$set_signif .byte 0x04 # eo$store_sign .byte 0x91 # eo$move 1 fpatdp: .byte 0x44,'. # eo$insert '. fpatzf: .byte 0x40,'0 # eo$load_fill '0 # construct pattern at (r3) to move r0 digits in editpc; # r6 digits already moved for this number patmov: movb $0x90,r2 # eo$move subl3 r6,$31,r1 # # digits remaining in packed addl2 r0,r6 cmpl r0,r1 # enough digits remaining? bleq patsml # yes tstl exp # zero 'fill'; before or after rest? bgeq pataft # after pushl r1 # # digits remaining movb $0x80,r2 # eo$fill subl3 $31,r6,r0 # number of fill bytes bsbb patsml # recursion! movl (sp)+,r0 movb $0x90,r2 # eo$move jbr patsml pataft: movl r1,r0 # last of the 31 bsbb patsml # recursion! subl3 $31,r6,r0 # number of fill bytes movb $0x80,r2 # eo$fill patsml: tstl r0 bleq patzer # DEC doesn't like repetition counts of 0 mnegl $15,r1 # 15 digits at a time subl2 r1,r0 # counteract acbl jbr pattst patmlp: bisb3 r2,$15,(r3)+ # 15 pattst: acbl $16,r1,r0,patmlp # until <= 15 left bisb3 r2,r0,(r3)+ # rest patzer: clrb (r3) # eo$end rsb scien: bsbw fltcvt # get packed digits scig: incl ndigit jbs $ndfndb,flags,L23 movl $7,ndigit L23: subl3 $17,ndigit,r0 # rounding position ashp r0,$17,(sp),$5,ndigit,16(sp) # shift and round bvc snovfl # band-aid for microcode error (spurious overflow) clrl r0 # assume even length result jlbc ndigit,sceven # right movl $4,r0 # odd length result sceven: cmpv r0,$4,16(sp),$0 # top digit zero iff true overflow bneq snovfl # end band-aid incl exp # rounding overflowed to 100... subl3 $1,ndigit,r0 ashp r0,$1,pone,$0,ndigit,16(sp) ashl $-1,ndigit,r0 # displ to last byte bisb2 sign,16(sp)[r0] # insert sign snovfl: jbc $gflagb,flags,enotg # not %g format # find trailing zeroes in packed number ashl $-1,ndigit,r0 addl2 r3,r0 # addr of l.s.digit and sign movl $4,r1 # bit position of digit movl ndigit,r7 # current length of packed jbr gtz gtz1: xorl2 $4,r1 # position of next digit bneq gtz # same byte decl r0 # different byte gtz: cmpv r1,$4,(r0),$0 # a trailing zero? jneq gntz sobgtr r7,gtz1 incl r7 gntz: # r7: minimum width of fraction cmpl exp,$-4 jleq eg # small exponents use %e subl3 r7,exp,r0 cmpl $5,r0 jleq eg # so do (w+5) <= exp tstl r0 # rest use %f jleq fg # did we trim too many trailing zeroes? movl exp,r7 # yes fg: subl3 ndigit,r7,r0 ashp r0,ndigit,16(sp),$0,r7,(sp) movp r7,(sp),16(sp) subl3 exp,r7,ndigit # correct ndigit for %f jbr fnovfl eg: subl3 ndigit,r7,r0 ashp r0,ndigit,16(sp),$0,r7,(sp) movp r7,(sp),16(sp) movl r7,ndigit # packed number has been trimmed enotg: movc3 $7,patsci,(sp) movl $1,r6 # 1P subl3 $1,ndigit,r0 # digits after dec.pt bsbw patmov editpc ndigit,16(sp),(sp),32(sp) # 32(sp)->result, r5->(end+1) decl exp # compensate: 1 digit left of dec.pt cvtlp exp,$2,(sp) # exponent editpc $2,(sp),patexp,(r5) prflt: movab 32(sp),r1 jbs $psignb,flags,prflt1 cmpb (r1)+,$'+ beql prflt1 decl r1 prflt1: skpc $' ,$63,(r1) jbr prstr general: jbcs $gflagb,flags,scien jbr scien # safety net # convert double-floating at (ap) to 17-digit packed at (sp), # set 'sign' and 'exp', advance ap. fltcvt: clrb sign movd (ap)+,r5 jeql fzero bgtr fpos mnegd r5,r5 incb sign fpos: extzv $7,$8,r5,r2 # exponent of 2 movaw -0600(r2)[r2],r2 # unbias and mult by 3 bgeq epos subl2 $9,r2 epos: divl2 $10,r2 bsbb expten cmpd r0,r5 bgtr ceil incl r2 ceil: movl r2,exp mnegl r2,r2 cmpl r2,$29 # 10^(29+9) is all we can handle bleq getman muld2 ten16,r5 subl2 $16,r2 getman: addl2 $9,r2 # -ceil(log10(x)) + 9 bsbb expten emodd r0,r4,r5,r0,r5 # (r0+r4)*r5; r0=int, r5=frac fz1: cvtlp r0,$9,16(sp) # leading 9 digits ashp $8,$9,16(sp),$0,$17,4(sp) # as top 9 of 17 emodd ten8,$0,r5,r0,r5 cvtlp r0,$8,16(sp) # trailing 8 digits addp4 $8,16(sp),$17,4(sp) # combine leading and trailing bisb2 sign,12(sp) # and insert sign rsb fzero: clrl r0 movl $1,exp # 0.000e+00 and 0.000 rather than 0.000e-01 and .000 jbr fz1 # return 10^r2 as a double float in r0||r1 and 8 extra bits of precision in r4 # preserve r2, r5||r6 expten: movd $one,r0 # begin computing 10^exp10 clrl r4 # bit counter movad ten1,r3 # table address tstl r2 bgeq e10lp mnegl r2,r2 # get absolute value jbss $6,r2,e10lp # flag as negative e10lp: jbc r4,r2,el1 # want this power? muld2 (r3),r0 # yes el1: addl2 $8,r3 # advance to next power aobleq $5,r4,e10lp # through 10^32 jbcc $6,r2,el2 # correct for negative exponent divd3 r0,$one,r0 # by taking reciprocal mnegl r2,r2 el2: clrl r4 # 8 extra bits of precision rsb # powers of ten .align 2 ten1: .word 0x4220,0,0,0 ten2: .word 0x43c8,0,0,0 ten4: .word 0x471c,0x4000,0,0 ten8: .word 0x4dbe,0xbc20,0,0 ten16: .word 0x5b0e,0x1bc9,0xbf04,0 ten32: .word 0x759d,0xc5ad,0xa82b,0x70b6 == 'l') { for (signum = 1; signum <= NSIG; signum++) { if (name = mesg[signum].iname) printf("%s ", name); if (signum == 16) putchar('\n'); } putchar('\n'); return; } if (digit(v[0][1])) { signum = atoi(v[0]+1); if (signum < 0 || signum > NSIG) bferr("Bad signal number"); } else bin/csh/sh.char.c 444 0 12 3353 5057637654 7072 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.char.c 5.3 (Berkeley) 3/29/86"; #endif #include "sh.char.h" unsigned short _cmap[256] = { /* nul soh stx etx */ 0, 0, 0, 0, /* eot enq ack bel */ 0, 0, 0, 0, /* bs ht nl vt */ 0, _SP|_META, _NL|_META, 0, /* np cr so si */ 0, 0, 0, 0, /* dle dc1 dc2 dc3 */ 0, 0, 0, 0, /* dc4 nak syn etb */ 0, 0, 0, 0, /* can em sub esc */ 0, 0, 0, 0, /* fs gs rs us */ 0, 0, 0, 0, /* sp ! " # */ _SP|_META, 0, _Q, _META, /* $ % & ' */ _DOL, 0, _META, _Q, /* ( ) * + */ _META, _META, _GLOB, 0, /* , - . / */ 0, 0, 0, 0, /* 0 1 2 3 */ _DIG, _DIG, _DIG, _DIG, /* 4 5 6 7 */ _DIG, _DIG, _DIG, _DIG, /* 8 9 : ; */ _DIG, _DIG, 0, _META, /* < = > ? */ _META, 0, _META, _GLOB, /* @ A B C */ 0, _LET, _LET, _LET, /* D E F G */ _LET, _LET, _LET, _LET, /* H I J K */ _LET, _LET, _LET, _LET, /* L M N O */ _LET, _LET, _LET, _LET, /* P Q R S */ _LET, _LET, _LET, _LET, /* T U V W */ _LET, _LET, _LET, _LET, /* X Y Z [ */ _LET, _LET, _LET, _GLOB, /* \ ] ^ _ */ _ESC, 0, 0, _LET, /* ` a b c */ _Q1|_GLOB, _LET, _LET, _LET, /* d e f g */ _LET, _LET, _LET, _LET, /* h i j k */ _LET, _LET, _LET, _LET, /* l m n o */ _LET, _LET, _LET, _LET, /* p q r s */ _LET, _LET, _LET, _LET, /* t u v w */ _LET, _LET, _LET, _LET, /* x y z { */ _LET, _LET, _LET, _GLOB, /* | } ~ del */ _META, 0, 0, 0, }; dth,r0 # if >0, how much to fill bgeq L24 clrl r0 # no fill L24: jbs $ljustb,flags,L25 mnegl r0,r0 L25: pushl r0 # fill count pushl r1 # addr first byte pushl r5 # length calls $5,__strout jbr loop pone: .byte 0x1C # packed 1 unsigned: lunsigned: extzv $bin/csh/sh.h 644 0 12 30711 5514435507 6172 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sh.h 5.3.1 (2.11BSD GTE) 1/1/94 */ #include #include #include #include #include #include #include #include "sh.local.h" #include "sh.char.h" /* * C shell * * Bill Joy, UC Berkeley * October, 1978; May 1980 * * Jim Kulp, IIASA, Laxenburg Austria * April, 1980 */ #define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR) typedef char bool; #define eq(a, b) (strcmp(a, b) == 0) /* * Global flags */ bool chkstop; /* Warned of stopped jobs... allow exit */ bool didfds; /* Have setup i/o fd's for child */ bool doneinp; /* EOF indicator after reset from readc */ bool exiterr; /* Exit if error or non-zero exit status */ bool child; /* Child shell ... errors cause exit */ bool haderr; /* Reset was because of an error */ bool intty; /* Input is a tty */ bool intact; /* We are interactive... therefore prompt */ bool justpr; /* Just print because of :p hist mod */ bool loginsh; /* We are a loginsh -> .login/.logout */ bool neednote; /* Need to pnotify() */ bool noexec; /* Don't execute, just syntax check */ bool pjobs; /* want to print jobs if interrupted */ bool setintr; /* Set interrupts on/off -> Wait intr... */ bool timflg; /* Time the next waited for command */ bool havhash; /* path hashing is available */ #ifdef FILEC bool filec; /* doing filename expansion */ #endif /* * Global i/o info */ char *arginp; /* Argument input for sh -c and internal `xx` */ int onelflg; /* 2 -> need line for -t, 1 -> exit on read */ char *file; /* Name of shell file for $0 */ char *err; /* Error message from scanner/parser */ int errno; /* Error from C library routines */ char *shtemp; /* Temp name for << shell files in /tmp */ struct timeval time0; /* Time at which the shell started */ struct rusage ru0; /* * Miscellany */ char *doldol; /* Character pid for $$ */ int uid; /* Invokers uid */ time_t chktim; /* Time mail last checked */ int shpgrp; /* Pgrp of shell */ int tpgrp; /* Terminal process group */ /* If tpgrp is -1, leave tty alone! */ int opgrp; /* Initial pgrp and tty pgrp */ int oldisc; /* Initial line discipline or -1 */ /* * These are declared here because they want to be * initialized in sh.init.c (to allow them to be made readonly) */ struct biltins { char *bname; int (*bfunct)(); short minargs, maxargs; } bfunc[]; extern int nbfunc; struct srch { char *s_name; short s_value; } srchn[]; extern int nsrchn; /* * To be able to redirect i/o for builtins easily, the shell moves the i/o * descriptors it uses away from 0,1,2. * Ideally these should be in units which are closed across exec's * (this saves work) but for version 6, this is not usually possible. * The desired initial values for these descriptors are defined in * sh.local.h. */ short SHIN; /* Current shell input (script) */ short SHOUT; /* Shell output */ short SHDIAG; /* Diagnostic output... shell errs go here */ short OLDSTD; /* Old standard input (def for cmds) */ /* * Error control * * Errors in scanning and parsing set up an error message to be printed * at the end and complete. Other errors always cause a reset. * Because of source commands and .cshrc we need nested error catches. */ jmp_buf reslab; #define setexit() ((void) setjmp(reslab)) #define reset() longjmp(reslab, 0) /* Should use structure assignment here */ #define getexit(a) copy((char *)(a), (char *)reslab, sizeof reslab) #define resexit(a) copy((char *)reslab, ((char *)(a)), sizeof reslab) char *gointr; /* Label for an onintr transfer */ int (*parintr)(); /* Parents interrupt catch */ int (*parterm)(); /* Parents terminate catch */ /* * Lexical definitions. * * All lexical space is allocated dynamically. * The eighth bit of characters is used to prevent recognition, * and eventually stripped. */ #define QUOTE 0200 /* Eighth char bit used internally for 'ing */ #define TRIM 0177 /* Mask to strip quote bit */ /* * Each level of input has a buffered input structure. * There are one or more blocks of buffered input for each level, * exactly one if the input is seekable and tell is available. * In other cases, the shell buffers enough blocks to keep all loops * in the buffer. */ struct Bin { off_t Bfseekp; /* Seek pointer */ off_t Bfbobp; /* Seekp of beginning of buffers */ off_t Bfeobp; /* Seekp of end of buffers */ short Bfblocks; /* Number of buffer blocks */ char **Bfbuf; /* The array of buffer blocks */ } B; #define fseekp B.Bfseekp #define fbobp B.Bfbobp #define feobp B.Bfeobp #define fblocks B.Bfblocks #define fbuf B.Bfbuf #define btell() fseekp #ifndef btell off_t btell(); #endif /* * The shell finds commands in loops by reseeking the input * For whiles, in particular, it reseeks to the beginning of the * line the while was on; hence the while placement restrictions. */ off_t lineloc; #ifdef TELL bool cantell; /* Is current source tellable ? */ #endif /* * Input lines are parsed into doubly linked circular * lists of words of the following form. */ struct wordent { char *word; struct wordent *prev; struct wordent *next; }; /* * During word building, both in the initial lexical phase and * when expanding $ variable substitutions, expansion by `!' and `$' * must be inhibited when reading ahead in routines which are themselves * processing `!' and `$' expansion or after characters such as `\' or in * quotations. The following flags are passed to the getC routines * telling them which of these substitutions are appropriate for the * next character to be returned. */ #define DODOL 1 #define DOEXCL 2 #define DOALL DODOL|DOEXCL /* * Labuf implements a general buffer for lookahead during lexical operations. * Text which is to be placed in the input stream can be stuck here. * We stick parsed ahead $ constructs during initial input, * process id's from `$$', and modified variable values (from qualifiers * during expansion in sh.dol.c) here. */ char labuf[BUFSIZ]; char *lap; /* * Parser structure * * Each command is parsed to a tree of command structures and * flags are set bottom up during this process, to be propagated down * as needed during the semantics/exeuction pass (sh.sem.c). */ struct command { short t_dtyp; /* Type of node */ short t_dflg; /* Flags, e.g. FAND|... */ union { char *T_dlef; /* Input redirect word */ struct command *T_dcar; /* Left part of list/pipe */ } L; union { char *T_drit; /* Output redirect word */ struct command *T_dcdr; /* Right part of list/pipe */ } R; #define t_dlef L.T_dlef #define t_dcar L.T_dcar #define t_drit R.T_drit #define t_dcdr R.T_dcdr char **t_dcom; /* Command/argument vector */ struct command *t_dspr; /* Pointer to ()'d subtree */ short t_nice; }; #define TCOM 1 /* t_dcom t_drit */ #define TPAR 2 /* ( t_dspr ) t_drit */ #define TFIL 3 /* t_dlef | t_drit */ #define TLST 4 /* t_dlef ; t_drit */ #define TOR 5 /* t_dlef || t_drit */ #define TAND 6 /* t_dlef && t_drit */ #define FSAVE (FNICE|FTIME|FNOHUP) /* save these when re-doing */ #define FAND (1<<0) /* executes in background */ #define FCAT (1<<1) /* output is redirected >> */ #define FPIN (1<<2) /* input is a pipe */ #define FPOU (1<<3) /* output is a pipe */ #define FPAR (1<<4) /* don't fork, last ()ized cmd */ #define FINT (1<<5) /* should be immune from intr's */ /* spare */ #define FDIAG (1<<7) /* redirect unit 2 with unit 1 */ #define FANY (1<<8) /* output was ! */ #define FHERE (1<<9) /* input redirection is << */ #define FREDO (1<<10) /* reexec aft if, repeat,... */ #define FNICE (1<<11) /* t_nice is meaningful */ #define FNOHUP (1<<12) /* nohup this command */ #define FTIME (1<<13) /* time this command */ /* * The keywords for the parser */ #define ZBREAK 0 #define ZBRKSW 1 #define ZCASE 2 #define ZDEFAULT 3 #define ZELSE 4 #define ZEND 5 #define ZENDIF 6 #define ZENDSW 7 #define ZEXIT 8 #define ZFOREACH 9 #define ZGOTO 10 #define ZIF 11 #define ZLABEL 12 #define ZLET 13 #define ZSET 14 #define ZSWITCH 15 #define ZTEST 16 #define ZTHEN 17 #define ZWHILE 18 /* * Structure defining the existing while/foreach loops at this * source level. Loops are implemented by seeking back in the * input. For foreach (fe), the word list is attached here. */ struct whyle { off_t w_start; /* Point to restart loop */ off_t w_end; /* End of loop (0 if unknown) */ char **w_fe, **w_fe0; /* Current/initial wordlist for fe */ char *w_fename; /* Name for fe */ struct whyle *w_next; /* Next (more outer) loop */ } *whyles; /* * Variable structure * * Aliases and variables are stored in AVL balanced binary trees. */ struct varent { char **vec; /* Array of words which is the value */ char *v_name; /* Name of variable/alias */ struct varent *v_link[3]; /* The links, see below */ int v_bal; /* Balance factor */ } shvhed, aliases; #define v_left v_link[0] #define v_right v_link[1] #define v_parent v_link[2] struct varent *adrof1(); #define adrof(v) adrof1(v, &shvhed) #define value(v) value1(v, &shvhed) /* * The following are for interfacing redo substitution in * aliases to the lexical routines. */ struct wordent *alhistp; /* Argument list (first) */ struct wordent *alhistt; /* Node after last in arg list */ char **alvec; /* The (remnants of) alias vector */ /* * Filename/command name expansion variables */ short gflag; /* After tglob -> is globbing needed? */ /* * A reasonable limit on number of arguments would seem to be * the maximum number of characters in an arg list / 6. */ #ifdef pdp11 #define GAVSIZ NCARGS / 12 #else #define GAVSIZ NCARGS / 6 #endif /* * Variables for filename expansion */ char **gargv; /* Pointer to the (stack) arglist */ short gargc; /* Number args in gargv */ short gnleft; /* * Variables for command expansion. */ char **pargv; /* Pointer to the argv list space */ char *pargs; /* Pointer to start current word */ short pargc; /* Count of arguments in pargv */ short pnleft; /* Number of chars left in pargs */ char *pargcp; /* Current index into pargs */ /* * History list * * Each history list entry contains an embedded wordlist * from the scanner, a number for the event, and a reference count * to aid in discarding old entries. * * Essentially "invisible" entries are put on the history list * when history substitution includes modifiers, and thrown away * at the next discarding since their event numbers are very negative. */ struct Hist { struct wordent Hlex; int Hnum; int Href; struct Hist *Hnext; } Histlist; struct wordent paraml; /* Current lexical word list */ int eventno; /* Next events number */ int lastev; /* Last event reference (default) */ char HIST; /* history invocation character */ char HISTSUB; /* auto-substitute character */ /* * In lines for frequently called functions */ #define XFREE(cp) { \ extern char end[]; \ char stack; \ if ((cp) >= end && (cp) < &stack) \ free(cp); \ } char *alloctmp; #define xalloc(i) ((alloctmp = malloc(i)) ? alloctmp : (char *)nomem(i)) char *Dfix1(); char **blkcat(); char **blkcpy(); char **blkend(); char **blkspl(); char *calloc(); char *malloc(); char *cname(); char **copyblk(); char **dobackp(); char *domod(); struct wordent *dosub(); char *exp3(); char *exp3a(); char *exp4(); char *exp5(); char *exp6(); struct Hist *enthist(); struct Hist *findev(); struct wordent *freenod(); char *getenv(); char *getinx(); struct varent *getvx(); struct passwd *getpwnam(); struct wordent *gethent(); struct wordent *getsub(); char *getwd(); char **glob(); char *globone(); char *index(); struct biltins *isbfunc(); off_t lseek(); char *operate(); int phup(); int pintr(); int pchild(); char *putn(); char *rindex(); char **saveblk(); char *savestr(); char *strcat(); char *strcpy(); char *strend(); char *strings(); char *strip(); char *strspl(); char *subword(); struct command *syntax(); struct command *syn0(); struct command *syn1(); struct command *syn1a(); struct command *syn1b(); struct command *syn2(); struct command *syn3(); char *value1(); char *xhome(); char *xname(); char *xset(); #define NOSTR ((char *) 0) /* * setname is a macro to save space (see sh.err.c) */ char *bname; #define setname(a) (bname = (a)) #ifdef VFORK char *Vsav; char **Vav; char *Vdp; #endif char **evalvec; char *evalp; struct mesg { char *iname; /* name from /usr/include */ char *pname; /* print name */ } mesg[]; mselves * processing `!' and `$' expansion or after chbin/csh/sh.file.c 444 0 12 31104 5057640052 7071 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.file.c 5.6 (Berkeley) 5/18/86"; #endif #ifdef FILEC /* * Tenex style file name recognition, .. and more. * History: * Author: Ken Greer, Sept. 1975, CMU. * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981. */ #include "sh.h" #include #include #include #define TRUE 1 #define FALSE 0 #define ON 1 #define OFF 0 #define ESC '\033' typedef enum {LIST, RECOGNIZE} COMMAND; int sortscmp(); /* defined in sh.glob.c */ /* * Put this here so the binary can be patched with adb to enable file * completion by default. Filec controls completion, nobeep controls * ringing the terminal bell on incomplete expansions. */ bool filec = 0; static setup_tty(on) int on; { struct sgttyb sgtty; static struct tchars tchars; /* INT, QUIT, XON, XOFF, EOF, BRK */ if (on) { (void) ioctl(SHIN, TIOCGETC, (char *)&tchars); tchars.t_brkc = ESC; (void) ioctl(SHIN, TIOCSETC, (char *)&tchars); /* * This must be done after every command: if * the tty gets into raw or cbreak mode the user * can't even type 'reset'. */ (void) ioctl(SHIN, TIOCGETP, (char *)&sgtty); if (sgtty.sg_flags & (RAW|CBREAK)) { sgtty.sg_flags &= ~(RAW|CBREAK); (void) ioctl(SHIN, TIOCSETP, (char *)&sgtty); } } else { tchars.t_brkc = -1; (void) ioctl(SHIN, TIOCSETC, (char *)&tchars); } } /* * Move back to beginning of current line */ static back_to_col_1() { struct sgttyb tty, tty_normal; long omask; omask = sigblock(sigmask(SIGINT)); (void) ioctl(SHIN, TIOCGETP, (char *)&tty); tty_normal = tty; tty.sg_flags &= ~CRMOD; (void) ioctl(SHIN, TIOCSETN, (char *)&tty); (void) write(SHOUT, "\r", 1); (void) ioctl(SHIN, TIOCSETN, (char *)&tty_normal); (void) sigsetmask(omask); } /* * Push string contents back into tty queue */ static pushback(string) char *string; { register char *p; struct sgttyb tty, tty_normal; long omask; omask = sigblock(sigmask(SIGINT)); (void) ioctl(SHOUT, TIOCGETP, (char *)&tty); tty_normal = tty; tty.sg_flags &= ~ECHO; (void) ioctl(SHOUT, TIOCSETN, (char *)&tty); for (p = string; *p; p++) (void) ioctl(SHOUT, TIOCSTI, p); (void) ioctl(SHOUT, TIOCSETN, (char *)&tty_normal); (void) sigsetmask(omask); } /* * Concatenate src onto tail of des. * Des is a string whose maximum length is count. * Always null terminate. */ static catn(des, src, count) register char *des, *src; register count; { while (--count >= 0 && *des) des++; while (--count >= 0) if ((*des++ = *src++) == 0) return; *des = '\0'; } /* * Like strncpy but always leave room for trailing \0 * and always null terminate. */ static copyn(des, src, count) register char *des, *src; register count; { while (--count >= 0) if ((*des++ = *src++) == 0) return; *des = '\0'; } static char filetype(dir, file) char *dir, *file; { char path[MAXPATHLEN]; struct stat statb; catn(strcpy(path, dir), file, sizeof path); if (lstat(path, &statb) == 0) { switch(statb.st_mode & S_IFMT) { case S_IFDIR: return ('/'); case S_IFLNK: if (stat(path, &statb) == 0 && /* follow it out */ (statb.st_mode & S_IFMT) == S_IFDIR) return ('>'); else return ('@'); case S_IFSOCK: return ('='); default: if (statb.st_mode & 0111) return ('*'); } } return (' '); } static struct winsize win; /* * Print sorted down columns */ static print_by_column(dir, items, count) char *dir, *items[]; { register int i, rows, r, c, maxwidth = 0, columns; if (ioctl(SHOUT, TIOCGWINSZ, (char *)&win) < 0 || win.ws_col == 0) win.ws_col = 80; for (i = 0; i < count; i++) maxwidth = maxwidth > (r = strlen(items[i])) ? maxwidth : r; maxwidth += 2; /* for the file tag and space */ columns = win.ws_col / maxwidth; if (columns == 0) columns = 1; rows = (count + (columns - 1)) / columns; for (r = 0; r < rows; r++) { for (c = 0; c < columns; c++) { i = c * rows + r; if (i < count) { register int w; printf("%s", items[i]); putchar(dir ? filetype(dir, items[i]) : ' '); if (c < columns - 1) { /* last column? */ w = strlen(items[i]) + 1; for (; w < maxwidth; w++) putchar(' '); } } } putchar('\n'); } } /* * Expand file name with possible tilde usage * ~person/mumble * expands to * home_directory_of_person/mumble */ static char * tilde(new, old) char *new, *old; { register char *o, *p; register struct passwd *pw; static char person[40]; if (old[0] != '~') return (strcpy(new, old)); for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++) ; *p = '\0'; if (person[0] == '\0') (void) strcpy(new, value("home")); else { pw = getpwnam(person); if (pw == NULL) return (NULL); (void) strcpy(new, pw->pw_dir); } (void) strcat(new, o); return (new); } /* * Cause pending line to be printed */ static retype() { int pending_input = LPENDIN; (void) ioctl(SHOUT, TIOCLBIS, (char *)&pending_input); } static beep() { if (adrof("nobeep") == 0) (void) write(SHOUT, "\007", 1); } /* * Erase that silly ^[ and * print the recognized part of the string */ static print_recognized_stuff(recognized_part) char *recognized_part; { /* An optimized erasing of that silly ^[ */ switch (strlen(recognized_part)) { case 0: /* erase two characters: ^[ */ printf("\210\210 \210\210"); break; case 1: /* overstrike the ^, erase the [ */ printf("\210\210%s \210", recognized_part); break; default: /* overstrike both characters ^[ */ printf("\210\210%s", recognized_part); break; } flush(); } /* * Parse full path in file into 2 parts: directory and file names * Should leave final slash (/) at end of dir. */ static extract_dir_and_name(path, dir, name) char *path, *dir, *name; { register char *p; p = rindex(path, '/'); if (p == NULL) { copyn(name, path, MAXNAMLEN); dir[0] = '\0'; } else { copyn(name, ++p, MAXNAMLEN); copyn(dir, path, p - path); } } static char * getentry(dir_fd, looking_for_lognames) DIR *dir_fd; { register struct passwd *pw; register struct direct *dirp; if (looking_for_lognames) { if ((pw = getpwent()) == NULL) return (NULL); return (pw->pw_name); } if (dirp = readdir(dir_fd)) return (dirp->d_name); return (NULL); } static free_items(items) register char **items; { register int i; for (i = 0; items[i]; i++) free(items[i]); free((char *)items); } #define FREE_ITEMS(items) { \ long omask;\ \ omask = sigblock(sigmask(SIGINT));\ free_items(items);\ items = NULL;\ (void) sigsetmask(omask);\ } /* * Perform a RECOGNIZE or LIST command on string "word". */ static search(word, command, max_word_length) char *word; COMMAND command; { static char **items = NULL; register DIR *dir_fd; register numitems = 0, ignoring = TRUE, nignored = 0; register name_length, looking_for_lognames; char tilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN + 1]; char name[MAXNAMLEN + 1], extended_name[MAXNAMLEN+1]; char *entry; #define MAXITEMS 1024 if (items != NULL) FREE_ITEMS(items); looking_for_lognames = (*word == '~') && (index(word, '/') == NULL); if (looking_for_lognames) { (void) setpwent(); copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */ } else { extract_dir_and_name(word, dir, name); if (tilde(tilded_dir, dir) == 0) return (0); dir_fd = opendir(*tilded_dir ? tilded_dir : "."); if (dir_fd == NULL) return (0); } again: /* search for matches */ name_length = strlen(name); for (numitems = 0; entry = getentry(dir_fd, looking_for_lognames); ) { if (!is_prefix(name, entry)) continue; /* Don't match . files on null prefix match */ if (name_length == 0 && entry[0] == '.' && !looking_for_lognames) continue; if (command == LIST) { if (numitems >= MAXITEMS) { printf ("\nYikes!! Too many %s!!\n", looking_for_lognames ? "names in password file":"files"); break; } if (items == NULL) items = (char **) calloc(sizeof (items[1]), MAXITEMS); items[numitems] = xalloc((unsigned)strlen(entry) + 1); copyn(items[numitems], entry, MAXNAMLEN); numitems++; } else { /* RECOGNIZE command */ if (ignoring && ignored(entry)) nignored++; else if (recognize(extended_name, entry, name_length, ++numitems)) break; } } if (ignoring && numitems == 0 && nignored > 0) { ignoring = FALSE; nignored = 0; if (looking_for_lognames) (void) setpwent(); else rewinddir(dir_fd); goto again; } if (looking_for_lognames) (void) endpwent(); else closedir(dir_fd); if (numitems == 0) return (0); if (command == RECOGNIZE) { if (looking_for_lognames) copyn(word, "~", 1); else /* put back dir part */ copyn(word, dir, max_word_length); /* add extended name */ catn(word, extended_name, max_word_length); return (numitems); } else { /* LIST */ qsort((char *)items, numitems, sizeof(items[1]), sortscmp); print_by_column(looking_for_lognames ? NULL : tilded_dir, items, numitems); if (items != NULL) FREE_ITEMS(items); } return (0); } /* * Object: extend what user typed up to an ambiguity. * Algorithm: * On first match, copy full entry (assume it'll be the only match) * On subsequent matches, shorten extended_name to the first * character mismatch between extended_name and entry. * If we shorten it back to the prefix length, stop searching. */ static recognize(extended_name, entry, name_length, numitems) char *extended_name, *entry; { if (numitems == 1) /* 1st match */ copyn(extended_name, entry, MAXNAMLEN); else { /* 2nd & subsequent matches */ register char *x, *ent; register int len = 0; x = extended_name; for (ent = entry; *x && *x == *ent++; x++, len++) ; *x = '\0'; /* Shorten at 1st char diff */ if (len == name_length) /* Ambiguous to prefix? */ return (-1); /* So stop now and save time */ } return (0); } /* * Return true if check matches initial chars in template. * This differs from PWB imatch in that if check is null * it matches anything. */ static is_prefix(check, template) register char *check, *template; { do if (*check == 0) return (TRUE); while (*check++ == *template++); return (FALSE); } /* * Return true if the chars in template appear at the * end of check, I.e., are it's suffix. */ static is_suffix(check, template) char *check, *template; { register char *c, *t; for (c = check; *c++;) ; for (t = template; *t++;) ; for (;;) { if (t == template) return 1; if (c == check || *--t != *--c) return 0; } } tenex(inputline, inputline_size) char *inputline; int inputline_size; { register int numitems, num_read; setup_tty(ON); while ((num_read = read(SHIN, inputline, inputline_size)) > 0) { static char *delims = " '\"\t;&<>()|^%"; register char *str_end, *word_start, last_char, should_retype; register int space_left; COMMAND command; last_char = inputline[num_read - 1] & 0177; if (last_char == '\n' || num_read == inputline_size) break; command = (last_char == ESC) ? RECOGNIZE : LIST; if (command == LIST) putchar('\n'); str_end = &inputline[num_read]; if (last_char == ESC) --str_end; /* wipeout trailing cmd char */ *str_end = '\0'; /* * Find LAST occurence of a delimiter in the inputline. * The word start is one character past it. */ for (word_start = str_end; word_start > inputline; --word_start) if (index(delims, word_start[-1])) break; space_left = inputline_size - (word_start - inputline) - 1; numitems = search(word_start, command, space_left); if (command == RECOGNIZE) { /* print from str_end on */ print_recognized_stuff(str_end); if (numitems != 1) /* Beep = No match/ambiguous */ beep(); } /* * Tabs in the input line cause trouble after a pushback. * tty driver won't backspace over them because column * positions are now incorrect. This is solved by retyping * over current line. */ should_retype = FALSE; if (index(inputline, '\t')) { /* tab char in input line? */ back_to_col_1(); should_retype = TRUE; } if (command == LIST) /* Always retype after a LIST */ should_retype = TRUE; if (should_retype) printprompt(); pushback(inputline); if (should_retype) retype(); } setup_tty(OFF); return (num_read); } static ignored(entry) register char *entry; { struct varent *vp; register char **cp; if ((vp = adrof("fignore")) == NULL || (cp = vp->vec) == NULL) return (FALSE); for (; *cp != NULL; cp++) if (is_suffix(entry, *cp)) return (TRUE); return (FALSE); } #endif FILEC ing 9 digits ashp $8,$9,16(sp),$0,$17,4(sp) # as top 9 of 17 emodd ten8,$0,r5,r0,r5 cvtlp r0,$8,16(sp) # trailing 8 digits addp4 $8,16(sp),$17,4(sp) # combine leading and trailing bisb2 sign,12(sp) # and insert sign rsb fzero: clrl r0 movl $1,exp # 0.000e+00 and 0.000 rather than 0.000e-01 and .000 jbr fz1 # return 10^r2 as a double float in r0||r1 and 8 extra bits of precision in r4 # preserve r2, r5||r6 expten: movd $one,r0bin/csh/printf.c 444 0 12 1477 5057637564 7053 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)printf.c 5.2 (Berkeley) 6/6/85"; #endif /* * Hacked "printf" which prints through putchar. * DONT USE WITH STDIO! */ printf(fmt, args) char *fmt; { _doprnt(fmt, &args, 0); } _strout(count, string, adjust, foo, fillch) register char *string; register int count; int adjust; register struct { int a[6]; } *foo; { if (foo != 0) abort(); while (adjust < 0) { if (*string=='-' && fillch=='0') { putchar(*string++); count--; } putchar(fillch); adjust++; } while (--count>=0) putchar(*string++); while (adjust) { putchar(fillch); adjust--; } } f" which prints through putchar. * DONT USE WITH STDIO! */ printf(fmt, args) char *fmt; { _doprnt(fmt, &args, 0); } _strout(count, string, adjust, foo, fillch) register char *string; registbin/csh/sh.dir.h 444 0 12 1042 4013203115 6675 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sh.dir.h 5.2 (Berkeley) 6/6/85 */ /* * Structure for entries in directory stack. */ struct directory { struct directory *di_next; /* next in loop */ struct directory *di_prev; /* prev in loop */ unsigned short *di_count; /* refcount of processes */ char *di_name; /* actual name */ }; struct directory *dcwd; /* the one we are in now */ r *new, *old; { register char *o, *p; registþƒ struct passwd *pw; static char person[40]; if (old[0] != '~') return (strcpy(new, old)); for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++) ; *p = '\0'; if (person[0] == '\0') (void) strcpy(new, value("home")); else { pw = getpwnam(person); if (pw == NULL) return (NULL); (void) strcpy(new, pw->pw_dir); } (void) strcat(new, o); return (new); } /* * Cause pending line to be printed */ statibin/csh/sh.err.c 444 0 12 5725 5057637753 6752 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.err.c 5.3 (Berkeley) 5/13/86"; #endif #include "sh.h" #include /* * C Shell */ bool errspl; /* Argument to error was spliced by seterr2 */ char one[2] = { '1', 0 }; char *onev[2] = { one, NOSTR }; /* * Print error string s with optional argument arg. * This routine always resets or exits. The flag haderr * is set so the routine who catches the unwind can propogate * it if they want. * * Note that any open files at the point of error will eventually * be closed in the routine process in sh.c which is the only * place error unwinds are ever caught. */ /*VARARGS1*/ error(s, arg) char *s; { register char **v; register char *ep; /* * Must flush before we print as we wish output before the error * to go on (some form of) standard output, while output after * goes on (some form of) diagnostic output. * If didfds then output will go to 1/2 else to FSHOUT/FSHDIAG. * See flush in sh.print.c. */ flush(); haderr = 1; /* Now to diagnostic output */ timflg = 0; /* This isn't otherwise reset */ if (v = pargv) pargv = 0, blkfree(v); if (v = gargv) gargv = 0, blkfree(v); /* * A zero arguments causes no printing, else print * an error diagnostic here. */ if (s) printf(s, arg), printf(".\n"); didfds = 0; /* Forget about 0,1,2 */ if ((ep = err) && errspl) { errspl = 0; xfree(ep); } errspl = 0; /* * Go away if -e or we are a child shell */ if (exiterr || child) exit(1); /* * Reset the state of the input. * This buffered seek to end of file will also * clear the while/foreach stack. */ btoeof(); setq("status", onev, &shvhed); if (tpgrp > 0) (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp); reset(); /* Unwind */ } /* * Perror is the shells version of perror which should otherwise * never be called. */ Perror(s) char *s; { /* * Perror uses unit 2, thus if we didn't set up the fd's * we must set up unit 2 now else the diagnostic will disappear */ if (!didfds) { register int oerrno = errno; (void) dcopy(SHDIAG, 2); errno = oerrno; } perror(s); error(NOSTR); /* To exit or unwind */ } bferr(cp) char *cp; { flush(); haderr = 1; printf("%s: ", bname); error(cp); } /* * The parser and scanner set up errors for later by calling seterr, * which sets the variable err as a side effect; later to be tested, * e.g. in process. */ seterr(s) char *s; { if (err == 0) err = s, errspl = 0; } /* Set err to a splice of cp and dp, to be freed later in error() */ seterr2(cp, dp) char *cp, *dp; { if (err) return; err = strspl(cp, dp); errspl++; } /* Set err to a splice of cp with a string form of character d */ seterrc(cp, d) char *cp, d; { char chbuf[2]; chbuf[0] = d; chbuf[1] = 0; seterr2(cp, chbuf); } ilded_dir[MAXPATHLEN + 1], dir[MAXPATHLEN +bin/csh/sh.exp.c 444 0 12 22705 5057640026 6756 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.exp.c 5.3 (Berkeley) 6/23/85"; #endif #include "sh.h" /* * C shell */ #define IGNORE 1 /* in ignore, it means to ignore value, just parse */ #define NOGLOB 2 /* in ignore, it means not to globone */ #define ADDOP 1 #define MULOP 2 #define EQOP 4 #define RELOP 8 #define RESTOP 16 #define ANYOP 31 #define EQEQ 1 #define GTR 2 #define LSS 4 #define NOTEQ 6 #define EQMATCH 7 #define NOTEQMATCH 8 exp(vp) register char ***vp; { return (exp0(vp, 0)); } exp0(vp, ignore) register char ***vp; bool ignore; { register int p1 = exp1(vp, ignore); #ifdef EDEBUG etraci("exp0 p1", p1, vp); #endif if (**vp && eq(**vp, "||")) { register int p2; (*vp)++; p2 = exp0(vp, (ignore&IGNORE) || p1); #ifdef EDEBUG etraci("exp0 p2", p2, vp); #endif return (p1 || p2); } return (p1); } exp1(vp, ignore) register char ***vp; { register int p1 = exp2(vp, ignore); #ifdef EDEBUG etraci("exp1 p1", p1, vp); #endif if (**vp && eq(**vp, "&&")) { register int p2; (*vp)++; p2 = exp1(vp, (ignore&IGNORE) || !p1); #ifdef EDEBUG etraci("exp1 p2", p2, vp); #endif return (p1 && p2); } return (p1); } exp2(vp, ignore) register char ***vp; bool ignore; { register int p1 = exp2a(vp, ignore); #ifdef EDEBUG etraci("exp3 p1", p1, vp); #endif if (**vp && eq(**vp, "|")) { register int p2; (*vp)++; p2 = exp2(vp, ignore); #ifdef EDEBUG etraci("exp3 p2", p2, vp); #endif return (p1 | p2); } return (p1); } exp2a(vp, ignore) register char ***vp; bool ignore; { register int p1 = exp2b(vp, ignore); #ifdef EDEBUG etraci("exp2a p1", p1, vp); #endif if (**vp && eq(**vp, "^")) { register int p2; (*vp)++; p2 = exp2a(vp, ignore); #ifdef EDEBUG etraci("exp2a p2", p2, vp); #endif return (p1 ^ p2); } return (p1); } exp2b(vp, ignore) register char ***vp; bool ignore; { register int p1 = exp2c(vp, ignore); #ifdef EDEBUG etraci("exp2b p1", p1, vp); #endif if (**vp && eq(**vp, "&")) { register int p2; (*vp)++; p2 = exp2b(vp, ignore); #ifdef EDEBUG etraci("exp2b p2", p2, vp); #endif return (p1 & p2); } return (p1); } exp2c(vp, ignore) register char ***vp; bool ignore; { register char *p1 = exp3(vp, ignore); register char *p2; register int i; #ifdef EDEBUG etracc("exp2c p1", p1, vp); #endif if (i = isa(**vp, EQOP)) { (*vp)++; if (i == EQMATCH || i == NOTEQMATCH) ignore |= NOGLOB; p2 = exp3(vp, ignore); #ifdef EDEBUG etracc("exp2c p2", p2, vp); #endif if (!(ignore&IGNORE)) switch (i) { case EQEQ: i = eq(p1, p2); break; case NOTEQ: i = !eq(p1, p2); break; case EQMATCH: i = Gmatch(p1, p2); break; case NOTEQMATCH: i = !Gmatch(p1, p2); break; } xfree(p1), xfree(p2); return (i); } i = egetn(p1); xfree(p1); return (i); } char * exp3(vp, ignore) register char ***vp; bool ignore; { register char *p1, *p2; register int i; p1 = exp3a(vp, ignore); #ifdef EDEBUG etracc("exp3 p1", p1, vp); #endif if (i = isa(**vp, RELOP)) { (*vp)++; if (**vp && eq(**vp, "=")) i |= 1, (*vp)++; p2 = exp3(vp, ignore); #ifdef EDEBUG etracc("exp3 p2", p2, vp); #endif if (!(ignore&IGNORE)) switch (i) { case GTR: i = egetn(p1) > egetn(p2); break; case GTR|1: i = egetn(p1) >= egetn(p2); break; case LSS: i = egetn(p1) < egetn(p2); break; case LSS|1: i = egetn(p1) <= egetn(p2); break; } xfree(p1), xfree(p2); return (putn(i)); } return (p1); } char * exp3a(vp, ignore) register char ***vp; bool ignore; { register char *p1, *p2, *op; register int i; p1 = exp4(vp, ignore); #ifdef EDEBUG etracc("exp3a p1", p1, vp); #endif op = **vp; if (op && any(op[0], "<>") && op[0] == op[1]) { (*vp)++; p2 = exp3a(vp, ignore); #ifdef EDEBUG etracc("exp3a p2", p2, vp); #endif if (op[0] == '<') i = egetn(p1) << egetn(p2); else i = egetn(p1) >> egetn(p2); xfree(p1), xfree(p2); return (putn(i)); } return (p1); } char * exp4(vp, ignore) register char ***vp; bool ignore; { register char *p1, *p2; register int i = 0; p1 = exp5(vp, ignore); #ifdef EDEBUG etracc("exp4 p1", p1, vp); #endif if (isa(**vp, ADDOP)) { register char *op = *(*vp)++; p2 = exp4(vp, ignore); #ifdef EDEBUG etracc("exp4 p2", p2, vp); #endif if (!(ignore&IGNORE)) switch (op[0]) { case '+': i = egetn(p1) + egetn(p2); break; case '-': i = egetn(p1) - egetn(p2); break; } xfree(p1), xfree(p2); return (putn(i)); } return (p1); } char * exp5(vp, ignore) register char ***vp; bool ignore; { register char *p1, *p2; register int i = 0; p1 = exp6(vp, ignore); #ifdef EDEBUG etracc("exp5 p1", p1, vp); #endif if (isa(**vp, MULOP)) { register char *op = *(*vp)++; p2 = exp5(vp, ignore); #ifdef EDEBUG etracc("exp5 p2", p2, vp); #endif if (!(ignore&IGNORE)) switch (op[0]) { case '*': i = egetn(p1) * egetn(p2); break; case '/': i = egetn(p2); if (i == 0) error("Divide by 0"); i = egetn(p1) / i; break; case '%': i = egetn(p2); if (i == 0) error("Mod by 0"); i = egetn(p1) % i; break; } xfree(p1), xfree(p2); return (putn(i)); } return (p1); } char * exp6(vp, ignore) register char ***vp; { int ccode, i; register char *cp, *dp, *ep; if (**vp == 0) bferr("Expression syntax"); if (eq(**vp, "!")) { (*vp)++; cp = exp6(vp, ignore); #ifdef EDEBUG etracc("exp6 ! cp", cp, vp); #endif i = egetn(cp); xfree(cp); return (putn(!i)); } if (eq(**vp, "~")) { (*vp)++; cp = exp6(vp, ignore); #ifdef EDEBUG etracc("exp6 ~ cp", cp, vp); #endif i = egetn(cp); xfree(cp); return (putn(~i)); } if (eq(**vp, "(")) { (*vp)++; ccode = exp0(vp, ignore); #ifdef EDEBUG etraci("exp6 () ccode", ccode, vp); #endif if (*vp == 0 || **vp == 0 || ***vp != ')') bferr("Expression syntax"); (*vp)++; return (putn(ccode)); } if (eq(**vp, "{")) { register char **v; struct command faket; char *fakecom[2]; faket.t_dtyp = TCOM; faket.t_dflg = 0; faket.t_dcar = faket.t_dcdr = faket.t_dspr = (struct command *)0; faket.t_dcom = fakecom; fakecom[0] = "{ ... }"; fakecom[1] = NOSTR; (*vp)++; v = *vp; for (;;) { if (!**vp) bferr("Missing }"); if (eq(*(*vp)++, "}")) break; } if (ignore&IGNORE) return (""); psavejob(); if (pfork(&faket, -1) == 0) { *--(*vp) = 0; evalav(v); exitstat(); } pwait(); prestjob(); #ifdef EDEBUG etraci("exp6 {} status", egetn(value("status")), vp); #endif return (putn(egetn(value("status")) == 0)); } if (isa(**vp, ANYOP)) return (""); cp = *(*vp)++; if (*cp == '-' && any(cp[1], "erwxfdzo")) { struct stat stb; if (isa(**vp, ANYOP)) bferr("Missing file name"); dp = *(*vp)++; if (ignore&IGNORE) return (""); ep = globone(dp); switch (cp[1]) { case 'r': i = !access(ep, 4); break; case 'w': i = !access(ep, 2); break; case 'x': i = !access(ep, 1); break; default: if (stat(ep, &stb)) { xfree(ep); return ("0"); } switch (cp[1]) { case 'f': i = (stb.st_mode & S_IFMT) == S_IFREG; break; case 'd': i = (stb.st_mode & S_IFMT) == S_IFDIR; break; case 'z': i = stb.st_size == 0; break; case 'e': i = 1; break; case 'o': i = stb.st_uid == uid; break; } } #ifdef EDEBUG etraci("exp6 -? i", i, vp); #endif xfree(ep); return (putn(i)); } #ifdef EDEBUG etracc("exp6 default", cp, vp); #endif return (ignore&NOGLOB ? savestr(cp) : globone(cp)); } evalav(v) register char **v; { struct wordent paraml; register struct wordent *hp = ¶ml; struct command *t; register struct wordent *wdp = hp; set("status", "0"); hp->prev = hp->next = hp; hp->word = ""; while (*v) { register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp); new->prev = wdp; new->next = hp; wdp->next = new; wdp = new; wdp->word = savestr(*v++); } hp->prev = wdp; alias(¶ml); t = syntax(paraml.next, ¶ml, 0); if (err) error(err); execute(t, -1); freelex(¶ml), freesyn(t); } isa(cp, what) register char *cp; register int what; { if (cp == 0) return ((what & RESTOP) != 0); if (cp[1] == 0) { if (what & ADDOP && (*cp == '+' || *cp == '-')) return (1); if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%')) return (1); if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' || *cp == '~' || *cp == '^' || *cp == '"')) return (1); } else if (cp[2] == 0) { if (what & RESTOP) { if (cp[0] == '|' && cp[1] == '&') return (1); if (cp[0] == '<' && cp[1] == '<') return (1); if (cp[0] == '>' && cp[1] == '>') return (1); } if (what & EQOP) { if (cp[0] == '=') { if (cp[1] == '=') return (EQEQ); if (cp[1] == '~') return (EQMATCH); } else if (cp[0] == '!') { if (cp[1] == '=') return (NOTEQ); if (cp[1] == '~') return (NOTEQMATCH); } } } if (what & RELOP) { if (*cp == '<') return (LSS); if (*cp == '>') return (GTR); } return (0); } egetn(cp) register char *cp; { if (*cp && *cp != '-' && !digit(*cp)) bferr("Expression syntax"); return (getn(cp)); } /* Phew! */ #ifdef EDEBUG etraci(str, i, vp) char *str; int i; char ***vp; { printf("%s=%d\t", str, i); blkpr(*vp); printf("\n"); } etracc(str, cp, vp) char *str, *cp; char ***vp; { printf("%s=%s\t", str, cp); blkpr(*vp); printf("\n"); } #endif nize(extended_name, entry, name_length, numitems) char *exbin/csh/sh.init.c 444 0 12 12073 5057640232 7121 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.init.c 5.2 (Berkeley) 6/6/85"; #endif #include "sh.local.h" /* * C shell */ extern int doalias(); extern int dobg(); extern int dobreak(); extern int dochngd(); extern int docontin(); extern int dodirs(); extern int doecho(); extern int doelse(); extern int doend(); extern int doendif(); extern int doendsw(); extern int doeval(); extern int doexit(); extern int dofg(); extern int doforeach(); extern int doglob(); extern int dogoto(); extern int dohash(); extern int dohist(); extern int doif(); extern int dojobs(); extern int dokill(); extern int dolet(); #ifndef NOLIMITS extern int dolimit(); #endif extern int dologin(); extern int dologout(); #ifdef NEWGRP extern int donewgrp(); #endif extern int donice(); extern int donotify(); extern int donohup(); extern int doonintr(); extern int dopopd(); extern int dopushd(); extern int dorepeat(); extern int doset(); extern int dosetenv(); extern int dosource(); extern int dostop(); extern int dosuspend(); extern int doswbrk(); extern int doswitch(); extern int dotime(); #ifndef NOLIMITS extern int dounlimit(); #endif extern int doumask(); extern int dowait(); extern int dowhile(); extern int dozip(); extern int execash(); extern int goodbye(); #ifdef VFORK extern int hashstat(); #endif extern int shift(); extern int showall(); extern int unalias(); extern int dounhash(); extern int unset(); extern int dounsetenv(); #define INF 1000 struct biltins { char *bname; int (*bfunct)(); short minargs, maxargs; } bfunc[] = { "@", dolet, 0, INF, "alias", doalias, 0, INF, "alloc", showall, 0, 1, "bg", dobg, 0, INF, "break", dobreak, 0, 0, "breaksw", doswbrk, 0, 0, #ifdef IIASA "bye", goodbye, 0, 0, #endif "case", dozip, 0, 1, "cd", dochngd, 0, 1, "chdir", dochngd, 0, 1, "continue", docontin, 0, 0, "default", dozip, 0, 0, "dirs", dodirs, 0, 1, "echo", doecho, 0, INF, "else", doelse, 0, INF, "end", doend, 0, 0, "endif", dozip, 0, 0, "endsw", dozip, 0, 0, "eval", doeval, 0, INF, "exec", execash, 1, INF, "exit", doexit, 0, INF, "fg", dofg, 0, INF, "foreach", doforeach, 3, INF, #ifdef IIASA "gd", dopushd, 0, 1, #endif "glob", doglob, 0, INF, "goto", dogoto, 1, 1, #ifdef VFORK "hashstat", hashstat, 0, 0, #endif "history", dohist, 0, 2, "if", doif, 1, INF, "jobs", dojobs, 0, 1, "kill", dokill, 1, INF, #ifndef NOLIMITS "limit", dolimit, 0, 3, #endif "login", dologin, 0, 1, "logout", dologout, 0, 0, #ifdef NEWGRP "newgrp", donewgrp, 1, 1, #endif "nice", donice, 0, INF, "nohup", donohup, 0, INF, "notify", donotify, 0, INF, "onintr", doonintr, 0, 2, "popd", dopopd, 0, 1, "pushd", dopushd, 0, 1, #ifdef IIASA "rd", dopopd, 0, 1, #endif "rehash", dohash, 0, 0, "repeat", dorepeat, 2, INF, "set", doset, 0, INF, "setenv", dosetenv, 0, 2, "shift", shift, 0, 1, "source", dosource, 1, 2, "stop", dostop, 1, INF, "suspend", dosuspend, 0, 0, "switch", doswitch, 1, INF, "time", dotime, 0, INF, "umask", doumask, 0, 1, "unalias", unalias, 1, INF, "unhash", dounhash, 0, 0, #ifndef NOLIMITS "unlimit", dounlimit, 0, INF, #endif "unset", unset, 1, INF, "unsetenv", dounsetenv, 1, INF, "wait", dowait, 0, 0, "while", dowhile, 1, INF, }; int nbfunc = sizeof bfunc / sizeof *bfunc; #define ZBREAK 0 #define ZBRKSW 1 #define ZCASE 2 #define ZDEFAULT 3 #define ZELSE 4 #define ZEND 5 #define ZENDIF 6 #define ZENDSW 7 #define ZEXIT 8 #define ZFOREACH 9 #define ZGOTO 10 #define ZIF 11 #define ZLABEL 12 #define ZLET 13 #define ZSET 14 #define ZSWITCH 15 #define ZTEST 16 #define ZTHEN 17 #define ZWHILE 18 struct srch { char *s_name; short s_value; } srchn[] = { "@", ZLET, "break", ZBREAK, "breaksw", ZBRKSW, "case", ZCASE, "default", ZDEFAULT, "else", ZELSE, "end", ZEND, "endif", ZENDIF, "endsw", ZENDSW, "exit", ZEXIT, "foreach", ZFOREACH, "goto", ZGOTO, "if", ZIF, "label", ZLABEL, "set", ZSET, "switch", ZSWITCH, "while", ZWHILE, }; int nsrchn = sizeof srchn / sizeof *srchn; struct mesg { char *iname; char *pname; } mesg[] = { 0, 0, "HUP", "Hangup", "INT", "Interrupt", "QUIT", "Quit", "ILL", "Illegal instruction", "TRAP", "Trace/BPT trap", "IOT", "IOT trap", "EMT", "EMT trap", "FPE", "Floating exception", "KILL", "Killed", "BUS", "Bus error", "SEGV", "Segmentation fault", "SYS", "Bad system call", "PIPE", "Broken pipe", "ALRM", "Alarm clock", "TERM", "Terminated", "URG", "Urgent I/O condition", "STOP", "Stopped (signal)", "TSTP", "Stopped", "CONT", "Continued", "CHLD", "Child exited", "TTIN", "Stopped (tty input)", "TTOU", "Stopped (tty output)", "IO", "I/O possible", "XCPU", "Cputime limit exceeded", "XFSZ", "Filesize limit exceeded", "VTALRM","Virtual timer expired", "PROF", "Profiling timer expired", "WINCH","Window size changed", 0, "Signal 29", "USR1", "User defined signal 1", "USR2", "User defined signal 2", 0, "Signal 32" }; dopushd(); extern int dorepeat(); extern int doset(); extern int dosetenv(); extern int dosource(); extern int dostop(); extern int dosuspend(); extern int doswbrk(); extern int doswitch(); extern int dotime(); #ifndef NOLIMITS extern int dounlimit(); #endif extern int doumask(); extern int dowait(); extern int dowhile(); extern int dozip(); extern int execash(); extern int goodbye(); #ifdef VFORK extern int hashstat(); #endif extern int shift(); ebin/csh/sh.proc.h 444 0 12 5737 4013203115 7101 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sh.proc.h 5.2 (Berkeley) 6/6/85 */ /* * C shell - process structure declarations */ /* * Structure for each process the shell knows about: * allocated and filled by pcreate. * flushed by pflush; freeing always happens at top level * so the interrupt level has less to worry about. * processes are related to "friends" when in a pipeline; * p_friends links makes a circular list of such jobs */ struct process { struct process *p_next; /* next in global "proclist" */ struct process *p_friends; /* next in job list (or self) */ struct directory *p_cwd; /* cwd of the job (only in head) */ short unsigned p_flags; /* various job status flags */ char p_reason; /* reason for entering this state */ char p_index; /* shorthand job index */ int p_pid; int p_jobid; /* pid of job leader */ /* if a job is stopped/background p_jobid gives its pgrp */ struct timeval p_btime; /* begin time */ struct timeval p_etime; /* end time */ struct rusage p_rusage; char *p_command; /* first PMAXLEN chars of command */ }; /* flag values for p_flags */ #define PRUNNING (1<<0) /* running */ #define PSTOPPED (1<<1) /* stopped */ #define PNEXITED (1<<2) /* normally exited */ #define PAEXITED (1<<3) /* abnormally exited */ #define PSIGNALED (1<<4) /* terminated by a signal != SIGINT */ #define PALLSTATES (PRUNNING|PSTOPPED|PNEXITED|PAEXITED|PSIGNALED|PINTERRUPTED) #define PNOTIFY (1<<5) /* notify async when done */ #define PTIME (1<<6) /* job times should be printed */ #define PAWAITED (1<<7) /* top level is waiting for it */ #define PFOREGND (1<<8) /* started in shells pgrp */ #define PDUMPED (1<<9) /* process dumped core */ #define PDIAG (1<<10) /* diagnostic output also piped out */ #define PPOU (1<<11) /* piped output */ #define PREPORTED (1<<12) /* status has been reported */ #define PINTERRUPTED (1<<13) /* job stopped via interrupt signal */ #define PPTIME (1<<14) /* time individual process */ #define PNEEDNOTE (1<<15) /* notify as soon as practical */ #define PNULL (struct process *)0 #define PMAXLEN 80 /* defines for arguments to pprint */ #define NUMBER 01 #define NAME 02 #define REASON 04 #define AMPERSAND 010 #define FANCY 020 #define SHELLDIR 040 /* print shell's dir if not the same */ #define JOBDIR 0100 /* print job's dir if not the same */ #define AREASON 0200 struct process proclist; /* list head of all processes */ bool pnoprocesses; /* pchild found nothing to wait for */ struct process *pholdjob; /* one level stack of current jobs */ struct process *pcurrjob; /* current job */ struct process *pcurrent; /* current job in table */ struct process *pprevious; /* previous job in table */ short pmaxindex; /* current maximum job index */ int psigint(); struct process *pgetcurr(); struct process *plookup(); struct process *pfind(); "setenv", dosetenv, 0, 2, "shiftbin/csh/sh.misc.c 444 0 12 11477 5057640312 7117 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.misc.c 5.3 (Berkeley) 3/29/86"; #endif #include "sh.h" /* * C Shell */ any(c, s) register int c; register char *s; { while (*s) if (*s++ == c) return(1); return(0); } onlyread(cp) char *cp; { extern char end[]; return (cp < end); } xfree(cp) char *cp; { extern char end[]; if (cp >= end && cp < (char *) &cp) free(cp); } char * savestr(s) register char *s; { char *n; register char *p; if (s == 0) s = ""; for (p = s; *p++;) ; n = p = xalloc((unsigned) (p - s)); while (*p++ = *s++) ; return (n); } char * calloc(i, j) register unsigned i; unsigned j; { char *cp; i *= j; cp = xalloc(i); bzero(cp, (int)i); return (cp); } nomem(i) unsigned i; { #ifdef debug static char *av[2] = {0, 0}; #endif child++; #ifndef debug error("Out of memory"); #ifdef lint i = i; #endif #else showall(av); printf("i=%d: Out of memory\n", i); chdir("/usr/bill/cshcore"); abort(); #endif return 0; /* fool lint */ } char ** blkend(up) register char **up; { while (*up) up++; return (up); } blkpr(av) register char **av; { for (; *av; av++) { printf("%s", *av); if (av[1]) printf(" "); } } blklen(av) register char **av; { register int i = 0; while (*av++) i++; return (i); } char ** blkcpy(oav, bv) char **oav; register char **bv; { register char **av = oav; while (*av++ = *bv++) continue; return (oav); } char ** blkcat(up, vp) char **up, **vp; { (void) blkcpy(blkend(up), vp); return (up); } blkfree(av0) char **av0; { register char **av = av0; for (; *av; av++) XFREE(*av) XFREE((char *)av0) } char ** saveblk(v) register char **v; { register char **newv = (char **) calloc((unsigned) (blklen(v) + 1), sizeof (char **)); char **onewv = newv; while (*v) *newv++ = savestr(*v++); return (onewv); } char * strspl(cp, dp) char *cp, *dp; { char *ep; register char *p, *q; for (p = cp; *p++;) ; for (q = dp; *q++;) ; ep = xalloc((unsigned) ((p - cp) + (q - dp) - 1)); for (p = ep, q = cp; *p++ = *q++;) ; for (p--, q = dp; *p++ = *q++;) ; return (ep); } char ** blkspl(up, vp) register char **up, **vp; { register char **wp = (char **) calloc((unsigned) (blklen(up) + blklen(vp) + 1), sizeof (char **)); (void) blkcpy(wp, up); return (blkcat(wp, vp)); } lastchr(cp) register char *cp; { if (!*cp) return (0); while (cp[1]) cp++; return (*cp); } /* * This routine is called after an error to close up * any units which may have been left open accidentally. */ closem() { register int f; for (f = 0; f < NOFILE; f++) if (f != SHIN && f != SHOUT && f != SHDIAG && f != OLDSTD && f != FSHTTY) (void) close(f); } donefds() { (void) close(0); (void) close(1); (void) close(2); didfds = 0; } /* * Move descriptor i to j. * If j is -1 then we just want to get i to a safe place, * i.e. to a unit > 2. This also happens in dcopy. */ dmove(i, j) register int i, j; { if (i == j || i < 0) return (i); if (j >= 0) { (void) dup2(i, j); return (j); } j = dcopy(i, j); if (j != i) (void) close(i); return (j); } dcopy(i, j) register int i, j; { if (i == j || i < 0 || j < 0 && i > 2) return (i); if (j >= 0) { (void) dup2(i, j); return (j); } (void) close(j); return (renum(i, j)); } renum(i, j) register int i, j; { register int k = dup(i); if (k < 0) return (-1); if (j == -1 && k > 2) return (k); if (k != j) { j = renum(k, j); (void) close(k); return (j); } return (k); } #ifndef copy copy(to, from, size) register char *to, *from; register int size; { if (size) do *to++ = *from++; while (--size != 0); } #endif /* * Left shift a command argument list, discarding * the first c arguments. Used in "shift" commands * as well as by commands like "repeat". */ lshift(v, c) register char **v; register int c; { register char **u = v; while (*u && --c >= 0) xfree(*u++); (void) blkcpy(v, u); } number(cp) char *cp; { if (*cp == '-') { cp++; if (!digit(*cp++)) return (0); } while (*cp && digit(*cp)) cp++; return (*cp == 0); } char ** copyblk(v) register char **v; { register char **nv = (char **) calloc((unsigned) (blklen(v) + 1), sizeof (char **)); return (blkcpy(nv, v)); } char * strend(cp) register char *cp; { while (*cp) cp++; return (cp); } char * strip(cp) char *cp; { register char *dp = cp; while (*dp++ &= TRIM) continue; return (cp); } udvar(name) char *name; { setname(name); bferr("Undefined variable"); } prefix(sub, str) register char *sub, *str; { for (;;) { if (*sub == 0) return (1); if (*str == 0) return (0); if (*sub++ != *str++) return (0); } } /* * C Shell */ any(c, s) register int c; register char *s; { while (*s) if (*s++ == c) return(1); return(0); } onlyread(cp) char *cp; { extern char end[]; return (cp < end); bin/csh/sh.parse.c 444 0 12 24267 5057640347 7307 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.parse.c 5.3 (Berkeley) 5/13/86"; #endif #include "sh.h" /* * C shell */ /* * Perform aliasing on the word list lex * Do a (very rudimentary) parse to separate into commands. * If word 0 of a command has an alias, do it. * Repeat a maximum of 20 times. */ alias(lex) register struct wordent *lex; { int aleft = 21; jmp_buf osetexit; getexit(osetexit); setexit(); if (haderr) { resexit(osetexit); reset(); } if (--aleft == 0) error("Alias loop"); asyntax(lex->next, lex); resexit(osetexit); } asyntax(p1, p2) register struct wordent *p1, *p2; { while (p1 != p2) if (any(p1->word[0], ";&\n")) p1 = p1->next; else { asyn0(p1, p2); return; } } asyn0(p1, p2) struct wordent *p1; register struct wordent *p2; { register struct wordent *p; register int l = 0; for (p = p1; p != p2; p = p->next) switch (p->word[0]) { case '(': l++; continue; case ')': l--; if (l < 0) error("Too many )'s"); continue; case '>': if (p->next != p2 && eq(p->next->word, "&")) p = p->next; continue; case '&': case '|': case ';': case '\n': if (l != 0) continue; asyn3(p1, p); asyntax(p->next, p2); return; } if (l == 0) asyn3(p1, p2); } asyn3(p1, p2) struct wordent *p1; register struct wordent *p2; { register struct varent *ap; struct wordent alout; register bool redid; if (p1 == p2) return; if (p1->word[0] == '(') { for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) if (p2 == p1) return; if (p2 == p1->next) return; asyn0(p1->next, p2); return; } ap = adrof1(p1->word, &aliases); if (ap == 0) return; alhistp = p1->prev; alhistt = p2; alvec = ap->vec; redid = lex(&alout); alhistp = alhistt = 0; alvec = 0; if (err) { freelex(&alout); error(err); } if (p1->word[0] && eq(p1->word, alout.next->word)) { char *cp = alout.next->word; alout.next->word = strspl("\200", cp); XFREE(cp) } p1 = freenod(p1, redid ? p2 : p1->next); if (alout.next != &alout) { p1->next->prev = alout.prev->prev; alout.prev->prev->next = p1->next; alout.next->prev = p1; p1->next = alout.next; XFREE(alout.prev->word) XFREE((char *)alout.prev) } reset(); /* throw! */ } struct wordent * freenod(p1, p2) register struct wordent *p1, *p2; { register struct wordent *retp = p1->prev; while (p1 != p2) { XFREE(p1->word) p1 = p1->next; XFREE((char *)p1->prev) } retp->next = p2; p2->prev = retp; return (retp); } #define PHERE 1 #define PIN 2 #define POUT 4 #define PDIAG 8 /* * syntax * empty * syn0 */ struct command * syntax(p1, p2, flags) register struct wordent *p1, *p2; int flags; { while (p1 != p2) if (any(p1->word[0], ";&\n")) p1 = p1->next; else return (syn0(p1, p2, flags)); return (0); } /* * syn0 * syn1 * syn1 & syntax */ struct command * syn0(p1, p2, flags) struct wordent *p1, *p2; int flags; { register struct wordent *p; register struct command *t, *t1; int l; l = 0; for (p = p1; p != p2; p = p->next) switch (p->word[0]) { case '(': l++; continue; case ')': l--; if (l < 0) seterr("Too many )'s"); continue; case '|': if (p->word[1] == '|') continue; /* fall into ... */ case '>': if (p->next != p2 && eq(p->next->word, "&")) p = p->next; continue; case '&': if (l != 0) break; if (p->word[1] == '&') continue; t1 = syn1(p1, p, flags); if (t1->t_dtyp == TLST || t1->t_dtyp == TAND || t1->t_dtyp == TOR) { t = (struct command *) calloc(1, sizeof (*t)); t->t_dtyp = TPAR; t->t_dflg = FAND|FINT; t->t_dspr = t1; t1 = t; } else t1->t_dflg |= FAND|FINT; t = (struct command *) calloc(1, sizeof (*t)); t->t_dtyp = TLST; t->t_dflg = 0; t->t_dcar = t1; t->t_dcdr = syntax(p, p2, flags); return(t); } if (l == 0) return (syn1(p1, p2, flags)); seterr("Too many ('s"); return (0); } /* * syn1 * syn1a * syn1a ; syntax */ struct command * syn1(p1, p2, flags) struct wordent *p1, *p2; int flags; { register struct wordent *p; register struct command *t; int l; l = 0; for (p = p1; p != p2; p = p->next) switch (p->word[0]) { case '(': l++; continue; case ')': l--; continue; case ';': case '\n': if (l != 0) break; t = (struct command *) calloc(1, sizeof (*t)); t->t_dtyp = TLST; t->t_dcar = syn1a(p1, p, flags); t->t_dcdr = syntax(p->next, p2, flags); if (t->t_dcdr == 0) t->t_dcdr = t->t_dcar, t->t_dcar = 0; return (t); } return (syn1a(p1, p2, flags)); } /* * syn1a * syn1b * syn1b || syn1a */ struct command * syn1a(p1, p2, flags) struct wordent *p1, *p2; int flags; { register struct wordent *p; register struct command *t; register int l = 0; for (p = p1; p != p2; p = p->next) switch (p->word[0]) { case '(': l++; continue; case ')': l--; continue; case '|': if (p->word[1] != '|') continue; if (l == 0) { t = (struct command *) calloc(1, sizeof (*t)); t->t_dtyp = TOR; t->t_dcar = syn1b(p1, p, flags); t->t_dcdr = syn1a(p->next, p2, flags); t->t_dflg = 0; return (t); } continue; } return (syn1b(p1, p2, flags)); } /* * syn1b * syn2 * syn2 && syn1b */ struct command * syn1b(p1, p2, flags) struct wordent *p1, *p2; int flags; { register struct wordent *p; register struct command *t; register int l = 0; l = 0; for (p = p1; p != p2; p = p->next) switch (p->word[0]) { case '(': l++; continue; case ')': l--; continue; case '&': if (p->word[1] == '&' && l == 0) { t = (struct command *) calloc(1, sizeof (*t)); t->t_dtyp = TAND; t->t_dcar = syn2(p1, p, flags); t->t_dcdr = syn1b(p->next, p2, flags); t->t_dflg = 0; return (t); } continue; } return (syn2(p1, p2, flags)); } /* * syn2 * syn3 * syn3 | syn2 * syn3 |& syn2 */ struct command * syn2(p1, p2, flags) struct wordent *p1, *p2; int flags; { register struct wordent *p, *pn; register struct command *t; register int l = 0; int f; for (p = p1; p != p2; p = p->next) switch (p->word[0]) { case '(': l++; continue; case ')': l--; continue; case '|': if (l != 0) continue; t = (struct command *) calloc(1, sizeof (*t)); f = flags | POUT; pn = p->next; if (pn != p2 && pn->word[0] == '&') { f |= PDIAG; t->t_dflg |= FDIAG; } t->t_dtyp = TFIL; t->t_dcar = syn3(p1, p, f); if (pn != p2 && pn->word[0] == '&') p = pn; t->t_dcdr = syn2(p->next, p2, flags | PIN); return (t); } return (syn3(p1, p2, flags)); } char *RELPAR = "<>()"; /* * syn3 * ( syn0 ) [ < in ] [ > out ] * word word* [ < in ] [ > out ] * KEYWORD ( word* ) word* [ < in ] [ > out ] * * KEYWORD = (@ exit foreach if set switch test while) */ struct command * syn3(p1, p2, flags) struct wordent *p1, *p2; int flags; { register struct wordent *p; struct wordent *lp, *rp; register struct command *t; register int l; char **av; int n, c; bool specp = 0; if (p1 != p2) { p = p1; again: switch (srchx(p->word)) { case ZELSE: p = p->next; if (p != p2) goto again; break; case ZEXIT: case ZFOREACH: case ZIF: case ZLET: case ZSET: case ZSWITCH: case ZWHILE: specp = 1; break; } } n = 0; l = 0; for (p = p1; p != p2; p = p->next) switch (p->word[0]) { case '(': if (specp) n++; l++; continue; case ')': if (specp) n++; l--; continue; case '>': case '<': if (l != 0) { if (specp) n++; continue; } if (p->next == p2) continue; if (any(p->next->word[0], RELPAR)) continue; n--; continue; default: if (!specp && l != 0) continue; n++; continue; } if (n < 0) n = 0; t = (struct command *) calloc(1, sizeof (*t)); av = (char **) calloc((unsigned) (n + 1), sizeof (char **)); t->t_dcom = av; n = 0; if (p2->word[0] == ')') t->t_dflg = FPAR; lp = 0; rp = 0; l = 0; for (p = p1; p != p2; p = p->next) { c = p->word[0]; switch (c) { case '(': if (l == 0) { if (lp != 0 && !specp) seterr("Badly placed ("); lp = p->next; } l++; goto savep; case ')': l--; if (l == 0) rp = p; goto savep; case '>': if (l != 0) goto savep; if (p->word[1] == '>') t->t_dflg |= FCAT; if (p->next != p2 && eq(p->next->word, "&")) { t->t_dflg |= FDIAG, p = p->next; if (flags & (POUT|PDIAG)) goto badout; } if (p->next != p2 && eq(p->next->word, "!")) t->t_dflg |= FANY, p = p->next; if (p->next == p2) { missfile: seterr("Missing name for redirect"); continue; } p = p->next; if (any(p->word[0], RELPAR)) goto missfile; if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit) badout: seterr("Ambiguous output redirect"); else t->t_drit = savestr(p->word); continue; case '<': if (l != 0) goto savep; if (p->word[1] == '<') t->t_dflg |= FHERE; if (p->next == p2) goto missfile; p = p->next; if (any(p->word[0], RELPAR)) goto missfile; if ((flags & PHERE) && (t->t_dflg & FHERE)) seterr("Can't << within ()'s"); else if ((flags & PIN) || t->t_dlef) seterr("Ambiguous input redirect"); else t->t_dlef = savestr(p->word); continue; savep: if (!specp) continue; default: if (l != 0 && !specp) continue; if (err == 0) av[n] = savestr(p->word); n++; continue; } } if (lp != 0 && !specp) { if (n != 0) seterr("Badly placed ()'s"); t->t_dtyp = TPAR; t->t_dspr = syn0(lp, rp, PHERE); } else { if (n == 0) seterr("Invalid null command"); t->t_dtyp = TCOM; } return (t); } freesyn(t) register struct command *t; { register char **v; if (t == 0) return; switch (t->t_dtyp) { case TCOM: for (v = t->t_dcom; *v; v++) XFREE(*v) XFREE((char *)t->t_dcom) goto lr; case TPAR: freesyn(t->t_dspr); /* fall into ... */ lr: XFREE(t->t_dlef) XFREE(t->t_drit) break; case TAND: case TOR: case TFIL: case TLST: freesyn(t->t_dcar), freesyn(t->t_dcdr); break; } XFREE((char *)t) } oo many )'s"); continue; case '>': if (p->next != p2 && eq(p->next->word, "&")) p = p->next; continue; case '&': case '|': case ';': case '\n': if (l != 0) continue; asyn3(p1, p); asyntax(p->next, p2); return; } if (l == 0) asyn3(p1, p2); } asyn3(p1, p2) struct wordent *p1; regisbin/csh/sh.sem.c 444 0 12 22355 5672226157 6757 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.sem.c 5.4.1 (2.11BSD GTE) 12/9/94"; #endif #include "sh.h" #include "sh.proc.h" #include #include /* * C shell */ /*VARARGS 1*/ execute(t, wanttty, pipein, pipeout) register struct command *t; int wanttty, *pipein, *pipeout; { bool forked = 0; struct biltins *bifunc; int pid = 0; int pv[2]; if (t == 0) return; if ((t->t_dflg & FAND) && wanttty > 0) wanttty = 0; switch (t->t_dtyp) { case TCOM: if ((t->t_dcom[0][0] & (QUOTE|TRIM)) == QUOTE) (void) strcpy(t->t_dcom[0], t->t_dcom[0] + 1); if ((t->t_dflg & FREDO) == 0) Dfix(t); /* $ " ' \ */ if (t->t_dcom[0] == 0) return; /* fall into... */ case TPAR: if (t->t_dflg & FPOU) mypipe(pipeout); /* * Must do << early so parent will know * where input pointer should be. * If noexec then this is all we do. */ if (t->t_dflg & FHERE) { (void) close(0); heredoc(t->t_dlef); if (noexec) (void) close(0); } if (noexec) break; set("status", "0"); /* * This mess is the necessary kludge to handle the prefix * builtins: nice, nohup, time. These commands can also * be used by themselves, and this is not handled here. * This will also work when loops are parsed. */ while (t->t_dtyp == TCOM) if (eq(t->t_dcom[0], "nice")) if (t->t_dcom[1]) if (any(t->t_dcom[1][0], "+-")) if (t->t_dcom[2]) { setname("nice"); t->t_nice = getn(t->t_dcom[1]); lshift(t->t_dcom, 2); t->t_dflg |= FNICE; } else break; else { t->t_nice = 4; lshift(t->t_dcom, 1); t->t_dflg |= FNICE; } else break; else if (eq(t->t_dcom[0], "nohup")) if (t->t_dcom[1]) { t->t_dflg |= FNOHUP; lshift(t->t_dcom, 1); } else break; else if (eq(t->t_dcom[0], "time")) if (t->t_dcom[1]) { t->t_dflg |= FTIME; lshift(t->t_dcom, 1); } else break; else break; /* * Check if we have a builtin function and remember which one. */ bifunc = t->t_dtyp == TCOM ? isbfunc(t) : (struct biltins *) 0; /* * We fork only if we are timed, or are not the end of * a parenthesized list and not a simple builtin function. * Simple meaning one that is not pipedout, niced, nohupped, * or &'d. * It would be nice(?) to not fork in some of these cases. */ if (((t->t_dflg & FTIME) || (t->t_dflg & FPAR) == 0 && (!bifunc || t->t_dflg & (FPOU|FAND|FNICE|FNOHUP)))) #ifdef VFORK if (t->t_dtyp == TPAR || t->t_dflg&(FREDO|FAND) || bifunc) #endif { forked++; pid = pfork(t, wanttty); } #ifdef VFORK else { int vffree(); int ochild, osetintr, ohaderr, odidfds; int oSHIN, oSHOUT, oSHDIAG, oOLDSTD, otpgrp; long omask; /* * Prepare for the vfork by saving everything * that the child corrupts before it exec's. * Note that in some signal implementations * which keep the signal info in user space * (e.g. Sun's) it will also be necessary to * save and restore the current sigvec's for * the signals the child touches before it * exec's. */ omask = sigblock(sigmask(SIGCHLD)); ochild = child; osetintr = setintr; ohaderr = haderr; odidfds = didfds; oSHIN = SHIN; oSHOUT = SHOUT; oSHDIAG = SHDIAG; oOLDSTD = OLDSTD; otpgrp = tpgrp; Vsav = Vdp = 0; Vav = 0; pid = vfork(); if (pid < 0) { (void) sigsetmask(omask); error("No more processes"); } forked++; if (pid) { /* parent */ register char **v; child = ochild; setintr = osetintr; haderr = ohaderr; didfds = odidfds; SHIN = oSHIN; SHOUT = oSHOUT; SHDIAG = oSHDIAG; OLDSTD = oOLDSTD; tpgrp = otpgrp; xfree(Vsav); Vsav = 0; xfree(Vdp); Vdp = 0; xfree((char *)Vav); Vav = 0; if (v = gargv) gargv = 0, blkfree(v); if (v = pargv) pargv = 0, blkfree(v); /* this is from pfork() */ palloc(pid, t); (void) sigsetmask(omask); } else { /* child */ /* this is from pfork() */ int pgrp; bool ignint = 0; if (setintr) ignint = (tpgrp == -1 && (t->t_dflg&FINT)) || gointr && eq(gointr, "-"); pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); child++; if (setintr) { setintr = 0; #ifdef notdef (void) signal(SIGCHLD, SIG_DFL); #endif (void) signal(SIGINT, ignint ? SIG_IGN : vffree); (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); if (wanttty >= 0) { (void) signal(SIGTSTP, SIG_DFL); (void) signal(SIGTTIN, SIG_DFL); (void) signal(SIGTTOU, SIG_DFL); } (void) signal(SIGTERM, parterm); } else if (tpgrp == -1 && (t->t_dflg&FINT)) { (void) signal(SIGINT, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); } if (wanttty > 0) (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&pgrp); if (wanttty >= 0 && tpgrp >= 0) (void) setpgrp(0, pgrp); if (tpgrp > 0) tpgrp = 0; if (t->t_dflg & FNOHUP) (void) signal(SIGHUP, SIG_IGN); if (t->t_dflg & FNICE) (void) setpriority(PRIO_PROCESS, 0, t->t_nice); } } #endif if (pid != 0) { /* * It would be better if we could wait for the * whole job when we knew the last process * had been started. Pwait, in fact, does * wait for the whole job anyway, but this test * doesn't really express our intentions. */ if (didfds==0 && t->t_dflg&FPIN) { (void) close(pipein[0]); (void) close(pipein[1]); } if ((t->t_dflg & (FPOU|FAND)) == 0) pwait(); break; } doio(t, pipein, pipeout); if (t->t_dflg & FPOU) { (void) close(pipeout[0]); (void) close(pipeout[1]); } /* * Perform a builtin function. * If we are not forked, arrange for possible stopping */ if (bifunc) { func(t, bifunc); if (forked) exitstat(); break; } if (t->t_dtyp != TPAR) { doexec(t); /*NOTREACHED*/ } /* * For () commands must put new 0,1,2 in FSH* and recurse */ OLDSTD = dcopy(0, FOLDSTD); SHOUT = dcopy(1, FSHOUT); SHDIAG = dcopy(2, FSHDIAG); (void) close(SHIN); SHIN = -1; didfds = 0; wanttty = -1; t->t_dspr->t_dflg |= t->t_dflg & FINT; execute(t->t_dspr, wanttty); exitstat(); case TFIL: t->t_dcar->t_dflg |= FPOU | (t->t_dflg & (FPIN|FAND|FDIAG|FINT)); execute(t->t_dcar, wanttty, pipein, pv); t->t_dcdr->t_dflg |= FPIN | (t->t_dflg & (FPOU|FAND|FPAR|FINT)); if (wanttty > 0) wanttty = 0; /* got tty already */ execute(t->t_dcdr, wanttty, pv, pipeout); break; case TLST: if (t->t_dcar) { t->t_dcar->t_dflg |= t->t_dflg & FINT; execute(t->t_dcar, wanttty); /* * In strange case of A&B make a new job after A */ if (t->t_dcar->t_dflg&FAND && t->t_dcdr && (t->t_dcdr->t_dflg&FAND) == 0) pendjob(); } if (t->t_dcdr) { t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); execute(t->t_dcdr, wanttty); } break; case TOR: case TAND: if (t->t_dcar) { t->t_dcar->t_dflg |= t->t_dflg & FINT; execute(t->t_dcar, wanttty); if ((getn(value("status")) == 0) != (t->t_dtyp == TAND)) return; } if (t->t_dcdr) { t->t_dcdr->t_dflg |= t->t_dflg & (FPAR|FINT); execute(t->t_dcdr, wanttty); } break; } /* * Fall through for all breaks from switch * * If there will be no more executions of this * command, flush all file descriptors. * Places that turn on the FREDO bit are responsible * for doing donefds after the last re-execution */ if (didfds && !(t->t_dflg & FREDO)) donefds(); } #ifdef VFORK vffree() { register char **v; if (v = gargv) gargv = 0, blkfree(v); if (v = pargv) pargv = 0, blkfree(v); _exit(1); } #endif /* * Perform io redirection. * We may or maynot be forked here. */ doio(t, pipein, pipeout) register struct command *t; int *pipein, *pipeout; { register char *cp; register int flags = t->t_dflg; if (didfds || (flags & FREDO)) return; if ((flags & FHERE) == 0) { /* FHERE already done */ (void) close(0); if (cp = t->t_dlef) { cp = globone(Dfix1(cp)); xfree(cp); if (open(cp, 0) < 0) Perror(cp); } else if (flags & FPIN) { (void) dup(pipein[0]); (void) close(pipein[0]); (void) close(pipein[1]); } else if ((flags & FINT) && tpgrp == -1) { (void) close(0); (void) open("/dev/null", 0); } else (void) dup(OLDSTD); } (void) close(1); if (cp = t->t_drit) { cp = globone(Dfix1(cp)); xfree(cp); if ((flags & FCAT) && open(cp, O_WRONLY | O_APPEND) >= 0) ; else { if (!(flags & FANY) && adrof("noclobber")) { if (flags & FCAT) Perror(cp); chkclob(cp); } if (creat(cp, 0666) < 0) Perror(cp); } } else if (flags & FPOU) (void) dup(pipeout[1]); else (void) dup(SHOUT); (void) close(2); if (flags & FDIAG) (void) dup(1); else (void) dup(SHDIAG); didfds = 1; } mypipe(pv) register int *pv; { if (pipe(pv) < 0) goto oops; pv[0] = dmove(pv[0], -1); pv[1] = dmove(pv[1], -1); if (pv[0] >= 0 && pv[1] >= 0) return; oops: error("Can't make pipe"); } chkclob(cp) register char *cp; { struct stat stb; if (stat(cp, &stb) < 0) return; if ((stb.st_mode & S_IFMT) == S_IFCHR) return; error("%s: File exists", cp); } /* * This mess is the necessary kludge to handle the prefix * builtins: nice, nohup, time. These commands can also * be used by themselves, and this is not handled here. * This will also work when loops are parsed. */ while (t->t_dtyp == TCOM) if (eq(tbin/csh/sh.set.c 444 0 12 27524 5057640510 6757 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.set.c 5.2 (Berkeley) 6/6/85"; #endif #include "sh.h" /* * C Shell */ doset(v) register char **v; { register char *p; char *vp, op; char **vecp; bool hadsub; int subscr; v++; p = *v++; if (p == 0) { prvars(); return; } do { hadsub = 0; for (vp = p; alnum(*p); p++) continue; if (vp == p || !letter(*vp)) goto setsyn; if (*p == '[') { hadsub++; p = getinx(p, &subscr); } if (op = *p) { *p++ = 0; if (*p == 0 && *v && **v == '(') p = *v++; } else if (*v && eq(*v, "=")) { op = '=', v++; if (*v) p = *v++; } if (op && op != '=') setsyn: bferr("Syntax error"); if (eq(p, "(")) { register char **e = v; if (hadsub) goto setsyn; for (;;) { if (!*e) bferr("Missing )"); if (**e == ')') break; e++; } p = *e; *e = 0; vecp = saveblk(v); set1(vp, vecp, &shvhed); *e = p; v = e + 1; } else if (hadsub) asx(vp, subscr, savestr(p)); else set(vp, savestr(p)); if (eq(vp, "path")) { exportpath(adrof("path")->vec); dohash(); } else if (eq(vp, "histchars")) { register char *p = value("histchars"); HIST = *p++; HISTSUB = *p; } else if (eq(vp, "user")) setenv("USER", value(vp)); else if (eq(vp, "term")) setenv("TERM", value(vp)); else if (eq(vp, "home")) setenv("HOME", value(vp)); #ifdef FILEC else if (eq(vp, "filec")) filec = 1; #endif } while (p = *v++); } char * getinx(cp, ip) register char *cp; register int *ip; { *ip = 0; *cp++ = 0; while (*cp && digit(*cp)) *ip = *ip * 10 + *cp++ - '0'; if (*cp++ != ']') bferr("Subscript error"); return (cp); } asx(vp, subscr, p) char *vp; int subscr; char *p; { register struct varent *v = getvx(vp, subscr); xfree(v->vec[subscr - 1]); v->vec[subscr - 1] = globone(p); } struct varent * getvx(vp, subscr) char *vp; { register struct varent *v = adrof(vp); if (v == 0) udvar(vp); if (subscr < 1 || subscr > blklen(v->vec)) bferr("Subscript out of range"); return (v); } char plusplus[2] = { '1', 0 }; dolet(v) char **v; { register char *p; char *vp, c, op; bool hadsub; int subscr; v++; p = *v++; if (p == 0) { prvars(); return; } do { hadsub = 0; for (vp = p; alnum(*p); p++) continue; if (vp == p || !letter(*vp)) goto letsyn; if (*p == '[') { hadsub++; p = getinx(p, &subscr); } if (*p == 0 && *v) p = *v++; if (op = *p) *p++ = 0; else goto letsyn; vp = savestr(vp); if (op == '=') { c = '='; p = xset(p, &v); } else { c = *p++; if (any(c, "+-")) { if (c != op || *p) goto letsyn; p = plusplus; } else { if (any(op, "<>")) { if (c != op) goto letsyn; c = *p++; letsyn: bferr("Syntax error"); } if (c != '=') goto letsyn; p = xset(p, &v); } } if (op == '=') if (hadsub) asx(vp, subscr, p); else set(vp, p); else if (hadsub) #ifndef V6 /* avoid bug in vax CC */ { struct varent *gv = getvx(vp, subscr); asx(vp, subscr, operate(op, gv->vec[subscr - 1], p)); } #else asx(vp, subscr, operate(op, getvx(vp, subscr)->vec[subscr - 1], p)); #endif else set(vp, operate(op, value(vp), p)); if (eq(vp, "path")) { exportpath(adrof("path")->vec); dohash(); } XFREE(vp) if (c != '=') XFREE(p) } while (p = *v++); } char * xset(cp, vp) char *cp, ***vp; { register char *dp; if (*cp) { dp = savestr(cp); --(*vp); xfree(**vp); **vp = dp; } return (putn(exp(vp))); } char * operate(op, vp, p) char op, *vp, *p; { char opr[2]; char *vec[5]; register char **v = vec; char **vecp = v; register int i; if (op != '=') { if (*vp) *v++ = vp; opr[0] = op; opr[1] = 0; *v++ = opr; if (op == '<' || op == '>') *v++ = opr; } *v++ = p; *v++ = 0; i = exp(&vecp); if (*vecp) bferr("Expression syntax"); return (putn(i)); } static char *putp; char * putn(n) register int n; { static char number[15]; putp = number; if (n < 0) { n = -n; *putp++ = '-'; } if (sizeof (int) == 2 && n == -32768) { *putp++ = '3'; n = 2768; #ifdef pdp11 } #else } else if (sizeof (int) == 4 && n == -2147483648) { *putp++ = '2'; n = 147483648; } #endif putn1(n); *putp = 0; return (savestr(number)); } putn1(n) register int n; { if (n > 9) putn1(n / 10); *putp++ = n % 10 + '0'; } getn(cp) register char *cp; { register int n; int sign; sign = 0; if (cp[0] == '+' && cp[1]) cp++; if (*cp == '-') { sign++; cp++; if (!digit(*cp)) goto badnum; } n = 0; while (digit(*cp)) n = n * 10 + *cp++ - '0'; if (*cp) goto badnum; return (sign ? -n : n); badnum: bferr("Badly formed number"); return (0); } char * value1(var, head) char *var; struct varent *head; { register struct varent *vp; vp = adrof1(var, head); return (vp == 0 || vp->vec[0] == 0 ? "" : vp->vec[0]); } struct varent * madrof(pat, vp) char *pat; register struct varent *vp; { register struct varent *vp1; for (; vp; vp = vp->v_right) { if (vp->v_left && (vp1 = madrof(pat, vp->v_left))) return vp1; if (Gmatch(vp->v_name, pat)) return vp; } return vp; } struct varent * adrof1(name, v) register char *name; register struct varent *v; { register cmp; v = v->v_left; while (v && ((cmp = *name - *v->v_name) || (cmp = strcmp(name, v->v_name)))) if (cmp < 0) v = v->v_left; else v = v->v_right; return v; } /* * The caller is responsible for putting value in a safe place */ set(var, val) char *var, *val; { register char **vec = (char **) xalloc(2 * sizeof (char **)); vec[0] = onlyread(val) ? savestr(val) : val; vec[1] = 0; set1(var, vec, &shvhed); } set1(var, vec, head) char *var, **vec; struct varent *head; { register char **oldv = vec; gflag = 0; tglob(oldv); if (gflag) { vec = glob(oldv); if (vec == 0) { bferr("No match"); blkfree(oldv); return; } blkfree(oldv); gargv = 0; } setq(var, vec, head); } setq(name, vec, p) char *name, **vec; register struct varent *p; { register struct varent *c; register f; f = 0; /* tree hangs off the header's left link */ while (c = p->v_link[f]) { if ((f = *name - *c->v_name) == 0 && (f = strcmp(name, c->v_name)) == 0) { blkfree(c->vec); goto found; } p = c; f = f > 0; } p->v_link[f] = c = (struct varent *)xalloc(sizeof (struct varent)); c->v_name = savestr(name); c->v_bal = 0; c->v_left = c->v_right = 0; c->v_parent = p; balance(p, f, 0); found: trim(c->vec = vec); } unset(v) char *v[]; { unset1(v, &shvhed); if (adrof("histchars") == 0) { HIST = '!'; HISTSUB = '^'; } #ifdef FILEC if (adrof("filec") == 0) filec = 0; #endif } unset1(v, head) register char *v[]; struct varent *head; { register struct varent *vp; register int cnt; while (*++v) { cnt = 0; while (vp = madrof(*v, head->v_left)) unsetv1(vp), cnt++; if (cnt == 0) setname(*v); } } unsetv(var) char *var; { register struct varent *vp; if ((vp = adrof1(var, &shvhed)) == 0) udvar(var); unsetv1(vp); } unsetv1(p) register struct varent *p; { register struct varent *c, *pp; register f; /* * Free associated memory first to avoid complications. */ blkfree(p->vec); XFREE(p->v_name); /* * If p is missing one child, then we can move the other * into where p is. Otherwise, we find the predecessor * of p, which is guaranteed to have no right child, copy * it into p, and move it's left child into it. */ if (p->v_right == 0) c = p->v_left; else if (p->v_left == 0) c = p->v_right; else { for (c = p->v_left; c->v_right; c = c->v_right) ; p->v_name = c->v_name; p->vec = c->vec; p = c; c = p->v_left; } /* * Move c into where p is. */ pp = p->v_parent; f = pp->v_right == p; if (pp->v_link[f] = c) c->v_parent = pp; /* * Free the deleted node, and rebalance. */ XFREE((char *)p); balance(pp, f, 1); } setNS(cp) char *cp; { set(cp, ""); } shift(v) register char **v; { register struct varent *argv; register char *name; v++; name = *v; if (name == 0) name = "argv"; else (void) strip(name); argv = adrof(name); if (argv == 0) udvar(name); if (argv->vec[0] == 0) bferr("No more words"); lshift(argv->vec, 1); } exportpath(val) char **val; { char exppath[BUFSIZ]; exppath[0] = 0; if (val) while (*val) { if (strlen(*val) + strlen(exppath) + 2 > BUFSIZ) { printf("Warning: ridiculously long PATH truncated\n"); break; } (void) strcat(exppath, *val++); if (*val == 0 || eq(*val, ")")) break; (void) strcat(exppath, ":"); } setenv("PATH", exppath); } /* macros to do single rotations on node p */ #define rright(p) (\ t = (p)->v_left,\ (t)->v_parent = (p)->v_parent,\ ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\ (t->v_right = (p))->v_parent = t,\ (p) = t) #define rleft(p) (\ t = (p)->v_right,\ (t)->v_parent = (p)->v_parent,\ ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\ (t->v_left = (p))->v_parent = t,\ (p) = t) /* * Rebalance a tree, starting at p and up. * F == 0 means we've come from p's left child. * D == 1 means we've just done a delete, otherwise an insert. */ balance(p, f, d) register struct varent *p; register f; { register struct varent *pp; register struct varent *t; /* used by the rotate macros */ register ff; /* * Ok, from here on, p is the node we're operating on; * pp is it's parent; f is the branch of p from which we have come; * ff is the branch of pp which is p. */ for (; pp = p->v_parent; p = pp, f = ff) { ff = pp->v_right == p; if (f ^ d) { /* right heavy */ switch (p->v_bal) { case -1: /* was left heavy */ p->v_bal = 0; break; case 0: /* was balanced */ p->v_bal = 1; break; case 1: /* was already right heavy */ switch (p->v_right->v_bal) { case 1: /* sigle rotate */ pp->v_link[ff] = rleft(p); p->v_left->v_bal = 0; p->v_bal = 0; break; case 0: /* single rotate */ pp->v_link[ff] = rleft(p); p->v_left->v_bal = 1; p->v_bal = -1; break; case -1: /* double rotate */ rright(p->v_right); pp->v_link[ff] = rleft(p); p->v_left->v_bal = p->v_bal < 1 ? 0 : -1; p->v_right->v_bal = p->v_bal > -1 ? 0 : 1; p->v_bal = 0; break; } break; } } else { /* left heavy */ switch (p->v_bal) { case 1: /* was right heavy */ p->v_bal = 0; break; case 0: /* was balanced */ p->v_bal = -1; break; case -1: /* was already left heavy */ switch (p->v_left->v_bal) { case -1: /* single rotate */ pp->v_link[ff] = rright(p); p->v_right->v_bal = 0; p->v_bal = 0; break; case 0: /* signle rotate */ pp->v_link[ff] = rright(p); p->v_right->v_bal = -1; p->v_bal = 1; break; case 1: /* double rotate */ rleft(p->v_left); pp->v_link[ff] = rright(p); p->v_left->v_bal = p->v_bal < 1 ? 0 : -1; p->v_right->v_bal = p->v_bal > -1 ? 0 : 1; p->v_bal = 0; break; } break; } } /* * If from insert, then we terminate when p is balanced. * If from delete, then we terminate when p is unbalanced. */ if ((p->v_bal == 0) ^ d) break; } } plist(p) register struct varent *p; { register struct varent *c; register len; if (setintr) (void) sigsetmask(sigblock(0L) & ~ sigmask(SIGINT)); for (;;) { while (p->v_left) p = p->v_left; x: if (p->v_parent == 0) /* is it the header? */ return; len = blklen(p->vec); printf(p->v_name); putchar('\t'); if (len != 1) putchar('('); blkpr(p->vec); if (len != 1) putchar(')'); putchar('\n'); if (p->v_right) { p = p->v_right; continue; } do { c = p; p = p->v_parent; } while (p->v_right == c); goto x; } } if (op != '=') { if (*vp) *v++ = vp; opr[0] = op; opr[1] = 0; *v++ = opr; if (op == '<' || op == '>') *v++ = opr; } *v++ = p; *v++ = 0; i = exp(&vecp); bin/csh/sh.glob.c 444 0 12 30326 5057640145 7105 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.glob.c 5.4 (Berkeley) 5/13/86"; #endif #include "sh.h" #include /* * C Shell */ int globcnt; char *gpath, *gpathp, *lastgpathp; int globbed; bool noglob; bool nonomatch; char *entp; char **sortbas; int sortscmp(); #define sort() qsort((char *)sortbas, &gargv[gargc] - sortbas, \ sizeof(*sortbas), sortscmp), sortbas = &gargv[gargc] char ** glob(v) register char **v; { char agpath[BUFSIZ]; char *agargv[GAVSIZ]; gpath = agpath; gpathp = gpath; *gpathp = 0; lastgpathp = &gpath[sizeof agpath - 2]; ginit(agargv); globcnt = 0; #ifdef GDEBUG printf("glob entered: "); blkpr(v); printf("\n"); #endif noglob = adrof("noglob") != 0; nonomatch = adrof("nonomatch") != 0; globcnt = noglob | nonomatch; while (*v) collect(*v++); #ifdef GDEBUG printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); blkpr(gargv); printf("\n"); #endif if (globcnt == 0 && (gflag&1)) { blkfree(gargv), gargv = 0; return (0); } else return (gargv = copyblk(gargv)); } ginit(agargv) char **agargv; { agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0; gnleft = NCARGS - 4; } collect(as) register char *as; { register int i; if (any('`', as)) { #ifdef GDEBUG printf("doing backp of %s\n", as); #endif (void) dobackp(as, 0); #ifdef GDEBUG printf("backp done, acollect'ing\n"); #endif for (i = 0; i < pargc; i++) if (noglob) { Gcat(pargv[i], ""); sortbas = &gargv[gargc]; } else acollect(pargv[i]); if (pargv) blkfree(pargv), pargv = 0; #ifdef GDEBUG printf("acollect done\n"); #endif } else if (noglob || eq(as, "{") || eq(as, "{}")) { Gcat(as, ""); sort(); } else acollect(as); } acollect(as) register char *as; { register int ogargc = gargc; gpathp = gpath; *gpathp = 0; globbed = 0; expand(as); if (gargc == ogargc) { if (nonomatch) { Gcat(as, ""); sort(); } } else sort(); } /* * String compare for qsort. Also used by filec code in sh.file.c. */ sortscmp(a1, a2) char **a1, **a2; { return (strcmp(*a1, *a2)); } expand(as) char *as; { register char *cs; register char *sgpathp, *oldcs; struct stat stb; sgpathp = gpathp; cs = as; if (*cs == '~' && gpathp == gpath) { addpath('~'); for (cs++; letter(*cs) || digit(*cs) || *cs == '-';) addpath(*cs++); if (!*cs || *cs == '/') { if (gpathp != gpath + 1) { *gpathp = 0; if (gethdir(gpath + 1)) error("Unknown user: %s", gpath + 1); (void) strcpy(gpath, gpath + 1); } else (void) strcpy(gpath, value("home")); gpathp = strend(gpath); } } while (!isglob(*cs)) { if (*cs == 0) { if (!globbed) Gcat(gpath, ""); else if (stat(gpath, &stb) >= 0) { Gcat(gpath, ""); globcnt++; } goto endit; } addpath(*cs++); } oldcs = cs; while (cs > as && *cs != '/') cs--, gpathp--; if (*cs == '/') cs++, gpathp++; *gpathp = 0; if (*oldcs == '{') { (void) execbrc(cs, NOSTR); return; } matchdir(cs); endit: gpathp = sgpathp; *gpathp = 0; } matchdir(pattern) char *pattern; { struct stat stb; register struct direct *dp; register DIR *dirp; dirp = opendir(gpath); if (dirp == NULL) { if (globbed) return; goto patherr2; } if (fstat(dirp->dd_fd, &stb) < 0) goto patherr1; if (!isdir(stb)) { errno = ENOTDIR; goto patherr1; } while ((dp = readdir(dirp)) != NULL) { if (dp->d_ino == 0) continue; if (match(dp->d_name, pattern)) { Gcat(gpath, dp->d_name); globcnt++; } } closedir(dirp); return; patherr1: closedir(dirp); patherr2: Perror(gpath); } execbrc(p, s) char *p, *s; { char restbuf[BUFSIZ + 2]; register char *pe, *pm, *pl; int brclev = 0; char *lm, savec, *sgpathp; for (lm = restbuf; *p != '{'; *lm++ = *p++) continue; for (pe = ++p; *pe; pe++) switch (*pe) { case '{': brclev++; continue; case '}': if (brclev == 0) goto pend; brclev--; continue; case '[': for (pe++; *pe && *pe != ']'; pe++) continue; if (!*pe) error("Missing ]"); continue; } pend: if (brclev || !*pe) error("Missing }"); for (pl = pm = p; pm <= pe; pm++) switch (*pm & (QUOTE|TRIM)) { case '{': brclev++; continue; case '}': if (brclev) { brclev--; continue; } goto doit; case ','|QUOTE: case ',': if (brclev) continue; doit: savec = *pm; *pm = 0; (void) strcpy(lm, pl); (void) strcat(restbuf, pe + 1); *pm = savec; if (s == 0) { sgpathp = gpathp; expand(restbuf); gpathp = sgpathp; *gpathp = 0; } else if (amatch(s, restbuf)) return (1); sort(); pl = pm + 1; continue; case '[': for (pm++; *pm && *pm != ']'; pm++) continue; if (!*pm) error("Missing ]"); continue; } return (0); } match(s, p) char *s, *p; { register int c; register char *sentp; char sglobbed = globbed; if (*s == '.' && *p != '.') return (0); sentp = entp; entp = s; c = amatch(s, p); entp = sentp; globbed = sglobbed; return (c); } amatch(s, p) register char *s, *p; { register int scc; int ok, lc; char *sgpathp; struct stat stb; int c, cc; globbed = 1; for (;;) { scc = *s++ & TRIM; switch (c = *p++) { case '{': return (execbrc(p - 1, s - 1)); case '[': ok = 0; lc = 077777; while (cc = *p++) { if (cc == ']') { if (ok) break; return (0); } if (cc == '-') { if (lc <= scc && scc <= *p++) ok++; } else if (scc == (lc = cc)) ok++; } if (cc == 0) error("Missing ]"); continue; case '*': if (!*p) return (1); if (*p == '/') { p++; goto slash; } for (s--; *s; s++) if (amatch(s, p)) return (1); return (0); case 0: return (scc == 0); default: if ((c & TRIM) != scc) return (0); continue; case '?': if (scc == 0) return (0); continue; case '/': if (scc) return (0); slash: s = entp; sgpathp = gpathp; while (*s) addpath(*s++); addpath('/'); if (stat(gpath, &stb) == 0 && isdir(stb)) if (*p == 0) { Gcat(gpath, ""); globcnt++; } else expand(p); gpathp = sgpathp; *gpathp = 0; return (0); } } } Gmatch(s, p) register char *s, *p; { register int scc; int ok, lc; int c, cc; for (;;) { scc = *s++ & TRIM; switch (c = *p++) { case '[': ok = 0; lc = 077777; while (cc = *p++) { if (cc == ']') { if (ok) break; return (0); } if (cc == '-') { if (lc <= scc && scc <= *p++) ok++; } else if (scc == (lc = cc)) ok++; } if (cc == 0) bferr("Missing ]"); continue; case '*': if (!*p) return (1); for (s--; *s; s++) if (Gmatch(s, p)) return (1); return (0); case 0: return (scc == 0); default: if ((c & TRIM) != scc) return (0); continue; case '?': if (scc == 0) return (0); continue; } } } Gcat(s1, s2) char *s1, *s2; { register char *p, *q; int n; for (p = s1; *p++;) ; for (q = s2; *q++;) ; gnleft -= (n = (p - s1) + (q - s2) - 1); if (gnleft <= 0 || ++gargc >= GAVSIZ) error("Arguments too long"); gargv[gargc] = 0; p = gargv[gargc - 1] = xalloc((unsigned)n); for (q = s1; *p++ = *q++;) ; for (p--, q = s2; *p++ = *q++;) ; } addpath(c) char c; { if (gpathp >= lastgpathp) error("Pathname too long"); *gpathp++ = c & TRIM; *gpathp = 0; } rscan(t, f) register char **t; int (*f)(); { register char *p; while (p = *t++) while (*p) (*f)(*p++); } trim(t) register char **t; { register char *p; while (p = *t++) while (*p) *p++ &= TRIM; } tglob(t) register char **t; { register char *p, c; while (p = *t++) { if (*p == '~') gflag |= 2; else if (*p == '{' && (p[1] == '\0' || p[1] == '}' && p[2] == '\0')) continue; while (c = *p++) if (isglob(c)) gflag |= c == '{' ? 2 : 1; } } char * globone(str) register char *str; { char *gv[2]; register char **gvp; register char *cp; gv[0] = str; gv[1] = 0; gflag = 0; tglob(gv); if (gflag) { gvp = glob(gv); if (gvp == 0) { setname(str); bferr("No match"); } cp = *gvp++; if (cp == 0) cp = ""; else if (*gvp) { setname(str); bferr("Ambiguous"); } else cp = strip(cp); /* if (cp == 0 || *gvp) { setname(str); bferr(cp ? "Ambiguous" : "No output"); } */ xfree((char *)gargv); gargv = 0; } else { trim(gv); cp = savestr(gv[0]); } return (cp); } /* * Command substitute cp. If literal, then this is * a substitution from a << redirection, and so we should * not crunch blanks and tabs, separating words only at newlines. */ char ** dobackp(cp, literal) char *cp; bool literal; { register char *lp, *rp; char *ep; char word[BUFSIZ]; char *apargv[GAVSIZ + 2]; if (pargv) { abort(); blkfree(pargv); } pargv = apargv; pargv[0] = NOSTR; pargcp = pargs = word; pargc = 0; pnleft = BUFSIZ - 4; for (;;) { for (lp = cp; *lp != '`'; lp++) { if (*lp == 0) { if (pargcp != pargs) pword(); #ifdef GDEBUG printf("leaving dobackp\n"); #endif return (pargv = copyblk(pargv)); } psave(*lp); } lp++; for (rp = lp; *rp && *rp != '`'; rp++) if (*rp == '\\') { rp++; if (!*rp) goto oops; } if (!*rp) oops: error("Unmatched `"); ep = savestr(lp); ep[rp - lp] = 0; backeval(ep, literal); #ifdef GDEBUG printf("back from backeval\n"); #endif cp = rp + 1; } } backeval(cp, literal) char *cp; bool literal; { int pvec[2]; int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; char ibuf[BUFSIZ]; register int icnt = 0, c; register char *ip; bool hadnl = 0; char *fakecom[2]; struct command faket; faket.t_dtyp = TCOM; faket.t_dflg = 0; faket.t_dlef = 0; faket.t_drit = 0; faket.t_dspr = 0; faket.t_dcom = fakecom; fakecom[0] = "` ... `"; fakecom[1] = 0; /* * We do the psave job to temporarily change the current job * so that the following fork is considered a separate job. * This is so that when backquotes are used in a * builtin function that calls glob the "current job" is not corrupted. * We only need one level of pushed jobs as long as we are sure to * fork here. */ psavejob(); /* * It would be nicer if we could integrate this redirection more * with the routines in sh.sem.c by doing a fake execute on a builtin * function that was piped out. */ mypipe(pvec); if (pfork(&faket, -1) == 0) { struct wordent paraml; struct command *t; (void) close(pvec[0]); (void) dmove(pvec[1], 1); (void) dmove(SHDIAG, 2); initdesc(); arginp = cp; while (*cp) *cp++ &= TRIM; (void) lex(¶ml); if (err) error(err); alias(¶ml); t = syntax(paraml.next, ¶ml, 0); if (err) error(err); if (t) t->t_dflg |= FPAR; (void) signal(SIGTSTP, SIG_IGN); (void) signal(SIGTTIN, SIG_IGN); (void) signal(SIGTTOU, SIG_IGN); execute(t, -1); exitstat(); } xfree(cp); (void) close(pvec[1]); do { int cnt = 0; for (;;) { if (icnt == 0) { ip = ibuf; icnt = read(pvec[0], ip, BUFSIZ); if (icnt <= 0) { c = -1; break; } } if (hadnl) break; --icnt; c = (*ip++ & TRIM); if (c == 0) break; if (c == '\n') { /* * Continue around the loop one * more time, so that we can eat * the last newline without terminating * this word. */ hadnl = 1; continue; } if (!quoted && (c == ' ' || c == '\t')) break; cnt++; psave(c | quoted); } /* * Unless at end-of-file, we will form a new word * here if there were characters in the word, or in * any case when we take text literally. If * we didn't make empty words here when literal was * set then we would lose blank lines. */ if (c != -1 && (cnt || literal)) pword(); hadnl = 0; } while (c >= 0); #ifdef GDEBUG printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]); printf("also c = %c <%o>\n", c, c); #endif (void) close(pvec[0]); pwait(); prestjob(); } psave(c) char c; { if (--pnleft <= 0) error("Word too long"); *pargcp++ = c; } pword() { psave(0); if (pargc == GAVSIZ) error("Too many words from ``"); pargv[pargc++] = savestr(pargs); pargv[pargc] = NOSTR; #ifdef GDEBUG printf("got word %s\n", pargv[pargc-1]); #endif pargcp = pargs; pnleft = BUFSIZ - 4; } HISTSUB = '^'; } #ifdef FILEC if (adrof("filec") == 0) filec = 0; #endif } unset1(v, head) register char *v[]; struct varent *head; { register struct varent *vp; register int cnt; while (*++v) { cnt = 0; while (vp = madrof(*v, head->v_left)) unsetv1(vp), cnt++; if (cnt == 0) bin/csh/sh.c 444 0 12 47736 5057637615 6210 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.c 5.3 (Berkeley) 3/29/86"; #endif #include "sh.h" #include /* * C Shell * * Bill Joy, UC Berkeley, California, USA * October 1978, May 1980 * * Jim Kulp, IIASA, Laxenburg, Austria * April 1980 */ char *pathlist[] = { ".", "/usr/ucb", "/bin", "/usr/bin", 0 }; char *dumphist[] = { "history", "-h", 0, 0 }; char *loadhist[] = { "source", "-h", "~/.history", 0 }; char HIST = '!'; char HISTSUB = '^'; bool nofile; bool reenter; bool nverbose; bool nexececho; bool quitit; bool fast; bool batch; bool prompt = 1; bool enterhist = 0; extern gid_t getegid(), getgid(); extern uid_t geteuid(), getuid(); main(c, av) int c; char **av; { register char **v, *cp; register int f; struct sigvec osv; settimes(); /* Immed. estab. timing base */ v = av; if (eq(v[0], "a.out")) /* A.out's are quittable */ quitit = 1; uid = getuid(); loginsh = **v == '-' && c == 1; if (loginsh) (void) time(&chktim); /* * Move the descriptors to safe places. * The variable didfds is 0 while we have only FSH* to work with. * When didfds is true, we have 0,1,2 and prefer to use these. */ initdesc(); /* * Initialize the shell variables. * ARGV and PROMPT are initialized later. * STATUS is also munged in several places. * CHILD is munged when forking/waiting */ set("status", "0"); dinit(cp = getenv("HOME")); /* dinit thinks that HOME == cwd in a * login shell */ if (cp == NOSTR) fast++; /* No home -> can't read scripts */ else set("home", savestr(cp)); /* * Grab other useful things from the environment. * Should we grab everything?? */ if ((cp = getenv("USER")) != NOSTR) set("user", savestr(cp)); if ((cp = getenv("TERM")) != NOSTR) set("term", savestr(cp)); /* * Re-initialize path if set in environment */ if ((cp = getenv("PATH")) == NOSTR) set1("path", saveblk(pathlist), &shvhed); else importpath(cp); set("shell", SHELLPATH); doldol = putn(getpid()); /* For $$ */ shtemp = strspl("/tmp/sh", doldol); /* For << */ /* * Record the interrupt states from the parent process. * If the parent is non-interruptible our hand must be forced * or we (and our children) won't be either. * Our children inherit termination from our parent. * We catch it only if we are the login shell. */ /* parents interruptibility */ (void) sigvec(SIGINT, (struct sigvec *)0, &osv); parintr = osv.sv_handler; /* parents terminability */ (void) sigvec(SIGTERM, (struct sigvec *)0, &osv); parterm = osv.sv_handler; if (loginsh) { (void) signal(SIGHUP, phup); /* exit processing on HUP */ (void) signal(SIGXCPU, phup); /* ...and on XCPU */ (void) signal(SIGXFSZ, phup); /* ...and on XFSZ */ } /* * Process the arguments. * * Note that processing of -v/-x is actually delayed till after * script processing. */ c--, v++; while (c > 0 && (cp = v[0])[0] == '-' && *++cp != '\0' && !batch) { do switch (*cp++) { case 'b': /* -b Next arg is input file */ batch++; break; case 'c': /* -c Command input from arg */ if (c == 1) exit(0); c--, v++; arginp = v[0]; prompt = 0; nofile++; break; case 'e': /* -e Exit on any error */ exiterr++; break; case 'f': /* -f Fast start */ fast++; break; case 'i': /* -i Interactive, even if !intty */ intact++; nofile++; break; case 'n': /* -n Don't execute */ noexec++; break; case 'q': /* -q (Undoc'd) ... die on quit */ quitit = 1; break; case 's': /* -s Read from std input */ nofile++; break; case 't': /* -t Read one line from input */ onelflg = 2; prompt = 0; nofile++; break; case 'v': /* -v Echo hist expanded input */ nverbose = 1; /* ... later */ break; case 'x': /* -x Echo just before execution */ nexececho = 1; /* ... later */ break; case 'V': /* -V Echo hist expanded input */ setNS("verbose"); /* NOW! */ break; case 'X': /* -X Echo just before execution */ setNS("echo"); /* NOW! */ break; } while (*cp); v++, c--; } if (quitit) /* With all due haste, for debugging */ (void) signal(SIGQUIT, SIG_DFL); /* * Unless prevented by -c, -i, -s, or -t, if there * are remaining arguments the first of them is the name * of a shell file from which to read commands. */ if (nofile == 0 && c > 0) { nofile = open(v[0], 0); if (nofile < 0) { child++; /* So this ... */ Perror(v[0]); /* ... doesn't return */ } file = v[0]; SHIN = dmove(nofile, FSHIN); /* Replace FSHIN */ (void) ioctl(SHIN, FIOCLEX, (char *)0); prompt = 0; c--, v++; } if (!batch && (uid != geteuid() || getgid() != getegid())) { errno = EACCES; child++; /* So this ... */ Perror("csh"); /* ... doesn't return */ } /* * Consider input a tty if it really is or we are interactive. */ intty = intact || isatty(SHIN); /* * Decide whether we should play with signals or not. * If we are explicitly told (via -i, or -) or we are a login * shell (arg0 starts with -) or the input and output are both * the ttys("csh", or "csh/dev/ttyx") * Note that in only the login shell is it likely that parent * may have set signals to be ignored */ if (loginsh || intact || intty && isatty(SHOUT)) setintr = 1; #ifdef TELL settell(); #endif /* * Save the remaining arguments in argv. */ setq("argv", v, &shvhed); /* * Set up the prompt. */ if (prompt) set("prompt", uid == 0 ? "# " : "% "); /* * If we are an interactive shell, then start fiddling * with the signals; this is a tricky game. */ shpgrp = getpgrp(0); opgrp = tpgrp = -1; oldisc = -1; if (setintr) { **av = '-'; if (!quitit) /* Wary! */ (void) signal(SIGQUIT, SIG_IGN); (void) signal(SIGINT, pintr); (void) sigblock(sigmask(SIGINT)); (void) signal(SIGTERM, SIG_IGN); if (quitit == 0 && arginp == 0) { (void) signal(SIGTSTP, SIG_IGN); (void) signal(SIGTTIN, SIG_IGN); (void) signal(SIGTTOU, SIG_IGN); /* * Wait till in foreground, in case someone * stupidly runs * csh & * dont want to try to grab away the tty. */ if (isatty(FSHDIAG)) f = FSHDIAG; else if (isatty(FSHOUT)) f = FSHOUT; else if (isatty(OLDSTD)) f = OLDSTD; else f = -1; retry: if (ioctl(f, TIOCGPGRP, (char *)&tpgrp) == 0 && tpgrp != -1) { int ldisc; if (tpgrp != shpgrp) { int (*old)() = signal(SIGTTIN, SIG_DFL); (void) kill(0, SIGTTIN); (void) signal(SIGTTIN, old); goto retry; } if (ioctl(f, TIOCGETD, (char *)&oldisc) != 0) goto notty; if (oldisc != NTTYDISC) { #ifdef DEBUG printf("Switching to new tty driver...\n"); #endif DEBUG ldisc = NTTYDISC; (void) ioctl(f, TIOCSETD, (char *)&ldisc); } else oldisc = -1; opgrp = shpgrp; shpgrp = getpid(); tpgrp = shpgrp; (void) ioctl(f, TIOCSPGRP, (char *)&shpgrp); (void) setpgrp(0, shpgrp); (void) ioctl(dcopy(f, FSHTTY), FIOCLEX, (char *)0); } else { notty: printf("Warning: no access to tty; thus no job control in this shell...\n"); tpgrp = -1; } } } if (setintr == 0 && parintr == SIG_DFL) setintr++; (void) signal(SIGCHLD, pchild); /* while signals not ready */ /* * Set an exit here in case of an interrupt or error reading * the shell start-up scripts. */ setexit(); haderr = 0; /* In case second time through */ if (!fast && reenter == 0) { reenter++; /* Will have value("home") here because set fast if don't */ srccat(value("home"), "/.cshrc"); if (!fast && !arginp && !onelflg && !havhash) dohash(); if (loginsh) { srccat(value("home"), "/.login"); } dosource(loadhist); } /* * Now are ready for the -v and -x flags */ if (nverbose) setNS("verbose"); if (nexececho) setNS("echo"); /* * All the rest of the world is inside this call. * The argument to process indicates whether it should * catch "error unwinds". Thus if we are a interactive shell * our call here will never return by being blown past on an error. */ process(setintr); /* * Mop-up. */ if (loginsh) { printf("logout\n"); (void) close(SHIN); child++; goodbye(); } rechist(); exitstat(); } untty() { if (tpgrp > 0) { (void) setpgrp(0, opgrp); (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&opgrp); if (oldisc != -1 && oldisc != NTTYDISC) { #ifdef DEBUG printf("\nReverting to old tty driver...\n"); #endif DEBUG (void) ioctl(FSHTTY, TIOCSETD, (char *)&oldisc); } } } importpath(cp) char *cp; { register int i = 0; register char *dp; register char **pv; int c; static char dot[2] = {'.', 0}; for (dp = cp; *dp; dp++) if (*dp == ':') i++; /* * i+2 where i is the number of colons in the path. * There are i+1 directories in the path plus we need * room for a zero terminator. */ pv = (char **) calloc((unsigned) (i + 2), sizeof (char **)); dp = cp; i = 0; if (*dp) for (;;) { if ((c = *dp) == ':' || c == 0) { *dp = 0; pv[i++] = savestr(*cp ? cp : dot); if (c) { cp = dp + 1; *dp = ':'; } else break; } dp++; } pv[i] = 0; set1("path", pv, &shvhed); } /* * Source to the file which is the catenation of the argument names. */ srccat(cp, dp) char *cp, *dp; { register char *ep = strspl(cp, dp); register int unit = dmove(open(ep, 0), -1); (void) ioctl(unit, FIOCLEX, (char *)0); xfree(ep); #ifdef INGRES srcunit(unit, 0, 0); #else srcunit(unit, 1, 0); #endif } /* * Source to a unit. If onlyown it must be our file or our group or * we don't chance it. This occurs on ".cshrc"s and the like. */ srcunit(unit, onlyown, hflg) register int unit; bool onlyown; bool hflg; { /* We have to push down a lot of state here */ /* All this could go into a structure */ int oSHIN = -1, oldintty = intty; struct whyle *oldwhyl = whyles; char *ogointr = gointr, *oarginp = arginp; char *oevalp = evalp, **oevalvec = evalvec; int oonelflg = onelflg; bool oenterhist = enterhist; char OHIST = HIST; #ifdef TELL bool otell = cantell; #endif struct Bin saveB; /* The (few) real local variables */ jmp_buf oldexit; int reenter; long omask; if (unit < 0) return; if (didfds) donefds(); if (onlyown) { struct stat stb; if (fstat(unit, &stb) < 0 || (stb.st_uid != uid && stb.st_gid != getgid())) { (void) close(unit); return; } } /* * There is a critical section here while we are pushing down the * input stream since we have stuff in different structures. * If we weren't careful an interrupt could corrupt SHIN's Bin * structure and kill the shell. * * We could avoid the critical region by grouping all the stuff * in a single structure and pointing at it to move it all at * once. This is less efficient globally on many variable references * however. */ getexit(oldexit); reenter = 0; if (setintr) omask = sigblock(sigmask(SIGINT)); setexit(); reenter++; if (reenter == 1) { /* Setup the new values of the state stuff saved above */ copy((char *)&saveB, (char *)&B, sizeof saveB); fbuf = (char **) 0; fseekp = feobp = fblocks = 0; oSHIN = SHIN, SHIN = unit, arginp = 0, onelflg = 0; intty = isatty(SHIN), whyles = 0, gointr = 0; evalvec = 0; evalp = 0; enterhist = hflg; if (enterhist) HIST = '\0'; /* * Now if we are allowing commands to be interrupted, * we let ourselves be interrupted. */ if (setintr) (void) sigsetmask(omask); #ifdef TELL settell(); #endif process(0); /* 0 -> blow away on errors */ } if (setintr) (void) sigsetmask(omask); if (oSHIN >= 0) { register int i; /* We made it to the new state... free up its storage */ /* This code could get run twice but xfree doesn't care */ for (i = 0; i < fblocks; i++) xfree(fbuf[i]); xfree((char *)fbuf); /* Reset input arena */ copy((char *)&B, (char *)&saveB, sizeof B); (void) close(SHIN), SHIN = oSHIN; arginp = oarginp, onelflg = oonelflg; evalp = oevalp, evalvec = oevalvec; intty = oldintty, whyles = oldwhyl, gointr = ogointr; if (enterhist) HIST = OHIST; enterhist = oenterhist; #ifdef TELL cantell = otell; #endif } resexit(oldexit); /* * If process reset() (effectively an unwind) then * we must also unwind. */ if (reenter >= 2) error(NOSTR); } rechist() { char buf[BUFSIZ]; int fp, ftmp, oldidfds; if (!fast) { if (value("savehist")[0] == '\0') return; (void) strcpy(buf, value("home")); (void) strcat(buf, "/.history"); fp = creat(buf, 0666); if (fp == -1) return; oldidfds = didfds; didfds = 0; ftmp = SHOUT; SHOUT = fp; (void) strcpy(buf, value("savehist")); dumphist[2] = buf; dohist(dumphist); (void) close(fp); SHOUT = ftmp; didfds = oldidfds; } } goodbye() { if (loginsh) { (void) signal(SIGQUIT, SIG_IGN); (void) signal(SIGINT, SIG_IGN); (void) signal(SIGTERM, SIG_IGN); setintr = 0; /* No interrupts after "logout" */ if (adrof("home")) srccat(value("home"), "/.logout"); } rechist(); exitstat(); } exitstat() { #ifdef PROF monitor(0); #endif /* * Note that if STATUS is corrupted (i.e. getn bombs) * then error will exit directly because we poke child here. * Otherwise we might continue unwarrantedly (sic). */ child++; exit(getn(value("status"))); } /* * in the event of a HUP we want to save the history */ phup() { rechist(); exit(1); } char *jobargv[2] = { "jobs", 0 }; /* * Catch an interrupt, e.g. during lexical input. * If we are an interactive shell, we reset the interrupt catch * immediately. In any case we drain the shell output, * and finally go through the normal error mechanism, which * gets a chance to make the shell go away. */ pintr() { pintr1(1); } pintr1(wantnl) bool wantnl; { register char **v; long omask; omask = sigblock(0L); if (setintr) { (void) sigsetmask(omask & ~sigmask(SIGINT)); if (pjobs) { pjobs = 0; printf("\n"); dojobs(jobargv); bferr("Interrupted"); } } (void) sigsetmask(omask & ~sigmask(SIGCHLD)); draino(); /* * If we have an active "onintr" then we search for the label. * Note that if one does "onintr -" then we shan't be interruptible * so we needn't worry about that here. */ if (gointr) { search(ZGOTO, 0, gointr); timflg = 0; if (v = pargv) pargv = 0, blkfree(v); if (v = gargv) gargv = 0, blkfree(v); reset(); } else if (intty && wantnl) printf("\n"); /* Some like this, others don't */ error(NOSTR); } /* * Process is the main driving routine for the shell. * It runs all command processing, except for those within { ... } * in expressions (which is run by a routine evalav in sh.exp.c which * is a stripped down process), and `...` evaluation which is run * also by a subset of this code in sh.glob.c in the routine backeval. * * The code here is a little strange because part of it is interruptible * and hence freeing of structures appears to occur when none is necessary * if this is ignored. * * Note that if catch is not set then we will unwind on any error. * If an end-of-file occurs, we return. */ process(catch) bool catch; { jmp_buf osetexit; register struct command *t; getexit(osetexit); for (;;) { pendjob(); paraml.next = paraml.prev = ¶ml; paraml.word = ""; t = 0; setexit(); justpr = enterhist; /* execute if not entering history */ /* * Interruptible during interactive reads */ if (setintr) (void) sigsetmask(sigblock(0L) & ~sigmask(SIGINT)); /* * For the sake of reset() */ freelex(¶ml), freesyn(t), t = 0; if (haderr) { if (!catch) { /* unwind */ doneinp = 0; resexit(osetexit); reset(); } haderr = 0; /* * Every error is eventually caught here or * the shell dies. It is at this * point that we clean up any left-over open * files, by closing all but a fixed number * of pre-defined files. Thus routines don't * have to worry about leaving files open due * to deeper errors... they will get closed here. */ closem(); continue; } if (doneinp) { doneinp = 0; break; } if (chkstop) chkstop--; if (neednote) pnote(); if (intty && prompt && evalvec == 0) { mailchk(); /* * If we are at the end of the input buffer * then we are going to read fresh stuff. * Otherwise, we are rereading input and don't * need or want to prompt. */ if (fseekp == feobp) printprompt(); } err = 0; /* * Echo not only on VERBOSE, but also with history expansion. * If there is a lexical error then we forego history echo. */ if (lex(¶ml) && !err && intty || adrof("verbose")) { haderr = 1; prlex(¶ml); haderr = 0; } /* * The parser may lose space if interrupted. */ if (setintr) (void) sigblock(sigmask(SIGINT)); /* * Save input text on the history list if * reading in old history, or it * is from the terminal at the top level and not * in a loop. */ if (enterhist || catch && intty && !whyles) savehist(¶ml); /* * Print lexical error messages, except when sourcing * history lists. */ if (!enterhist && err) error(err); /* * If had a history command :p modifier then * this is as far as we should go */ if (justpr) reset(); alias(¶ml); /* * Parse the words of the input into a parse tree. */ t = syntax(paraml.next, ¶ml, 0); if (err) error(err); /* * Execute the parse tree */ execute(t, tpgrp); /* * Made it! */ freelex(¶ml), freesyn(t); } resexit(osetexit); } dosource(t) register char **t; { register char *f; register int u; bool hflg = 0; char buf[BUFSIZ]; t++; if (*t && eq(*t, "-h")) { t++; hflg++; } (void) strcpy(buf, *t); f = globone(buf); u = dmove(open(f, 0), -1); xfree(f); if (u < 0 && !hflg) Perror(f); (void) ioctl(u, FIOCLEX, (char *)0); srcunit(u, 0, hflg); } /* * Check for mail. * If we are a login shell, then we don't want to tell * about any mail file unless its been modified * after the time we started. * This prevents us from telling the user things he already * knows, since the login program insists on saying * "You have mail." */ mailchk() { register struct varent *v; register char **vp; time_t t; int intvl, cnt; struct stat stb; bool new; v = adrof("mail"); if (v == 0) return; (void) time(&t); vp = v->vec; cnt = blklen(vp); intvl = (cnt && number(*vp)) ? (--cnt, getn(*vp++)) : MAILINTVL; if (intvl < 1) intvl = 1; if (chktim + intvl > t) return; for (; *vp; vp++) { if (stat(*vp, &stb) < 0) continue; new = stb.st_mtime > time0.tv_sec; if (stb.st_size == 0 || stb.st_atime > stb.st_mtime || (stb.st_atime < chktim && stb.st_mtime < chktim) || loginsh && !new) continue; if (cnt == 1) printf("You have %smail.\n", new ? "new " : ""); else printf("%s in %s.\n", new ? "New mail" : "Mail", *vp); } chktim = t; } #include /* * Extract a home directory from the password file * The argument points to a buffer where the name of the * user whose home directory is sought is currently. * We write the home directory of the user back there. */ gethdir(home) char *home; { register struct passwd *pp = getpwnam(home); if (pp == 0) return (1); (void) strcpy(home, pp->pw_dir); return (0); } /* * Move the initial descriptors to their eventual * resting places, closin all other units. */ initdesc() { didfds = 0; /* 0, 1, 2 aren't set up */ (void) ioctl(SHIN = dcopy(0, FSHIN), FIOCLEX, (char *)0); (void) ioctl(SHOUT = dcopy(1, FSHOUT), FIOCLEX, (char *)0); (void) ioctl(SHDIAG = dcopy(2, FSHDIAG), FIOCLEX, (char *)0); (void) ioctl(OLDSTD = dcopy(SHIN, FOLDSTD), FIOCLEX, (char *)0); closem(); } #ifdef PROF done(i) #else exit(i) #endif int i; { untty(); _exit(i); } printprompt() { register char *cp; if (!whyles) { for (cp = value("prompt"); *cp; cp++) if (*cp == HIST) printf("%d", eventno + 1); else { if (*cp == '\\' && cp[1] == HIST) cp++; putchar(*cp | QUOTE); } } else /* * Prompt for forward reading loop * body content. */ printf("? "); flush(); } = onelflg; bool oenterhist = entebin/csh/sh.dol.c 444 0 12 32400 5057637727 6747 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.dol.c 5.3 (Berkeley) 3/29/86"; #endif #include "sh.h" /* * C shell */ /* * These routines perform variable substitution and quoting via ' and ". * To this point these constructs have been preserved in the divided * input words. Here we expand variables and turn quoting via ' and " into * QUOTE bits on characters (which prevent further interpretation). * If the `:q' modifier was applied during history expansion, then * some QUOTEing may have occurred already, so we dont "trim()" here. */ int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */ char *Dcp, **Dvp; /* Input vector for Dreadc */ #define DEOF -1 #define unDgetC(c) Dpeekc = c #define QUOTES (_Q|_Q1|_ESC) /* \ ' " ` */ /* * The following variables give the information about the current * $ expansion, recording the current word position, the remaining * words within this expansion, the count of remaining words, and the * information about any : modifier which is being applied. */ char *dolp; /* Remaining chars from this word */ char **dolnxt; /* Further words */ int dolcnt; /* Count of further words */ char dolmod; /* : modifier character */ int dolmcnt; /* :gx -> 10000, else 1 */ /* * Fix up the $ expansions and quotations in the * argument list to command t. */ Dfix(t) register struct command *t; { register char **pp; register char *p; if (noexec) return; /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */ for (pp = t->t_dcom; p = *pp++;) while (*p) if (cmap(*p++, _DOL|QUOTES)) { /* $, \, ', ", ` */ Dfix2(t->t_dcom); /* found one */ blkfree(t->t_dcom); t->t_dcom = gargv; gargv = 0; return; } } /* * $ substitute one word, for i/o redirection */ char * Dfix1(cp) register char *cp; { char *Dv[2]; if (noexec) return (0); Dv[0] = cp; Dv[1] = NOSTR; Dfix2(Dv); if (gargc != 1) { setname(cp); bferr("Ambiguous"); } cp = savestr(gargv[0]); blkfree(gargv), gargv = 0; return (cp); } /* * Subroutine to do actual fixing after state initialization. */ Dfix2(v) char **v; { char *agargv[GAVSIZ]; ginit(agargv); /* Initialize glob's area pointers */ Dvp = v; Dcp = ""; /* Setup input vector for Dreadc */ unDgetC(0); unDredc(0); /* Clear out any old peeks (at error) */ dolp = 0; dolcnt = 0; /* Clear out residual $ expands (...) */ while (Dword()) continue; gargv = copyblk(gargv); } /* * Get a word. This routine is analogous to the routine * word() in sh.lex.c for the main lexical input. One difference * here is that we don't get a newline to terminate our expansion. * Rather, DgetC will return a DEOF when we hit the end-of-input. */ Dword() { register int c, c1; char wbuf[BUFSIZ]; register char *wp = wbuf; register int i = BUFSIZ - 4; register bool dolflg; bool sofar = 0; loop: c = DgetC(DODOL); switch (c) { case DEOF: deof: if (sofar == 0) return (0); /* finish this word and catch the code above the next time */ unDredc(c); /* fall into ... */ case '\n': *wp = 0; goto ret; case ' ': case '\t': goto loop; case '`': /* We preserve ` quotations which are done yet later */ *wp++ = c, --i; case '\'': case '"': /* * Note that DgetC never returns a QUOTES character * from an expansion, so only true input quotes will * get us here or out. */ c1 = c; dolflg = c1 == '"' ? DODOL : 0; for (;;) { c = DgetC(dolflg); if (c == c1) break; if (c == '\n' || c == DEOF) error("Unmatched %c", c1); if ((c & (QUOTE|TRIM)) == ('\n' | QUOTE)) --wp, ++i; if (--i <= 0) goto toochars; switch (c1) { case '"': /* * Leave any `s alone for later. * Other chars are all quoted, thus `...` * can tell it was within "...". */ *wp++ = c == '`' ? '`' : c | QUOTE; break; case '\'': /* Prevent all further interpretation */ *wp++ = c | QUOTE; break; case '`': /* Leave all text alone for later */ *wp++ = c; break; } } if (c1 == '`') *wp++ = '`', --i; goto pack; /* continue the word */ case '\\': c = DgetC(0); /* No $ subst! */ if (c == '\n' || c == DEOF) goto loop; c |= QUOTE; break; } unDgetC(c); pack: sofar = 1; /* pack up more characters in this word */ for (;;) { c = DgetC(DODOL); if (c == '\\') { c = DgetC(0); if (c == DEOF) goto deof; if (c == '\n') c = ' '; else c |= QUOTE; } if (c == DEOF) goto deof; if (cmap(c, _SP|_NL|_Q|_Q1)) { /* sp \t\n'"` */ unDgetC(c); if (cmap(c, QUOTES)) goto loop; *wp++ = 0; goto ret; } if (--i <= 0) toochars: error("Word too long"); *wp++ = c; } ret: Gcat("", wbuf); return (1); } /* * Get a character, performing $ substitution unless flag is 0. * Any QUOTES character which is returned from a $ expansion is * QUOTEd so that it will not be recognized above. */ DgetC(flag) register int flag; { register int c; top: if (c = Dpeekc) { Dpeekc = 0; return (c); } if (lap) { c = *lap++ & (QUOTE|TRIM); if (c == 0) { lap = 0; goto top; } quotspec: if (cmap(c, QUOTES)) return (c | QUOTE); return (c); } if (dolp) { if (c = *dolp++ & (QUOTE|TRIM)) goto quotspec; if (dolcnt > 0) { setDolp(*dolnxt++); --dolcnt; return (' '); } dolp = 0; } if (dolcnt > 0) { setDolp(*dolnxt++); --dolcnt; goto top; } c = Dredc(); if (c == '$' && flag) { Dgetdol(); goto top; } return (c); } char *nulvec[] = { 0 }; struct varent nulargv = { nulvec, "argv", 0 }; /* * Handle the multitudinous $ expansion forms. * Ugh. */ Dgetdol() { register char *np; register struct varent *vp; char name[20]; int c, sc; int subscr = 0, lwb = 1, upb = 0; bool dimen = 0, bitset = 0; char wbuf[BUFSIZ]; dolmod = dolmcnt = 0; c = sc = DgetC(0); if (c == '{') c = DgetC(0); /* sc is { to take } later */ if ((c & TRIM) == '#') dimen++, c = DgetC(0); /* $# takes dimension */ else if (c == '?') bitset++, c = DgetC(0); /* $? tests existence */ switch (c) { case '$': if (dimen || bitset) goto syntax; /* No $?$, $#$ */ setDolp(doldol); goto eatbrac; case '<'|QUOTE: if (dimen || bitset) goto syntax; /* No $?<, $#< */ for (np = wbuf; read(OLDSTD, np, 1) == 1; np++) { if (np >= &wbuf[BUFSIZ-1]) error("$< line too long"); if (*np <= 0 || *np == '\n') break; } *np = 0; /* * KLUDGE: dolmod is set here because it will * cause setDolp to call domod and thus to copy wbuf. * Otherwise setDolp would use it directly. If we saved * it ourselves, no one would know when to free it. * The actual function of the 'q' causes filename * expansion not to be done on the interpolated value. */ dolmod = 'q'; dolmcnt = 10000; setDolp(wbuf); goto eatbrac; case DEOF: case '\n': goto syntax; case '*': (void) strcpy(name, "argv"); vp = adrof("argv"); subscr = -1; /* Prevent eating [...] */ break; default: np = name; if (digit(c)) { if (dimen) goto syntax; /* No $#1, e.g. */ subscr = 0; do { subscr = subscr * 10 + c - '0'; c = DgetC(0); } while (digit(c)); unDredc(c); if (subscr < 0) goto oob; if (subscr == 0) { if (bitset) { dolp = file ? "1" : "0"; goto eatbrac; } if (file == 0) error("No file for $0"); setDolp(file); goto eatbrac; } if (bitset) goto syntax; vp = adrof("argv"); if (vp == 0) { vp = &nulargv; goto eatmod; } break; } if (!alnum(c)) goto syntax; for (;;) { *np++ = c; c = DgetC(0); if (!alnum(c)) break; if (np >= &name[sizeof name - 2]) syntax: error("Variable syntax"); } *np++ = 0; unDredc(c); vp = adrof(name); } if (bitset) { dolp = (vp || getenv(name)) ? "1" : "0"; goto eatbrac; } if (vp == 0) { np = getenv(name); if (np) { addla(np); goto eatbrac; } udvar(name); /*NOTREACHED*/ } c = DgetC(0); upb = blklen(vp->vec); if (dimen == 0 && subscr == 0 && c == '[') { np = name; for (;;) { c = DgetC(DODOL); /* Allow $ expand within [ ] */ if (c == ']') break; if (c == '\n' || c == DEOF) goto syntax; if (np >= &name[sizeof name - 2]) goto syntax; *np++ = c; } *np = 0, np = name; if (dolp || dolcnt) /* $ exp must end before ] */ goto syntax; if (!*np) goto syntax; if (digit(*np)) { register int i = 0; while (digit(*np)) i = i * 10 + *np++ - '0'; if ((i < 0 || i > upb) && !any(*np, "-*")) { oob: setname(vp->v_name); error("Subscript out of range"); } lwb = i; if (!*np) upb = lwb, np = "*"; } if (*np == '*') np++; else if (*np != '-') goto syntax; else { register int i = upb; np++; if (digit(*np)) { i = 0; while (digit(*np)) i = i * 10 + *np++ - '0'; if (i < 0 || i > upb) goto oob; } if (i < lwb) upb = lwb - 1; else upb = i; } if (lwb == 0) { if (upb != 0) goto oob; upb = -1; } if (*np) goto syntax; } else { if (subscr > 0) if (subscr > upb) lwb = 1, upb = 0; else lwb = upb = subscr; unDredc(c); } if (dimen) { char *cp = putn(upb - lwb + 1); addla(cp); xfree(cp); } else { eatmod: c = DgetC(0); if (c == ':') { c = DgetC(0), dolmcnt = 1; if (c == 'g') c = DgetC(0), dolmcnt = 10000; if (!any(c, "htrqxe")) error("Bad : mod in $"); dolmod = c; if (c == 'q') dolmcnt = 10000; } else unDredc(c); dolnxt = &vp->vec[lwb - 1]; dolcnt = upb - lwb + 1; } eatbrac: if (sc == '{') { c = Dredc(); if (c != '}') goto syntax; } } setDolp(cp) register char *cp; { register char *dp; if (dolmod == 0 || dolmcnt == 0) { dolp = cp; return; } dp = domod(cp, dolmod); if (dp) { dolmcnt--; addla(dp); xfree(dp); } else addla(cp); dolp = ""; } unDredc(c) int c; { Dpeekrd = c; } Dredc() { register int c; if (c = Dpeekrd) { Dpeekrd = 0; return (c); } if (Dcp && (c = *Dcp++)) return (c&(QUOTE|TRIM)); if (*Dvp == 0) { Dcp = 0; return (DEOF); } Dcp = *Dvp++; return (' '); } Dtestq(c) register int c; { if (cmap(c, QUOTES)) gflag = 1; } /* * Form a shell temporary file (in unit 0) from the words * of the shell input up to a line the same as "term". * Unit 0 should have been closed before this call. */ heredoc(term) char *term; { register int c; char *Dv[2]; char obuf[BUFSIZ], lbuf[BUFSIZ], mbuf[BUFSIZ]; int ocnt, lcnt, mcnt; register char *lbp, *obp, *mbp; char **vp; bool quoted; if (creat(shtemp, 0600) < 0) Perror(shtemp); (void) close(0); if (open(shtemp, 2) < 0) { int oerrno = errno; (void) unlink(shtemp); errno = oerrno; Perror(shtemp); } (void) unlink(shtemp); /* 0 0 inode! */ Dv[0] = term; Dv[1] = NOSTR; gflag = 0; trim(Dv); rscan(Dv, Dtestq); quoted = gflag; ocnt = BUFSIZ; obp = obuf; for (;;) { /* * Read up a line */ lbp = lbuf; lcnt = BUFSIZ - 4; for (;;) { c = readc(1); /* 1 -> Want EOF returns */ if (c < 0) { setname(term); bferr("<< terminator not found"); } if (c == '\n') break; if (c &= TRIM) { *lbp++ = c; if (--lcnt < 0) { setname("<<"); error("Line overflow"); } } } *lbp = 0; /* * Compare to terminator -- before expansion */ if (eq(lbuf, term)) { (void) write(0, obuf, BUFSIZ - ocnt); (void) lseek(0, (off_t)0, 0); return; } /* * If term was quoted or -n just pass it on */ if (quoted || noexec) { *lbp++ = '\n'; *lbp = 0; for (lbp = lbuf; c = *lbp++;) { *obp++ = c; if (--ocnt == 0) { (void) write(0, obuf, BUFSIZ); obp = obuf; ocnt = BUFSIZ; } } continue; } /* * Term wasn't quoted so variable and then command * expand the input line */ Dcp = lbuf; Dvp = Dv + 1; mbp = mbuf; mcnt = BUFSIZ - 4; for (;;) { c = DgetC(DODOL); if (c == DEOF) break; if ((c &= TRIM) == 0) continue; /* \ quotes \ $ ` here */ if (c =='\\') { c = DgetC(0); if (!any(c, "$\\`")) unDgetC(c | QUOTE), c = '\\'; else c |= QUOTE; } *mbp++ = c; if (--mcnt == 0) { setname("<<"); bferr("Line overflow"); } } *mbp++ = 0; /* * If any ` in line do command substitution */ mbp = mbuf; if (any('`', mbp)) { /* * 1 arg to dobackp causes substitution to be literal. * Words are broken only at newlines so that all blanks * and tabs are preserved. Blank lines (null words) * are not discarded. */ vp = dobackp(mbuf, 1); } else /* Setup trivial vector similar to return of dobackp */ Dv[0] = mbp, Dv[1] = NOSTR, vp = Dv; /* * Resurrect the words from the command substitution * each separated by a newline. Note that the last * newline of a command substitution will have been * discarded, but we put a newline after the last word * because this represents the newline after the last * input line! */ for (; *vp; vp++) { for (mbp = *vp; *mbp; mbp++) { *obp++ = *mbp & TRIM; if (--ocnt == 0) { (void) write(0, obuf, BUFSIZ); obp = obuf; ocnt = BUFSIZ; } } *obp++ = '\n'; if (--ocnt == 0) { (void) write(0, obuf, BUFSIZ); obp = obuf; ocnt = BUFSIZ; } } if (pargv) blkfree(pargv), pargv = 0; } } '`': /* We preserve ` quotations which are done yet later */ *wp++ = c, --i; case '\'': case '"': /* * Note that DgetC never returns a QUOTES character * from an expansion, so only true input quotes will * get us here or out. */ c1 =bin/csh/sh.dir.c 444 0 12 22601 5057637701 6741 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.dir.c 5.3 (Berkeley) 6/11/85"; #endif #include "sh.h" #include "sh.dir.h" /* * C Shell - directory management */ struct directory *dfind(); char *dfollow(); char *dcanon(); struct directory dhead; /* "head" of loop */ int printd; /* force name to be printed */ static char *fakev[] = { "dirs", NOSTR }; /* * dinit - initialize current working directory */ dinit(hp) char *hp; { register char *cp; register struct directory *dp; char path[MAXPATHLEN]; if (loginsh && hp) cp = hp; else { cp = getwd(path); if (cp == NULL) { (void) write(2, path, strlen(path)); exit(1); } } dp = (struct directory *)calloc(sizeof (struct directory), 1); dp->di_name = savestr(cp); dp->di_count = 0; dhead.di_next = dhead.di_prev = dp; dp->di_next = dp->di_prev = &dhead; printd = 0; dnewcwd(dp); } /* * dodirs - list all directories in directory loop */ dodirs(v) char **v; { register struct directory *dp; bool lflag; char *hp = value("home"); if (*hp == '\0') hp = NOSTR; if (*++v != NOSTR) if (eq(*v, "-l") && *++v == NOSTR) lflag = 1; else error("Usage: dirs [ -l ]"); else lflag = 0; dp = dcwd; do { if (dp == &dhead) continue; if (!lflag && hp != NOSTR) { dtildepr(hp, dp->di_name); } else printf("%s", dp->di_name); printf(" "); } while ((dp = dp->di_prev) != dcwd); printf("\n"); } dtildepr(home, dir) register char *home, *dir; { if (!eq(home, "/") && prefix(home, dir)) printf("~%s", dir + strlen(home)); else printf("%s", dir); } /* * dochngd - implement chdir command. */ dochngd(v) char **v; { register char *cp; register struct directory *dp; printd = 0; if (*++v == NOSTR) { if ((cp = value("home")) == NOSTR || *cp == 0) bferr("No home directory"); if (chdir(cp) < 0) bferr("Can't change to home directory"); cp = savestr(cp); } else if ((dp = dfind(*v)) != 0) { printd = 1; if (chdir(dp->di_name) < 0) Perror(dp->di_name); dcwd->di_prev->di_next = dcwd->di_next; dcwd->di_next->di_prev = dcwd->di_prev; goto flushcwd; } else cp = dfollow(*v); dp = (struct directory *)calloc(sizeof (struct directory), 1); dp->di_name = cp; dp->di_count = 0; dp->di_next = dcwd->di_next; dp->di_prev = dcwd->di_prev; dp->di_prev->di_next = dp; dp->di_next->di_prev = dp; flushcwd: dfree(dcwd); dnewcwd(dp); } /* * dfollow - change to arg directory; fall back on cdpath if not valid */ char * dfollow(cp) register char *cp; { register char *dp; struct varent *c; cp = globone(cp); if (chdir(cp) >= 0) goto gotcha; if (cp[0] != '/' && !prefix("./", cp) && !prefix("../", cp) && (c = adrof("cdpath"))) { char **cdp; register char *p; char buf[MAXPATHLEN]; for (cdp = c->vec; *cdp; cdp++) { for (dp = buf, p = *cdp; *dp++ = *p++;) ; dp[-1] = '/'; for (p = cp; *dp++ = *p++;) ; if (chdir(buf) >= 0) { printd = 1; xfree(cp); cp = savestr(buf); goto gotcha; } } } dp = value(cp); if ((dp[0] == '/' || dp[0] == '.') && chdir(dp) >= 0) { xfree(cp); cp = savestr(dp); printd = 1; goto gotcha; } xfree(cp); /* XXX, use after free */ Perror(cp); gotcha: if (*cp != '/') { register char *p, *q; int cwdlen; /* * All in the name of efficiency? */ for (p = dcwd->di_name; *p++;) ; if ((cwdlen = p - dcwd->di_name - 1) == 1) /* root */ cwdlen = 0; for (p = cp; *p++;) ; dp = xalloc((unsigned) (cwdlen + (p - cp) + 1)); for (p = dp, q = dcwd->di_name; *p++ = *q++;) ; if (cwdlen) p[-1] = '/'; else p--; /* don't add a / after root */ for (q = cp; *p++ = *q++;) ; xfree(cp); cp = dp; dp += cwdlen; } else dp = cp; return dcanon(cp, dp); } /* * dopushd - push new directory onto directory stack. * with no arguments exchange top and second. * with numeric argument (+n) bring it to top. */ dopushd(v) char **v; { register struct directory *dp; printd = 1; if (*++v == NOSTR) { if ((dp = dcwd->di_prev) == &dhead) dp = dhead.di_prev; if (dp == dcwd) bferr("No other directory"); if (chdir(dp->di_name) < 0) Perror(dp->di_name); dp->di_prev->di_next = dp->di_next; dp->di_next->di_prev = dp->di_prev; dp->di_next = dcwd->di_next; dp->di_prev = dcwd; dcwd->di_next->di_prev = dp; dcwd->di_next = dp; } else if (dp = dfind(*v)) { if (chdir(dp->di_name) < 0) Perror(dp->di_name); } else { register char *cp; cp = dfollow(*v); dp = (struct directory *)calloc(sizeof (struct directory), 1); dp->di_name = cp; dp->di_count = 0; dp->di_prev = dcwd; dp->di_next = dcwd->di_next; dcwd->di_next = dp; dp->di_next->di_prev = dp; } dnewcwd(dp); } /* * dfind - find a directory if specified by numeric (+n) argument */ struct directory * dfind(cp) register char *cp; { register struct directory *dp; register int i; register char *ep; if (*cp++ != '+') return (0); for (ep = cp; digit(*ep); ep++) continue; if (*ep) return (0); i = getn(cp); if (i <= 0) return (0); for (dp = dcwd; i != 0; i--) { if ((dp = dp->di_prev) == &dhead) dp = dp->di_prev; if (dp == dcwd) bferr("Directory stack not that deep"); } return (dp); } /* * dopopd - pop a directory out of the directory stack * with a numeric argument just discard it. */ dopopd(v) char **v; { register struct directory *dp, *p; printd = 1; if (*++v == NOSTR) dp = dcwd; else if ((dp = dfind(*v)) == 0) bferr("Bad directory"); if (dp->di_prev == &dhead && dp->di_next == &dhead) bferr("Directory stack empty"); if (dp == dcwd) { if ((p = dp->di_prev) == &dhead) p = dhead.di_prev; if (chdir(p->di_name) < 0) Perror(p->di_name); } dp->di_prev->di_next = dp->di_next; dp->di_next->di_prev = dp->di_prev; if (dp == dcwd) dnewcwd(p); else dodirs(fakev); dfree(dp); } /* * dfree - free the directory (or keep it if it still has ref count) */ dfree(dp) register struct directory *dp; { if (dp->di_count != 0) dp->di_next = dp->di_prev = 0; else xfree(dp->di_name), xfree((char *)dp); } /* * dcanon - canonicalize the pathname, removing excess ./ and ../ etc. * we are of course assuming that the file system is standardly * constructed (always have ..'s, directories have links) */ char * dcanon(cp, p) register char *cp, *p; { register char *sp; register char *p1, *p2; /* general purpose */ bool slash; if (*cp != '/') abort(); while (*p) { /* for each component */ sp = p; /* save slash address */ while (*++p == '/') /* flush extra slashes */ ; if (p != ++sp) for (p1 = sp, p2 = p; *p1++ = *p2++;) ; p = sp; /* save start of component */ slash = 0; while (*++p) /* find next slash or end of path */ if (*p == '/') { slash = 1; *p = 0; break; } if (*sp == '\0') /* if component is null */ if (--sp == cp) /* if path is one char (i.e. /) */ break; else *sp = '\0'; else if (sp[0] == '.' && sp[1] == 0) { if (slash) { for (p1 = sp, p2 = p + 1; *p1++ = *p2++;) ; p = --sp; } else if (--sp != cp) *sp = '\0'; } else if (sp[0] == '.' && sp[1] == '.' && sp[2] == 0) { char link[MAXPATHLEN]; int cc; char *newcp; /* * We have something like "yyy/xxx/..", where "yyy" * can be null or a path starting at /, and "xxx" * is a single component. * Before compressing "xxx/..", we want to expand * "yyy/xxx", if it is a symbolic link. */ *--sp = 0; /* form the pathname for readlink */ if (sp != cp && (cc = readlink(cp, link, sizeof link)) >= 0) { link[cc] = '\0'; if (slash) *p = '/'; /* * Point p to the '/' in "/..", and restore * the '/'. */ *(p = sp) = '/'; /* * find length of p */ for (p1 = p; *p1++;) ; if (*link != '/') { /* * Relative path, expand it between * the "yyy/" and the "/..". * First, back sp up to the character * past "yyy/". */ while (*--sp != '/') ; sp++; *sp = 0; /* * New length is * "yyy/" + link + "/.." and rest */ p1 = newcp = xalloc((unsigned) ((sp - cp) + cc + (p1 - p))); /* * Copy new path into newcp */ for (p2 = cp; *p1++ = *p2++;) ; for (p1--, p2 = link; *p1++ = *p2++;) ; for (p1--, p2 = p; *p1++ = *p2++;) ; /* * Restart canonicalization at * expanded "/xxx". */ p = sp - cp - 1 + newcp; } else { /* * New length is link + "/.." and rest */ p1 = newcp = xalloc((unsigned) (cc + (p1 - p))); /* * Copy new path into newcp */ for (p2 = link; *p1++ = *p2++;) ; for (p1--, p2 = p; *p1++ = *p2++;) ; /* * Restart canonicalization at beginning */ p = newcp; } xfree(cp); cp = newcp; continue; /* canonicalize the link */ } *sp = '/'; if (sp != cp) while (*--sp != '/') ; if (slash) { for (p1 = sp + 1, p2 = p + 1; *p1++ = *p2++;) ; p = sp; } else if (cp == sp) *++sp = '\0'; else *sp = '\0'; } else if (slash) *p = '/'; } return cp; } /* * dnewcwd - make a new directory in the loop the current one */ dnewcwd(dp) register struct directory *dp; { dcwd = dp; set("cwd", savestr(dcwd->di_name)); if (printd) dodirs(fakev); } do { if (dp == &dhead) continue; if (!lflag && hp != NOSTR) { dtildepr(hp, dp->di_name); } else printf("%s", dbin/csh/sh.lex.c 444 0 12 53153 5057640266 6761 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.lex.c 5.4 (Berkeley) 3/29/86"; #endif #include "sh.h" #include /* * C shell */ /* * These lexical routines read input and form lists of words. * There is some involved processing here, because of the complications * of input buffering, and especially because of history substitution. */ char *word(); /* * Peekc is a peek characer for getC, peekread for readc. * There is a subtlety here in many places... history routines * will read ahead and then insert stuff into the input stream. * If they push back a character then they must push it behind * the text substituted by the history substitution. On the other * hand in several places we need 2 peek characters. To make this * all work, the history routines read with getC, and make use both * of ungetC and unreadc. The key observation is that the state * of getC at the call of a history reference is such that calls * to getC from the history routines will always yield calls of * readc, unless this peeking is involved. That is to say that during * getexcl the variables lap, exclp, and exclnxt are all zero. * * Getdol invokes history substitution, hence the extra peek, peekd, * which it can ungetD to be before history substitutions. */ char peekc, peekd; char peekread; char *exclp; /* (Tail of) current word from ! subst */ struct wordent *exclnxt; /* The rest of the ! subst words */ int exclc; /* Count of remainig words in ! subst */ char *alvecp; /* "Globp" for alias resubstitution */ /* * Lex returns to its caller not only a wordlist (as a "var" parameter) * but also whether a history substitution occurred. This is used in * the main (process) routine to determine whether to echo, and also * when called by the alias routine to determine whether to keep the * argument list. */ bool hadhist; char getCtmp; #define getC(f) ((getCtmp = peekc) ? (peekc = 0, getCtmp) : getC1(f)) #define ungetC(c) peekc = c #define ungetD(c) peekd = c lex(hp) register struct wordent *hp; { register struct wordent *wdp; int c; lineloc = btell(); hp->next = hp->prev = hp; hp->word = ""; alvecp = 0, hadhist = 0; do c = readc(0); while (c == ' ' || c == '\t'); if (c == HISTSUB && intty) /* ^lef^rit from tty is short !:s^lef^rit */ getexcl(c); else unreadc(c); wdp = hp; /* * The following loop is written so that the links needed * by freelex will be ready and rarin to go even if it is * interrupted. */ do { register struct wordent *new = (struct wordent *) xalloc(sizeof *wdp); new->word = 0; new->prev = wdp; new->next = hp; wdp->next = new; wdp = new; wdp->word = word(); } while (wdp->word[0] != '\n'); hp->prev = wdp; return (hadhist); } prlex(sp0) struct wordent *sp0; { register struct wordent *sp = sp0->next; for (;;) { printf("%s", sp->word); sp = sp->next; if (sp == sp0) break; if (sp->word[0] != '\n') putchar(' '); } } copylex(hp, fp) register struct wordent *hp; register struct wordent *fp; { register struct wordent *wdp; wdp = hp; fp = fp->next; do { register struct wordent *new = (struct wordent *) xalloc(sizeof *wdp); new->prev = wdp; new->next = hp; wdp->next = new; wdp = new; wdp->word = savestr(fp->word); fp = fp->next; } while (wdp->word[0] != '\n'); hp->prev = wdp; } freelex(vp) register struct wordent *vp; { register struct wordent *fp; while (vp->next != vp) { fp = vp->next; vp->next = fp->next; XFREE(fp->word) XFREE((char *)fp) } vp->prev = vp; } char * word() { register char c, c1; register char *wp; char wbuf[BUFSIZ]; register bool dolflg; register int i; wp = wbuf; i = BUFSIZ - 4; loop: while ((c = getC(DOALL)) == ' ' || c == '\t') ; if (cmap(c, _META|_ESC)) switch (c) { case '&': case '|': case '<': case '>': *wp++ = c; c1 = getC(DOALL); if (c1 == c) *wp++ = c1; else ungetC(c1); goto ret; case '#': if (intty) break; c = 0; do { c1 = c; c = getC(0); } while (c != '\n'); if (c1 == '\\') goto loop; /* fall into ... */ case ';': case '(': case ')': case '\n': *wp++ = c; goto ret; case '\\': c = getC(0); if (c == '\n') { if (onelflg == 1) onelflg = 2; goto loop; } if (c != HIST) *wp++ = '\\', --i; c |= QUOTE; } c1 = 0; dolflg = DOALL; for (;;) { if (c1) { if (c == c1) { c1 = 0; dolflg = DOALL; } else if (c == '\\') { c = getC(0); if (c == HIST) c |= QUOTE; else { if (c == '\n') /* if (c1 == '`') c = ' '; else */ c |= QUOTE; ungetC(c); c = '\\'; } } else if (c == '\n') { seterrc("Unmatched ", c1); ungetC(c); break; } } else if (cmap(c, _META|_Q|_Q1|_ESC)) { if (c == '\\') { c = getC(0); if (c == '\n') { if (onelflg == 1) onelflg = 2; break; } if (c != HIST) *wp++ = '\\', --i; c |= QUOTE; } else if (cmap(c, _Q|_Q1)) { /* '"` */ c1 = c; dolflg = c == '"' ? DOALL : DOEXCL; } else if (c != '#' || !intty) { ungetC(c); break; } } if (--i > 0) { *wp++ = c; c = getC(dolflg); } else { seterr("Word too long"); wp = &wbuf[1]; break; } } ret: *wp = 0; return (savestr(wbuf)); } getC1(flag) register int flag; { register char c; top: if (c = peekc) { peekc = 0; return (c); } if (lap) { if ((c = *lap++) == 0) lap = 0; else { if (cmap(c, _META|_Q|_Q1)) c |= QUOTE; return (c); } } if (c = peekd) { peekd = 0; return (c); } if (exclp) { if (c = *exclp++) return (c); if (exclnxt && --exclc >= 0) { exclnxt = exclnxt->next; setexclp(exclnxt->word); return (' '); } exclp = 0; exclnxt = 0; } if (exclnxt) { exclnxt = exclnxt->next; if (--exclc < 0) exclnxt = 0; else setexclp(exclnxt->word); goto top; } c = readc(0); if (c == '$' && (flag & DODOL)) { getdol(); goto top; } if (c == HIST && (flag & DOEXCL)) { getexcl(0); goto top; } return (c); } getdol() { register char *np; char name[40]; register int c; int sc; bool special = 0; np = name, *np++ = '$'; c = sc = getC(DOEXCL); if (any(c, "\t \n")) { ungetD(c); ungetC('$' | QUOTE); return; } if (c == '{') *np++ = c, c = getC(DOEXCL); if (c == '#' || c == '?') special++, *np++ = c, c = getC(DOEXCL); *np++ = c; switch (c) { case '<': case '$': if (special) goto vsyn; goto ret; case '\n': ungetD(c); np--; goto vsyn; case '*': if (special) goto vsyn; goto ret; default: if (digit(c)) { /* * let $?0 pass for now if (special) goto vsyn; */ while (digit(c = getC(DOEXCL))) { if (np < &name[sizeof name / 2]) *np++ = c; } } else if (letter(c)) while (letter(c = getC(DOEXCL))) { if (np < &name[sizeof name / 2]) *np++ = c; } else goto vsyn; } if (c == '[') { *np++ = c; do { c = getC(DOEXCL); if (c == '\n') { ungetD(c); np--; goto vsyn; } if (np >= &name[sizeof name - 8]) goto vsyn; *np++ = c; } while (c != ']'); c = getC(DOEXCL); } if (c == ':') { *np++ = c, c = getC(DOEXCL); if (c == 'g') *np++ = c, c = getC(DOEXCL); *np++ = c; if (!any(c, "htrqxe")) goto vsyn; } else ungetD(c); if (sc == '{') { c = getC(DOEXCL); if (c != '}') { ungetC(c); goto vsyn; } *np++ = c; } ret: *np = 0; addla(name); return; vsyn: seterr("Variable syntax"); goto ret; } addla(cp) char *cp; { char buf[BUFSIZ]; if (lap != 0 && strlen(cp) + strlen(lap) >= sizeof (labuf) - 4) { seterr("Expansion buf ovflo"); return; } if (lap) (void) strcpy(buf, lap); (void) strcpy(labuf, cp); if (lap) (void) strcat(labuf, buf); lap = labuf; } char lhsb[32]; char slhs[32]; char rhsb[64]; int quesarg; getexcl(sc) char sc; { register struct wordent *hp, *ip; int left, right, dol; register int c; if (sc == 0) { sc = getC(0); if (sc != '{') { ungetC(sc); sc = 0; } } quesarg = -1; lastev = eventno; hp = gethent(sc); if (hp == 0) return; hadhist = 1; dol = 0; if (hp == alhistp) for (ip = hp->next->next; ip != alhistt; ip = ip->next) dol++; else for (ip = hp->next->next; ip != hp->prev; ip = ip->next) dol++; left = 0, right = dol; if (sc == HISTSUB) { ungetC('s'), unreadc(HISTSUB), c = ':'; goto subst; } c = getC(0); if (!any(c, ":^$*-%")) goto subst; left = right = -1; if (c == ':') { c = getC(0); unreadc(c); if (letter(c) || c == '&') { c = ':'; left = 0, right = dol; goto subst; } } else ungetC(c); if (!getsel(&left, &right, dol)) return; c = getC(0); if (c == '*') ungetC(c), c = '-'; if (c == '-') { if (!getsel(&left, &right, dol)) return; c = getC(0); } subst: exclc = right - left + 1; while (--left >= 0) hp = hp->next; if (sc == HISTSUB || c == ':') { do { hp = getsub(hp); c = getC(0); } while (c == ':'); } unreadc(c); if (sc == '{') { c = getC(0); if (c != '}') seterr("Bad ! form"); } exclnxt = hp; } struct wordent * getsub(en) struct wordent *en; { register char *cp; int delim; register int c; int sc; bool global = 0; char orhsb[sizeof rhsb]; exclnxt = 0; sc = c = getC(0); if (c == 'g') global++, c = getC(0); switch (c) { case 'p': justpr++; goto ret; case 'x': case 'q': global++; /* fall into ... */ case 'h': case 'r': case 't': case 'e': break; case '&': if (slhs[0] == 0) { seterr("No prev sub"); goto ret; } (void) strcpy(lhsb, slhs); break; /* case '~': if (lhsb[0] == 0) goto badlhs; break; */ case 's': delim = getC(0); if (letter(delim) || digit(delim) || any(delim, " \t\n")) { unreadc(delim); bads: lhsb[0] = 0; seterr("Bad substitute"); goto ret; } cp = lhsb; for (;;) { c = getC(0); if (c == '\n') { unreadc(c); break; } if (c == delim) break; if (cp > &lhsb[sizeof lhsb - 2]) goto bads; if (c == '\\') { c = getC(0); if (c != delim && c != '\\') *cp++ = '\\'; } *cp++ = c; } if (cp != lhsb) *cp++ = 0; else if (lhsb[0] == 0) { /*badlhs:*/ seterr("No prev lhs"); goto ret; } cp = rhsb; (void) strcpy(orhsb, cp); for (;;) { c = getC(0); if (c == '\n') { unreadc(c); break; } if (c == delim) break; /* if (c == '~') { if (&cp[strlen(orhsb)] > &rhsb[sizeof rhsb - 2]) goto toorhs; (void) strcpy(cp, orhsb); cp = strend(cp); continue; } */ if (cp > &rhsb[sizeof rhsb - 2]) { /*toorhs:*/ seterr("Rhs too long"); goto ret; } if (c == '\\') { c = getC(0); if (c != delim /* && c != '~' */) *cp++ = '\\'; } *cp++ = c; } *cp++ = 0; break; default: if (c == '\n') unreadc(c); seterrc("Bad ! modifier: ", c); goto ret; } (void) strcpy(slhs, lhsb); if (exclc) en = dosub(sc, en, global); ret: return (en); } struct wordent * dosub(sc, en, global) int sc; struct wordent *en; bool global; { struct wordent lex; bool didsub = 0; struct wordent *hp = &lex; register struct wordent *wdp; register int i = exclc; wdp = hp; while (--i >= 0) { register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp); new->prev = wdp; new->next = hp; wdp->next = new; wdp = new; en = en->next; wdp->word = global || didsub == 0 ? subword(en->word, sc, &didsub) : savestr(en->word); } if (didsub == 0) seterr("Modifier failed"); hp->prev = wdp; return (&enthist(-1000, &lex, 0)->Hlex); } char * subword(cp, type, adid) char *cp; int type; bool *adid; { char wbuf[BUFSIZ]; register char *wp, *mp, *np; register int i; switch (type) { case 'r': case 'e': case 'h': case 't': case 'q': case 'x': wp = domod(cp, type); if (wp == 0) return (savestr(cp)); *adid = 1; return (wp); default: wp = wbuf; i = BUFSIZ - 4; for (mp = cp; *mp; mp++) if (matchs(mp, lhsb)) { for (np = cp; np < mp;) *wp++ = *np++, --i; for (np = rhsb; *np; np++) switch (*np) { case '\\': if (np[1] == '&') np++; /* fall into ... */ default: if (--i < 0) goto ovflo; *wp++ = *np; continue; case '&': i -= strlen(lhsb); if (i < 0) goto ovflo; *wp = 0; (void) strcat(wp, lhsb); wp = strend(wp); continue; } mp += strlen(lhsb); i -= strlen(mp); if (i < 0) { ovflo: seterr("Subst buf ovflo"); return (""); } *wp = 0; (void) strcat(wp, mp); *adid = 1; return (savestr(wbuf)); } return (savestr(cp)); } } char * domod(cp, type) char *cp; int type; { register char *wp, *xp; register int c; switch (type) { case 'x': case 'q': wp = savestr(cp); for (xp = wp; c = *xp; xp++) if ((c != ' ' && c != '\t') || type == 'q') *xp |= QUOTE; return (wp); case 'h': case 't': if (!any('/', cp)) return (type == 't' ? savestr(cp) : 0); wp = strend(cp); while (*--wp != '/') continue; if (type == 'h') xp = savestr(cp), xp[wp - cp] = 0; else xp = savestr(wp + 1); return (xp); case 'e': case 'r': wp = strend(cp); for (wp--; wp >= cp && *wp != '/'; wp--) if (*wp == '.') { if (type == 'e') xp = savestr(wp + 1); else xp = savestr(cp), xp[wp - cp] = 0; return (xp); } return (savestr(type == 'e' ? "" : cp)); } return (0); } matchs(str, pat) register char *str, *pat; { while (*str && *pat && *str == *pat) str++, pat++; return (*pat == 0); } getsel(al, ar, dol) register int *al, *ar; int dol; { register int c = getC(0); register int i; bool first = *al < 0; switch (c) { case '%': if (quesarg == -1) goto bad; if (*al < 0) *al = quesarg; *ar = quesarg; break; case '-': if (*al < 0) { *al = 0; *ar = dol - 1; unreadc(c); } return (1); case '^': if (*al < 0) *al = 1; *ar = 1; break; case '$': if (*al < 0) *al = dol; *ar = dol; break; case '*': if (*al < 0) *al = 1; *ar = dol; if (*ar < *al) { *ar = 0; *al = 1; return (1); } break; default: if (digit(c)) { i = 0; while (digit(c)) { i = i * 10 + c - '0'; c = getC(0); } if (i < 0) i = dol + 1; if (*al < 0) *al = i; *ar = i; } else if (*al < 0) *al = 0, *ar = dol; else *ar = dol - 1; unreadc(c); break; } if (first) { c = getC(0); unreadc(c); if (any(c, "-$*")) return (1); } if (*al > *ar || *ar > dol) { bad: seterr("Bad ! arg selector"); return (0); } return (1); } struct wordent * gethent(sc) int sc; { register struct Hist *hp; register char *np; register int c; int event; bool back = 0; c = sc == HISTSUB ? HIST : getC(0); if (c == HIST) { if (alhistp) return (alhistp); event = eventno; goto skip; } switch (c) { case ':': case '^': case '$': case '*': case '%': ungetC(c); if (lastev == eventno && alhistp) return (alhistp); event = lastev; break; case '-': back = 1; c = getC(0); goto number; case '#': /* !# is command being typed in (mrh) */ return(¶ml); default: if (any(c, "(=~")) { unreadc(c); ungetC(HIST); return (0); } if (digit(c)) goto number; np = lhsb; while (!any(c, ": \t\\\n}")) { if (np < &lhsb[sizeof lhsb - 2]) *np++ = c; c = getC(0); } unreadc(c); if (np == lhsb) { ungetC(HIST); return (0); } *np++ = 0; hp = findev(lhsb, 0); if (hp) lastev = hp->Hnum; return (&hp->Hlex); case '?': np = lhsb; for (;;) { c = getC(0); if (c == '\n') { unreadc(c); break; } if (c == '?') break; if (np < &lhsb[sizeof lhsb - 2]) *np++ = c; } if (np == lhsb) { if (lhsb[0] == 0) { seterr("No prev search"); return (0); } } else *np++ = 0; hp = findev(lhsb, 1); if (hp) lastev = hp->Hnum; return (&hp->Hlex); number: event = 0; while (digit(c)) { event = event * 10 + c - '0'; c = getC(0); } if (back) event = eventno + (alhistp == 0) - (event ? event : 0); unreadc(c); break; } skip: for (hp = Histlist.Hnext; hp; hp = hp->Hnext) if (hp->Hnum == event) { hp->Href = eventno; lastev = hp->Hnum; return (&hp->Hlex); } np = putn(event); noev(np); return (0); } struct Hist * findev(cp, anyarg) char *cp; bool anyarg; { register struct Hist *hp; for (hp = Histlist.Hnext; hp; hp = hp->Hnext) { char *dp; register char *p, *q; register struct wordent *lp = hp->Hlex.next; int argno = 0; if (lp->word[0] == '\n') continue; if (!anyarg) { p = cp; q = lp->word; do if (!*p) return (hp); while (*p++ == *q++); continue; } do { for (dp = lp->word; *dp; dp++) { p = cp; q = dp; do if (!*p) { quesarg = argno; return (hp); } while (*p++ == *q++); } lp = lp->next; argno++; } while (lp->word[0] != '\n'); } noev(cp); return (0); } noev(cp) char *cp; { seterr2(cp, ": Event not found"); } setexclp(cp) register char *cp; { if (cp && cp[0] == '\n') return; exclp = cp; } unreadc(c) char c; { peekread = c; } readc(wanteof) bool wanteof; { register int c; static sincereal; if (c = peekread) { peekread = 0; return (c); } top: if (alvecp) { if (c = *alvecp++) return (c); if (*alvec) { alvecp = *alvec++; return (' '); } } if (alvec) { if (alvecp = *alvec) { alvec++; goto top; } /* Infinite source! */ return ('\n'); } if (evalp) { if (c = *evalp++) return (c); if (*evalvec) { evalp = *evalvec++; return (' '); } evalp = 0; } if (evalvec) { if (evalvec == (char **)1) { doneinp = 1; reset(); } if (evalp = *evalvec) { evalvec++; goto top; } evalvec = (char **)1; return ('\n'); } do { if (arginp == (char *) 1 || onelflg == 1) { if (wanteof) return (-1); exitstat(); } if (arginp) { if ((c = *arginp++) == 0) { arginp = (char *) 1; return ('\n'); } return (c); } reread: c = bgetc(); if (c < 0) { struct sgttyb tty; if (wanteof) return (-1); /* was isatty but raw with ignoreeof yields problems */ if (ioctl(SHIN, TIOCGETP, (char *)&tty) == 0 && (tty.sg_flags & RAW) == 0) { /* was 'short' for FILEC */ int ctpgrp; if (++sincereal > 25) goto oops; if (tpgrp != -1 && ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp) == 0 && tpgrp != ctpgrp) { (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp); (void) killpg(ctpgrp, SIGHUP); printf("Reset tty pgrp from %d to %d\n", ctpgrp, tpgrp); goto reread; } if (adrof("ignoreeof")) { if (loginsh) printf("\nUse \"logout\" to logout.\n"); else printf("\nUse \"exit\" to leave csh.\n"); reset(); } if (chkstop == 0) panystop(1); } oops: doneinp = 1; reset(); } sincereal = 0; if (c == '\n' && onelflg) onelflg--; } while (c == 0); return (c); } bgetc() { register int buf, off, c; #ifdef FILEC char ttyline[BUFSIZ]; register int numleft = 0, roomleft; #endif #ifdef TELL if (cantell) { if (fseekp < fbobp || fseekp > feobp) { fbobp = feobp = fseekp; (void) lseek(SHIN, fseekp, 0); } if (fseekp == feobp) { fbobp = feobp; do c = read(SHIN, fbuf[0], BUFSIZ); while (c < 0 && errno == EINTR); if (c <= 0) return (-1); feobp += c; } c = fbuf[0][fseekp - fbobp]; fseekp++; return (c & 0377); } #endif again: buf = (int) fseekp / BUFSIZ; if (buf >= fblocks) { register char **nfbuf = (char **) calloc((unsigned) (fblocks + 2), sizeof (char **)); if (fbuf) { (void) blkcpy(nfbuf, fbuf); xfree((char *)fbuf); } fbuf = nfbuf; fbuf[fblocks] = calloc(BUFSIZ, sizeof (char)); fblocks++; goto again; } if (fseekp >= feobp) { buf = (int) feobp / BUFSIZ; off = (int) feobp % BUFSIZ; #ifndef FILEC for (;;) { c = read(SHIN, fbuf[buf] + off, BUFSIZ - off); #else roomleft = BUFSIZ - off; for (;;) { if (filec && intty) { c = numleft ? numleft : tenex(ttyline, BUFSIZ); if (c > roomleft) { /* start with fresh buffer */ feobp = fseekp = fblocks * BUFSIZ; numleft = c; goto again; } if (c > 0) copy(fbuf[buf] + off, ttyline, c); numleft = 0; } else c = read(SHIN, fbuf[buf] + off, roomleft); #endif if (c >= 0) break; if (errno == EWOULDBLOCK) { int off = 0; (void) ioctl(SHIN, FIONBIO, (char *)&off); } else if (errno != EINTR) break; } if (c <= 0) return (-1); feobp += c; #ifndef FILEC goto again; #else if (filec && !intty) goto again; #endif } c = fbuf[buf][(int) fseekp % BUFSIZ]; fseekp++; return (c & 0377); } bfree() { register int sb, i; #ifdef TELL if (cantell) return; #endif if (whyles) return; sb = (int) (fseekp - 1) / BUFSIZ; if (sb > 0) { for (i = 0; i < sb; i++) xfree(fbuf[i]); (void) blkcpy(fbuf, &fbuf[sb]); fseekp -= BUFSIZ * sb; feobp -= BUFSIZ * sb; fblocks -= sb; } } bseek(l) off_t l; { register struct whyle *wp; fseekp = l; #ifdef TELL if (!cantell) { #endif if (!whyles) return; for (wp = whyles; wp->w_next; wp = wp->w_next) continue; if (wp->w_start > l) l = wp->w_start; #ifdef TELL } #endif } /* any similarity to bell telephone is purely accidental */ #ifndef btell off_t btell() { return (fseekp); } #endif btoeof() { (void) lseek(SHIN, (off_t)0, 2); fseekp = feobp; wfree(); bfree(); } #ifdef TELL settell() { cantell = 0; if (arginp || onelflg || intty) return; if (lseek(SHIN, (off_t)0, 1) < 0 || errno == ESPIPE) return; fbuf = (char **) calloc(2, sizeof (char **)); fblocks = 1; fbuf[0] = calloc(BUFSIZ, sizeof (char)); fseekp = fbobp = feobp = lseek(SHIN, (off_t)0, 1); cantell = 1; } #endif ool *adid; { char wbuf[BUFSIZ]; register char *wp, *mp, *np; register int i; switch (type) { case 'r': case 'e': case 'h': case 't': case 'q': case 'x': wp = domod(cp, type); if (wp == 0) return (savestr(cp)); *adid = 1; return (wp); default: wp = wbuf; i = BUFSIZ - 4; for (mp = cp; *mp; mp++) if (matchs(mp, lhsb)) { for (np = cp; np < mp;) *wp++ = *np++, --i;bin/csh/sh.func.c 444 0 12 45127 5057640102 7113 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)sh.func.c 5.3 (Berkeley) 5/13/86"; #endif #include "sh.h" #include /* * C shell */ struct biltins * isbfunc(t) struct command *t; { register char *cp = t->t_dcom[0]; register struct biltins *bp, *bp1, *bp2; int dolabel(), dofg1(), dobg1(); static struct biltins label = { "", dolabel, 0, 0 }; static struct biltins foregnd = { "%job", dofg1, 0, 0 }; static struct biltins backgnd = { "%job &", dobg1, 0, 0 }; if (lastchr(cp) == ':') { label.bname = cp; return (&label); } if (*cp == '%') { if (t->t_dflg & FAND) { t->t_dflg &= ~FAND; backgnd.bname = cp; return (&backgnd); } foregnd.bname = cp; return (&foregnd); } /* * Binary search * Bp1 is the beginning of the current search range. * Bp2 is one past the end. */ for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { register i; bp = bp1 + (bp2 - bp1 >> 1); if ((i = *cp - *bp->bname) == 0 && (i = strcmp(cp, bp->bname)) == 0) return bp; if (i < 0) bp2 = bp; else bp1 = bp + 1; } return (0); } func(t, bp) register struct command *t; register struct biltins *bp; { int i; xechoit(t->t_dcom); setname(bp->bname); i = blklen(t->t_dcom) - 1; if (i < bp->minargs) bferr("Too few arguments"); if (i > bp->maxargs) bferr("Too many arguments"); (*bp->bfunct)(t->t_dcom, t); } dolabel() { } doonintr(v) char **v; { register char *cp; register char *vv = v[1]; if (parintr == SIG_IGN) return; if (setintr && intty) bferr("Can't from terminal"); cp = gointr, gointr = 0, xfree(cp); if (vv == 0) { if (setintr) (void) sigblock(sigmask(SIGINT)); else (void) signal(SIGINT, SIG_DFL); gointr = 0; } else if (eq((vv = strip(vv)), "-")) { (void) signal(SIGINT, SIG_IGN); gointr = "-"; } else { gointr = savestr(vv); (void) signal(SIGINT, pintr); } } donohup() { if (intty) bferr("Can't from terminal"); if (setintr == 0) { (void) signal(SIGHUP, SIG_IGN); #ifdef CC submit(getpid()); #endif } } dozip() { ; } prvars() { plist(&shvhed); } doalias(v) register char **v; { register struct varent *vp; register char *p; v++; p = *v++; if (p == 0) plist(&aliases); else if (*v == 0) { vp = adrof1(strip(p), &aliases); if (vp) blkpr(vp->vec), printf("\n"); } else { if (eq(p, "alias") || eq(p, "unalias")) { setname(p); bferr("Too dangerous to alias that"); } set1(strip(p), saveblk(v), &aliases); } } unalias(v) char **v; { unset1(v, &aliases); } dologout() { islogin(); goodbye(); } dologin(v) char **v; { islogin(); rechist(); (void) signal(SIGTERM, parterm); execl("/bin/login", "login", v[1], 0); untty(); exit(1); } #ifdef NEWGRP donewgrp(v) char **v; { if (chkstop == 0 && setintr) panystop(0); (void) signal(SIGTERM, parterm); execl("/bin/newgrp", "newgrp", v[1], 0); execl("/usr/bin/newgrp", "newgrp", v[1], 0); untty(); exit(1); } #endif islogin() { if (chkstop == 0 && setintr) panystop(0); if (loginsh) return; error("Not login shell"); } doif(v, kp) char **v; struct command *kp; { register int i; register char **vv; v++; i = exp(&v); vv = v; if (*vv == NOSTR) bferr("Empty if"); if (eq(*vv, "then")) { if (*++vv) bferr("Improper then"); setname("then"); /* * If expression was zero, then scan to else, * otherwise just fall into following code. */ if (!i) search(ZIF, 0); return; } /* * Simple command attached to this if. * Left shift the node in this tree, munging it * so we can reexecute it. */ if (i) { lshift(kp->t_dcom, vv - kp->t_dcom); reexecute(kp); donefds(); } } /* * Reexecute a command, being careful not * to redo i/o redirection, which is already set up. */ reexecute(kp) register struct command *kp; { kp->t_dflg &= FSAVE; kp->t_dflg |= FREDO; /* * If tty is still ours to arbitrate, arbitrate it; * otherwise dont even set pgrp's as the jobs would * then have no way to get the tty (we can't give it * to them, and our parent wouldn't know their pgrp, etc. */ execute(kp, tpgrp > 0 ? tpgrp : -1); } doelse() { search(ZELSE, 0); } dogoto(v) char **v; { register struct whyle *wp; char *lp; /* * While we still can, locate any unknown ends of existing loops. * This obscure code is the WORST result of the fact that we * don't really parse. */ for (wp = whyles; wp; wp = wp->w_next) if (wp->w_end == 0) { search(ZBREAK, 0); wp->w_end = btell(); } else bseek(wp->w_end); search(ZGOTO, 0, lp = globone(v[1])); xfree(lp); /* * Eliminate loops which were exited. */ wfree(); } doswitch(v) register char **v; { register char *cp, *lp; v++; if (!*v || *(*v++) != '(') goto syntax; cp = **v == ')' ? "" : *v++; if (*(*v++) != ')') v--; if (*v) syntax: error("Syntax error"); search(ZSWITCH, 0, lp = globone(cp)); xfree(lp); } dobreak() { if (whyles) toend(); else bferr("Not in while/foreach"); } doexit(v) char **v; { if (chkstop == 0) panystop(0); /* * Don't DEMAND parentheses here either. */ v++; if (*v) { set("status", putn(exp(&v))); if (*v) bferr("Expression syntax"); } btoeof(); if (intty) (void) close(SHIN); } doforeach(v) register char **v; { register char *cp; register struct whyle *nwp; v++; cp = strip(*v); while (*cp && letter(*cp)) cp++; if (*cp || strlen(*v) >= 20) bferr("Invalid variable"); cp = *v++; if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') bferr("Words not ()'ed"); v++; gflag = 0, tglob(v); v = glob(v); if (v == 0) bferr("No match"); nwp = (struct whyle *) calloc(1, sizeof *nwp); nwp->w_fe = nwp->w_fe0 = v; gargv = 0; nwp->w_start = btell(); nwp->w_fename = savestr(cp); nwp->w_next = whyles; whyles = nwp; /* * Pre-read the loop so as to be more * comprehensible to a terminal user. */ if (intty) preread(); doagain(); } dowhile(v) char **v; { register int status; register bool again = whyles != 0 && whyles->w_start == lineloc && whyles->w_fename == 0; v++; /* * Implement prereading here also, taking care not to * evaluate the expression before the loop has been read up * from a terminal. */ if (intty && !again) status = !exp0(&v, 1); else status = !exp(&v); if (*v) bferr("Expression syntax"); if (!again) { register struct whyle *nwp = (struct whyle *) calloc(1, sizeof (*nwp)); nwp->w_start = lineloc; nwp->w_end = 0; nwp->w_next = whyles; whyles = nwp; if (intty) { /* * The tty preread */ preread(); doagain(); return; } } if (status) /* We ain't gonna loop no more, no more! */ toend(); } preread() { whyles->w_end = -1; if (setintr) (void) sigsetmask(sigblock(0L) & ~sigmask(SIGINT)); search(ZBREAK, 0); if (setintr) (void) sigblock(sigmask(SIGINT)); whyles->w_end = btell(); } doend() { if (!whyles) bferr("Not in while/foreach"); whyles->w_end = btell(); doagain(); } docontin() { if (!whyles) bferr("Not in while/foreach"); doagain(); } doagain() { /* Repeating a while is simple */ if (whyles->w_fename == 0) { bseek(whyles->w_start); return; } /* * The foreach variable list actually has a spurious word * ")" at the end of the w_fe list. Thus we are at the * of the list if one word beyond this is 0. */ if (!whyles->w_fe[1]) { dobreak(); return; } set(whyles->w_fename, savestr(*whyles->w_fe++)); bseek(whyles->w_start); } dorepeat(v, kp) char **v; struct command *kp; { register int i; register long omask; i = getn(v[1]); if (setintr) omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); lshift(v, 2); while (i > 0) { if (setintr) (void) sigsetmask(omask); reexecute(kp); --i; } donefds(); if (setintr) (void) sigsetmask(omask); } doswbrk() { search(ZBRKSW, 0); } srchx(cp) register char *cp; { register struct srch *sp, *sp1, *sp2; register i; /* * Binary search * Sp1 is the beginning of the current search range. * Sp2 is one past the end. */ for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { sp = sp1 + (sp2 - sp1 >> 1); if ((i = *cp - *sp->s_name) == 0 && (i = strcmp(cp, sp->s_name)) == 0) return sp->s_value; if (i < 0) sp2 = sp; else sp1 = sp + 1; } return (-1); } char Stype; char *Sgoal; /*VARARGS2*/ search(type, level, goal) int type; register int level; char *goal; { char wordbuf[BUFSIZ]; register char *aword = wordbuf; register char *cp; Stype = type; Sgoal = goal; if (type == ZGOTO) bseek((off_t)0); do { if (intty && fseekp == feobp) printf("? "), flush(); aword[0] = 0; (void) getword(aword); switch (srchx(aword)) { case ZELSE: if (level == 0 && type == ZIF) return; break; case ZIF: while (getword(aword)) continue; if ((type == ZIF || type == ZELSE) && eq(aword, "then")) level++; break; case ZENDIF: if (type == ZIF || type == ZELSE) level--; break; case ZFOREACH: case ZWHILE: if (type == ZBREAK) level++; break; case ZEND: if (type == ZBREAK) level--; break; case ZSWITCH: if (type == ZSWITCH || type == ZBRKSW) level++; break; case ZENDSW: if (type == ZSWITCH || type == ZBRKSW) level--; break; case ZLABEL: if (type == ZGOTO && getword(aword) && eq(aword, goal)) level = -1; break; default: if (type != ZGOTO && (type != ZSWITCH || level != 0)) break; if (lastchr(aword) != ':') break; aword[strlen(aword) - 1] = 0; if (type == ZGOTO && eq(aword, goal) || type == ZSWITCH && eq(aword, "default")) level = -1; break; case ZCASE: if (type != ZSWITCH || level != 0) break; (void) getword(aword); if (lastchr(aword) == ':') aword[strlen(aword) - 1] = 0; cp = strip(Dfix1(aword)); if (Gmatch(goal, cp)) level = -1; xfree(cp); break; case ZDEFAULT: if (type == ZSWITCH && level == 0) level = -1; break; } (void) getword(NOSTR); } while (level >= 0); } getword(wp) register char *wp; { register int found = 0; register int c, d; c = readc(1); d = 0; do { while (c == ' ' || c == '\t') c = readc(1); if (c == '#') do c = readc(1); while (c >= 0 && c != '\n'); if (c < 0) goto past; if (c == '\n') { if (wp) break; return (0); } unreadc(c); found = 1; do { c = readc(1); if (c == '\\' && (c = readc(1)) == '\n') c = ' '; if (c == '\'' || c == '"') if (d == 0) d = c; else if (d == c) d = 0; if (c < 0) goto past; if (wp) *wp++ = c; } while ((d || c != ' ' && c != '\t') && c != '\n'); } while (wp == 0); unreadc(c); if (found) *--wp = 0; return (found); past: switch (Stype) { case ZIF: bferr("then/endif not found"); case ZELSE: bferr("endif not found"); case ZBRKSW: case ZSWITCH: bferr("endsw not found"); case ZBREAK: bferr("end not found"); case ZGOTO: setname(Sgoal); bferr("label not found"); } /*NOTREACHED*/ } toend() { if (whyles->w_end == 0) { search(ZBREAK, 0); whyles->w_end = btell() - 1; } else bseek(whyles->w_end); wfree(); } wfree() { long o = btell(); while (whyles) { register struct whyle *wp = whyles; register struct whyle *nwp = wp->w_next; if (o >= wp->w_start && (wp->w_end == 0 || o < wp->w_end)) break; if (wp->w_fe0) blkfree(wp->w_fe0); if (wp->w_fename) xfree(wp->w_fename); xfree((char *)wp); whyles = nwp; } } doecho(v) char **v; { echo(' ', v); } doglob(v) char **v; { echo(0, v); flush(); } echo(sep, v) char sep; register char **v; { register char *cp; int nonl = 0; if (setintr) (void) sigsetmask(sigblock(0L) & ~sigmask(SIGINT)); v++; if (*v == 0) return; gflag = 0, tglob(v); if (gflag) { v = glob(v); if (v == 0) bferr("No match"); } else trim(v); if (sep == ' ' && *v && !strcmp(*v, "-n")) nonl++, v++; while (cp = *v++) { register int c; while (c = *cp++) putchar(c | QUOTE); if (*v) putchar(sep | QUOTE); } if (sep && nonl == 0) putchar('\n'); else flush(); if (setintr) (void) sigblock(sigmask(SIGINT)); if (gargv) blkfree(gargv), gargv = 0; } char **environ; dosetenv(v) register char **v; { char *vp, *lp; v++; if ((vp = *v++) == 0) { register char **ep; if (setintr) (void) sigsetmask(sigblock(0L) & ~ sigmask(SIGINT)); for (ep = environ; *ep; ep++) printf("%s\n", *ep); return; } if ((lp = *v++) == 0) lp = ""; setenv(vp, lp = globone(lp)); if (eq(vp, "PATH")) { importpath(lp); dohash(); } xfree(lp); } dounsetenv(v) register char **v; { v++; do unsetenv(*v++); while (*v); } setenv(name, val) char *name, *val; { register char **ep = environ; register char *cp, *dp; char *blk[2], **oep = ep; for (; *ep; ep++) { for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) continue; if (*cp != 0 || *dp != '=') continue; cp = strspl("=", val); xfree(*ep); *ep = strspl(name, cp); xfree(cp); trim(ep); return; } blk[0] = strspl(name, "="); blk[1] = 0; environ = blkspl(environ, blk); xfree((char *)oep); setenv(name, val); } unsetenv(name) char *name; { register char **ep = environ; register char *cp, *dp; char **oep = ep; for (; *ep; ep++) { for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) continue; if (*cp != 0 || *dp != '=') continue; cp = *ep; *ep = 0; environ = blkspl(environ, ep+1); *ep = cp; xfree(cp); xfree((char *)oep); return; } } doumask(v) register char **v; { register char *cp = v[1]; register int i; if (cp == 0) { i = umask(0); (void) umask(i); printf("%o\n", i); return; } i = 0; while (digit(*cp) && *cp != '8' && *cp != '9') i = i * 8 + *cp++ - '0'; if (*cp || i < 0 || i > 0777) bferr("Improper mask"); (void) umask(i); } #ifndef NOLIMITS struct limits { int limconst; char *limname; int limdiv; char *limscale; } limits[] = { RLIMIT_CPU, "cputime", 1, "seconds", RLIMIT_FSIZE, "filesize", 1024, "kbytes", RLIMIT_DATA, "datasize", 1024, "kbytes", RLIMIT_STACK, "stacksize", 1024, "kbytes", RLIMIT_CORE, "coredumpsize", 1024, "kbytes", RLIMIT_RSS, "memoryuse", 1024, "kbytes", -1, 0, }; struct limits * findlim(cp) char *cp; { register struct limits *lp, *res; res = 0; for (lp = limits; lp->limconst >= 0; lp++) if (prefix(cp, lp->limname)) { if (res) bferr("Ambiguous"); res = lp; } if (res) return (res); bferr("No such limit"); /*NOTREACHED*/ } dolimit(v) register char **v; { register struct limits *lp; register long limit; long getval(); char hard = 0; v++; if (*v && eq(*v, "-h")) { hard = 1; v++; } if (*v == 0) { for (lp = limits; lp->limconst >= 0; lp++) plim(lp, hard); return; } lp = findlim(v[0]); if (v[1] == 0) { plim(lp, hard); return; } limit = getval(lp, v+1); if (setlim(lp, hard, limit) < 0) error(NOSTR); } long getval(lp, v) register struct limits *lp; char **v; { register float f; double atof(); char *cp = *v++; f = atof(cp); while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') cp++; if (*cp == 0) { if (*v == 0) return ((long)(f+0.5) * lp->limdiv); cp = *v; } switch (*cp) { case ':': if (lp->limconst != RLIMIT_CPU) goto badscal; return ((long)(f * 60.0 + atof(cp+1))); case 'h': if (lp->limconst != RLIMIT_CPU) goto badscal; limtail(cp, "hours"); f *= 3600.; break; case 'm': if (lp->limconst == RLIMIT_CPU) { limtail(cp, "minutes"); f *= 60.; break; } case 'M': if (lp->limconst == RLIMIT_CPU) goto badscal; *cp = 'm'; limtail(cp, "megabytes"); f *= 1024.*1024.; break; case 's': if (lp->limconst != RLIMIT_CPU) goto badscal; limtail(cp, "seconds"); break; case 'k': if (lp->limconst == RLIMIT_CPU) goto badscal; limtail(cp, "kbytes"); f *= 1024; break; case 'u': limtail(cp, "unlimited"); return (RLIM_INFINITY); default: badscal: bferr("Improper or unknown scale factor"); } return ((long)(f+0.5)); } limtail(cp, str0) char *cp, *str0; { register char *str = str0; while (*cp && *cp == *str) cp++, str++; if (*cp) error("Bad scaling; did you mean ``%s''?", str0); } plim(lp, hard) register struct limits *lp; char hard; { struct rlimit rlim; long limit; printf("%s \t", lp->limname); (void) getrlimit(lp->limconst, &rlim); limit = hard ? rlim.rlim_max : rlim.rlim_cur; if (limit == RLIM_INFINITY) printf("unlimited"); else if (lp->limconst == RLIMIT_CPU) psecs((long)limit); else printf("%ld %s", limit / lp->limdiv, lp->limscale); printf("\n"); } dounlimit(v) register char **v; { register struct limits *lp; int err = 0; char hard = 0; v++; if (*v && eq(*v, "-h")) { hard = 1; v++; } if (*v == 0) { for (lp = limits; lp->limconst >= 0; lp++) if (setlim(lp, hard, (long)RLIM_INFINITY) < 0) err++; if (err) error(NOSTR); return; } while (*v) { lp = findlim(*v++); if (setlim(lp, hard, (long)RLIM_INFINITY) < 0) error(NOSTR); } } setlim(lp, hard, limit) register struct limits *lp; char hard; long limit; { struct rlimit rlim; (void) getrlimit(lp->limconst, &rlim); if (hard) rlim.rlim_max = limit; else if (limit == RLIM_INFINITY && geteuid() != 0) rlim.rlim_cur = rlim.rlim_max; else rlim.rlim_cur = limit; if (setrlimit(lp->limconst, &rlim) < 0) { printf("%s: %s: Can't %s%s limit\n", bname, lp->limname, limit == RLIM_INFINITY ? "remove" : "set", hard ? " hard" : ""); return (-1); } return (0); } #endif !NOLIMITS dosuspend() { int ldisc, ctpgrp; int (*old)(); if (loginsh) error("Can't suspend a login shell (yet)"); untty(); old = signal(SIGTSTP, SIG_DFL); (void) kill(0, SIGTSTP); /* the shell stops here */ (void) signal(SIGTSTP, old); if (tpgrp != -1) { retry: (void) ioctl(FSHTTY, TIOCGPGRP, (char *)&ctpgrp); if (ctpgrp != opgrp) { old = signal(SIGTTIN, SIG_DFL); (void) kill(0, SIGTTIN); (void) signal(SIGTTIN, old); goto retry; } (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&shpgrp); (void) setpgrp(0, shpgrp); } (void) ioctl(FSHTTY, TIOCGETD, (char *)&oldisc); if (oldisc != NTTYDISC) { printf("Switching to new tty driver...\n"); ldisc = NTTYDISC; (void) ioctl(FSHTTY, TIOCSETD, (char *)&ldisc); } } doeval(v) char **v; { char **oevalvec = evalvec; char *oevalp = evalp; jmp_buf osetexit; int reenter; char **gv = 0; v++; if (*v == 0) return; gflag = 0, tglob(v); if (gflag) { gv = v = glob(v); gargv = 0; if (v == 0) error("No match"); v = copyblk(v); } else trim(v); getexit(osetexit); reenter = 0; setexit(); reenter++; if (reenter == 1) { evalvec = v; evalp = 0; process(0); } evalvec = oevalvec; evalp = oevalp; doneinp = 0; if (gv) blkfree(gv); resexit(osetexit); if (reenter >= 2) error(NOSTR); } flush(); aword[0] = 0; (void) getword(aword); switch (srchx(aword)) { case ZELSE: if (level == 0 && type == ZIF) return; break; case ZIF: while (getword(aword)) continue; if ((type == ZIF || type == ZELSE) && eq(aword, "then")) level++; break; case ZENDIF: if (type == ZIF || type == ZELSE) level--; break; case ZFOREACH: case ZWHILE: if (type == ZBREAK) level+bin/csh/sh.char.h 444 0 12 2011 4013203120 7025 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley Software License Agreement * specifies the terms and conditions for redistribution. * * @(#)sh.char.h 5.3 (Berkeley) 3/29/86 */ /* * Table for spotting special characters quickly * * Makes for very obscure but efficient coding. */ extern unsigned short _cmap[]; #define _Q 0x01 /* '" */ #define _Q1 0x02 /* ` */ #define _SP 0x04 /* space and tab */ #define _NL 0x08 /* \n */ #define _META 0x10 /* lex meta characters, sp #'`";&<>()|\t\n */ #define _GLOB 0x20 /* glob characters, *?{[` */ #define _ESC 0x40 /* \ */ #define _DOL 0x80 /* $ */ #define _DIG 0x100 /* 0-9 */ #define _LET 0x200 /* a-z, A-Z, _ */ #define cmap(c, bits) (_cmap[(unsigned char)(c)] & (bits)) #define isglob(c) cmap(c, _GLOB) #define isspace(c) cmap(c, _SP) #define isspnl(c) cmap(c, _SP|_NL) #define ismeta(c) cmap(c, _META) #define digit(c) cmap(c, _DIG) #define letter(c) cmap(c, _LET) #define alnum(c) (digit(c) || letter(c)) *v, "-h")) { hard = 1; v++; } if (*v == 0) { for (lp = limits; lp->limconst >= 0; lp++) if (setlim(lp, hard, (long)RLIM_INFINITY) < 0) err++; if (err) error(NOSTR); return; } while (*v) { lp = findlim(*v++); if (setlim(lp, hard, (long)RLIM_INFINITY) < 0) error(NOSTR); } } setlim(lp, hard, limit) register struct limits *lp; char hard; long limit; { struct rlimit rlim; (void) getrlimit(lp->limconst, &rlim); if (hard) rlim.rlim_max = limit; else if (limit =bin/csh/doprnt11.s 444 0 12 6343 4020232123 7201 #ifdef LIBC_SCCS <@(#)doprnt.s 5.4 (Berkeley) 1/25/87\0> .even #endif LIBC_SCCS /* * doprnt(fmt, argl, iop) * char *fmt, *argl; * FILE *iop; * * Output argl to iop using fmt - implements printf, etc. Special version of * doprnt for csh which doesn't need any floating point support. */ .data nulstr: <(null)\0> .even swtab: decimal; 'd octal; 'o hex; 'x charac; 'c string; 's longorunsg; 'l longorunsg; 'L unsigned; 'u remote; 'r long; 'D loct; 'O lhex; 'X lunsigned; 'U 0; 0 .text .globl __strout, csv, cret width = -10. formp = -12. rjust = -14. ndfnd = -16. ndigit = -18. zfill = -20. .globl __doprnt __doprnt: jsr r5,csv sub $128.+12.,sp mov 4(r5),formp(r5) / format mov 6(r5),r4 loop: mov sp,r3 mov formp(r5),r1 2: movb (r1)+,r2 beq 2f cmp r2,$'% beq 2f movb r2,(r3)+ br 2b 2: mov r1,formp(r5) cmp r3,sp beq 2f mov sp,r0 mov 8(r5),-(sp) clr -(sp) mov r0,-(sp) / string mov r3,-(sp) / count sub r0,(sp) jsr pc,__strout add $8,sp 2: tst r2 bne 2f jmp cret 2: mov sp,r3 2: clr rjust(r5) clr ndigit(r5) mov $' ,zfill(r5) cmpb *formp(r5),$'- bne 2f inc formp(r5) inc rjust(r5) 2: cmpb *formp(r5),$'0 bne 2f mov $'0,zfill(r5) 2: jsr r3,gnum mov r1,width(r5) clr ndfnd(r5) cmp r0,$'. bne 1f jsr r3,gnum mov r1,ndigit(r5) 1: mov $swtab,r1 1: mov (r1)+,r2 bne 2f movb r0,(r3)+ jmp prbuf 2: cmp r0,(r1)+ bne 1b jmp (r2) longorunsg: movb *formp(r5),r0 inc formp(r5) cmp r0,$'o beq loct cmp r0,$'x beq lhex cmp r0,$'d beq long cmp r0,$'u beq lunsigned dec formp(r5) br unsigned octal: clr r0 br 1f loct: mov (r4)+,r0 1: mov $8.,r2 br 2f hex: clr r0 br 1f lhex: mov (r4)+,r0 1: mov $16.,r2 2: mov (r4)+,r1 br compute decimal: mov (r4)+,r1 sxt r0 bmi 3f br 2f unsigned: clr r0 br 1f long: mov (r4)+,r0 bge 1f mov (r4)+,r1 3: neg r0 neg r1 sbc r0 movb $'-,(r3)+ br 2f lunsigned: mov (r4)+,r0 1: mov (r4)+,r1 2: mov $10.,r2 /* * Algorithm courtesy Keith Davis */ compute: mov r5,-(sp) mov r4,-(sp) mov r0,r4 mov ndigit(r5),r0 mov r1,r5 ashc $0,r4 beq 1f tst r0 beq 1f movb $'0,(r3)+ 1: jsr pc,1f mov (sp)+,r4 mov (sp)+,r5 br prbuf 1: clr r0 mov r4,r1 beq 2f div r2,r0 mov r0,r4 mov r1,r0 2: mov r5,r1 asl r2 div r2,r0 asr r2 asl r0 cmp r2,r1 bgt 2f sub r2,r1 inc r0 2: mov r1,-(sp) mov r0,r5 bne 2f tst r4 beq 1f 2: jsr pc,1b 1: mov (sp)+,r0 add $'0,r0 cmp r0,$'9 ble 1f add $'a-'0-10.,r0 1: movb r0,(r3)+ rts pc charac: mov $' ,zfill(r5) mov (r4)+,r0 bic $!377,r0 beq prbuf movb r0,(r3)+ br prbuf string: mov $' ,zfill(r5) mov ndigit(r5),r1 mov (r4),r2 mov r2,r3 bne 1f mov $nulstr,r2 mov r2,r3 mov r2,(r4) 1: tstb (r2)+ beq 1f inc r3 sob r1,1b 1: mov (r4)+,r2 br prstr remote: mov (r4)+,r4 mov (r4)+,formp(r5) jmp loop prbuf: mov sp,r2 prstr: sub r2,r3 mov width(r5),r1 sub r3,r1 bge 1f clr r1 1: tst rjust(r5) bne 1f neg r1 1: mov zfill(r5),-(sp) mov 8(r5),-(sp) mov r1,-(sp) mov r2,-(sp) / string mov r3,-(sp) / count jsr pc,__strout add $10.,sp jmp loop gnum: clr ndfnd(r5) clr r1 1: movb *formp(r5),r0 inc formp(r5) sub $'0,r0 cmp r0,$'*-'0 bne 2f mov (r4)+,r0 br 3f 2: cmp r0,$9. bhi 1f 3: inc ndfnd(r5) mul $10.,r1 add r0,r1 br 1b 1: add $'0,r0 rts r3 break; case ZIF: while (getword(aword)) continue; if ((type == ZIF || type == ZELSE) && eq(aword, "then")) level++; break; case ZENDIF: if (type == ZIF || type == ZELSE) level--; break; case ZFOREACH: case ZWHILE: if (type == ZBREAK) level+bin/csh/alloc11.c 444 0 12 11321 5057637505 7005 #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)alloc.c 4.1 10/9/80"; #endif #include "sh.local.h" #ifdef debug #define ASSERT(p) if(!(p))botch("p");else botch(s) char *s; { printf("assertion botched: %s\n",s); abort(); } #else #define ASSERT(p) #endif /* avoid break bug */ #ifdef pdp11 #define GRANULE 64 #else #define GRANULE 0 #endif /* C storage allocator * circular first-fit strategy * works with noncontiguous, but monotonically linked, arena * each block is preceded by a ptr to the (pointer of) * the next following block * blocks are exact number of words long * aligned to the data type requirements of ALIGN * pointers to blocks must have BUSY bit 0 * bit in ptr is 1 for busy, 0 for idle * gaps in arena are merely noted as busy blocks * last block of arena (pointed to by alloct) is empty and * has a pointer to first * idle blocks are coalesced during space search * * a different implementation may need to redefine * ALIGN, NALIGN, BLOCK, BUSY, INT * where INT is integer type to which a pointer can be cast */ #define INT int #define ALIGN int #define NALIGN 1 #define WORD sizeof(union store) #define BLOCK 1024 /* a multiple of WORD*/ #define BUSY 1 #define NULL 0 #define testbusy(p) ((INT)(p)&BUSY) #define setbusy(p) (union store *)((INT)(p)|BUSY) #define clearbusy(p) (union store *)((INT)(p)&~BUSY) union store { union store *ptr; ALIGN dummy[NALIGN]; int calloc; /*calloc clears an array of integers*/ }; static union store allocs[2]; /*initial arena*/ static union store *allocp; /*search ptr*/ static union store *alloct; /*arena top*/ static union store *allocx; /*for benefit of realloc*/ char *sbrk(); char * malloc(nbytes) unsigned nbytes; { register union store *p, *q; register nw; static temp; /*coroutines assume no auto*/ if(allocs[0].ptr==0) { /*first time*/ allocs[0].ptr = setbusy(&allocs[1]); allocs[1].ptr = setbusy(&allocs[0]); alloct = &allocs[1]; allocp = &allocs[0]; } nw = (nbytes+WORD+WORD-1)/WORD; ASSERT(allocp>=allocs && allocp<=alloct); ASSERT(allock()); for(p=allocp; ; ) { for(temp=0; ; ) { if(!testbusy(p->ptr)) { while(!testbusy((q=p->ptr)->ptr)) { ASSERT(q>p&&qptr = q->ptr; } if(q>=p+nw && p+nw>=p) goto found; } q = p; p = clearbusy(p->ptr); if(p>q) ASSERT(p<=alloct); else if(q!=alloct || p!=allocs) { ASSERT(q==alloct&&p==allocs); return(NULL); } else if(++temp>1) break; } temp = ((nw+BLOCK/WORD)/(BLOCK/WORD))*(BLOCK/WORD); q = (union store *)sbrk(0); if(q+temp+GRANULE < q) { return(NULL); } q = (union store *)sbrk(temp*WORD); if((INT)q == -1) { return(NULL); } ASSERT(q>alloct); alloct->ptr = q; if(q!=alloct+1) alloct->ptr = setbusy(alloct->ptr); alloct = q->ptr = q+temp-1; alloct->ptr = setbusy(allocs); } found: allocp = p + nw; ASSERT(allocp<=alloct); if(q>allocp) { allocx = allocp->ptr; allocp->ptr = p->ptr; } p->ptr = setbusy(allocp); return((char *)(p+1)); } /* freeing strategy tuned for LIFO allocation */ free(ap) register char *ap; { register union store *p = (union store *)ap; ASSERT(p>clearbusy(allocs[1].ptr)&&p<=alloct); ASSERT(allock()); allocp = --p; ASSERT(testbusy(p->ptr)); p->ptr = clearbusy(p->ptr); ASSERT(p->ptr > allocp && p->ptr <= alloct); } /* realloc(p, nbytes) reallocates a block obtained from malloc() * and freed since last call of malloc() * to have new size nbytes, and old content * returns new location, or 0 on failure */ char * realloc(p, nbytes) register union store *p; unsigned nbytes; { register union store *q; union store *s, *t; register unsigned nw; unsigned onw; if(testbusy(p[-1].ptr)) free((char *)p); onw = p[-1].ptr - p; q = (union store *)malloc(nbytes); if(q==NULL || q==p) return((char *)q); s = p; t = q; nw = (nbytes+WORD-1)/WORD; if(nw=p) (q+(q+nw-p))->ptr = allocx; return((char *)q); } #ifdef debug allock() { #ifdef longdebug register union store *p; int x; x = 0; for(p= &allocs[0]; clearbusy(p->ptr) > p; p=clearbusy(p->ptr)) { if(p==allocp) x++; } ASSERT(p==alloct); return(x==1|p==allocp); #else return(1); #endif } #endif showall(s) char **s; { register union store *p, *q; int used = 0, free = 0, i; if (s[1]) printf("Memory allocation statistics %s\n", s[1]); for (p = clearbusy(allocs[1].ptr); p != alloct; p = q) { q = clearbusy(p->ptr); i = ((unsigned) q - (unsigned) p); if (testbusy(p->ptr)) { if (s[1]) printf(" addr %06o, len %5d BUSY\n", p, i); used += i; } else { if (s[1]) printf(" addr %06o, len %5d FREE\n", p, i); free += i; } } printf("%d used, %d free, %l end\n", used, free, clearbusy(alloct)); } oto past; if (c == '\n') { if (wp) break; return (0); } unreadc(c); found = 1; do { c = readc(1); if (c == '\\' && (c = readc(1)) == '\n') c = ' '; if (c == '\'' || c == '"') if (d == 0) d = c; else if (d == c) d = 0; if (c < 0) goto past; ifbin/csh/tags 444 0 12 30723 4100233425 6252 Bin sh.h /^struct Bin {$/ COMMAND sh.file.c /^typedef enum {LIST, RECOGNIZE} COMMAND;$/ Dfix sh.dol.c /^Dfix(t)$/ Dfix1 sh.dol.c /^Dfix1(cp)$/ Dfix2 sh.dol.c /^Dfix2(v)$/ DgetC sh.dol.c /^DgetC(flag)$/ Dgetdol sh.dol.c /^Dgetdol()$/ Dredc sh.dol.c /^Dredc()$/ Dtestq sh.dol.c /^Dtestq(c)$/ Dword sh.dol.c /^Dword()$/ FREE_ITEMS sh.file.c /^#define FREE_ITEMS(items) { \\$/ Gcat sh.glob.c /^Gcat(s1, s2)$/ Gmatch sh.glob.c /^Gmatch(s, p)$/ Hist sh.h /^struct Hist {$/ Msh sh.c /^main(c, av)$/ Perror sh.err.c /^Perror(s)$/ XFREE sh.h /^#define XFREE(cp) { \\$/ acollect sh.glob.c /^acollect(as)$/ addla sh.lex.c /^addla(cp)$/ addpath sh.glob.c /^addpath(c)$/ adrof sh.h /^#define adrof(v) adrof1(v, &shvhed)$/ adrof1 sh.set.c /^adrof1(name, v)$/ alias sh.parse.c /^alias(lex)$/ alnum sh.char.h /^#define alnum(c) (digit(c) || letter(c))$/ amatch sh.glob.c /^amatch(s, p)$/ any sh.misc.c /^any(c, s)$/ asx sh.set.c /^asx(vp, subscr, p)$/ asyn0 sh.parse.c /^asyn0(p1, p2)$/ asyn3 sh.parse.c /^asyn3(p1, p2)$/ asyntax sh.parse.c /^asyntax(p1, p2)$/ back_to_col_1 sh.file.c /^back_to_col_1()$/ backeval sh.glob.c /^backeval(cp, literal)$/ balance sh.set.c /^balance(p, f, d)$/ beep sh.file.c /^beep()$/ bferr sh.err.c /^bferr(cp)$/ bgetc sh.lex.c /^bgetc()$/ biltins sh.h /^struct biltins {$/ bis sh.exec.c /^#define bis(h, b) ((h)[(b) >> 3] |= 1 << ((b) & 7)/ bit sh.exec.c /^#define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7))/ blkcat sh.misc.c /^blkcat(up, vp)$/ blkcpy sh.misc.c /^blkcpy(oav, bv)$/ blkend sh.misc.c /^blkend(up)$/ blkfree sh.misc.c /^blkfree(av0)$/ blklen sh.misc.c /^blklen(av)$/ blkpr sh.misc.c /^blkpr(av)$/ blkspl sh.misc.c /^blkspl(up, vp)$/ bool sh.h /^typedef char bool;$/ btell sh.h /^#define btell() fseekp$/ calloc sh.misc.c /^calloc(i, j)$/ catn sh.file.c /^catn(des, src, count)$/ chkclob sh.sem.c /^chkclob(cp)$/ closem sh.misc.c /^closem()$/ cmap sh.char.h /^#define cmap(c, bits) (_cmap[(unsigned char)(c)] &/ collect sh.glob.c /^collect(as)$/ command sh.h /^struct command {$/ copy sh.local.h /^#define copy(to, from, size) bcopy(from, to, size)/ copyblk sh.misc.c /^copyblk(v)$/ copylex sh.lex.c /^copylex(hp, fp)$/ copyn sh.file.c /^copyn(des, src, count)$/ dcanon sh.dir.c /^dcanon(cp, p)$/ dcopy sh.misc.c /^dcopy(i, j)$/ dfind sh.dir.c /^dfind(cp)$/ dfollow sh.dir.c /^dfollow(cp)$/ dfree sh.dir.c /^dfree(dp)$/ digit sh.char.h /^#define digit(c) cmap(c, _DIG)$/ dinit sh.dir.c /^dinit(hp)$/ directory sh.dir.h /^struct directory {$/ dmove sh.misc.c /^dmove(i, j)$/ dnewcwd sh.dir.c /^dnewcwd(dp)$/ doagain sh.func.c /^doagain()$/ doalias sh.func.c /^doalias(v)$/ dobackp sh.glob.c /^dobackp(cp, literal)$/ dobg sh.proc.c /^dobg(v)$/ dobg1 sh.proc.c /^dobg1(v)$/ dobreak sh.func.c /^dobreak()$/ dochngd sh.dir.c /^dochngd(v)$/ docontin sh.func.c /^docontin()$/ dodirs sh.dir.c /^dodirs(v)$/ doecho sh.func.c /^doecho(v)$/ doelse sh.func.c /^doelse()$/ doend sh.func.c /^doend()$/ doeval sh.func.c /^doeval(v)$/ doexec sh.exec.c /^doexec(t)$/ doexit sh.func.c /^doexit(v)$/ dofg sh.proc.c /^dofg(v)$/ dofg1 sh.proc.c /^dofg1(v)$/ doforeach sh.func.c /^doforeach(v)$/ doglob sh.func.c /^doglob(v)$/ dogoto sh.func.c /^dogoto(v)$/ dohash sh.exec.c /^dohash()$/ dohist sh.hist.c /^dohist(vp)$/ dohist1 sh.hist.c /^dohist1(hp, np, rflg, hflg)$/ doif sh.func.c /^doif(v, kp)$/ doio sh.sem.c /^doio(t, pipein, pipeout)$/ dojobs sh.proc.c /^dojobs(v)$/ dokill sh.proc.c /^dokill(v)$/ dolabel sh.func.c /^dolabel()$/ dolet sh.set.c /^dolet(v)$/ dolimit sh.func.c /^dolimit(v)$/ dologin sh.func.c /^dologin(v)$/ dologout sh.func.c /^dologout()$/ domod sh.lex.c /^domod(cp, type)$/ donefds sh.misc.c /^donefds()$/ donewgrp sh.func.c /^donewgrp(v)$/ donice sh.time.c /^donice(v)$/ donohup sh.func.c /^donohup()$/ donotify sh.proc.c /^donotify(v)$/ doonintr sh.func.c /^doonintr(v)$/ dopopd sh.dir.c /^dopopd(v)$/ dopushd sh.dir.c /^dopushd(v)$/ dorepeat sh.func.c /^dorepeat(v, kp)$/ doset sh.set.c /^doset(v)$/ dosetenv sh.func.c /^dosetenv(v)$/ dosource sh.c /^dosource(t)$/ dostop sh.proc.c /^dostop(v)$/ dosub sh.lex.c /^dosub(sc, en, global)$/ dosuspend sh.func.c /^dosuspend()$/ doswbrk sh.func.c /^doswbrk()$/ doswitch sh.func.c /^doswitch(v)$/ dotime sh.time.c /^dotime()$/ doumask sh.func.c /^doumask(v)$/ dounhash sh.exec.c /^dounhash()$/ dounlimit sh.func.c /^dounlimit(v)$/ dounsetenv sh.func.c /^dounsetenv(v)$/ dowait sh.proc.c /^dowait()$/ dowhile sh.func.c /^dowhile(v)$/ dozip sh.func.c /^dozip()$/ draino sh.print.c /^draino()$/ dtildepr sh.dir.c /^dtildepr(home, dir)$/ echo sh.func.c /^echo(sep, v)$/ egetn sh.exp.c /^egetn(cp)$/ enthist sh.hist.c /^enthist(event, lp, docopy)$/ eq sh.h /^#define eq(a, b) (strcmp(a, b) == 0)$/ error sh.err.c /^error(s, arg)$/ etracc sh.exp.c /^etracc(str, cp, vp)$/ etraci sh.exp.c /^etraci(str, i, vp)$/ evalav sh.exp.c /^evalav(v)$/ execash sh.exec.c /^execash(t, kp)$/ execbrc sh.glob.c /^execbrc(p, s)$/ execute sh.sem.c /^execute(t, wanttty, pipein, pipeout)$/ exit sh.local.h /^#define exit(n) done(n)$/ exitstat sh.c /^exitstat()$/ exp sh.exp.c /^exp(vp)$/ exp0 sh.exp.c /^exp0(vp, ignore)$/ exp1 sh.exp.c /^exp1(vp, ignore)$/ exp2 sh.exp.c /^exp2(vp, ignore)$/ exp2a sh.exp.c /^exp2a(vp, ignore)$/ exp2b sh.exp.c /^exp2b(vp, ignore)$/ exp2c sh.exp.c /^exp2c(vp, ignore)$/ exp3 sh.exp.c /^exp3(vp, ignore)$/ exp3a sh.exp.c /^exp3a(vp, ignore)$/ exp4 sh.exp.c /^exp4(vp, ignore)$/ exp5 sh.exp.c /^exp5(vp, ignore)$/ exp6 sh.exp.c /^exp6(vp, ignore)$/ expand sh.glob.c /^expand(as)$/ exportpath sh.set.c /^exportpath(val)$/ extract_dir_and_name sh.file.c /^extract_dir_and_name(path, dir, name)$/ filetype sh.file.c /^filetype(dir, file)$/ findev sh.lex.c /^findev(cp, anyarg)$/ findlim sh.func.c /^findlim(cp)$/ flush sh.print.c /^flush()$/ free_items sh.file.c /^free_items(items)$/ freelex sh.lex.c /^freelex(vp)$/ freenod sh.parse.c /^freenod(p1, p2)$/ freesyn sh.parse.c /^freesyn(t)$/ func sh.func.c /^func(t, bp)$/ getC sh.lex.c /^#define getC(f) ((getCtmp = peekc) ? (peekc = 0, / getC1 sh.lex.c /^getC1(flag)$/ getdol sh.lex.c /^getdol()$/ getentry sh.file.c /^getentry(dir_fd, looking_for_lognames)$/ getexcl sh.lex.c /^getexcl(sc)$/ getexit sh.h /^#define getexit(a) copy((char *)(a), (char *)resla/ gethdir sh.c /^gethdir(home)$/ gethent sh.lex.c /^gethent(sc)$/ getinx sh.set.c /^getinx(cp, ip)$/ getn sh.set.c /^getn(cp)$/ getsel sh.lex.c /^getsel(al, ar, dol)$/ getsub sh.lex.c /^getsub(en)$/ getval sh.func.c /^getval(lp, v)$/ getvx sh.set.c /^getvx(vp, subscr)$/ getword sh.func.c /^getword(wp)$/ ginit sh.glob.c /^ginit(agargv)$/ glob sh.glob.c /^glob(v)$/ globone sh.glob.c /^globone(str)$/ goodbye sh.c /^goodbye()$/ hash sh.exec.c /^#define hash(a, b) ((a) * HSHMUL + (b) & HSHMASK)$/ hashname sh.exec.c /^hashname(cp)$/ hashstat sh.exec.c /^hashstat()$/ heredoc sh.dol.c /^heredoc(term)$/ hfree sh.hist.c /^hfree(hp)$/ ignored sh.file.c /^ignored(entry)$/ importpath sh.c /^importpath(cp)$/ initdesc sh.c /^initdesc()$/ is_prefix sh.file.c /^is_prefix(check, template)$/ is_suffix sh.file.c /^is_suffix(check, template)$/ isa sh.exp.c /^isa(cp, what)$/ isbfunc sh.func.c /^isbfunc(t)$/ isdir sh.h /^#define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR)/ isglob sh.char.h /^#define isglob(c) cmap(c, _GLOB)$/ islogin sh.func.c /^islogin()$/ ismeta sh.char.h /^#define ismeta(c) cmap(c, _META)$/ isspace sh.char.h /^#define isspace(c) cmap(c, _SP)$/ isspnl sh.char.h /^#define isspnl(c) cmap(c, _SP|_NL)$/ lastchr sh.misc.c /^lastchr(cp)$/ letter sh.char.h /^#define letter(c) cmap(c, _LET)$/ lex sh.lex.c /^lex(hp)$/ limits sh.func.c /^struct limits {$/ limtail sh.func.c /^limtail(cp, str0)$/ lshift sh.misc.c /^lshift(v, c)$/ madrof sh.set.c /^madrof(pat, vp)$/ mailchk sh.c /^mailchk()$/ match sh.glob.c /^match(s, p)$/ matchdir sh.glob.c /^matchdir(pattern)$/ matchs sh.lex.c /^matchs(str, pat)$/ mesg sh.h /^struct mesg {$/ mypipe sh.sem.c /^mypipe(pv)$/ noev sh.lex.c /^noev(cp)$/ nomem sh.misc.c /^nomem(i)$/ number sh.misc.c /^number(cp)$/ okpcntl sh.proc.c /^okpcntl()$/ onlyread sh.misc.c /^onlyread(cp)$/ operate sh.set.c /^operate(op, vp, p)$/ p2dig sh.print.c /^p2dig(i)$/ padd sh.proc.c /^padd(t)$/ pads sh.proc.c /^pads(cp)$/ palloc sh.proc.c /^palloc(pid, t)$/ panystop sh.proc.c /^panystop(neednl)$/ pchild sh.proc.c /^pchild()$/ pclrcurr sh.proc.c /^pclrcurr(pp)$/ pdeltat sh.time.c /^pdeltat(t1, t0)$/ pendjob sh.proc.c /^pendjob()$/ pexerr sh.exec.c /^pexerr()$/ pfind sh.proc.c /^pfind(cp)$/ pflush sh.proc.c /^pflush(pp)$/ pflushall sh.proc.c /^pflushall()$/ pfork sh.proc.c /^pfork(t, wanttty)$/ pgetcurr sh.proc.c /^pgetcurr(pp)$/ phist sh.hist.c /^phist(hp, hflg)$/ phup sh.c /^phup()$/ pintr sh.c /^pintr()$/ pintr1 sh.c /^pintr1(wantnl)$/ pjwait sh.proc.c /^pjwait(pp)$/ pkill sh.proc.c /^pkill(v, signum)$/ plim sh.func.c /^plim(lp, hard)$/ plist sh.set.c /^plist(p)$/ pnote sh.proc.c /^pnote()$/ pprint sh.proc.c /^pprint(pp, flag)$/ prefix sh.misc.c /^prefix(sub, str)$/ preread sh.func.c /^preread()$/ prestjob sh.proc.c /^prestjob()$/ print_by_column sh.file.c /^print_by_column(dir, items, count)$/ print_recognized_stuff sh.file.c /^print_recognized_stuff(recognized_part)$/ printprompt sh.c /^printprompt()$/ prlex sh.lex.c /^prlex(sp0)$/ process sh.proc.h /^struct process {$/ prusage sh.time.c /^prusage(r0, r1, e, b)$/ prvars sh.func.c /^prvars()$/ psave sh.glob.c /^psave(c)$/ psavejob sh.proc.c /^psavejob()$/ psecs sh.print.c /^psecs(l)$/ pstart sh.proc.c /^pstart(pp, foregnd)$/ ptprint sh.proc.c /^ptprint(tp)$/ pushback sh.file.c /^pushback(string)$/ putchar sh.print.c /^putchar(c)$/ putn sh.set.c /^putn(n)$/ putn1 sh.set.c /^putn1(n)$/ pwait sh.proc.c /^pwait()$/ pword sh.glob.c /^pword()$/ readc sh.lex.c /^readc(wanteof)$/ rechist sh.c /^rechist()$/ recognize sh.file.c /^recognize(extended_name, entry, name_length, numit/ reexecute sh.func.c /^reexecute(kp)$/ renum sh.misc.c /^renum(i, j)$/ reset sh.h /^#define reset() longjmp(reslab, 0)$/ resexit sh.h /^#define resexit(a) copy((char *)reslab, ((char *)(/ retype sh.file.c /^retype()$/ rleft sh.set.c /^#define rleft(p) (\\$/ rright sh.set.c /^#define rright(p) (\\$/ rscan sh.glob.c /^rscan(t, f)$/ ruadd sh.time.c /^ruadd(ru, ru2)$/ saveblk sh.misc.c /^saveblk(v)$/ savehist sh.hist.c /^savehist(sp)$/ savestr sh.misc.c /^savestr(s)$/ search sh.file.c /^search(word, command, max_word_length)$/ set sh.set.c /^set(var, val)$/ set1 sh.set.c /^set1(var, vec, head)$/ setDolp sh.dol.c /^setDolp(cp)$/ setNS sh.set.c /^setNS(cp)$/ setenv sh.func.c /^setenv(name, val)$/ seterr sh.err.c /^seterr(s)$/ seterr2 sh.err.c /^seterr2(cp, dp)$/ seterrc sh.err.c /^seterrc(cp, d)$/ setexclp sh.lex.c /^setexclp(cp)$/ setexit sh.h /^#define setexit() ((void) setjmp(reslab))$/ setlim sh.func.c /^setlim(lp, hard, limit)$/ setname sh.h /^#define setname(a) (bname = (a))$/ setq sh.set.c /^setq(name, vec, p)$/ settimes sh.time.c /^settimes()$/ setup_tty sh.file.c /^setup_tty(on)$/ shift sh.set.c /^shift(v)$/ sort sh.glob.c /^#define sort() qsort((char *)sortbas, &gargv[gargc/ sortscmp sh.glob.c /^sortscmp(a1, a2)$/ srccat sh.c /^srccat(cp, dp)$/ srch sh.h /^struct srch {$/ srchx sh.func.c /^srchx(cp)$/ srcunit sh.c /^srcunit(unit, onlyown, hflg)$/ strend sh.misc.c /^strend(cp)$/ strip sh.misc.c /^strip(cp)$/ strspl sh.misc.c /^strspl(cp, dp)$/ subword sh.lex.c /^subword(cp, type, adid)$/ syn0 sh.parse.c /^syn0(p1, p2, flags)$/ syn1 sh.parse.c /^syn1(p1, p2, flags)$/ syn1a sh.parse.c /^syn1a(p1, p2, flags)$/ syn1b sh.parse.c /^syn1b(p1, p2, flags)$/ syn2 sh.parse.c /^syn2(p1, p2, flags)$/ syn3 sh.parse.c /^syn3(p1, p2, flags)$/ syntax sh.parse.c /^syntax(p1, p2, flags)$/ tenex sh.file.c /^tenex(inputline, inputline_size)$/ texec sh.exec.c /^texec(f, t)$/ tglob sh.glob.c /^tglob(t)$/ tilde sh.file.c /^tilde(new, old)$/ toend sh.func.c /^toend()$/ trim sh.glob.c /^trim(t)$/ tvadd sh.time.c /^tvadd(tsum, t0)$/ tvsub sh.time.c /^tvsub(tdiff, t1, t0)$/ udvar sh.misc.c /^udvar(name)$/ unDgetC sh.dol.c /^#define unDgetC(c) Dpeekc = c$/ unDredc sh.dol.c /^unDredc(c)$/ unalias sh.func.c /^unalias(v)$/ ungetC sh.lex.c /^#define ungetC(c) peekc = c$/ ungetD sh.lex.c /^#define ungetD(c) peekd = c$/ unreadc sh.lex.c /^unreadc(c)$/ unset sh.set.c /^unset(v)$/ unset1 sh.set.c /^unset1(v, head)$/ unsetenv sh.func.c /^unsetenv(name)$/ unsetv sh.set.c /^unsetv(var)$/ unsetv1 sh.set.c /^unsetv1(p)$/ untty sh.c /^untty()$/ value sh.h /^#define value(v) value1(v, &shvhed)$/ value1 sh.set.c /^value1(var, head)$/ varent sh.h /^struct varent {$/ vffree sh.sem.c /^vffree()$/ wfree sh.func.c /^wfree()$/ whyle sh.h /^struct whyle {$/ word sh.lex.c /^word()$/ wordent sh.h /^struct wordent {$/ xalloc sh.h /^#define xalloc(i) ((alloctmp = malloc(i)) ? alloct/ xechoit sh.exec.c /^xechoit(t)$/ xfree sh.misc.c /^xfree(cp)$/ xset sh.set.c /^xset(cp, vp)$/ ) { i = umask(0); (void) umask(i); prinbin/sed/ 755 0 12 0 6024536001 5262 bin/sed/sed1.c 444 0 12 24554 4013202644 6376 /* sed1.c 4.2 85/04/05 */ #include #include "sed.h" char *trans[040] = { "\\01", "\\02", "\\03", "\\04", "\\05", "\\06", "\\07", "<-", ">-", "\n", "\\13", "\\14", "\\15", "\\16", "\\17", "\\20", "\\21", "\\22", "\\23", "\\24", "\\25", "\\26", "\\27", "\\30", "\\31", "\\32", "\\33", "\\34", "\\35", "\\36", "\\37" }; char rub[] = {"\177"}; execute(file) char *file; { register char *p1, *p2; register union reptr *ipc; int c; char *execp; if (file) { if ((f = open(file, 0)) < 0) { fprintf(stderr, "Can't open %s\n", file); } } else f = 0; ebp = ibuf; cbp = ibuf; if(pending) { ipc = pending; pending = 0; goto yes; } for(;;) { if((execp = gline(linebuf)) == badp) { close(f); return; } spend = execp; for(ipc = ptrspace; ipc->command; ) { p1 = ipc->ad1; p2 = ipc->ad2; if(p1) { if(ipc->inar) { if(*p2 == CEND) { p1 = 0; } else if(*p2 == CLNUM) { c = p2[1]; if(lnum > tlno[c]) { ipc->inar = 0; if(ipc->negfl) goto yes; ipc++; continue; } if(lnum == tlno[c]) { ipc->inar = 0; } } else if(match(p2, 0)) { ipc->inar = 0; } } else if(*p1 == CEND) { if(!dolflag) { if(ipc->negfl) goto yes; ipc++; continue; } } else if(*p1 == CLNUM) { c = p1[1]; if(lnum != tlno[c]) { if(ipc->negfl) goto yes; ipc++; continue; } if(p2) ipc->inar = 1; } else if(match(p1, 0)) { if(p2) ipc->inar = 1; } else { if(ipc->negfl) goto yes; ipc++; continue; } } if(ipc->negfl) { ipc++; continue; } yes: command(ipc); if(delflag) break; if(jflag) { jflag = 0; if((ipc = ipc->lb1) == 0) { ipc = ptrspace; break; } } else ipc++; } if(!nflag && !delflag) { for(p1 = linebuf; p1 < spend; p1++) putc(*p1, stdout); putc('\n', stdout); } if(aptr > abuf) { arout(); } delflag = 0; } } match(expbuf, gf) char *expbuf; { register char *p1, *p2, c; if(gf) { if(*expbuf) return(0); p1 = linebuf; p2 = genbuf; while(*p1++ = *p2++); locs = p1 = loc2; } else { p1 = linebuf; locs = 0; } p2 = expbuf; if(*p2++) { loc1 = p1; if(*p2 == CCHR && p2[1] != *p1) return(0); return(advance(p1, p2)); } /* fast check for first character */ if(*p2 == CCHR) { c = p2[1]; do { if(*p1 != c) continue; if(advance(p1, p2)) { loc1 = p1; return(1); } } while(*p1++); return(0); } do { if(advance(p1, p2)) { loc1 = p1; return(1); } } while(*p1++); return(0); } advance(alp, aep) char *alp, *aep; { register char *lp, *ep, *curlp; char c; char *bbeg; int ct; /*fprintf(stderr, "*lp = %c, %o\n*ep = %c, %o\n", *lp, *lp, *ep, *ep); /*DEBUG*/ lp = alp; ep = aep; for (;;) switch (*ep++) { case CCHR: if (*ep++ == *lp++) continue; return(0); case CDOT: if (*lp++) continue; return(0); case CNL: case CDOL: if (*lp == 0) continue; return(0); case CEOF: loc2 = lp; return(1); case CCL: c = *lp++ & 0177; if(ep[c>>3] & bittab[c & 07]) { ep += 16; continue; } return(0); case CBRA: braslist[*ep++] = lp; continue; case CKET: braelist[*ep++] = lp; continue; case CBACK: bbeg = braslist[*ep]; ct = braelist[*ep++] - bbeg; if(ecmp(bbeg, lp, ct)) { lp += ct; continue; } return(0); case CBACK|STAR: bbeg = braslist[*ep]; ct = braelist[*ep++] - bbeg; curlp = lp; while(ecmp(bbeg, lp, ct)) lp += ct; while(lp >= curlp) { if(advance(lp, ep)) return(1); lp -= ct; } return(0); case CDOT|STAR: curlp = lp; while (*lp++); goto star; case CCHR|STAR: curlp = lp; while (*lp++ == *ep); ep++; goto star; case CCL|STAR: curlp = lp; do { c = *lp++ & 0177; } while(ep[c>>3] & bittab[c & 07]); ep += 16; goto star; star: if(--lp == curlp) { continue; } if(*ep == CCHR) { c = ep[1]; do { if(*lp != c) continue; if(advance(lp, ep)) return(1); } while(lp-- > curlp); return(0); } if(*ep == CBACK) { c = *(braslist[ep[1]]); do { if(*lp != c) continue; if(advance(lp, ep)) return(1); } while(lp-- > curlp); return(0); } do { if(lp == locs) break; if (advance(lp, ep)) return(1); } while (lp-- > curlp); return(0); default: fprintf(stderr, "RE botch, %o\n", *--ep); } } substitute(ipc) union reptr *ipc; { if(match(ipc->re1, 0) == 0) return(0); sflag = 1; dosub(ipc->rhs); if(ipc->gfl) { while(*loc2) { if(match(ipc->re1, 1) == 0) break; dosub(ipc->rhs); } } return(1); } dosub(rhsbuf) char *rhsbuf; { register char *lp, *sp, *rp; int c; lp = linebuf; sp = genbuf; rp = rhsbuf; while (lp < loc1) *sp++ = *lp++; while(c = *rp++) { if (c == '&') { sp = place(sp, loc1, loc2); continue; } else if (c&0200 && (c &= 0177) >= '1' && c < NBRA+'1') { sp = place(sp, braslist[c-'1'], braelist[c-'1']); continue; } *sp++ = c&0177; if (sp >= &genbuf[LBSIZE]) fprintf(stderr, "output line too long.\n"); } lp = loc2; loc2 = sp - genbuf + linebuf; while (*sp++ = *lp++) if (sp >= &genbuf[LBSIZE]) { fprintf(stderr, "Output line too long.\n"); } lp = linebuf; sp = genbuf; while (*lp++ = *sp++); spend = lp-1; } char *place(asp, al1, al2) char *asp, *al1, *al2; { register char *sp, *l1, *l2; sp = asp; l1 = al1; l2 = al2; while (l1 < l2) { *sp++ = *l1++; if (sp >= &genbuf[LBSIZE]) fprintf(stderr, "Output line too long.\n"); } return(sp); } command(ipc) union reptr *ipc; { register int i; register char *p1, *p2, *p3; char *execp; switch(ipc->command) { case ACOM: *aptr++ = ipc; if(aptr >= &abuf[ABUFSIZE]) { fprintf(stderr, "Too many appends after line %ld\n", lnum); } *aptr = 0; break; case CCOM: delflag = 1; if(!ipc->inar || dolflag) { for(p1 = ipc->re1; *p1; ) putc(*p1++, stdout); putc('\n', stdout); } break; case DCOM: delflag++; break; case CDCOM: p1 = p2 = linebuf; while(*p1 != '\n') { if(*p1++ == 0) { delflag++; return; } } p1++; while(*p2++ = *p1++); spend = p2-1; jflag++; break; case EQCOM: fprintf(stdout, "%ld\n", lnum); break; case GCOM: p1 = linebuf; p2 = holdsp; while(*p1++ = *p2++); spend = p1-1; break; case CGCOM: *spend++ = '\n'; p1 = spend; p2 = holdsp; while(*p1++ = *p2++) if(p1 >= lbend) break; spend = p1-1; break; case HCOM: p1 = holdsp; p2 = linebuf; while(*p1++ = *p2++); hspend = p1-1; break; case CHCOM: *hspend++ = '\n'; p1 = hspend; p2 = linebuf; while(*p1++ = *p2++) if(p1 >= hend) break; hspend = p1-1; break; case ICOM: for(p1 = ipc->re1; *p1; ) putc(*p1++, stdout); putc('\n', stdout); break; case BCOM: jflag = 1; break; case LCOM: p1 = linebuf; p2 = genbuf; genbuf[72] = 0; while(*p1) if(*p1 >= 040) { if(*p1 == 0177) { p3 = rub; while(*p2++ = *p3++) if(p2 >= lcomend) { *p2 = '\\'; fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } p2--; p1++; continue; } *p2++ = *p1++; if(p2 >= lcomend) { *p2 = '\\'; fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } } else { p3 = trans[*p1-1]; while(*p2++ = *p3++) if(p2 >= lcomend) { *p2 = '\\'; fprintf(stdout, "%s\n", genbuf); p2 = genbuf; } p2--; p1++; } *p2 = 0; fprintf(stdout, "%s\n", genbuf); break; case NCOM: if(!nflag) { for(p1 = linebuf; p1 < spend; p1++) putc(*p1, stdout); putc('\n', stdout); } if(aptr > abuf) arout(); if((execp = gline(linebuf)) == badp) { pending = ipc; delflag = 1; break; } spend = execp; break; case CNCOM: if(aptr > abuf) arout(); *spend++ = '\n'; if((execp = gline(spend)) == badp) { pending = ipc; delflag = 1; break; } spend = execp; break; case PCOM: for(p1 = linebuf; p1 < spend; p1++) putc(*p1, stdout); putc('\n', stdout); break; case CPCOM: cpcom: for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; ) putc(*p1++, stdout); putc('\n', stdout); break; case QCOM: if(!nflag) { for(p1 = linebuf; p1 < spend; p1++) putc(*p1, stdout); putc('\n', stdout); } if(aptr > abuf) arout(); fclose(stdout); exit(0); case RCOM: *aptr++ = ipc; if(aptr >= &abuf[ABUFSIZE]) fprintf(stderr, "Too many reads after line%ld\n", lnum); *aptr = 0; break; case SCOM: i = substitute(ipc); if(ipc->pfl && i) if(ipc->pfl == 1) { for(p1 = linebuf; p1 < spend; p1++) putc(*p1, stdout); putc('\n', stdout); } else goto cpcom; if(i && ipc->fcode) goto wcom; break; case TCOM: if(sflag == 0) break; sflag = 0; jflag = 1; break; wcom: case WCOM: fprintf(ipc->fcode, "%s\n", linebuf); fflush(ipc->fcode); break; case XCOM: p1 = linebuf; p2 = genbuf; while(*p2++ = *p1++); p1 = holdsp; p2 = linebuf; while(*p2++ = *p1++); spend = p2 - 1; p1 = genbuf; p2 = holdsp; while(*p2++ = *p1++); hspend = p2 - 1; break; case YCOM: p1 = linebuf; p2 = ipc->re1; while(*p1 = p2[*p1]) p1++; break; } } char * gline(addr) char *addr; { register char *p1, *p2; register c; p1 = addr; p2 = cbp; for (;;) { if (p2 >= ebp) { if ((c = read(f, ibuf, BUFSIZ)) <= 0) { return(badp); } p2 = ibuf; ebp = ibuf+c; } if ((c = *p2++) == '\n') { if(p2 >= ebp) { if((c = read(f, ibuf, BUFSIZ)) <= 0) { close(f); if(eargc == 0) dolflag = 1; } p2 = ibuf; ebp = ibuf + c; } break; } if(c) if(p1 < lbend) *p1++ = c; } lnum++; *p1 = 0; cbp = p2; return(p1); } ecmp(a, b, count) char *a, *b; { while(count--) if(*a++ != *b++) return(0); return(1); } arout() { register char *p1; FILE *fi; char c; int t; aptr = abuf - 1; while(*++aptr) { if((*aptr)->command == ACOM) { for(p1 = (*aptr)->re1; *p1; ) putc(*p1++, stdout); putc('\n', stdout); } else { if((fi = fopen((*aptr)->re1, "r")) == NULL) continue; while((t = getc(fi)) != EOF) { c = t; putc(c, stdout); } fclose(fi); } } aptr = abuf; *aptr = 0; } atof(cp); while (digit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') cp++; if (*cp == 0) { if (*v == 0) return ((long)(f+0.5) * lp->limdbin/sed/sed0.c 444 0 12 35701 4013202644 6371 /* sed0.c 4.2 85/06/19 */ #include #include "sed.h" struct label *labtab = ltab; char CGMES[] = "command garbled: %s\n"; char TMMES[] = "Too much text: %s\n"; char LTL[] = "Label too long: %s\n"; char AD0MES[] = "No addresses allowed: %s\n"; char AD1MES[] = "Only one address allowed: %s\n"; char bittab[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; main(argc, argv) char *argv[]; { eargc = argc; eargv = argv; badp = &bad; aptr = abuf; lab = labtab + 1; /* 0 reserved for end-pointer */ rep = ptrspace; rep->ad1 = respace; lbend = &linebuf[LBSIZE]; hend = &holdsp[LBSIZE]; lcomend = &genbuf[71]; ptrend = &ptrspace[PTRSIZE]; reend = &respace[RESIZE]; labend = &labtab[LABSIZE]; lnum = 0; pending = 0; depth = 0; spend = linebuf; hspend = holdsp; fcode[0] = stdout; nfiles = 1; if(eargc == 1) exit(0); while (--eargc > 0 && (++eargv)[0][0] == '-') switch (eargv[0][1]) { case 'n': nflag++; continue; case 'f': if(eargc-- <= 0) exit(2); if((fin = fopen(*++eargv, "r")) == NULL) { fprintf(stderr, "Cannot open pattern-file: %s\n", *eargv); exit(2); } fcomp(); fclose(fin); continue; case 'e': eflag++; fcomp(); eflag = 0; continue; case 'g': gflag++; continue; default: fprintf(stdout, "Unknown flag: %c\n", eargv[0][1]); continue; } if(compfl == 0) { eargv--; eargc++; eflag++; fcomp(); eargv++; eargc--; eflag = 0; } if(depth) { fprintf(stderr, "Too many {'s"); exit(2); } labtab->address = rep; dechain(); /* abort(); /*DEBUG*/ if(eargc <= 0) execute((char *)NULL); else while(--eargc >= 0) { execute(*eargv++); } fclose(stdout); exit(0); } fcomp() { register char *p, *op, *tp; char *address(); union reptr *pt, *pt1; int i; struct label *lpt; compfl = 1; op = lastre; if(rline(linebuf) < 0) return; if(*linebuf == '#') { if(linebuf[1] == 'n') nflag = 1; } else { cp = linebuf; goto comploop; } for(;;) { if(rline(linebuf) < 0) break; cp = linebuf; comploop: /* fprintf(stdout, "cp: %s\n", cp); /*DEBUG*/ while(*cp == ' ' || *cp == '\t') cp++; if(*cp == '\0' || *cp == '#') continue; if(*cp == ';') { cp++; goto comploop; } p = address(rep->ad1); if(p == badp) { fprintf(stderr, CGMES, linebuf); exit(2); } if(p == rep->ad1) { if(op) rep->ad1 = op; else { fprintf(stderr, "First RE may not be null\n"); exit(2); } } else if(p == 0) { p = rep->ad1; rep->ad1 = 0; } else { op = rep->ad1; if(*cp == ',' || *cp == ';') { cp++; if((rep->ad2 = p) > reend) { fprintf(stderr, TMMES, linebuf); exit(2); } p = address(rep->ad2); if(p == badp || p == 0) { fprintf(stderr, CGMES, linebuf); exit(2); } if(p == rep->ad2) rep->ad2 = op; else op = rep->ad2; } else rep->ad2 = 0; } if(p > reend) { fprintf(stderr, "Too much text: %s\n", linebuf); exit(2); } while(*cp == ' ' || *cp == '\t') cp++; swit: switch(*cp++) { default: fprintf(stderr, "Unrecognized command: %s\n", linebuf); exit(2); case '!': rep->negfl = 1; goto swit; case '{': rep->command = BCOM; rep->negfl = !(rep->negfl); cmpend[depth++] = &rep->lb1; if(++rep >= ptrend) { fprintf(stderr, "Too many commands: %s\n", linebuf); exit(2); } rep->ad1 = p; if(*cp == '\0') continue; goto comploop; case '}': if(rep->ad1) { fprintf(stderr, AD0MES, linebuf); exit(2); } if(--depth < 0) { fprintf(stderr, "Too many }'s\n"); exit(2); } *cmpend[depth] = rep; rep->ad1 = p; continue; case '=': rep->command = EQCOM; if(rep->ad2) { fprintf(stderr, AD1MES, linebuf); exit(2); } break; case ':': if(rep->ad1) { fprintf(stderr, AD0MES, linebuf); exit(2); } while(*cp++ == ' '); cp--; tp = lab->asc; while((*tp++ = *cp++)) if(tp >= &(lab->asc[8])) { fprintf(stderr, LTL, linebuf); exit(2); } *--tp = '\0'; if(lpt = search(lab)) { if(lpt->address) { fprintf(stderr, "Duplicate labels: %s\n", linebuf); exit(2); } } else { lab->chain = 0; lpt = lab; if(++lab >= labend) { fprintf(stderr, "Too many labels: %s\n", linebuf); exit(2); } } lpt->address = rep; rep->ad1 = p; continue; case 'a': rep->command = ACOM; if(rep->ad2) { fprintf(stderr, AD1MES, linebuf); exit(2); } if(*cp == '\\') cp++; if(*cp++ != '\n') { fprintf(stderr, CGMES, linebuf); exit(2); } rep->re1 = p; p = text(rep->re1); break; case 'c': rep->command = CCOM; if(*cp == '\\') cp++; if(*cp++ != ('\n')) { fprintf(stderr, CGMES, linebuf); exit(2); } rep->re1 = p; p = text(rep->re1); break; case 'i': rep->command = ICOM; if(rep->ad2) { fprintf(stderr, AD1MES, linebuf); exit(2); } if(*cp == '\\') cp++; if(*cp++ != ('\n')) { fprintf(stderr, CGMES, linebuf); exit(2); } rep->re1 = p; p = text(rep->re1); break; case 'g': rep->command = GCOM; break; case 'G': rep->command = CGCOM; break; case 'h': rep->command = HCOM; break; case 'H': rep->command = CHCOM; break; case 't': rep->command = TCOM; goto jtcommon; case 'b': rep->command = BCOM; jtcommon: while(*cp++ == ' '); cp--; if(*cp == '\0') { if(pt = labtab->chain) { while(pt1 = pt->lb1) pt = pt1; pt->lb1 = rep; } else labtab->chain = rep; break; } tp = lab->asc; while((*tp++ = *cp++)) if(tp >= &(lab->asc[8])) { fprintf(stderr, LTL, linebuf); exit(2); } cp--; *--tp = '\0'; if(lpt = search(lab)) { if(lpt->address) { rep->lb1 = lpt->address; } else { pt = lpt->chain; while(pt1 = pt->lb1) pt = pt1; pt->lb1 = rep; } } else { lab->chain = rep; lab->address = 0; if(++lab >= labend) { fprintf(stderr, "Too many labels: %s\n", linebuf); exit(2); } } break; case 'n': rep->command = NCOM; break; case 'N': rep->command = CNCOM; break; case 'p': rep->command = PCOM; break; case 'P': rep->command = CPCOM; break; case 'r': rep->command = RCOM; if(rep->ad2) { fprintf(stderr, AD1MES, linebuf); exit(2); } if(*cp++ != ' ') { fprintf(stderr, CGMES, linebuf); exit(2); } rep->re1 = p; p = text(rep->re1); break; case 'd': rep->command = DCOM; break; case 'D': rep->command = CDCOM; rep->lb1 = ptrspace; break; case 'q': rep->command = QCOM; if(rep->ad2) { fprintf(stderr, AD1MES, linebuf); exit(2); } break; case 'l': rep->command = LCOM; break; case 's': rep->command = SCOM; seof = *cp++; rep->re1 = p; p = compile(rep->re1); if(p == badp) { fprintf(stderr, CGMES, linebuf); exit(2); } if(p == rep->re1) { if(op) rep->re1 = op; else { fprintf(stderr, "First RE may not be null\n"); exit(2); } } else { op = rep->re1; } if((rep->rhs = p) > reend) { fprintf(stderr, TMMES, linebuf); exit(2); } if((p = compsub(rep->rhs)) == badp) { fprintf(stderr, CGMES, linebuf); exit(2); } if(*cp == 'g') { cp++; rep->gfl++; } else if(gflag) rep->gfl++; if(*cp == 'p') { cp++; rep->pfl = 1; } if(*cp == 'P') { cp++; rep->pfl = 2; } if(*cp == 'w') { cp++; if(*cp++ != ' ') { fprintf(stderr, CGMES, linebuf); exit(2); } if(nfiles >= 10) { fprintf(stderr, "Too many files in w commands\n"); exit(2); } text(fname[nfiles]); for(i = nfiles - 1; i >= 0; i--) if(cmp(fname[nfiles],fname[i]) == 0) { rep->fcode = fcode[i]; goto done; } if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) { fprintf(stderr, "cannot open %s\n", fname[nfiles]); exit(2); } fcode[nfiles++] = rep->fcode; } break; case 'w': rep->command = WCOM; if(*cp++ != ' ') { fprintf(stderr, CGMES, linebuf); exit(2); } if(nfiles >= 10){ fprintf(stderr, "Too many files in w commands\n"); exit(2); } text(fname[nfiles]); for(i = nfiles - 1; i >= 0; i--) if(cmp(fname[nfiles], fname[i]) == 0) { rep->fcode = fcode[i]; goto done; } if((rep->fcode = fopen(fname[nfiles], "w")) == NULL) { fprintf(stderr, "Cannot create %s\n", fname[nfiles]); exit(2); } fcode[nfiles++] = rep->fcode; break; case 'x': rep->command = XCOM; break; case 'y': rep->command = YCOM; seof = *cp++; rep->re1 = p; p = ycomp(rep->re1); if(p == badp) { fprintf(stderr, CGMES, linebuf); exit(2); } if(p > reend) { fprintf(stderr, TMMES, linebuf); exit(2); } break; } done: if(++rep >= ptrend) { fprintf(stderr, "Too many commands, last: %s\n", linebuf); exit(2); } rep->ad1 = p; if(*cp++ != '\0') { if(cp[-1] == ';') goto comploop; fprintf(stderr, CGMES, linebuf); exit(2); } } rep->command = 0; lastre = op; } char *compsub(rhsbuf) char *rhsbuf; { register char *p, *q; p = rhsbuf; q = cp; for(;;) { if((*p = *q++) == '\\') { *p = *q++; if(*p > numbra + '0' && *p <= '9') return(badp); *p++ |= 0200; continue; } if(*p == seof) { *p++ = '\0'; cp = q; return(p); } if(*p++ == '\0') { return(badp); } } } char *compile(expbuf) char *expbuf; { register c; register char *ep, *sp; char neg; char *lastep, *cstart; int cclcnt; int closed; char bracket[NBRA], *bracketp; if(*cp == seof) { cp++; return(expbuf); } ep = expbuf; lastep = 0; bracketp = bracket; closed = numbra = 0; sp = cp; if (*sp == '^') { *ep++ = 1; sp++; } else { *ep++ = 0; } for (;;) { if (ep >= &expbuf[ESIZE]) { cp = sp; return(badp); } if((c = *sp++) == seof) { if(bracketp != bracket) { cp = sp; return(badp); } cp = sp; *ep++ = CEOF; return(ep); } if(c != '*') lastep = ep; switch (c) { case '\\': if((c = *sp++) == '(') { if(numbra >= NBRA) { cp = sp; return(badp); } *bracketp++ = numbra; *ep++ = CBRA; *ep++ = numbra++; continue; } if(c == ')') { if(bracketp <= bracket) { cp = sp; return(badp); } *ep++ = CKET; *ep++ = *--bracketp; closed++; continue; } if(c >= '1' && c <= '9') { if((c -= '1') >= closed) return(badp); *ep++ = CBACK; *ep++ = c; continue; } if(c == '\n') { cp = sp; return(badp); } if(c == 'n') { c = '\n'; } goto defchar; case '\0': continue; case '\n': cp = sp; return(badp); case '.': *ep++ = CDOT; continue; case '*': if (lastep == 0) goto defchar; if(*lastep == CKET) { cp = sp; return(badp); } *lastep |= STAR; continue; case '$': if (*sp != seof) goto defchar; *ep++ = CDOL; continue; case '[': if(&ep[17] >= &expbuf[ESIZE]) { fprintf(stderr, "RE too long: %s\n", linebuf); exit(2); } *ep++ = CCL; neg = 0; if((c = *sp++) == '^') { neg = 1; c = *sp++; } cstart = sp; do { if(c == '\0') { fprintf(stderr, CGMES, linebuf); exit(2); } if (c=='-' && sp>cstart && *sp!=']') { for (c = sp[-2]; c<*sp; c++) ep[c>>3] |= bittab[c&07]; } if(c == '\\') { switch(c = *sp++) { case 'n': c = '\n'; break; } } ep[c >> 3] |= bittab[c & 07]; } while((c = *sp++) != ']'); if(neg) for(cclcnt = 0; cclcnt < 16; cclcnt++) ep[cclcnt] ^= -1; ep[0] &= 0376; ep += 16; continue; defchar: default: *ep++ = CCHR; *ep++ = c; } } } rline(lbuf) char *lbuf; { register char *p, *q; register t; static char *saveq; p = lbuf - 1; if(eflag) { if(eflag > 0) { eflag = -1; if(eargc-- <= 0) exit(2); q = *++eargv; while(*++p = *q++) { if(*p == '\\') { if((*++p = *q++) == '\0') { saveq = 0; return(-1); } else continue; } if(*p == '\n') { *p = '\0'; saveq = q; return(1); } } saveq = 0; return(1); } if((q = saveq) == 0) return(-1); while(*++p = *q++) { if(*p == '\\') { if((*++p = *q++) == '0') { saveq = 0; return(-1); } else continue; } if(*p == '\n') { *p = '\0'; saveq = q; return(1); } } saveq = 0; return(1); } while((t = getc(fin)) != EOF) { *++p = t; if(*p == '\\') { t = getc(fin); *++p = t; } else if(*p == '\n') { *p = '\0'; return(1); } } *++p = '\0'; return(-1); } char *address(expbuf) char *expbuf; { register char *rcp; long lno; if(*cp == '$') { cp++; *expbuf++ = CEND; *expbuf++ = CEOF; return(expbuf); } if(*cp == '/') { seof = '/'; cp++; return(compile(expbuf)); } rcp = cp; lno = 0; while(*rcp >= '0' && *rcp <= '9') lno = lno*10 + *rcp++ - '0'; if(rcp > cp) { *expbuf++ = CLNUM; *expbuf++ = nlno; tlno[nlno++] = lno; if(nlno >= NLINES) { fprintf(stderr, "Too many line numbers\n"); exit(2); } *expbuf++ = CEOF; cp = rcp; return(expbuf); } return(0); } cmp(a, b) char *a,*b; { register char *ra, *rb; ra = a - 1; rb = b - 1; while(*++ra == *++rb) if(*ra == '\0') return(0); return(1); } char *text(textbuf) char *textbuf; { register char *p, *q; p = textbuf; q = cp; while(*q == '\t' || *q == ' ') q++; for(;;) { if((*p = *q++) == '\\') *p = *q++; if(*p == '\0') { cp = --q; return(++p); } if(*p == '\n') { while(*q == '\t' || *q == ' ') q++; } p++; } } struct label *search(ptr) struct label *ptr; { struct label *rp; rp = labtab; while(rp < ptr) { if(cmp(rp->asc, ptr->asc) == 0) return(rp); rp++; } return(0); } dechain() { struct label *lptr; union reptr *rptr, *trptr; for(lptr = labtab; lptr < lab; lptr++) { if(lptr->address == 0) { fprintf(stderr, "Undefined label: %s\n", lptr->asc); exit(2); } if(lptr->chain) { rptr = lptr->chain; while(trptr = rptr->lb1) { rptr->lb1 = lptr->address; rptr = trptr; } rptr->lb1 = lptr->address; } } } char *ycomp(expbuf) char *expbuf; { register char c, *ep, *tsp; char *sp; ep = expbuf; sp = cp; for(tsp = cp; *tsp != seof; tsp++) { if(*tsp == '\\') tsp++; if(*tsp == '\n') return(badp); } tsp++; while((c = *sp++ & 0177) != seof) { if(c == '\\' && *sp == 'n') { sp++; c = '\n'; } if((ep[c] = *tsp++) == '\\' && *tsp == 'n') { ep[c] = '\n'; tsp++; } if(ep[c] == seof || ep[c] == '\0') return(badp); } if(*tsp != seof) return(badp); cp = ++tsp; for(c = 0; !(c & 0200); c++) if(ep[c] == 0) ep[c] = c; return(ep + 0200); } 2); } if(*cp == '\\') cp++; if(*cp++ != ('\n')) { bin/sed/sed.h 444 0 12 4427 4013202644 6277 /* sed.h 4.1 85/04/05 */ /* * sed -- stream editor */ #define CBRA 1 #define CCHR 2 #define CDOT 4 #define CCL 6 #define CNL 8 #define CDOL 10 #define CEOF 11 #define CKET 12 #define CNULL 13 #define CLNUM 14 #define CEND 16 #define CDONT 17 #define CBACK 18 #define STAR 01 #define NLINES 256 #define DEPTH 20 #define PTRSIZE 200 #define RESIZE 10000 #define ABUFSIZE 20 #define LBSIZE 4000 #define ESIZE 256 #define LABSIZE 50 #define NBRA 9 FILE *fin; union reptr *abuf[ABUFSIZE]; union reptr **aptr; char *lastre; char ibuf[BUFSIZ]; char *cbp; char *ebp; char genbuf[LBSIZE]; char *loc1; char *loc2; char *locs; char seof; char *reend; char *lbend; char *hend; char *lcomend; union reptr *ptrend; int eflag; int dolflag; int sflag; int jflag; int numbra; int delflag; long lnum; char linebuf[LBSIZE+1]; char holdsp[LBSIZE+1]; char *spend; char *hspend; int nflag; int gflag; char *braelist[NBRA]; char *braslist[NBRA]; long tlno[NLINES]; int nlno; char fname[12][40]; FILE *fcode[12]; int nfiles; #define ACOM 01 #define BCOM 020 #define CCOM 02 #define CDCOM 025 #define CNCOM 022 #define COCOM 017 #define CPCOM 023 #define DCOM 03 #define ECOM 015 #define EQCOM 013 #define FCOM 016 #define GCOM 027 #define CGCOM 030 #define HCOM 031 #define CHCOM 032 #define ICOM 04 #define LCOM 05 #define NCOM 012 #define PCOM 010 #define QCOM 011 #define RCOM 06 #define SCOM 07 #define TCOM 021 #define WCOM 014 #define CWCOM 024 #define YCOM 026 #define XCOM 033 char *cp; char *reend; char *lbend; union reptr { struct reptr1 { char *ad1; char *ad2; char *re1; char *rhs; FILE *fcode; char command; char gfl; char pfl; char inar; char negfl; } A; struct reptr2 { char *ad1; char *ad2; union reptr *lb1; char *rhs; FILE *fcode; char command; char gfl; char pfl; char inar; char negfl; } B; } ptrspace[PTRSIZE], *rep; char respace[RESIZE]; struct label { char asc[9]; union reptr *chain; union reptr *address; } ltab[LABSIZE]; struct label *lab; struct label *labend; int f; int depth; int eargc; char **eargv; extern char bittab[]; union reptr **cmpend[DEPTH]; int depth; union reptr *pending; char *badp; char bad; char *compile(); char *ycomp(); char *address(); char *text(); char *compsub(); struct label *search(); char *gline(); char *place(); char compfl; else continue; } if(*p == '\n') { *p = '\0'; saveq = q; return(1); } } saveq = 0; return(1); } if((q = saveq) == 0) return(-1); while(*++p = *q++) { if(*p == '\\') { if((*++p =bin/sed/Makefile 444 0 12 316 4015050056 6764 # Makefile 4.1 85/04/05 # CFLAGS=-O -w SEPFLAG=-i sed: sed0.o sed1.o cc ${SEPFLAG} -o sed *.o sed0.o: sed0.c sed.h sed1.o: sed1.c sed.h install: sed install -s sed $(DESTDIR)/bin clean: rm -f *.o sed bin/make/ 755 0 12 0 6024535774 5444 bin/make/dosys.c 444 0 12 5435 5050607732 7033 /* static char *sccsid = "@(#)dosys.c 4.10 (Berkeley) 12/23/84"; */ #include "defs" #include dosys(comstring,nohalt) register char *comstring; int nohalt; { register int status; if(metas(comstring)) status = doshell(comstring,nohalt); else status = doexec(comstring); return(status); } metas(s) /* Are there are any Shell meta-characters? */ register char *s; { register char c; while( (funny[c = *s++] & META) == 0 ) ; return( c ); } doshell(comstring,nohalt) char *comstring; int nohalt; { #ifdef SHELLENV char *getenv(), *rindex(); char *shellcom = getenv("SHELL"); char *shellstr; #endif if((waitpid = vfork()) == 0) { enbint(SIG_DFL); doclose(); #ifdef SHELLENV if (shellcom == 0) shellcom = SHELLCOM; shellstr = rindex(shellcom, '/') + 1; execl(shellcom, shellstr, (nohalt ? "-c" : "-ce"), comstring, 0); #else execl(SHELLCOM, "sh", (nohalt ? "-c" : "-ce"), comstring, 0); #endif fatal("Couldn't load Shell"); } return( await() ); } int intrupt(); await() { int status; register int pid; enbint(SIG_IGN); while( (pid = wait(&status)) != waitpid) if(pid == -1) fatal("bad wait code"); waitpid = 0; enbint(intrupt); return(status); } /* * Close open directory files before exec'ing */ doclose() { register struct dirhdr *od; for (od = firstod; od; od = od->nxtopendir) if (od->dirfc != NULL) /* * vfork kludge... * we cannot call closedir since this will modify * the parents data space; just call close directly. */ close(od->dirfc->dd_fd); } #define MAXARGV 254 /* execvp can only handle 254 anyhow */ doexec(str) register char *str; { register char *t; static char *argv[MAXARGV]; /* docom() ate most of the stack already */ register char **p; while( *str==' ' || *str=='\t' ) ++str; if( *str == '\0' ) return(-1); /* no command */ p = argv; for(t = str ; *t ; ) { if (p >= argv + MAXARGV) fatal1("%s: Too many arguments.", str); *p++ = t; while(*t!=' ' && *t!='\t' && *t!='\0') ++t; if(*t) for( *t++ = '\0' ; *t==' ' || *t=='\t' ; ++t) ; } *p = NULL; if((waitpid = vfork()) == 0) { enbint(SIG_DFL); doclose(); enbint(intrupt); execvp(str, argv); fatal1("Cannot load %s",str); } return( await() ); } #include #include touch(force, name) int force; char *name; { struct stat stbuff; char junk[1]; int fd; if( stat(name,&stbuff) < 0) if(force) goto create; else { fprintf(stderr, "touch: file %s does not exist.\n", name); return; } if(stbuff.st_size == 0) goto create; if( (fd = open(name, 2)) < 0) goto bad; if( read(fd, junk, 1) < 1) { close(fd); goto bad; } lseek(fd, 0L, 0); if( write(fd, junk, 1) < 1 ) { close(fd); goto bad; } close(fd); return; bad: fprintf(stderr, "Cannot touch %s\n", name); return; create: if( (fd = creat(name, 0666)) < 0) goto bad; close(fd); } else if(*p == '\n') { *p = '\0'; return(1); } } *++p = '\0'; return(-1); } char *address(expbuf) char *expbuf; { register char *rcp; long lno; if(*cp == '$') { cp++; *expbuf++ = CEND; *expbuf++ = CEOF; bin/make/gcos.c 444 0 12 13112 4106225526 6632 static char *sccsid = "@(#)gcos.c 4.3 (Berkeley) 85/08/30"; /* GCOS DEPENDENT PROCEDURES */ /* DEFAULT RULES FOR GCOS */ char *builtin[] { ".SUFFIXES : .d .c .y .lib", ".d.c:", "\t./dtgen $<", ".y.c:", "\t./yacc $<", "\tcopy y.tab.c; /$@", ".y.lib:", "\t./yacc $<", "\t./cc y.tab.c r=$@", ".c.lib:", "\t./cc $< r=$@", 0 }; # define MAXCSIZE 500 # define YZERO 60 int gtcalled 0; /* all kinds of static declarations that must be used.. */ static double day { 64*1000*60*60*24 }; /* length of day in clock ticks */ struct { int lhs:18, rhs:18; }; struct catb { int words[6], name1, name2, passw1, passw2, word10, word11, datcreat, datmod, datused, stuff[6], jjjj:18, tused:18; }; struct { int :3, slot:18; }; /* slot where time from cat. block fits */ struct catdesc { int cat1, cat2, cpass1, cpass2, file1, file2, filep1, filep2, endmark; }; extern int _q_reg, _a_reg; # define A10(x,y) 10*x + y /* interpret the mm/dd/yy format */ struct d9 { int :5, m1:4, :5, m2:4, :9, :5, d1:4, :5, d2:4, :9, :5, y1:4, :5, y2:4 ;}; struct d6 { int :2, m61:4, :2, m62:4, :2, d61:4, :2, d62:4, :2, y61:4, :2, y62:4; }; static day6( d6word ){ /* return the day number of a word in bci format */ int m, y, d; y = A10( d6word.y61, d6word.y62 ); m = A10( d6word.m61, d6word.m62 ); d = A10( d6word.d61, d6word.d62 ); return( d + 31*( m + 12*(y-YZERO) ) ); } static day9( p ) register int *p; { int m, y, d; y = A10( p->y1, p->y2 ); m = A10( p->m1, p->m2 ); d = A10( p->d1, p->d2 ); return( d + 31*( m + 12*(y-YZERO) ) ); } static int dfold( dayno, timeno ){ int kk; kk = ( day*dayno + timeno) / 32768.; } int prestime(){ int date[2]; drldrl( 021, date ); return( dfold( day9(date), _q_reg ) ); } # define DODRL ar[0] = status; ar[1] = &b.cat1; drldrl(30,sp1,sp2); p=ar[0]<<18; static struct { int fn1, fn2; int ftm; } fbb[MAXCSIZE]; static int catsiz; getcat() { register i, *p, j; int asname[4]; struct catdesc b; int sp1, sp2, temp; int ar[2], status[2]; int filbuf[380]; gtcalled = 1; sp1 = ar; sp1 =>> 18; sp2 = filbuf; sp2 =>>18; sp2.lhs = 19; b.cat1 = b.cat2 = b.file1 = -1; b.cpass1 = b.cpass2 = 0202020202020; DODRL sp2.lhs++; for( i=0; p!=0 && iname1; fbb[i].fn2 = b.file2 = p->name2; b.filep1 = p->passw1; b.filep2 = p->passw2; b.endmark = -1; temp = 0; temp.slot = p->tused; fbb[i].ftm = dfold( day6(p->datmod), temp ); DODRL } catsiz = i; } exists( p ) struct nameblock *p; { char *s, *cp, name[13]; int i, *p, bcd[2]; /* cheat about names with slashes -- try opening; if it is openable, it exists, and assume it was made at t=1 (long time ago); otherwise, assume it does not exist */ cp = p->namep; for(s=cp ; *s ; ++s) if(*s == '/') if(i = copen(cp,'r') < 0) return(0); else { cclose(i); return(1); } if(gtcalled == 0) getcat(); p = name; for( i=0; *cp; ++i ) name[i] = *cp++; while( i<12 ) name[i++] = ' '; f9to6( *p, bcd[0], 12 ); for ( i=0; inxtpattern) if(! unequal(pat, patp->patval)) return(0); patp = ALLOC(pattern); patp->nxtpattern = firstpat; firstpat = patp; patp->patval = copys(pat); endir = 0; for(p=pat; *p!='\0'; ++p) if(*p=='/') endir = p; if(endir==0) { dirname = ""; dirpref = ""; filepat = pat; } else { fatal("File name has an embedded slash"); dirname = pat; *endir = '\0'; dirpref = concat(dirname, "/", temp); filepat = endir+1; } for(i=0;inextp = nextdbl; thisdbl->depname = q; nextdbl = thisdbl; } } } if(endir != 0) *endir = '/'; return(thisdbl); } /* stolen from glob through find */ amatch(s, p) char *s, *p; { register int cc, scc, k; int c, lc; scc = *s; lc = 077777; switch (c = *p) { case '[': k = 0; while (cc = *++p) { switch (cc) { case ']': if (k) return(amatch(++s, ++p)); else return(0); case '-': k =| lc <= scc & scc <= (cc=p[1]); } if (scc==(lc=cc)) k++; } return(0); case '?': caseq: if(scc) return(amatch(++s, ++p)); return(0); case '*': return(umatch(s, ++p)); case 0: return(!scc); } if (c==scc) goto caseq; return(0); } umatch(s, p) char *s, *p; { if(*p==0) return(1); while(*s) if (amatch(s++,p)) return(1); return(0); } dosys(comstring,nohalt) char *comstring; int nohalt; { char *p; for(p=comstring ; *p!='\0' ; ++p); if( p-comstring > 80) fatal("Command string longer than 80 characters"); system(comstring); return(0); } touch(s) char *s; { fprintf(stderr, "touch not yet implemented on GCOS\n"); cexit(2); } labtab->chain = rep; break; } tp = lab->asc; while((*tp++ = *cp++)) if(tp >= &(lab->asc[8])) { fprintf(stderr, LTL, linebuf); exit(2); } cp--; *--tp = '\0'; if(lpt = search(lab)) { if(lpt->address) { rep->lb1 = lpt->address; } else { pt = lpt->chain; while(pt1 = pt->lb1) pt = pt1; pt->lb1 = rep; } } else { lab->chain = rep; bin/make/misc.c 444 0 12 11031 4455475016 6640 /* static char *sccsid = "@(#)misc.c 4.4 (Berkeley) 87/05/21"; */ #include "defs" FSTATIC struct nameblock *hashtab[HASHSIZE]; FSTATIC int nhashed = 0; /* simple linear hash. hash function is sum of characters mod hash table size. */ hashloc(s) char *s; { register int i; register int hashval; register char *t; hashval = 0; for(t=s; *t!='\0' ; ++t) hashval += *t; hashval %= HASHSIZE; for(i=hashval; hashtab[i]!=0 && unequal(s,hashtab[i]->namep); i = (i+1)%HASHSIZE ) ; return(i); } struct nameblock *srchname(s) char *s; { return( hashtab[hashloc(s)] ); } struct nameblock *makename(s) char *s; { /* make a fresh copy of the string s */ char *copys(); register struct nameblock *p; if(nhashed++ > HASHSIZE-3) fatal("Hash table overflow"); p = ALLOC(nameblock); p->nxtnameblock = firstname; p->namep = copys(s); p->linep = 0; p->done = 0; p->septype = 0; p->modtime = 0; firstname = p; if(mainname == NULL) if(s[0]!='.' || hasslash(s) ) mainname = p; hashtab[hashloc(s)] = p; return(p); } hasslash(s) char *s; { for( ; *s ; ++s) if(*s == '/') return(YES); return(NO); } char *copys(s) register char *s; { char *calloc(); register char *t, *t0; if( (t = t0 = calloc( strlen(s)+1 , sizeof(char)) ) == NULL) fatal("out of memory"); while(*t++ = *s++) ; return(t0); } char *concat(a,b,c) /* c = concatenation of a and b */ register char *a,*b; char *c; { register char *t; t = c; while(*t = *a++) t++; while(*t++ = *b++); return(c); } suffix(a,b,p) /* is b the suffix of a? if so, set p = prefix */ register char *a,*b,*p; { char *a0,*b0; a0 = a; b0 = b; while(*a++); while(*b++); if( (a-a0) < (b-b0) ) return(0); while(b>b0) if(*--a != *--b) return(0); while(a0 100) fatal("infinitely recursive macro?"); if(a!=0) while(*a) { if(*a != '$') *b++ = *a++; else if(*++a=='\0' || *a=='$') *b++ = *a++; else { s = vname; if( *a=='(' || *a=='{' ) { closer = ( *a=='(' ? ')' : '}'); ++a; while(*a == ' ') ++a; while(*a!=' ' && *a!=closer && *a!='\0') *s++ = *a++; while(*a!=closer && *a!='\0') ++a; if(*a == closer) ++a; } else *s++ = *a++; *s = '\0'; if( (vbp = varptr(vname)) ->varval != 0) { b = subst(vbp->varval, b); vbp->used = YES; } } } *b = '\0'; --depth; return(b); } setvar(v,s) char *v, *s; { struct varblock *varptr(), *p; p = varptr(v); if(p->noreset == 0) { p->varval = s; p->noreset = inarglist; if(p->used && unequal(v,"@") && unequal(v,"*") && unequal(v,"<") && unequal(v,"?") ) fprintf(stderr, "Warning: %s changed after being used\n",v); } } eqsign(a) /*look for arguments with equal signs but not colons */ char *a; { register char *s, *t, c; while(*a == ' ') ++a; for(s=a ; *s!='\0' && *s!=':' ; ++s) if(*s == '=') { for(t = a ; *t!='=' && *t!=' ' && *t!='\t' ; ++t ); c = *t; *t = '\0'; for(++s; *s==' ' || *s=='\t' ; ++s); setvar(a, copys(s)); *t = c; return(YES); } return(NO); } struct varblock *varptr(v) char *v; { register struct varblock *vp; for(vp = firstvar; vp ; vp = vp->nxtvarblock) if(! unequal(v , vp->varname)) return(vp); vp = ALLOC(varblock); vp->nxtvarblock = firstvar; firstvar = vp; vp->varname = copys(v); vp->varval = 0; return(vp); } fatal1(s, t) char *s, *t; { char buf[BUFSIZ]; sprintf(buf, s, t); fatal(buf); } fatal(s) char *s; { if(s) fprintf(stderr, "Make: %s. Stop.\n", s); else fprintf(stderr, "\nStop.\n"); #ifdef unix exit(1); #endif #ifdef gcos exit(0); #endif } yyerror(s) char *s; { char buf[50]; extern int yylineno; sprintf(buf, "line %d: %s", yylineno, s); fatal(buf); } struct chain *appendq(head, tail) struct chain *head; char *tail; { register struct chain *p, *q; p = ALLOC(chain); p->datap = tail; if(head) { for(q = head ; q->nextp ; q = q->nextp) ; q->nextp = p; return(head); } else return(p); } char *mkqlist(p) struct chain *p; { register char *qbufp, *s; static char qbuf[QBUFMAX]; if(p == NULL) { qbuf[0] = '\0'; return; } qbufp = qbuf; for( ; p ; p = p->nextp) { s = p->datap; if(qbufp+strlen(s) > &qbuf[QBUFMAX-3]) { fprintf(stderr, "$? list too long\n"); break; } while (*s) *qbufp++ = *s++; *qbufp++ = ' '; } *--qbufp = '\0'; return(qbuf); } depname = q; nextdbl = thisdbl; } } } if(endir != 0) *endir = '/'; return(thisdbl); } /* stolen from glob through find */ amatch(s, p) char *s, *p; { register int cc, scc, k; int c, lc; scc = *s; lc = 077777; switch (c = *p) { case '[': k = 0; while (cc = *++p) { switch (cc) { case ']': if (k) return(amatch(++s, ++p)); else return(0); case '-': k =| lc <= scc & scc <= (cc=p[1]); } if (scc==(lc=cc)) k++; } return(0bin/make/main.c 444 0 12 16160 5051070500 6617 /* static char *sccsid = "@(#)main.c 4.9 (Berkeley) 87/05/21"; */ # include "defs" /* command make to update programs. Flags: 'd' print out debugging comments 'p' print out a version of the input graph 's' silent mode--don't print out commands 'f' the next argument is the name of the description file; "makefile" is the default 'i' ignore error codes from the shell 'S' stop after any command fails (normally do parallel work) 'n' don't issue, just print, commands 't' touch (update time of) files but don't issue command 'q' don't do anything, but check if object is up to date; returns exit code 0 if up to date, -1 if not 'e' environment variables have precedence over makefiles */ struct nameblock *mainname = NULL; struct nameblock *firstname = NULL; struct lineblock *sufflist = NULL; struct varblock *firstvar = NULL; struct pattern *firstpat = NULL; struct dirhdr *firstod = NULL; #include int sigivalue = 0; int sigqvalue = 0; int waitpid = 0; int dbgflag = NO; int prtrflag = NO; int silflag = NO; int noexflag = NO; int keepgoing = NO; int noruleflag = NO; int touchflag = NO; int questflag = NO; int ndocoms = NO; int ignerr = NO; /* default is to stop on error */ int okdel = YES; int doenvlast = NO; int inarglist; #ifdef pwb char *prompt = ">"; /* other systems -- pick what you want */ #else char *prompt = ""; /* other systems -- pick what you want */ #endif int nopdir = 0; char junkname[20]; char funny[128]; char options[26 + 1] = { '-' }; main(argc,argv) int argc; char *argv[]; { register struct nameblock *p; register int i, j; int descset, nfargs; TIMETYPE tjunk; char c, *s; static char onechar[2] = 'X'; #ifdef unix int intrupt(); #endif char *op = options + 1; #ifdef METERFILE meter(METERFILE); #endif descset = 0; funny['\0'] = (META | TERMINAL); for(s = "=|^();&<>*?[]:$`'\"\\\n" ; *s ; ++s) funny[*s] |= META; for(s = "\n\t :;&>|" ; *s ; ++s) funny[*s] |= TERMINAL; inarglist = 1; for(i=1; i= argc-1) fatal("No description argument after -f flag"); if( rddescf(argv[i+1]) ) fatal1("Cannot open %s", argv[i+1]); argv[i+1] = 0; ++descset; break; case 'e': doenvlast = YES; break; default: onechar[0] = c; /* to make lint happy */ fatal1("Unknown flag argument %s", onechar); } } argv[i] = 0; } *op++ = '\0'; if (strcmp(options, "-") == 0) *options = '\0'; setvar("MFLAGS", options); /* MFLAGS=options to make */ setvar("MACHINE", MACHINE); if( !descset ) #ifdef unix if( rddescf("makefile") ) rddescf("Makefile"); #endif #ifdef gcos rddescf("makefile"); #endif if (doenvlast == YES) readenv(); if(prtrflag) printdesc(NO); if( srchname(".IGNORE") ) ++ignerr; if( srchname(".SILENT") ) silflag = 1; if(p=srchname(".SUFFIXES")) sufflist = p->linep; if( !sufflist ) fprintf(stderr,"No suffix list.\n"); #ifdef unix sigivalue = (int) signal(SIGINT, SIG_IGN) & 01; sigqvalue = (int) signal(SIGQUIT, SIG_IGN) & 01; enbint(intrupt); #endif nfargs = 0; for(i=1; i #ifdef unix intrupt() { struct varblock *varptr(); char *p; TIMETYPE exists(); struct stat sbuf; if(okdel && !noexflag && !touchflag && (p = varptr("@")->varval) && (stat(p, &sbuf) >= 0 && (sbuf.st_mode&S_IFMT) == S_IFREG) && !isprecious(p) ) { fprintf(stderr, "\n*** %s removed.", p); unlink(p); } if(junkname[0]) unlink(junkname); fprintf(stderr, "\n"); exit(2); } isprecious(p) char *p; { register struct lineblock *lp; register struct depblock *dp; register struct nameblock *np; if(np = srchname(".PRECIOUS")) for(lp = np->linep ; lp ; lp = lp->nxtlineblock) for(dp = lp->depp ; dp ; dp = dp->nxtdepblock) if(! unequal(p, dp->depname->namep)) return(YES); return(NO); } enbint(k) int (*k)(); { if(sigivalue == 0) signal(SIGINT,k); if(sigqvalue == 0) signal(SIGQUIT,k); } #endif extern char *builtin[]; char **linesptr = builtin; FILE * fin; int firstrd = 0; rddescf(descfile) char *descfile; { FILE * k; /* read and parse description */ if( !firstrd++ ) { if( !noruleflag ) rdd1( (FILE *) NULL); if (doenvlast == NO) readenv(); #ifdef pwb { char *nlog, s[BUFSIZ]; nlog = logdir(); if ( (k=fopen( concat(nlog,"/makecomm",s), "r")) != NULL) rdd1(k); else if ( (k=fopen( concat(nlog,"/Makecomm",s), "r")) != NULL) rdd1(k); if ( (k=fopen("makecomm", "r")) != NULL) rdd1(k); else if ( (k=fopen("Makecomm", "r")) != NULL) rdd1(k); } #endif } if(! unequal(descfile, "-")) return( rdd1(stdin) ); if( (k = fopen(descfile,"r")) != NULL) return( rdd1(k) ); return(1); } rdd1(k) FILE * k; { extern int yylineno; extern char *zznextc; fin = k; yylineno = 0; zznextc = 0; if( yyparse() ) fatal("Description file error"); if(fin != NULL && fin != stdin) fclose(fin); return(0); } printdesc(prntflag) int prntflag; { struct nameblock *p; struct depblock *dp; struct varblock *vp; struct dirhdr *od; struct shblock *sp; struct lineblock *lp; #ifdef unix if(prntflag) { printf("Open directories:\n"); for (od = firstod; od; od = od->nxtopendir) printf("\t%d: %s\n", od->dirfc->dd_fd, od->dirn); } #endif if(firstvar != 0) printf("Macros:\n"); for(vp = firstvar; vp ; vp = vp->nxtvarblock) printf("\t%s = %s\n" , vp->varname , vp->varval); for(p = firstname; p; p = p->nxtnameblock) { printf("\n\n%s",p->namep); if(p->linep != 0) printf(":"); if(prntflag) printf(" done=%d",p->done); if(p==mainname) printf(" (MAIN NAME)"); for(lp = p->linep ; lp ; lp = lp->nxtlineblock) { if( dp = lp->depp ) { printf("\n depends on:"); for(; dp ; dp = dp->nxtdepblock) if(dp->depname != 0) printf(" %s ", dp->depname->namep); } if(sp = lp->shp) { printf("\n commands:\n"); for( ; sp!=0 ; sp = sp->nxtshblock) printf("\t%s\n", sp->shbp); } } } printf("\n"); fflush(stdout); } readenv() { register char **ep, *p; extern char **environ; for(ep = environ ; *ep ; ++ep) { for (p = *ep; *p; p++) { if (isalnum(*p)) continue; if (*p == '=') { eqsign(*ep); } break; } } } ; break; case 'f': op--; /* don't pass this one */ if(i >= argc-1) fatal("No description argument after -f flag"); if( rddescf(argv[i+1]) ) fatal1("Cannot open %s", argv[i+1]); argv[i+1] = 0; ++descset; break; case 'e': doenvlast = YES; break; default: onechar[0] = c; /* to make lint happy */ fatal1("Unknown flag argument %s", onecbin/make/doname.c 444 0 12 16543 5514435545 7165 /* static char *sccsid = "@(#)doname.c 4.9.1 (2.11BSD GTE) 1/1/94"; */ #include "defs" #include #include /* BASIC PROCEDURE. RECURSIVE. */ /* p->done = 0 don't know what to do yet p->done = 1 file in process of being updated p->done = 2 file already exists in current state p->done = 3 file make failed */ extern char *sys_siglist[], arfile[], *arfname; doname(p, reclevel, tval) register struct nameblock *p; int reclevel; TIMETYPE *tval; { int errstat; u_char okdel1; u_char didwork; TIMETYPE td, td1, tdep, ptime, ptime1, prestime(); register struct depblock *q; struct depblock *qtemp, *srchdir(), *suffp, *suffp1; struct nameblock *p1, *p2; struct shblock *implcom, *explcom; register struct lineblock *lp; struct lineblock *lp1, *lp2; #ifdef pdp11 /* temp and sourcename are mutually exclusive - save 254 bytes of stack by * reusing sourcename's buffer */ char sourcename[256], prefix[256], *temp = sourcename, concsuff[20]; #else char sourcename[BUFSIZ], prefix[BUFSIZ], temp[BUFSIZ], concsuff[20]; #endif char *pnamep, *p1namep, *cp, *savenamep = NULL; char *mkqlist(); struct chain *qchain, *appendq(); { /* * VPATH= ${PATH1}:${PATH2} didn't work. This fix is so ugly I don't * even want to think about it. Basically it grabs VPATH and * explicitly does macro expansion before resolving names. Why * VPATH didn't get handled correctly I have no idea; the symptom * was that, while macro expansion got done, the .c files in the * non-local directories wouldn't be found. */ static struct varblock *vpath_cp; struct varblock *varptr(); static char vpath_exp[256]; if (!vpath_cp) { vpath_cp = varptr("VPATH"); if (vpath_cp->varval) { subst(vpath_cp->varval, vpath_exp); setvar("VPATH", vpath_exp); } } } if(p == 0) { *tval = 0; return(0); } if(dbgflag) { printf("doname(%s,%d)\n",p->namep,reclevel); fflush(stdout); } if(p->done > 0) { *tval = p->modtime; return(p->done == 3); } errstat = 0; tdep = 0; implcom = 0; explcom = 0; ptime = exists(p); ptime1 = 0; didwork = NO; p->done = 1; /* avoid infinite loops */ qchain = NULL; /* Expand any names that have embedded metacharaters */ for(lp = p->linep ; lp ; lp = lp->nxtlineblock) for(q = lp->depp ; q ; q=qtemp ) { qtemp = q->nxtdepblock; expand(q); } /* make sure all dependents are up to date */ for(lp = p->linep ; lp ; lp = lp->nxtlineblock) { td = 0; for(q = lp->depp ; q ; q = q->nxtdepblock) { errstat += doname(q->depname, reclevel+1, &td1); if(dbgflag) printf("TIME(%s)=%ld\n", q->depname->namep, td1); if(td1 > td) td = td1; if(ptime < td1) qchain = appendq(qchain, q->depname->namep); } if(p->septype == SOMEDEPS) { if(lp->shp!=0) if( ptimedepp==0) { okdel1 = okdel; okdel = NO; setvar("@", p->namep); setvar("?", mkqlist(qchain) ); qchain = NULL; if( !questflag ) errstat += docom(lp->shp); setvar("@", (char *) NULL); okdel = okdel1; ptime1 = prestime(); didwork = YES; } } else { if(lp->shp != 0) { if(explcom) fprintf(stderr, "Too many command lines for `%s'\n", p->namep); else explcom = lp->shp; } if(td > tdep) tdep = td; } } /* Look for implicit dependents, using suffix rules */ if (index(p->namep, '(')) { savenamep = p->namep; p->namep = arfname; } for(lp = sufflist ; lp ; lp = lp->nxtlineblock) for(suffp = lp->depp ; suffp ; suffp = suffp->nxtdepblock) { pnamep = suffp->depname->namep; if(suffix(p->namep , pnamep , prefix)) { if (savenamep) pnamep = ".a"; srchdir( concat(prefix,"*",temp), NO, (struct depblock *) NULL); for(lp1 = sufflist ; lp1 ; lp1 = lp1->nxtlineblock) for(suffp1=lp1->depp ; suffp1 ; suffp1 = suffp1->nxtdepblock) { p1namep = suffp1->depname->namep; if( (p1=srchname(concat(p1namep, pnamep ,concsuff))) && (p2=srchname(concat(prefix, p1namep ,sourcename))) ) { errstat += doname(p2, reclevel+1, &td); if(ptime < td) qchain = appendq(qchain, p2->namep); if(dbgflag) printf("TIME(%s)=%ld\n", p2->namep, td); if(td > tdep) tdep = td; setvar("*", prefix); if (p2->alias) setvar("<", copys(p2->alias)); else setvar("<", copys(p2->namep)); for(lp2=p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) if(implcom = lp2->shp) break; goto endloop; } } cp = rindex(prefix, '/'); if (cp++ == 0) cp = prefix; setvar("*", cp); } } endloop: if (savenamep) p->namep = savenamep; if(errstat==0 && (ptime0 ? tdep : prestime() ); setvar("@", savenamep ? arfile : p->namep); setvar("?", mkqlist(qchain) ); if(explcom) errstat += docom(explcom); else if(implcom) errstat += docom(implcom); else if(p->septype == 0) if(p1=srchname(".DEFAULT")) { if (p->alias) setvar("<", p->alias); else setvar("<", p->namep); for(lp2 = p1->linep ; lp2 ; lp2 = lp2->nxtlineblock) if(implcom = lp2->shp) { errstat += docom(implcom); break; } } else if(keepgoing) { printf("Don't know how to make %s\n", p->namep); ++errstat; } else fatal1(" Don't know how to make %s", p->namep); setvar("@", (char *) NULL); if(noexflag || (ptime = exists(p)) == 0) ptime = prestime(); } else if(errstat!=0 && reclevel==0) printf("`%s' not remade because of errors\n", p->namep); else if(!questflag && reclevel==0 && didwork==NO) printf("`%s' is up to date.\n", p->namep); if(questflag && reclevel==0) exit(ndocoms>0 ? -1 : 0); p->done = (errstat ? 3 : 2); if(ptime1 > ptime) ptime = ptime1; p->modtime = ptime; *tval = ptime; return(errstat); } docom(q) struct shblock *q; { register char *s; struct varblock *varptr(); register int ign, nopr; char string[OUTMAX]; char string2[OUTMAX]; ++ndocoms; if(questflag) return(NO); if(touchflag) { s = varptr("@")->varval; if(!silflag) printf("touch(%s)\n", s); if(!noexflag) touch(YES, s); } else for( ; q ; q = q->nxtshblock ) { subst(q->shbp,string2); fixname(string2, string); ign = ignerr; nopr = NO; for(s = string ; *s=='-' || *s=='@' ; ++s) if(*s == '-') ign = YES; else nopr = YES; if( docom1(s, ign, nopr) && !ign) if(keepgoing) return(YES); else fatal( (char *) NULL); } return(NO); } docom1(comstring, nohalt, noprint) register char *comstring; int nohalt, noprint; { register int status; if(comstring[0] == '\0') return(0); if(!silflag && (!noprint || noexflag) ) { printf("%s%s\n", (noexflag ? "" : prompt), comstring); fflush(stdout); } if(noexflag) return(0); if( status = dosys(comstring, nohalt) ) { unsigned sig = status & 0177; if( sig ) { if (sig < NSIG && sys_siglist[sig] != NULL && *sys_siglist[sig] != '\0') printf("*** %s", sys_siglist[sig]); else printf("*** Signal %d", sig); if (status & 0200) printf(" - core dumped"); } else printf("*** Exit %d", status>>8 ); if(nohalt) printf(" (ignored)\n"); else printf("\n"); fflush(stdout); } return(status); } /* If there are any Shell meta characters in the name, expand into a list, after searching directory */ expand(q) register struct depblock *q; { register char *s; char *s1; struct depblock *p, *srchdir(); if (q->depname == NULL) return; s1 = q->depname->namep; for(s=s1 ; ;) switch(*s++) { case '\0': return; case '*': case '?': case '[': if( p = srchdir(s1 , YES, q->nxtdepblock) ) { q->nxtdepblock = p; q->depname = 0; } return; } } * reusing sourcename's buffer */ char sourcename[256], prefix[256], *temp = sourcename, concsuff[20]; #else char sourcename[BUFSIZ], prefix[BUFSIZ], temp[BUbin/make/Makefile 444 0 12 1620 5513161577 7164 # Description file for the Make command # Makefile 4.5 94/1/3 OBJECTS=ident.o main.o doname.o misc.o files.o dosys.o gram.o LIBES= LINT= lint -ps XSTR= /usr/ucb/xstr CFLAGS= -O -I. -I../ar SEPFLAG= -i # Special massaging of C files for sharing of strings .c.o: ${CC} -E ${CFLAGS} $*.c | ${XSTR} -c - ${CC} -c ${CFLAGS} x.c mv -f x.o $*.o rm -f x.c all: make make: ${OBJECTS} strings.o ${CC} -o make ${CFLAGS} ${SEPFLAG} ${OBJECTS} strings.o ${LIBES} ${OBJECTS}: defs clean: -rm -f *.o gram.c make a.out errs x.c xs.c strings install: make install -s make ${DESTDIR}/bin/make lint : dosys.c doname.c files.c main.c misc.c ident.c gram.c ${LINT} dosys.c doname.c files.c main.c misc.c ident.c gram.c rm -f gram.c gram.c: gram.y yacc gram.y fgrep -v "static char yaccpar_sccsid" y.tab.c >gram.c rm -f y.tab.c strings.o: strings ${XSTR} ${CC} -c xs.c mv -f xs.o strings.o rm -f xs.c name[256], prefix[256], *temp = sourcename, concsuff[20]; #else char sourcename[BUFSIZ], prefix[BUFSIZ], temp[BUbin/make/gram.y 444 0 12 12000 5051307413 6642 %{#include "defs" /* static char *sccsid = "@(#)gram.y 4.1 (Berkeley) 81/02/28"; */ %} %term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER %union { struct shblock *yshblock; struct depblock *ydepblock; struct nameblock *ynameblock; } %type SHELLINE, shlist, shellist %type NAME, namelist %type deplist, dlist %% %{ struct depblock *pp; FSTATIC struct shblock *prevshp; FSTATIC struct nameblock *lefts[NLEFTS]; struct nameblock *leftp; FSTATIC int nlefts; struct lineblock *lp, *lpp; FSTATIC struct depblock *prevdep; FSTATIC int sepc; %} file: | file comline ; comline: START | MACRODEF | START namelist deplist shellist = { while( --nlefts >= 0) { leftp = lefts[nlefts]; if(leftp->septype == 0) leftp->septype = sepc; else if(leftp->septype != sepc) fprintf(stderr, "Inconsistent rules lines for `%s'\n", leftp->namep); else if(sepc==ALLDEPS && *(leftp->namep)!='.' && $4!=0) { for(lp=leftp->linep; lp->nxtlineblock!=0; lp=lp->nxtlineblock) if(lp->shp) fprintf(stderr, "Multiple rules lines for `%s'\n", leftp->namep); } lp = ALLOC(lineblock); lp->nxtlineblock = NULL; lp->depp = $3; lp->shp = $4; if(! unequal(leftp->namep, ".SUFFIXES") && $3==0) leftp->linep = 0; else if(leftp->linep == 0) leftp->linep = lp; else { for(lpp = leftp->linep; lpp->nxtlineblock; lpp = lpp->nxtlineblock) ; if(sepc==ALLDEPS && leftp->namep[0]=='.') lpp->shp = 0; lpp->nxtlineblock = lp; } } } | error ; namelist: NAME = { lefts[0] = $1; nlefts = 1; } | namelist NAME = { lefts[nlefts++] = $2; if(nlefts>=NLEFTS) fatal("Too many lefts"); } ; deplist: { char junk[10]; sprintf(junk, "%d", yylineno); fatal1("Must be a separator on rules line %s", junk); } | dlist ; dlist: sepchar = { prevdep = 0; $$ = 0; } | dlist NAME = { pp = ALLOC(depblock); pp->nxtdepblock = NULL; pp->depname = $2; if(prevdep == 0) $$ = pp; else prevdep->nxtdepblock = pp; prevdep = pp; } ; sepchar: COLON = { sepc = ALLDEPS; } | DOUBLECOLON = { sepc = SOMEDEPS; } ; shellist: = {$$ = 0; } | shlist = { $$ = $1; } ; shlist: SHELLINE = { $$ = $1; prevshp = $1; } | shlist SHELLINE = { $$ = $1; prevshp->nxtshblock = $2; prevshp = $2; } ; %% char *zznextc; /* zero if need another line; otherwise points to next char */ int yylineno; extern FILE * fin; yylex() { register char *p; register char *q; char word[INMAX]; if(zznextc == 0) return( nextlin() ); while( isspace(*zznextc) ) ++zznextc; if(*zznextc == '\0') return( nextlin() ); if(*zznextc == ':') { if(*++zznextc == ':') { ++zznextc; return(DOUBLECOLON); } else return(COLON); } if(*zznextc == '>') { ++zznextc; return(GREATER); } if(*zznextc == ';') return( retsh(zznextc) ); p = zznextc; q = word; while( ! ( funny[*p] & TERMINAL) ) *q++ = *p++; if(p != zznextc) { *q = '\0'; if((yylval.ynameblock=srchname(word))==0) yylval.ynameblock = makename(word); zznextc = p; return(NAME); } else { fprintf(stderr,"Bad character %c (octal %o), line %d", *zznextc,*zznextc,yylineno); fatal( (char *) NULL ); } return(0); /* never executed */ } retsh(q) char *q; { register char *p; struct shblock *sp; char *copys(); for(p=q+1 ; *p==' '||*p=='\t' ; ++p) ; sp = ALLOC(shblock); sp->nxtshblock = NULL; sp->shbp = (fin == NULL ? p : copys(p) ); yylval.yshblock = sp; zznextc = 0; return(SHELLINE); } nextlin() { static char yytext[INMAX]; static char *yytextl = yytext+INMAX; char *text, templin[INMAX]; register char c; register char *p, *t; char lastch, *lastchp; extern char **linesptr; int incom; int kc; again: incom = NO; zznextc = 0; if(fin == NULL) { if( (text = *linesptr++) == 0) return(0); ++yylineno; } else { for(p = text = yytext ; p I/O System (stdio.h) 2.16 Removed references to double floats and macro HAVELONGS; committed to use of long ints for times. 2.17 Corrected metacharacter list in dosys.c. 2.18 Miscellaneous fixes 2.19 Updated files.c to use include file stat.h 2.20 Added -q flag for Mike Lesk 2.21 Added AWK rules and .w suffix to files.c 2.22 Added colon to the list of metacharacters 2.23 Macro substitutions on dependency lines. Redid argument and macro setting. Close files before exec'ing. Print > at beginning of command lines. No printing of commands beginnng with @. 2.24 Parametrized propt sequence in doname.c (4/1/77) 2.25 Added $? facility 2.26 Fixed bug in macro expansion 2.27 Repaired interrupt handling 2.28 Repaired bug in -n 2.29 Repaired bug in file closing and $? string creation 2.30 Repaired bug in grammar about command lines 2.31 Added -k flag, modified doname.c and defs 2.32 Made "keepgoing" the default, added -S flag, changed handling of funny characters internally 2.3 Small fixups to interrupt and quit handling. Changed default back to -k. 2.34 Added .PRECIOUS rule for interrupts 2.35 Added references to include files (due to TLL) 2.36 Fixed bug in lex.c so = permitted in rules on :; line 2.37 Miscellaneous code cleanups 2.38 Sleep one second after each touch in -t mode 2.39 Extended string[] declaration in doname.c 2.40 Permit recursive macro references 2.41 Separated YYLMAX into INMAX and OUTMAX macros, specifying longest input and output lines respectively. 2.42 Fixed bug involving :: lines without dependents 2.43 Main name is first name that contains a slash or doesn't begin with a dot 2.44 Fixed bug involving $$ on command line 2.45 Changed files.c to put .f before .e, .r and to use f77 instead of fc. 2.46 Changed dosys.c to eliminate copying and to call execvp. 2.47 Changed files.c to add ".out" suffix and rules. 2.48 Changed misc.c to permit tabs preceding = in macro definition 2.49 Added reference to . Removed -lS references from files.c 2.50 General cleanup to reduce lint messages. (changes in declarations and in uses of variables) 2.51 Further cleanup making use of new Yacc features. 2.52 2.53 Changed handling of "touch" 2.54 Fixed bug involving comments in lexical analyzer. 2.55 Ignore commands that begin with a # are comments. 2.56 Added = to list of META characters (to permit shell commands) 2.57 Changed lookarch and getobj to fix bugs. 2.58 Fixed interrupt handling. 2.59 Changed references to sprintf to accomodate new function definition Also fixed extern declarations. 2.60 Limited the number of open directories. 2.61 Added code to handle archives with ascii headers. */ $1; } ; shlist: SHELLINE = { $$ = $1; prevshp = $1; } | shlist SHELLINE = { $$ = $1; prevshp->nxtshblock = $2; prevshp = $2; } ; %% char *zznextc; /* zero if need another line; otherwise points to next char */ int yylineno; extern FILE * fin; yylex() { register char *p; register char *q; char word[INMAX]; if(zznextc == 0) return( nextlibin/make/files.c 444 0 0 25613 5514435566 7002 /* static char *sccsid = "@(#)files.c 4.16.1 (2.11BSD) 1/3/94"; */ #include #include /* UNIX DEPENDENT PROCEDURES */ /* DEFAULT RULES FOR UNIX */ char *builtin[] = { #ifdef pwb ".SUFFIXES : .L .out .a .o .c .f .e .r .y .yr .ye .l .s .z .x .t .h .cl", #else ".SUFFIXES : .out .a .o .c .F .f .e .r .y .yr .ye .l .s .cl .p", #endif "YACC=yacc", "YACCR=yacc -r", "YACCE=yacc -e", "YFLAGS=", "LEX=lex", "LFLAGS=", "CC=cc", #if defined(vax) || defined(sun) || defined(tahoe) "AS=as", #else "AS=as -", #endif "PC=pc", "PFLAGS=", "CFLAGS=", "RC=f77", "RFLAGS=", "FC=f77", "EFLAGS=", "FFLAGS=", "LOADLIBES=", #ifdef pwb "SCOMP=scomp", "SCFLAGS=", "CMDICT=cmdict", "CMFLAGS=", #endif ".c.a :", "\t$(CC) $(CFLAGS) -c $<", "\tar r $@ $*.o", "\trm -f $*.o", ".c.o :", "\t$(CC) $(CFLAGS) -c $<", ".p.o :", "\t$(PC) $(PFLAGS) -c $<", ".cl.o :", "\tclass -c $<", ".e.o .r.o .F.o .f.o :", "\t$(FC) $(RFLAGS) $(EFLAGS) $(FFLAGS) -c $<", ".s.o :", "\t$(AS) -o $@ $<", ".y.o :", "\t$(YACC) $(YFLAGS) $<", "\t$(CC) $(CFLAGS) -c y.tab.c", "\trm y.tab.c", "\tmv y.tab.o $@", ".yr.o:", "\t$(YACCR) $(YFLAGS) $<", "\t$(RC) $(RFLAGS) -c y.tab.r", "\trm y.tab.r", "\tmv y.tab.o $@", ".ye.o :", "\t$(YACCE) $(YFLAGS) $<", "\t$(EC) $(RFLAGS) -c y.tab.e", "\trm y.tab.e", "\tmv y.tab.o $@", ".l.o :", "\t$(LEX) $(LFLAGS) $<", "\t$(CC) $(CFLAGS) -c lex.yy.c", "\trm lex.yy.c", "\tmv lex.yy.o $@", ".y.c :", "\t$(YACC) $(YFLAGS) $<", "\tmv y.tab.c $@", ".l.c :", "\t$(LEX) $(LFLAGS) $<", "\tmv lex.yy.c $@", ".yr.r:", "\t$(YACCR) $(YFLAGS) $<", "\tmv y.tab.r $@", ".ye.e :", "\t$(YACCE) $(YFLAGS) $<", "\tmv y.tab.e $@", #ifdef pwb ".o.L .c.L .t.L:", "\t$(SCOMP) $(SCFLAGS) $<", ".t.o:", "\t$(SCOMP) $(SCFLAGS) -c $<", ".t.c:", "\t$(SCOMP) $(SCFLAGS) -t $<", ".h.z .t.z:", "\t$(CMDICT) $(CMFLAGS) $<", ".h.x .t.x:", "\t$(CMDICT) $(CMFLAGS) -c $<", #endif ".s.out .c.out .o.out :", "\t$(CC) $(CFLAGS) $< $(LOADLIBES) -o $@", ".f.out .F.out .r.out .e.out :", "\t$(FC) $(EFLAGS) $(RFLAGS) $(FFLAGS) $< $(LOADLIBES) -o $@", "\t-rm $*.o", ".y.out :", "\t$(YACC) $(YFLAGS) $<", "\t$(CC) $(CFLAGS) y.tab.c $(LOADLIBES) -ly -o $@", "\trm y.tab.c", ".l.out :", "\t$(LEX) $(LFLAGS) $<", "\t$(CC) $(CFLAGS) lex.yy.c $(LOADLIBES) -ll -o $@", "\trm lex.yy.c", 0 }; #include "defs" #include TIMETYPE exists(pname) struct nameblock *pname; { struct stat buf; register char *s, *filename; TIMETYPE lookarch(); extern char *findfl(); filename = pname->namep; for(s = filename ; *s!='\0' && *s!='(' ; ++s) ; if(*s == '(') return(lookarch(filename)); if (stat(filename, &buf) < 0) { s = findfl(filename); if(s != (char *)-1) { pname->alias = copys(s); if(stat(pname->alias, &buf) == 0) return(buf.st_mtime); } return(0); } else return(buf.st_mtime); } TIMETYPE prestime() { TIMETYPE t; time(&t); return(t); } FSTATIC char nbuf[MAXNAMLEN + 1]; FSTATIC char *nbufend = &nbuf[MAXNAMLEN]; struct depblock *srchdir(pat, mkchain, nextdbl) register char *pat; /* pattern to be matched in directory */ int mkchain; /* nonzero if results to be remembered */ struct depblock *nextdbl; /* final value for chain */ { register DIR *dirf; int cldir; char *dirname, *dirpref, *endir, *filepat, *p, temp[MAXPATHLEN]; char fullname[MAXPATHLEN], *p1, *p2; struct nameblock *q; struct depblock *thisdbl; struct dirhdr *od; struct pattern *patp; struct varblock *cp, *varptr(); char *path, pth[MAXPATHLEN], *strcpy(); struct direct *dptr; thisdbl = 0; if(mkchain == NO) for(patp=firstpat ; patp ; patp = patp->nxtpattern) if(! unequal(pat, patp->patval)) return(0); patp = ALLOC(pattern); patp->nxtpattern = firstpat; firstpat = patp; patp->patval = copys(pat); endir = 0; for(p=pat; *p!='\0'; ++p) if(*p=='/') endir = p; if(endir==0) { dirpref = ""; filepat = pat; cp = varptr("VPATH"); if (cp->varval == NULL) path = "."; else { path = pth; *path = '\0'; /* * expand VPATH; this is almost surely not the place to do * this, but I have no intention whatsoever of attempting * to understand this code. */ if (strncmp(cp->varval, ".:", 2) != 0) { strcpy(pth,".:"); subst(cp->varval, pth + 2); } else subst(cp->varval, pth); } } else { *endir = '\0'; path = strcpy(pth, pat); dirpref = concat(pat, "/", temp); filepat = endir+1; } while (*path) { /* Loop thru each VPATH directory */ dirname = path; for (; *path; path++) if (*path == ':') { *path++ = '\0'; break; } dirf = NULL; cldir = NO; for(od = firstod; od; od = od->nxtopendir) if(! unequal(dirname, od->dirn) ) { dirf = od->dirfc; if (dirf != NULL) rewinddir(dirf); /* start over at the beginning */ break; } if(dirf == NULL) { dirf = opendir(dirname); if(nopdir >= MAXDIR) cldir = YES; else { ++nopdir; od = ALLOC(dirhdr); od->nxtopendir = firstod; firstod = od; od->dirfc = dirf; od->dirn = copys(dirname); fcntl(dirf->dd_fd, F_SETFD, 1); } } if(dirf == NULL) { fprintf(stderr, "Directory %s: ", dirname); fatal("Cannot open"); } else for (dptr = readdir(dirf); dptr != NULL; dptr = readdir(dirf)) { p1 = dptr->d_name; p2 = nbuf; while( (p2nxtdepblock = nextdbl; thisdbl->depname = q; nextdbl = thisdbl; } } } if(endir != 0) *endir = '/'; if(cldir) { closedir(dirf); dirf = NULL; } } /* End of VPATH loop */ return(thisdbl); } /* stolen from glob through find */ static amatch(s, p) char *s, *p; { register int cc, scc, k; int c, lc; scc = *s; lc = 077777; switch (c = *p) { case '[': k = 0; while (cc = *++p) { switch (cc) { case ']': if (k) return(amatch(++s, ++p)); else return(0); case '-': k |= (lc <= scc) & (scc <= (cc=p[1]) ) ; } if (scc==(lc=cc)) k++; } return(0); case '?': caseq: if(scc) return(amatch(++s, ++p)); return(0); case '*': return(umatch(s, ++p)); case 0: return(!scc); } if (c==scc) goto caseq; return(0); } static umatch(s, p) char *s, *p; { if(*p==0) return(1); while(*s) if (amatch(s++,p)) return(1); return(0); } #ifdef METERFILE #include int meteron = 0; /* default: metering off */ meter(file) char *file; { TIMETYPE tvec; char *p, *ctime(); FILE * mout; struct passwd *pwd, *getpwuid(); if(file==0 || meteron==0) return; pwd = getpwuid(getuid()); time(&tvec); if( (mout=fopen(file,"a")) != NULL ) { p = ctime(&tvec); p[16] = '\0'; fprintf(mout,"User %s, %s\n",pwd->pw_name,p+4); fclose(mout); } } #endif /* look inside archive for notation a(b) a(b) is file member b in archive a */ #include #include "archive.h" /* from 'ar's directory */ char arfile[MAXPATHLEN]; CHDR chdr; char *arfname = chdr.name; FILE *arfd; off_t arpos; TIMETYPE lookarch(filename) char *filename; { char *p, *q, *send, s[MAXNAMLEN + 1]; for (p = filename; *p!= '(' ; ++p) ; *p = '\0'; strcpy(arfile, filename); openarch(filename); *p++ = '('; send = s + sizeof(s); for( q = s; q < send && *p!='\0' && *p!=')' ; *q++ = *p++) ; *q++ = '\0'; while (getarch()) { if (!strcmp(arfname, s)) { clarch(); return(chdr.date); } arpos += (chdr.size + (chdr.size + chdr.lname & 1)); arpos += sizeof (struct ar_hdr); } strcpy(chdr.name, s); clarch(); return(0L); } clarch() { if (arfd) fclose( arfd ); } openarch(f) register char *f; { char magic[SARMAG]; arfd = fopen(f, "r"); if (arfd == NULL) return; fseek(arfd, 0L, 0); fread(magic, SARMAG, 1, arfd); arpos = SARMAG; if (strncmp(magic, ARMAG, SARMAG)) fatal1("%s is not an archive", f); } /* * "borrowed" from 'ld' because we didn't want to drag in everything * from 'ar'. The error checking was also ripped out, basically if any * of the criteria for being an archive are not met then a -1 is returned * and the rest of 'make' figures out what to do (bails out). */ typedef struct ar_hdr HDR; extern long strtol(); /* Convert ar header field to an integer. */ #define AR_ATOI(from, to, len, base) { \ bcopy(from, buf, len); \ buf[len] = '\0'; \ to = strtol(buf, (char **)NULL, base); \ } getarch() { char hb[sizeof(HDR) + 1]; /* real header */ struct ar_hdr arhead; register HDR *hdr; register int len; int nr; register char *p; char buf[20]; if (!arfd) return(0); fseek(arfd, arpos, 0); nr = fread(hb, 1, sizeof(HDR), arfd); if (nr != sizeof(HDR)) return(0); hdr = (HDR *)hb; if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1)) return(0); /* Convert the header into the internal format. */ #define DECIMAL 10 #define OCTAL 8 AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL); AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL); AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL); AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL); AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL); /* Leading spaces should never happen. */ if (hdr->ar_name[0] == ' ') return(-1); /* * Long name support. Set the "real" size of the file, and the * long name flag/size. */ if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) { chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1); if (len <= 0 || len > MAXNAMLEN) return(-1); nr = fread(chdr.name, 1, (size_t)len, arfd); if (nr != len) return(0); chdr.name[len] = 0; chdr.size -= len; } else { chdr.lname = 0; bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name)); /* Strip trailing spaces, null terminate. */ for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p); *++p = '\0'; } return(1); } /* * findfl(name) (like execvp, but does path search and finds files) */ static char fname[128]; char *execat(); char *findfl(name) register char *name; { register char *p; struct varblock *cp, *varptr(); struct stat buf; for (p = name; *p; p++) if(*p == '/') return(name); cp = varptr("VPATH"); if(cp->varval == NULL || *cp->varval == 0) p = ":"; else p = cp->varval; do { p = execat(p, name, fname); if(stat(fname,&buf) >= 0) return(fname); } while (p); return((char *)-1); } char *execat(s1, s2, si) register char *s1, *s2; char *si; { register char *s; s = si; while (*s1 && *s1 != ':' && *s1 != '-') *s++ = *s1++; if (si != s) *s++ = '/'; while (*s2) *s++ = *s2++; *s = '\0'; return(*s1? ++s1: 0); } /* copy s to d, changing file names to file aliases */ fixname(s, d) char *s, *d; { register char *r, *q; struct nameblock *pn; char name[MAXPATHLEN]; while (*s) { if (isspace(*s)) *d++ = *s++; else { r = name; while (*s) { if (isspace(*s)) break; *r++ = *s++; } *r = '\0'; if (((pn = srchname(name)) != 0) && (pn->alias)) q = pn->alias; else q = name; while (*q) *d++ = *q++; } } *d = '\0'; } path = pth; *path = '\0'; /* * expand VPATH; this is almost surely not the place to do * this, but Ibin/make/defs 444 0 12 4606 5051305105 6357 /* defs 4.10 86/03/22 */ #include #include #include #include #define SHELLCOM "/bin/sh" typedef long int TIMETYPE; /* to install metering, add a statement like * #define METERFILE "/usr/sif/make/Meter" * to turn metering on, set external variable meteron to 1. */ /* define FSTATIC to be static on systems with C compilers supporting file-static; otherwise define it to be null */ #define FSTATIC static #define NO 0 #define YES 1 #define unequal strcmp #ifdef BSD2_10 #define HASHSIZE 509 #define NLEFTS 80 #define NCHARS 500 #define NINTS 250 #define INMAX 1350 #define OUTMAX 2300 #define MAXDIR 10 #else !BSD2_10 #define HASHSIZE 1021 #define NLEFTS 512 #define NCHARS 500 #define NINTS 250 #define INMAX 7000 #define OUTMAX 7000 #define MAXDIR 10 #endif BSD2_10 #define QBUFMAX 5000 #define ALLDEPS 1 #define SOMEDEPS 2 #define META 01 #define TERMINAL 02 extern char funny[128]; #define ALLOC(x) (struct x *) ckalloc(sizeof(struct x)) extern int sigivalue; extern int sigqvalue; extern int waitpid; extern int dbgflag; extern int prtrflag; extern int silflag; extern int noexflag; extern int keepgoing; extern int noruleflag; extern int touchflag; extern int questflag; extern int ndocoms; extern int ignerr; extern int okdel; extern int inarglist; extern char *prompt; extern int nopdir; extern char junkname[ ]; struct nameblock { struct nameblock *nxtnameblock; char *namep; char *alias; struct lineblock *linep; int done:3; int septype:3; TIMETYPE modtime; }; extern struct nameblock *mainname ; extern struct nameblock *firstname; struct lineblock { struct lineblock *nxtlineblock; struct depblock *depp; struct shblock *shp; }; extern struct lineblock *sufflist; struct depblock { struct depblock *nxtdepblock; struct nameblock *depname; }; struct shblock { struct shblock *nxtshblock; char *shbp; }; struct varblock { struct varblock *nxtvarblock; char *varname; char *varval; int noreset:1; int used:1; }; extern struct varblock *firstvar; struct pattern { struct pattern *nxtpattern; char *patval; }; extern struct pattern *firstpat; struct dirhdr { struct dirhdr *nxtopendir; DIR *dirfc; char *dirn; }; extern struct dirhdr *firstod; struct chain { struct chain *nextp; char *datap; }; char *copys(), *concat(), *subst(); int *ckalloc(); struct nameblock *srchname(), *makename(); TIMETYPE exists(); hdr.name, 1, (size_t)len, arfd); if (nr != len) return(0); chdr.name[len] = 0; chdr.size -= len; } else { chdrbin/diff/ 755 0 12 0 6024535761 5433 bin/diff/diff.c 444 0 12 6207 5110035036 6560 #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)diff.c 4.6 4/3/86"; #endif #include "diff.h" /* * diff - driver and subroutines */ char diff[] = DIFF; char diffh[] = DIFFH; char pr[] = PR; main(argc, argv) int argc; char **argv; { register char *argp; ifdef1 = "FILE1"; ifdef2 = "FILE2"; status = 2; diffargv = argv; argc--, argv++; while (argc > 2 && argv[0][0] == '-') { argp = &argv[0][1]; argv++, argc--; while (*argp) switch(*argp++) { #ifdef notdef case 'I': opt = D_IFDEF; wantelses = 0; continue; case 'E': opt = D_IFDEF; wantelses = 1; continue; case '1': opt = D_IFDEF; ifdef1 = argp; *--argp = 0; continue; #endif case 'D': /* -Dfoo = -E -1 -2foo */ wantelses = 1; ifdef1 = ""; /* fall through */ #ifdef notdef case '2': #endif opt = D_IFDEF; ifdef2 = argp; *--argp = 0; continue; case 'e': opt = D_EDIT; continue; case 'f': opt = D_REVERSE; continue; case 'n': opt = D_NREVERSE; continue; case 'b': bflag = 1; continue; case 'w': wflag = 1; continue; case 'i': iflag = 1; continue; case 't': tflag = 1; continue; case 'c': opt = D_CONTEXT; if (isdigit(*argp)) { context = atoi(argp); while (isdigit(*argp)) argp++; if (*argp) { fprintf(stderr, "diff: -c: bad count\n"); done(); } argp = ""; } else context = 3; continue; case 'h': hflag++; continue; case 'S': if (*argp == 0) { fprintf(stderr, "diff: use -Sstart\n"); done(); } start = argp; *--argp = 0; /* don't pass it on */ continue; case 'r': rflag++; continue; case 's': sflag++; continue; case 'l': lflag++; continue; default: fprintf(stderr, "diff: -%s: unknown option\n", --argp); done(); } } if (argc != 2) { fprintf(stderr, "diff: two filename arguments required\n"); done(); } file1 = argv[0]; file2 = argv[1]; if (hflag && opt) { fprintf(stderr, "diff: -h doesn't support -e, -f, -n, -c, or -I\n"); done(); } if (!strcmp(file1, "-")) stb1.st_mode = S_IFREG; else if (stat(file1, &stb1) < 0) { fprintf(stderr, "diff: "); perror(file1); done(); } if (!strcmp(file2, "-")) stb2.st_mode = S_IFREG; else if (stat(file2, &stb2) < 0) { fprintf(stderr, "diff: "); perror(file2); done(); } if ((stb1.st_mode & S_IFMT) == S_IFDIR && (stb2.st_mode & S_IFMT) == S_IFDIR) { diffdir(argv); } else diffreg(); done(); } char * savestr(cp) register char *cp; { register char *dp = malloc(strlen(cp)+1); if (dp == 0) { fprintf(stderr, "diff: ran out of memory\n"); done(); } strcpy(dp, cp); return (dp); } min(a,b) int a,b; { return (a < b ? a : b); } max(a,b) int a,b; { return (a > b ? a : b); } done() { if (tempfile) unlink(tempfile); exit(status); } char * talloc(n) { register char *p; if ((p = malloc((unsigned)n)) != NULL) return(p); noroom(); } char * ralloc(p,n) char *p; { register char *q; char *realloc(); if ((q = realloc(p, (unsigned)n)) == NULL) noroom(); return(q); } noroom() { fprintf(stderr, "diff: files too big, try -h\n"); done(); } tflag = 1; continue; case 'c': opt = D_CONTEXT; if (isdigit(*argp)) { context = atoi(argp); while (isdigit(*argp)) argp++; if (*argp) { fprintf(stderr, "diff: -c: bad count\n"); done(); } argp = ""; } else context = 3; continue; case 'h': hflag++; continue; case 'S': if (*argp == 0) { fprintf(bin/diff/diff.h 444 0 12 3676 3534711303 6602 /* diff.h 4.7 85/08/16 */ /* * diff - common declarations */ #include #include #include #include #include #include /* * Output format options */ int opt; #define D_NORMAL 0 /* Normal output */ #define D_EDIT -1 /* Editor script out */ #define D_REVERSE 1 /* Reverse editor script */ #define D_CONTEXT 2 /* Diff with context */ #define D_IFDEF 3 /* Diff with merged #ifdef's */ #define D_NREVERSE 4 /* Reverse ed script with numbered lines and no trailing . */ int tflag; /* expand tabs on output */ /* * Algorithm related options */ int hflag; /* -h, use halfhearted DIFFH */ int bflag; /* ignore blanks in comparisons */ int wflag; /* totally ignore blanks in comparisons */ int iflag; /* ignore case in comparisons */ /* * Options on hierarchical diffs. */ int lflag; /* long output format with header */ int rflag; /* recursively trace directories */ int sflag; /* announce files which are same */ char *start; /* do file only if name >= this */ /* * Variables for -I D_IFDEF option. */ int wantelses; /* -E */ char *ifdef1; /* String for -1 */ char *ifdef2; /* String for -2 */ char *endifname; /* What we will print on next #endif */ int inifdef; /* * Variables for -c context option. */ int context; /* lines of context to be printed */ /* * State for exit status. */ int status; int anychange; char *tempfile; /* used when comparing against std input */ /* * Variables for diffdir. */ char **diffargv; /* option list to pass to recursive diffs */ /* * Input file names. * With diffdir, file1 and file2 are allocated BUFSIZ space, * and padded with a '/', and then efile0 and efile1 point after * the '/'. */ char *file1, *file2, *efile1, *efile2; struct stat stb1, stb2; char *malloc(), *talloc(), *ralloc(); char *savestr(), *splice(), *splicen(); char *mktemp(), *copytemp(), *rindex(); int done(); extern char diffh[], diff[], pr[]; rgv[1]; if (hflag && opt) { fprintf(stderr, "diff: -h doebin/diff/diffreg.c 444 0 12 57350 5514435625 7323 #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)diffreg.c 4.16.1 (2.11BSD) 1/1/94"; #endif #include "diff.h" /* * diff - compare two files. */ /* * Uses an algorithm due to Harold Stone, which finds * a pair of longest identical subsequences in the two * files. * * The major goal is to generate the match vector J. * J[i] is the index of the line in file1 corresponding * to line i file0. J[i] = 0 if there is no * such line in file1. * * Lines are hashed so as to work in core. All potential * matches are located by sorting the lines of each file * on the hash (called ``value''). In particular, this * collects the equivalence classes in file1 together. * Subroutine equiv replaces the value of each line in * file0 by the index of the first element of its * matching equivalence in (the reordered) file1. * To save space equiv squeezes file1 into a single * array member in which the equivalence classes * are simply concatenated, except that their first * members are flagged by changing sign. * * Next the indices that point into member are unsorted into * array class according to the original order of file0. * * The cleverness lies in routine stone. This marches * through the lines of file0, developing a vector klist * of "k-candidates". At step i a k-candidate is a matched * pair of lines x,y (x in file0 y in file1) such that * there is a common subsequence of length k * between the first i lines of file0 and the first y * lines of file1, but there is no such subsequence for * any smaller y. x is the earliest possible mate to y * that occurs in such a subsequence. * * Whenever any of the members of the equivalence class of * lines in file1 matable to a line in file0 has serial number * less than the y of some k-candidate, that k-candidate * with the smallest such y is replaced. The new * k-candidate is chained (via pred) to the current * k-1 candidate so that the actual subsequence can * be recovered. When a member has serial number greater * that the y of all k-candidates, the klist is extended. * At the end, the longest subsequence is pulled out * and placed in the array J by unravel * * With J in hand, the matches there recorded are * check'ed against reality to assure that no spurious * matches have crept in due to hashing. If they have, * they are broken, and "jackpot" is recorded--a harmless * matter except that a true match for a spuriously * mated line may now be unnecessarily reported as a change. * * Much of the complexity of the program comes simply * from trying to minimize core utilization and * maximize the range of doable problems by dynamically * allocating what is needed and reusing what is not. * The core requirements for problems larger than somewhat * are (in words) 2*length(file0) + length(file1) + * 3*(number of k-candidates installed), typically about * 6n words for files of length n. */ #define prints(s) fputs(s,stdout) FILE *input[2]; FILE *fopen(); struct cand { int x; int y; int pred; } cand; struct line { int serial; int value; } *file[2], line; int len[2]; struct line *sfile[2]; /* shortened by pruning common prefix and suffix */ int slen[2]; int pref, suff; /* length of prefix and suffix */ int *class; /* will be overlaid on file[0] */ int *member; /* will be overlaid on file[1] */ int *klist; /* will be overlaid on file[0] after class */ struct cand *clist; /* merely a free storage pot for candidates */ int clen = 0; int *J; /* will be overlaid on class */ long *ixold; /* will be overlaid on klist */ long *ixnew; /* will be overlaid on file[1] */ char *chrtran; /* translation table for case-folding */ /* chrtran points to one of 2 translation tables: * cup2low if folding upper to lower case * clow2low if not folding case */ char clow2low[256] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff }; char cup2low[256] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff }; diffreg() { register int i, j; FILE *f1, *f2; char buf1[BUFSIZ], buf2[BUFSIZ]; if (hflag) { diffargv[0] = "diffh"; execv(diffh, diffargv); fprintf(stderr, "diff: "); perror(diffh); done(); } chrtran = (iflag? cup2low : clow2low); if ((stb1.st_mode & S_IFMT) == S_IFDIR) { file1 = splice(file1, file2); if (stat(file1, &stb1) < 0) { fprintf(stderr, "diff: "); perror(file1); done(); } } else if ((stb2.st_mode & S_IFMT) == S_IFDIR) { file2 = splice(file2, file1); if (stat(file2, &stb2) < 0) { fprintf(stderr, "diff: "); perror(file2); done(); } } else if (!strcmp(file1, "-")) { if (!strcmp(file2, "-")) { fprintf(stderr, "diff: can't specify - -\n"); done(); } file1 = copytemp(); if (stat(file1, &stb1) < 0) { fprintf(stderr, "diff: "); perror(file1); done(); } } else if (!strcmp(file2, "-")) { file2 = copytemp(); if (stat(file2, &stb2) < 0) { fprintf(stderr, "diff: "); perror(file2); done(); } } if ((f1 = fopen(file1, "r")) == NULL) { fprintf(stderr, "diff: "); perror(file1); done(); } if ((f2 = fopen(file2, "r")) == NULL) { fprintf(stderr, "diff: "); perror(file2); fclose(f1); done(); } if (stb1.st_size != stb2.st_size) goto notsame; for (;;) { i = fread(buf1, 1, BUFSIZ, f1); j = fread(buf2, 1, BUFSIZ, f2); if (i < 0 || j < 0 || i != j) goto notsame; if (i == 0 && j == 0) { fclose(f1); fclose(f2); status = 0; /* files don't differ */ goto same; } for (j = 0; j < i; j++) if (buf1[j] != buf2[j]) goto notsame; } notsame: /* * Files certainly differ at this point; set status accordingly */ status = 1; if (!asciifile(f1) || !asciifile(f2)) { printf("Binary files %s and %s differ\n", file1, file2); fclose(f1); fclose(f2); done(); } prepare(0, f1); prepare(1, f2); fclose(f1); fclose(f2); prune(); sort(sfile[0],slen[0]); sort(sfile[1],slen[1]); member = (int *)file[1]; equiv(sfile[0], slen[0], sfile[1], slen[1], member); member = (int *)ralloc((char *)member,(slen[1]+2)*sizeof(int)); class = (int *)file[0]; unsort(sfile[0], slen[0], class); class = (int *)ralloc((char *)class,(slen[0]+2)*sizeof(int)); klist = (int *)talloc((slen[0]+2)*sizeof(int)); clist = (struct cand *)talloc(sizeof(cand)); i = stone(class, slen[0], member, klist); free((char *)member); free((char *)class); J = (int *)talloc((len[0]+2)*sizeof(int)); unravel(klist[i]); free((char *)clist); free((char *)klist); ixold = (long *)talloc((len[0]+2)*sizeof(long)); ixnew = (long *)talloc((len[1]+2)*sizeof(long)); check(); output(); status = anychange; same: if (opt == D_CONTEXT && anychange == 0) printf("No differences encountered\n"); done(); } char * copytemp() { char buf[BUFSIZ]; register int i, f; signal(SIGHUP,done); signal(SIGINT,done); signal(SIGPIPE,done); signal(SIGTERM,done); tempfile = mktemp("/tmp/dXXXXX"); f = creat(tempfile,0600); if (f < 0) { fprintf(stderr, "diff: "); perror(tempfile); done(); } while ((i = read(0,buf,BUFSIZ)) > 0) if (write(f,buf,i) != i) { fprintf(stderr, "diff: "); perror(tempfile); done(); } close(f); return (tempfile); } char * splice(dir, file) char *dir, *file; { char *tail; char buf[BUFSIZ]; if (!strcmp(file, "-")) { fprintf(stderr, "diff: can't specify - with other arg directory\n"); done(); } tail = rindex(file, '/'); if (tail == 0) tail = file; else tail++; sprintf(buf, "%s/%s", dir, tail); return (savestr(buf)); } prepare(i, fd) int i; FILE *fd; { register struct line *p; register j,h; fseek(fd, (long)0, 0); p = (struct line *)talloc(3*sizeof(line)); for(j=0; h=readhash(fd);) { p = (struct line *)ralloc((char *)p,(++j+3)*sizeof(line)); p[j].value = h; } len[i] = j; file[i] = p; } prune() { register i,j; for(pref=0;pref 0); } return(k); } newcand(x,y,pred) { register struct cand *q; clist = (struct cand *)ralloc((char *)clist,++clen*sizeof(cand)); q = clist + clen -1; q->x = x; q->y = y; q->pred = pred; return(clen-1); } search(c, k, y) int *c; { register int i, j, l; int t; if(clist[c[k]].y>= 1) <= i) break; t = clist[c[l]].y; if(t > y) j = l; else if(t < y) i = l; else return(l); } return(l+1); } unravel(p) { register int i; register struct cand *q; for(i=0; i<=len[0]; i++) J[i] = i<=pref ? i: i>len[0]-suff ? i+len[1]-len[0]: 0; for(q=clist+p;q->y!=0;q=clist+q->pred) J[q->x+pref] = q->y+pref; } /* check does double duty: 1. ferret out any fortuitous correspondences due to confounding by hashing (which result in "jackpot") 2. collect random access indexes to the two files */ check() { register int i, j; int jackpot; long ctold, ctnew; register int c,d; if ((input[0] = fopen(file1,"r")) == NULL) { perror(file1); done(); } if ((input[1] = fopen(file2,"r")) == NULL) { perror(file2); done(); } j = 1; ixold[0] = ixnew[0] = 0; jackpot = 0; ctold = ctnew = 0; for(i=1;i<=len[0];i++) { if(J[i]==0) { ixold[i] = ctold += skipline(0); continue; } while(j a; ai -= m) { aim = &ai[m]; if(aim < ai) break; /*wraparound*/ if(aim->value > ai[0].value || aim->value == ai[0].value && aim->serial > ai[0].serial) break; w.value = ai[0].value; ai[0].value = aim->value; aim->value = w.value; w.serial = ai[0].serial; ai[0].serial = aim->serial; aim->serial = w.serial; } } } } unsort(f, l, b) struct line *f; int *b; { register int *a; register int i; a = (int *)talloc((l+1)*sizeof(int)); for(i=1;i<=l;i++) a[f[i].serial] = f[i].value; for(i=1;i<=l;i++) b[i] = a[i]; free((char *)a); } skipline(f) { register i, c; for(i=1;(c=getc(input[f]))!='\n';i++) if (c < 0) return(i); return(i); } output() { int m; register int i0, i1, j1; int j0; input[0] = fopen(file1,"r"); input[1] = fopen(file2,"r"); m = len[0]; J[0] = 0; J[m+1] = len[1]+1; if(opt!=D_EDIT) for(i0=1;i0<=m;i0=i1+1) { while(i0<=m&&J[i0]==J[i0-1]+1) i0++; j0 = J[i0-1]+1; i1 = i0-1; while(i1=1;i0=i1-1) { while(i0>=1&&J[i0]==J[i0+1]-1&&J[i0]!=0) i0--; j0 = J[i0+1]-1; i1 = i0+1; while(i1>1&&J[i1-1]==0) i1--; j1 = J[i1-1]+1; J[i1] = j1; change(i1,i0,j1,j0); } if(m==0) change(1,0,1,len[1]); if (opt==D_IFDEF) { for (;;) { #define c i0 c = getc(input[0]); if (c < 0) return; putchar(c); } #undef c } if (anychange && opt == D_CONTEXT) dump_context_vec(); } /* * The following struct is used to record change information when * doing a "context" diff. (see routine "change" to understand the * highly mneumonic field names) */ struct context_vec { int a; /* start line in old file */ int b; /* end line in old file */ int c; /* start line in new file */ int d; /* end line in new file */ }; struct context_vec *context_vec_start, *context_vec_end, *context_vec_ptr; #define MAX_CONTEXT 128 /* indicate that there is a difference between lines a and b of the from file to get to lines c to d of the to file. If a is greater then b then there are no lines in the from file involved and this means that there were lines appended (beginning at b). If c is greater than d then there are lines missing from the to file. */ change(a,b,c,d) { int ch; int lowa,upb,lowc,upd; struct stat stbuf; if (opt != D_IFDEF && a>b && c>d) return; if (anychange == 0) { anychange = 1; if(opt == D_CONTEXT) { printf("*** %s ", file1); stat(file1, &stbuf); printf("%s--- %s ", ctime(&stbuf.st_mtime), file2); stat(file2, &stbuf); printf("%s", ctime(&stbuf.st_mtime)); context_vec_start = (struct context_vec *) malloc(MAX_CONTEXT * sizeof(struct context_vec)); context_vec_end = context_vec_start + MAX_CONTEXT; context_vec_ptr = context_vec_start - 1; } } if (a <= b && c <= d) ch = 'c'; else ch = (a <= b) ? 'd' : 'a'; if(opt == D_CONTEXT) { /* * if this new change is within 'context' lines of * the previous change, just add it to the change * record. If the record is full or if this * change is more than 'context' lines from the previous * change, dump the record, reset it & add the new change. */ if ( context_vec_ptr >= context_vec_end || ( context_vec_ptr >= context_vec_start && a > (context_vec_ptr->b + 2*context) && c > (context_vec_ptr->d + 2*context) ) ) dump_context_vec(); context_vec_ptr++; context_vec_ptr->a = a; context_vec_ptr->b = b; context_vec_ptr->c = c; context_vec_ptr->d = d; return; } switch (opt) { case D_NORMAL: case D_EDIT: range(a,b,","); putchar(a>b?'a':c>d?'d':'c'); if(opt==D_NORMAL) range(c,d,","); putchar('\n'); break; case D_REVERSE: putchar(a>b?'a':c>d?'d':'c'); range(a,b," "); putchar('\n'); break; case D_NREVERSE: if (a>b) printf("a%d %d\n",b,d-c+1); else { printf("d%d %d\n",a,b-a+1); if (!(c>d)) /* add changed lines */ printf("a%d %d\n",b, d-c+1); } break; } if(opt == D_NORMAL || opt == D_IFDEF) { fetch(ixold,a,b,input[0],"< ", 1); if(a<=b&&c<=d && opt == D_NORMAL) prints("---\n"); } fetch(ixnew,c,d,input[1],opt==D_NORMAL?"> ":"", 0); if ((opt ==D_EDIT || opt == D_REVERSE) && c<=d) prints(".\n"); if (inifdef) { fprintf(stdout, "#endif %s\n", endifname); inifdef = 0; } } range(a,b,separator) char *separator; { printf("%d", a>b?b:a); if(ab), else to (nb: 0 vs 1 orig) */ nc = f[a>b? b : a-1 ] - curpos; for (i = 0; i < nc; i++) putchar(getc(lb)); } if (a > b) return; if (opt == D_IFDEF) { if (inifdef) fprintf(stdout, "#else %s%s\n", oneflag && oldfile==1 ? "!" : "", ifdef2); else { if (oneflag) { /* There was only one ifdef given */ endifname = ifdef2; if (oldfile) fprintf(stdout, "#ifndef %s\n", endifname); else fprintf(stdout, "#ifdef %s\n", endifname); } else { endifname = oldfile ? ifdef1 : ifdef2; fprintf(stdout, "#ifdef %s\n", endifname); } } inifdef = 1+oldfile; } for(i=a;i<=b;i++) { fseek(lb,f[i-1],0); nc = f[i]-f[i-1]; if (opt != D_IFDEF) prints(s); col = 0; for(j=0;j>HALFLONG) /* * hashing has the effect of * arranging line in 7-bit bytes and then * summing 1-s complement in 16-bit hunks */ readhash(f) register FILE *f; { register long sum; register unsigned shift; register t; register space; sum = 1; space = 0; if(!bflag && !wflag) { if(iflag) for(shift=0;(t=getc(f))!='\n';shift+=7) { if(t==-1) return(0); sum += (long)chrtran[t] << (shift #ifdef POW2 &= HALFLONG - 1); #else %= HALFLONG); #endif } else for(shift=0;(t=getc(f))!='\n';shift+=7) { if(t==-1) return(0); sum += (long)t << (shift #ifdef POW2 &= HALFLONG - 1); #else %= HALFLONG); #endif } } else { for(shift=0;;) { switch(t=getc(f)) { case -1: return(0); case '\t': case ' ': space++; continue; default: if(space && !wflag) { shift += 7; space = 0; } sum += (long)chrtran[t] << (shift #ifdef POW2 &= HALFLONG - 1); #else %= HALFLONG); #endif shift += 7; continue; case '\n': break; } break; } } sum = low(sum) + high(sum); return((short)low(sum) + (short)high(sum)); } #include asciifile(f) FILE *f; { char buf[BUFSIZ]; register int cnt; register char *cp; fseek(f, (long)0, 0); cnt = fread(buf, 1, BUFSIZ, f); if (cnt >= sizeof (struct exec)) { struct exec hdr; hdr = *(struct exec *)buf; if (!N_BADMAG(hdr)) return (0); } cp = buf; while (--cnt >= 0) if (*cp++ & 0200) return (0); return (1); } /* dump accumulated "context" diff changes */ dump_context_vec() { register int a, b, c, d; register char ch; register struct context_vec *cvp = context_vec_start; register int lowa, upb, lowc, upd; register int do_output; if ( cvp > context_vec_ptr ) return; lowa = max(1, cvp->a - context); upb = min(len[0], context_vec_ptr->b + context); lowc = max(1, cvp->c - context); upd = min(len[1], context_vec_ptr->d + context); printf("***************\n*** "); range(lowa,upb,","); printf(" ****\n"); /* * output changes to the "old" file. The first loop suppresses * output if there were no changes to the "old" file (we'll see * the "old" lines as context in the "new" list). */ do_output = 0; for ( ; cvp <= context_vec_ptr; cvp++) if (cvp->a <= cvp->b) { cvp = context_vec_start; do_output++; break; } if ( do_output ) { while (cvp <= context_vec_ptr) { a = cvp->a; b = cvp->b; c = cvp->c; d = cvp->d; if (a <= b && c <= d) ch = 'c'; else ch = (a <= b) ? 'd' : 'a'; if (ch == 'a') fetch(ixold,lowa,b,input[0]," "); else { fetch(ixold,lowa,a-1,input[0]," "); fetch(ixold,a,b,input[0],ch == 'c' ? "! " : "- "); } lowa = b + 1; cvp++; } fetch(ixold, b+1, upb, input[0], " "); } /* output changes to the "new" file */ printf("--- "); range(lowc,upd,","); printf(" ----\n"); do_output = 0; for (cvp = context_vec_start; cvp <= context_vec_ptr; cvp++) if (cvp->c <= cvp->d) { cvp = context_vec_start; do_output++; break; } if (do_output) { while (cvp <= context_vec_ptr) { a = cvp->a; b = cvp->b; c = cvp->c; d = cvp->d; if (a <= b && c <= d) ch = 'c'; else ch = (a <= b) ? 'd' : 'a'; if (ch == 'd') fetch(ixnew,lowc,d,input[1]," "); else { fetch(ixnew,lowc,c-1,input[1]," "); fetch(ixnew,c,d,input[1],ch == 'c' ? "! " : "+ "); } lowc = d + 1; cvp++; } fetch(ixnew, d+1, upd, input[1], " "); } context_vec_ptr = context_vec_start - 1; } if(c=='\n') break; } } ixold[i] = ctold; ixnew[j] = ctnew; j++; } for(;j<=len[1];j++) { ixnew[j] = ctnew += skipline(1); } fclose(input[0]); fclose(input[1]); /* if(jackpot) fprintf(stderr, "jackpot\n"); */ } sort(a,n) /*shellsort CACM #201*/ struct libin/diff/diffdir.c 444 0 12 17767 5110035041 7310 #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)diffdir.c 4.9 (Berkeley) 8/28/84"; #endif #include "diff.h" /* * diff - directory comparison */ #define d_flags d_ino #define ONLY 1 /* Only in this directory */ #define SAME 2 /* Both places and same */ #define DIFFER 4 /* Both places and different */ #define DIRECT 8 /* Directory */ struct dir { ino_t d_ino; short d_reclen; short d_namlen; char *d_entry; }; struct dir *setupdir(); int header; char title[2*BUFSIZ], *etitle; diffdir(argv) char **argv; { register struct dir *d1, *d2; struct dir *dir1, *dir2; register int i; int cmp; if (opt == D_IFDEF) { fprintf(stderr, "diff: can't specify -I with directories\n"); done(); } if (opt == D_EDIT && (sflag || lflag)) fprintf(stderr, "diff: warning: shouldn't give -s or -l with -e\n"); title[0] = 0; strcpy(title, "diff "); for (i = 1; diffargv[i+2]; i++) { if (!strcmp(diffargv[i], "-")) continue; /* was -S, dont look silly */ strcat(title, diffargv[i]); strcat(title, " "); } for (etitle = title; *etitle; etitle++) ; setfile(&file1, &efile1, file1); setfile(&file2, &efile2, file2); argv[0] = file1; argv[1] = file2; dir1 = setupdir(file1); dir2 = setupdir(file2); d1 = dir1; d2 = dir2; while (d1->d_entry != 0 || d2->d_entry != 0) { if (d1->d_entry && useless(d1->d_entry)) { d1++; continue; } if (d2->d_entry && useless(d2->d_entry)) { d2++; continue; } if (d1->d_entry == 0) cmp = 1; else if (d2->d_entry == 0) cmp = -1; else cmp = strcmp(d1->d_entry, d2->d_entry); if (cmp < 0) { if (lflag) d1->d_flags |= ONLY; else if (opt == 0 || opt == 2) only(d1, 1); d1++; } else if (cmp == 0) { compare(d1); d1++; d2++; } else { if (lflag) d2->d_flags |= ONLY; else if (opt == 0 || opt == 2) only(d2, 2); d2++; } } if (lflag) { scanpr(dir1, ONLY, "Only in %.*s", file1, efile1, 0, 0); scanpr(dir2, ONLY, "Only in %.*s", file2, efile2, 0, 0); scanpr(dir1, SAME, "Common identical files in %.*s and %.*s", file1, efile1, file2, efile2); scanpr(dir1, DIFFER, "Binary files which differ in %.*s and %.*s", file1, efile1, file2, efile2); scanpr(dir1, DIRECT, "Common subdirectories of %.*s and %.*s", file1, efile1, file2, efile2); } if (rflag) { if (header && lflag) printf("\f"); for (d1 = dir1; d1->d_entry; d1++) { if ((d1->d_flags & DIRECT) == 0) continue; strcpy(efile1, d1->d_entry); strcpy(efile2, d1->d_entry); calldiff(0); } } } setfile(fpp, epp, file) char **fpp, **epp; char *file; { register char *cp; *fpp = malloc(BUFSIZ); if (*fpp == 0) { fprintf(stderr, "diff: ran out of memory\n"); exit(1); } strcpy(*fpp, file); for (cp = *fpp; *cp; cp++) continue; *cp++ = '/'; *epp = cp; } scanpr(dp, test, title, file1, efile1, file2, efile2) register struct dir *dp; int test; char *title, *file1, *efile1, *file2, *efile2; { int titled = 0; for (; dp->d_entry; dp++) { if ((dp->d_flags & test) == 0) continue; if (titled == 0) { if (header == 0) header = 1; else printf("\n"); printf(title, efile1 - file1 - 1, file1, efile2 - file2 - 1, file2); printf(":\n"); titled = 1; } printf("\t%s\n", dp->d_entry); } } only(dp, which) struct dir *dp; int which; { char *file = which == 1 ? file1 : file2; char *efile = which == 1 ? efile1 : efile2; printf("Only in %.*s: %s\n", efile - file - 1, file, dp->d_entry); } int entcmp(); struct dir * setupdir(cp) char *cp; { register struct dir *dp = 0, *ep; register struct direct *rp; register int nitems, n; DIR *dirp; dirp = opendir(cp); if (dirp == NULL) { fprintf(stderr, "diff: "); perror(cp); done(); } nitems = 0; #ifdef pdp11 while (readdir(dirp)) nitems++; rewinddir(dirp); dp = (struct dir *)calloc(nitems+1, sizeof (struct dir)); nitems = 0; #else dp = (struct dir *)malloc(sizeof (struct dir)); #endif if (dp == 0) { fprintf(stderr, "diff: ran out of memory\n"); done(); } while (rp = readdir(dirp)) { ep = &dp[nitems++]; ep->d_reclen = rp->d_reclen; ep->d_namlen = rp->d_namlen; ep->d_entry = 0; ep->d_flags = 0; if (ep->d_namlen > 0) { ep->d_entry = malloc(ep->d_namlen + 1); if (ep->d_entry == 0) { fprintf(stderr, "diff: out of memory\n"); done(); } strcpy(ep->d_entry, rp->d_name); } #ifndef pdp11 dp = (struct dir *)realloc((char *)dp, (nitems + 1) * sizeof (struct dir)); if (dp == 0) { fprintf(stderr, "diff: ran out of memory\n"); done(); } #endif } dp[nitems].d_entry = 0; /* delimiter */ closedir(dirp); qsort(dp, nitems, sizeof (struct dir), entcmp); return (dp); } entcmp(d1, d2) struct dir *d1, *d2; { return (strcmp(d1->d_entry, d2->d_entry)); } compare(dp) register struct dir *dp; { register int i, j; int f1, f2, fmt1, fmt2; struct stat stb1, stb2; int flag = 0; char buf1[BUFSIZ], buf2[BUFSIZ]; strcpy(efile1, dp->d_entry); strcpy(efile2, dp->d_entry); f1 = open(file1, 0); if (f1 < 0) { perror(file1); return; } f2 = open(file2, 0); if (f2 < 0) { perror(file2); close(f1); return; } fstat(f1, &stb1); fstat(f2, &stb2); fmt1 = stb1.st_mode & S_IFMT; fmt2 = stb2.st_mode & S_IFMT; if (fmt1 != S_IFREG || fmt2 != S_IFREG) { if (fmt1 == fmt2) { if (fmt1 != S_IFDIR && stb1.st_rdev == stb2.st_rdev) goto same; if (fmt1 == S_IFDIR) { dp->d_flags = DIRECT; if (lflag || opt == D_EDIT) goto closem; printf("Common subdirectories: %s and %s\n", file1, file2); goto closem; } } goto notsame; } if (stb1.st_size != stb2.st_size) goto notsame; for (;;) { i = read(f1, buf1, BUFSIZ); j = read(f2, buf2, BUFSIZ); if (i < 0 || j < 0 || i != j) goto notsame; if (i == 0 && j == 0) goto same; for (j = 0; j < i; j++) if (buf1[j] != buf2[j]) goto notsame; } same: if (sflag == 0) goto closem; if (lflag) dp->d_flags = SAME; else printf("Files %s and %s are identical\n", file1, file2); goto closem; notsame: if (!ascii(f1) || !ascii(f2)) { if (lflag) dp->d_flags |= DIFFER; else if (opt == D_NORMAL || opt == D_CONTEXT) printf("Binary files %s and %s differ\n", file1, file2); goto closem; } close(f1); close(f2); anychange = 1; if (lflag) calldiff(title); else { if (opt == D_EDIT) { printf("ed - %s << '-*-END-*-'\n", dp->d_entry); calldiff(0); } else { printf("%s%s %s\n", title, file1, file2); calldiff(0); } if (opt == D_EDIT) printf("w\nq\n-*-END-*-\n"); } return; closem: close(f1); close(f2); } char *prargs[] = { "pr", "-h", 0, "-f", 0, 0 }; calldiff(wantpr) char *wantpr; { int pid, status, status2, pv[2]; prargs[2] = wantpr; fflush(stdout); if (wantpr) { sprintf(etitle, "%s %s", file1, file2); pipe(pv); pid = fork(); if (pid == -1) { fprintf(stderr, "No more processes"); done(); } if (pid == 0) { close(0); dup(pv[0]); close(pv[0]); close(pv[1]); execv(pr+4, prargs); execv(pr, prargs); perror(pr); done(); } } pid = fork(); if (pid == -1) { fprintf(stderr, "diff: No more processes\n"); done(); } if (pid == 0) { if (wantpr) { close(1); dup(pv[1]); close(pv[0]); close(pv[1]); } execv(diff+4, diffargv); execv(diff, diffargv); perror(diff); done(); } if (wantpr) { close(pv[0]); close(pv[1]); } while (wait(&status) != pid) continue; while (wait(&status2) != -1) continue; /* if ((status >> 8) >= 2) done(); */ } #include ascii(f) int f; { char buf[BUFSIZ]; register int cnt; register char *cp; lseek(f, (long)0, 0); cnt = read(f, buf, BUFSIZ); if (cnt >= sizeof (struct exec)) { struct exec hdr; hdr = *(struct exec *)buf; if (!N_BADMAG(hdr)) return (0); } cp = buf; while (--cnt >= 0) if (*cp++ & 0200) return (0); return (1); } /* * THIS IS CRUDE. */ useless(cp) register char *cp; { if (cp[0] == '.') { if (cp[1] == '\0') return (1); /* directory "." */ if (cp[1] == '.' && cp[2] == '\0') return (1); /* directory ".." */ } if (start && strcmp(start, cp) > 0) return (1); return (0); } tr; cvp++bin/diff/diffh.c 444 0 12 10246 5110035045 6746 #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)diffh.c 4.4 11/27/85"; #endif #include #include #include #include #define C 3 #define RANGE 30 #define LEN 255 #define INF 16384 char *text[2][RANGE]; long lineno[2] = {1, 1}; /*no. of 1st stored line in each file*/ int ntext[2]; /*number of stored lines in each*/ long n0,n1; /*scan pointer in each*/ int bflag; int debug = 0; FILE *file[2]; /* return pointer to line n of file f*/ char *getl(f,n) long n; { register char *t; char *malloc(); register delta, nt; again: delta = n - lineno[f]; nt = ntext[f]; if(delta<0) progerr("1"); if(deltant) progerr("2"); if(nt>=RANGE) progerr("3"); if(feof(file[f])) return(NULL); t = text[f][nt]; if(t==0) { t = text[f][nt] = malloc(LEN+1); if(t==NULL) if(hardsynch()) goto again; else progerr("5"); } t = fgets(t,LEN,file[f]); if(t!=NULL) ntext[f]++; return(t); } /*remove thru line n of file f from storage*/ clrl(f,n) long n; { register i,j; j = n-lineno[f]+1; for(i=0;i+j=0&&b>=0) printf("---\n"); for(i=0;i<=b;i++) { s = getl(1,n1+i); if(s==NULL) break; printf("> %s",s); clrl(1,n1+i); } n1 += i-1; return(1); } change(a,b,c,d,s) long a,c; char *s; { range(a,b); printf("%s",s); range(c,d); printf("\n"); } range(a,b) long a; { if(b==INF) printf("%ld,$",a); else if(b==0) printf("%ld",a); else printf("%ld,%ld",a,a+b); } cmp(s,t) char *s,*t; { if(debug) printf("%s:%s\n",s,t); for(;;){ if(bflag&&isspace(*s)&&isspace(*t)) { while(isspace(*++s)) ; while(isspace(*++t)) ; } if(*s!=*t||*s==0) break; s++; t++; } return(*s-*t); } FILE *dopen(f1,f2) char *f1,*f2; { FILE *f; char b[100],*bptr,*eptr; struct stat statbuf; if(cmp(f1,"-")==0) if(cmp(f2,"-")==0) error("can't do - -",""); else return(stdin); if(stat(f1,&statbuf)==-1) error("can't access ",f1); if((statbuf.st_mode&S_IFMT)==S_IFDIR) { for(bptr=b;*bptr= *f1++;bptr++) ; *bptr++ = '/'; for(eptr=f2;*eptr;eptr++) if(*eptr=='/'&&eptr[1]!=0&&eptr[1]!='/') f2 = eptr+1; while(*bptr++= *f2++) ; f1 = b; } f = fopen(f1,"r"); if(f==NULL) error("can't open",f1); return(f); } progerr(s) char *s; { error("program error ",s); } error(s,t) char *s,*t; { fprintf(stderr,"diffh: %s%s\n",s,t); exit(2); } /*stub for resychronization beyond limits of text buf*/ hardsynch() { change(n0,INF,n1,INF,"c"); printf("---change record omitted\n"); error("can't resynchronize",""); return(0); } ) { if(!easysynch()&&!hardsynch()) progerr("5"); status = 1; } else { clrl(0,n0); clrl(1,n1); } } if(s0==NULL&&s1==NULL) exit(status); if(s0==NULL) output(-1,INF); if(s1==NULL) output(INF,-1); exit(1); } /* synch on C successive matches*/ easysynch() { int i,j; register k,m; char *s0,*s1; for(i=j=1;i 9: .even .text error: tst passno / on pass1,2 ? bpl errorp2 inc errflg mov r0,-(sp) mov r1,-(sp) mov r5,r0 tst *curarg beq 1f mov r0,-(sp) mov *curarg,-(sp) clr *curarg jsr pc,filerr tst (sp)+ mov (sp)+,r0 1: mov r2,-(sp) mov r3,-(sp) jsr pc,errcmn mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,r0 rts pc errorp2: mov pc,errflg mov $666,outmod / make nonexecutable mov r3,-(sp) mov r2,-(sp) mov r1,-(sp) mov r0,-(sp) tst -(sp) / write(1, argb, strlen(argb)) mov $argb,-(sp) mov $1,-(sp) mov $argb,r1 clr r0 1: tstb (r1)+ beq 2f inc r0 br 1b 2: mov r0,4(sp) jsr pc,_write add $6,sp movb 12(sp),r0 jsr pc,errcmn mov (sp)+,r0 mov (sp)+,r1 mov (sp)+,r2 mov (sp)+,r3 mov (sp)+,(sp) rts pc errcmn: mov line,r3 movb r0,9f mov $9f+6,r0 mov $4,r1 2: clr r2 div $10.,r2 add $'0,r3 movb r3,-(r0) mov r2,r3 sob r1,2b mov $7,-(sp) / write(1, 9f, 7) mov $9f,-(sp) mov $1,-(sp) jsr pc,_write add $6,sp rts pc .data 9: .even .text p0putw: tst ifflg beq 1f cmp r4,$'\n bne 2f 1: mov r4,*obufp add $2,obufp cmp obufp,$outbuf+1024. blo 2f mov $outbuf,obufp mov r1,-(sp) / protect r1 from library mov $1024.,-(sp) / write(fout, outbuf, 1024) mov $outbuf,-(sp) mov fout,-(sp) jsr pc,_write add $6,sp mov (sp)+,r1 tst r0 bpl 2f jmp wrterr 2: rts pc / Pass 0. pass0: jsr pc,p0readop jsr pc,checkeos br 7f tst ifflg beq 3f cmp r4,$200 blos pass0 cmpb (r4),$21 /if bne 2f inc ifflg 2: cmpb (r4),$22 /endif bne pass0 dec ifflg br pass0 3: mov r4,-(sp) jsr pc,p0readop cmp r4,$'= beq 4f cmp r4,$': beq 1f mov r4,savop mov (sp)+,r4 jsr pc,opline br ealoop 1: mov (sp)+,r4 cmp r4,$200 bhis 1f cmp r4,$1 / digit beq 3f mov $'x,r5 jsr pc,error br pass0 1: bitb $37,(r4) beq 1f mov $'m,r5 jsr pc,error 1: bisb dot-2,(r4) mov dot,2(r4) br pass0 3: mov numval,r0 jsr pc,fbcheck movb dotrel,curfbr(r0) asl r0 movb dotrel,nxtfb mov dot,nxtfb+2 movb r0,nxtfb+1 mov dot,curfb(r0) cmp fbfree,$4 / room for another fb entry? bge 5f / yes - br jsr pc,growfb / no - grow the table 5: sub $4,fbfree / four bytes less available mov nxtfb,*fbptr / store first word add $2,fbptr / advance to next mov nxtfb+2,*fbptr / store second word add $2,fbptr / point to next entry br pass0 4: jsr pc,p0readop jsr pc,expres mov (sp)+,r1 cmp r1,$200 bhis 1f mov $'x,r5 jsr pc,error 7: br ealoop 1: cmp r1,$dotrel bne 2f bic $40,r3 cmp r3,dotrel bne 1f 2: bicb $37,(r1) bic $!37,r3 bne 2f clr r2 2: bisb r3,(r1) mov r2,2(r1) br ealoop 1: mov $'.,r5 jsr pc,error movb $2,dotrel ealoop: cmp r4,$'; beq 9f cmp r4,$'\n bne 1f inc line br 9f 1: cmp r4,$'\e bne 2f tst ifflg beq 1f mov $'x,r5 jsr pc,error 1: rts pc 2: mov $'x,r5 jsr pc,error 2: jsr pc,checkeos br 9f jsr pc,p0readop br 2b 9: jmp pass0 fbcheck: cmp r0,$9. bhi 1f rts pc 1: mov $'f,r5 jsr pc,error clr r0 rts pc / the 'fb' table never grows to be large. In fact all of the assemblies / of C compiler generated code which were processed by 'c2' never / produced a table larger than 0 bytes. So we 'realloc' because / this is not done enough to matter. growfb: mov r1,-(sp) / save r1 from library add $256.,fbtblsz / new size of fb table mov $256.,fbfree / number available now mov fbtblsz,-(sp) / fbtbl = realloc(fbtbl, fbtblsz); mov fbtbl,-(sp) bne 1f / extending table - br mov $1,(sp) / r0 = calloc(1, fbtblsz); jsr pc,_calloc br 2f 1: jsr pc,_realloc 2: cmp (sp)+,(sp)+ mov r0,fbtbl bne 1f iot / Can never happen (I hope) 1: add fbtblsz,r0 / fbptr starts 256 bytes from sub $256.,r0 / end of new region mov r0,fbptr mov (sp)+,r1 / restore register rts pc / Symbol table lookup and hashtable maintenance. rname: mov r1,-(sp) mov r2,-(sp) mov r3,-(sp) movb Ncps,r5 / Max num of chars to accept mov $symbol,r2 clr (r2) clr -(sp) clr -(sp) cmp r0,$'~ / symbol not for hash table? bne 1f / no - br inc 2(sp) clr ch 1: jsr pc,rch movb chartab(r0),r3 ble 1f add r3,(sp) swab (sp) dec r5 blt 1b movb r3,(r2)+ br 1b 1: clrb (r2)+ / null terminate string movb r0,ch mov (sp)+,r1 clr r0 tst (sp)+ beq 1f mov symend,r4 br 4f / go insert into symtable (!hashtbl) 1: div $hshsiz,r0 ashc $1,r0 add hshtab,r1 clr timesaround 1: sub r0,r1 cmp r1,hshtab bhi 2f add $2*hshsiz,r1 tst timesaround beq 3f mov $8f-9f,-(sp) / write(fileno(stdout),9f,8f-9f); mov $9f,-(sp) mov $1,-(sp) jsr pc,_write add $6,sp jmp aexit .data timesaround: 0 9: 8: .even .text 3: inc timesaround 2: mov $symbol,r2 mov -(r1),r4 beq 3f mov (r4)+,r3 / ptr to symbol's name 9: cmpb (r2),(r3)+ bne 1b / not the right symbol - br tstb (r2)+ / at end of symbol? bne 9b / nope - keep looking br 1f / yep - br 3: mov symend,r4 jsr pc,isroom / make sure there's room in block mov r4,(r1) 4: jsr pc,isroom / check for room in current block mov $symbol,r2 / length of string (including null) 8 : tstb (r2)+ bne 8b sub $symbol,r2 jsr pc,astring / allocate string space mov r0,(r4)+ / save string pointer in symtab entry mov $symbol,r1 9: movb (r1)+,(r0)+ / copy symbol name to string block bne 9b sub $SYMENTSZ,symleft / each new symbol is assigned a unique one up number. This is done because / the user symbol table is no longer contiguous - the symbol number can / not be calculated by subtracting a base address and dividing by the / size of a symbol. clr (r4)+ / flags word clr (r4)+ / value word mov symnum,(r4)+ inc symnum mov r4,symend sub $6,r4 / point to flags word 1: mov r4,-(sp) mov r4,r3 tst -(r3) / back to beginning of entry cmp r3,$ebsymtab / Permanent Symbol Table(opcode, etc)? blo 1f / yes - br mov 6(r3),r4 / get symbol number add $4000,r4 / user symbol flag br 2f 1: / PST entries are PSTENTSZ bytes each because they do not have a 'symnum' / entry associated with them. sub $symtab,r3 clr r2 div $PSTENTSZ,r2 mov r2,r4 add $1000,r4 / builtin symbol 2: jsr pc,p0putw mov (sp)+,r4 mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,r1 tst (sp)+ rts pc isroom: cmp symleft,$SYMENTSZ / room for another symbol? bge 1f / yes - br mov r1,-(sp) / save from library mov $SYMBLKSZ+2,-(sp) / size of sym block plus link word mov $1,-(sp) / number of blocks to allocate jsr pc,_calloc / calloc(1, SYMBLKSZ+2); cmp (sp)+,(sp)+ / check for failure? mov r0,*symblk / link new block to old mov r0,symblk / this is now the current block tst (r0)+ / skip link word mov $SYMBLKSZ,symleft / number of bytes available mov r0,r4 / put where it's expected mov (sp)+,r1 / restore saved register 1: rts pc / return / allocate room for a string, the length is in R2 and includes room for / a terminating null byte. astring: cmp r2,strleft / room in current block? ble 1f / yes - go carve out a chunk mov $STRBLKSZ+2,-(sp) mov $1,-(sp) jsr pc,_calloc / symblk = calloc(1,STRBLKSZ+2) / check for failure? cmp (sp)+,(sp)+ mov r0,*strblk / update forward link between blocks mov r0,strblk / update current string block pointer tst (r0)+ / skip link word mov r0,strend / current data pointer mov $STRBLKSZ,strleft / amount of space left 1: mov strend,r0 / string address add r2,strend / update current end point sub r2,strleft / update amount of space left rts pc number: mov r2,-(sp) mov r3,-(sp) mov r5,-(sp) clr r1 clr r5 1: jsr pc,rch cmp r0,$'0 blt 1f cmp r0,$'9 bgt 1f sub $'0,r0 mul $10.,r5 add r0,r5 ash $3,r1 add r0,r1 br 1b 1: cmp r0,$'b beq 1f cmp r0,$'f beq 1f cmp r0,$'. bne 2f mov r5,r1 clr r0 2: movb r0,ch mov r1,r0 mov (sp)+,r5 mov (sp)+,r3 mov (sp)+,r2 rts pc 1: mov r0,r3 mov r5,r0 jsr pc,fbcheck add $141,r0 cmp r3,$'b beq 1f add $10.,r0 1: mov r0,r4 mov (sp)+,r5 mov (sp)+,r3 mov (sp)+,r2 add $2,(sp) rts pc rch: movb ch,r0 beq 1f clrb ch rts pc 1: dec ibufc blt 2f movb *ibufp,r0 inc ibufp bic $!177,r0 beq 1b rts pc 2: mov fin,r0 bmi 3f mov r1,-(sp) / protect r1 from library mov $1024.,-(sp) / read(fin, inbuf, 1024) mov $inbuf,-(sp) mov r0,-(sp) jsr pc,_read add $6,sp mov (sp)+,r1 tst r0 ble 2f mov r0,ibufc mov $inbuf,ibufp br 1b 2: mov r1,-(sp) / protect r1 from library mov fin,-(sp) / close(r0) jsr pc,_close tst (sp)+ mov $-1,fin mov (sp)+,r1 3: dec nargs bge 2f mov $'\e,r0 rts pc 2: tst ifflg beq 2f mov $'i,r5 jsr pc,error jmp aexit 2: / check for the filename arguments of "-" or "--", these mean to read 'stdin'. / Additional filenames are permitted and will be processed when EOF / is detected on stdin. mov *curarg,r0 cmpb (r0)+,$'- bne 5f / not the special case - br tstb (r0) / must be '-' by itself beq 4f cmpb (r0)+,$'- / check for "--" bne 5f / not a double -, must be a filename tstb (r0) / null terminated? bne 5f / no - must be a filename 4: clr fin / file descriptor is 0 for stdin br 2f 5: mov r1,-(sp) / protect r1 from library clr -(sp) / open((r0), O_RDONLY, 0) clr -(sp) mov *curarg,-(sp) jsr pc,_open add $6,sp mov (sp)+,r1 mov r0,fin bpl 2f mov *curarg,-(sp) jsr pc,filerr tst (sp)+ jmp aexit 2: mov $1,line mov r4,-(sp) mov r1,-(sp) mov $5,r4 jsr pc,p0putw mov *curarg,r1 2: movb (r1)+,r4 beq 2f jsr pc,p0putw br 2b 2: add $2,curarg mov $-1,r4 jsr pc,p0putw mov (sp)+,r1 mov (sp)+,r4 br 1b p0readop: mov savop,r4 beq 1f clr savop rts pc 1: jsr pc,8f jsr pc,p0putw rts pc 8: jsr pc,rch mov r0,r4 movb chartab(r0),r1 bgt rdname jmp *1f-2(r1) .data fixor escp 8b retread dquote garb squote rdname skip rdnum retread string 1: .text escp: jsr pc,rch mov $esctab,r1 1: cmpb r0,(r1)+ beq 1f tstb (r1)+ bne 1b rts pc 1: movb (r1),r4 rts pc .data esctab: .byte '/, '/ .byte '\<, 035 .byte '>, 036 .byte '%, 037 .byte 0, 0 .text fixor: mov $037,r4 retread: rts pc rdname: movb r0,ch cmp r1,$'0 blo 1f cmp r1,$'9 blos rdnum 1: jmp rname rdnum: jsr pc,number br 1f rts pc squote: jsr pc,rsch br 1f dquote: jsr pc,rsch mov r0,-(sp) jsr pc,rsch swab r0 bis (sp)+,r0 1: mov r0,numval mov $1,r4 jsr pc,p0putw mov numval,r4 jsr pc,p0putw mov $1,r4 tst (sp)+ rts pc skip: jsr pc,rch mov r0,r4 cmp r0,$'\e beq 1f cmp r0,$'\n bne skip 1: rts pc garb: mov $'g,r5 jsr pc,error br 8b string: mov $'<,r4 jsr pc,p0putw clr numval 1: jsr pc,rsch tst r1 bne 1f mov r0,r4 bis $400,r4 jsr pc,p0putw inc numval br 1b 1: mov $-1,r4 jsr pc,p0putw mov $'<,r4 tst (sp)+ rts pc rsch: jsr pc,rch cmp r0,$'\e beq 4f cmp r0,$'\n beq 4f clr r1 cmp r0,$'\\ bne 3f jsr pc,rch mov $schar,r2 1: cmpb (r2)+,r0 beq 2f tstb (r2)+ bpl 1b rts pc 2: movb (r2)+,r0 clr r1 rts pc 3: cmp r0,$'> bne 1f inc r1 1: rts pc 4: mov $'<,r5 jsr pc,error jmp aexit .data schar: .byte 'n, 012 .byte 's, 040 .byte 't, 011 .byte 'e, 004 .byte '0, 000 .byte 'r, 015 .byte 'a, 006 .byte 'p, 033 .byte 0, -1 .text opline: mov r4,r0 bmi 1f cmp r0,$200 bgt 1f cmp r0,$'< bne xpr jmp opl17 xpr: jsr pc,expres add $2,dot rts pc 1: movb (r4),r0 cmp r0,$24 beq xpr cmp r0,$5 blt xpr cmp r0,$36 bgt xpr mov r0,-(sp) jsr pc,p0readop mov (sp)+,r0 asl r0 jmp *1f-12(r0) .data 1: opl13 / map fop freg,fdst to double opl6 opl7 opl10 opl11 opl13 / map fld/fst to double opl13 opl13 / map fop fsrc,freg to double opl15 opl16 opl17 opl20 opl21 opl22 opl23 xpr opl25 opl26 opl27 opl13 / map mul s,r to double opl31 opl32 xpr xpr opl35 opl36 .text opl35: / jbr mov $4,-(sp) br 1f opl36: / jeq, etc mov $6,-(sp) 1: jsr pc,expres cmp r3,dotrel bne 1f sub dot,r2 bge 1f cmp r2,$-376 blt 1f mov $2,(sp) 1: add (sp)+,dot rts pc opl13: opl7: /double jsr pc,addres op2: cmp r4,$', beq 1f jsr pc,errora rts pc 1: jsr pc,p0readop opl15: / single operand jsr pc,addres add $2,dot rts pc opl31: / sob jsr pc,expres cmp r4,$', beq 1f jsr pc,errora 1: jsr pc,p0readop opl6: opl10: opl11: /branch jsr pc,expres add $2,dot rts pc opl16: / .byte jsr pc,expres inc dot cmp r4,$', bne 1f jsr pc,p0readop br opl16 1: rts pc opl17: / < (.ascii) add numval,dot jsr pc,p0readop rts pc opl20: /.even inc dot bic $1,dot rts pc opl21: /.if jsr pc,expres tst r3 bne 1f mov $'U,r5 jsr pc,error 1: tst r2 bne opl22 inc ifflg opl22: /endif rts pc opl23: /.globl cmp r4,$200 blo 1f bisb $40,(r4) jsr pc,p0readop cmp r4,$', bne 1f jsr pc,p0readop br opl23 1: rts pc opl25: opl26: opl27: mov dotrel,r1 asl r1 mov dot,savdot-4(r1) mov savdot-[2*25](r0),dot asr r0 sub $25-2,r0 mov r0,dotrel rts pc opl32: / .common cmp r4,$200 blo 1f bis $40,(r4) jsr pc,p0readop cmp r4,$', bne 1f jsr pc,p0readop jsr pc,expres rts pc 1: mov $'x,r5 jsr pc,error rts pc addres: cmp r4,$'( beq alp cmp r4,$'- beq amin cmp r4,$'$ beq adoll cmp r4,$'* beq astar getx: jsr pc,expres cmp r4,$'( bne 2f jsr pc,p0readop jsr pc,expres jsr pc,checkreg jsr pc,checkrp 1: add $2,dot clr r0 rts pc 2: cmp r3,$24 / register type bne 1b jsr pc,checkreg clr r0 rts pc alp: jsr pc,p0readop jsr pc,expres jsr pc,checkrp jsr pc,checkreg cmp r4,$'+ bne 1f jsr pc,p0readop clr r0 rts pc 1: mov $2,r0 rts pc amin: jsr pc,p0readop cmp r4,$'( beq 1f mov r4,savop mov $'-,r4 br getx 1: jsr pc,p0readop jsr pc,expres jsr pc,checkrp jsr pc,checkreg clr r0 rts pc adoll: jsr pc,p0readop jsr pc,expres add $2,dot clr r0 rts pc astar: jsr pc,p0readop cmp r4,$'* bne 1f mov $'*,r5 jsr pc,error 1: jsr pc,addres add r0,dot rts pc errora: mov $'a,r5 jsr pc,error rts pc checkreg: cmp r2,$7 bhi 1f cmp r3,$1 beq 2f cmp r3,$4 bhi 2f 1: jsr pc,errora 2: rts pc errore: mov $'e,r5 jsr pc,error rts pc checkrp: cmp r4,$') beq 1f mov $'),r5 jsr pc,error rts pc 1: jsr pc,p0readop rts pc expres: mov r5,-(sp) mov $'+,-(sp) clr opfound clr r2 mov $1,r3 br 1f advanc: jsr pc,p0readop 1: mov r4,r0 tst r0 blt 6f cmp r0,$177 ble 7f 6: movb (r4),r0 mov 2(r4),r1 br oprand 7: cmp r4,$141 blo 1f cmp r4,$141+10. bhis 2f movb curfbr-141(r4),r0 asl r4 mov curfb-[2*141](r4),r2 cmp r2,$-1 bne oprand mov $'f,r5 jsr pc,error br oprand 2: clr r3 clr r2 br oprand 1: mov $esw1,r1 1: cmp (r1)+,r4 beq 1f tst (r1)+ bne 1b tst opfound bne 2f jsr pc,errore 2: tst (sp)+ mov (sp)+,r5 rts pc 1: jmp *(r1) .data esw1: '+; binop '-; binop '*; binop '/; binop '&; binop 037; binop 035; binop 036; binop '%; binop '[; brack '^; binop 1; exnum '!; binop 0; 0 .text binop: cmpb (sp),$'+ beq 1f jsr pc,errore 1: movb r4,(sp) br advanc exnum: mov numval,r1 mov $1,r0 br oprand brack: mov r2,-(sp) mov r3,-(sp) jsr pc,p0readop jsr pc,expres cmp r4,$'] beq 1f mov $'],r5 jsr pc,error 1: mov r3,r0 mov r2,r1 mov (sp)+,r3 mov (sp)+,r2 oprand: inc opfound mov $exsw2,r5 1: cmp (sp),(r5)+ beq 1f tst (r5)+ bne 1b br eoprnd 1: jmp *(r5) .data exsw2: '+; exadd '-; exsub '*; exmul '/; exdiv 037; exor '&; exand 035;exlsh 036;exrsh '%; exmod '!; exnot '^; excmbin 0; 0 .text excmbin: mov r0,r3 / give left flag of right br eoprnd exrsh: neg r1 beq exlsh inc r1 clc ror r2 exlsh: clr r5 jsr pc,combin ash r1,r2 br eoprnd exmod: clr r5 jsr pc,combin mov r1,-(sp) mov r2,r1 clr r0 div (sp)+,r0 mov r1,r2 br eoprnd exadd: clr r5 jsr pc,combin add r1,r2 br eoprnd exsub: mov $1,r5 jsr pc,combin sub r1,r2 br eoprnd exand: clr r5 jsr pc,combin com r1 bic r1,r2 br eoprnd exor: clr r5 jsr pc,combin bis r1,r2 br eoprnd exmul: clr r5 jsr pc,combin mul r2,r1 mov r1,r2 br eoprnd exdiv: clr r5 jsr pc,combin mov r1,-(sp) mov r2,r1 clr r0 div (sp)+,r0 mov r0,r2 br eoprnd exnot: clr r5 jsr pc,combin com r1 add r1,r2 br eoprnd eoprnd: mov $'+,(sp) jmp advanc combin: mov r0,-(sp) bis r3,(sp) bic $!40,(sp) bic $!37,r0 bic $!37,r3 cmp r0,r3 ble 1f mov r0,-(sp) mov r3,r0 mov (sp)+,r3 1: tst r0 beq 1f tst r5 beq 2f cmp r0,r3 bne 2f mov $1,r3 br 2f 1: clr r3 2: bis (sp)+,r3 rts pc .data chartab: .byte -14,-14,-14,-14,-02,-14,-14,-14 .byte -14,-22, -2,-14,-14,-22,-14,-14 .byte -14,-14,-14,-14,-14,-14,-14,-14 .byte -14,-14,-14,-14,-14,-14,-14,-14 .byte -22,-20,-16,-14,-20,-20,-20,-12 .byte -20,-20,-20,-20,-20,-20,056,-06 .byte 060,061,062,063,064,065,066,067 .byte 070,071,-20,-02,-00,-20,-14,-14 .byte -14,101,102,103,104,105,106,107 .byte 110,111,112,113,114,115,116,117 .byte 120,121,122,123,124,125,126,127 .byte 130,131,132,-20,-24,-20,-20,137 .byte -14,141,142,143,144,145,146,147 .byte 150,151,152,153,154,155,156,157 .byte 160,161,162,163,164,165,166,167 .byte 170,171,172,-14,-26,-14,176,-14 a.tmp1: Ncps: .byte 8. 1: <-\0> .even dash: 1b fin: -1 fout: -1 / The next two _must_ be adjacent! Not sure why, but then this whole / assembler is weird beyond belief. curfb: -1;-1;-1;-1;-1;-1;-1;-1;-1;-1 nxtfb: .=.+20. / first 4 used by pass0, all 20. by pass1+2 .bss curfbr: .=.+10. savdot: .=.+6 hshtab: .=.+2 / dynamically allocated ch: .=.+2 symnum: .=.+2 / symbol number symbol: .=.+32. / XXX .=.+2 / paranoia to make sure a null is present inbuf: .=.+1024. line: .=.+2 ifflg: .=.+2 nargs: .=.+2 curarg: .=.+2 opfound:.=.+2 savop: .=.+2 numval: .=.+2 fbtblsz:.=.+2 fbfree: .=.+2 fbptr: .=.+2 fbtbl: .=.+2 usymtab:.=.+2 / ptr to first block of symbols symleft:.=.+2 / bytes left in current symbol block symend: .=.+2 / ptr to next symbol space in block symblk: .=.+2 / ptr to beginning of current sym block strleft:.=.+2 / amount left in string block strend: .=.+2 / ptr to next available string byte strblk: .=.+2 / ptr to current string block link word / key to types / 0 undefined / 1 absolute (nop, reset, bpt, ...) / 2 text / 3 data / 4 bss / 5 flop freg,dst (movfo, = stcfd) / 6 branch / 7 jsr / 10 rts / 11 sys, trap / 12 movf (=ldf,stf) / 13 double operand (mov) / 14 flop fsrc,freg (addf) / 15 single operand (clr) / 16 .byte / 17 string (.ascii, "<") / 20 .even / 21 .if / 22 .endif / 23 .globl / 24 register / 25 .text / 26 .data / 27 .bss / 30 mul,div, etc / 31 sob / 32 .comm / 33 estimated text / 34 estimated data / 35 jbr / 36 jeq, jne, etc .data / the format of PST entries was changed. rather than fixed 8 byte strings / (often with many trailing nulls) a pointer to a null terminated string / is now used. This saves quite a bit of space since most PST entries are / only 3 or 4 characters long. we had to do this the hard way since there / is no macro capability in the assembler and i'd chuck out the SDI [Span / Dependent Instruction] stuff and use my own assembler before trying to / add macros to this one. Symbols beginning with 'L' are used since the / linker can be told to discard those. symtab: / special symbols L1; dotrel: 02; dot: 0000000 L2; 01; dotdot: 0000000 / register L3; 24; 000000 L4; 24; 000001 L5; 24; 000002 L6; 24; 000003 L7; 24; 000004 L8; 24; 000005 L9; 24; 000006 L10; 24; 000007 / double operand L11; 13; 0010000 L12; 13; 0110000 L13; 13; 0020000 L14; 13; 0120000 L15; 13; 0030000 L16; 13; 0130000 L17; 13; 0040000 L18; 13; 0140000 L19; 13; 0050000 L20; 13; 0150000 L21; 13; 0060000 L22; 13; 0160000 / branch L23; 06; 0000400 L24; 06; 0001000 L25; 06; 0001400 L26; 06; 0002000 L27; 06; 0002400 L28; 06; 0003000 L29; 06; 0003400 L30; 06; 0100000 L31; 06; 0100400 L32; 06; 0101000 L33; 06; 0101400 L34; 06; 0102000 L35; 06; 0102400 L36; 06; 0103000 L37; 06; 0103000 L38; 06; 0103000 L39; 06; 0103400 L40; 06; 0103400 L41; 06; 0103400 / jump/branch type L42; 35; 0000400 L43; 36; 0001000 L44; 36; 0001400 L45; 36; 0002000 L46; 36; 0002400 L47; 36; 0003000 L48; 36; 0003400 L49; 36; 0100000 L50; 36; 0100400 L51; 36; 0101000 L52; 36; 0101400 L53; 36; 0102000 L54; 36; 0102400 L55; 36; 0103000 L56; 36; 0103000 L57; 36; 0103000 L58; 36; 0103400 L59; 36; 0103400 L60; 36; 0103400 / single operand L61; 15; 0005000 L62; 15; 0105000 L63; 15; 0005100 L64; 15; 0105100 L65; 15; 0005200 L66; 15; 0105200 L67; 15; 0005300 L68; 15; 0105300 L69; 15; 0005400 L70; 15; 0105400 L71; 15; 0005500 L72; 15; 0105500 L73; 15; 0005600 L74; 15; 0105600 L75; 15; 0005700 L76; 15; 0105700 L77; 15; 0006000 L78; 15; 0106000 L79; 15; 0006100 L80; 15; 0106100 L81; 15; 0006200 L82; 15; 0106200 L83; 15; 0006300 L84; 15; 0106300 L85; 15; 0000100 L86; 15; 0000300 L87; 15; 0006500 L88; 15; 0006600 L89; 15; 0106500 L90; 15; 0106600 L91; 15; 0170300 L92; 15; 0106700 L93; 15; 0106400 L94; 15; 0007000 L95; 15; 0007200 L96; 15; 0007300 / jsr L97; 07; 0004000 / rts L98; 010; 000200 / simple operand L99; 011; 104400 L102; 011; 000230 / flag-setting L103; 01; 0000240 L104; 01; 0000241 L105; 01; 0000242 L106; 01; 0000244 L107; 01; 0000250 L108; 01; 0000257 L109; 01; 0000261 L110; 01; 0000262 L111; 01; 0000264 L112; 01; 0000270 L113; 01; 0000277 L114; 01; 0000000 L115; 01; 0000001 L116; 01; 0000002 L117; 01; 0000003 L118; 01; 0000004 L119; 01; 0000005 L120; 01; 0000006 L121; 01; 0000007 / floating point ops L122; 01; 170000 L123; 01; 170001 L124; 01; 170011 L125; 01; 170002 L126; 01; 170012 L127; 15; 170400 L128; 15; 170700 L129; 15; 170600 L130; 15; 170500 L131; 12; 172400 L132; 14; 177000 L133; 05; 175400 L134; 14; 177400 L135; 05; 176000 L136; 14; 172000 L137; 14; 173000 L138; 14; 171000 L139; 14; 174400 L140; 14; 173400 L141; 14; 171400 L142; 14; 176400 L143; 05; 175000 L144; 15; 170100 L145; 15; 170200 L146; 24; 000000 L147; 24; 000001 L148; 24; 000002 L149; 24; 000003 L150; 24; 000004 L151; 24; 000005 L152; 30; 070000 L153; 30; 071000 L154; 30; 072000 L155; 30; 073000 L156; 07; 074000 L157; 15; 006700 L158; 11; 006400 L159; 31; 077000 / pseudo ops L160; 16; 000000 L161; 20; 000000 L162; 21; 000000 L163; 22; 000000 L164; 23; 000000 L165; 25; 000000 L166; 26; 000000 L167; 27; 000000 L168; 32; 000000 ebsymtab: L1: <.\0> L2: <..\0> L3: L4: L5: L6: L7: L8: L9: L10: L11: L12: L13: L14: L15: L16: L17: L18: L19: L20: L21: L22: L23: L24: L25: L26: L27: L28: L29: L30: L31: L32: L33: L34: L35: L36: L37: L38: L39: L40: L41: L42: L43: L44: L45: L46: L47: L48: L49: L50: L51: L52: L53: L54: L55: L56: L57: L58: L59: L60: L61: L62: L63: L64: L65: L66: L67: L68: L69: L70: L71: L72: L73: L74: L75: L76: L77: L78: L79: L80: L81: L82: L83: L84: L85: L86: L87: L88: L89: L90: L91: L92: L93: L94: L95: L96: L97: L98: L99: L102: L103: L104: L105: L106: L107: L108: L109: L110: L111: L112: L113: L114: L115: L116: L117: L118: L119: L120: L121: L122: L123: L124: L125: L126: L127: L128: L129: L130: L131: L132: L133: L134: L135: L136: L137: L138: L139: L140: L141: L142: L143: L144: L145: L146: L147: L148: L149: L150: L151: L152: L153: L154: L155: L156: L157: L158: L159: L160: <.byte\0> L161: <.even\0> L162: <.if\0> L163: <.endif\0> L164: <.globl\0> L165: <.text\0> L166: <.data\0> L167: <.bss\0> L168: <.comm\0> .text ,p0readop 1: mov r4,r0 tst r0 blt 6f cmp r0,$177 ble 7f 6: movb (r4),r0 mov 2(r4),r1 br oprand 7: cmp r4bin/as/as2.s 644 0 12 61270 5445747172 6121 .globl _signal, _close, _lseek, _unlink, _umask, _chmod, __exit .globl _write, _read, _brk, _end, _open, _creat, _realloc, _fchmod .globl pass1, hshsiz, outmod, dot, dotdot, error .globl checkeos, curfb, savdot, ch, line, savop, inbuf, errflg .globl fbptr, fbtbl, symnum, hshtab, symblk, symleft, dotrel .globl symtab, aexit, overlaid, defund, a.outp, passno, filerr .globl wrterr, argb, errore, errora, curfb, nxtfb, usymtab .globl fin, fout, a.tmp1, ibufc, ibufp, obufp, outbuf, symbol .globl PSTENTSZ, SYMENTSZ, SYMBLKSZ, Newsym pass1: mov fout,fin / tmp file is now input file mov $666,-(sp) / mode mov $3001 ,-(sp) / O_WRONLY|O_CREAT|O_TRUNC mov a.outp,-(sp) / filename jsr pc,_open add $6,sp mov r0,fout / file descriptor any good? bpl 1f / yes - br mov a.outp,-(sp) jsr pc,filerr 1: / 'symnum' has number of symbols. The hashtable from pass 0 is no / longer needed - we can reuse it directly for 'usymtab' if there are less / than 'hshsiz' symbols. If there are more than 'hshsiz' (currently / 1500) symbols we have to realloc. / / The 'fb' table (usually 0 long) is appended to the 'usymtab' (4 byte / entries per symbol). mov fbptr,r0 sub fbtbl,r0 / # bytes in 'fb' table asr r0 / convert to number of words add symnum,r0 / add in number of symbols twice add symnum,r0 / because we need 2 words per symbol inc r0 / one more for terminator word cmp r0,$hshsiz / is hashtable big enough already? blo 1f / yes -br asl r0 / convert to bytes mov r0,-(sp) mov hshtab,-(sp) jsr pc,_realloc / hshtab = realloc(hshtab, r0) mov r0,hshtab / check for failure? 1: mov hshtab,r1 mov usymtab,r2 9: mov r2,symblk / save ptr to start of block tst (r2)+ / skip link word mov $SYMBLKSZ,symleft / init amount left in block 1: tst (r2) / end of symbol table block beq 4f / yes - br add $8.,symsiz / size of symbol table tst Newsym / are we doing new style? bne 8f / yes - br add $4,symsiz / no, symbol table entries are bigger 8: mov 2(r2),r0 / flags word bic $!37,r0 cmp r0,$2 /text blo 2f cmp r0,$3 /data bhi 2f add $31,r0 /mark "estimated" mov r0,(r1)+ / store flags word mov 4(r2),(r1)+ / copy value word br 3f 2: clr (r1)+ clr (r1)+ 3: add $SYMENTSZ,r2 / skip to next symbol entry sub $SYMENTSZ,symleft / one symbol less in block cmp symleft,$SYMENTSZ / room for another symbol? bge 1b / yes - br 4: mov *symblk,r2 / follow link to next block bne 9b / if not at end 1: / The 'fb' table needs to be appended to the 'usymtab' table now mov fbtbl,r0 mov r1,fbbufp / save start of 'fb' table 1: cmp r0,fbptr / at end of table? bhis 2f / yes - br mov (r0)+,r4 add $31,r4 / "estimated" mov r4,(r1)+ mov (r0)+,(r1)+ br 1b 2: mov r1,endtable mov $100000,(r1)+ mov $savdot,r0 / reset the 'psect' (text,data,bss) clr (r0)+ / counters for the next pass clr (r0)+ clr (r0)+ jsr pc,setup / init fb stuff jsr pc,pass1_2 / do pass 1 / prepare for pass 2 inc passno cmp outmod,$777 beq 1f jmp aexit 1: jsr pc,setup inc bsssiz bic $1,bsssiz mov txtsiz,r1 inc r1 bic $1,r1 mov r1,txtsiz mov datsiz,r2 inc r2 bic $1,r2 mov r2,datsiz mov r1,r3 mov r3,datbase / txtsiz mov r3,savdot+2 add r2,r3 mov r3,bssbase / txtsiz+datsiz mov r3,savdot+4 clr r0 asl r3 adc r0 add $20,r3 adc r0 mov r3,symseek+2 / 2*txtsiz+2*datsiz+20 mov r0,symseek sub r2,r3 sbc r0 mov r3,drelseek+2 / 2*txtsiz+datsiz mov r0,drelseek sub r1,r3 sbc r0 mov r3,trelseek+2 / txtsiz+datsiz+20 mov r0,trelseek sub r2,r3 sbc r0 mov r0,datseek mov r3,datseek+2 / txtsiz+20 mov hshtab,r1 1: jsr pc,doreloc add $4,r1 cmp r1,endtable blo 1b clr r0 clr r1 mov $txtp,-(sp) jsr pc,oset mov trelseek,r0 mov trelseek+2,r1 mov $relp,-(sp) jsr pc,oset mov $8.,r2 mov $txtmagic,r1 1: mov (r1)+,r0 mov $txtp,-(sp) jsr pc,putw sob r2,1b jsr pc,pass1_2 / do pass 2 /polish off text and relocation mov $txtp,-(sp) jsr pc,flush mov $relp,-(sp) jsr pc,flush / append full symbol table mov symseek,r0 mov symseek+2,r1 mov $txtp,-(sp) jsr pc,oset mov usymtab,r2 / pointer to first symbol block mov hshtab,r1 / 'type' and 'value' array tst Newsym beq 8f jsr pc,nsymout br 9f 8: jsr pc,osymout 9: mov $txtp,-(sp) jsr pc,flush br aexit saexit: mov pc,errflg aexit: mov $a.tmp1,-(sp) / unlink(a.tmp1) jsr pc,_unlink tst errflg bne 2f clr (sp) jsr pc,_umask bic r0,outmod / fchmod(fout, outmod&umask(0)) mov outmod,(sp) mov fout,-(sp) jsr pc,_fchmod tst (sp)+ clr (sp) br 1f 2: mov $2,(sp) 1: jsr pc,__exit / _exit(errflg ? 2 : 0) filerr: mov 2(sp),r0 / filename string. no need to clean tst -(sp) / stack, this routine goes to saexit. mov r0,-(sp) mov $1,-(sp) 1: tstb (r0)+ bne 1b sub 2(sp),r0 dec r0 mov r0,4(sp) jsr pc,_write add $6,sp mov $2,-(sp) / write(1, "?\n", 2) mov $qnl,-(sp) mov $1,-(sp) jsr pc,_write add $6,sp tst passno bpl saexit rts pc osymout: 9: mov r2,symblk / save ptr to current sym block tst (r2)+ / skip link word mov $SYMBLKSZ,symleft / space left in symbol block 1: mov (r2),r4 / pointer to symbol name beq 4f / end of block - br mov $8.,r5 / max number to copy mov $symbol,r0 / destination buffer 2: movb (r4),(r0)+ / copy a byte beq 6f inc r4 / non null - bump source ptr 6: sob r5,2b / Now put four words of symbol name to the object file mov $4,r5 / number of words to do mov $symbol,r4 6: mov (r4)+,r0 / word (2 chars) of symbol name mov $txtp,-(sp) jsr pc,putw sob r5,6b / values from 'hshtab' (parallel array to symbol table) are retrieved now, / they take the place of the flags and value entries of the symbol table. mov (r1)+,r0 mov $txtp,-(sp) jsr pc,putw mov (r1)+,r0 mov $txtp,-(sp) jsr pc,putw add $SYMENTSZ,r2 / skip to next symbol sub $SYMENTSZ,symleft / one less symbol in block cmp symleft,$SYMENTSZ / room for another? bge 1b / yes - br 4: mov *symblk,r2 / no, follow link to next block bne 9b / unless it's end of list rts pc nsymout: clr totalsz mov $4,totalsz+2 / string table min size is 4 9: mov r2,symblk / save ptr to current symbol block tst (r2)+ / skip link word mov $SYMBLKSZ,symleft / amount of space left in block 1: mov (r2),r4 / pointer to symbol's string beq 4f / end of block - br mov totalsz,r0 / now output the... mov $txtp,-(sp) / high order of the string index... jsr pc,putw / to the object file mov totalsz+2,r0 mov $txtp,-(sp) jsr pc,putw / and the low order word 2: tstb (r4)+ / find the end of the string bne 2b sub (r2),r4 / compute length including the null add r4,totalsz+2 / offset of next string adc totalsz mov (r1)+,r0 / 'type' word of symbol mov $txtp,-(sp) jsr pc,putw mov (r1)+,r0 / 'value' word of symbol mov $txtp,-(sp) jsr pc,putw add $SYMENTSZ,r2 / advance to next symbol sub $SYMENTSZ,symleft / adjust amount left in symbol block cmp symleft,$SYMENTSZ / is there enough for another symbol? bge 1b / yes - br 4: mov *symblk,r2 / follow link to next symbol block bne 9b / more - br mov totalsz,r0 / now output the string table length mov $txtp,-(sp) / high order word first jsr pc,putw mov totalsz+2,r0 / followed by the low order mov $txtp,-(sp) jsr pc,putw / Now write the strings out mov usymtab,r2 / start at beginning of symbols 9: mov r2,symblk / save pointer to current block tst (r2)+ / skip link word mov $SYMBLKSZ,symleft / amount left in block 1: mov (r2),r4 / pointer to symbol's string beq 4f / at end of block - br jsr pc,putstring / write out the string add $SYMENTSZ,r2 / advance to next symbol sub $SYMENTSZ,symleft / adjust amount left in block cmp symleft,$SYMENTSZ / enough for another symbol? bge 1b / yes - br 4: mov *symblk,r2 / move to next block of symbols bne 9b / any left - br / probably not necessary but let us leave the file size on an even / byte boundary. bit $1,totalsz+2 / odd number of bytes in string table? beq 5f / no - br mov symblk,r4 / we know 'symblk' points to a null jsr pc,putstring / output a single null 5: rts pc / R4 has the address of a null terminated string to write to the output / file. The terminating null is included in the output. This routine / "inlines" the 'txtp seek structure' manipulation because the 'putw' / routine was 1) not suitable to byte output and 2) symbol strings are / only written using the 'txtp' (as opposed to 'relp' - relocation info) / structure. putstring: cmp txtp,txtp+2 / room for another byte? bhis 1f / no - br 3: movb (r4),*txtp / put byte in buffer inc txtp / advance output position tstb (r4)+ / did we just do the null? bne putstring / no - go again rts pc / yes - we're done, return 1: mov r2,-(sp) / save r2 from being destroyed mov $txtp,-(sp) / flush buffered output and... jsr pc,flush / reset the pointers mov (sp)+,r2 / restore symbol pointer br 3b / go output a byte doreloc: movb (r1),r0 bne 1f bisb defund,(r1) 1: bic $!37,r0 cmp r0,$5 bhis 1f cmp r0,$3 blo 1f beq 2f add bssbase,2(r1) rts pc 2: add datbase,2(r1) 1: rts pc setup: clr dot mov $2,dotrel mov $..,dotdot clr brtabp mov $curfb,r4 1: clr (r4)+ cmp r4,$curfb+40. blo 1b clr r4 1: jsr pc,fbadv inc r4 cmp r4,$10. blt 1b / just rewind /tmp/atm1xx rather than close and re-open clr -(sp) clr -(sp) clr -(sp) mov fin,-(sp) jsr pc,_lseek / lseek(fin, 0L, 0) add $8.,sp clr ibufc rts pc outw: cmp dot-2,$4 beq 9f bit $1,dot bne 1f add $2,dot tst passno beq 8f clr -(sp) rol r3 adc (sp) asr r3 / get relative pc bit cmp r3,$40 bne 2f / external references mov $666,outmod / make nonexecutable mov xsymbol,r3 sub hshtab,r3 asl r3 bis $4,r3 / external relocation br 3f 2: bic $40,r3 / clear any ext bits cmp r3,$5 blo 4f cmp r3,$33 / est. text, data beq 6f cmp r3,$34 bne 7f 6: mov $'r,-(sp) jsr pc,error 7: mov $1,r3 / make absolute 4: cmp r3,$2 blo 5f cmp r3,$4 bhi 5f tst (sp) bne 4f add dotdot,r2 br 4f 5: tst (sp) beq 4f sub dotdot,r2 4: dec r3 bpl 3f clr r3 3: asl r3 bis (sp)+,r3 mov r2,r0 mov $txtp,-(sp) jsr pc,putw mov tseekp,r0 add $2,2(r0) adc (r0) mov r3,r0 mov $relp,-(sp) jsr pc,putw mov rseekp,r0 add $2,2(r0) adc (r0) 8: rts pc 1: mov $'o,-(sp) jsr pc,error clr r3 jsr pc,outb rts pc 9: mov $'x,-(sp) jsr pc,error rts pc outb: cmp dot-2,$4 / test bss mode beq 9b cmp r3,$1 blos 1f mov $'r,-(sp) jsr pc,error 1: tst passno beq 2f mov r2,r0 bit $1,dot bne 1f mov $txtp,-(sp) jsr pc,putw clr r0 mov $relp,-(sp) jsr pc,putw mov tseekp,r0 add $2,2(r0) adc (r0) mov rseekp,r0 add $2,2(r0) adc (r0) br 2f 1: mov txtp,r0 movb r2,-1(r0) 2: inc dot rts pc / pass 1 and 2 common code pass1_2: jsr pc,readop cmp r4,$5 beq 2f cmp r4,$'< beq 2f jsr pc,checkeos br eal1 mov r4,-(sp) cmp (sp),$1 bne 1f mov $2,(sp) jsr pc,getw mov r4,numval 1: jsr pc,readop cmp r4,$'= beq 4f cmp r4,$': beq 1f mov r4,savop mov (sp)+,r4 2: jsr pc,opline dotmax: tst passno bne eal1 movb dotrel,r0 asl r0 cmp dot,txtsiz-4(r0) bhi 8f jmp ealoop 8: mov dot,txtsiz-4(r0) eal1: jmp ealoop 1: mov (sp)+,r4 cmp r4,$200 bhis 1f cmp r4,$2 beq 3f mov $'x,-(sp) jsr pc,error br pass1_2 1: tst passno bne 2f movb (r4),r0 bic $!37,r0 beq 5f cmp r0,$33 blt 6f cmp r0,$34 ble 5f 6: mov $'m,-(sp) jsr pc,error 5: bic $37,(r4) bis dotrel,(r4) mov 2(r4),brdelt sub dot,brdelt mov dot,2(r4) br pass1_2 2: cmp dot,2(r4) beq pass1_2 mov $'p,-(sp) jsr pc,error br pass1_2 3: mov numval,r4 jsr pc,fbadv asl r4 mov curfb(r4),r0 movb dotrel,(r0) mov 2(r0),brdelt sub dot,brdelt mov dot,2(r0) br pass1_2 4: jsr pc,readop jsr pc,expres mov (sp)+,r1 cmp r1,$dotrel /test for dot bne 1f bic $40,r3 cmp r3,dotrel / can't change relocation bne 2f cmp r3,$4 / bss bne 3f mov r2,dot br dotmax 3: sub dot,r2 bmi 2f mov r2,-(sp) 3: dec (sp) bmi 3f clr r2 mov $1,r3 jsr pc,outb br 3b 3: tst (sp)+ br dotmax 2: mov $'.,-(sp) jsr pc,error br ealoop 1: cmp r3,$40 bne 1f mov $'r,-(sp) jsr pc,error 1: bic $37,(r1) bic $!37,r3 bne 1f clr r2 1: bisb r3,(r1) mov r2,2(r1) ealoop: cmp r4,$'\n beq 1f cmp r4,$'\e bne 9f rts pc 1: inc line 9: jmp pass1_2 checkeos: cmp r4,$'\n beq 1f cmp r4,$'; beq 1f cmp r4,$'\e beq 1f add $2,(sp) 1: rts pc fbadv: asl r4 mov nxtfb(r4),r1 mov r1,curfb(r4) bne 1f mov fbbufp,r1 br 2f 1: add $4,r1 2: cmpb 1(r1),r4 beq 1f tst (r1) bpl 1b 1: mov r1,nxtfb(r4) asr r4 rts pc oset: mov r2,-(sp) mov r3,-(sp) mov 6(sp),r3 mov r1,r2 bic $!1777,r1 add r3,r1 add $8,r1 mov r1,(r3)+ / next slot mov r3,r1 add $2006,r1 mov r1,(r3)+ / buf max mov r0,(r3)+ mov r2,(r3)+ / seek addr mov (sp)+,r3 mov (sp)+,r2 mov (sp)+,(sp) rts pc putw: mov r1,-(sp) mov r2,-(sp) mov 6(sp),r2 mov (r2)+,r1 / slot cmp r1,(r2) / buf max bhis 1f mov r0,(r1)+ mov r1,-(r2) br 2f 1: tst (r2)+ mov r0,-(sp) jsr pc,flush1 mov (sp)+,r0 mov r0,*(r2)+ add $2,-(r2) 2: mov (sp)+,r2 mov (sp)+,r1 mov (sp)+,(sp) ret: rts pc flush: mov 2(sp),r2 mov (sp)+,(sp) cmp (r2)+,(r2)+ flush1: clr -(sp) / lseek(fout, (r2)L+, L_SET) mov 2(r2),-(sp) mov (r2)+,-(sp) tst (r2)+ mov fout,-(sp) jsr pc,_lseek add $8.,sp cmp -(sp),-(sp) / write(fout, , ) bic $!1777,r1 add r2,r1 / write address mov r1,-(sp) / { } mov r2,r0 bis $1777,-(r2) add $1,(r2) / new seek addr adc -(r2) cmp -(r2),-(r2) sub (r2),r1 neg r1 mov r1,2(sp) / count mov r0,(r2) / new next slot mov fout,-(sp) mov r1,6(sp) / protect r1 from library jsr pc,_write add $6,sp mov (sp)+,r1 tst r0 bpl ret / fall thru to wrterr wrterr: mov $8f-9f,-(sp) / write(1, 9f, 8f-9f) mov $9f,-(sp) mov $1,-(sp) jsr pc,_write add $6,sp jmp saexit .data 9: 8: .even .text readop: mov savop,r4 beq 1f clr savop rts pc 1: jsr pc,getw1 cmp r4,$200 blo 1f cmp r4,$4000 blo 2f sub $4000,r4 asl r4 asl r4 add hshtab,r4 rts pc 2: / remove PST flag (1000) then multiply by PSTENTSZ. In pass 0 the PST / symbol number was divided by PSTENTSZ(to make it fit) - we now reverse / that process. mov r5,-(sp) mov r4,r5 sub $1000,r5 mul $PSTENTSZ,r5 mov r5,r4 mov (sp)+,r5 add $dotrel,r4 / point at dot's flag field 1: rts pc getw: mov savop,r4 beq getw1 clr savop rts pc getw1: dec ibufc bgt 1f mov r1,-(sp) / protect r1 from library mov $1024.,-(sp) / read(fin, inbuf, 1024) mov $inbuf,-(sp) mov fin,-(sp) jsr pc,_read add $6,sp mov (sp)+,r1 asr r0 mov r0,ibufc bgt 2f mov $4,r4 sev rts pc 2: mov $inbuf,ibufp 1: mov *ibufp,r4 add $2,ibufp rts pc opline: mov r4,r0 bmi 2f cmp r0,$177 bgt 2f cmp r4,$5 beq opeof cmp r4,$'< bne xpr jmp opl17 xxpr: tst (sp)+ xpr: jsr pc,expres jsr pc,outw rts pc 2: movb (r4),r0 cmp r0,$24 /reg beq xpr cmp r0,$33 /est text beq xpr cmp r0,$34 / est data beq xpr cmp r0,$5 blt xpr cmp r0,$36 bgt xpr mov 2(r4),-(sp) mov r0,-(sp) jsr pc,readop mov (sp)+,r0 asl r0 mov $adrbuf,r5 clr swapf mov $-1,rlimit jmp *1f-10.(r0) .data 1: opl5 opl6 opl7 opl10 opl11 opl12 opl13 opl14 opl15 opl16 opl17 opl20 opl21 opl22 opl23 xxpr opl25 opl26 opl27 opl30 opl31 opl32 xxpr xxpr opl35 opl36 .text opeof: mov $1,line mov $20,-(sp) mov $argb,r1 1: jsr pc,getw tst r4 bmi 1f movb r4,(r1)+ dec (sp) bgt 1b tstb -(r1) br 1b 1: movb $'\n,(r1)+ clrb (r1)+ tst (sp)+ rts pc opl30: / mul, div etc inc swapf mov $1000,rlimit br opl13 opl14: / flop freg,fsrc inc swapf opl5: / flop src,freg mov $400,rlimit opl13: /double jsr pc,addres op2a: mov r2,-(sp) jsr pc,readop op2b: jsr pc,addres tst swapf beq 1f mov (sp),r0 mov r2,(sp) mov r0,r2 1: swab (sp) asr (sp) asr (sp) cmp (sp),rlimit blo 1f mov $'x,-(sp) jsr pc,error 1: bis (sp)+,r2 bis (sp)+,r2 clr r3 jsr pc,outw mov $adrbuf,r1 1: cmp r1,r5 bhis 1f mov (r1)+,r2 mov (r1)+,r3 mov (r1)+,xsymbol jsr pc,outw br 1b 1: rts pc opl15: / single operand clr -(sp) br op2b opl12: / movf mov $400,rlimit jsr pc,addres cmp r2,$4 / see if source is fregister blo 1f inc swapf br op2a 1: mov $174000,(sp) br op2a opl35: / jbr opl36: / jeq, jne, etc jsr pc,expres tst passno bne 1f mov r2,r0 jsr pc,setbr tst r2 beq 2f cmp (sp),$br beq 2f add $2,r2 2: add r2,dot / if doesn't fit add $2,dot tst (sp)+ rts pc 1: jsr pc,getbr bcc dobranch mov (sp)+,r0 mov r2,-(sp) mov r3,-(sp) cmp r0,$br beq 2f mov $402,r2 xor r0,r2 / flip cond, add ".+6" mov $1,r3 jsr pc,outw 2: mov $1,r3 mov $jmp+37,r2 jsr pc,outw mov (sp)+,r3 mov (sp)+,r2 jsr pc,outw rts pc opl31: / sob jsr pc,expres jsr pc,checkreg swab r2 asr r2 asr r2 bis r2,(sp) jsr pc,readop jsr pc,expres tst passno beq 3f sub dot,r2 neg r2 mov r2,r0 cmp r0,$-2 blt 2f cmp r0,$175 bgt 2f add $4,r2 br 1f opl6: /branch jsr pc,expres tst passno beq 3f dobranch: sub dot,r2 mov r2,r0 cmp r0,$-254. blt 2f cmp r0,$256. bgt 2f 1: bit $1,r2 bne 2f cmp r3,dot-2 / same relocation as . bne 2f asr r2 dec r2 bic $177400,r2 3: bis (sp)+,r2 clr r3 jsr pc,outw rts pc 2: mov $'b,-(sp) jsr pc,error clr r2 br 3b opl7: /jsr jsr pc,expres jsr pc,checkreg jmp op2a opl10: / rts jsr pc,expres jsr pc,checkreg br 1f opl11: / sys jsr pc,expres cmp r2,$256. bhis 0f cmp r3,$1 ble 1f 0: jsr pc,errora 1: bis (sp)+,r2 jsr pc,outw rts pc opl16: / .byte jsr pc,expres jsr pc,outb cmp r4,$', bne 1f jsr pc,readop br opl16 1: tst (sp)+ rts pc opl17: / < (.ascii) jsr pc,getw mov $1,r3 mov r4,r2 bmi 2f bic $!377,r2 jsr pc,outb br opl17 2: jsr pc,getw rts pc opl20: /.even bit $1,dot beq 1f cmp dot-2,$4 beq 2f / bss mode clr r2 clr r3 jsr pc,outb br 1f 2: inc dot 1: tst (sp)+ rts pc opl21: /if jsr pc,expres opl22: oplret: tst (sp)+ rts pc opl23: /.globl cmp r4,$200 blo 1f bisb $40,(r4) jsr pc,readop cmp r4,$', bne 1f jsr pc,readop br opl23 1: tst (sp)+ rts pc opl25: / .text, .data, .bss opl26: opl27: inc dot bic $1,dot mov r0,-(sp) mov dot-2,r1 asl r1 mov dot,savdot-4(r1) tst passno beq 1f mov $txtp,-(sp) jsr pc,flush mov $relp,-(sp) jsr pc,flush mov (sp),r2 asl r2 add $txtseek-[4*25],r2 mov r2,tseekp mov (r2),r0 mov 2(r2),r1 mov $txtp,-(sp) jsr pc,oset add $trelseek-txtseek,r2 mov (r2),r0 mov 2(r2),r1 mov r2,rseekp mov $relp,-(sp) jsr pc,oset 1: mov (sp)+,r0 mov savdot-[2*25](r0),dot asr r0 sub $25-2,r0 mov r0,dot-2 / new . relocation tst (sp)+ rts pc opl32: cmp r4,$200 blo 1f mov r4,-(sp) jsr pc,readop jsr pc,readop jsr pc,expres mov (sp)+,r0 bit $37,(r0) bne 1f bis $40,(r0) mov r2,2(r0) 1: tst (sp)+ rts pc addres: clr -(sp) 4: cmp r4,$'( beq alp cmp r4,$'- beq amin cmp r4,$'$ beq adoll cmp r4,$'* bne getx jmp astar getx: jsr pc,expres cmp r4,$'( bne 2f jsr pc,readop mov r2,(r5)+ mov r3,(r5)+ mov xsymbol,(r5)+ jsr pc,expres jsr pc,checkreg jsr pc,checkrp bis $60,r2 bis (sp)+,r2 rts pc 2: cmp r3,$24 bne 1f jsr pc,checkreg bis (sp)+,r2 rts pc 1: mov r3,-(sp) bic $40,r3 mov (sp)+,r3 bis $100000,r3 sub dot,r2 sub $4,r2 cmp r5,$adrbuf beq 1f sub $2,r2 1: mov r2,(r5)+ / index mov r3,(r5)+ / index reloc. mov xsymbol,(r5)+ / index global mov $67,r2 / address mode bis (sp)+,r2 rts pc alp: jsr pc,readop jsr pc,expres jsr pc,checkrp jsr pc,checkreg cmp r4,$'+ beq 1f tst (sp)+ beq 2f bis $70,r2 clr (r5)+ clr (r5)+ mov xsymbol,(r5)+ rts pc 2: bis $10,r2 rts pc 1: jsr pc,readop bis $20,r2 bis (sp)+,r2 rts pc amin: jsr pc,readop cmp r4,$'( beq 1f mov r4,savop mov $'-,r4 br getx 1: jsr pc,readop jsr pc,expres jsr pc,checkrp jsr pc,checkreg bis (sp)+,r2 bis $40,r2 rts pc adoll: jsr pc,readop jsr pc,expres mov r2,(r5)+ mov r3,(r5)+ mov xsymbol,(r5)+ mov (sp)+,r2 bis $27,r2 rts pc astar: tst (sp) beq 1f mov $'*,-(sp) jsr pc,error 1: mov $10,(sp) jsr pc,readop jmp 4b checkreg: cmp r2,$7 bhi 1f cmp r1,$1 blos 2f cmp r3,$5 blo 1f 2: rts pc 1: jsr pc,errora clr r2 clr r3 rts pc checkrp: cmp r4,$') beq 1f mov $'),-(sp) jsr pc,error rts pc 1: jsr pc,readop rts pc setbr: mov brtabp,r1 cmp r1,$brlen blt 1f mov $2,r2 rts pc 1: inc brtabp clr -(sp) sub dot,r0 ble 1f sub brdelt,r0 1: cmp r0,$-254. blt 1f cmp r0,$256. ble 2f 1: mov r1,-(sp) bic $!7,(sp) mov $1,r0 ash (sp)+,r0 ash $-3,r1 bisb r0,brtab(r1) mov $2,(sp) 2: mov (sp)+,r2 rts pc getbr: mov brtabp,r1 cmp r1,$brlen blt 1f sec rts pc 1: mov r1,-(sp) bic $!7,(sp) neg (sp) inc brtabp ash $-3,r1 movb brtab(r1),r1 ash (sp)+,r1 ror r1 / 0-bit into c-bit rts pc expres: clr xsymbol expres1: mov r5,-(sp) mov $'+,-(sp) clr r2 mov $1,r3 br 1f advanc: jsr pc,readop 1: mov r4,r0 blt 6f cmp r0,$177 ble 7f 6: movb (r4),r0 bne 1f tst passno beq 1f mov $'u,-(sp) jsr pc,error 1: tst overlaid beq 0f / / Bill Shannon's hack to the assembler to force globl text / references to remain undefined so that the link editor may / resolve them. This is necessary if a function is used as an / arg in an overlay located piece of code, and the function is / actually in another overlay. Elsewise, the assembler fix's up / the reference before the link editor changes the globl refrence / to the thunk. -wfj 5/80 cmp r0,$42 / is it globl text ? bne 0f / nope mov $40,r0 / yes, treat it as undefined external 0: cmp r0,$40 bne 1f mov r4,xsymbol clr r1 br oprand 1: mov 2(r4),r1 br oprand 7: cmp r4,$141 blo 1f asl r4 mov curfb-[2*141](r4),r0 mov 2(r0),r1 movb (r0),r0 br oprand 1: mov $esw1,r1 1: cmp (r1)+,r4 beq 1f tst (r1)+ bne 1b tst (sp)+ mov (sp)+,r5 rts pc 1: jmp *(r1) .data esw1: '+; binop '-; binop '*; binop '/; binop '&; binop 037; binop 035; binop 036; binop '%; binop '[; brack '^; binop 1; exnum 2; exnum1 '!; binop 200; 0 .text binop: cmpb (sp),$'+ beq 1f jsr pc,errore 1: movb r4,(sp) br advanc exnum1: mov numval,r1 br 1f exnum: jsr pc,getw mov r4,r1 1: mov $1,r0 br oprand brack: mov r2,-(sp) mov r3,-(sp) jsr pc,readop jsr pc,expres1 cmp r4,$'] beq 1f mov $'],-(sp) jsr pc,error 1: mov r3,r0 mov r2,r1 mov (sp)+,r3 mov (sp)+,r2 oprand: mov $exsw2,r5 1: cmp (sp),(r5)+ beq 1f tst (r5)+ bne 1b br eoprnd 1: jmp *(r5) .data exsw2: '+; exadd '-; exsub '*; exmul '/; exdiv 037; exor '&; exand 035;exlsh 036;exrsh '%; exmod '^; excmbin '!; exnot 200; 0 .text excmbin: mov r0,r3 br eoprnd exrsh: neg r1 beq exlsh inc r1 clc ror r2 exlsh: mov $relte2,r5 jsr pc,combin ash r1,r2 br eoprnd exmod: mov $relte2,r5 jsr pc,combin mov r3,r0 mov r2,r3 clr r2 div r1,r2 mov r3,r2 mov r0,r3 br eoprnd exadd: mov $reltp2,r5 jsr pc,combin add r1,r2 br eoprnd exsub: mov $reltm2,r5 jsr pc,combin sub r1,r2 br eoprnd exand: mov $relte2,r5 jsr pc,combin com r1 bic r1,r2 br eoprnd exor: mov $relte2,r5 jsr pc,combin bis r1,r2 br eoprnd exmul: mov $relte2,r5 jsr pc,combin mul r2,r1 mov r1,r2 br eoprnd exdiv: mov $relte2,r5 jsr pc,combin mov r3,r0 mov r2,r3 clr r2 div r1,r2 mov r0,r3 br eoprnd exnot: mov $relte2,r5 jsr pc,combin com r1 add r1,r2 br eoprnd eoprnd: mov $'+,(sp) jmp advanc combin: tst passno bne combin1 mov r0,-(sp) bis r3,(sp) bic $!40,(sp) bic $!37,r0 bic $!37,r3 cmp r0,r3 ble 1f mov r0,-(sp) mov r3,r0 mov (sp)+,r3 1: tst r0 beq 1f cmp r5,$reltm2 bne 2f cmp r0,r3 bne 2f mov $1,r3 br 2f 1: clr r3 2: bis (sp)+,r3 rts pc combin1: mov r1,-(sp) clr maxtyp jsr pc,maprel mov r0,r1 mul $6,r1 mov r3,r0 jsr pc,maprel add r5,r0 add r1,r0 movb (r0),r3 bpl 1f cmp r3,$-1 beq 2f mov $'r,-(sp) jsr pc,error 2: mov maxtyp,r3 1: mov (sp)+,r1 rts pc maprel: cmp r0,$40 bne 1f mov $5,r0 rts pc 1: bic $!37,r0 cmp r0,maxtyp blos 1f mov r0,maxtyp 1: cmp r0,$5 blo 1f mov $1,r0 1: rts pc .data X = -2 M = -1 reltp2: .byte 0, 0, 0, 0, 0, 0 .byte 0, M, 2, 3, 4,40 .byte 0, 2, X, X, X, X .byte 0, 3, X, X, X, X .byte 0, 4, X, X, X, X .byte 0,40, X, X, X, X reltm2: .byte 0, 0, 0, 0, 0, 0 .byte 0, M, 2, 3, 4,40 .byte 0, X, 1, X, X, X .byte 0, X, X, 1, X, X .byte 0, X, X, X, 1, X .byte 0, X, X, X, X, X relte2: .byte 0, 0, 0, 0, 0, 0 .byte 0, M, X, X, X, X .byte 0, X, X, X, X, X .byte 0, X, X, X, X, X .byte 0, X, X, X, X, X .byte 0, X, X, X, X, X qnl: a.out: .even a.outp: a.out obufp: outbuf passno: -1 outmod: 0777 tseekp: txtseek rseekp: trelseek txtmagic: br .+20 txtsiz: .=.+2 datsiz: .=.+2 bsssiz: .=.+2 symsiz: .=.+2 .=.+6 txtseek:0; 20 datseek:.=.+4 .=.+4 trelseek:.=.+4 drelseek:.=.+4 .=.+4 symseek:.=.+4 .bss brlen = 1024. brtab: .=.+[brlen\/8.] brtabp: .=.+2 brdelt: .=.+2 fbbufp: .=.+2 defund: .=.+2 datbase:.=.+2 bssbase:.=.+2 ibufc: .=.+2 overlaid: .=.+2 adrbuf: .=.+12. xsymbol:.=.+2 errflg: .=.+2 argb: .=.+22. numval: .=.+2 maxtyp: .=.+2 ibufp: .=.+2 txtp: .=.+8. .=.+1024. relp: .=.+8. outbuf: .=.+1024. swapf: .=.+2 rlimit: .=.+2 endtable:.=.+2 totalsz: / string table length .=.+4 .text pr mov 2(r4),-(sp) mov r0,-(sp) jsr pc,readop mov (sp)+,r0 asl r0 mov $adrbuf,r5 clr swapf mov $-1,rlimit jmp *1f-10.(r0) .data 1: opl5 opl6 opl7 opl10 opl11 opl12 opl13 opl14 opl15 opl16 opl17 opl20 opl21 opl22 opl23 xxpr opl25 opl26 opl27 opl30 opl31 opl32 xxpr xxpr opl35 opl36 .text opebin/df.c 444 0 12 11271 5514436162 5363 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)df.c 5.1.1 (2.11BSD GTE) 1/1/94"; #endif #include #include #include #include #include #include #include /* * df */ struct mtab mtab[NMOUNT]; char root[32]; char *mpath(); int iflag; union { struct fs iu_fs; char dummy[SBSIZE]; } sb; #define sblock sb.iu_fs int fi; daddr_t alloc(); char *strcpy(); main(argc, argv) int argc; char **argv; { int i; while (argc > 1 && argv[1][0]=='-') { switch (argv[1][1]) { case 'i': iflag++; break; default: fprintf(stderr, "usage: df [ -i ] [ filsys... ]\n"); exit(0); } argc--, argv++; } i = open("/etc/mtab", 0); if (i >= 0) { (void) read(i, (char *)mtab, sizeof (mtab)); (void) close(i); } sync(); printf("Filesystem kbytes used avail capacity"); if (iflag) printf(" iused ifree %%iused"); printf(" Mounted on\n"); if (argc <= 1) { struct fstab *fsp; if (setfsent() == 0) perror(FSTAB), exit(1); while (fsp = getfsent()) { if (strcmp(fsp->fs_type, FSTAB_RW) && strcmp(fsp->fs_type, FSTAB_RO) && strcmp(fsp->fs_type, FSTAB_RQ)) continue; if (root[0] == 0) (void) strcpy(root, fsp->fs_spec); dfree(fsp->fs_spec, 1); } endfsent(); exit(0); } for (i=1; ifs_spec, &stb) == 0 && stb.st_rdev == stbuf.st_dev) { file = fsp->fs_spec; endfsent(); goto found; } } endfsent(); fprintf(stderr, "%s: mounted on unknown device\n", file); return; } found: fi = open(file, 0); if (fi < 0) { perror(file); return; } if (bread(SBLOCK, (char *)&sblock, SBSIZE) == 0) { (void) close(fi); return; } printf("%-12.12s", file); #ifdef pdp11 totalblks = (long) sblock.fs_fsize - (long)sblock.fs_isize; free = sblock.fs_tfree; used = totalblks - free; printf("%8ld%8ld%8ld%6.0f%%", totalblks, used, free, totalblks == 0L ? 0.0 : (double) used / (double)totalblks * 100.0); if (iflag) { u_short inodes = (sblock.fs_isize - 2) * INOPB, iused = inodes - sblock.fs_tinode; printf("%8u%8u%7.0f%%", iused, sblock.fs_tinode, inodes ? (float)iused / (float)inodes * 100.0 : 0.0); #else totalblks = sblock.fs_dsize; free = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag + sblock.fs_cstotal.cs_nffree; used = totalblks - free; availblks = totalblks * (100 - sblock.fs_minfree) / 100; avail = availblks > used ? availblks - used : 0; printf("%8d%8d%8d", totalblks * sblock.fs_fsize / 1024, used * sblock.fs_fsize / 1024, avail * sblock.fs_fsize / 1024); printf("%6.0f%%", availblks == 0 ? 0.0 : (double) used / (double) availblks * 100.0); if (iflag) { int inodes = sblock.fs_ncg * sblock.fs_ipg; used = inodes - sblock.fs_cstotal.cs_nifree; printf("%8ld%8ld%6.0f%% ", used, sblock.fs_cstotal.cs_nifree, inodes == 0 ? 0.0 : (double)used / (double)inodes * 100.0); #endif } else printf(" "); printf(" %s\n", mpath(file)); (void) close(fi); } long lseek(); bread(bno, buf, cnt) daddr_t bno; char *buf; { int n; extern errno; (void) lseek(fi, (long)(bno * DEV_BSIZE), 0); if ((n=read(fi, buf, cnt)) != cnt) { /* probably a dismounted disk if errno == EIO */ if (errno != EIO) { printf("\nread error bno = %ld\n", bno); printf("count = %d; errno = %d\n", n, errno); } return (0); } return (1); } /* * Given a name like /dev/rrp0h, returns the mounted path, like /usr. */ char * mpath(file) char *file; { register struct mtab *mp; if (eq(file, root)) return ("/"); for (mp = mtab; mp < mtab + NMOUNT; mp++) if (eq(file, mp->m_dname)) return (mp->m_path); return ""; } eq(f1, f2) char *f1, *f2; { if (strncmp(f1, "/dev/", 5) == 0) f1 += 5; if (strncmp(f2, "/dev/", 5) == 0) f2 += 5; if (!strcmp(f1, f2)) return (1); if (*f1 == 'r' && !strcmp(f1+1, f2)) return (1); if (*f2 == 'r' && !strcmp(f1, f2+1)) return (1); if (*f1 == 'r' && *f2 == 'r' && strcmp(f1+1, f2+1) == 0) return (1); return (0); } cmp r2,$7 bhi 1f cmp r1,$1 blos 2f cmp r3,$5 blo 1f 2: rts pc 1: jsr pc,errora clr r2 clr r3 rts pc checkrp: cmp r4,$') beq 1f mov $'),-(sp) jsr pc,error rts pc 1: jsr pc,readop rts pc setbr: mov brtabp,r1 cmp r1,$brlen blt 1f mov $2,r2 rts pc 1: inc brtabp clr -(sp) sub dot,r0 ble 1f sub brdelt,bin/hostid.c 444 0 12 2515 5511645037 6245 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)hostid.c 1.2 (2.11BSD GTE) 1/1/94"; #endif #include #include #include #include extern char *index(); extern unsigned long inet_addr(); main(argc, argv) int argc; char **argv; { register char *id; u_long addr; long hostid; struct hostent *hp; if (argc < 2) { #ifdef pdp11 { long val; if (val = gethostid()) printf("0x%lx\n",val); else puts("0"); } #else printf("%#lx\n", gethostid()); #endif exit(0); } id = argv[1]; if (hp = gethostbyname(id)) { bcopy(hp->h_addr, &addr, sizeof(addr)); hostid = addr; } else if (index(id, '.')) { if ((hostid = inet_addr(id)) == -1) goto usage; } else { if (id[0] == '0' && (id[1] == 'x' || id[1] == 'X')) id += 2; if (sscanf(id, "%lx", &hostid) != 1) { usage: fprintf(stderr, "usage: %s [hexnum or internet address]\n", argv[0]); exit(1); } } if (sethostid(hostid) < 0) { perror("sethostid"); exit(1); } exit(0); } 1); while (fsp = getfsent()) { if (strcmp(fsp->fs_type, FSTAB_RW) && strcmp(fsp->fs_type, FSTAB_RO) && strcmp(fsp->fs_type, FSTAB_RQ)) continue; if (rootbin/mail.c 644 0 12 32012 5576454414 5722 #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)mail.c 4.33.2 (2.11BSD GTE) 6/11/94"; #endif #include #include #include #include #include #include #include #include #include #include #include /* copylet flags */ #define REMOTE 1 /* remote mail, add rmtmsg */ #define ORDINARY 2 #define ZAP 3 /* zap header and trailing empty line */ #define FORWARD 4 #define LSIZE 256 #define MAXLET 300 /* maximum number of letters */ #define MAILMODE 0600 /* mode of created mail */ char line[LSIZE]; char resp[LSIZE]; struct let { long adr; char change; } let[MAXLET]; int nlet = 0; char lfil[50]; long iop, time(); char *getenv(); char *index(); char lettmp[] = "/tmp/maXXXXX"; char maildir[] = "/usr/spool/mail/"; char mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; char dead[] = "dead.letter"; char forwmsg[] = " forwarded\n"; FILE *tmpf; FILE *malf; char my_name[60]; char *getlogin(); int error; int changed; int forward; char from[] = "From "; long ftell(); int delex(); char *ctime(); int flgf; int flgp; int delflg = 1; int hseqno; jmp_buf sjbuf; int rmail; main(argc, argv) char **argv; { register int i; char *name; struct passwd *pwent; if (!(name = getlogin()) || !*name || !(pwent = getpwnam(name)) || getuid() != pwent->pw_uid) pwent = getpwuid(getuid()); strncpy(my_name, pwent ? pwent->pw_name : "???", sizeof(my_name)-1); if (setjmp(sjbuf)) done(); for (i=SIGHUP; i<=SIGTERM; i++) setsig(i, delex); i = mkstemp(lettmp); tmpf = fdopen(i, "r+w"); if (i < 0 || tmpf == NULL) panic("mail: %s: cannot open for writing", lettmp); /* * This protects against others reading mail from temp file and * if we exit, the file will be deleted already. */ unlink(lettmp); if (argv[0][0] == 'r') rmail++; if (argv[0][0] != 'r' && /* no favors for rmail*/ (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd"))) printmail(argc, argv); else bulkmail(argc, argv); done(); } setsig(i, f) int i; int (*f)(); { if (signal(i, SIG_IGN) != SIG_IGN) signal(i, f); } any(c, str) register int c; register char *str; { while (*str) if (c == *str++) return(1); return(0); } printmail(argc, argv) char **argv; { int flg, i, j, print; char *p, *getarg(); struct stat statb; setuid(getuid()); cat(mailfile, maildir, my_name); #ifdef notdef if (stat(mailfile, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { strcat(mailfile, "/"); strcat(mailfile, my_name); } #endif for (; argc > 1; argv++, argc--) { if (argv[1][0] != '-') break; switch (argv[1][1]) { case 'p': flgp++; /* fall thru... */ case 'q': delflg = 0; break; case 'f': if (argc >= 3) { strcpy(mailfile, argv[2]); argv++, argc--; } break; case 'b': forward = 1; break; default: panic("unknown option %c", argv[1][1]); /*NOTREACHED*/ } } malf = fopen(mailfile, "r"); if (malf == NULL) { printf("No mail.\n"); return; } flock(fileno(malf), LOCK_SH); copymt(malf, tmpf); fclose(malf); /* implicit unlock */ fseek(tmpf, 0L, L_SET); changed = 0; print = 1; for (i = 0; i < nlet; ) { j = forward ? i : nlet - i - 1; if (setjmp(sjbuf)) { print = 0; } else { if (print) copylet(j, stdout, ORDINARY); print = 1; } if (flgp) { i++; continue; } setjmp(sjbuf); fputs("? ", stdout); fflush(stdout); if (fgets(resp, LSIZE, stdin) == NULL) break; switch (resp[0]) { default: printf("usage\n"); case '?': print = 0; printf("q\tquit\n"); printf("x\texit without changing mail\n"); printf("p\tprint\n"); printf("s[file]\tsave (default mbox)\n"); printf("w[file]\tsame without header\n"); printf("-\tprint previous\n"); printf("d\tdelete\n"); printf("+\tnext (no delete)\n"); printf("m user\tmail to user\n"); printf("! cmd\texecute cmd\n"); break; case '+': case 'n': case '\n': i++; break; case 'x': changed = 0; case 'q': goto donep; case 'p': break; case '^': case '-': if (--i < 0) i = 0; break; case 'y': case 'w': case 's': flg = 0; if (resp[1] != '\n' && resp[1] != ' ') { printf("illegal\n"); flg++; print = 0; continue; } if (resp[1] == '\n' || resp[1] == '\0') { p = getenv("HOME"); if (p != 0) cat(resp+1, p, "/mbox"); else cat(resp+1, "", "mbox"); } for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) { malf = fopen(lfil, "a"); if (malf == NULL) { printf("mail: %s: cannot append\n", lfil); flg++; continue; } copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY); fclose(malf); } if (flg) print = 0; else { let[j].change = 'd'; changed++; i++; } break; case 'm': flg = 0; if (resp[1] == '\n' || resp[1] == '\0') { i++; continue; } if (resp[1] != ' ') { printf("invalid command\n"); flg++; print = 0; continue; } for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) if (!sendmail(j, lfil, my_name)) flg++; if (flg) print = 0; else { let[j].change = 'd'; changed++; i++; } break; case '!': system(resp+1); printf("!\n"); print = 0; break; case 'd': let[j].change = 'd'; changed++; i++; if (resp[1] == 'q') goto donep; break; } } donep: if (changed) copyback(); } /* copy temp or whatever back to /usr/spool/mail */ copyback() { register int i, c; long oldmask; int fd, new = 0; struct stat stbuf; oldmask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)|sigmask(SIGQUIT)); fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE); if (fd >= 0) { flock(fd, LOCK_EX); malf = fdopen(fd, "r+w"); } if (fd < 0 || malf == NULL) panic("can't rewrite %s", lfil); fstat(fd, &stbuf); if (stbuf.st_size != let[nlet].adr) { /* new mail has arrived */ fseek(malf, let[nlet].adr, L_SET); fseek(tmpf, let[nlet].adr, L_SET); while ((c = getc(malf)) != EOF) putc(c, tmpf); let[++nlet].adr = stbuf.st_size; new = 1; fseek(malf, 0L, L_SET); } ftruncate(fd, 0L); for (i = 0; i < nlet; i++) if (let[i].change != 'd') copylet(i, malf, ORDINARY); fclose(malf); /* implict unlock */ if (new) printf("New mail has arrived.\n"); sigsetmask(oldmask); } /* copy mail (f1) to temp (f2) */ copymt(f1, f2) FILE *f1, *f2; { long nextadr; nlet = nextadr = 0; let[0].adr = 0; while (fgets(line, LSIZE, f1) != NULL) { if (isfrom(line)) let[nlet++].adr = nextadr; nextadr += strlen(line); fputs(line, f2); } let[nlet].adr = nextadr; /* last plus 1 */ } copylet(n, f, type) FILE *f; { int ch; long k; char hostname[MAXHOSTNAMELEN]; fseek(tmpf, let[n].adr, L_SET); k = let[n+1].adr - let[n].adr; while (k-- > 1 && (ch = getc(tmpf)) != '\n') if (type != ZAP) putc(ch, f); switch (type) { case REMOTE: gethostname(hostname, sizeof (hostname)); fprintf(f, " remote from %s\n", hostname); break; case FORWARD: fprintf(f, forwmsg); break; case ORDINARY: putc(ch, f); break; case ZAP: break; default: panic("Bad letter type %d to copylet.", type); } while (k-- > 1) { ch = getc(tmpf); putc(ch, f); } if (type != ZAP || ch != '\n') putc(getc(tmpf), f); } isfrom(lp) register char *lp; { register char *p; for (p = from; *p; ) if (*lp++ != *p++) return(0); return(1); } bulkmail(argc, argv) char **argv; { char *truename; int first; register char *cp; char *newargv[1000]; register char **ap; register char **vp; int dflag; dflag = 0; delflg = 0; if (argc < 1) { fprintf(stderr, "puke\n"); return; } for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++) if (ap[0][0] == '-' && ap[0][1] == 'd') dflag++; if (!dflag) { /* give it to sendmail, rah rah! */ unlink(lettmp); ap = newargv+1; if (rmail) *ap-- = "-s"; *ap = "-sendmail"; setuid(getuid()); execv(_PATH_SENDMAIL, ap); perror(_PATH_SENDMAIL); exit(EX_UNAVAILABLE); } truename = 0; line[0] = '\0'; /* * When we fall out of this, argv[1] should be first name, * argc should be number of names + 1. */ while (argc > 1 && *argv[1] == '-') { cp = *++argv; argc--; switch (cp[1]) { case 'r': if (argc <= 1) usage(); truename = argv[1]; fgets(line, LSIZE, stdin); if (strcmpn("From", line, 4) == 0) line[0] = '\0'; argv++; argc--; break; case 'h': if (argc <= 1) usage(); hseqno = atoi(argv[1]); argv++; argc--; break; case 'd': break; default: usage(); } } if (argc <= 1) usage(); if (truename == 0) truename = my_name; time(&iop); fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop)); iop = ftell(tmpf); flgf = first = 1; for (;;) { if (first) { first = 0; if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL) break; } else { if (fgets(line, LSIZE, stdin) == NULL) break; } if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin))) break; if (isfrom(line)) putc('>', tmpf); fputs(line, tmpf); flgf = 0; } putc('\n', tmpf); nlet = 1; let[0].adr = 0; let[1].adr = ftell(tmpf); if (flgf) return; while (--argc > 0) if (!sendmail(0, *++argv, truename)) error++; if (error && safefile(dead)) { setuid(getuid()); malf = fopen(dead, "w"); if (malf == NULL) { printf("mail: cannot open %s\n", dead); fclose(tmpf); return; } copylet(0, malf, ZAP); fclose(malf); printf("Mail saved in %s\n", dead); } fclose(tmpf); } sendrmt(n, name) char *name; { FILE *rmf, *popen(); register char *p; char rsys[64], cmd[64]; register pid; int sts; #ifdef notdef if (any('^', name)) { while (p = index(name, '^')) *p = '!'; if (strncmp(name, "researc", 7)) { strcpy(rsys, "research"); if (*name != '!') --name; goto skip; } } #endif for (p=rsys; *name!='!'; *p++ = *name++) if (*name=='\0') return(0); /* local address, no '!' */ *p = '\0'; if (name[1]=='\0') { printf("null name\n"); return(0); } skip: if ((pid = fork()) == -1) { fprintf(stderr, "mail: can't create proc for remote\n"); return(0); } if (pid) { while (wait(&sts) != pid) { if (wait(&sts)==-1) return(0); } return(!sts); } setuid(getuid()); if (any('!', name+1)) (void)sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1); else (void)sprintf(cmd, "uux - %s!rmail %s", rsys, name+1); if ((rmf=popen(cmd, "w")) == NULL) exit(1); copylet(n, rmf, REMOTE); exit(pclose(rmf) != 0); } usage() { fprintf(stderr, "Usage: mail [ -f ] people . . .\n"); error = EX_USAGE; done(); } #include #include #include notifybiff(msg) char *msg; { static struct sockaddr_in addr; static int f = -1; if (addr.sin_family == 0) { struct hostent *hp = gethostbyname("localhost"); struct servent *sp = getservbyname("biff", "udp"); if (hp && sp) { addr.sin_family = hp->h_addrtype; bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); addr.sin_port = sp->s_port; } } if (addr.sin_family) { if (f < 0) f = socket(AF_INET, SOCK_DGRAM, 0); if (f >= 0) sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr)); } } sendmail(n, name, fromaddr) int n; char *name, *fromaddr; { char file[256]; int mask, fd; struct passwd *pw; #ifdef notdef struct stat statb; #endif char buf[128]; if (*name=='!') name++; if (any('!', name)) return (sendrmt(n, name)); if ((pw = getpwnam(name)) == NULL) { printf("mail: can't send to %s\n", name); return(0); } cat(file, maildir, name); #ifdef notdef if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { strcat(file, "/"); strcat(file, name); } #endif if (!safefile(file)) return(0); fd = open(file, O_WRONLY | O_CREAT, MAILMODE); if (fd >= 0) { flock(fd, LOCK_EX); malf = fdopen(fd, "a"); } if (fd < 0 || malf == NULL) { close(fd); printf("mail: %s: cannot append\n", file); return(0); } fchown(fd, pw->pw_uid, pw->pw_gid); (void)sprintf(buf, "%s@%ld\n", name, ftell(malf)); copylet(n, malf, ORDINARY); fclose(malf); notifybiff(buf); return(1); } delex(i) { if (i != SIGINT) { setsig(i, SIG_DFL); sigsetmask(sigblock(0L) &~ sigmask(i)); } putc('\n', stderr); if (delflg) longjmp(sjbuf, 1); if (error == 0) error = i; done(); } done() { unlink(lettmp); exit(error); } cat(to, from1, from2) char *to, *from1, *from2; { register char *cp, *dp; cp = to; for (dp = from1; *cp = *dp++; cp++) ; for (dp = from2; *cp++ = *dp++; ) ; } /* copy p... into s, update p */ char * getarg(s, p) register char *s, *p; { while (*p == ' ' || *p == '\t') p++; if (*p == '\n' || *p == '\0') return(NULL); while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') *s++ = *p++; *s = '\0'; return(p); } safefile(f) char *f; { struct stat statb; if (lstat(f, &statb) < 0) return (1); if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) { fprintf(stderr, "mail: %s has more than one link or is a symbolic link\n", f); return (0); } return (1); } panic(msg, a1, a2, a3) char *msg; { fprintf(stderr, "mail: "); fprintf(stderr, msg, a1, a2, a3); fprintf(stderr, "\n"); done(); } return; } flock(fileno(malf), LOCK_SH); copymt(malf, tmpf); fclose(malf); /* implicit unlock */ fseek(tmpf, 0L, L_SET); changed = 0; print = 1; for (i = 0; i < nlet; ) { j = forward ? i : nlet - i - 1; if (setjmp(sjbuf)) { print = 0; } else { if (print) copylet(j, stdout, ORDINARY); print = 1; } if (flgp) { i++; continue; } setjmp(sjbuf); fputs("? ", stdout); fflush(stdout); if (fgets(resp, LSIZE, stdin) == NULL) break; switch (resp[0]) { bin/du.c 444 0 12 5536 4013202656 5361 #ifndef lint static char *sccsid = "@(#)du.c 4.11 (Berkeley) 7/1/83"; #endif #include #include #include #include char path[BUFSIZ], name[BUFSIZ]; int aflg; int sflg; char *dot = "."; #define ML 1000 struct { int dev; ino_t ino; } ml[ML]; int mlx; long descend(); char *index(), *rindex(), *strcpy(), *sprintf(); #define kb(n) (howmany(dbtob(n), 1024)) main(argc, argv) int argc; char **argv; { long blocks = 0; register char *np; int pid; argc--, argv++; again: if (argc && !strcmp(*argv, "-s")) { sflg++; argc--, argv++; goto again; } if (argc && !strcmp(*argv, "-a")) { aflg++; argc--, argv++; goto again; } if (argc == 0) { argv = ˙ argc = 1; } do { if (argc > 1) { pid = fork(); if (pid == -1) { fprintf(stderr, "No more processes.\n"); exit(1); } if (pid != 0) wait((int *)0); } if (argc == 1 || pid == 0) { (void) strcpy(path, *argv); (void) strcpy(name, *argv); if (np = rindex(name, '/')) { *np++ = '\0'; if (chdir(*name ? name : "/") < 0) { perror(*name ? name : "/"); exit(1); } } else np = path; blocks = descend(path, *np ? np : "."); if (sflg) printf("%ld\t%s\n", kb(blocks), path); if (argc > 1) exit(1); } argc--, argv++; } while (argc > 0); exit(0); } DIR *dirp = NULL; long descend(base, name) char *base, *name; { char *ebase0, *ebase; struct stat stb; int i; long blocks = 0; long curoff = NULL; register struct direct *dp; ebase0 = ebase = index(base, 0); if (ebase > base && ebase[-1] == '/') ebase--; if (lstat(name, &stb) < 0) { perror(base); *ebase0 = 0; return (0); } if (stb.st_nlink > 1 && (stb.st_mode&S_IFMT) != S_IFDIR) { for (i = 0; i <= mlx; i++) if (ml[i].ino == stb.st_ino && ml[i].dev == stb.st_dev) return (0); if (mlx < ML) { ml[mlx].dev = stb.st_dev; ml[mlx].ino = stb.st_ino; mlx++; } } blocks = stb.st_blocks; if ((stb.st_mode&S_IFMT) != S_IFDIR) { if (aflg) printf("%ld\t%s\n", kb(blocks), base); return (blocks); } if (dirp != NULL) closedir(dirp); dirp = opendir(name); if (dirp == NULL) { perror(base); *ebase0 = 0; return (0); } if (chdir(name) < 0) { perror(base); *ebase0 = 0; closedir(dirp); dirp = NULL; return (0); } while (dp = readdir(dirp)) { if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; (void) sprintf(ebase, "/%s", dp->d_name); curoff = telldir(dirp); blocks += descend(base, ebase+1); *ebase = 0; if (dirp == NULL) { dirp = opendir("."); if (dirp == NULL) { perror("."); return (0); } seekdir(dirp, curoff); } } closedir(dirp); dirp = NULL; if (sflg == 0) printf("%ld\t%s\n", kb(blocks), base); if (chdir("..") < 0) { (void) sprintf(index(base, 0), "/.."); perror(base); exit(1); } *ebase0 = 0; return (blocks); } ) { i++; continue; } if (resp[1] != ' ') { printf("invalid command\n"); flg++; print = 0; continue; } for (p = resp+1; (p = gebin/strip.c 444 0 12 2617 5514436141 6114 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)strip.c 5.1.1 (2.11BSD GTE) 1/1/94"; #endif #include #include #include #include struct xexec head; int status; main(argc, argv) char *argv[]; { register i; signal(SIGHUP, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); for (i = 1; i < argc; i++) { strip(argv[i]); if (status > 1) break; } exit(status); } strip(name) char *name; { register f; long size; f = open(name, O_RDWR); if (f < 0) { fprintf(stderr, "strip: "); perror(name); status = 1; goto out; } if (read(f, (char *)&head, sizeof (head)) < 0 || N_BADMAG(head.e)) { printf("strip: %s not in a.out format\n", name); status = 1; goto out; } if ((head.e.a_syms == 0) && ((head.e.a_flag & 1) != 0)) goto out; size = N_DATOFF(head) + head.e.a_data; head.e.a_syms = 0; head.e.a_flag |= 1; if (ftruncate(f, size) < 0) { fprintf("strip: "); perror(name); status = 1; goto out; } (void) lseek(f, (long)0, L_SET); (void) write(f, (char *)&head.e, sizeof (head.e)); out: close(f); } *ebase0, *ebase; struct stat stb; int i; long blocks = 0; long curoff = NULL; register struct direct *dp; bin/stty.c 444 0 12 27376 5672226032 6010 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)stty.c 5.4.1 (2.11BSD GTE) 12/9/94"; #endif /* * set teletype modes */ #include #include struct { char *string; int speed; } speeds[] = { "0", B0, "50", B50, "75", B75, "110", B110, "134", B134, "134.5",B134, "150", B150, "200", B200, "300", B300, "600", B600, "1200", B1200, "1800", B1800, "2400", B2400, "4800", B4800, "9600", B9600, "exta", EXTA, "19200", EXTA, "extb", EXTB, "38400", EXTB, 0, }; struct { char *string; int set; int reset; int lset; int lreset; } modes[] = { "even", EVENP, 0, 0, 0, "-even", 0, EVENP, 0, 0, "odd", ODDP, 0, 0, 0, "-odd", 0, ODDP, 0, 0, "raw", RAW, 0, 0, 0, "-raw", 0, RAW, 0, 0, "cooked", 0, RAW, 0, 0, "-nl", CRMOD, 0, 0, 0, "nl", 0, CRMOD, 0, 0, "echo", ECHO, 0, 0, 0, "-echo", 0, ECHO, 0, 0, "-tabs", XTABS, 0, 0, 0, "tabs", 0, XTABS, 0, 0, "tandem", TANDEM, 0, 0, 0, "-tandem", 0, TANDEM, 0, 0, "cbreak", CBREAK, 0, 0, 0, "-cbreak", 0, CBREAK, 0, 0, "cr0", CR0, CR3, 0, 0, "cr1", CR1, CR3, 0, 0, "cr2", CR2, CR3, 0, 0, "cr3", CR3, CR3, 0, 0, "tab0", TAB0, XTABS, 0, 0, "tab1", TAB1, XTABS, 0, 0, "tab2", TAB2, XTABS, 0, 0, "nl0", NL0, NL3, 0, 0, "nl1", NL1, NL3, 0, 0, "nl2", NL2, NL3, 0, 0, "nl3", NL3, NL3, 0, 0, "ff0", FF0, FF1, 0, 0, "ff1", FF1, FF1, 0, 0, "bs0", BS0, BS1, 0, 0, "bs1", BS1, BS1, 0, 0, "33", CR1, ALLDELAY, 0, 0, "tty33", CR1, ALLDELAY, 0, 0, "37", FF1+CR2+TAB1+NL1, ALLDELAY, 0, 0, "tty37", FF1+CR2+TAB1+NL1, ALLDELAY, 0, 0, "05", NL2, ALLDELAY, 0, 0, "vt05", NL2, ALLDELAY, 0, 0, "tn", CR1, ALLDELAY, 0, 0, "tn300", CR1, ALLDELAY, 0, 0, "ti", CR2, ALLDELAY, 0, 0, "ti700", CR2, ALLDELAY, 0, 0, "tek", FF1, ALLDELAY, 0, 0, "crtbs", 0, 0, LCRTBS, LPRTERA, "-crtbs", 0, 0, 0, LCRTBS, "prterase", 0, 0, LPRTERA, LCRTBS+LCRTKIL+LCRTERA, "-prterase", 0, 0, 0, LPRTERA, "crterase", 0, 0, LCRTERA, LPRTERA, "-crterase", 0, 0, 0, LCRTERA, "crtkill", 0, 0, LCRTKIL, LPRTERA, "-crtkill", 0, 0, 0, LCRTKIL, "mdmbuf", 0, 0, LMDMBUF, 0, "-mdmbuf", 0, 0, 0, LMDMBUF, "litout", 0, 0, LLITOUT, 0, "-litout", 0, 0, 0, LLITOUT, "pass8", 0, 0, LPASS8, 0, "-pass8", 0, 0, 0, LPASS8, "tostop", 0, 0, LTOSTOP, 0, "-tostop", 0, 0, 0, LTOSTOP, "flusho", 0, 0, LFLUSHO, 0, "-flusho", 0, 0, 0, LFLUSHO, "nohang", 0, 0, LNOHANG, 0, "-nohang", 0, 0, 0, LNOHANG, #ifdef notdef "etxack", 0, 0, LETXACK, 0, "-etxack", 0, 0, 0, LETXACK, #endif "ctlecho", 0, 0, LCTLECH, 0, "-ctlecho", 0, 0, 0, LCTLECH, "pendin", 0, 0, LPENDIN, 0, "-pendin", 0, 0, 0, LPENDIN, "decctlq", 0, 0, LDECCTQ, 0, "-decctlq", 0, 0, 0, LDECCTQ, "noflsh", 0, 0, LNOFLSH, 0, "-noflsh", 0, 0, 0, LNOFLSH, 0, }; struct tchars tc; struct ltchars ltc; struct sgttyb mode; struct winsize win; int lmode; int oldisc, ldisc; struct special { char *name; char *cp; char def; } special[] = { "erase", &mode.sg_erase, CERASE, "kill", &mode.sg_kill, CKILL, "intr", &tc.t_intrc, CINTR, "quit", &tc.t_quitc, CQUIT, "start", &tc.t_startc, CSTART, "stop", &tc.t_stopc, CSTOP, "eof", &tc.t_eofc, CEOF, "brk", &tc.t_brkc, CBRK, "susp", <c.t_suspc, CSUSP, "dsusp", <c.t_dsuspc, CDSUSP, "rprnt", <c.t_rprntc, CRPRNT, "flush", <c.t_flushc, CFLUSH, "werase", <c.t_werasc, CWERASE, "lnext", <c.t_lnextc, CLNEXT, 0 }; char *arg; int argc; char **argv; main(iargc, iargv) char **iargv; { int i; register struct special *sp; char obuf[BUFSIZ]; setbuf(stderr, obuf); argc = iargc; argv = iargv; ioctl(1, TIOCGETP, &mode); ioctl(1, TIOCGETD, &ldisc); oldisc = ldisc; ioctl(1, TIOCGETC, &tc); ioctl(1, TIOCLGET, &lmode); ioctl(1, TIOCGLTC, <c); ioctl(1, TIOCGWINSZ, &win); if(argc == 1) { prmodes(0); exit(0); } if (argc == 2 && !strcmp(argv[1], "all")) { prmodes(1); exit(0); } if (argc == 2 && !strcmp(argv[1], "everything")) { prmodes(2); exit(0); } /* if (argc == 2 && !strcmp(argv[1], "all")) { prmodes(2); exit(0); } */ while(--argc > 0) { arg = *++argv; if (eq("ek")){ mode.sg_erase = '#'; mode.sg_kill = '@'; continue; } if (eq("new")){ ldisc = NTTYDISC; if (ioctl(1, TIOCSETD, &ldisc)<0) perror("ioctl"); continue; } if (eq("newcrt")){ ldisc = NTTYDISC; lmode &= ~LPRTERA; lmode |= LCRTBS|LCTLECH; if (mode.sg_ospeed >= B1200) lmode |= LCRTERA|LCRTKIL; if (ioctl(1, TIOCSETD, &ldisc)<0) perror("ioctl"); continue; } if (eq("crt")){ lmode &= ~LPRTERA; lmode |= LCRTBS|LCTLECH; if (mode.sg_ospeed >= B1200) lmode |= LCRTERA|LCRTKIL; continue; } if (eq("old")){ ldisc = 0; if (ioctl(1, TIOCSETD, &ldisc)<0) perror("ioctl"); continue; } if (eq("dec")){ mode.sg_erase = 0177; mode.sg_kill = CTRL(u); tc.t_intrc = CTRL(c); ldisc = NTTYDISC; lmode &= ~LPRTERA; lmode |= LCRTBS|LCTLECH|LDECCTQ; if (mode.sg_ospeed >= B1200) lmode |= LCRTERA|LCRTKIL; if (ioctl(1, TIOCSETD, &ldisc)<0) perror("ioctl"); continue; } for (sp = special; sp->name; sp++) if (eq(sp->name)) { if (--argc == 0) goto done; if (**++argv == 'u') *sp->cp = 0377; else if (**argv == '^') *sp->cp = ((*argv)[1] == '?') ? 0177 : (*argv)[1] & 037; else *sp->cp = **argv; goto cont; } if (eq("gspeed")) { mode.sg_ispeed = B300; mode.sg_ospeed = B9600; continue; } if (eq("hup")) { ioctl(1, TIOCHPCL, NULL); continue; } if (eq("rows")) { if (--argc == 0) goto done; win.ws_row = atoi(*++argv); } if (eq("cols") || eq("columns")) { if (--argc == 0) goto done; win.ws_col = atoi(*++argv); } if (eq("size")) { ioctl(open("/dev/tty", 0), TIOCGWINSZ, &win); printf("%d %d\n", win.ws_row, win.ws_col); exit(0); } for(i=0; speeds[i].string; i++) if(eq(speeds[i].string)) { mode.sg_ispeed = mode.sg_ospeed = speeds[i].speed; goto cont; } if (eq("speed")) { ioctl(open("/dev/tty", 0), TIOCGETP, &mode); for(i=0; speeds[i].string; i++) if (mode.sg_ospeed == speeds[i].speed) { printf("%s\n", speeds[i].string); exit(0); } printf("unknown\n"); exit(1); } for(i=0; modes[i].string; i++) if(eq(modes[i].string)) { mode.sg_flags &= ~modes[i].reset; mode.sg_flags |= modes[i].set; lmode &= ~modes[i].lreset; lmode |= modes[i].lset; } if(arg) fprintf(stderr,"unknown mode: %s\n", arg); cont: ; } done: ioctl(1, TIOCSETN, &mode); ioctl(1, TIOCSETC, &tc); ioctl(1, TIOCSLTC, <c); ioctl(1, TIOCLSET, &lmode); ioctl(1, TIOCSWINSZ, &win); } eq(string) char *string; { int i; if(!arg) return(0); i = 0; loop: if(arg[i] != string[i]) return(0); if(arg[i++] != '\0') goto loop; arg = 0; return(1); } prmodes(all) { register m; int any; if(ldisc==NETLDISC) fprintf(stderr, "net discipline, "); else if(ldisc==NTTYDISC) fprintf(stderr, "new tty, "); else if(all==2) fprintf(stderr, "old tty, "); if(mode.sg_ispeed != mode.sg_ospeed) { prspeed("input speed ", mode.sg_ispeed); prspeed("output speed ", mode.sg_ospeed); } else prspeed("speed ", mode.sg_ispeed); if (all) fprintf(stderr, ", %d rows, %d columns", win.ws_row, win.ws_col); fprintf(stderr, all==2 ? "\n" : "; "); m = mode.sg_flags; if(all==2 || (m&(EVENP|ODDP))!=(EVENP|ODDP)) { if(m & EVENP) fprintf(stderr,"even "); if(m & ODDP) fprintf(stderr,"odd "); } if(all==2 || m&RAW) fprintf(stderr,"-raw "+((m&RAW)!=0)); if(all==2 || (m&CRMOD)==0) fprintf(stderr,"-nl "+((m&CRMOD)==0)); if(all==2 || (m&ECHO)==0) fprintf(stderr,"-echo "+((m&ECHO)!=0)); if(all==2 || (m&TANDEM)) fprintf(stderr,"-tandem "+((m&TANDEM)!=0)); fprintf(stderr,"-tabs "+((m&XTABS)!=XTABS)); if(all==2 || (m&CBREAK)) fprintf(stderr,"-cbreak "+((m&CBREAK)!=0)); if(all==2 || (m&NLDELAY)) delay((m&NLDELAY)/NL1, "nl"); if ((m&TBDELAY)!=XTABS) delay((m&TBDELAY)/TAB1, "tab"); if(all==2 || (m&CRDELAY)) delay((m&CRDELAY)/CR1, "cr"); if(all==2 || (m&VTDELAY)) delay((m&VTDELAY)/FF1, "ff"); if(all==2 || (m&BSDELAY)) delay((m&BSDELAY)/BS1, "bs"); if (all) fprintf(stderr,"\n"); #define lpit(what,str) \ if (all==2||(lmode&what)) { \ fprintf(stderr,str+((lmode&what)!=0)); any++; \ } if (ldisc == NTTYDISC) { int newcrt = (lmode&(LCTLECH|LCRTBS)) == (LCTLECH|LCRTBS) && (lmode&(LCRTERA|LCRTKIL)) == ((mode.sg_ospeed > B300) ? LCRTERA|LCRTKIL : 0); int nothing = 1; if (newcrt) { if (all==2) fprintf(stderr, "crt: (crtbs crterase crtkill ctlecho) "); else fprintf(stderr, "crt "); any++; } else { lpit(LCRTBS, "-crtbs "); lpit(LCRTERA, "-crterase "); lpit(LCRTKIL, "-crtkill "); lpit(LCTLECH, "-ctlecho "); lpit(LPRTERA, "-prterase "); } lpit(LTOSTOP, "-tostop "); if (all==2) { fprintf(stderr, "\n"); any = 0; nothing = 0; } lpit(LFLUSHO, "-flusho "); lpit(LMDMBUF, "-mdmbuf "); lpit(LLITOUT, "-litout "); lpit(LPASS8, "-pass8 "); lpit(LNOHANG, "-nohang "); if (any) { fprintf(stderr,"\n"); any = 0; nothing = 0; } #ifdef notdef lpit(LETXACK, "-etxack "); #endif lpit(LPENDIN, "-pendin "); lpit(LDECCTQ, "-decctlq "); lpit(LNOFLSH, "-noflsh "); if (any || nothing) fprintf(stderr,"\n"); } else if (!all) fprintf(stderr,"\n"); if (all) { switch (ldisc) { case 0: fprintf(stderr,"\ erase kill intr quit stop eof\ \n"); pcol(mode.sg_erase, -1); pcol(mode.sg_kill, -1); pcol(tc.t_intrc, -1); pcol(tc.t_quitc, -1); pcol(tc.t_stopc, tc.t_startc); pcol(tc.t_eofc, tc.t_brkc); fprintf(stderr,"\n"); break; case NTTYDISC: fprintf(stderr,"\ erase kill werase rprnt flush lnext susp intr quit stop eof\ \n"); pcol(mode.sg_erase, -1); pcol(mode.sg_kill, -1); pcol(ltc.t_werasc, -1); pcol(ltc.t_rprntc, -1); pcol(ltc.t_flushc, -1); pcol(ltc.t_lnextc, -1); pcol(ltc.t_suspc, ltc.t_dsuspc); pcol(tc.t_intrc, -1); pcol(tc.t_quitc, -1); pcol(tc.t_stopc, tc.t_startc); pcol(tc.t_eofc, tc.t_brkc); fprintf(stderr,"\n"); break; } } else if (ldisc != NETLDISC) { register struct special *sp; int first = 1; for (sp = special; sp->name; sp++) { if ((*sp->cp&0377) != (sp->def&0377)) { pit(*sp->cp, sp->name, first ? "" : ", "); first = 0; }; if (sp->cp == &tc.t_brkc && ldisc == 0) break; } if (!first) fprintf(stderr, "\n"); } } pcol(ch1, ch2) int ch1, ch2; { int nout = 0; ch1 &= 0377; ch2 &= 0377; if (ch1 == ch2) ch2 = 0377; for (; ch1 != 0377 || ch2 != 0377; ch1 = ch2, ch2 = 0377) { if (ch1 == 0377) continue; if (ch1 & 0200) { fprintf(stderr, "M-"); nout += 2; ch1 &= ~ 0200; } if (ch1 == 0177) { fprintf(stderr, "^"); nout++; ch1 = '?'; } else if (ch1 < ' ') { fprintf(stderr, "^"); nout++; ch1 += '@'; } fprintf(stderr, "%c", ch1); nout++; if (ch2 != 0377) { fprintf(stderr, "/"); nout++; } } while (nout < 7) { fprintf(stderr, " "); nout++; } } pit(what, itsname, sep) unsigned what; char *itsname, *sep; { what &= 0377; fprintf(stderr, "%s%s", sep, itsname); if (what == 0377) { fprintf(stderr, " "); return; } fprintf(stderr, " = "); if (what & 0200) { fprintf(stderr, "M-"); what &= ~ 0200; } if (what == 0177) { fprintf(stderr, "^"); what = '?'; } else if (what < ' ') { fprintf(stderr, "^"); what += '@'; } fprintf(stderr, "%c", what); } delay(m, s) char *s; { if(m) fprintf(stderr,"%s%d ", s, m); } unsigned speed[] = { 0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400 }; prspeed(c, s) char *c; { fprintf(stderr,"%s%u baud", c, speed[s]); } return (sendrmt(n, name)); if ((pw = getpwnam(name)) == NULL) { printf("mail: can't send to %s\n", name); return(0); } cat(file, maildir, name); #ifdef notdef if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) { strcat(file, "/");bin/cat.c 444 0 12 7554 4013202657 5523 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)cat.c 5.2 (Berkeley) 12/6/85"; #endif not lint /* * Concatenate files. */ #include #include #include /* #define OPTSIZE BUFSIZ /* define this only if not 4.2 BSD or beyond */ int bflg, eflg, nflg, sflg, tflg, uflg, vflg; int spaced, col, lno, inline, ibsize, obsize; main(argc, argv) char **argv; { int fflg = 0; register FILE *fi; register c; int dev, ino = -1; struct stat statb; int retval = 0; lno = 1; for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) { switch(argv[1][1]) { case 0: break; case 'u': setbuf(stdout, (char *)NULL); uflg++; continue; case 'n': nflg++; continue; case 'b': bflg++; nflg++; continue; case 'v': vflg++; continue; case 's': sflg++; continue; case 'e': eflg++; vflg++; continue; case 't': tflg++; vflg++; continue; } break; } if (fstat(fileno(stdout), &statb) == 0) { statb.st_mode &= S_IFMT; if (statb.st_mode!=S_IFCHR && statb.st_mode!=S_IFBLK) { dev = statb.st_dev; ino = statb.st_ino; } #ifndef OPTSIZE obsize = statb.st_blksize; #endif } else obsize = 0; if (argc < 2) { argc = 2; fflg++; } while (--argc > 0) { if (fflg || (*++argv)[0]=='-' && (*argv)[1]=='\0') fi = stdin; else { if ((fi = fopen(*argv, "r")) == NULL) { perror(*argv); retval = 1; continue; } } if (fstat(fileno(fi), &statb) == 0) { if ((statb.st_mode & S_IFMT) == S_IFREG && statb.st_dev==dev && statb.st_ino==ino) { fprintf(stderr, "cat: input %s is output\n", fflg?"-": *argv); fclose(fi); retval = 1; continue; } #ifndef OPTSIZE ibsize = statb.st_blksize; #endif } else ibsize = 0; if (nflg||sflg||vflg) copyopt(fi); else if (uflg) { while ((c = getc(fi)) != EOF) putchar(c); } else retval |= fastcat(fileno(fi)); /* no flags specified */ if (fi!=stdin) fclose(fi); else clearerr(fi); /* reset sticky eof */ if (ferror(stdout)) { fprintf(stderr, "cat: output write error\n"); retval = 1; break; } } exit(retval); } copyopt(f) register FILE *f; { register int c; top: c = getc(f); if (c == EOF) return; if (c == '\n') { if (inline == 0) { if (sflg && spaced) goto top; spaced = 1; } if (nflg && bflg==0 && inline == 0) printf("%6d\t", lno++); if (eflg) putchar('$'); putchar('\n'); inline = 0; goto top; } if (nflg && inline == 0) printf("%6d\t", lno++); inline = 1; if (vflg) { if (tflg==0 && c == '\t') putchar(c); else { if (c > 0177) { printf("M-"); c &= 0177; } if (c < ' ') printf("^%c", c+'@'); else if (c == 0177) printf("^?"); else putchar(c); } } else putchar(c); spaced = 0; goto top; } fastcat(fd) register int fd; { register int buffsize, n, nwritten, offset; register char *buff; struct stat statbuff; char *malloc(); #ifndef OPTSIZE if (obsize) buffsize = obsize; /* common case, use output blksize */ else if (ibsize) buffsize = ibsize; else buffsize = BUFSIZ; #else buffsize = OPTSIZE; #endif if ((buff = malloc(buffsize)) == NULL) { perror("cat: no memory"); return (1); } /* * Note that on some systems (V7), very large writes to a pipe * return less than the requested size of the write. * In this case, multiple writes are required. */ while ((n = read(fd, buff, buffsize)) > 0) { offset = 0; do { nwritten = write(fileno(stdout), &buff[offset], n); if (nwritten <= 0) { perror("cat: write error"); exit(2); } offset += nwritten; } while ((n -= nwritten) > 0); } free(buff); if (n < 0) { perror("cat: read error"); return (1); } return (0); } exit(1); } for(i=0; modes[i].string; i++) if(eq(modes[i].string)) { mode.sg_flags &= ~modes[i].reset; mode.sg_flags |= modes[i].sebin/ld/ 755 0 12 0 6024535766 5127 bin/ld/ld.c 644 0 12 133035 5753566072 6026 #if defined(DOSCCS) && !defined(lint) static char *sccsid = "@(#)ld.c 4.4 1995/05/08"; #endif /* * 4.4 1995/05/08 - sms * Add -q to turn off undefined symbol reporting. Used when building * networking kernels and many undefineds are expected but look worrisome. * Add -v to enable the VM statistics printout (now optional). * * 4.3 1/14/94 - sms * Make the number of VM segments a compile time option in the Makefile. * 4.2 1/2/94 - sms * Fixed a couple serious bugs, one dealing with overlaid programs - the * overlay header wasn't being written out, the second was a typographical * error causing the relocation information to be wrong. * * 4.1 11/27/93 -sms * Success at reading new style object files and libraries but the * speed was abysmal. Logic added to attempt to hold string tables * in memory when possible (less than 8kb) and to use a larger buffer * when reading strings. Also, added a fifth i/o stream area for use * by the library scanning routine 'ldrand' - this prevents the 'thrashing' * between 'load1' and 'ldrand' (each of these was undoing the other's * seek for a string). * * 4.0 11/1/93 - sms * Previous versions not released. With 'ar' and 'ranlib' ported it * is now 'ld's turn to be modified to support the new object file * format. Major changes (and unfortunately another slip in speed). * * 3.0 9/15/93 - sms * Implement a VM tmp file for the symbol table. * * 2.x 9/3/93 - sms@wlv.iipo.gtegsc.com * Couple of major changes made in preparation for supporting long * symbol names. 'ld' was approximately 1kb away from not running * at all (due to data+bss exceeding 56kb). The first change * made 'syshash' a bitmap saving 3.75kb. The next change involved * modifying 'ldrand' so that the entire table of contents from a * library did not have to fit in memory at once - this saved about * 8kb. The last major change was a rewrite of the input subsystem * making it faster and simpler. */ #include #include #include #include #include #include #include #include #include #include #include "archive.h" /* * Layout of standard part of a.out file header: * u_int a_magic; magic number * u_int a_text; text size ) * u_int a_data; data size ) in bytes but even * u_int a_bss; bss size ) * u_int a_syms; symbol table size * u_int a_entry; entry point * u_int a_unused; (unused) * u_int a_flag bit 0 set if no relocation * * Layout of overlaid part of a.out file header: * int max_ovl; maximum overlay size * u_int ov_siz[NOVL]; overlay sizes * * Non-overlaid offsets: * header: 0 * text: 16 * data: 16 + a_text * relocation: 16 + a_text + a_data * * If relocation info stripped: * symbol table: 16 + a_text + a_data * string table: 16 + a_text + a_data + a_syms * else * symbol table: 16 + 2 * (a_text + a_data) * string table: 16 + 2 * (a_text + a_data) + a_syms * * Overlaid offsets: * header: 0 * overlay header: 16 * text: 16 + 2 + 2*NOVL = 16 + 2 + 2*15 = 48 * data: 48 + a_text + SUM(ov_siz) * relocation: 48 + a_text + SUM(ov_siz) + a_data * * If relocation info stripped: * symbol table: 48 + a_text + SUM(ov_siz) + a_data * string table: symbol_table + a_syms * else * symbol table: 48 + 2 * (a_text + SUM(ov_siz) + a_data) * string table: symbol_table + a_syms * * where SUM(ov_siz) is the sum of the overlays. */ /* * Do not set the following too high (normally set in the Makefile) or * 'ld' will not be able to allocate room (currently 8kb) for string * tables and performance will suffer badly. It is possible that this * could be raised a bit higher but 18 gives 'adequate' performance on * all but the largest ('tcsh' for example) programs, and even there it's * not _too_ bad. */ #ifndef NUM_VM_PAGES #define NUM_VM_PAGES 18 #endif #define NNAMESIZE 32 /* Maximum symbol string length */ #define SYMSPERSEG (BYTESPERSEG / sizeof (SYMBOL)) #define NSYM 2000 /* 1103 originally */ #define NROUT 350 /* 256 originally */ #define NSYMPR 800 /* 1000 originally */ #define N_COMM 05 /* internal use only; other values in a.out.h */ #define RABS 00 #define RTEXT 02 #define RDATA 04 #define RBSS 06 #define REXT 010 #define RELFLG 01 #define THUNKSIZ 8 /* * one entry for each archive member referenced; * set in first pass; needs restoring for overlays */ typedef struct { long loc; } LIBLIST; LIBLIST liblist[NROUT]; LIBLIST *libp = liblist; typedef struct { union { int *iptr; char *cptr; } ptr; int bno; int nibuf; int nsize; int nread; int bsize; /* MUST be a power of 2 */ int *buff; } STREAM; #define Iptr ptr.iptr #define Cptr ptr.cptr #define TEXT 0 #define RELOC 1 #define SYMBOLS 2 #define STRINGS 3 #define STRINGS2 4 #define NUM_IO_PLACES 5 STREAM Input[NUM_IO_PLACES]; /* * Header from the a.out and the archive it is from (if any). */ struct xexec filhdr; CHDR chdr; /* symbol management */ typedef struct { char n_name[NNAMESIZE]; char n_type; char n_ovly; u_int n_value; u_int sovalue; } SYMBOL; #define SYMTAB ((VADDR)0) /* virtual base address of symbol table */ u_short symhash[(NSYM+15)/16]; /* bitmap of hash table entries */ short lastsym; /* index # of last symbol entered */ short hshtab[NSYM+2]; /* hash table for symbols */ short p_etext = -1, p_edata = -1, p_end = -1, entrypt = -1; struct xsymbol { char n_name[NNAMESIZE]; char n_type; char n_ovly; u_int n_value; }; struct xsymbol cursym; /* current symbol */ int nsym; /* pass2: number of local symbols */ struct local { short locindex; /* index to symbol in file */ short locsymbol; /* ptr to symbol table */ }; struct local local[NSYMPR]; short symindex; /* next available symbol table entry */ /* * Options. */ int quiet; /* -q, suppress undefined error message */ int trace; int verbose; /* -v, emit VM statistics */ int xflag; /* discard local symbols */ int Xflag; /* discard locals starting with 'L' */ int Sflag; /* discard all except locals and globals*/ int rflag; /* preserve relocation bits, don't define common */ int arflag; /* original copy of rflag */ int sflag; /* discard all symbols */ int Mflag; /* print rudimentary load map */ int nflag; /* pure procedure */ int Oflag; /* set magic # to 0405 (overlay) */ int dflag; /* define common even with rflag */ int iflag; /* I/D space separated */ /* * These are the cumulative sizes, set in pass1, which * appear in the a.out header when the loader is finished. */ u_int tsize, dsize, bsize; long ssize, rnd8k(); /* * Symbol relocation: */ u_int ctrel, cdrel, cbrel; /* * The base addresses for the loaded text, data and bass from the * current module during pass2 are given by torigin, dorigin and borigin. */ u_int torigin, dorigin, borigin; /* * Errlev is nonzero when errors have occured. * Delarg is an implicit argument to the routine delexit * which is called on error. We do ``delarg = errlev'' before normal * exits, and only if delarg is 0 (i.e. errlev was 0) do we make the * result file executable. */ int errlev, delarg = 4; int ofilfnd; /* -o given; otherwise move l.out to a.out */ char *ofilename = "l.out"; int infil; /* current input file descriptor */ char *filname; /* and its name */ char tfname[] = "/tmp/ldaXXXXX"; FILE *toutb, *doutb, *troutb, *droutb, *soutb, *voutb; u_int torgwas; /* Saves torigin while doing overlays */ u_int tsizwas; /* Saves tsize while doing overlays */ int numov; /* Total number of overlays */ int curov; /* Overlay being worked on just now */ int inov; /* 1 if working on an overlay */ /* Kernel overlays have a special subroutine to do the switch */ struct xsymbol ovhndlr = { "ovhndlr1", N_EXT+N_UNDF, 0, 0 }; #define HNDLR_NUM 7 /* position of ov number in ovhndlr.n_name[] */ u_int ovbase; /* The base address of the overlays */ #define NDIRS 25 #define NDEFDIRS 3 /* number of default directories in dirs[] */ char *dirs[NDIRS]; /* directories for library search */ int ndir; /* number of directories */ struct vspace Vspace; /* The virtual address space for symbols */ short *lookup(), *slookup(), *lookloc(); char *rstrtab; /* ranlib string table pointer */ u_int add(); int delexit(); VADDR sym2va(); off_t skip(); extern long lseek(), atol(), strtol(); extern char *mktemp(); main(argc, argv) char **argv; { register int c, i; int num; register char *ap, **p; char save; /* * Initialize the hash table, indicating that all entries are unused. * -1 is used as a "no symbol" flag. */ memset(hshtab, -1, sizeof(hshtab)); /* * Initialize the first three input buffers. The remaining two are * left for later because it may be possible to hold the string table * in memory and the input buffer won't be needed. */ Input[TEXT].buff = (int *)malloc(512); Input[TEXT].bsize = 512; Input[RELOC].buff = (int *)malloc(512); Input[RELOC].bsize = 512; Input[SYMBOLS].buff = (int *)malloc(512); Input[SYMBOLS].bsize = 512; if (signal(SIGINT, SIG_IGN) != SIG_IGN) { signal(SIGINT, delexit); signal(SIGTERM, delexit); } if (argc == 1) exit(4); /* * Initialize the "VM" system with NUM_VM_PAGES memory segments (memory * resident pages). Then "open the address space" - this creates the paging * (tmp) file. */ if (vminit(NUM_VM_PAGES) < 0) error(1, "vminit failed"); if (vmopen(&Vspace, (char *)NULL) < 0) error(1, "vmopen failed"); /* * Pull out search directories. */ for (c = 1; c < argc; c++) { ap = argv[c]; if (ap[0] == '-' && ap[1] == 'L') { if (ap[2] == 0) error(1, "-L: pathname missing"); if (ndir >= NDIRS - NDEFDIRS) error(1, "-L: too many directories"); dirs[ndir++] = &ap[2]; } } /* add default search directories */ dirs[ndir++] = "/lib"; dirs[ndir++] = "/usr/lib"; dirs[ndir++] = "/usr/local/lib"; p = argv+1; /* * Scan files once to find where symbols are defined. */ for (c=1; c= argc) error(1, "-o where?"); ofilename = *p++; ofilfnd++; continue; case 'u': case 'e': if (++c >= argc) error(1, "-u or -c: arg missing"); enter(slookup(*p++)); if (ap[i]=='e') entrypt = lastsym; continue; case 'D': if (++c >= argc) error(1, "-D: arg missing"); num = atoi(*p++); if (dsize>num) error(1, "-D: too small"); dsize = num; continue; case 'l': save = ap[--i]; ap[i]='-'; load1arg(&ap[i], -1); ap[i]=save; goto next; case 'M': Mflag++; continue; case 'x': xflag++; continue; case 'X': Xflag++; continue; case 'S': Sflag++; continue; case 'r': rflag++; arflag++; continue; case 's': sflag++; xflag++; continue; case 'n': nflag++; continue; case 'd': dflag++; continue; case 'i': case 'z': iflag++; continue; case 't': trace++; continue; case 'q': quiet++; continue; case 'v': verbose++; continue; case 'L': goto next; case 'O': Oflag++; continue; case 'Y': if (inov == 0) error(1, "-Y: Not in overlay"); filhdr.o.ov_siz[curov - 1] = tsize; if (trace) printf("overlay %d size %d\n", curov, filhdr.o.ov_siz[curov - 1]); curov = inov = 0; tsize = tsizwas; continue; case 'Z': if (!inov) { tsizwas = tsize; if (numov == 0) { cursym = ovhndlr; enter(lookup()); } } else { filhdr.o.ov_siz[curov - 1] = tsize; if (trace) printf("overlay %d size %d\n", curov, filhdr.o.ov_siz[curov - 1]); } tsize = 0; inov = 1; numov++; if (numov > NOVL) { printf("ld:too many overlays, max is %d\n",NOVL); error(1, (char *)NULL); } curov++; continue; case 'y': case 'A': case 'H': case 'N': case 'T': default: printf("ld:bad flag %c\n",ap[i]); error(1, (char *)NULL); } next: ; } endload(argc, argv); exit(0); } delexit() { unlink("l.out"); if (delarg==0) chmod(ofilename, 0777 & ~umask(0)); if (verbose) printf("ld: nswaps: %ld, nmapsegs: %ld sbrk(0): %u\n", nswaps, nmapsegs, sbrk(0)); exit(delarg); } endload(argc, argv) int argc; char **argv; { register int c, i; int dnum; register char *ap, **p; if (numov) rflag = 0; filname = 0; middle(); setupout(); p = argv+1; libp = liblist; for (c=1; cloc = -1; libp++; if (rstrtab) free(rstrtab); if (Input[STRINGS2].buff) { free(Input[STRINGS2].buff); Input[STRINGS2].buff = NULL; } break; /* * Table of contents is out of date, so search * as a normal library (but skip the __.SYMDEF file). */ case 3: error(-1, "warning: table of contents for archive is out of date; rerun ranlib(1)"); nloc = SARMAG; do nloc += skip(); while (step(nloc)); break; case -1: return; } close(infil); } /* * Advance to the next archive member, which * is at offset nloc in the archive. If the member * is useful, record its location in the liblist structure * for use in pass2. Mark the end of the archive in libilst with a -1. */ step(nloc) off_t nloc; { lseek(infil, nloc, L_SET); if (get_arobj(infil) <= 0) { libp->loc = -1; libp++; return (0); } if (load1(1, nloc + sizeof (struct ar_hdr) + chdr.lname)) { libp->loc = nloc; libp++; if (Mflag) printf("\t%s\n", chdr.name); } return (1); } ldrand(totnum, sloc) int totnum; off_t sloc; { register int ntab; SYMBOL *sp; short *hp; VADDR vsym; LIBLIST *oldp = libp; int amt, tnum = totnum; off_t loc; /* * 'ar' header + member header + SYMDEF table.of.contents + long filename */ off_t opos = (off_t)SARMAG + sizeof (struct ar_hdr) + sizeof (long) + chdr.lname; #define TABSZ 64 char localname[NNAMESIZE]; register struct ranlib *tp; struct ranlib tab[TABSZ], *tplast; while (tnum) { if (tnum > TABSZ) ntab = TABSZ; else ntab = tnum; tplast = &tab[ntab - 1]; (void)lseek(infil, opos, L_SET); amt = ntab * sizeof (struct ranlib); if (read(infil, tab, amt) != amt) error(1, "EOF in ldrand"); tnum -= ntab; opos += amt; for (tp = tab; tp <= tplast; tp++) { /* * This is slower and uglier than we would like, but it is not always * possible to hold the entire string table in memory. Need to add * an extra increment to skip over the string table size longword. */ if (rstrtab) strncpy(localname, (int)tp->ran_un.ran_strx + rstrtab, NNAMESIZE); else { dseek(STRINGS2, tp->ran_un.ran_strx + sloc + sizeof (long), 07777); mgets(localname, NNAMESIZE, STRINGS2); } hp = slookup(localname); if (*hp == -1) continue; vsym = sym2va(*hp); sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + VOFF(vsym)); if (sp->n_type != N_EXT+N_UNDF) continue; step(tp->ran_off); loc = tp->ran_off; while (tp < tplast && (tp+1)->ran_off == loc) tp++; } } return(oldp != libp); } mgets(buf, maxlen, which) register char *buf; int maxlen, which; { register STREAM *sp; register int n; sp = &Input[which]; for (n = 0; n < maxlen; n++) { if (--sp->nibuf < 0) { dseek(which, (off_t)(sp->bno + 1) * sp->bsize, 077777); sp->nibuf--; } if ((*buf++ = *sp->Cptr++) == 0) break; } } /* * Examine a single file or archive member on pass 1. */ load1(libflg, loc) off_t loc; { register SYMBOL *sp; int savindex; int ndef, type, mtype; long nlocal; VADDR vsym; struct nlist objsym; off_t strloc; long strsize; char *strtab; register struct vseg *seg; readhdr(loc); if (filhdr.e.a_syms == 0) { if (filhdr.e.a_text+filhdr.e.a_data == 0) return (0); error(1, "no namelist"); } ctrel = tsize; cdrel += dsize; cbrel += bsize; ndef = 0; nlocal = sizeof (cursym); savindex = symindex; bzero(symhash, sizeof (symhash)); if ((filhdr.e.a_flag&RELFLG)==1) { error(1, "No relocation bits"); return(0); } dseek(SYMBOLS, loc + N_SYMOFF(filhdr), filhdr.e.a_syms); strloc = loc + N_STROFF(filhdr); lseek(infil, strloc, L_SET); read(infil, &strsize, sizeof (long)); strtab = NULL; if (strsize <= 8192L) { strtab = (char *)malloc((int)strsize); if (strtab) read(infil, strtab, (int)strsize); } if (!strtab) inistr(STRINGS); while (Input[SYMBOLS].nsize > 0) { mget((int *)&objsym, sizeof objsym, SYMBOLS); type = objsym.n_type; if (Sflag) { mtype = type&037; if (mtype==1 || mtype>4) { continue; } } /* * Now convert 'nlist' format symbol to 'fixed' (semi old style) format. * This may look strange but it greatly simplifies things and avoids having * to read the entire string table into virtual memory. * * Also, we access the symbols in order. The assembler was nice enough * to place the strings in the same order as the symbols - so effectively * we are doing a sequential read of the string table. */ if (strtab) strncpy(cursym.n_name, (int)objsym.n_un.n_strx + strtab - sizeof (long), NNAMESIZE); else { dseek(STRINGS, objsym.n_un.n_strx + strloc, 077777); mgets(cursym.n_name, NNAMESIZE, STRINGS); } cursym.n_type = objsym.n_type; cursym.n_value = objsym.n_value; cursym.n_ovly = objsym.n_ovly; if ((type&N_EXT)==0) { if (Xflag==0 || cursym.n_name[0]!='L') nlocal += sizeof (cursym); continue; } switch (cursym.n_type) { case N_TEXT: case N_EXT+N_TEXT: cursym.n_value += ctrel; break; case N_DATA: case N_EXT+N_DATA: cursym.n_value += cdrel; break; case N_BSS: case N_EXT+N_BSS: cursym.n_value += cbrel; break; case N_EXT+N_UNDF: break; default: if (cursym.n_type&N_EXT) cursym.n_type = N_EXT+N_ABS; break; } if (enter(lookup())) continue; vsym = sym2va(lastsym); seg = vmmapseg(&Vspace, VSEG(vsym)); sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); if (sp->n_type != N_EXT+N_UNDF) continue; if (cursym.n_type == N_EXT+N_UNDF) { if (cursym.n_value > sp->n_value) { sp->n_value = cursym.n_value; vmmodify(seg); } continue; } if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT) continue; ndef++; sp->n_type = cursym.n_type; sp->n_value = cursym.n_value; sp->n_ovly = ((sp->n_type &~ N_EXT) == N_TEXT) ? curov : 0; VMMODIFY(seg); if (trace) printf("%.*s type 0%o in overlay %u at %u\n", NNAMESIZE, sp->n_name, sp->n_type, sp->n_ovly, sp->n_value); } if (strtab) free(strtab); if (Input[STRINGS].buff) { free(Input[STRINGS].buff); Input[STRINGS].buff = NULL; } if (libflg==0 || ndef) { tsize = add(tsize,filhdr.e.a_text,"text overflow"); dsize = add(dsize,filhdr.e.a_data,"data overflow"); bsize = add(bsize,filhdr.e.a_bss,"bss overflow"); ssize += nlocal; return (1); } /* * No symbols defined by this library member. * Rip out the hash table entries and reset the symbol table. */ hreset(); symindex = savindex; return(0); } static hreset() { register u_short *sp, i; u_short j; register u_short mask; sp = symhash; for (i = 0; i < NSYM; sp++, i += 16) { if (*sp == 0) continue; for (mask = 1, j = i; *sp; j++) { if (*sp & mask) { hshtab[j] = -1; *sp &= ~mask; } mask <<= 1; } } } middle() { VADDR vsym; register SYMBOL *sp; register int i; register struct vseg *seg; u_int csize; u_int nund, corigin; u_int ttsize; torigin = 0; dorigin = 0; borigin = 0; p_etext = *slookup("_etext"); p_edata = *slookup("_edata"); p_end = *slookup("_end"); /* * If there are any undefined symbols, save the relocation bits. * (Unless we are overlaying.) */ if (rflag==0 && !numov) { for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo + VOFF(vsym)); if (sp->n_type==N_EXT+N_UNDF && sp->n_value==0 && i != p_end && i != p_edata && i != p_etext) { rflag++; dflag = 0; break; } } } if (rflag) nflag = sflag = iflag = Oflag = 0; /* * Assign common locations. */ csize = 0; if (dflag || rflag==0) { ldrsym(p_etext, tsize, N_EXT+N_TEXT); ldrsym(p_edata, dsize, N_EXT+N_DATA); ldrsym(p_end, bsize, N_EXT+N_BSS); for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { register int t; seg = vmmapseg(&Vspace, VSEG(vsym)); sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); if (sp->n_type==N_EXT+N_UNDF && (t = sp->n_value)!=0) { t = (t+1) & ~01; sp->n_value = csize; sp->n_type = N_EXT+N_COMM; VMMODIFY(seg); csize = add(csize, t, "bss overflow"); } } } if (numov) { for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { seg = vmmapseg(&Vspace, VSEG(vsym)); sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); if (trace) printf("%.*s n_type %o n_value %o sovalue %o ovly %d\n", NNAMESIZE, sp->n_name, sp->n_type, sp->n_value, sp->sovalue, sp->n_ovly); if (sp->n_ovly && sp->n_type == N_EXT+N_TEXT) { sp->sovalue = sp->n_value; sp->n_value = tsize; VMMODIFY(seg); tsize += THUNKSIZ; if (trace) printf("relocating %.*s in overlay %d from %o to %o\n", NNAMESIZE,sp->n_name,sp->n_ovly, sp->sovalue, sp->n_value); } } } /* * Now set symbols to their final value */ if (nflag || iflag) tsize = (tsize + 077) & ~077; ttsize = tsize; if (numov) { register int i; ovbase = (u_int)rnd8k(tsize); if (trace) printf("overlay base is %u.\n", ovbase); for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { seg = vmmapseg(&Vspace, VSEG(vsym)); sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); if (sp->n_ovly && sp->n_type == N_EXT+N_TEXT) { sp->sovalue += ovbase; VMMODIFY(seg); if (trace) printf("%.*s at %u overlay %d\n", NNAMESIZE, sp->n_name, sp->sovalue, sp->n_ovly); } } for (i = 0; i < NOVL; i++) { filhdr.o.ov_siz[i] = (filhdr.o.ov_siz[i] + 077) &~ 077; if (filhdr.o.ov_siz[i] > filhdr.o.max_ovl) filhdr.o.max_ovl = filhdr.o.ov_siz[i]; } if (trace) printf("max overlay size is %u\n", filhdr.o.max_ovl); ttsize = (u_int)rnd8k(ovbase + filhdr.o.max_ovl); if (trace) printf("overlays end before %u.\n", ttsize); } dorigin = ttsize; if (nflag) dorigin = (u_int)rnd8k(ttsize); if (iflag) dorigin = 0; corigin = dorigin + dsize; borigin = corigin + csize; nund = 0; for (i=0, vsym=sym2va(0); i < symindex; i++, vsym=sym2va(i)) { seg = vmmapseg(&Vspace, VSEG(vsym)); sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); switch (sp->n_type) { case N_EXT+N_UNDF: if (arflag == 0) errlev |= 01; if ((arflag==0 || dflag) && sp->n_value==0) { if (i == p_end || i == p_etext || i == p_edata) continue; if (quiet) continue; if (nund==0) printf("Undefined:\n"); nund++; printf("%.*s\n", NNAMESIZE, sp->n_name); } continue; case N_EXT+N_ABS: default: continue; case N_EXT+N_TEXT: sp->n_value += torigin; VMMODIFY(seg); continue; case N_EXT+N_DATA: sp->n_value += dorigin; VMMODIFY(seg); continue; case N_EXT+N_BSS: sp->n_value += borigin; VMMODIFY(seg); continue; case N_EXT+N_COMM: sp->n_type = N_EXT+N_BSS; sp->n_value += corigin; VMMODIFY(seg); continue; } } if (sflag || xflag) ssize = 0; bsize = add(bsize, csize, "bss overflow"); nsym = ssize / (sizeof cursym); } ldrsym(ix, val, type) short ix; u_int val; int type; { VADDR vsym; register struct vseg *seg; register SYMBOL *sp; if (ix == -1) return; vsym = sym2va(ix); seg = vmmapseg(&Vspace, VSEG(vsym)); sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); if (sp->n_type != N_EXT+N_UNDF || sp->n_value) { printf("%.*s: n_value %o", NNAMESIZE, sp->n_name, sp->n_value); error(0, "attempt to redefine loader-defined symbol"); return; } sp->n_type = type; sp->n_value = val; VMMODIFY(seg); } setupout() { VADDR vsym; register SYMBOL *sp; tcreat(&toutb, 0); mktemp(tfname); tcreat(&doutb, 1); if (sflag==0 || xflag==0) tcreat(&soutb, 1); if (rflag) { tcreat(&troutb, 1); tcreat(&droutb, 1); } if (numov) tcreat(&voutb, 1); filhdr.e.a_magic = (Oflag ? A_MAGIC4 : (iflag ? A_MAGIC3 : (nflag ? A_MAGIC2 : A_MAGIC1))); if (numov) { if (filhdr.e.a_magic == A_MAGIC1) error(1, "-n or -i must be used with overlays"); filhdr.e.a_magic |= 020; } filhdr.e.a_text = tsize; filhdr.e.a_data = dsize; filhdr.e.a_bss = bsize; ssize = sflag? 0 : (ssize + (sizeof (struct nlist)) * symindex); /* * This is an estimate, the real size is computed later and the * a.out header rewritten with the correct value. */ filhdr.e.a_syms = ssize&0177777; if (entrypt != -1) { vsym = sym2va(entrypt); sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo + VOFF(vsym)); if (sp->n_type!=N_EXT+N_TEXT) error(0, "entry point not in text"); else if (sp->n_ovly) error(0, "entry point in overlay"); else filhdr.e.a_entry = sp->n_value | 01; } else filhdr.e.a_entry = 0; filhdr.e.a_flag = (rflag==0); fwrite(&filhdr.e, sizeof (filhdr.e), 1, toutb); if (numov) fwrite(&filhdr.o, sizeof (filhdr.o), 1, toutb); } load2arg(acp, flag) char *acp; int flag; { register char *cp; register LIBLIST *lp; cp = acp; switch (getfile(cp, flag, 2)) { case 0: while (*cp) cp++; while (cp >= acp && *--cp != '/') ; mkfsym(++cp); load2(0L); break; case -1: return; default: /* scan archive members referenced */ for (lp = libp; lp->loc != -1; lp++) { lseek(infil, lp->loc, L_SET); get_arobj(infil); mkfsym(chdr.name); load2(lp->loc + sizeof (struct ar_hdr) + chdr.lname); } libp = ++lp; break; } close(infil); } load2(loc) long loc; { register SYMBOL *sp; register struct local *lp; register int symno; int type, mtype; VADDR vsym; short i; struct nlist objsym; off_t stroff; char *strtab; long strsize; readhdr(loc); ctrel = torigin; cdrel += dorigin; cbrel += borigin; /* * Reread the symbol table, recording the numbering * of symbols for fixing external references. */ lp = local; symno = -1; dseek(SYMBOLS, loc + N_SYMOFF(filhdr), filhdr.e.a_syms); stroff = loc + N_STROFF(filhdr); lseek(infil, stroff, L_SET); read(infil, &strsize, sizeof (long)); strtab = NULL; if (strsize <= 8192L) { strtab = (char *)malloc((int)strsize); if (strtab) read(infil, strtab, (int)strsize); } if (!strtab) inistr(STRINGS); while (Input[SYMBOLS].nsize > 0) { symno++; mget((int *)&objsym, sizeof objsym, SYMBOLS); if (strtab) strncpy(cursym.n_name, (int)objsym.n_un.n_strx + strtab - sizeof (long), NNAMESIZE); else { dseek(STRINGS, objsym.n_un.n_strx + stroff, 07777); mgets(cursym.n_name, NNAMESIZE, STRINGS); } cursym.n_type = objsym.n_type; cursym.n_value = objsym.n_value; cursym.n_ovly = objsym.n_ovly; switch (cursym.n_type) { case N_TEXT: case N_EXT+N_TEXT: cursym.n_value += ctrel; break; case N_DATA: case N_EXT+N_DATA: cursym.n_value += cdrel; break; case N_BSS: case N_EXT+N_BSS: cursym.n_value += cbrel; break; case N_EXT+N_UNDF: break; default: if (cursym.n_type&N_EXT) cursym.n_type = N_EXT+N_ABS; break; } type = cursym.n_type; if (Sflag) { mtype = type&037; if (mtype==1 || mtype>4) continue; } if ((type&N_EXT) == 0) { if (!sflag && !xflag && (!Xflag || cursym.n_name[0] != 'L')) { /* * preserve overlay number for locals * mostly for adb. mjk 7/81 */ if ((type == N_TEXT) && inov) cursym.n_ovly = curov; fwrite(&cursym, sizeof cursym, 1, soutb); } continue; } i = *lookup(); if (i == -1) error(1, "internal error: symbol not found"); if (cursym.n_type == N_EXT+N_UNDF || cursym.n_type == N_EXT+N_TEXT) { if (lp >= &local[NSYMPR]) error(2, "Local symbol overflow"); lp->locindex = symno; lp++->locsymbol = i; continue; } vsym = sym2va(i); sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo + VOFF(vsym)); if (cursym.n_type != sp->n_type || cursym.n_value != sp->n_value && !sp->n_ovly || sp->n_ovly && cursym.n_value != sp->sovalue) { printf("%.*s: ", NNAMESIZE, cursym.n_name); if (trace) printf(" ovly %d sovalue %o new %o hav %o ", sp->n_ovly, sp->sovalue, cursym.n_value, sp->n_value); error(0, "multiply defined"); } } if (strtab) free(strtab); if (Input[STRINGS].buff) { free(Input[STRINGS].buff); Input[STRINGS].buff = NULL; } dseek(TEXT, loc + N_TXTOFF(filhdr.e), filhdr.e.a_text); dseek(RELOC, loc + N_TRELOC(filhdr.e), filhdr.e.a_text); load2td(lp, ctrel, inov ? voutb : toutb, troutb); dseek(TEXT, loc + N_DATOFF(filhdr), filhdr.e.a_data); dseek(RELOC, loc + N_DRELOC(filhdr), filhdr.e.a_data); load2td(lp, cdrel, doutb, droutb); torigin += filhdr.e.a_text; dorigin += filhdr.e.a_data; borigin += filhdr.e.a_bss; } load2td(lp, creloc, b1, b2) struct local *lp; u_int creloc; FILE *b1, *b2; { register u_int r, t; register SYMBOL *sp; short i; VADDR vsym; for (;;) { /* * Can't do this because of the word/byte count fakery that's used to * prevrent erroneous EOF indications. Yuck. t = get(TEXT); t = get(RELOC); */ /* * The pickup code is copied from "get" for speed. */ /* next text or data word */ if (--Input[TEXT].nsize <= 0) { if (Input[TEXT].nsize < 0) break; Input[TEXT].nsize++; t = get(TEXT); } else if (--Input[TEXT].nibuf < 0) { Input[TEXT].nibuf++; Input[TEXT].nsize++; t = get(TEXT); } else t = *Input[TEXT].Iptr++; /* next relocation word */ if (--Input[RELOC].nsize <= 0) { if (Input[RELOC].nsize < 0) error(1, "relocation error"); Input[RELOC].nsize++; r = get(RELOC); } else if (--Input[RELOC].nibuf < 0) { Input[RELOC].nibuf++; Input[RELOC].nsize++; r = get(RELOC); } else r = *Input[RELOC].Iptr++; switch (r&016) { case RTEXT: t += ctrel; break; case RDATA: t += cdrel; break; case RBSS: t += cbrel; break; case REXT: i = *lookloc(lp, r); vsym = sym2va(i); sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + VOFF(vsym)); if (sp->n_type==N_EXT+N_UNDF) { r = (r&01) + ((nsym + i)<<4) + REXT; break; } t += sp->n_value; r = (r&01) + ((sp->n_type-(N_EXT+N_ABS))<<1); break; #ifndef pdp11 default: error(1, "relocation format botch (symbol type))"); #endif } if (r&01) t -= creloc; putw(t, b1); if (rflag) putw(r, b2); } } finishout() { register u_int n; register SYMBOL *sp; struct nlist objsym; VADDR vsym; int type, len; off_t stroff; long dtotal, ovrnd; int thunk[THUNKSIZ / sizeof (int)]; if (numov) { int aovhndlr[NOVL+1]; for (n=1; n<=numov; n++) { /* Note that NOVL can be up to 15 with this */ ovhndlr.n_name[HNDLR_NUM] = "0123456789abcdef"[n]; aovhndlr[n] = adrof(ovhndlr.n_name); } for (n=0,vsym=sym2va(0); n < symindex; n++,vsym=sym2va(n)) { sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + VOFF(vsym)); if (sp->n_ovly && (sp->n_type & (N_EXT+N_TEXT))) { thunk[0] = 012701; /* mov $~foo+4, r1 */ thunk[1] = sp->sovalue + 4; thunk[2] = 04537; /* jsr r5, ovhndlrx */ thunk[3] = aovhndlr[sp->n_ovly]; fwrite(thunk, THUNKSIZ, 1, toutb); torigin += THUNKSIZ; } } } if (nflag||iflag) { n = torigin; while (n&077) { n += 2; putw(0, toutb); if (rflag) putw(0, troutb); } } if (numov) copy(voutb); copy(doutb); if (rflag) { copy(troutb); copy(droutb); } if (sflag==0) { /* * Now write the symbol table out, converting from the 'fixed' style * symbol table used internally to the string table version used in * object/executable files. First the "local" (non-global) symbols * are written out, these are the symbols placed in the temporary file * accessed via 'soutb'. * * 'voutb' (overlay temp file), 'troutb' (text relocation temp file), * 'droutb' (data relocation temp file), and 'doutb' (data temp file) * have all been finished with and closed by this point. We reuse one * of these ('doutb') to build the string table. */ tcreat(&doutb, 1); nsym = 0; stroff = sizeof (long); /* string table size */ if (xflag == 0) { fflush(soutb); /* flush local symbol file */ rewind(soutb); while (fread(&cursym, sizeof (cursym), 1, soutb) == 1) { if (feof(soutb)) break; objsym.n_value = cursym.n_value; objsym.n_type = cursym.n_type; objsym.n_ovly = cursym.n_ovly; objsym.n_un.n_strx = stroff; len = strlen(cursym.n_name); if (len >= NNAMESIZE) len = NNAMESIZE; fwrite(cursym.n_name, 1, len, doutb); fputc('\0', doutb); stroff += (len + 1); fwrite(&objsym, sizeof (objsym), 1, toutb); nsym++; } fclose(soutb); } /* * Now we dump the global/external symbol table by marching thru the * 'vm' addresss space. */ for (n = 0, vsym = sym2va(0); n < symindex; n++, vsym = sym2va(n)) { sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + VOFF(vsym)); objsym.n_value = sp->n_value; objsym.n_type = sp->n_type; objsym.n_ovly = sp->n_ovly; objsym.n_un.n_strx = stroff; len = strlen(sp->n_name); if (len > NNAMESIZE) len = NNAMESIZE; fwrite(sp->n_name, 1, len, doutb); fputc('\0', doutb); stroff += (len + 1); fwrite(&objsym, sizeof (objsym), 1, toutb); nsym++; } #ifdef whybother if (stroff & 1) { fputc('\0', doutb); stroff++; } #endif /* * Now write the length of the string table out. Then copy the temp * file containing the strings to the image being built. */ fwrite(&stroff, sizeof (stroff), 1, toutb); copy(doutb); } /* * Fix up the header with the correct symbol table size - we now know * _exactly_ how many symbols were placed in the symbol table (the size * used earlier was only an estimate */ fflush(toutb); rewind(toutb); fread(&filhdr.e, sizeof (filhdr.e), 1, toutb); filhdr.e.a_syms = nsym * sizeof (objsym); rewind(toutb); fwrite(&filhdr.e, sizeof (filhdr.e), 1, toutb); fclose(toutb); if (!ofilfnd) { if (rename("l.out", "a.out") < 0) error(1, "cannot move l.out to a.out"); ofilename = "a.out"; } /* * we now do a sanity check on the total sizes of things. Previously the * linker could produce a program marked as executable but which had bogus * overlay+root sizes, etc. */ #define K56 (56L * 1024L) #define K64 (64L * 1024L) dtotal = (long)dsize + (long)bsize; ovrnd = rnd8k(filhdr.o.max_ovl); /* 0 if not overlaid */ type = 0; if (nflag) { if (rnd8k(tsize) + ovrnd + dtotal > K56) type = filhdr.e.a_magic; } else if (iflag) { if ((rnd8k(tsize) + ovrnd > K64) || (dtotal > K56)) type = filhdr.e.a_magic; } else { if ((long)tsize + dtotal > K56) type = filhdr.e.a_magic; } if (type && !rflag) { fprintf(stderr, "ld: too big for type %o\n", type); errlev = 2; } delarg = errlev; delexit(); } long rnd8k(siz) u_int siz; { long l = siz; return((l + 017777) & ~017777L); } mkfsym(s) char *s; { if (sflag || xflag) return; strncpy(cursym.n_name, s, NNAMESIZE); cursym.n_type = N_FN; cursym.n_value = torigin; fwrite(&cursym, sizeof (cursym), 1, soutb); } mget(loc, an, which) register int *loc; int an, which; { register int n; register STREAM *tp = &Input[which]; n = an >> 1; if ((tp->nibuf -= n) >= 0) { if ((tp->nsize -= n) > 0) { bcopy(tp->ptr, loc, an); tp->Iptr += n; return; } tp->nsize += n; } tp->nibuf += n; do { *loc++ = get(which); } while (--n); } dseek(which, aloc, s) int which; off_t aloc; int s; { register STREAM *sp = &Input[which]; register u_int b, o; int n; b = aloc / sp->bsize; o = aloc & (sp->bsize - 1); if (sp->bno != b) { (void)lseek(infil, (off_t)sp->bsize * b, L_SET); if ((n = read(infil, (char *)sp->buff, sp->bsize)) < 0) n = 0; sp->bno = b; sp->nread = n; } sp->nibuf = sp->nread - o; sp->Cptr = (char *)sp->buff + o; if (which != STRINGS) sp->nibuf >>= 1; if (s != -1) sp->nsize = (s >> 1) & 077777; if (sp->nibuf <= 0) sp->nsize = 0; } get(which) int which; { register STREAM *sp = &Input[which]; if (--sp->nibuf < 0) { dseek(which, (off_t)(sp->bno + 1) * sp->bsize, -1); --sp->nibuf; } if (--sp->nsize <= 0) { if (sp->nsize < 0) error(1, "premature EOF#1"); } return(*sp->Iptr++); } getfile(acp, flag, phase) char *acp; int flag; /* 1 = fatal if file not found, -1 = not fatal */ { char arcmag[SARMAG+1]; struct stat stb; filname = acp; chdr.name[0] = '\0'; /* not in archive for now */ if (filname[0] == '-' && filname[1] == 'l') infil = libopen(filname + 2, O_RDONLY); else infil = open(filname, O_RDONLY); if (infil < 0) { if (phase == 1) /* only complain once on phase 1 */ error(flag, "cannot open"); return(-1); } fstat(infil, &stb); Input[TEXT].bno = -1; Input[RELOC].bno = -1; Input[SYMBOLS].bno = -1; Input[STRINGS].bno = -1; dseek(TEXT, 0L, SARMAG); if (Input[TEXT].nsize <= 0) error(1, "premature EOF#2"); mget((char *)arcmag, SARMAG, TEXT); arcmag[SARMAG] = 0; if (strcmp(arcmag, ARMAG)) return(0); lseek(infil, (off_t)SARMAG, L_SET); if (get_arobj(infil) <= 0) return(1); if (strcmp(chdr.name, RANLIBMAG)) return(1); /* regular archive */ return (stb.st_mtime > chdr.date ? 3 : 2); } /* * Search for a library with given name * using the directory search array. */ libopen(name, oflags) char *name; int oflags; { register char *p, *cp; register int i; static char buf[100]; int fd; for (i = 0; i < ndir ; i++) { p = buf; for (cp = dirs[i]; *cp; *p++ = *cp++) ; *p++ = '/'; *p++ = 'l'; *p++ = 'i'; *p++ = 'b'; for (cp = name; *cp; *p++ = *cp++) ; *p++ = '.'; *p++ = 'a'; *p++ = '\0'; fd = open(buf, oflags); if (fd != -1) { filname = buf; return(fd); } } return(-1); } short * lookup() { register short *hp; register char *cp; SYMBOL *sp; union { long x; short y[2]; } sh; VADDR vsym; sh.x = 0; for (cp = cursym.n_name; cp < &cursym.n_name[NNAMESIZE] && *cp;) sh.x = (sh.x<<1) + *cp++; sh.y[1] += sh.y[0]; hp = &hshtab[(sh.y[1]&077777)%NSYM+2]; while (*hp != -1) { vsym = sym2va(*hp); sp = (SYMBOL *)(vmmapseg(&Vspace,VSEG(vsym))->s_cinfo + VOFF(vsym)); if (!strncmp(sp->n_name, cursym.n_name, NNAMESIZE)) break; if (++hp >= &hshtab[NSYM+2]) hp = hshtab; } return(hp); } short * slookup(s) char *s; { strncpy(cursym.n_name, s, NNAMESIZE); cursym.n_type = N_EXT+N_UNDF; cursym.n_value = 0; return(lookup()); } enter(hp) short *hp; { register SYMBOL *sp; u_int word, bit, hnum; VADDR vsym; register struct vseg *seg; if (*hp == -1) { if (symindex>=NSYM) error(1, "symbol table overflow"); hnum = hp - hshtab; word = hnum / 16; bit = hnum % 16; symhash[word] |= (1 << bit); vsym = sym2va(symindex); *hp = lastsym = symindex; symindex++; seg = vmmapseg(&Vspace, VSEG(vsym)); sp = (SYMBOL *)(seg->s_cinfo + VOFF(vsym)); strncpy(sp->n_name, cursym.n_name, NNAMESIZE); sp->n_type = cursym.n_type; sp->n_value = cursym.n_value; if (sp->n_type == N_EXT+N_TEXT) { sp->n_ovly = curov; if (trace) printf("found %.*s in overlay %d at %u\n", NNAMESIZE, sp->n_name, sp->n_ovly, sp->n_value); } VMMODIFY(seg); return(1); } lastsym = *hp; return(0); } error(n, s) char *s; { if (!s) delexit(); if (errlev==0) printf("ld:"); if (filname) { printf("%s", filname); if (n != -1 && chdr.name[0]) printf("(%s)", chdr.name); printf(": "); } printf("%s\n", s); if (n == -1) return; if (n) delexit(); errlev = 2; } readhdr(loc) off_t loc; { dseek(TEXT, loc, sizeof filhdr); mget((int *)&filhdr.e, sizeof filhdr.e, TEXT); if (filhdr.e.a_magic != A_MAGIC1) error(1, "bad magic number"); if (filhdr.e.a_text&01) ++filhdr.e.a_text; if (filhdr.e.a_data&01) ++filhdr.e.a_data; if (filhdr.e.a_bss&01) ++filhdr.e.a_bss; cdrel = -filhdr.e.a_text; cbrel = cdrel - filhdr.e.a_data; } tcreat(fpp, tempflg) FILE **fpp; int tempflg; { register int ufd; char *nam; nam = (tempflg ? tfname : ofilename); if ((ufd = open(nam, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) error(2, tempflg?"cannot create temp":"cannot create output"); if (tempflg) unlink(tfname); *fpp = fdopen(ufd, "r+"); } adrof(s) char *s; { register short *p; register SYMBOL *sp; VADDR vsym; p = slookup(s); if (*p == -1) { printf("%.*s: ", NNAMESIZE, s); error(1, "undefined"); } vsym = sym2va(*p); sp = (SYMBOL *)(vmmapseg(&Vspace, VSEG(vsym))->s_cinfo + VOFF(vsym)); return(sp->n_value); } copy(fp) register FILE *fp; { register int c; fflush(fp); rewind(fp); while ((c = getc(fp)) != EOF) putc(c, toutb); fclose(fp); } short * lookloc(alp, r) struct local *alp; { register struct local *clp, *lp; register int sn; lp = alp; sn = (r>>4) & 07777; for (clp = local; clplocindex == sn) return(&clp->locsymbol); error(1, "local symbol botch"); /*NOTREACHED*/ } roundov() { while (torigin & 077) { putw(0, voutb); torigin += sizeof (int); } } u_int add(a,b,s) int a, b; char *s; { long r; r = (long)(u_int)a + (u_int)b; if (r >= 0200000) error(1,s); return(r); } /* * "borrowed" from 'ar' because we didn't want to drag in everything else * from 'ar'. The error checking was also ripped out, basically if any * of the criteria for being an archive are not met then a -1 is returned * and the rest of 'ld' figures out what to do. */ typedef struct ar_hdr HDR; static char hb[sizeof(HDR) + 1]; /* real header */ /* Convert ar header field to an integer. */ #define AR_ATOI(from, to, len, base) { \ bcopy(from, buf, len); \ buf[len] = '\0'; \ to = strtol(buf, (char **)NULL, base); \ } /* * get_arobj -- * read the archive header for this member */ get_arobj(fd) int fd; { HDR *hdr; register int len, nr; register char *p; char buf[20]; nr = read(fd, hb, sizeof(HDR)); if (nr != sizeof(HDR)) return(-1); hdr = (HDR *)hb; if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1)) return(-1); /* Convert the header into the internal format. */ #define DECIMAL 10 #define OCTAL 8 AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL); AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL); AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL); AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL); AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL); /* Leading spaces should never happen. */ if (hdr->ar_name[0] == ' ') return(-1); /* * Long name support. Set the "real" size of the file, and the * long name flag/size. */ if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) { chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1); if (len <= 0 || len > MAXNAMLEN) return(-1); nr = read(fd, chdr.name, (size_t)len); if (nr != len) return(-1); chdr.name[len] = 0; chdr.size -= len; } else { chdr.lname = 0; bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name)); /* Strip trailing spaces, null terminate. */ for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p); *++p = '\0'; } return(1); } /* * skip - where to seek for next archive member. */ off_t skip() { off_t len; len = chdr.size + (chdr.size + chdr.lname & 1); len += sizeof (HDR); return(len); } inistr(which) int which; { register STREAM *sp = &Input[which]; register int size = 4096; if (sp->buff == (int *)NULL) { while (size > 256) { sp->buff = (int *)malloc(size); if (sp->buff) { sp->bsize = size; return; } size >>= 1; } error(1, "No memory for strings"); } } ff++; } #endif /* * Now write the length of the string table out. Then copy the temp * file containing the strings to the image being built. */ fwrite(&stroff, sizeof (stroff), 1, toutb); copy(doutb); } /* * Fix up the header with the correct symbol table size - we now know * _exactly_ how many symbols were placed in the symbol table (the size * used earlier was only an estimate */ fflush(toutb); rewind(toutb); fread(&filhdr.e, sizeof (filhdr.e), 1, toutb); fibin/ld/Makefile 644 0 12 414 5707650141 6623 # Version 2.1 January 19, 1994 SRCS= ld.c OBJS= ld.o CFLAGS= -O -I../ar -DNUM_VM_PAGES=20 all: ld ld: ${OBJS} cc -i -o ld ${OBJS} -lvmf install: install -c -s -o bin -g bin -m 755 ld ${DESTDIR}/bin/ld lint: lint -havx -I../ar ${SRCS} clean: rm -f *.o *.0 ld bin/login/ 755 0 12 0 6024521647 5631 bin/login/Makefile 644 0 12 2325 5326557240 7362 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that the above copyright notice and this paragraph are # duplicated in all such forms and that any documentation, advertising # materials, and other materials related to such redistribution and # use acknowledge that the software was developed by the University # of California, Berkeley. The name of the University may not be # used to endorse or promote products derived from this software # without specific prior written permission. THIS SOFTWARE IS PROVIDED # ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, # WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND # FITNESS FOR A PARTICULAR PURPOSE. # # @(#)Makefile 5.3 (Berkeley) 5/9/89 # CFLAGS= -O -i LIBC= /lib/libc.a SRCS= login.c OBJS= MAN= all: login login: ${LIBC} ${CC} -o $@ ${CFLAGS} $@.c -lutil clean: rm -f ${OBJS} core login cleandir: clean rm -f ${MAN} tags .depend depend: ${SRCS} mkdep -p ${CFLAGS} ${SRCS} install: login install -s -o root -g bin -m 4755 login ${DESTDIR}/bin/login lint: ${SRCS} lint ${CFLAGS} ${SRCS} tags: ${SRCS} ctags ${SRCS} t"); ofilename = "a.out"; } /* * we now do a sanity check on the total sizes of things. Previously the * linker could produce a program marked as executable but which had bogus * overlay+root sizes, etc. */ #define K56 (56L * 1024L) #define K64 (64L * 1024L) dtotal = (long)dsize + (long)bsbin/login/login.c 644 0 12 33636 5514435667 7236 /* * Copyright (c) 1980, 1987, 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1980, 1987, 1988 The Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)login.c 5.40.1 (2.11BSD GTE) 1/1/94"; #endif /* * login [ name ] * login -h hostname (for telnetd, etc.) * login -f name (for pre-authenticated login: datakit, xterm, etc.) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" #ifdef KERBEROS #include #include char realm[REALM_SZ]; int kerror = KSUCCESS, notickets = 1; #endif #define TTYGRPNAME "tty" /* name of group to own ttys */ /* * This bounds the time given to login. Not a define so it can * be patched on machines where it's too small. */ int timeout = 300; struct passwd *pwd; int failures; char term[64], *hostname, *username, *tty; struct sgttyb sgttyb; struct tchars tc = { CINTR, CQUIT, CSTART, CSTOP, CEOT, CBRK }; struct ltchars ltc = { CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT }; char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; main(argc, argv) int argc; char **argv; { extern int errno, optind; extern char *optarg, **environ; struct timeval tp; struct tm *ttp; struct group *gr; register int ch; register char *p; int ask, fflag, hflag, pflag, cnt; int quietlog, passwd_req, ioctlval, timedout(); char *domain, *salt, *envinit[1], *ttyn, *pp; char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; char *ctime(), *ttyname(), *stypeof(), *crypt(), *getpass(); time_t time(); off_t lseek(); (void)signal(SIGALRM, timedout); (void)alarm((u_int)timeout); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)setpriority(PRIO_PROCESS, 0, 0); (void)quota(Q_SETUID, 0, 0, 0); /* * -p is used by getty to tell login not to destroy the environment * -f is used to skip a second login authentication * -h is used by other servers to pass the name of the remote * host to login so that it may be placed in utmp and wtmp */ (void)gethostname(tbuf, sizeof(tbuf)); domain = index(tbuf, '.'); fflag = hflag = pflag = 0; passwd_req = 1; while ((ch = getopt(argc, argv, "fh:p")) != EOF) switch (ch) { case 'f': fflag = 1; break; case 'h': if (getuid()) { (void)fprintf(stderr, "login: -h for super-user only.\n"); exit(1); } hflag = 1; if (domain && (p = index(optarg, '.')) && strcasecmp(p, domain) == 0) *p = 0; hostname = optarg; break; case 'p': pflag = 1; break; case '?': default: (void)fprintf(stderr, "usage: login [-fp] [username]\n"); exit(1); } argc -= optind; argv += optind; if (*argv) { username = *argv; ask = 0; } else ask = 1; ioctlval = 0; (void)ioctl(0, TIOCLSET, &ioctlval); (void)ioctl(0, TIOCNXCL, 0); (void)fcntl(0, F_SETFL, ioctlval); (void)ioctl(0, TIOCGETP, &sgttyb); sgttyb.sg_erase = CERASE; sgttyb.sg_kill = CKILL; (void)ioctl(0, TIOCSLTC, <c); (void)ioctl(0, TIOCSETC, &tc); (void)ioctl(0, TIOCSETP, &sgttyb); for (cnt = getdtablesize(); cnt > 2; cnt--) close(cnt); ttyn = ttyname(0); if (ttyn == NULL || *ttyn == '\0') { (void)sprintf(tname, "%s??", _PATH_TTY); ttyn = tname; } if (tty = rindex(ttyn, '/')) ++tty; else tty = ttyn; openlog("login", LOG_ODELAY, LOG_AUTH); for (cnt = 0;; ask = 1) { ioctlval = 0; (void)ioctl(0, TIOCSETD, &ioctlval); if (ask) { fflag = 0; getloginname(); } /* * Note if trying multiple user names; * log failures for previous user name, * but don't bother logging one failure * for nonexistent name (mistyped username). */ if (failures && strcmp(tbuf, username)) { if (failures > (pwd ? 0 : 1)) badlogin(tbuf); failures = 0; } (void)strcpy(tbuf, username); if (pwd = getpwnam(username)) salt = pwd->pw_passwd; else salt = "xx"; /* if user not super-user, check for disabled logins */ if (pwd == NULL || pwd->pw_uid) checknologin(); /* * Disallow automatic login to root; if not invoked by * root, disallow if the uid's differ. */ if (fflag && pwd) { int uid = getuid(); passwd_req = pwd->pw_uid == 0 || (uid && uid != pwd->pw_uid); } /* * If trying to log in as root, but with insecure terminal, * refuse the login attempt. */ if (pwd->pw_uid == 0 && !rootterm(tty)) { (void)fprintf(stderr, "%s login refused on this terminal.\n", pwd->pw_name); if (hostname) syslog(LOG_NOTICE, "LOGIN %s REFUSED FROM %s ON TTY %s", pwd->pw_name, hostname, tty); else syslog(LOG_NOTICE, "LOGIN %s REFUSED ON TTY %s", pwd->pw_name, tty); continue; } /* * If no pre-authentication and a password exists * for this user, prompt for one and verify it. */ if (!passwd_req || (pwd && !*pwd->pw_passwd)) break; setpriority(PRIO_PROCESS, 0, -4); pp = getpass("Password:"); p = crypt(pp, salt); setpriority(PRIO_PROCESS, 0, 0); #ifdef KERBEROS /* * If not present in pw file, act as we normally would. * If we aren't Kerberos-authenticated, try the normal * pw file for a password. If that's ok, log the user * in without issueing any tickets. */ if (pwd && !krb_get_lrealm(realm,1)) { /* * get TGT for local realm; be careful about uid's * here for ticket file ownership */ (void)setreuid(geteuid(),pwd->pw_uid); kerror = krb_get_pw_in_tkt(pwd->pw_name, "", realm, "krbtgt", realm, DEFAULT_TKT_LIFE, pp); (void)setuid(0); if (kerror == INTK_OK) { bzero(pp, strlen(pp)); notickets = 0; /* user got ticket */ break; } } #endif (void) bzero(pp, strlen(pp)); if (pwd && !strcmp(p, pwd->pw_passwd)) break; (void)printf("Login incorrect\n"); failures++; /* we allow 10 tries, but after 3 we start backing off */ if (++cnt > 3) { if (cnt >= 10) { badlogin(username); (void)ioctl(0, TIOCHPCL, (struct sgttyb *)NULL); sleepexit(1); } sleep((u_int)((cnt - 3) * 5)); } } /* committed to login -- turn off timeout */ (void)alarm((u_int)0); /* paranoia... */ endpwent(); if (quota(Q_SETUID, pwd->pw_uid, 0, 0) < 0 && errno != EINVAL) { switch(errno) { case EUSERS: (void)fprintf(stderr, "Too many users logged on already.\nTry again later.\n"); break; case EPROCLIM: (void)fprintf(stderr, "You have too many processes running.\n"); break; default: perror("quota (Q_SETUID)"); } sleepexit(0); } if (chdir(pwd->pw_dir) < 0) { (void)printf("No directory %s!\n", pwd->pw_dir); if (chdir("/")) exit(0); pwd->pw_dir = "/"; (void)printf("Logging in with home = \"/\".\n"); } quietlog = access(_PATH_HUSHLOGIN, F_OK) == 0; #ifdef KERBEROS if (notickets && !quietlog) (void)printf("Warning: no Kerberos tickets issued\n"); #endif #define TWOWEEKS (14*24*60*60) if (pwd->pw_change || pwd->pw_expire) (void)gettimeofday(&tp, (struct timezone *)NULL); if (pwd->pw_change) if (tp.tv_sec >= pwd->pw_change) { (void)printf("Sorry -- your password has expired.\n"); sleepexit(1); } else if (pwd->pw_change - tp.tv_sec < TWOWEEKS && !quietlog) { ttp = localtime(&pwd->pw_change); (void)printf("Warning: your password expires on %s %d, %d\n", months[ttp->tm_mon], ttp->tm_mday, TM_YEAR_BASE + ttp->tm_year); } if (pwd->pw_expire) if (tp.tv_sec >= pwd->pw_expire) { (void)printf("Sorry -- your account has expired.\n"); sleepexit(1); } else if (pwd->pw_expire - tp.tv_sec < TWOWEEKS && !quietlog) { ttp = localtime(&pwd->pw_expire); (void)printf("Warning: your account expires on %s %d, %d\n", months[ttp->tm_mon], ttp->tm_mday, TM_YEAR_BASE + ttp->tm_year); } /* nothing else left to fail -- really log in */ { struct utmp utmp; bzero((char *)&utmp, sizeof(utmp)); (void)time(&utmp.ut_time); strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); if (hostname) strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); login(&utmp); } dolastlog(quietlog); if (!hflag) { /* XXX */ static struct winsize win = { 0, 0, 0, 0 }; (void)ioctl(0, TIOCSWINSZ, &win); } (void)chown(ttyn, pwd->pw_uid, (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); (void)chmod(ttyn, 0620); (void)setgid(pwd->pw_gid); initgroups(username, pwd->pw_gid); quota(Q_DOWARN, pwd->pw_uid, (dev_t)-1, 0); if (*pwd->pw_shell == '\0') pwd->pw_shell = _PATH_BSHELL; /* turn on new line discipline for the csh */ else if (!strcmp(pwd->pw_shell, _PATH_CSHELL)) { ioctlval = NTTYDISC; (void)ioctl(0, TIOCSETD, &ioctlval); } /* destroy environment unless user has requested preservation */ if (!pflag) environ = envinit; (void)setenv("HOME", pwd->pw_dir, 1); (void)setenv("SHELL", pwd->pw_shell, 1); if (term[0] == '\0') strncpy(term, stypeof(tty), sizeof(term)); (void)setenv("TERM", term, 0); (void)setenv("USER", pwd->pw_name, 1); (void)setenv("PATH", _PATH_DEFPATH, 0); if (tty[sizeof("tty")-1] == 'd') syslog(LOG_INFO, "DIALUP %s, %s", tty, pwd->pw_name); if (pwd->pw_uid == 0) if (hostname) syslog(LOG_NOTICE, "ROOT LOGIN ON %s FROM %s", tty, hostname); else syslog(LOG_NOTICE, "ROOT LOGIN ON %s", tty); if (!quietlog) { struct stat st; motd(); (void)sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); if (stat(tbuf, &st) == 0 && st.st_size != 0) (void)printf("You have %smail.\n", (st.st_mtime > st.st_atime) ? "new " : ""); } (void)signal(SIGALRM, SIG_DFL); (void)signal(SIGQUIT, SIG_DFL); (void)signal(SIGINT, SIG_DFL); (void)signal(SIGTSTP, SIG_IGN); tbuf[0] = '-'; strcpy(tbuf + 1, (p = rindex(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell); /* discard permissions last so can't get killed and drop core */ (void)setuid(pwd->pw_uid); execlp(pwd->pw_shell, tbuf, 0); (void)fprintf(stderr, "login: no shell: %s.\n", strerror(errno)); exit(0); } getloginname() { register int ch; register char *p; static char nbuf[UT_NAMESIZE + 1]; for (;;) { (void)printf("login: "); for (p = nbuf; (ch = getchar()) != '\n'; ) { if (ch == EOF) { badlogin(username); exit(0); } if (p < nbuf + UT_NAMESIZE) *p++ = ch; } if (p > nbuf) if (nbuf[0] == '-') (void)fprintf(stderr, "login names may not start with '-'.\n"); else { *p = '\0'; username = nbuf; break; } } } timedout() { (void)fprintf(stderr, "Login timed out after %d seconds\n", timeout); exit(0); } rootterm(ttyn) char *ttyn; { struct ttyent *t; return((t = getttynam(ttyn)) && t->ty_status&TTY_SECURE); } jmp_buf motdinterrupt; motd() { register int fd, nchars; int (*oldint)(), sigint(); char tbuf[BUFSIZ]; if ((fd = open(_PATH_MOTDFILE, O_RDONLY, 0)) < 0) return; oldint = signal(SIGINT, sigint); if (setjmp(motdinterrupt) == 0) while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) (void)write(fileno(stdout), tbuf, nchars); (void)signal(SIGINT, oldint); (void)close(fd); } sigint() { longjmp(motdinterrupt, 1); } checknologin() { register int fd, nchars; char tbuf[BUFSIZ]; if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) (void)write(fileno(stdout), tbuf, nchars); sleepexit(0); } } dolastlog(quiet) int quiet; { struct lastlog ll; int fd; char *ctime(); if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); if (!quiet) { if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && ll.ll_time != 0) { (void)printf("Last login: %.*s ", 24-5, (char *)ctime(&ll.ll_time)); if (*ll.ll_host != '\0') (void)printf("from %.*s\n", sizeof(ll.ll_host), ll.ll_host); else (void)printf("on %.*s\n", sizeof(ll.ll_line), ll.ll_line); } (void)lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); } bzero((char *)&ll, sizeof(ll)); (void)time(&ll.ll_time); strncpy(ll.ll_line, tty, sizeof(ll.ll_line)); if (hostname) strncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); (void)write(fd, (char *)&ll, sizeof(ll)); (void)close(fd); } } badlogin(name) char *name; { if (failures == 0) return; if (hostname) syslog(LOG_NOTICE, "%d LOGIN FAILURE%s FROM %s, %s", failures, failures > 1 ? "S" : "", hostname, name); else syslog(LOG_NOTICE, "%d LOGIN FAILURE%s ON %s, %s", failures, failures > 1 ? "S" : "", tty, name); } #undef UNKNOWN #define UNKNOWN "su" char * stypeof(ttyid) char *ttyid; { struct ttyent *t; return(ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); } getstr(buf, cnt, err) char *buf, *err; int cnt; { char ch; do { if (read(0, &ch, sizeof(ch)) != sizeof(ch)) exit(1); if (--cnt < 0) { (void)fprintf(stderr, "%s too long\r\n", err); sleepexit(1); } *buf++ = ch; } while (ch); } sleepexit(eval) int eval; { sleep((u_int)5); exit(eval); } >ar_fmag, ARFMAG, sizeof(ARFMAG) - 1)) return(-1); /* Convert the header into the internal forbin/login/pathnames.h 644 0 12 2163 4505545546 10057 /* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)pathnames.h 5.3 (Berkeley) 5/9/89 */ #include #define _PATH_DEFPATH "/bin:/usr/ucb:/usr/bin:/usr/games:" #define _PATH_HUSHLOGIN ".hushlogin" #define _PATH_LASTLOG "/usr/adm/lastlog" #define _PATH_MAILDIR "/usr/spool/mail" #define _PATH_MOTDFILE "/etc/motd" #define _PATH_NOLOGIN "/etc/nologin" LOG_NOTICE, "LOGIN %s REFUSED FROM %s ON TTY %s", pwd->pw_name, hostname, tty); else syslog(LOG_NOTICE, "LOGIN %s REFUSED ON TTY %s", pwd->pw_name, tty); continue; } /* * If no pre-authentication and a password exists * for this user, prompt for one and verify it. */ if (!passwd_req || (pwd && !*pwd->pw_passwd)) break; setprioritybin/time.c 444 0 12 2122 4026072621 5674 #ifndef lint static char *sccsid = "@(#)time.c 4.5 (Berkeley) 7/1/83"; #endif /* * time */ #include #include #include #include #include main(argc, argv) int argc; char **argv; { int status; register int p; struct timeval before, after; struct rusage ru; if (argc<=1) exit(0); gettimeofday(&before, 0); p = fork(); if (p < 0) { perror("time"); exit(1); } if (p == 0) { execvp(argv[1], &argv[1]); perror(argv[1]); exit(1); } signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); while (wait3(&status, 0, &ru) != p) ; gettimeofday(&after, 0); if ((status&0377) != 0) fprintf(stderr, "Command terminated abnormally.\n"); after.tv_sec -= before.tv_sec; after.tv_usec -= before.tv_usec; if (after.tv_usec < 0) after.tv_sec--, after.tv_usec += 1000000; printt("real", &after); printt("user", &ru.ru_utime); printt("sys ", &ru.ru_stime); fprintf(stderr, "\n"); exit (status>>8); } printt(s, tv) char *s; struct timeval *tv; { fprintf(stderr, "%9ld.%01ld %s ", tv->tv_sec, tv->tv_usec/100000, s); } iority(PRIO_PROCESS, 0, 0); #ifdef KERBEROS /* * If not present in pw file, act as we normally would. * If we aren't Kerberos-authenticated, try the normal * pw file for a password. If that's ok, log the user * in without issueing any tickets. */ if (pwd && !krb_get_lrealm(realm,1)) { /* * get TGT for local realm; be careful about uid's * here for ticket file ownership */ (void)setreuidbin/ed.c 444 0 12 52352 4013202660 5352 #ifndef lint static char sccsid[] = "@(#)ed.c 4.5.1.1 (Berkeley) 8/12/86"; #endif /* * Editor */ #include #include #undef CEOF #include #define NULL 0 #define FNSIZE 64 #define LBSIZE 512 #define ESIZE 128 #define GBSIZE 256 #define NBRA 5 #define EOF -1 #define CBRA 1 #define CCHR 2 #define CDOT 4 #define CCL 6 #define NCCL 8 #define CDOL 10 #define CEOF 11 #define CKET 12 #define CBACK 14 #define STAR 01 char Q[] = ""; char T[] = "TMP"; #define READ 0 #define WRITE 1 int peekc; int lastc; char savedfile[FNSIZE]; char file[FNSIZE]; char linebuf[LBSIZE]; char rhsbuf[LBSIZE/2]; char expbuf[ESIZE+4]; int circfl; int *zero; int *dot; int *dol; int *addr1; int *addr2; char genbuf[LBSIZE]; long count; char *nextip; char *linebp; int ninbuf; int io; int pflag; long lseek(); int (*oldhup)(); int (*oldquit)(); int vflag = 1; int listf; int col; char *globp; int tfile = -1; int tline; char *tfname; char *loc1; char *loc2; char *locs; char ibuff[512]; int iblock = -1; char obuff[512]; int oblock = -1; int ichanged; int nleft; char WRERR[] = "WRITE ERROR"; int names[26]; int anymarks; char *braslist[NBRA]; char *braelist[NBRA]; int nbra; int subnewa; int subolda; int fchange; int wrapp; unsigned nlall = 128; int *address(); char *getline(); char *getblock(); char *place(); char *mktemp(); char *malloc(); char *realloc(); jmp_buf savej; main(argc, argv) char **argv; { register char *p1, *p2; extern int onintr(), quit(), onhup(); int (*oldintr)(); oldquit = signal(SIGQUIT, SIG_IGN); oldhup = signal(SIGHUP, SIG_IGN); oldintr = signal(SIGINT, SIG_IGN); if ((int)signal(SIGTERM, SIG_IGN) == 0) signal(SIGTERM, quit); argv++; while (argc > 1 && **argv=='-') { switch((*argv)[1]) { case '\0': vflag = 0; break; case 'q': signal(SIGQUIT, SIG_DFL); vflag = 1; break; } argv++; argc--; } if (argc>1) { p1 = *argv; p2 = savedfile; while (*p2++ = *p1++) ; globp = "r"; } zero = (int *)malloc(nlall*sizeof(int)); tfname = mktemp("/tmp/eXXXXX"); init(); if (((int)oldintr&01) == 0) signal(SIGINT, onintr); if (((int)oldhup&01) == 0) signal(SIGHUP, onhup); setjmp(savej); commands(); quit(); } commands() { int getfile(), gettty(); register *a1, c; for (;;) { if (pflag) { pflag = 0; addr1 = addr2 = dot; goto print; } addr1 = 0; addr2 = 0; do { addr1 = addr2; if ((a1 = address())==0) { c = getchr(); break; } addr2 = a1; if ((c=getchr()) == ';') { c = ','; dot = a1; } } while (c==','); if (addr1==0) addr1 = addr2; switch(c) { case 'a': setdot(); newline(); append(gettty, addr2); continue; case 'c': delete(); append(gettty, addr1-1); continue; case 'd': delete(); continue; case 'E': fchange = 0; c = 'e'; case 'e': setnoaddr(); if (vflag && fchange) { fchange = 0; error(Q); } filename(c); init(); addr2 = zero; goto caseread; case 'f': setnoaddr(); filename(c); puts(savedfile); continue; case 'g': global(1); continue; case 'i': setdot(); nonzero(); newline(); append(gettty, addr2-1); continue; case 'j': if (addr2==0) { addr1 = dot; addr2 = dot+1; } setdot(); newline(); nonzero(); join(); continue; case 'k': if ((c = getchr()) < 'a' || c > 'z') error(Q); newline(); setdot(); nonzero(); names[c-'a'] = *addr2 & ~01; anymarks |= 01; continue; case 'm': move(0); continue; case '\n': if (addr2==0) addr2 = dot+1; addr1 = addr2; goto print; case 'l': listf++; case 'p': case 'P': newline(); print: setdot(); nonzero(); a1 = addr1; do { puts(getline(*a1++)); } while (a1 <= addr2); dot = addr2; listf = 0; continue; case 'Q': fchange = 0; case 'q': setnoaddr(); newline(); quit(); case 'r': filename(c); caseread: if ((io = open(file, 0)) < 0) { lastc = '\n'; error(file); } setall(); ninbuf = 0; c = zero != dol; append(getfile, addr2); exfile(); fchange = c; continue; case 's': setdot(); nonzero(); substitute(globp!=0); continue; case 't': move(1); continue; case 'u': setdot(); nonzero(); newline(); if ((*addr2&~01) != subnewa) error(Q); *addr2 = subolda; dot = addr2; continue; case 'v': global(0); continue; case 'W': wrapp++; case 'w': setall(); nonzero(); filename(c); if(!wrapp || ((io = open(file,1)) == -1) || ((lseek(io, 0L, 2)) == -1)) if ((io = creat(file, 0666)) < 0) error(file); wrapp = 0; putfile(); exfile(); if (addr1==zero+1 && addr2==dol) fchange = 0; continue; case '=': setall(); newline(); count = (addr2-zero)&077777; putd(); putchr('\n'); continue; case '!': callunix(); continue; case EOF: return; } error(Q); } } int * address() { register *a1, minus, c; int n, relerr; minus = 0; a1 = 0; for (;;) { c = getchr(); if ('0'<=c && c<='9') { n = 0; do { n *= 10; n += c - '0'; } while ((c = getchr())>='0' && c<='9'); peekc = c; if (a1==0) a1 = zero; if (minus<0) n = -n; a1 += n; minus = 0; continue; } relerr = 0; if (a1 || minus) relerr++; switch(c) { case ' ': case '\t': continue; case '+': minus++; if (a1==0) a1 = dot; continue; case '-': case '^': minus--; if (a1==0) a1 = dot; continue; case '?': case '/': compile(c); a1 = dot; for (;;) { if (c=='/') { a1++; if (a1 > dol) a1 = zero; } else { a1--; if (a1 < zero) a1 = dol; } if (execute(0, a1)) break; if (a1==dot) error(Q); } break; case '$': a1 = dol; break; case '.': a1 = dot; break; case '\'': if ((c = getchr()) < 'a' || c > 'z') error(Q); for (a1=zero; a1<=dol; a1++) if (names[c-'a'] == (*a1 & ~01)) break; break; default: peekc = c; if (a1==0) return(0); a1 += minus; if (a1dol) error(Q); return(a1); } if (relerr) error(Q); } } setdot() { if (addr2 == 0) addr1 = addr2 = dot; if (addr1 > addr2) error(Q); } setall() { if (addr2==0) { addr1 = zero+1; addr2 = dol; if (dol==zero) addr1 = zero; } setdot(); } setnoaddr() { if (addr2) error(Q); } nonzero() { if (addr1<=zero || addr2>dol) error(Q); } newline() { register c; if ((c = getchr()) == '\n') return; if (c=='p' || c=='l') { pflag++; if (c=='l') listf++; if (getchr() == '\n') return; } error(Q); } filename(comm) { register char *p1, *p2; register c; count = 0; c = getchr(); if (c=='\n' || c==EOF) { p1 = savedfile; if (*p1==0 && comm!='f') error(Q); p2 = file; while (*p2++ = *p1++) ; return; } if (c!=' ') error(Q); while ((c = getchr()) == ' ') ; if (c=='\n') error(Q); p1 = file; do { *p1++ = c; if (c==' ' || c==EOF) error(Q); } while ((c = getchr()) != '\n'); *p1++ = 0; if (savedfile[0]==0 || comm=='e' || comm=='f') { p1 = savedfile; p2 = file; while (*p1++ = *p2++) ; } } exfile() { close(io); io = -1; if (vflag) { putd(); putchr('\n'); } } onintr() { signal(SIGINT, onintr); putchr('\n'); lastc = '\n'; error(Q); } onhup() { signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); if (dol > zero) { addr1 = zero+1; addr2 = dol; io = creat("ed.hup", 0666); if (io > 0) putfile(); } fchange = 0; quit(); } error(s) char *s; { register c; wrapp = 0; listf = 0; putchr('?'); puts(s); count = 0; lseek(0, (long)0, 2); pflag = 0; if (globp) lastc = '\n'; globp = 0; peekc = lastc; if(lastc) while ((c = getchr()) != '\n' && c != EOF) ; if (io > 0) { close(io); io = -1; } longjmp(savej, 1); } getchr() { char c; if (lastc=peekc) { peekc = 0; return(lastc); } if (globp) { if ((lastc = *globp++) != 0) return(lastc); globp = 0; return(EOF); } if (read(0, &c, 1) <= 0) return(lastc = EOF); lastc = c&0177; return(lastc); } gettty() { register c; register char *gf; register char *p; p = linebuf; gf = globp; while ((c = getchr()) != '\n') { if (c==EOF) { if (gf) peekc = c; return(c); } if ((c &= 0177) == 0) continue; *p++ = c; if (p >= &linebuf[LBSIZE-2]) error(Q); } *p++ = 0; if (linebuf[0]=='.' && linebuf[1]==0) return(EOF); return(0); } getfile() { register c; register char *lp, *fp; lp = linebuf; fp = nextip; do { if (--ninbuf < 0) { if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0) return(EOF); fp = genbuf; while(fp < &genbuf[ninbuf]) { if (*fp++ & 0200) { break; } } fp = genbuf; } c = *fp++; if (c=='\0') continue; if (c&0200 || lp >= &linebuf[LBSIZE]) { lastc = '\n'; error(Q); } *lp++ = c; count++; } while (c != '\n'); *--lp = 0; nextip = fp; return(0); } putfile() { int *a1, n; register char *fp, *lp; register nib; nib = 512; fp = genbuf; a1 = addr1; do { lp = getline(*a1++); for (;;) { if (--nib < 0) { n = fp-genbuf; if(write(io, genbuf, n) != n) { puts(WRERR); error(Q); } nib = 511; fp = genbuf; } count++; if ((*fp++ = *lp++) == 0) { fp[-1] = '\n'; break; } } } while (a1 <= addr2); n = fp-genbuf; if(write(io, genbuf, n) != n) { puts(WRERR); error(Q); } } append(f, a) int *a; int (*f)(); { register *a1, *a2, *rdot; int nline, tl; nline = 0; dot = a; while ((*f)() == 0) { if ((dol-zero)+1 >= nlall) { int *ozero = zero; nlall += 512; if ((zero = (int *)realloc((char *)zero, nlall*sizeof(int)))==NULL) { lastc = '\n'; zero = ozero; error("MEM?"); } dot += zero - ozero; dol += zero - ozero; } tl = putline(); nline++; a1 = ++dol; a2 = a1+1; rdot = ++dot; while (a1 > rdot) *--a2 = *--a1; *rdot = tl; } return(nline); } callunix() { register (*savint)(), pid, rpid; int retcode; setnoaddr(); if ((pid = fork()) == 0) { signal(SIGHUP, oldhup); signal(SIGQUIT, oldquit); execl("/bin/sh", "sh", "-t", 0); exit(0100); } savint = signal(SIGINT, SIG_IGN); while ((rpid = wait(&retcode)) != pid && rpid != -1) ; signal(SIGINT, savint); puts("!"); } quit() { if (vflag && fchange && dol!=zero) { fchange = 0; error(Q); } unlink(tfname); exit(0); } delete() { setdot(); newline(); nonzero(); rdelete(addr1, addr2); } rdelete(ad1, ad2) int *ad1, *ad2; { register *a1, *a2, *a3; a1 = ad1; a2 = ad2+1; a3 = dol; dol -= a2 - a1; do { *a1++ = *a2++; } while (a2 <= a3); a1 = ad1; if (a1 > dol) a1 = dol; dot = a1; fchange = 1; } gdelete() { register *a1, *a2, *a3; a3 = dol; for (a1=zero+1; (*a1&01)==0; a1++) if (a1>=a3) return; for (a2=a1+1; a2<=a3;) { if (*a2&01) { a2++; dot = a1; } else *a1++ = *a2++; } dol = a1-1; if (dot>dol) dot = dol; fchange = 1; } char * getline(tl) { register char *bp, *lp; register nl; lp = linebuf; bp = getblock(tl, READ); nl = nleft; tl &= ~0377; while (*lp++ = *bp++) if (--nl == 0) { bp = getblock(tl+=0400, READ); nl = nleft; } return(linebuf); } putline() { register char *bp, *lp; register nl; int tl; fchange = 1; lp = linebuf; tl = tline; bp = getblock(tl, WRITE); nl = nleft; tl &= ~0377; while (*bp = *lp++) { if (*bp++ == '\n') { *--bp = 0; linebp = lp; break; } if (--nl == 0) { bp = getblock(tl+=0400, WRITE); nl = nleft; } } nl = tline; tline += (((lp-linebuf)+03)>>1)&077776; return(nl); } char * getblock(atl, iof) { extern read(), write(); register bno, off; register char *p1, *p2; register int n; bno = (atl>>8)&0377; off = (atl<<1)&0774; if (bno >= 255) { lastc = '\n'; error(T); } nleft = 512 - off; if (bno==iblock) { ichanged |= iof; return(ibuff+off); } if (bno==oblock) return(obuff+off); if (iof==READ) { if (ichanged) { blkio(iblock, ibuff, write); } ichanged = 0; iblock = bno; blkio(bno, ibuff, read); return(ibuff+off); } if (oblock>=0) { blkio(oblock, obuff, write); } oblock = bno; return(obuff+off); } blkio(b, buf, iofcn) char *buf; int (*iofcn)(); { lseek(tfile, (long)b<<9, 0); if ((*iofcn)(tfile, buf, 512) != 512) { error(T); } } init() { register *markp; close(tfile); tline = 2; for (markp = names; markp < &names[26]; ) *markp++ = 0; subnewa = 0; anymarks = 0; iblock = -1; oblock = -1; ichanged = 0; close(creat(tfname, 0600)); tfile = open(tfname, 2); dot = dol = zero; } global(k) { register char *gp; register c; register int *a1; char globuf[GBSIZE]; if (globp) error(Q); setall(); nonzero(); if ((c=getchr())=='\n') error(Q); compile(c); gp = globuf; while ((c = getchr()) != '\n') { if (c==EOF) error(Q); if (c=='\\') { c = getchr(); if (c!='\n') *gp++ = '\\'; } *gp++ = c; if (gp >= &globuf[GBSIZE-2]) error(Q); } *gp++ = '\n'; *gp++ = 0; for (a1=zero; a1<=dol; a1++) { *a1 &= ~01; if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k) *a1 |= 01; } /* * Special case: g/.../d (avoid n^2 algorithm) */ if (globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') { gdelete(); return; } for (a1=zero; a1<=dol; a1++) { if (*a1 & 01) { *a1 &= ~01; dot = a1; globp = globuf; commands(); a1 = zero; } } } join() { register char *gp, *lp; register *a1; gp = genbuf; for (a1=addr1; a1<=addr2; a1++) { lp = getline(*a1); while (*gp = *lp++) if (gp++ >= &genbuf[LBSIZE-2]) error(Q); } lp = linebuf; gp = genbuf; while (*lp++ = *gp++) ; *addr1 = putline(); if (addr1= &rhsbuf[LBSIZE/2]) error(Q); } *p++ = 0; if ((peekc = getchr()) == 'g') { peekc = 0; newline(); return(1); } newline(); return(0); } getsub() { register char *p1, *p2; p1 = linebuf; if ((p2 = linebp) == 0) return(EOF); while (*p1++ = *p2++) ; linebp = 0; return(0); } dosub() { register char *lp, *sp, *rp; int c; lp = linebuf; sp = genbuf; rp = rhsbuf; while (lp < loc1) *sp++ = *lp++; while (c = *rp++&0377) { if (c=='&') { sp = place(sp, loc1, loc2); continue; } else if (c&0200 && (c &= 0177) >='1' && c < nbra+'1') { sp = place(sp, braslist[c-'1'], braelist[c-'1']); continue; } *sp++ = c&0177; if (sp >= &genbuf[LBSIZE]) error(Q); } lp = loc2; loc2 = sp - genbuf + linebuf; while (*sp++ = *lp++) if (sp >= &genbuf[LBSIZE]) error(Q); lp = linebuf; sp = genbuf; while (*lp++ = *sp++) ; } char * place(sp, l1, l2) register char *sp, *l1, *l2; { while (l1 < l2) { *sp++ = *l1++; if (sp >= &genbuf[LBSIZE]) error(Q); } return(sp); } move(cflag) { register int *adt, *ad1, *ad2; int getcopy(); setdot(); nonzero(); if ((adt = address())==0) error(Q); newline(); if (cflag) { int *ozero, delta; ad1 = dol; ozero = zero; append(getcopy, ad1++); ad2 = dol; delta = zero - ozero; ad1 += delta; adt += delta; } else { ad2 = addr2; for (ad1 = addr1; ad1 <= ad2;) *ad1++ &= ~01; ad1 = addr1; } ad2++; if (adt= ad2) { dot = adt++; reverse(ad1, ad2); reverse(ad2, adt); reverse(ad1, adt); } else error(Q); fchange = 1; } reverse(a1, a2) register int *a1, *a2; { register int t; for (;;) { t = *--a2; if (a2 <= a1) return; *a2 = *a1; *a1++ = t; } } getcopy() { if (addr1 > addr2) return(EOF); getline(*addr1++); return(0); } compile(aeof) { register eof, c; register char *ep; char *lastep; char bracket[NBRA], *bracketp; int cclcnt; ep = expbuf; eof = aeof; bracketp = bracket; if ((c = getchr()) == eof) { if (*ep==0) error(Q); return; } circfl = 0; nbra = 0; if (c=='^') { c = getchr(); circfl++; } peekc = c; lastep = 0; for (;;) { if (ep >= &expbuf[ESIZE]) goto cerror; c = getchr(); if (c==eof) { if (bracketp != bracket) goto cerror; *ep++ = CEOF; return; } if (c!='*') lastep = ep; switch (c) { case '\\': if ((c = getchr())=='(') { if (nbra >= NBRA) goto cerror; *bracketp++ = nbra; *ep++ = CBRA; *ep++ = nbra++; continue; } if (c == ')') { if (bracketp <= bracket) goto cerror; *ep++ = CKET; *ep++ = *--bracketp; continue; } if (c>='1' && c<'1'+NBRA) { *ep++ = CBACK; *ep++ = c-'1'; continue; } *ep++ = CCHR; if (c=='\n') goto cerror; *ep++ = c; continue; case '.': *ep++ = CDOT; continue; case '\n': goto cerror; case '*': if (lastep==0 || *lastep==CBRA || *lastep==CKET) goto defchar; *lastep |= STAR; continue; case '$': if ((peekc=getchr()) != eof) goto defchar; *ep++ = CDOL; continue; case '[': *ep++ = CCL; *ep++ = 0; cclcnt = 1; if ((c=getchr()) == '^') { c = getchr(); ep[-2] = NCCL; } do { if (c=='\n') goto cerror; if (c=='-' && ep[-1]!=0) { if ((c=getchr())==']') { *ep++ = '-'; cclcnt++; break; } while (ep[-1]=&expbuf[ESIZE]) goto cerror; } } *ep++ = c; cclcnt++; if (ep >= &expbuf[ESIZE]) goto cerror; } while ((c = getchr()) != ']'); lastep[1] = cclcnt; continue; defchar: default: *ep++ = CCHR; *ep++ = c; } } cerror: expbuf[0] = 0; nbra = 0; error(Q); } execute(gf, addr) int *addr; { register char *p1, *p2, c; for (c=0; c= curlp) { if (advance(lp, ep)) return(1); lp -= braelist[i] - braslist[i]; } continue; case CDOT|STAR: curlp = lp; while (*lp++) ; goto star; case CCHR|STAR: curlp = lp; while (*lp++ == *ep) ; ep++; goto star; case CCL|STAR: case NCCL|STAR: curlp = lp; while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))) ; ep += *ep; goto star; star: do { lp--; if (lp==locs) break; if (advance(lp, ep)) return(1); } while (lp > curlp); return(0); default: error(Q); } } backref(i, lp) register i; register char *lp; { register char *bp; bp = braslist[i]; while (*bp++ == *lp++) if (bp >= braelist[i]) return(1); return(0); } cclass(set, c, af) register char *set, c; { register n; if (c==0) return(0); n = *set++; while (--n) if (*set++ == c) return(af); return(!af); } putd() { register r; r = count%10; count /= 10; if (count) putd(); putchr(r + '0'); } puts(sp) register char *sp; { col = 0; while (*sp) putchr(*sp++); putchr('\n'); } char line[70]; char *linp = line; putchr(ac) { register char *lp; register c; lp = linp; c = ac; if (listf) { col++; if (col >= 72) { col = 0; *lp++ = '\\'; *lp++ = '\n'; } if (c=='\t') { c = '>'; goto esc; } if (c=='\b') { c = '<'; esc: *lp++ = '-'; *lp++ = '\b'; *lp++ = c; goto out; } if (c<' ' && c!= '\n') { *lp++ = '\\'; *lp++ = (c>>3)+'0'; *lp++ = (c&07)+'0'; col += 2; goto out; } } *lp++ = c; out: if(c == '\n' || lp >= &line[64]) { linp = line; write(1, line, lp-line); return; } linp = lp; } ((lp-linebuf)+03)>>1)&077776; return(nl); } char * getblock(atl, iof) { extern read(), write(); register bno, off; register char *p1, *p2; register int n; bno = (atl>>8)&0377; off = (atl<<1)&0774; if (bno >= 255) { lastc = '\n'; error(T); } nleft = 512 - off; bin/ar/ 755 0 12 0 6024535736 5127 bin/ar/Makefile 644 0 12 1400 5511170536 6640 # @(#)Makefile 5.8 (Berkeley) 3/10/91 CFLAGS= -I. -O LFLAGS= -z SRCS= append.c ar.c archive.c contents.c delete.c extract.c misc.c \ move.c print.c replace.c EXTRASRCS= strmode.c OBJS= append.o ar.o archive.o contents.o delete.o extract.o misc.o \ move.o print.o replace.o EXTRAOBJ= strmode.o # strftime.o ctime.o all: ar ar.1.0 ar.5.0 ar: ${OBJS} ${EXTRAOBJ} cc ${LFLAGS} -o ar ${OBJS} ${EXTRAOBJ} ar.1.0: ar.1 nroff -man ar.1 > ar.1.0 ar.5.0: ar.5.5 nroff -man ar.5.5 > ar.5.0 install: install -s -m 755 ar ${DESTDIR}/bin/ar install -c -o bin -g bin -m 444 ar.1.0 ${DESTDIR}/usr/man/cat1/ar.0 install -c -o bin -g bin -m 444 ar.5.0 ${DESTDIR}/usr/man/cat5/ar.0 lint: lint -havx -I. ${SRCS} ${EXTRASRCS} clean: rm -f core ar *.o ar.1.0 ar.5.0 || *lastep==CKET) goto defchar; *lastep |= STAR; continue; case '$': if ((peekc=getchr()) != eof) goto defchar; *ep++ = CDOL; continue; case '[': *ep++ = CCL; *ep++ = 0; cclcnt = 1; if ((c=getchr()) == '^') { c bin/ar/append.c 644 0 12 6034 5450760366 6633 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)append.c 5.6 (Berkeley) 3/12/91"; #endif #include #include #include #include #include #include #include #include "archive.h" #include "extern.h" extern char *archive; /* archive name */ extern int errno; /* * append -- * Append files to the archive - modifies original archive or creates * a new archive if named archive does not exist. */ append(argv) char **argv; { register int fd, afd; register char *file; struct stat sb; CF cf; int eval; afd = open_archive(O_CREAT|O_RDWR); if (lseek(afd, (off_t)0, L_XTND) == (off_t)-1) error(archive); /* Read from disk, write to an archive; pad on write. */ SETCF(0, 0, afd, archive, WPAD); for (eval = 0; file = *argv++;) { if ((fd = open(file, O_RDONLY)) < 0) { (void)fprintf(stderr, "ar: %s: %s.\n", file, strerror(errno)); eval = 1; continue; } if (options & AR_V) (void)printf("q - %s\n", file); cf.rfd = fd; cf.rname = file; put_arobj(&cf, &sb); (void)close(fd); } close_archive(afd); return(eval); } reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contribin/ar/ar.1 644 0 12 21574 5450741603 5723 .\" Copyright (c) 1990 The Regents of the University of California. .\" All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Hugh Smith at The University of Guelph. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)ar.1 6.10 (Berkeley) 3/21/91 .\" .TH AR 1 "March 21, 1991" .AT 3 .SH NAME ar \- create and maintain library archives .SH SYNOPSIS .nf .ft B ar -d [-Tv] archive file ... ar -m [-Tv] archive file ... ar -m [-abiTv] position archive file ... ar -p [-Tv] archive [file ...] ar -q [-cTv] archive file ... ar -r [-cuTv] archive file ... ar -r [-abciuTv] position archive file ... ar -t [-Tv] archive [file ...] ar -x [-ouTv] archive [file ...] .fi .ft R .SH DESCRIPTION The .I ar utility creates and maintains groups of files combined into an archive. Once an archive has been created, new files can be added and existing files can be extracted, deleted, or replaced. .PP Files are named in the archive by a single component, i.e., if a file referenced by a path containing a slash (``/'') is archived it will be named by the last component of that path. When matching paths listed on the command line against file names stored in the archive, only the last component of the path will be compared. .PP All informational and error messages use the path listed on the command line, if any was specified, otherwise the name in the archive is used. If multiple files in the archive have the same name, and paths are listed on the command line to ``select'' archive files for an operation, only the .B first file with a matching name will be selected. .PP The normal use of .I ar is for the creation and maintenance of libraries suitable for use with the loader (see .IR ld (1)) although it is not restricted to this purpose. The options are as follows: .TP \-a A positioning modifier used with the options \-r and \-m. The files are entered or moved .B after the archive member .IR position , which must be specified. .TP \-b A positioning modifier used with the options \-r and \-m. The files are entered or moved .B before the archive member .IR position , which must be specified. .TP \-c Whenever an archive is created, an informational message to that effect is written to standard error. If the \-c option is specified, .I ar creates the archive silently. .TP \-d Delete the specified archive files. .TP \-i Identical to the \-b option. .TP \-m Move the specified archive files within the archive. If one of the options \-a, \-b or \-i are specified, the files are moved before or after the .I position file in the archive. If none of those options are specified, the files are moved to the end of the archive. .TP \-o Set the access and modification times of extracted files to the modification time of the file when it was entered into the archive. This will fail if the user is not the owner of the extracted file or the super-user. .TP \-p Write the contents of the specified archive files to the standard output. If no files are specified, the contents of all the files in the archive are written in the order they appear in the archive. .TP \-q (Quickly) append the specified files to the archive. If the archive does not exist a new archive file is created. Much faster than the \-r option, when creating a large archive piece-by-piece, as no checking is done to see if the files already exist in the archive. .TP \-r Replace or add the specified files to the archive. If the archive does not exist a new archive file is created. Files that replace existing files do not change the order of the files within the archive. New files are appended to the archive unless one of the options \-a, \-b or \-i is specified. .TP \-T Select and/or name archive members using only the first fifteen characters of the archive member or command line file name. The historic archive format had sixteen bytes for the name, but some historic archiver and loader implementations were unable to handle names that used the entire space. This means that file names that are not unique in their first fifteen characters can subsequently be confused. A warning message is printed to the standard error output if any file names are truncated. (See .IR ar (5) for more information.) .TP \-t List the specified files in the order in which they appear in the archive, each on a separate line. If no files are specified, all files in the archive are listed. .TP \-u Update files. When used with the \-r option, files in the archive will be replaced only if the disk file has a newer modification time than the file in the archive. When used with the \-x option, files in the archive will be extracted only if the archive file has a newer modification time than the file on disk. .TP \-v Provide verbose output. When used with the \-d, \-m, \-q or \-x options, .I ar gives a file-by-file description of the archive modification. This description consists of three, white-space separated fields: the option letter, a dash (``-'') and the file name. When used with the \-r option, .I ar displays the description as above, but the initial letter is an ``a'' if the file is added to the archive and an ``r'' if the file replaces a file already in the archive. .IP When used with the \-p option, the name of each printed file is written to the standard output before the contents of the file, preceded by a single newline character, and followed by two newline characters, enclosed in less-than (``<'') and greater-than (``>'') characters. .IP When used with the \-t option, .I ar displays an ``ls -l'' style listing of information about the members of the archive. This listing consists of eight, white-space separated fields: the file permissions (see .IR strmode (3)), the decimal user and group ID's, separated by a single slash (``/''), the file size (in bytes), the file modification time (in the .IR date (1) format ``%b %e %H:%M %Y''), and the name of the file. .TP \-x Extract the specified archive members into the files named by the command line arguments. If no members are specified, all the members of the archive are extracted into the current directory. .IP If the file does not exist, it is created; if it does exist, the owner and group will be unchanged. The file access and modification times are the time of the extraction (but see the \-o option). The file permissions will be set to those of the file when it was entered into the archive; this will fail if the user is not the owner of the extracted file or the super-user. .PP The .I ar utility exits 0 on success, and >0 if an error occurs. .SH ENVIRONMENT .TP TMPDIR The pathname of the directory to use when creating temporary files. .SH FILES .TP 14 /tmp default temporary file directory .TP 14 ar.XXXXXX temporary file names .SH COMPATIBILITY By default, .I ar writes archives that may be incompatible with historic archives, as the format used for storing archive members with names longer than fifteen characters has changed. This implementation of .I ar is backward compatible with previous versions of .I ar in that it can read and write (using the \-T option) historic archives. The \-T option is provided for compatibility only, and will be deleted in a future release. See .IR ar (5) for more information. .SH STANDARDS The .I ar utility is expected to offer a superset of the POSIX 1003.2 functionality. .SH "SEE ALSO" ld(1), ranlib(1), strmode(3), ar(5) ibutions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. bin/ar/ar.5.5 644 0 12 13067 5450741606 6073 .\" Copyright (c) 1990, 1991 The Regents of the University of California. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)ar.5.5 6.3 (Berkeley) 5/10/91 .\" 6.3.1 (2.11BSD) 9/24/93 .\" .TH AR 5 "September 24, 1993" .UC 2 .SH NAME ar \- archive (library) file format .SH SYNOPSIS #include .SH DESCRIPTION The archive command .I ar combines several files into one. Archives are mainly used as libraries of object files intended to be loaded using the link-editor .IR ld (1). .PP A file created with .I ar begins with the ``magic'' string "!\en". The rest of the archive is made up of objects, each of which is composed of a header for a file, a possible file name, and the file contents. The header is portable between machine architectures, and, if the file contents are printable, the archive is itself printable. .PP The header is made up of six variable length ASCII fields, followed by a two character trailer. The fields are the object name (16 characters), the file last modification time (12 characters), the user and group id's (each 6 characters), the file mode (8 characters) and the file size (10 characters). All numeric fields are in decimal, except for the file mode which is in octal. .PP The modification time is the file .I st_mtime field, i.e., .B CUT seconds since the epoch. The user and group id's are the file .I st_uid and .I st_gid fields. The file mode is the file .I st_mode field. The file size is the file .I st_size field. The two-byte trailer is the string "\`\en". .PP Only the name field has any provision for overflow. If any file name is more than 16 characters in length or contains an embedded space, the string "#1/" followed by the ASCII length of the name is written in the name field. The file size (stored in the archive header) is incremented by the length of the name. The name is then written immediately following the archive header. .PP Any unused characters in any of these fields are written as space characters. If any fields are their particular maximum number of characters in length, there will be no separation between the fields. .PP Objects in the archive are always an even number of bytes long; files which are an odd number of bytes long are padded with a newline (``\en'') character, although the size in the header does not reflect this. .SH SEE ALSO .IR ar (1), .IR stat (2) .SH HISTORY There have been at least four .I ar formats. The first was denoted by the leading ``magic'' number 0177555 (stored as type int). These archives were almost certainly created on a 16-bit machine, and contain headers made up of five fields. The fields are the object name (8 characters), the file last modification time (type long), the user id (type char), the file mode (type char) and the file size (type unsigned int). Files were padded to an even number of bytes. .PP The second was denoted by the leading ``magic'' number 0177545 (stored as type int). These archives may have been created on either 16 or 32-bit machines, and contain headers made up of six fields. The fields are the object name (14 characters), the file last modification time (type long), the user and group id's (each type char), the file mode (type int) and the file size (type long). Files were padded to an even number of bytes. For more information on converting from this format see .IR arcv (8). .PP The current archive format (without support for long character names and names with embedded spaces) was introduced in 4.0BSD. The headers were the same as the current format, with the exception that names longer than 16 characters were truncated, and names with embedded spaces (and often trailing spaces) were not supported. It has been extended for these reasons, as described above. This format is under development. .SH COMPATIBILITY No archive format is currently specified by any standard. AT&T System V UNIX has historically distributed archives in a different format from all of the above. pace. This means that file names that are not unique in their first fifteen characters can subsequently be confused. A warning message is printed to the standard error output if any file names are truncated. (See .IR ar (5) for more information.) .TP \-t List the specified files in the order in which they appear in the archive, each on a separate line. If no files are specified, all files in the archive are listed. .TP \-u Update files. When used with tbin/ar/ar.c 644 0 12 14671 5450741615 6010 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)ar.c 5.11 (Berkeley) 3/21/91"; #endif #include #include #include #include #include #include #include #include "archive.h" #include "extern.h" extern char *malloc(); extern int errno; CHDR chdr; u_int options; char *archive, *envtmp, *posarg, *posname; static void badoptions(), usage(); /* * main -- * main basically uses getopt to parse options and calls the appropriate * functions. Some hacks that let us be backward compatible with 4.3 ar * option parsing and sanity checking. */ main(argc, argv) int argc; char **argv; { extern int optind; int c; char *p; int (*fcall)(), append(), contents(), delete(), extract(), move(), print(), replace(); if (argc < 3) usage(); /* * Historic versions didn't require a '-' in front of the options. * Fix it, if necessary. */ if (*argv[1] != '-') { if (!(p = malloc((u_int)(strlen(argv[1]) + 2)))) { (void)fprintf(stderr, "ar: %s.\n", strerror(errno)); exit(1); } *p = '-'; (void)strcpy(p + 1, argv[1]); argv[1] = p; } while ((c = getopt(argc, argv, "abcdilmopqrTtuvx")) != EOF) { switch(c) { case 'a': options |= AR_A; break; case 'b': case 'i': options |= AR_B; break; case 'c': options |= AR_C; break; case 'd': options |= AR_D; fcall = delete; break; case 'l': /* not documented, compatibility only */ envtmp = "."; break; case 'm': options |= AR_M; fcall = move; break; case 'o': options |= AR_O; break; case 'p': options |= AR_P; fcall = print; break; case 'q': options |= AR_Q; fcall = append; break; case 'r': options |= AR_R; fcall = replace; break; case 'T': options |= AR_TR; break; case 't': options |= AR_T; fcall = contents; break; case 'u': options |= AR_U; break; case 'v': options |= AR_V; break; case 'x': options |= AR_X; fcall = extract; break; default: usage(); } } argv += optind; argc -= optind; /* One of -dmpqrtx required. */ if (!(options & (AR_D|AR_M|AR_P|AR_Q|AR_R|AR_T|AR_X))) { (void)fprintf(stderr, "ar: one of options -dmpqrtx is required.\n"); usage(); } /* Only one of -a and -bi allowed. */ if (options & AR_A && options & AR_B) { (void)fprintf(stderr, "ar: only one of -a and -[bi] options allowed.\n"); usage(); } /* -ab require a position argument. */ if (options & (AR_A|AR_B)) { if (!(posarg = *argv++)) { (void)fprintf(stderr, "ar: no position operand specified.\n"); usage(); } posname = rname(posarg); } /* -d only valid with -Tv. */ if (options & AR_D && options & ~(AR_D|AR_TR|AR_V)) badoptions("-d"); /* -m only valid with -abiTv. */ if (options & AR_M && options & ~(AR_A|AR_B|AR_M|AR_TR|AR_V)) badoptions("-m"); /* -p only valid with -Tv. */ if (options & AR_P && options & ~(AR_P|AR_TR|AR_V)) badoptions("-p"); /* -q only valid with -cTv. */ if (options & AR_Q && options & ~(AR_C|AR_Q|AR_TR|AR_V)) badoptions("-q"); /* -r only valid with -abcuTv. */ if (options & AR_R && options & ~(AR_A|AR_B|AR_C|AR_R|AR_U|AR_TR|AR_V)) badoptions("-r"); /* -t only valid with -Tv. */ if (options & AR_T && options & ~(AR_T|AR_TR|AR_V)) badoptions("-t"); /* -x only valid with -ouTv. */ if (options & AR_X && options & ~(AR_O|AR_U|AR_TR|AR_V|AR_X)) badoptions("-x"); if (!(archive = *argv++)) { (void)fprintf(stderr, "ar: no archive specified.\n"); usage(); } /* -dmqr require a list of archive elements. */ if (options & (AR_D|AR_M|AR_Q|AR_R) && !*argv) { (void)fprintf(stderr, "ar: no archive members specified.\n"); usage(); } exit((*fcall)(argv)); } static void badoptions(arg) char *arg; { (void)fprintf(stderr, "ar: illegal option combination for %s.\n", arg); usage(); } static void usage() { (void)fprintf(stderr, "usage: ar -d [-Tv] archive file ...\n"); (void)fprintf(stderr, "\tar -m [-Tv] archive file ...\n"); (void)fprintf(stderr, "\tar -m [-abiTv] position archive file ...\n"); (void)fprintf(stderr, "\tar -p [-Tv] archive [file ...]\n"); (void)fprintf(stderr, "\tar -q [-cTv] archive file ...\n"); (void)fprintf(stderr, "\tar -r [-cuTv] archive file ...\n"); (void)fprintf(stderr, "\tar -r [-abciuTv] position archive file ...\n"); (void)fprintf(stderr, "\tar -t [-Tv] archive [file ...]\n"); (void)fprintf(stderr, "\tar -x [-ouTv] archive [file ...]\n"); exit(1); } he header does not reflect this. .SH SEE ALSO .IR ar (1), .IR stat (2) bin/ar/archive.c 644 0 12 21073 5450755446 7030 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)archive.c 5.7 (Berkeley) 3/21/91"; #endif #include #include #include #include #include #include #include #include #include "archive.h" #include "extern.h" extern CHDR chdr; /* converted header */ extern char *archive; /* archive name */ extern int errno; typedef struct ar_hdr HDR; static char hb[sizeof(HDR) + 1]; /* real header */ open_archive(mode) int mode; { int created, fd, nr; char buf[SARMAG]; created = 0; if (mode & O_CREAT) { mode |= O_EXCL; if ((fd = open(archive, mode, 0666)) >= 0) { /* POSIX.2 puts create message on stderr. */ if (!(options & AR_C)) (void)fprintf(stderr, "ar: creating archive %s.\n", archive); created = 1; goto opened; } if (errno != EEXIST) error(archive); mode &= ~O_EXCL; } if ((fd = open(archive, mode, 0666)) < 0) error(archive); /* * Attempt to place a lock on the opened file - if we get an * error then someone is already working on this library (or * it's going across NFS). */ opened: if (flock(fd, LOCK_EX|LOCK_NB) && errno != EOPNOTSUPP) error(archive); /* * If not created, O_RDONLY|O_RDWR indicates that it has to be * in archive format. */ if (!created && ((mode & 3) == O_RDONLY || (mode & 3) == O_RDWR)) { if ((nr = read(fd, buf, SARMAG) != SARMAG)) { if (nr >= 0) badfmt(); error(archive); } else if (bcmp(buf, ARMAG, SARMAG)) badfmt(); } else if (write(fd, ARMAG, SARMAG) != SARMAG) error(archive); return(fd); } void close_archive(fd) int fd; { (void)close(fd); /* Implicit unlock. */ } /* Convert ar header field to an integer. */ #define AR_ATOI(from, to, len, base) { \ bcopy(from, buf, len); \ buf[len] = '\0'; \ to = strtol(buf, (char **)NULL, base); \ } /* * get_arobj -- * read the archive header for this member */ get_arobj(fd) int fd; { struct ar_hdr *hdr; register int len, nr; register char *p; char buf[20]; nr = read(fd, hb, sizeof(HDR)); if (nr != sizeof(HDR)) { if (!nr) return(0); if (nr < 0) error(archive); badfmt(); } hdr = (struct ar_hdr *)hb; if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1)) badfmt(); /* Convert the header into the internal format. */ #define DECIMAL 10 #define OCTAL 8 AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL); AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL); AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL); AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL); AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL); /* Leading spaces should never happen. */ if (hdr->ar_name[0] == ' ') badfmt(); /* * Long name support. Set the "real" size of the file, and the * long name flag/size. */ if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) { chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1); if (len <= 0 || len > MAXNAMLEN) badfmt(); nr = read(fd, chdr.name, (size_t)len); if (nr != len) { if (nr < 0) error(archive); badfmt(); } chdr.name[len] = 0; chdr.size -= len; } else { chdr.lname = 0; bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name)); /* Strip trailing spaces, null terminate. */ for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p); *++p = '\0'; } return(1); } static int already_written; /* * put_arobj -- * Write an archive member to a file. */ put_arobj(cfp, sb) CF *cfp; struct stat *sb; { register int lname; register char *name; struct ar_hdr *hdr; off_t size; /* * If passed an sb structure, reading a file from disk. Get stat(2) * information, build a name and construct a header. (Files are named * by their last component in the archive.) If not, then just write * the last header read. */ if (sb) { name = rname(cfp->rname); (void)fstat(cfp->rfd, sb); /* * If not truncating names and the name is too long or contains * a space, use extended format 1. */ lname = strlen(name); if (options & AR_TR) { if (lname > OLDARMAXNAME) { (void)fflush(stdout); (void)fprintf(stderr, "ar: warning: %s truncated to %.*s\n", name, OLDARMAXNAME, name); (void)fflush(stderr); } (void)sprintf(hb, HDR3, name, sb->st_mtime, sb->st_uid, sb->st_gid, sb->st_mode, sb->st_size, ARFMAG); lname = 0; } else if (lname > sizeof(hdr->ar_name) || index(name, ' ')) (void)sprintf(hb, HDR1, AR_EFMT1, lname, sb->st_mtime, sb->st_uid, sb->st_gid, sb->st_mode, sb->st_size + lname, ARFMAG); else { lname = 0; (void)sprintf(hb, HDR2, name, sb->st_mtime, sb->st_uid, sb->st_gid, sb->st_mode, sb->st_size, ARFMAG); } size = sb->st_size; } else { lname = chdr.lname; name = chdr.name; size = chdr.size; } if (write(cfp->wfd, hb, sizeof(HDR)) != sizeof(HDR)) error(cfp->wname); if (lname) { if (write(cfp->wfd, name, (size_t)lname) != lname) error(cfp->wname); already_written = lname; } copy_ar(cfp, size); already_written = 0; } /* * copy_ar -- * Copy size bytes from one file to another - taking care to handle the * extra byte (for odd size files) when reading archives and writing an * extra byte if necessary when adding files to archive. The length of * the object is the long name plus the object itself; the variable * already_written gets set if a long name was written. * * The padding is really unnecessary, and is almost certainly a remnant * of early archive formats where the header included binary data which * a PDP-11 required to start on an even byte boundary. (Or, perhaps, * because 16-bit word addressed copies were faster?) Anyhow, it should * have been ripped out long ago. */ copy_ar(cfp, size) CF *cfp; off_t size; { static char pad = '\n'; off_t sz; register int from, nr, nw, off, to; #ifdef pdp11 char buf[2*1024]; #else char buf[8*1024]; #endif if (!(sz = size)) return; from = cfp->rfd; to = cfp->wfd; while (sz && (nr = read(from, buf, (size_t)(MIN(sz, sizeof(buf))))) > 0) { sz -= nr; for (off = 0; off < nr; nr -= off, off += nw) if ((nw = write(to, buf + off, (size_t)nr)) < 0) error(cfp->wname); } if (sz) { if (nr == 0) badfmt(); error(cfp->rname); } if (cfp->flags & RPAD && size & 1 && (nr = read(from, buf, 1)) != 1) { if (nr == 0) badfmt(); error(cfp->rname); } if (cfp->flags & WPAD && (size + already_written) & 1 && write(to, &pad, 1) != 1) error(cfp->wname); } /* * skip_arobj - * Skip over an object -- taking care to skip the pad bytes. */ void skip_arobj(fd) int fd; { off_t len; len = chdr.size + (chdr.size + chdr.lname & 1); if (lseek(fd, len, L_INCR) == (off_t)-1) error(archive); } != EOPNOTSUPP) error(archive); /* * If not created, O_RDONLY|O_RDWR indicates that it has to be * in archive format. */ if (!created && ((mode & 3) == O_RDONLY || (mode & 3) == O_RDWR)) { if ((nr = read(fd, buf, SARMAG) != SARMAG)) { if (nr >= 0) badfmt(); error(archive); } else if (bcmp(buf, ARMAG, SARMAG)) badfmt(); } else if (write(fd, ARMAG, SARMAG) != SARMAG) error(archive); return(fd); } void close_archibin/ar/archive.h 644 0 12 6577 5450741634 7023 /*- * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)archive.h 5.8 (Berkeley) 4/12/91 */ /* Ar(1) options. */ #define AR_A 0x0001 #define AR_B 0x0002 #define AR_C 0x0004 #define AR_D 0x0008 #define AR_M 0x0010 #define AR_O 0x0020 #define AR_P 0x0040 #define AR_Q 0x0080 #define AR_R 0x0100 #define AR_T 0x0200 #define AR_TR 0x0400 #define AR_U 0x0800 #define AR_V 0x1000 #define AR_X 0x2000 extern u_int options; /* Set up file copy. */ #define SETCF(from, fromname, to, toname, pad) { \ cf.rfd = from; \ cf.rname = fromname; \ cf.wfd = to; \ cf.wname = toname; \ cf.flags = pad; \ } /* File copy structure. */ typedef struct { int rfd; /* read file descriptor */ char *rname; /* read name */ int wfd; /* write file descriptor */ char *wname; /* write name */ #define NOPAD 0x00 /* don't pad */ #define RPAD 0x01 /* pad on reads */ #define WPAD 0x02 /* pad on writes */ u_int flags; /* pad flags */ } CF; /* Header structure internal format. */ typedef struct { off_t size; /* size of the object in bytes */ long date; /* date */ int lname; /* size of the long name in bytes */ int gid; /* group */ int uid; /* owner */ u_short mode; /* permissions */ char name[MAXNAMLEN + 1]; /* name */ } CHDR; /* Header format strings. */ #define HDR1 "%s%-13d%-12ld%-6u%-6u%-8o%-10ld%2s" #define HDR2 "%-16.16s%-12ld%-6u%-6u%-8o%-10ld%2s" #define OLDARMAXNAME 15 #define HDR3 "%-16.15s%-12ld%-6u%-6u%-8o%-10ld%2s" void close_archive(); void skip_arobj(); int copy_ar(); int get_arobj(); int open_archive(); int put_arobj(); , ARMAG, SARMAG)) badfmt(); } else if (write(fd, ARMAG, SARMAG) != SARMAG) error(archive); return(fd); } void close_archibin/ar/contents.c 644 0 12 7307 5450756720 7224 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)contents.c 5.6 (Berkeley) 3/12/91"; #endif #include #include #include #include #include #include #include #include #include #include "archive.h" #include "extern.h" extern CHDR chdr; /* converted header */ extern char *archive; /* archive name */ /* * contents -- * Handles t[v] option - opens the archive and then reads headers, * skipping member contents. */ contents(argv) register char **argv; { register int afd, all; struct tm *tp; char *file, buf[25]; afd = open_archive(O_RDONLY); for (all = !*argv; get_arobj(afd);) { if (all) file = chdr.name; else if (!(file = files(argv))) goto next; if (options & AR_V) { (void)strmode(chdr.mode, buf); (void)printf("%s %6d/%-6d %8ld ", buf + 1, chdr.uid, chdr.gid, chdr.size); tp = localtime(&chdr.date); #ifdef bloat (void)strftime(buf, sizeof(buf), "%b %e %H:%M %Y", tp); (void)printf("%s %s\n", buf, file); #else { /* * Bloat avoidance alert! Doing the date this way saves dragging in not only * strftime() but mktime() and ctime() for a savings of over 8kb. God, those * leap seconds or whatever don't come cheap, the old (4.3BSD) timezone code * was big enough but this new stuff (posix?) is horrid. */ static char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; (void)printf("%s %02d %02d:%02d %4d %s\n", months[tp->tm_mon], tp->tm_mday, tp->tm_hour, tp->tm_min, 1900+tp->tm_year, file); } #endif } else (void)printf("%s\n", file); if (!all && !*argv) break; next: skip_arobj(afd); } close_archive(afd); if (*argv) { orphans(argv); return(1); } return(0); } , WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)contents.c 5.6 (Berkeley) 3/12/91"; #endif #bin/ar/delete.c 644 0 12 6224 5450741644 6625 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)delete.c 5.6 (Berkeley) 3/12/91"; #endif #include #include #include #include #include #include #include #include "archive.h" #include "extern.h" #include "pathnames.h" extern CHDR chdr; /* converted header */ extern char *archive; /* archive name */ extern char *tname; /* temporary file "name" */ /*- * delete -- * Deletes named members from the archive. */ delete(argv) register char **argv; { CF cf; off_t size; int afd, tfd; char *file; afd = open_archive(O_RDWR); tfd = tmp(); /* Read and write to an archive; pad on both. */ SETCF(afd, archive, tfd, tname, RPAD|WPAD); while (get_arobj(afd)) { if (*argv && (file = files(argv))) { if (options & AR_V) (void)printf("d - %s\n", file); skip_arobj(afd); continue; } put_arobj(&cf, (struct stat *)NULL); } size = lseek(tfd, (off_t)0, L_INCR); (void)lseek(tfd, (off_t)0, L_SET); (void)lseek(afd, (off_t)SARMAG, L_SET); SETCF(tfd, tname, afd, archive, NOPAD); copy_ar(&cf, size); (void)close(tfd); (void)ftruncate(afd, size + SARMAG); close_archive(afd); if (*argv) { orphans(argv); return(1); } return(0); } ine HDR2 "%-16.16s%-12ld%-6u%-6u%-8o%-10ld%2s" #define OLDARMAXNAME 15 #define HDR3 "%-16.15s%-12ld%-6u%-6u%-8o%-10ld%2s" void close_archive(); void skip_arobj(); int copy_ar(); int get_arobj(); int open_archive(); int put_arobj(); , ARMAG, SARMAG)) badfmt(); } else if (write(fd, ARMAG, SARMAG) != SARMAG) error(archive); return(fd); } void close_archibin/ar/extern.h 644 0 12 4011 5450745331 6662 /*- * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)extern.h 5.1 (Berkeley) 4/3/91 */ void badfmt(); void error(); void orphans(); int compare(); int tmp(); char *files(); char *rname(); void strmode(); extern long strtol(); extern off_t lseek(); extern char *getenv(); s/param.h> #include #include #include #include #include #include #include "archive.h" #include "extern.h" #include "pathnames.h" extern CHDR chdr; /* converted header */ extern char *archive; /* archive name */ extern char *tname; /* temporary file "name" */ /*- * delete -- * Deletes named members from the archive. */ delete(argv) register char **argv; { CF cf; off_t size; int afd, tfd; char *file; bin/ar/extract.c 644 0 12 7530 5450741653 7036 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)extract.c 5.5 (Berkeley) 3/12/91"; #endif #include #include #include #include #include #include #include #include #include "archive.h" #include "extern.h" extern int errno; extern CHDR chdr; /* converted header */ extern char *archive; /* archive name */ /* * extract -- * Extract files from the named archive - if member names given only * extract those members otherwise extract all members. If 'o' option * selected modify date of newly created file to be same as archive * members date otherwise date is time of extraction. Does not modify * archive. */ extract(argv) char **argv; { register int afd, all, tfd; struct timeval tv[2]; struct stat sb; CF cf; char *file; tv[0].tv_usec = tv[1].tv_usec = 0; afd = open_archive(O_RDONLY); /* Read from an archive, write to disk; pad on read. */ SETCF(afd, archive, 0, 0, RPAD); for (all = !*argv; get_arobj(afd);) { if (all) file = chdr.name; else if (!(file = files(argv))) { skip_arobj(afd); continue; } if (options & AR_U && !stat(file, &sb) && sb.st_mtime > chdr.date) continue; if ((tfd = open(file, O_WRONLY|O_CREAT|O_TRUNC, 0200)) < 0) { (void)fprintf(stderr, "ar: %s: %s.\n", file, strerror(errno)); skip_arobj(afd); continue; } if (options & AR_V) (void)printf("x - %s\n", file); cf.wfd = tfd; cf.wname = file; copy_ar(&cf, chdr.size); if (fchmod(tfd, (short)chdr.mode)) { (void)fprintf(stderr, "ar: %s: chmod: %s\n", file, strerror(errno)); } if (options & AR_O) { tv[0].tv_sec = tv[1].tv_sec = chdr.date; if (utimes(file, tv)) { (void)fprintf(stderr, "ar: %s: utimes: %s\n", file, strerror(errno)); } } (void)close(tfd); if (!all && !*argv) break; } close_archive(afd); if (*argv) { orphans(argv); return(1); } return(0); } ; int open_archive(); int put_arobj(); , ARMAG, SARMAG)) badfmt(); } else if (write(fd, ARMAG, SARMAG) != SARMAG) error(archive); return(fd); } void close_archibin/ar/misc.c 644 0 12 7247 5450741661 6323 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)misc.c 5.7 (Berkeley) 5/27/91"; #endif #include #include #include #include #include #include #include "archive.h" #include "extern.h" #include "pathnames.h" extern int errno; extern CHDR chdr; /* converted header */ extern char *archive; /* archive name */ char *tname = "temporary file"; /* temporary file "name" */ tmp() { extern char *envtmp; long oset; static int first; int fd; char path[MAXPATHLEN]; if (!first && !envtmp) { envtmp = (char *)getenv("TMPDIR"); first = 1; } if (envtmp) (void)sprintf(path, "%s/%s", envtmp, _NAME_ARTMP); else bcopy(_PATH_ARTMP, path, sizeof(_PATH_ARTMP)); oset = sigsetmask(~0L); if ((fd = mkstemp(path)) == -1) error(tname); (void)unlink(path); (void)sigsetmask(oset); return(fd); } /* * files -- * See if the current file matches any file in the argument list; if it * does, remove it from the argument list. */ char * files(argv) char **argv; { register char **list; char *p; for (list = argv; *list; ++list) if (compare(*list)) { p = *list; for (; list[0] = list[1]; ++list); return(p); } return(NULL); } void orphans(argv) char **argv; { for (; *argv; ++argv) (void)fprintf(stderr, "ar: %s: not found in archive.\n", *argv); } char * rname(path) char *path; { register char *ind; return((ind = rindex(path, '/')) ? ind + 1 : path); } compare(dest) char *dest; { if (options & AR_TR) return(!strncmp(chdr.name, rname(dest), OLDARMAXNAME)); return(!strcmp(chdr.name, rname(dest))); } void badfmt() { errno = EINVAL; error(archive); } void error(name) char *name; { (void)fprintf(stderr, "ar: %s: %s\n", name, strerror(errno)); exit(1); } len); \ buf[len] = '\0'; \ to = strtol(buf, (char **)NULL, base); \ } /* * get_arobj -- * read the archive header for this member */ get_arobj(fd) int fd; { struct ar_hdr *hdr; register int len, nr; register char *p; char buf[20]; nr = read(fd, hb, sizeof(HDR)); if (nr != sizeof(HDR)) { if (!nr) return(0); if (nr < 0) bin/ar/move.c 644 0 12 11030 5450741666 6344 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)move.c 5.6 (Berkeley) 3/12/91"; #endif #include #include #include #include #include #include #include #include "archive.h" #include "extern.h" #include "pathnames.h" extern CHDR chdr; /* converted header */ extern char *archive; /* archive name */ extern char *tname; /* temporary file "name" */ /* * move -- * Change location of named members in archive - if 'b' or 'i' option * selected then named members are placed before 'posname'. If 'a' * option selected members go after 'posname'. If no options, members * are moved to end of archive. */ move(argv) char **argv; { extern char *posarg, *posname; /* positioning file names */ CF cf; off_t size, tsize; int afd, curfd, mods, tfd1, tfd2, tfd3; char *file; afd = open_archive(O_RDWR); mods = options & (AR_A|AR_B); tfd1 = tmp(); /* Files before key file. */ tfd2 = tmp(); /* Files selected by user. */ tfd3 = tmp(); /* Files after key file. */ /* * Break archive into three parts -- selected entries and entries * before and after the key entry. If positioning before the key, * place the key at the beginning of the after key entries and if * positioning after the key, place the key at the end of the before * key entries. Put it all back together at the end. */ /* Read and write to an archive; pad on both. */ SETCF(afd, archive, 0, tname, RPAD|WPAD); for (curfd = tfd1; get_arobj(afd);) { if (*argv && (file = files(argv))) { if (options & AR_V) (void)printf("m - %s\n", file); cf.wfd = tfd2; put_arobj(&cf, (struct stat *)NULL); continue; } if (mods && compare(posname)) { mods = 0; if (options & AR_B) curfd = tfd3; cf.wfd = curfd; put_arobj(&cf, (struct stat *)NULL); if (options & AR_A) curfd = tfd3; } else { cf.wfd = curfd; put_arobj(&cf, (struct stat *)NULL); } } if (mods) { (void)fprintf(stderr, "ar: %s: archive member not found.\n", posarg); close_archive(afd); return(1); } (void)lseek(afd, (off_t)SARMAG, L_SET); SETCF(tfd1, tname, afd, archive, NOPAD); tsize = size = lseek(tfd1, (off_t)0, L_INCR); (void)lseek(tfd1, (off_t)0, L_SET); copy_ar(&cf, size); tsize += size = lseek(tfd2, (off_t)0, L_INCR); (void)lseek(tfd2, (off_t)0, L_SET); cf.rfd = tfd2; copy_ar(&cf, size); tsize += size = lseek(tfd3, (off_t)0, L_INCR); (void)lseek(tfd3, (off_t)0, L_SET); cf.rfd = tfd3; copy_ar(&cf, size); (void)ftruncate(afd, tsize + SARMAG); close_archive(afd); if (*argv) { orphans(argv); return(1); } return(0); } st)) { p = *list; for (; list[0] = list[1]; ++list); return(p); } return(NULL); } void orphans(argv) char **argv; { for (; *argv; ++argv) (void)fprintf(stderr, "ar: %s: not found in archive.\n", *argv); } char * rname(path) char *path; { register char *ind; return((ind = rindex(path, '/')) ? ind + 1 : path); } compare(dest) char *dest; { if (options & AR_TR) return(!strncmp(chdr.name, rname(dest), OLDARMAXNAME)); return(!strcmp(chdr.name, rname(dest)bin/ar/pathnames.h 644 0 12 4003 5450741672 7342 /*- * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)pathnames.h 5.4 (Berkeley) 4/12/91 */ #define _NAME_ARTMP "ar.XXXXXX" #define _PATH_ARTMP "/tmp/ar.XXXXXX" - %s\n", file); cf.wfd = tfd2; put_arobj(&cf, (struct stat *)NULL); continue; } if (mods && compare(posname)) { mods = 0; if (options & AR_B) curfd = tfd3; cf.wfd = curfd; put_arobj(&cf, (struct stat *)NULL); if (options & AR_A) curfd = tfd3; } else { cf.wfd = curfd; put_arobj(&cf, (struct stat *)NULL); } } if (mods) { (void)fprintf(stderr, "ar: %s: archive member not found.\n", posarg); close_archive(afd); return(1); } (void)lseek(afd, (off_bin/ar/print.c 644 0 12 5656 5450741673 6531 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)print.c 5.6 (Berkeley) 3/12/91"; #endif #include #include #include #include #include "archive.h" #include "extern.h" extern CHDR chdr; /* converted header */ extern char *archive; /* archive name */ /* * print -- * Prints archive members on stdout - if member names given only * print those members, otherwise print all members. */ print(argv) char **argv; { CF cf; register int afd, all; char *file; afd = open_archive(O_RDONLY); /* Read from an archive, write to stdout; pad on read. */ SETCF(afd, archive, fileno(stdout), "stdout", RPAD); for (all = !*argv; get_arobj(afd);) { if (all) file = chdr.name; else if (!(file = files(argv))) { skip_arobj(afd); continue; } if (options & AR_V) { (void)printf("\n<%s>\n\n", file); (void)fflush(stdout); } copy_ar(&cf, chdr.size); if (!all && !*argv) break; } close_archive(afd); if (*argv) { orphans(argv); return(1); } return(0); } afd, tsize + SARMAG); close_archive(afd); if (*argv) { orphans(argv); returbin/ar/replace.c 644 0 12 13305 5450741700 7005 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Hugh Smith at The University of Guelph. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)replace.c 5.8 (Berkeley) 3/15/91"; #endif #include #include #include #include #include #include #include #include #include #include "archive.h" #include "extern.h" extern int errno; extern CHDR chdr; /* converted header */ extern char *archive; /* archive name */ extern char *tname; /* temporary file "name" */ /* * replace -- * Replace or add named members to archive. Entries already in the * archive are swapped in place. Others are added before or after * the key entry, based on the a, b and i options. If the u option * is specified, modification dates select for replacement. */ replace(argv) char **argv; { extern char *posarg, *posname; /* positioning file name */ register char *file; register int afd, curfd, mods, sfd; struct stat sb; CF cf; off_t size, tsize; int err, exists, tfd1, tfd2; char *rname(); err = 0; /* * If doesn't exist, simply append to the archive. There's * a race here, but it's pretty short, and not worth fixing. */ exists = !stat(archive, &sb); afd = open_archive(O_CREAT|O_RDWR); if (!exists) { tfd1 = -1; tfd2 = tmp(); goto append; } tfd1 = tmp(); /* Files before key file. */ tfd2 = tmp(); /* Files after key file. */ /* * Break archive into two parts -- entries before and after the key * entry. If positioning before the key, place the key at the * beginning of the after key entries and if positioning after the * key, place the key at the end of the before key entries. Put it * all back together at the end. */ mods = (options & (AR_A|AR_B)); for (curfd = tfd1; get_arobj(afd);) { if (*argv && (file = files(argv))) { if ((sfd = open(file, O_RDONLY)) < 0) { err = 1; (void)fprintf(stderr, "ar: %s: %s.\n", file, strerror(errno)); goto useold; } (void)fstat(sfd, &sb); if (options & AR_U && sb.st_mtime <= chdr.date) { (void)close(sfd); goto useold; } if (options & AR_V) (void)printf("r - %s\n", file); /* Read from disk, write to an archive; pad on write */ SETCF(sfd, file, curfd, tname, WPAD); put_arobj(&cf, &sb); (void)close(sfd); skip_arobj(afd); continue; } if (mods && compare(posname)) { mods = 0; if (options & AR_B) curfd = tfd2; /* Read and write to an archive; pad on both. */ SETCF(afd, archive, curfd, tname, RPAD|WPAD); put_arobj(&cf, (struct stat *)NULL); if (options & AR_A) curfd = tfd2; } else { /* Read and write to an archive; pad on both. */ useold: SETCF(afd, archive, curfd, tname, RPAD|WPAD); put_arobj(&cf, (struct stat *)NULL); } } if (mods) { (void)fprintf(stderr, "ar: %s: archive member not found.\n", posarg); close_archive(afd); return(1); } /* Append any left-over arguments to the end of the after file. */ append: while (file = *argv++) { if (options & AR_V) (void)printf("a - %s\n", file); if ((sfd = open(file, O_RDONLY)) < 0) { err = 1; (void)fprintf(stderr, "ar: %s: %s.\n", file, strerror(errno)); continue; } (void)fstat(sfd, &sb); /* Read from disk, write to an archive; pad on write. */ SETCF(sfd, file, options & (AR_A|AR_B) ? tfd1 : tfd2, tname, WPAD); put_arobj(&cf, &sb); (void)close(sfd); } (void)lseek(afd, (off_t)SARMAG, L_SET); SETCF(tfd1, tname, afd, archive, NOPAD); if (tfd1 != -1) { tsize = size = lseek(tfd1, (off_t)0, L_INCR); (void)lseek(tfd1, (off_t)0, L_SET); copy_ar(&cf, size); } else tsize = 0; tsize += size = lseek(tfd2, (off_t)0, L_INCR); (void)lseek(tfd2, (off_t)0, L_SET); cf.rfd = tfd2; copy_ar(&cf, size); (void)ftruncate(afd, tsize + SARMAG); close_archive(afd); return(err); } ted to the standard error output if any file names are truncated. (See .IR ar (5) for more information.) .TP \-t List the specified files in the order in which they appear in the archive, each on a separate line. If no files are specified, all files in the archive are listed. .TP \-u Update files. When used with tbin/ar/strmode.c 644 0 12 7465 5703140137 7037 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)strmode.c 5.3.1 (2.11BSD GTE) 1/5/95"; #endif /* LIBC_SCCS and not lint */ #include #include #define S_IRUSR S_IREAD #define S_IWUSR S_IWRITE #define S_IXUSR S_IEXEC #define S_IRGRP (S_IREAD >> 3) #define S_IWGRP (S_IWRITE >> 3) #define S_IXGRP (S_IEXEC >> 3) #define S_IROTH (S_IREAD >> 6) #define S_IWOTH (S_IWRITE >> 6) #define S_IXOTH (S_IEXEC >> 6) void strmode(mode, p) register mode_t mode; register char *p; { /* print type */ switch (mode & S_IFMT) { case S_IFDIR: /* directory */ *p++ = 'd'; break; case S_IFCHR: /* character special */ *p++ = 'c'; break; case S_IFBLK: /* block special */ *p++ = 'b'; break; case S_IFREG: /* regular */ *p++ = '-'; break; case S_IFLNK: /* symbolic link */ *p++ = 'l'; break; case S_IFSOCK: /* socket */ *p++ = 's'; break; #ifdef S_IFIFO case S_IFIFO: /* fifo */ *p++ = 'p'; break; #endif default: /* unknown */ *p++ = '?'; break; } /* usr */ if (mode & S_IRUSR) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWUSR) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXUSR | S_ISUID)) { case 0: *p++ = '-'; break; case S_IXUSR: *p++ = 'x'; break; case S_ISUID: *p++ = 'S'; break; case S_IXUSR | S_ISUID: *p++ = 's'; break; } /* group */ if (mode & S_IRGRP) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWGRP) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXGRP | S_ISGID)) { case 0: *p++ = '-'; break; case S_IXGRP: *p++ = 'x'; break; case S_ISGID: *p++ = 'S'; break; case S_IXGRP | S_ISGID: *p++ = 's'; break; } /* other */ if (mode & S_IROTH) *p++ = 'r'; else *p++ = '-'; if (mode & S_IWOTH) *p++ = 'w'; else *p++ = '-'; switch (mode & (S_IXOTH | S_ISVTX)) { case 0: *p++ = '-'; break; case S_IXOTH: *p++ = 'x'; break; case S_ISVTX: *p++ = 'T'; break; case S_IXOTH | S_ISVTX: *p++ = 't'; break; } *p++ = ' '; /* will be a '+' if ACL's implemented */ *p = '\0'; } y and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific priorbin/dd.c 444 0 12 25122 4775316225 5366 #ifndef lint static char *sccsid = "@(#)dd.c 4.4 (Berkeley) 1/22/85"; #endif #include #include #define BIG 2147483647 #define LCASE 01 #define UCASE 02 #define SWAB 04 #define NERR 010 #define SYNC 020 int cflag; int fflag; int skip; int seekn; int count; int files = 1; char *string; char *ifile; char *ofile; char *ibuf; char *obuf; char *sbrk(); int ibs = 512; int obs = 512; int bs; int cbs; int ibc; int obc; int cbc; int nifr; int nipr; int nofr; int nopr; int ntrunc; int ibf; int obf; char *op; int nspace; char etoa[] = { 0000,0001,0002,0003,0234,0011,0206,0177, 0227,0215,0216,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0235,0205,0010,0207, 0030,0031,0222,0217,0034,0035,0036,0037, 0200,0201,0202,0203,0204,0012,0027,0033, 0210,0211,0212,0213,0214,0005,0006,0007, 0220,0221,0026,0223,0224,0225,0226,0004, 0230,0231,0232,0233,0024,0025,0236,0032, 0040,0240,0241,0242,0243,0244,0245,0246, 0247,0250,0133,0056,0074,0050,0053,0041, 0046,0251,0252,0253,0254,0255,0256,0257, 0260,0261,0135,0044,0052,0051,0073,0136, 0055,0057,0262,0263,0264,0265,0266,0267, 0270,0271,0174,0054,0045,0137,0076,0077, 0272,0273,0274,0275,0276,0277,0300,0301, 0302,0140,0072,0043,0100,0047,0075,0042, 0303,0141,0142,0143,0144,0145,0146,0147, 0150,0151,0304,0305,0306,0307,0310,0311, 0312,0152,0153,0154,0155,0156,0157,0160, 0161,0162,0313,0314,0315,0316,0317,0320, 0321,0176,0163,0164,0165,0166,0167,0170, 0171,0172,0322,0323,0324,0325,0326,0327, 0330,0331,0332,0333,0334,0335,0336,0337, 0340,0341,0342,0343,0344,0345,0346,0347, 0173,0101,0102,0103,0104,0105,0106,0107, 0110,0111,0350,0351,0352,0353,0354,0355, 0175,0112,0113,0114,0115,0116,0117,0120, 0121,0122,0356,0357,0360,0361,0362,0363, 0134,0237,0123,0124,0125,0126,0127,0130, 0131,0132,0364,0365,0366,0367,0370,0371, 0060,0061,0062,0063,0064,0065,0066,0067, 0070,0071,0372,0373,0374,0375,0376,0377, }; char atoe[] = { 0000,0001,0002,0003,0067,0055,0056,0057, 0026,0005,0045,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0074,0075,0062,0046, 0030,0031,0077,0047,0034,0035,0036,0037, 0100,0117,0177,0173,0133,0154,0120,0175, 0115,0135,0134,0116,0153,0140,0113,0141, 0360,0361,0362,0363,0364,0365,0366,0367, 0370,0371,0172,0136,0114,0176,0156,0157, 0174,0301,0302,0303,0304,0305,0306,0307, 0310,0311,0321,0322,0323,0324,0325,0326, 0327,0330,0331,0342,0343,0344,0345,0346, 0347,0350,0351,0112,0340,0132,0137,0155, 0171,0201,0202,0203,0204,0205,0206,0207, 0210,0211,0221,0222,0223,0224,0225,0226, 0227,0230,0231,0242,0243,0244,0245,0246, 0247,0250,0251,0300,0152,0320,0241,0007, 0040,0041,0042,0043,0044,0025,0006,0027, 0050,0051,0052,0053,0054,0011,0012,0033, 0060,0061,0032,0063,0064,0065,0066,0010, 0070,0071,0072,0073,0004,0024,0076,0341, 0101,0102,0103,0104,0105,0106,0107,0110, 0111,0121,0122,0123,0124,0125,0126,0127, 0130,0131,0142,0143,0144,0145,0146,0147, 0150,0151,0160,0161,0162,0163,0164,0165, 0166,0167,0170,0200,0212,0213,0214,0215, 0216,0217,0220,0232,0233,0234,0235,0236, 0237,0240,0252,0253,0254,0255,0256,0257, 0260,0261,0262,0263,0264,0265,0266,0267, 0270,0271,0272,0273,0274,0275,0276,0277, 0312,0313,0314,0315,0316,0317,0332,0333, 0334,0335,0336,0337,0352,0353,0354,0355, 0356,0357,0372,0373,0374,0375,0376,0377, }; char atoibm[] = { 0000,0001,0002,0003,0067,0055,0056,0057, 0026,0005,0045,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0074,0075,0062,0046, 0030,0031,0077,0047,0034,0035,0036,0037, 0100,0132,0177,0173,0133,0154,0120,0175, 0115,0135,0134,0116,0153,0140,0113,0141, 0360,0361,0362,0363,0364,0365,0366,0367, 0370,0371,0172,0136,0114,0176,0156,0157, 0174,0301,0302,0303,0304,0305,0306,0307, 0310,0311,0321,0322,0323,0324,0325,0326, 0327,0330,0331,0342,0343,0344,0345,0346, 0347,0350,0351,0255,0340,0275,0137,0155, 0171,0201,0202,0203,0204,0205,0206,0207, 0210,0211,0221,0222,0223,0224,0225,0226, 0227,0230,0231,0242,0243,0244,0245,0246, 0247,0250,0251,0300,0117,0320,0241,0007, 0040,0041,0042,0043,0044,0025,0006,0027, 0050,0051,0052,0053,0054,0011,0012,0033, 0060,0061,0032,0063,0064,0065,0066,0010, 0070,0071,0072,0073,0004,0024,0076,0341, 0101,0102,0103,0104,0105,0106,0107,0110, 0111,0121,0122,0123,0124,0125,0126,0127, 0130,0131,0142,0143,0144,0145,0146,0147, 0150,0151,0160,0161,0162,0163,0164,0165, 0166,0167,0170,0200,0212,0213,0214,0215, 0216,0217,0220,0232,0233,0234,0235,0236, 0237,0240,0252,0253,0254,0255,0256,0257, 0260,0261,0262,0263,0264,0265,0266,0267, 0270,0271,0272,0273,0274,0275,0276,0277, 0312,0313,0314,0315,0316,0317,0332,0333, 0334,0335,0336,0337,0352,0353,0354,0355, 0356,0357,0372,0373,0374,0375,0376,0377, }; main(argc, argv) int argc; char **argv; { int (*conv)(); register char *ip; register c; int ebcdic(), ibm(), ascii(), null(), cnull(), term(), block(), unblock(); int a; conv = null; for(c=1; cibuf;) *--ip = 0; ibc = read(ibf, ibuf, ibs); } if(ibc == -1) { perror("read"); if((cflag&NERR) == 0) { flsh(); term(1); } ibc = 0; for(c=0; c> 1; if(cflag&SWAB && c) do { a = *ip++; ip[-1] = *ip; *ip++ = a; } while(--c); ip = ibuf; if (fflag) { obc = ibc; flsh(); ibc = 0; } goto loop; } c = 0; c |= *ip++; c &= 0377; (*conv)(c); goto loop; } flsh() { register c; if(obc) { if(obc == obs) nofr++; else nopr++; c = write(obf, obuf, obc); if(c != obc) { perror("write"); term(1); } obc = 0; } } match(s) char *s; { register char *cs; cs = string; while(*cs++ == *s) if(*s++ == '\0') goto true; if(*s != '\0') return(0); true: cs--; string = cs; return(1); } number(big) { register char *cs; long n; cs = string; n = 0; while(*cs >= '0' && *cs <= '9') n = n*10 + *cs++ - '0'; for(;;) switch(*cs++) { case 'k': n *= 1024; continue; case 'w': n *= sizeof(int); continue; case 'b': n *= 512; continue; case '*': case 'x': string = cs; n *= number(BIG); case '\0': if (n>=big || n<0) { fprintf(stderr, "dd: argument %D out of range\n", n); exit(1); } return(n); } /* never gets here */ } cnull(cc) { register c; c = cc; if(cflag&UCASE && c>='a' && c<='z') c += 'A'-'a'; if(cflag&LCASE && c>='A' && c<='Z') c += 'a'-'A'; null(c); } null(c) { *op = c; op++; if(++obc >= obs) { flsh(); op = obuf; } } ascii(cc) { register c; c = etoa[cc] & 0377; if(cbs == 0) { cnull(c); return; } if(c == ' ') { nspace++; goto out; } while(nspace > 0) { null(' '); nspace--; } cnull(c); out: if(++cbc >= cbs) { null('\n'); cbc = 0; nspace = 0; } } unblock(cc) { register c; c = cc & 0377; if(cbs == 0) { cnull(c); return; } if(c == ' ') { nspace++; goto out; } while(nspace > 0) { null(' '); nspace--; } cnull(c); out: if(++cbc >= cbs) { null('\n'); cbc = 0; nspace = 0; } } ebcdic(cc) { register c; c = cc; if(cflag&UCASE && c>='a' && c<='z') c += 'A'-'a'; if(cflag&LCASE && c>='A' && c<='Z') c += 'a'-'A'; c = atoe[c] & 0377; if(cbs == 0) { null(c); return; } if(cc == '\n') { while(cbc < cbs) { null(atoe[' ']); cbc++; } cbc = 0; return; } if(cbc == cbs) ntrunc++; cbc++; if(cbc <= cbs) null(c); } ibm(cc) { register c; c = cc; if(cflag&UCASE && c>='a' && c<='z') c += 'A'-'a'; if(cflag&LCASE && c>='A' && c<='Z') c += 'a'-'A'; c = atoibm[c] & 0377; if(cbs == 0) { null(c); return; } if(cc == '\n') { while(cbc < cbs) { null(atoibm[' ']); cbc++; } cbc = 0; return; } if(cbc == cbs) ntrunc++; cbc++; if(cbc <= cbs) null(c); } block(cc) { register c; c = cc; if(cflag&UCASE && c>='a' && c<='z') c += 'A'-'a'; if(cflag&LCASE && c>='A' && c<='Z') c += 'a'-'A'; c &= 0377; if(cbs == 0) { null(c); return; } if(cc == '\n') { while(cbc < cbs) { null(' '); cbc++; } cbc = 0; return; } if(cbc == cbs) ntrunc++; cbc++; if(cbc <= cbs) null(c); } term(status) int status; { stats(); exit(status); } stats() { fprintf(stderr,"%u+%u records in\n", nifr, nipr); fprintf(stderr,"%u+%u records out\n", nofr, nopr); if(ntrunc) fprintf(stderr,"%u truncated records\n", ntrunc); } 15,0135,0134,0116,0153,0140,0113,0141, 0360,0361,0362,0363,0364,0365,0366,0367, 0370,0371,0172,0136,0114,0176,0156,0157, 0174,0301,0302,0303,0304,0305,0306,0307, 0310,0311,0321,0322,0323,0324,0325,0326, 0327,0330,0331,0342,0343,0344,0345,0346, 0347,0350,0351,0112,0340,0132,0137,0155, 0171,0201,0202,0203,0204,0205,0206,0207, 0210,0211,0221,0222,0223,0224,0225,0226, 0227,0230,0231,0242,0243,0244,0245,0246, 0247,0250,02bin/su.c 444 0 12 7550 4414461556 5411 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)su.c 5.4 (Berkeley) 1/13/86"; #endif not lint #include #include #include #include #include #include #include char userbuf[64] = "USER="; char homebuf[128] = "HOME="; char shellbuf[128] = "SHELL="; char pathbuf[128] = "PATH=:/usr/ucb:/bin:/usr/bin"; char *cleanenv[] = { userbuf, homebuf, shellbuf, pathbuf, 0, 0 }; char *user = "root"; char *shell = "/bin/sh"; int fulllogin; int fastlogin; extern char **environ; struct passwd *pwd; char *crypt(); char *getpass(); char *getenv(); char *getlogin(); main(argc,argv) int argc; char *argv[]; { char *password; char buf[1000]; FILE *fp; register char *p; openlog("su", LOG_ODELAY, LOG_AUTH); again: if (argc > 1 && strcmp(argv[1], "-f") == 0) { fastlogin++; argc--, argv++; goto again; } if (argc > 1 && strcmp(argv[1], "-") == 0) { fulllogin++; argc--, argv++; goto again; } if (argc > 1 && argv[1][0] != '-') { user = argv[1]; argc--, argv++; } if ((pwd = getpwuid(getuid())) == NULL) { fprintf(stderr, "Who are you?\n"); exit(1); } strcpy(buf, pwd->pw_name); if ((pwd = getpwnam(user)) == NULL) { fprintf(stderr, "Unknown login: %s\n", user); exit(1); } /* * Only allow those in group zero to su to root. */ if (pwd->pw_uid == 0) { struct group *gr; int i; if ((gr = getgrgid(0)) != NULL) { for (i = 0; gr->gr_mem[i] != NULL; i++) if (strcmp(buf, gr->gr_mem[i]) == 0) goto userok; fprintf(stderr, "You do not have permission to su %s\n", user); exit(1); } userok: setpriority(PRIO_PROCESS, 0, -2); } #define Getlogin() (((p = getlogin()) && *p) ? p : buf) if (pwd->pw_passwd[0] == '\0' || getuid() == 0) goto ok; password = getpass("Password:"); if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) { fprintf(stderr, "Sorry\n"); if (pwd->pw_uid == 0) { syslog(LOG_CRIT, "BAD SU %s on %s", Getlogin(), ttyname(2)); } exit(2); } ok: endpwent(); if (pwd->pw_uid == 0) { syslog(LOG_NOTICE, "%s on %s", Getlogin(), ttyname(2)); closelog(); } if (setgid(pwd->pw_gid) < 0) { perror("su: setgid"); exit(3); } if (initgroups(user, pwd->pw_gid)) { fprintf(stderr, "su: initgroups failed\n"); exit(4); } if (setuid(pwd->pw_uid) < 0) { perror("su: setuid"); exit(5); } if (pwd->pw_shell && *pwd->pw_shell) shell = pwd->pw_shell; if (fulllogin) { cleanenv[4] = getenv("TERM"); environ = cleanenv; } if (strcmp(user, "root")) setenv("USER", pwd->pw_name, userbuf); setenv("SHELL", shell, shellbuf); setenv("HOME", pwd->pw_dir, homebuf); setpriority(PRIO_PROCESS, 0, 0); if (fastlogin) { *argv-- = "-f"; *argv = "su"; } else if (fulllogin) { if (chdir(pwd->pw_dir) < 0) { fprintf(stderr, "No directory\n"); exit(6); } *argv = "-su"; } else *argv = "su"; execv(shell, argv); fprintf(stderr, "No shell\n"); exit(7); } setenv(ename, eval, buf) char *ename, *eval, *buf; { register char *cp, *dp; register char **ep = environ; /* * this assumes an environment variable "ename" already exists */ while (dp = *ep++) { for (cp = ename; *cp == *dp && *cp; cp++, dp++) continue; if (*cp == 0 && (*dp == '=' || *dp == 0)) { strcat(buf, eval); *--ep = buf; return; } } } char * getenv(ename) char *ename; { register char *cp, *dp; register char **ep = environ; while (dp = *ep++) { for (cp = ename; *cp == *dp && *cp; cp++, dp++) continue; if (*cp == 0 && (*dp == '=' || *dp == 0)) return (*--ep); } return ((char *)0); } 241,0007, 0040,0041,0042,0043,0044,0025,0006,0027, 0050,0051,0052,0053,0054,0011,0012,0033, 0060,0061,0032,0063,0064,0065,0066,0010, 0070,0071,0072,bin/rm.c 444 0 12 11723 4013202661 5376 static char *sccsid = "@(#)rm.c 4.18 (Berkeley) 1/6/86"; /* * rm - for ReMoving files, directories & trees. */ #include #include #include #include #include int fflg; /* -f force - supress error messages */ int iflg; /* -i interrogate user on each file */ int rflg; /* -r recurse */ int errcode; /* true if errors occured */ char *strcpy(), *malloc(), *realloc(); main(argc, argv) char *argv[]; { register char *arg; fflg = !isatty(0); iflg = 0; rflg = 0; while (argc > 1 && argv[1][0] == '-') { arg = *++argv; argc--; /* * all files following a null option are considered file names */ if (arg[1] == '\0') break; while (*++arg != '\0') switch(*arg) { case 'f': fflg++; break; case 'i': iflg++; break; case 'R': case 'r': rflg++; break; default: fprintf(stderr, "usage: rm [-rif] file ...\n"); exit(1); } } if (argc < 2 && !fflg) { fprintf(stderr, "usage: rm [-rif] file ...\n"); exit(1); } while (--argc > 0) (void) rm(*++argv, 0); exit(errcode != 0); } char *path; /* pointer to malloc'ed buffer for path */ char *pathp; /* current pointer to end of path */ int pathsz; /* size of path */ /* * Return TRUE if sucessful. Recursive with -r (rflg) */ rm(arg, level) char arg[]; { int ok; /* true if recursive rm succeeded */ struct stat buf; /* for finding out what a file is */ struct direct *dp; /* for reading a directory */ DIR *dirp; /* for reading a directory */ char prevname[MAXNAMLEN + 1]; /* previous name for -r */ char *cp; if (dotname(arg)) { fprintf(stderr, "rm: cannot remove `.' or `..'\n"); return (0); } if (lstat(arg, &buf)) { if (!fflg) { fprintf(stderr, "rm: %s nonexistent\n", arg); errcode++; } return (0); /* error */ } if ((buf.st_mode&S_IFMT) == S_IFDIR) { if (!rflg) { if (!fflg) { fprintf(stderr, "rm: %s directory\n", arg); errcode++; } return (0); } if (iflg && level != 0) { printf("rm: remove directory %s? ", arg); if (!yes()) return (0); /* didn't remove everything */ } if (access(arg, R_OK|W_OK|X_OK) != 0) { if (rmdir(arg) == 0) return (1); /* salvaged: removed empty dir */ if (!fflg) { fprintf(stderr, "rm: %s not changed\n", arg); errcode++; } return (0); /* error */ } if ((dirp = opendir(arg)) == NULL) { if (!fflg) { fprintf(stderr, "rm: cannot read %s?\n", arg); errcode++; } return (0); } if (level == 0) append(arg); prevname[0] = '\0'; while ((dp = readdir(dirp)) != NULL) { if (dotname(dp->d_name)) { strcpy(prevname, dp->d_name); continue; } append(dp->d_name); closedir(dirp); ok = rm(path, level + 1); for (cp = pathp; *--cp != '/' && cp > path; ) ; pathp = cp; *cp++ = '\0'; if ((dirp = opendir(arg)) == NULL) { if (!fflg) { fprintf(stderr, "rm: cannot read %s?\n", arg); errcode++; } break; } /* pick up where we left off */ if (prevname[0] != '\0') { while ((dp = readdir(dirp)) != NULL && strcmp(prevname, dp->d_name) != 0) ; } /* skip the one we just failed to delete */ if (!ok) { dp = readdir(dirp); if (dp != NULL && strcmp(cp, dp->d_name)) { fprintf(stderr, "rm: internal synchronization error: %s, %s, %s\n", arg, cp, dp->d_name); } strcpy(prevname, dp->d_name); } } closedir(dirp); if (level == 0) { pathp = path; *pathp = '\0'; } if (iflg) { printf("rm: remove %s? ", arg); if (!yes()) return (0); } if (rmdir(arg) < 0) { if (!fflg || iflg) { fprintf(stderr, "rm: %s not removed\n", arg); errcode++; } return (0); } return (1); } if (iflg) { printf("rm: remove %s? ", arg); if (!yes()) return (0); } else if (!fflg) { if ((buf.st_mode&S_IFMT) != S_IFLNK && access(arg, W_OK) < 0) { printf("rm: override protection %o for %s? ", buf.st_mode&0777, arg); if (!yes()) return (0); } } if (unlink(arg) < 0) { if (!fflg || iflg) { fprintf(stderr, "rm: %s not removed\n", arg); errcode++; } return (0); } return (1); } /* * boolean: is it "." or ".." ? */ dotname(s) char *s; { if (s[0] == '.') if (s[1] == '.') if (s[2] == '\0') return (1); else return (0); else if (s[1] == '\0') return (1); return (0); } /* * Get a yes/no answer from the user. */ yes() { int i, b; i = b = getchar(); while (b != '\n' && b != EOF) b = getchar(); return (i == 'y'); } /* * Append 'name' to 'path'. */ append(name) char *name; { register int n; n = strlen(name); if (path == NULL) { pathsz = MAXNAMLEN + MAXPATHLEN + 2; if ((path = malloc(pathsz)) == NULL) { fprintf(stderr, "rm: ran out of memory\n"); exit(1); } pathp = path; } else if (pathp + n + 2 > path + pathsz) { fprintf(stderr, "rm: path name too long: %s\n", path); exit(1); } else if (pathp != path && pathp[-1] != '/') *pathp++ = '/'; strcpy(pathp, name); pathp += n; } return (0); } if (level == 0) appendbin/pr.c 444 0 12 15500 4013202661 5376 static char *sccsid = "@(#)pr.c 4.5 (Berkeley) 12/12/84"; /* * print file with headings * 2+head+2+page[56]+5 */ #include #include #include #include /* Making putcp a macro sped things up by 14%. */ #define putcp(c) if (page >= fpage) putchar(c) int ncol = 1; char *header; int col; int icol; FILE *file; char *bufp; #define BUFS 9000 /* at least 66 * 132 */ char buffer[BUFS]; /* for multi-column output */ char obuf[BUFSIZ]; #define FF 014 int line; char *colp[72]; int nofile; char isclosed[10]; FILE *ifile[10]; char **lastarg; int peekc; int fpage; int page; int colw; int nspace; int width = 72; int length = 66; int plength = 61; int margin = 10; int ntflg; int fflg; int mflg; int tabc; char *tty; int mode; char *ttyname(); char *ctime(); main(argc, argv) char **argv; { int nfdone; int onintr(); setbuf(stdout, obuf); if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, onintr); lastarg = &argv[argc-1]; fixtty(); for (nfdone=0; argc>1; argc--) { argv++; if (**argv == '-') { switch (*++*argv) { case 'h': /* define page header */ if (argc>=2) { header = *++argv; argc--; } continue; case 't': /* don't print page headers */ ntflg++; continue; case 'f': /* use form feeds */ fflg++; plength = 60; continue; case 'l': /* length of page */ length = atoi(++*argv); continue; case 'w': /* width of page */ width = atoi(++*argv); continue; case 's': /* col separator */ if (*++*argv) tabc = **argv; else tabc = '\t'; continue; case 'm': /* all files at once */ mflg++; continue; default: if (numeric(*argv)) { /* # of cols */ if ((ncol = atoi(*argv)) == 0) { fprintf(stderr, "can't print 0 cols, using 1 instead.\n"); ncol = 1; } } else { fprintf(stderr, "pr: bad key %s\n", *argv); exit(1); } continue; } } else if (**argv == '+') { /* start at page ++*argv */ fpage = atoi(++*argv); } else { print(*argv, argv); nfdone++; if (mflg) break; } } if (nfdone==0) print((char *)0, (char **)0); done(); } done() { if (tty) chmod(tty, mode); exit(0); } /* numeric -- returns 1 if str is numeric, elsewise 0 */ numeric(str) char *str; { for (; *str ; str++) { if (*str > '9' || *str < '0') { return(0); } } return(1); } onintr() { if (tty) chmod(tty, mode); _exit(1); } fixtty() { struct stat sbuf; tty = ttyname(1); if (tty == 0) return; stat(tty, &sbuf); mode = sbuf.st_mode&0777; chmod(tty, 0600); } /* print -- print file */ print(fp, argp) char *fp; char **argp; { extern char *sprintf(); struct stat sbuf; register sncol; register char *sheader; register char *cbuf; char linebuf[150], *cp; if (ntflg) margin = 0; else margin = 10; if (length <= margin) length = 66; if (width <= 0) width = 72; if (ncol>72 || ncol>width) { fprintf(stderr, "pr: No room for columns.\n"); done(); } if (mflg) { mopen(argp); ncol = nofile; } colw = width/(ncol==0? 1 : ncol); sncol = ncol; sheader = header; plength = length-5; if (ntflg) plength = length; if (--ncol<0) ncol = 0; if (mflg) fp = 0; if (fp) { if((file=fopen(fp, "r"))==NULL) { if (tty==NULL) perror(fp); ncol = sncol; header = sheader; return; } stat(fp, &sbuf); } else { file = stdin; time(&sbuf.st_mtime); } if (header == 0) header = fp?fp:""; cbuf = ctime(&sbuf.st_mtime); cbuf[16] = '\0'; cbuf[24] = '\0'; page = 1; icol = 0; colp[ncol] = bufp = buffer; if (mflg==0) nexbuf(); while (mflg&&nofile || (!mflg)&&tpgetc(ncol)>0) { if (mflg==0) { colp[ncol]--; if (colp[ncol] < buffer) colp[ncol] = &buffer[BUFS]; } line = 0; if (ntflg==0) { if (fflg) { /* Assume a ff takes two blank lines at the top of the page. */ line = 2; sprintf(linebuf, "%s %s %s Page %d\n\n\n", cbuf+4, cbuf+20, header, page); } else sprintf(linebuf, "\n\n%s %s %s Page %d\n\n\n", cbuf+4, cbuf+20, header, page); for(cp=linebuf;*cp;) put(*cp++); } putpage(); if (ntflg==0) { if (fflg) put('\f'); else while(line=10) { fprintf(stderr, "pr: Too many args\n"); done(); } } } putpage() { register int lastcol, i, c; int j; if (ncol==0) { while (line512) n = 512; if((n=fread(rbufp,1,n,file)) <= 0){ fclose(file); *rbufp = 0376; } else { rbufp += n; if (rbufp >= &buffer[BUFS]) rbufp = buffer; *rbufp = 0375; } bufp = rbufp; } tpgetc(ai) { register char **p; register int c, i; i = ai; if (mflg) { if((c=getc(ifile[i])) == EOF) { if (isclosed[i]==0) { isclosed[i] = 1; if (--nofile <= 0) return(0); } return('\n'); } if (c==FF && ncol>0) c = '\n'; return(c); } loop: c = **(p = &colp[i]) & 0377; if (c == 0375) { nexbuf(); c = **p & 0377; } if (c == 0376) return(0); (*p)++; if (*p >= &buffer[BUFS]) *p = buffer; if (c==0) goto loop; return(c); } pgetc(i) { register int c; if (peekc) { c = peekc; peekc = 0; } else c = tpgetc(i); if (tabc) return(c); switch (c) { case '\t': icol++; if ((icol&07) != 0) peekc = '\t'; return(' '); case '\n': icol = 0; break; case 010: case 033: icol--; break; } if (c >= ' ') icol++; return(c); } put(ac) { register int ns, c; c = ac; if (tabc) { putcp(c); if (c=='\n') line++; return; } switch (c) { case ' ': nspace++; col++; return; case '\n': col = 0; nspace = 0; line++; break; case 010: case 033: if (--col<0) col = 0; if (--nspace<0) nspace = 0; } while(nspace) { if (nspace>2 && col > (ns=((col-nspace)|07))) { nspace = col-ns-1; putcp('\t'); } else { nspace--; putcp(' '); } } if (c >= ' ') col++; putcp(c); } op = obuf; if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, term); while(skip) { read(ibf, ibuf, ibs); skip--; } while(seekn) { lseek(obf, (long)obs, 1); seekn--; } loopbin/cp.c 444 0 12 11300 4013202661 5351 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)cp.c 4.13 (Berkeley) 10/11/85"; #endif not lint /* * cp */ #include #include #include #include #include int iflag; int rflag; int pflag; char *rindex(); main(argc, argv) int argc; char **argv; { struct stat stb; int rc, i; argc--, argv++; while (argc > 0 && **argv == '-') { (*argv)++; while (**argv) switch (*(*argv)++) { case 'i': iflag++; break; case 'R': case 'r': rflag++; break; case 'p': /* preserve mtimes, atimes, and modes */ pflag++; (void) umask(0); break; default: goto usage; } argc--; argv++; } if (argc < 2) goto usage; if (argc > 2) { if (stat(argv[argc-1], &stb) < 0) goto usage; if ((stb.st_mode&S_IFMT) != S_IFDIR) goto usage; } rc = 0; for (i = 0; i < argc-1; i++) rc |= copy(argv[i], argv[argc-1]); exit(rc); usage: fprintf(stderr, "Usage: cp [-ip] f1 f2; or: cp [-irp] f1 ... fn d2\n"); exit(1); } copy(from, to) char *from, *to; { int fold, fnew, n, exists; char *last, destname[MAXPATHLEN + 1], buf[MAXBSIZE]; struct stat stfrom, stto; fold = open(from, 0); if (fold < 0) { Perror(from); return (1); } if (fstat(fold, &stfrom) < 0) { Perror(from); (void) close(fold); return (1); } if (stat(to, &stto) >= 0 && (stto.st_mode&S_IFMT) == S_IFDIR) { last = rindex(from, '/'); if (last) last++; else last = from; if (strlen(to) + strlen(last) >= sizeof destname - 1) { fprintf(stderr, "cp: %s/%s: Name too long", to, last); (void) close(fold); return(1); } (void) sprintf(destname, "%s/%s", to, last); to = destname; } if (rflag && (stfrom.st_mode&S_IFMT) == S_IFDIR) { int fixmode = 0; /* cleanup mode after rcopy */ (void) close(fold); if (stat(to, &stto) < 0) { if (mkdir(to, (stfrom.st_mode & 07777) | 0700) < 0) { Perror(to); return (1); } fixmode = 1; } else if ((stto.st_mode&S_IFMT) != S_IFDIR) { fprintf(stderr, "cp: %s: Not a directory.\n", to); return (1); } else if (pflag) fixmode = 1; n = rcopy(from, to); if (fixmode) (void) chmod(to, stfrom.st_mode & 07777); return (n); } if ((stfrom.st_mode&S_IFMT) == S_IFDIR) fprintf(stderr, "cp: %s: Is a directory (copying as plain file).\n", from); exists = stat(to, &stto) == 0; if (exists) { if (stfrom.st_dev == stto.st_dev && stfrom.st_ino == stto.st_ino) { fprintf(stderr, "cp: %s and %s are identical (not copied).\n", from, to); (void) close(fold); return (1); } if (iflag && isatty(fileno(stdin))) { int i, c; fprintf (stderr, "overwrite %s? ", to); i = c = getchar(); while (c != '\n' && c != EOF) c = getchar(); if (i != 'y') { (void) close(fold); return(1); } } } fnew = creat(to, stfrom.st_mode & 07777); if (fnew < 0) { Perror(to); (void) close(fold); return(1); } if (exists && pflag) (void) fchmod(fnew, stfrom.st_mode & 07777); for (;;) { n = read(fold, buf, sizeof buf); if (n == 0) break; if (n < 0) { Perror(from); (void) close(fold); (void) close(fnew); return (1); } if (write(fnew, buf, n) != n) { Perror(to); (void) close(fold); (void) close(fnew); return (1); } } (void) close(fold); (void) close(fnew); if (pflag) return (setimes(to, &stfrom)); return (0); } rcopy(from, to) char *from, *to; { DIR *fold = opendir(from); struct direct *dp; struct stat statb; int errs = 0; char fromname[MAXPATHLEN + 1]; if (fold == 0 || (pflag && fstat(fold->dd_fd, &statb) < 0)) { Perror(from); return (1); } for (;;) { dp = readdir(fold); if (dp == 0) { closedir(fold); if (pflag) return (setimes(to, &statb) + errs); return (errs); } if (dp->d_ino == 0) continue; if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if (strlen(from)+1+strlen(dp->d_name) >= sizeof fromname - 1) { fprintf(stderr, "cp: %s/%s: Name too long.\n", from, dp->d_name); errs++; continue; } (void) sprintf(fromname, "%s/%s", from, dp->d_name); errs += copy(fromname, to); } } int setimes(path, statp) char *path; struct stat *statp; { struct timeval tv[2]; tv[0].tv_sec = statp->st_atime; tv[1].tv_sec = statp->st_mtime; tv[0].tv_usec = tv[1].tv_usec = 0; if (utimes(path, tv) < 0) { Perror(path); return (1); } return (0); } Perror(s) char *s; { fprintf(stderr, "cp: "); perror(s); } \n'); line++; if (c==FF) break; } return; } colp[0] = colp[ncol]; if (mflg==0) for (i=1; i<=ncol; i++) { colp[i] = colp[i-1]; for (j = margin; j #include #include #include #include #include #define DIFF 1 /* found differences */ #define ERR 2 /* error during run */ #define NO 0 /* no/false */ #define OK 0 /* didn't find differences */ #define YES 1 /* yes/true */ static int fd1, fd2, /* file descriptors */ silent = NO; /* if silent run */ static short all = NO; /* if report all differences */ static u_char buf1[MAXBSIZE], /* read buffers */ buf2[MAXBSIZE]; static char *file1, *file2; /* file names */ main(argc, argv) int argc; char **argv; { extern char *optarg; extern int optind; int ch; u_long otoi(); while ((ch = getopt(argc, argv, "ls")) != EOF) switch(ch) { case 'l': /* print all differences */ all = YES; break; case 's': /* silent run */ silent = YES; break; case '?': default: usage(); } argv += optind; argc -= optind; if (argc < 2 || argc > 4) usage(); /* open up files; "-" is stdin */ file1 = argv[0]; if (strcmp(file1, "-") && (fd1 = open(file1, O_RDONLY, 0)) < 0) error(file1); file2 = argv[1]; if ((fd2 = open(file2, O_RDONLY, 0)) < 0) error(file2); /* handle skip arguments */ if (argc > 2) { skip(otoi(argv[2]), fd1, file1); if (argc == 4) skip(otoi(argv[3]), fd2, file2); } cmp(); /*NOTREACHED*/ } /* * skip -- * skip first part of file */ static skip(dist, fd, fname) register u_long dist; /* length in bytes, to skip */ register int fd; /* file descriptor */ char *fname; /* file name for error */ { register int rlen; /* read length */ register int nread; for (; dist; dist -= rlen) { rlen = MIN(dist, sizeof(buf1)); if ((nread = read(fd, buf1, rlen)) != rlen) { if (nread < 0) error(fname); else endoffile(fname); } } } static cmp() { register u_char *C1, *C2; /* traveling pointers */ register int cnt, /* counter */ len1, len2; /* read lengths */ register long byte, /* byte count */ line; /* line count */ short dfound = NO; /* if difference found */ for (byte = 0, line = 1;;) { switch(len1 = read(fd1, buf1, MAXBSIZE)) { case -1: error(file1); case 0: /* * read of file 1 just failed, find out * if there's anything left in file 2 */ switch(read(fd2, buf2, 1)) { case -1: error(file2); case 0: exit(dfound ? DIFF : OK); default: endoffile(file1); } } /* * file1 might be stdio, which means that a read of less than * MAXBSIZE might not mean an EOF. So, read whatever we read * from file1 from file2. */ if ((len2 = read(fd2, buf2, len1)) == -1) error(file2); if (bcmp(buf1, buf2, len2)) { if (silent) exit(DIFF); if (all) { dfound = YES; for (C1 = buf1, C2 = buf2, cnt = len2; cnt--; ++C1, ++C2) { ++byte; if (*C1 != *C2) printf("%6ld %3o %3o\n", byte, *C1, *C2); } } else for (C1 = buf1, C2 = buf2;; ++C1, ++C2) { ++byte; if (*C1 != *C2) { printf("%s %s differ: char %ld, line %ld\n", file1, file2, byte, line); exit(DIFF); } if (*C1 == '\n') ++line; } } else { byte += len2; /* * here's the real performance problem, we've got to * count the stupid lines, which means that -l is a * *much* faster version, i.e., unless you really * *want* to know the line number, run -s or -l. */ if (!silent && !all) for (C1 = buf1, cnt = len2; cnt--;) if (*C1++ == '\n') ++line; } /* * couldn't read as much from file2 as from file1; checked * here because there might be a difference before we got * to this point, which would have precedence. */ if (len2 < len1) endoffile(file2); } } /* * otoi -- * octal/decimal string to u_long */ static u_long otoi(C) register char *C; /* argument string */ { register u_long val; /* return value */ register int base; /* number base */ base = (*C == '0') ? 8 : 10; for (val = 0; isdigit(*C); ++C) val = val * base + *C - '0'; return(val); } /* * error -- * print I/O error message and die */ static error(filename) char *filename; { extern int errno; int sverrno; if (!silent) { sverrno = errno; (void)fprintf(stderr, "cmp: %s: ", filename); errno = sverrno; perror((char *)NULL); } exit(ERR); } /* * endoffile -- * print end-of-file message and exit indicating the files were different */ static endoffile(filename) char *filename; { /* 32V put this message on stdout, S5 does it on stderr. */ if (!silent) (void)fprintf(stderr, "cmp: EOF on %s\n", filename); exit(DIFF); } /* * usage -- * print usage and die */ static usage() { fputs("usage: cmp [-ls] file1 file2 [skip1] [skip2]\n", stderr); exit(ERR); } n int optind; int ch; u_long otoi(); while ((ch = getopt(argc, argv, "ls")) != EOF) switch(ch) { case 'l': /* print all differences */ allbin/true.sh 444 0 12 7 4013202661 6020 exit 0 .Ë .. adbudÒ awkcÀ tp.c¸ shc˜ cshh? sed1: makei/ diff.( asfi$ df.c#hostid.c"mail.cc! du.cc strip.cstty.c cat.c ldc logintime.ces. ed.cc arc dd.cd su.cd rm.cdÿ pr.cdþ cp.cdý cmp.cütrue.shcûfalse.shú ln.c.ùgrep.chøwrite.c÷ mv.c.öpasswdòecho.ccñ disklabelëbin/false.sh 444 0 12 7 4013202662 6134 exit 1 .Ë .. adbudÒ awkcÀ tp.c¸ shc˜ cshh? sed1: makei/ diff.( asfi$ df.c#hostid.c"mail.cc! du.cc strip.cstty.c cat.c ldc logintime.ces. ed.cc arc dd.cd su.cd rm.cdÿ pr.cdþ cp.cdý cmp.cütrue.shcûfalse.shú ln.c.ùgrep.chøwrite.c÷ mv.c.öpasswdòecho.ccñ disklabelëbin/ln.c 444 0 12 3111 4013202662 5342 static char sccsid[] = "@(#)ln.c 4.6 11/15/85"; /* * ln */ #include #include #include #include struct stat stb; int fflag; /* force flag set? */ int sflag; char name[BUFSIZ]; char *rindex(); extern int errno; main(argc, argv) int argc; register char **argv; { register int i, r; argc--, argv++; again: if (argc && strcmp(argv[0], "-f") == 0) { fflag++; argv++; argc--; } if (argc && strcmp(argv[0], "-s") == 0) { sflag++; argv++; argc--; } if (argc == 0) goto usage; else if (argc == 1) { argv[argc] = "."; argc++; } if (sflag == 0 && argc > 2) { if (stat(argv[argc-1], &stb) < 0) goto usage; if ((stb.st_mode&S_IFMT) != S_IFDIR) goto usage; } r = 0; for(i = 0; i < argc-1; i++) r |= linkit(argv[i], argv[argc-1]); exit(r); usage: fprintf(stderr, "Usage: ln [ -s ] f1\nor: ln [ -s ] f1 f2\nln [ -s ] f1 ... fn d2\n"); exit(1); } int link(), symlink(); linkit(from, to) char *from, *to; { char *tail; int (*linkf)() = sflag ? symlink : link; /* is target a directory? */ if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) { printf("%s is a directory\n", from); return (1); } if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) { tail = rindex(from, '/'); if (tail == 0) tail = from; else tail++; sprintf(name, "%s/%s", to, tail); to = name; } if ((*linkf)(from, to) < 0) { if (errno == EEXIST || sflag) perror(to); else if (access(from, 0) < 0) perror(from); else perror(to); return (1); } return (0); } ; case '?': default: usage(); } argv += optind; argc -= optind; if (argc < 2 || argc > 4) usage(); /* open up files; "-" is stdin */ file1 = argv[0]; if (strcmp(file1, "-") && (fd1 = open(file1, O_RDONLY, 0)) < 0) error(file1); file2 = argv[1]; if ((fd2 = open(file2, O_RDONLY, 0)) < 0) error(file2); /* handle skip arguments */ if (argc > 2) { skip(otoi(argv[2]), fd1, file1); if (argc == 4) skip(otoi(abin/grep.c 444 0 12 16615 4013202662 5723 #ifndef lint static char sccsid[] = "@(#)grep.c 4.6 (Berkeley) 5/14/84"; #endif /* * grep -- print lines matching (or not matching) a pattern * * status returns: * 0 - ok, and some matches * 1 - ok, but no matches * 2 - some error */ #include #include #define CBRA 1 #define CCHR 2 #define CDOT 4 #define CCL 6 #define NCCL 8 #define CDOL 10 #define CEOF 11 #define CKET 12 #define CBRC 14 #define CLET 15 #define CBACK 18 #define STAR 01 #define LBSIZE BUFSIZ #define ESIZE 256 #define NBRA 9 char expbuf[ESIZE]; long lnum; char linebuf[LBSIZE+1]; char ybuf[ESIZE]; int bflag; int lflag; int nflag; int cflag; int vflag; int nfile; int hflag = 1; int sflag; int yflag; int wflag; int retcode = 0; int circf; int blkno; long tln; int nsucc; char *braslist[NBRA]; char *braelist[NBRA]; char bittab[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; main(argc, argv) char **argv; { while (--argc > 0 && (++argv)[0][0]=='-') switch (argv[0][1]) { case 'i': case 'y': yflag++; continue; case 'w': wflag++; continue; case 'h': hflag = 0; continue; case 's': sflag++; continue; case 'v': vflag++; continue; case 'b': bflag++; continue; case 'l': lflag++; continue; case 'c': cflag++; continue; case 'n': nflag++; continue; case 'e': --argc; ++argv; goto out; default: errexit("grep: unknown flag\n", (char *)NULL); continue; } out: if (argc<=0) exit(2); if (yflag) { register char *p, *s; for (s = ybuf, p = *argv; *p; ) { if (*p == '\\') { *s++ = *p++; if (*p) *s++ = *p++; } else if (*p == '[') { while (*p != '\0' && *p != ']') *s++ = *p++; } else if (islower(*p)) { *s++ = '['; *s++ = toupper(*p); *s++ = *p++; *s++ = ']'; } else *s++ = *p++; if (s >= ybuf+ESIZE-5) errexit("grep: argument too long\n", (char *)NULL); } *s = '\0'; *argv = ybuf; } compile(*argv); nfile = --argc; if (argc<=0) { if (lflag) exit(1); execute((char *)NULL); } else while (--argc >= 0) { argv++; execute(*argv); } exit(retcode != 0 ? retcode : nsucc == 0); } compile(astr) char *astr; { register c; register char *ep, *sp; char *cstart; char *lastep; int cclcnt; char bracket[NBRA], *bracketp; int closed; char numbra; char neg; ep = expbuf; sp = astr; lastep = 0; bracketp = bracket; closed = numbra = 0; if (*sp == '^') { circf++; sp++; } if (wflag) *ep++ = CBRC; for (;;) { if (ep >= &expbuf[ESIZE]) goto cerror; if ((c = *sp++) != '*') lastep = ep; switch (c) { case '\0': if (wflag) *ep++ = CLET; *ep++ = CEOF; return; case '.': *ep++ = CDOT; continue; case '*': if (lastep==0 || *lastep==CBRA || *lastep==CKET || *lastep == CBRC || *lastep == CLET) goto defchar; *lastep |= STAR; continue; case '$': if (*sp != '\0') goto defchar; *ep++ = CDOL; continue; case '[': if(&ep[17] >= &expbuf[ESIZE]) goto cerror; *ep++ = CCL; neg = 0; if((c = *sp++) == '^') { neg = 1; c = *sp++; } cstart = sp; do { if (c=='\0') goto cerror; if (c=='-' && sp>cstart && *sp!=']') { for (c = sp[-2]; c<*sp; c++) ep[c>>3] |= bittab[c&07]; sp++; } ep[c>>3] |= bittab[c&07]; } while((c = *sp++) != ']'); if(neg) { for(cclcnt = 0; cclcnt < 16; cclcnt++) ep[cclcnt] ^= -1; ep[0] &= 0376; } ep += 16; continue; case '\\': if((c = *sp++) == 0) goto cerror; if(c == '<') { *ep++ = CBRC; continue; } if(c == '>') { *ep++ = CLET; continue; } if(c == '(') { if(numbra >= NBRA) { goto cerror; } *bracketp++ = numbra; *ep++ = CBRA; *ep++ = numbra++; continue; } if(c == ')') { if(bracketp <= bracket) { goto cerror; } *ep++ = CKET; *ep++ = *--bracketp; closed++; continue; } if(c >= '1' && c <= '9') { if((c -= '1') >= closed) goto cerror; *ep++ = CBACK; *ep++ = c; continue; } defchar: default: *ep++ = CCHR; *ep++ = c; } } cerror: errexit("grep: RE error\n", (char *)NULL); } execute(file) char *file; { register char *p1, *p2; register c; if (file) { if (freopen(file, "r", stdin) == NULL) { perror(file); retcode = 2; } } lnum = 0; tln = 0; for (;;) { lnum++; p1 = linebuf; while ((c = getchar()) != '\n') { if (c == EOF) { if (cflag) { if (nfile>1) printf("%s:", file); printf("%D\n", tln); fflush(stdout); } return; } *p1++ = c; if (p1 >= &linebuf[LBSIZE-1]) break; } *p1++ = '\0'; p1 = linebuf; p2 = expbuf; if (circf) { if (advance(p1, p2)) goto found; goto nfound; } /* fast check for first character */ if (*p2==CCHR) { c = p2[1]; do { if (*p1!=c) continue; if (advance(p1, p2)) goto found; } while (*p1++); goto nfound; } /* regular algorithm */ do { if (advance(p1, p2)) goto found; } while (*p1++); nfound: if (vflag) succeed(file); continue; found: if (vflag==0) succeed(file); } } advance(lp, ep) register char *lp, *ep; { register char *curlp; char c; char *bbeg; int ct; for (;;) switch (*ep++) { case CCHR: if (*ep++ == *lp++) continue; return(0); case CDOT: if (*lp++) continue; return(0); case CDOL: if (*lp==0) continue; return(0); case CEOF: return(1); case CCL: c = *lp++ & 0177; if(ep[c>>3] & bittab[c & 07]) { ep += 16; continue; } return(0); case CBRA: braslist[*ep++] = lp; continue; case CKET: braelist[*ep++] = lp; continue; case CBACK: bbeg = braslist[*ep]; if (braelist[*ep]==0) return(0); ct = braelist[*ep++] - bbeg; if(ecmp(bbeg, lp, ct)) { lp += ct; continue; } return(0); case CBACK|STAR: bbeg = braslist[*ep]; if (braelist[*ep]==0) return(0); ct = braelist[*ep++] - bbeg; curlp = lp; while(ecmp(bbeg, lp, ct)) lp += ct; while(lp >= curlp) { if(advance(lp, ep)) return(1); lp -= ct; } return(0); case CDOT|STAR: curlp = lp; while (*lp++); goto star; case CCHR|STAR: curlp = lp; while (*lp++ == *ep); ep++; goto star; case CCL|STAR: curlp = lp; do { c = *lp++ & 0177; } while(ep[c>>3] & bittab[c & 07]); ep += 16; goto star; star: if(--lp == curlp) { continue; } if(*ep == CCHR) { c = ep[1]; do { if(*lp != c) continue; if(advance(lp, ep)) return(1); } while(lp-- > curlp); return(0); } do { if (advance(lp, ep)) return(1); } while (lp-- > curlp); return(0); case CBRC: if (lp == expbuf) continue; #define uletter(c) (isalpha(c) || (c) == '_') if (uletter(*lp) || isdigit(*lp)) if (!uletter(lp[-1]) && !isdigit(lp[-1])) continue; return (0); case CLET: if (!uletter(*lp) && !isdigit(*lp)) continue; return (0); default: errexit("grep RE botch\n", (char *)NULL); } } succeed(f) char *f; { nsucc = 1; if (sflag) return; if (cflag) { tln++; return; } if (lflag) { printf("%s\n", f); fflush(stdout); fseek(stdin, 0l, 2); return; } if (nfile > 1 && hflag) printf("%s:", f); if (bflag) printf("%u:", blkno); if (nflag) printf("%ld:", lnum); printf("%s\n", linebuf); fflush(stdout); } ecmp(a, b, count) char *a, *b; { register cc = count; while(cc--) if(*a++ != *b++) return(0); return(1); } errexit(s, f) char *s, *f; { fprintf(stderr, s, f); exit(2); } the stupid lines, which means that -l is a * *much* faster version, i.e., unless you really * *want* to knobin/write.c 444 0 12 10756 5511210534 6121 #ifndef lint static char *sccsid = "@(#)write.c 4.13.1 12/31/93"; #endif /* * write to another user */ #include #include #include #include #include #include #include #define NMAX sizeof(ubuf.ut_name) #define LMAX sizeof(ubuf.ut_line) char *strcat(); char *strcpy(); struct utmp ubuf; int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; char me[NMAX + 1] = "???"; char *him; char *mytty; char histty[32]; char ttybuf[32]; char *histtya; char *ttyname(); char *rindex(); int logcnt; int eof(); int timout(); FILE *tf; char *getenv(); time_t time(); main(argc, argv) int argc; char *argv[]; { struct stat stbuf; register i; register FILE *uf; int c1, c2; long clock = time(0); int suser = getuid() == 0; int nomesg = 0; struct tm *localtime(); struct tm *localclock = localtime( &clock ); if (argc < 2) { fprintf(stderr, "Usage: write user [ttyname]\n"); exit(1); } him = argv[1]; if (argc > 2) histtya = argv[2]; if ((uf = fopen("/etc/utmp", "r")) == NULL) { perror("write: Can't open /etc/utmp"); if (histtya == 0) exit(10); goto cont; } mytty = ttyname(2); if (mytty == NULL) { fprintf(stderr, "write: Can't find your tty\n"); exit(1); } if (stat(mytty, &stbuf) < 0) { perror("write: Can't stat your tty"); exit(1); } if ((stbuf.st_mode&020) == 0) { fprintf(stderr, "write: You have write permission turned off\n"); if (!suser) exit(1); } mytty = rindex(mytty, '/') + 1; if (histtya) { strcpy(histty, "/dev/"); strcat(histty, histtya); } while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) { if (ubuf.ut_name[0] == '\0') continue; if (strcmp(ubuf.ut_line, mytty)==0) { for (i=0; i 1) { fprintf(stderr, "write: %s logged in more than once ... writing to %s\n", him, histty+5); } cont: if (access(histty, 0) < 0) { fprintf(stderr, "write: No such tty\n"); exit(1); } signal(SIGALRM, timout); alarm(5); if ((tf = fopen(histty, "w")) == NULL) { fprintf(stderr, "write: Permission denied\n"); exit(1); } alarm(0); sigs(eof); { char hostname[32]; gethostname(hostname, sizeof (hostname)); fprintf(tf, "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007", me, hostname, mytty, localclock->tm_hour, localclock->tm_min); fflush(tf); } for (;;) { char buf[BUFSIZ]; register char *bp; i = read(0, buf, sizeof buf); if (i <= 0) eof(); if (buf[0] == '!') { buf[i] = 0; ex(buf); continue; } for (bp = buf; --i >= 0; bp++) { if (*bp == '\n') putc('\r', tf); if (!isascii(*bp)) { putc('M', tf); putc('-', tf); *bp = toascii(*bp); } if (isprint(*bp) || *bp == ' ' || *bp == '\t' || *bp == '\n') { putc(*bp, tf); } else { putc('^', tf); putc(*bp ^ 0100, tf); } if (*bp == '\n') fflush(tf); if (ferror(tf) || feof(tf)) { printf("\n\007Write failed (%s logged out?)\n", him); exit(1); } } } } timout() { fprintf(stderr, "write: Timeout opening their tty\n"); exit(1); } eof() { fprintf(tf, "EOF\r\n"); exit(0); } ex(bp) char *bp; { register i; sigs(SIG_IGN); i = fork(); if (i < 0) { printf("Try again\n"); goto out; } if (i == 0) { fclose(tf); /* Close his terminal */ setgid(getgid()); /* Give up effective group privs */ sigs((int (*)())0); execl(getenv("SHELL") ? getenv("SHELL") : "/bin/sh", "sh", "-c", bp+1, 0); exit(0); } while (wait((int *)NULL) != i) ; printf("!\n"); out: sigs(eof); } sigs(sig) int (*sig)(); { register i; for (i=0; signum[i]; i++) signal(signum[i], sig); } tv[1].tv_sec = stbin/mv.c 444 0 12 13212 4013202662 5376 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)mv.c 5.3 (Berkeley) 5/15/86"; #endif not lint /* * mv file1 file2 */ #include #include #include #include #include #include #include #define DELIM '/' #define MODEBITS 07777 #define ISDIR(st) (((st).st_mode&S_IFMT) == S_IFDIR) #define ISLNK(st) (((st).st_mode&S_IFMT) == S_IFLNK) #define ISREG(st) (((st).st_mode&S_IFMT) == S_IFREG) #define ISDEV(st) \ (((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK) char *sprintf(); char *dname(); struct stat s1, s2; int iflag = 0; /* interactive mode */ int fflag = 0; /* force overwriting */ extern unsigned errno; main(argc, argv) register char *argv[]; { register i, r; register char *arg; char *dest; if (argc < 2) goto usage; while (argc > 1 && *argv[1] == '-') { argc--; arg = *++argv; /* * all files following a null option * are considered file names */ if (*(arg+1) == '\0') break; while (*++arg != '\0') switch (*arg) { case 'i': iflag++; break; case 'f': fflag++; break; default: goto usage; } } if (argc < 3) goto usage; dest = argv[argc-1]; if (stat(dest, &s2) >= 0 && ISDIR(s2)) { r = 0; for (i = 1; i < argc-1; i++) r |= movewithshortname(argv[i], dest); exit(r); } if (argc > 3) goto usage; r = move(argv[1], argv[2]); exit(r); /*NOTREACHED*/ usage: fprintf(stderr, "usage: mv [-if] f1 f2 or mv [-if] f1 ... fn d1 (`fn' is a file or directory)\n"); return (1); } movewithshortname(src, dest) char *src, *dest; { register char *shortname; char target[MAXPATHLEN + 1]; shortname = dname(src); if (strlen(dest) + strlen(shortname) > MAXPATHLEN - 1) { error("%s/%s: pathname too long", dest, shortname); return (1); } sprintf(target, "%s/%s", dest, shortname); return (move(src, target)); } move(source, target) char *source, *target; { int targetexists; if (lstat(source, &s1) < 0) { Perror2(source, "Cannot access"); return (1); } /* * First, try to rename source to destination. * The only reason we continue on failure is if * the move is on a nondirectory and not across * file systems. */ targetexists = lstat(target, &s2) >= 0; if (targetexists) { if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) { error("%s and %s are identical", source, target); return (1); } if (iflag && !fflag && isatty(fileno(stdin)) && query("remove %s? ", target) == 0) return (1); if (access(target, 2) < 0 && !fflag && isatty(fileno(stdin))) { if (query("override protection %o for %s? ", s2.st_mode & MODEBITS, target) == 0) return (1); } } if (rename(source, target) >= 0) return (0); if (errno != EXDEV) { Perror2(errno == ENOENT && targetexists == 0 ? target : source, "rename"); return (1); } if (ISDIR(s1)) { error("can't mv directories across file systems"); return (1); } if (targetexists && unlink(target) < 0) { Perror2(target, "Cannot unlink"); return (1); } /* * File can't be renamed, try to recreate the symbolic * link or special device, or copy the file wholesale * between file systems. */ if (ISLNK(s1)) { register m; char symln[MAXPATHLEN + 1]; m = readlink(source, symln, sizeof (symln) - 1); if (m < 0) { Perror(source); return (1); } symln[m] = '\0'; m = umask(~(s1.st_mode & MODEBITS)); if (symlink(symln, target) < 0) { Perror(target); return (1); } (void) umask(m); goto cleanup; } if (ISDEV(s1)) { struct timeval tv[2]; if (mknod(target, s1.st_mode, s1.st_rdev) < 0) { Perror(target); return (1); } tv[0].tv_sec = s1.st_atime; tv[0].tv_usec = 0; tv[1].tv_sec = s1.st_mtime; tv[1].tv_usec = 0; (void) utimes(target, tv); goto cleanup; } if (ISREG(s1)) { register int fi, fo, n; struct timeval tv[2]; char buf[MAXBSIZE]; fi = open(source, 0); if (fi < 0) { Perror(source); return (1); } fo = creat(target, s1.st_mode & MODEBITS); if (fo < 0) { Perror(target); close(fi); return (1); } for (;;) { n = read(fi, buf, sizeof buf); if (n == 0) { break; } else if (n < 0) { Perror2(source, "read"); close(fi); close(fo); return (1); } else if (write(fo, buf, n) != n) { Perror2(target, "write"); close(fi); close(fo); return (1); } } close(fi); close(fo); tv[0].tv_sec = s1.st_atime; tv[0].tv_usec = 0; tv[1].tv_sec = s1.st_mtime; tv[1].tv_usec = 0; (void) utimes(target, tv); goto cleanup; } error("%s: unknown file type %o", source, s1.st_mode); return (1); cleanup: if (unlink(source) < 0) { Perror2(source, "Cannot unlink"); return (1); } return (0); } /*VARARGS*/ query(prompt, a1, a2) char *a1; { register int i, c; fprintf(stderr, prompt, a1, a2); i = c = getchar(); while (c != '\n' && c != EOF) c = getchar(); return (i == 'y'); } char * dname(name) register char *name; { register char *p; p = name; while (*p) if (*p++ == DELIM && *p) name = p; return name; } /*VARARGS*/ error(fmt, a1, a2) char *fmt; { fprintf(stderr, "mv: "); fprintf(stderr, fmt, a1, a2); fprintf(stderr, "\n"); } Perror(s) char *s; { char buf[MAXPATHLEN + 10]; sprintf(buf, "mv: %s", s); perror(buf); } Perror2(s1, s2) char *s1, *s2; { char buf[MAXPATHLEN + 20]; sprintf(buf, "mv: %s: %s", s1, s2); perror(buf); } ol512) n = 512; if((n=fread(rbufp,1,n,file)) <= 0){ fclose(file); *rbufp = 0376; } else { rbufp += n; if (rbufp >= &buffer[BUFS]) rbufp = bbin/passwd/ 755 0 12 0 6024536000 6007 bin/passwd/Makefile 644 0 12 2633 5326557242 7557 # # Copyright (c) 1988 The Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that the above copyright notice and this paragraph are # duplicated in all such forms and that any documentation, # advertising materials, and other materials related to such # distribution and use acknowledge that the software was developed # by the University of California, Berkeley. The name of the # University may not be used to endorse or promote products derived # from this software without specific prior written permission. # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # @(#)Makefile 5.4 (Berkeley) 2/22/89 # CFLAGS= -I. -O SEPFLAG= -i LIBC= /lib/libc.a SRCS= passwd.c OBJS= passwd.o MAN= passwd.0 MANSRC= passwd.1 all: passwd passwd: ${LIBC} ${OBJS} ${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS} ${MAN}: ${MANSRC} /usr/man/manroff ${MANSRC} > ${MAN} clean: rm -f ${OBJS} ${MAN} core passwd cleandir: clean rm -f tags .depend depend: ${SRCS} mkdep -p ${CFLAGS} ${SRCS} install: ${MAN} passwd install -s -o root -g bin -m 4755 passwd ${DESTDIR}/bin/passwd install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat1 lint: ${SRCS} lint ${CFLAGS} ${SRCS} tags: ${SRCS} ctags ${SRCS} ster char *shortname; char target[MAXPATHLEN + 1]; shortname = dname(src); if (strlen(dest) + strbin/passwd/passwd.1 644 0 12 3412 4433456055 7474 .\" Copyright (c) 1988 The Regents of the University of California. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms are permitted .\" provided that the above copyright notice and this paragraph are .\" duplicated in all such forms and that any documentation, .\" advertising materials, and other materials related to such .\" distribution and use acknowledge that the software was developed .\" by the University of California, Berkeley. The name of the .\" University may not be used to endorse or promote products derived .\" from this software without specific prior written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .\" @(#)passwd.1 6.5 (Berkeley) 2/22/89 .\" .TH PASSWD 1 "February 22, 1989" .UC 4 .SH NAME passwd \- change password file information .SH SYNOPSIS .B passwd [ user ] .SH DESCRIPTION .I Passwd changes the user's password. First, the user is prompted for their old password, and then, if that is correct, for the new password. The new password must be entered twice to forestall any typing errors. The super-user is not prompted for the old password. .PP Once the password has been verified, .I passwd uses .IR mkpasswd (8) to update the user database. This is run in the background, and, at very large sites could take several minutes. Until this update is completed, the password file is unavailable for other updates and the new password will not be available to programs. .SH FILES .DT /etc/master.passwd the user database .RE .SH "SEE ALSO" chpass(1), login(1), passwd(5), mkpasswd(8), vipw(8) .br Robert Morris and Ken Thompson, .I UNIX password security and that any documentation, .\" advertising materials, and other materials related to such .\" distribution and use acknowledge that the software was developed .\" by the University of California, Berkeley. The name of the .\" University may notbin/passwd/passwd.c 644 0 12 14613 4433456056 7604 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)passwd.c 4.35 (Berkeley) 3/16/89"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include uid_t uid; main(argc, argv) int argc; char **argv; { extern int errno; struct passwd *pw; struct rlimit rlim; FILE *temp_fp; int fd; char *fend, *np, *passwd, *temp, *tend; char from[MAXPATHLEN], to[MAXPATHLEN]; char *getnewpasswd(); uid = getuid(); switch(--argc) { case 0: if (!(pw = getpwuid(uid))) { fprintf(stderr, "passwd: unknown user: uid %u\n", uid); exit(1); } break; case 1: if (!(pw = getpwnam(argv[1]))) { fprintf(stderr, "passwd: unknown user %s.\n", argv[1]); exit(1); } if (uid && uid != pw->pw_uid) { fprintf(stderr, "passwd: %s\n", strerror(EACCES)); exit(1); } break; default: fprintf(stderr, "usage: passwd [user]\n"); exit(1); } (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGTSTP, SIG_IGN); rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &rlim); (void)setrlimit(RLIMIT_FSIZE, &rlim); (void)umask(0); temp = _PATH_PTMP; if ((fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) { if (errno == EEXIST) { fprintf(stderr, "passwd: password file busy -- try again later.\n"); exit(0); } fprintf(stderr, "passwd: %s: %s", temp, strerror(errno)); goto bad; } if (!(temp_fp = fdopen(fd, "w"))) { fprintf(stderr, "passwd: can't write %s\n", temp); goto bad; } passwd = _PATH_MASTERPASSWD; if (!freopen(passwd, "r", stdin)) { fprintf(stderr, "passwd: can't read %s\n", passwd); goto bad; } printf("Changing password for %s.\n", pw->pw_name); np = getnewpasswd(pw, temp); if (!copy(pw->pw_name, np, temp_fp, pw)) goto bad; (void)fclose(temp_fp); (void)fclose(stdin); switch(fork()) { case 0: break; case -1: fprintf(stderr, "passwd: can't fork"); goto bad; /* NOTREACHED */ default: exit(0); /* NOTREACHED */ } if (makedb(temp)) { fprintf(stderr, "passwd: mkpasswd failed"); bad: fprintf(stderr, "; password unchanged.\n"); (void)unlink(temp); exit(1); } /* * possible race; have to rename four files, and someone could slip * in between them. LOCK_EX and rename the ``passwd.dir'' file first * so that getpwent(3) can't slip in; the lock should never fail and * it's unclear what to do if it does. Rename ``ptmp'' last so that * passwd/vipw/chpass can't slip in. */ (void)setpriority(PRIO_PROCESS, 0, -20); fend = strcpy(from, temp) + strlen(temp); tend = strcpy(to, _PATH_PASSWD) + strlen(_PATH_PASSWD); bcopy(".dir", fend, 5); bcopy(".dir", tend, 5); if ((fd = open(from, O_RDONLY, 0)) >= 0) (void)flock(fd, LOCK_EX); /* here we go... */ (void)rename(from, to); bcopy(".pag", fend, 5); bcopy(".pag", tend, 5); (void)rename(from, to); bcopy(".orig", fend, 6); (void)rename(from, _PATH_PASSWD); (void)rename(temp, passwd); /* done! */ exit(0); } copy(name, np, fp, pw) char *name, *np; FILE *fp; struct passwd *pw; { register int done; register char *p; char buf[256]; for (done = 0; fgets(buf, sizeof(buf), stdin);) { /* skip lines that are too big */ if (!index(buf, '\n')) { fprintf(stderr, "passwd: line too long.\n"); return(0); } if (done) { fprintf(fp, "%s", buf); continue; } if (!(p = index(buf, ':'))) { fprintf(stderr, "passwd: corrupted entry.\n"); return(0); } *p = '\0'; if (strcmp(buf, name)) { *p = ':'; fprintf(fp, "%s", buf); continue; } if (!(p = index(++p, ':'))) { fprintf(stderr, "passwd: corrupted entry.\n"); return(0); } /* * reset change time to zero; when classes are implemented, * go and get the "offset" value for this class and reset * the timer. */ fprintf(fp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name, np, pw->pw_uid, pw->pw_gid, pw->pw_class, 0L, pw->pw_expire, pw->pw_gecos, pw->pw_dir, pw->pw_shell); done = 1; } return(1); } char * getnewpasswd(pw, temp) register struct passwd *pw; char *temp; { register char *p, *t; char buf[10], salt[2], *crypt(), *getpass(); time_t time(); if (uid && pw->pw_passwd && strcmp(crypt(getpass("Old password:"), pw->pw_passwd), pw->pw_passwd)) { (void)printf("passwd: %s.\n", strerror(EACCES)); (void)unlink(temp); exit(1); } for (buf[0] = '\0';;) { p = getpass("New password:"); if (!*p) { (void)printf("Password unchanged.\n"); (void)unlink(temp); exit(0); } if (strlen(p) <= 5) { printf("Please enter a longer password.\n"); continue; } for (t = p; *t && islower(*t); ++t); if (!*t) { printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n"); continue; } (void)strcpy(buf, p); if (!strcmp(buf, getpass("Retype new password:"))) break; printf("Mismatch; try again, EOF to quit.\n"); } /* grab a random printable character that isn't a colon */ (void)srandom((int)time((time_t *)NULL)); while ((salt[0] = random() % 93 + 33) == ':'); while ((salt[1] = random() % 93 + 33) == ':'); return(crypt(buf, salt)); } makedb(file) char *file; { int status, pid, w; if (!(pid = vfork())) { execl(_PATH_MKPASSWD, "mkpasswd", "-p", file, NULL); _exit(127); } while ((w = wait(&status)) != pid && w != -1); return(w == -1 || status); } utcp(c); if (c=='\n') line++; return; } switch (c) { case ' ': nspace++; col++; return; case '\n':bin/echo.c 444 0 12 614 4013202663 5635 static char *sccsid = "@(#)echo.c 4.2 (Berkeley) 5/27/85"; #include main(argc, argv) int argc; char *argv[]; { register int i, nflg; nflg = 0; if(argc > 1 && argv[1][0] == '-' && argv[1][1] == 'n' && !argv[1][2]) { nflg++; argc--; argv++; } for(i=1; i disklabel.0 disklabel.5.0: disklabel.5.5 /usr/man/manroff disklabel.5.5 > disklabel.5.0 el: disklabel.o cc ${CFLAGS} ${SEPFLAG} -o $@ $@.o -lutil install: all install -s -c -o bin -g operator -m 2550 disklabel \ ${DESTDIR}/bin/disklabel install -c -o bin -g bin -m 444 disklabel.5.0 \ ${DESTDIR}${MANDIR}5/disklabel.0 install -c -o bin -g bin -m 444 disklabel.0 \ ${DESTDIR}/${MANDIR}8/disklabel.0 clean: rm -f *.o *.0 *.core disklabel disklabin/disklabel/disklabel.5.5 644 0 12 31711 5746106513 10747 .\" Copyright (c) 1987, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Symmetric Computer Systems. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)disklabel.5.5 8.1.1 (2.11BSD) 1995/04/21 .\" .TH DISKLABEL 5 "April 21, 1995" .UC 2 .SH NAME disklabel \- disk pack label .SH SYNOPSIS .B #include .SH DESCRIPTION Each disk or disk pack on a system may contain a disk label which provides detailed information about the geometry of the disk and the partitions into which the disk is divided. It should be initialized when the disk is formatted, and may be changed later with the .IR disklabel (8) program. This information is used by the system disk driver and by the bootstrap program to determine how to program the drive and where to find the filesystems on the disk partitions. Additional information is used by the filesystem in order to use the disk most efficiently and to locate important filesystem information. The description of each partition contains an identifier for the partition type (standard filesystem, swap area, etc.). The filesystem updates the in-core copy of the label if it contains incomplete information about the filesystem. .PP The label is located in sector number .B LABELSECTOR of the drive, usually sector 0 where it may be found without any information about the disk geometry. It is at an offset .B LABELOFFSET from the beginning of the sector, to allow room for the initial bootstrap. The disk sector containing the label is normally made read-only so that it is not accidentally overwritten by pack-to-pack copies or swap operations; the .B DIOCWLABEL .IR ioctl (2), which is done as needed by the .IR disklabel (8) program. .PP A copy of the in-core label for a disk can be obtained with the .B DIOCGDINFO .IR ioctl (2); this works with a file descriptor for a block or character (``raw'') device for any partition of the disk. The in-core copy of the label is set by the .B DIOCSDINFO .IR ioctl (2). The offset of a partition cannot generally be changed while it is open, nor can it be made smaller while it is open. One exception is that any change is allowed if no label was found on the disk, and the driver was able to construct only a skeletal label without partition information. Finally, the .B DIOCWDINFO .IR ioctl (2) operation sets the in-core label and then updates the on-disk label; there must be an existing label on the disk for this operation to succeed. Thus, the initial label for a disk or disk pack must be installed by writing to the raw disk. All of these operations are normally done using .IR disklabel (8). .PP The format of the disk label, as specified in .I \ , is: .PP .nf /* * Disk description table, see disktab(5) */ #define _PATH_DISKTAB "/etc/disktab" /* * Each disk has a label which includes information about the hardware * disk geometry, filesystem partitions, and drive specific information. * The label is in block 0 or 1, possibly offset from the beginning * to leave room for a bootstrap, etc. */ /* These should be defined per controller/drive elsewhere, not here! */ #define LABELSECTOR 1 /* sector containing label */ #define LABELOFFSET 0 /* offset of label in sector */ #define DISKMAGIC ((u_long) 0x82564557) /* The disk magic number */ #define MAXPARTITIONS 8 /* * 2.11BSD's disklabels are different than 4.4BSD for a couple reasons: * * 1) D space is precious in the 2.11 kernel. Many of the fields do * not need to be 'long' (or even a 'short'), a 'short' (or 'char') * is more than adequate. If anyone ever ports the FFS to a PDP11 * changing the label format will be the least of the problems. * * 2) There is no need to support a bootblock more than 512 bytes long. * The hardware (disk bootroms) only read the first sector, thus the * label is always at sector 1 (the second half of the first file- * system block). * * Almost all of the fields have been retained but with reduced sizes. * This is for future expansion and to ease the porting of the various * utilities which use the disklabel structure. The 2.11 kernel uses * very little other than the partition tables. Indeed only the * partition tables are resident in the kernel address space, the actual * label block is allocated external to the kernel and mapped in as * needed. */ struct disklabel { u_long d_magic; /* the magic number */ u_char d_type; /* drive type */ u_char d_subtype; /* controller/d_type specific */ char d_typename[16]; /* type name, e.g. "eagle" */ /* * d_packname contains the pack identifier and is returned when * the disklabel is read off the disk or in-core copy. * d_boot0 is the (optional) name of the primary (block 0) bootstrap * as found in /mdec. This is returned when using * getdiskbyname(3) to retrieve the values from /etc/disktab. */ #if defined(KERNEL) || defined(STANDALONE) char d_packname[16]; /* pack identifier */ #else union { char un_d_packname[16]; /* pack identifier */ char *un_d_boot0; /* primary bootstrap name */ } d_un; #define d_packname d_un.un_d_packname #define d_boot0 d_un.un_d_boot0 #endif /* ! KERNEL or STANDALONE */ /* disk geometry: */ u_short d_secsize; /* # of bytes per sector */ u_short d_nsectors; /* # of data sectors per track */ u_short d_ntracks; /* # of tracks per cylinder */ u_short d_ncylinders; /* # of data cylinders per unit */ u_short d_secpercyl; /* # of data sectors per cylinder */ u_long d_secperunit; /* # of data sectors per unit */ /* * Spares (bad sector replacements) below * are not counted in d_nsectors or d_secpercyl. * Spare sectors are assumed to be physical sectors * which occupy space at the end of each track and/or cylinder. */ u_short d_sparespertrack; /* # of spare sectors per track */ u_short d_sparespercyl; /* # of spare sectors per cylinder */ /* * Alternate cylinders include maintenance, replacement, * configuration description areas, etc. */ u_short d_acylinders; /* # of alt. cylinders per unit */ /* hardware characteristics: */ /* * d_interleave, d_trackskew and d_cylskew describe perturbations * in the media format used to compensate for a slow controller. * Interleave is physical sector interleave, set up by the formatter * or controller when formatting. When interleaving is in use, * logically adjacent sectors are not physically contiguous, * but instead are separated by some number of sectors. * It is specified as the ratio of physical sectors traversed * per logical sector. Thus an interleave of 1:1 implies contiguous * layout, while 2:1 implies that logical sector 0 is separated * by one sector from logical sector 1. * d_trackskew is the offset of sector 0 on track N * relative to sector 0 on track N-1 on the same cylinder. * Finally, d_cylskew is the offset of sector 0 on cylinder N * relative to sector 0 on cylinder N-1. */ u_short d_rpm; /* rotational speed */ u_char d_interleave; /* hardware sector interleave */ u_char d_trackskew; /* sector 0 skew, per track */ u_char d_cylskew; /* sector 0 skew, per cylinder */ u_char d_headswitch; /* head swith time, usec */ u_short d_trkseek; /* track-to-track seek, msec */ u_short d_flags; /* generic flags */ #define NDDATA 5 u_long d_drivedata[NDDATA]; /* drive-type specific information */ #define NSPARE 5 u_long d_spare[NSPARE]; /* reserved for future use */ u_long d_magic2; /* the magic number (again) */ u_short d_checksum; /* xor of data incl. partitions */ /* filesystem and partition information: */ u_short d_npartitions; /* number of partitions in following */ u_short d_bbsize; /* size of boot area at sn0, bytes */ u_short d_sbsize; /* max size of fs superblock, bytes */ struct partition { /* the partition table */ u_long p_size; /* number of sectors in partition */ u_long p_offset; /* starting sector */ u_short p_fsize; /* filesystem basic fragment size */ u_char p_fstype; /* filesystem type, see below */ u_char p_frag; /* filesystem fragments per block */ } d_partitions[MAXPARTITIONS]; /* actually may be more */ }; /* d_type values: */ #define DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */ #define DTYPE_MSCP 2 /* MSCP */ #define DTYPE_DEC 3 /* other DEC (rk, rl) */ #define DTYPE_SCSI 4 /* SCSI */ #define DTYPE_ESDI 5 /* ESDI interface */ #define DTYPE_ST506 6 /* ST506 etc. */ #define DTYPE_FLOPPY 7 /* floppy */ #ifdef DKTYPENAMES static char *dktypenames[] = { "unknown", "SMD", "MSCP", "old DEC", "SCSI", "ESDI", "ST506", "floppy", 0 }; #define DKMAXTYPES (sizeof(dktypenames) / sizeof(dktypenames[0]) - 1) #endif /* * Filesystem type and version. * Used to interpret other filesystem-specific * per-partition information. */ #define FS_UNUSED 0 /* unused */ #define FS_SWAP 1 /* swap */ #define FS_V6 2 /* Sixth Edition */ #define FS_V7 3 /* Seventh Edition */ #define FS_SYSV 4 /* System V */ /* * 2.11BSD uses type 5 filesystems even though block numbers are 4 bytes * (rather than the packed 3 byte format) and the directory structure is * that of 4.3BSD (long filenames). */ #define FS_V71K 5 /* V7 with 1K blocks (4.1,2.9,2.11) */ #define FS_V8 6 /* Eighth Edition, 4K blocks */ #define FS_BSDFFS 7 /* 4.2BSD fast file system */ #define FS_MSDOS 8 /* MSDOS file system */ #define FS_BSDLFS 9 /* 4.4BSD log file system */ #define FS_OTHER 10 /* in use, but unknown/unsupported */ #define FS_HPFS 11 /* OS/2 high-performance filesystem */ #define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */ #ifdef DKTYPENAMES static char *fstypenames[] = { "unused", "swap", "Version 6", "Version 7", "System V", "2.11BSD", "Eighth Edition", "4.2BSD", "MSDOS", "4.4LFS", "unknown", "HPFS", "ISO9660", 0 }; #define FSMAXTYPES (sizeof(fstypenames) / sizeof(fstypenames[0]) - 1) #endif /* * flags shared by various drives: */ #define D_REMOVABLE 0x01 /* removable media */ #define D_ECC 0x02 /* supports ECC */ #define D_BADSECT 0x04 /* supports bad sector forw. */ #define D_RAMDISK 0x08 /* disk emulator */ /* * Structure used to perform a format * or other raw operation, returning data * and/or register values. * Register identification and format * are device- and driver-dependent. */ struct format_op { char *df_buf; int df_count; /* value-result */ daddr_t df_startblk; int df_reg[8]; /* result */ }; /* * Structure used internally to retrieve * information about a partition on a disk. */ struct partinfo { struct disklabel *disklab; struct partition *part; }; /* * Disk-specific ioctls. */ /* get and set disklabel; DIOCGPART used internally */ #define DIOCGDINFO _IOR(d, 101, struct disklabel)/* get */ #define DIOCSDINFO _IOW(d, 102, struct disklabel)/* set */ #define DIOCWDINFO _IOW(d, 103, struct disklabel)/* set, update disk */ #define DIOCGPART _IOW(d, 104, struct partinfo) /* get partition */ /* do format operation, read or write */ #define DIOCRFORMAT _IOWR(d, 105, struct format_op) #define DIOCWFORMAT _IOWR(d, 106, struct format_op) #define DIOCSSTEP _IOW(d, 107, int) /* set step rate */ #define DIOCSRETRIES _IOW(d, 108, int) /* set # of retries */ #define DIOCWLABEL _IOW(d, 109, int) /* write en/disable label */ #define DIOCSBAD _IOW(d, 110, struct dkbad) /* set kernel dkbad */ #ifndef KERNEL struct disklabel *getdiskbyname(); #endif .fi .SH SEE ALSO .IR disklabel (8) without partition information. Finally, the .B DIOCWDIbin/disklabel/disklabel.8 644 0 12 22725 5767212603 10615 .\" Copyright (c) 1987, 1988, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" Symmetric Computer Systems. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)disklabel.8 8.2.1 (2.11BSD) 1995/04/21 .\" .TH DISKLABEL 8 "April 21, 1995" .UC 2 .SH NAME disklabel \- read and write disk pack label .SH SYNOPSIS .B disklabel \-r .IR disk .br .B disklabel \-w [ .B \-r ] .IR disk .IR disktype [ .IR packid ] .br .B disklabel \-e [ .B \-r ] .IR disk .br .B disklabel \-R [ .B \-r ] .IR disk .IR protofile .br .B disklabel [ .B \-NW ] .IR disk .sp .B disklabel \-B [ .B \-b .IR boot ] .IR disk [ .IR disktype ] .br .B disklabel \-w \-B [ .B \-b .IR boot ] .IR disk .IR disktype [ .IR packid ] .br .B disklabel \-R \-B [ .B \-b .IR boot ] .IR disk .IR protofile [ .IR disktype ] .SH DESCRIPTION .B Disklabel can be used to install, examine or modify the label on a disk drive or pack. When writing the label, it can be used to change the drive identification, the disk partitions on the drive, or to replace a damaged label. On some systems, .B disklabel can be used to install bootstrap code as well. There are several forms of the command that read (display), install or edit the label on a disk. Each form has an additional option, \fB\-r\fP, which causes the label to be read from or written to the disk directly, rather than going through the system's in-core copy of the label. This option may allow a label to be installed on a disk without kernel support for a label, such as when labels are first installed on a system; it must be used when first installing a label on a disk. The specific effect of .B \-r is described under each command. The read and install forms also support the .B \-B option to install bootstrap code. These variants are described later. .PP The first form of the command (read) is used to examine the label on the named disk drive (e.g. ra0 or /dev/rra0a). It will display all of the parameters associated with the drive and its partition layout. Unless the .B \-r flag is given, the kernel's in-core copy of the label is displayed; if the disk has no label, or the partition types on the disk are incorrect, the kernel may have constructed or modified the label. If the .B \-r flag is given, the label from the raw disk will be displayed rather than the in-core label. .PP The second form of the command, with the .B \-w flag, is used to write a standard label on the designated drive. The required arguments to .B disklabel are the drive to be labelled (e.g. sd0), and the drive type as described in the .IR disktab (5) file. The drive parameters and partitions are taken from that file. If different disks of the same physical type are to have different partitions, it will be necessary to have separate disktab entries describing each, or to edit the label after installation as described below. The optional argument is a pack identification string, up to 16 characters long. The pack id must be quoted if it contains blanks. If the .B \-r flag is given, the disk sectors containing the label and bootstrap will be written directly. A side-effect of this is that any existing bootstrap code will be overwritten and the disk rendered unbootable. If .B \-r is not specified, the existing label will be updated via the in-core copy and any bootstrap code will be unaffected. If the disk does not already have a label, the .B \-r flag must be used. In either case, the kernel's in-core label is replaced. .PP An existing disk label may be edited by using the .B \-e flag. The label is read from the in-core kernel copy, or directly from the disk if the .B \-r flag is also given. The label is formatted and then supplied to an editor for changes. If no editor is specified in an .B EDITOR environment variable, .IR vi (1) is used. When the editor terminates, the formatted label is reread and used to rewrite the disk label. Existing bootstrap code is unchanged regardless of whether .B \-r was specified. .PP With the .B \-R flag, .B disklabel is capable of restoring a disk label that was formatted in a prior operation and saved in an ascii file. The prototype file used to create the label should be in the same format as that produced when reading or editing a label. Comments are delimited by .IR \&# and newline. As with .B \-w , any existing bootstrap code will be clobbered if .B \-r is specified and will be unaffected otherwise. .PP The .B \-NW flags for .B disklabel explicitly disallow and allow, respectively, writing of the pack label area on the selected disk. .PP The final three forms of .B disklabel are used to install bootstrap code on machines where the bootstrap is part of the label. The bootstrap code is comprised of one or two boot programs depending on the machine. The .B \-B option is used to denote that bootstrap code is to be installed. The .B \-r flag is implied by .B \-B and never needs to be specified. The name of the boot program(s) to be installed can be selected in a variety of ways. First, the names can be specified explicitly via the .B \-b flag. If the name is not explicitly given, standard boot blocks will be used. The boot programs are located in .IR /mdec . The names of the program is taken from the ``b0'' parameter of the .IR disktab (5) entry for the disk if .I disktype was given and its disktab entry exists and includes that parameter. Otherwise, the boot program name is derived from the name of the disk. These name is of the form \fIbasename\fPuboot ; for example, .I /usr/mdec/rauboot if the disk device is .IR ra0 . .PP The first of the three boot-installation forms is used to install bootstrap code without changing the existing label. It is essentially a read command with respect to the disk label itself and all options are related to the specification of the boot program as described previously. The final two forms are analogous to the basic write and restore versions except that they will install bootstrap code in addition to a new label. .SH FILES /etc/disktab .br /mdec/\fIxx\fPuboot .SH EXAMPLES .in +0.5i disklabel sd0 .br .in -0.5i .PP Display the in-core label for ra0 as obtained via .IR /dev/rra0a . .PP .in +0.5i disklabel \-w \-r /dev/rra0a ra81x foo .br .in -0.5i .PP Create a label for sd0 based on information for ``ra81x'' found in .IR /etc/disktab . Any existing bootstrap code will be clobbered. .PP .in +0.5i disklabel -e -r ra0 .in -0.5i .PP Read the on-disk label for ra0, edit it and reinstall in-core as well as on-disk. Existing bootstrap code is unaffected. .PP .in +0.5i disklabel -R ra0 mylabel .br .in -0.5i .PP Restore the on-disk and in-core label for sd0 from information in .IR mylabel . Existing bootstrap code is unaffected. .PP .in +0.5i disklabel -B ra0 .br .in -0.5i .PP Install a new bootstrap on ra0. The boot code comes from .IR /mdec/rauboot . On-disk and in-core labels are unchanged. .PP .in +0.5i disklabel -w -B /dev/rra0a -b newboot ra81x .br .in -0.5i .PP Install a new label and bootstrap. The label is derived from disktab information for ``ra81x'' and installed both in-core and on-disk. The bootstrap code comes from the file .IR /mdec/newboot . .SH SEE ALSO disktab(5), disklabel(5) .SH DIAGNOSTICS The kernel device drivers will not allow the size of a disk partition to be decreased or the offset of a partition to be changed while it is open. Some device drivers create a label containing only a single large partition if a disk is unlabeled; thus, the label must be written to the ``a'' partition of the disk while it is open. This sometimes requires the desired label to be set in two steps, the first one creating at least one other partition, and the second setting the label on the new partition while shrinking the ``a'' partition. .SH BUGS When a disk name is given without a full pathname, the constructed device name uses the ``a'' partition on the tahoe and pdp\-11 the ``c'' partition on all others. the raw disk will be displayed rather thanbin/disklabel/disklabel.c 644 0 12 65566 6000403644 10666 /* * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Symmetric Computer Systems. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if !defined(lint) && defined(DOSCCS) static char copyright[] = "@(#) Copyright (c) 1987, 1993\n\ The Regents of the University of California. All rights reserved.\n"; static char sccsid[] = "@(#)disklabel.c 8.1.2 (2.11BSD) 1995/07/10"; /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ #endif #include #include #include #include #include #include #define DKTYPENAMES #include #include #include #include #include #include "pathnames.h" /* * Disklabel: read and write disklabels. * The label is usually placed on one of the first sectors of the disk. * Many machines also place a bootstrap in the same area, * in which case the label is embedded in the bootstrap. * The bootstrap source must leave space at the proper offset * for the label on such machines. */ /* * 2.11BSD has to do some things differently than other systems. BBSIZE * may be 1024 bytes but the disk boot roms only read the 512 byte sector 0. * The boot and label areas each occupy 1/2 of the 1kb 'filesystem block' * which precedes the superblock. The bootblock is sector 0 and the label block * is sector 1. Each is a disjoint and independent area. Thus the logic in * this program which treated the label area as a subset or offset of the * boot area had to change. * * The 'a' partition is used to access the raw device - as did the 'tahoe'. */ #define RAWPARTITION 'a' #define DEFEDITOR _PATH_VI #define streq(a,b) (strcmp(a,b) == 0) char *dkname; char *specname; char tmpfil[] = _PATH_TMP; extern int errno; extern long atol(); char namebuf[256], *np = namebuf; struct disklabel lab; struct disklabel *readlabel(), *makebootarea(); char bootarea[BBSIZE]; /* 512 for bootblock, 512 for label */ int installboot; /* non-zero if we should install a boot program */ char *xxboot; /* primary boot */ char boot0[MAXPATHLEN]; enum { UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT } op = UNSPEC; int rflag; #ifdef DEBUG int debug; #define OPTIONS "BNRWb:derw" #else #define OPTIONS "BNRWb:erw" #endif main(argc, argv) int argc; char *argv[]; { extern char *optarg; extern int optind; register struct disklabel *lp; FILE *t; int ch, f, flag, error = 0; char *name = 0; while ((ch = getopt(argc, argv, OPTIONS)) != EOF) switch (ch) { case 'B': ++installboot; break; case 'b': xxboot = optarg; break; case 'N': if (op != UNSPEC) usage(); op = NOWRITE; break; case 'R': if (op != UNSPEC) usage(); op = RESTORE; break; case 'W': if (op != UNSPEC) usage(); op = WRITEABLE; break; case 'e': if (op != UNSPEC) usage(); op = EDIT; break; case 'r': ++rflag; break; case 'w': if (op != UNSPEC) usage(); op = WRITE; break; #ifdef DEBUG case 'd': debug++; break; #endif case '?': default: usage(); } argc -= optind; argv += optind; if (installboot) { rflag++; if (op == UNSPEC) op = WRITEBOOT; } else { if (op == UNSPEC) op = READ; xxboot = 0; } if (argc < 1) usage(); dkname = argv[0]; if (dkname[0] != '/') { (void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION); specname = np; np += strlen(specname) + 1; } else specname = dkname; f = open(specname, op == READ ? O_RDONLY : O_RDWR); if (f < 0 && errno == ENOENT && dkname[0] != '/') { (void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname); np = namebuf + strlen(specname) + 1; f = open(specname, op == READ ? O_RDONLY : O_RDWR); } if (f < 0) Perror(specname); switch(op) { case EDIT: if (argc != 1) usage(); lp = readlabel(f); error = edit(lp, f); break; case NOWRITE: flag = 0; if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) Perror("ioctl DIOCWLABEL"); break; case READ: if (argc != 1) usage(); lp = readlabel(f); display(stdout, lp); error = checklabel(lp); break; case RESTORE: if (installboot && argc == 3) { makelabel(argv[2], 0, &lab); argc--; } if (argc != 2) usage(); lp = makebootarea(bootarea, &lab, f); if (!(t = fopen(argv[1], "r"))) Perror(argv[1]); if (getasciilabel(t, lp)) error = writelabel(f, bootarea, lp); break; case WRITE: if (argc == 3) { name = argv[2]; argc--; } if (argc != 2) usage(); makelabel(argv[1], name, &lab); lp = makebootarea(bootarea, &lab, f); *lp = lab; if (checklabel(lp) == 0) error = writelabel(f, bootarea, lp); break; case WRITEABLE: flag = 1; if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) Perror("ioctl DIOCWLABEL"); break; case WRITEBOOT: { struct disklabel tlab; lp = readlabel(f); tlab = *lp; if (argc == 2) makelabel(argv[1], 0, &lab); lp = makebootarea(bootarea, &lab, f); *lp = tlab; if (checklabel(lp) == 0) error = writelabel(f, bootarea, lp); break; } } exit(error); } /* * Construct a prototype disklabel from /etc/disktab. As a side * effect, set the names of the primary and secondary boot files * if specified. */ makelabel(type, name, lp) char *type, *name; register struct disklabel *lp; { register struct disklabel *dp; char *strcpy(); dp = getdiskbyname(type); if (dp == NULL) { fprintf(stderr, "%s: unknown disk type\n", type); exit(1); } *lp = *dp; /* * Set bootstrap name. * 1. If set from command line, use it, * 2. otherwise, check if disktab specifies it (b0), * 3. otherwise, makebootarea() will choose one based on the name * of the disk special file. E.g. /dev/ra0 -> rauboot */ if (!xxboot && lp->d_boot0) { if (*lp->d_boot0 != '/') (void)sprintf(boot0, "%s/%s", _PATH_BOOTDIR, lp->d_boot0); else (void)strcpy(boot0, lp->d_boot0); xxboot = boot0; } /* d_packname is union d_boot0, so zero */ bzero(lp->d_packname, sizeof(lp->d_packname)); if (name) (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); } writelabel(f, boot, lp) int f; char *boot; register struct disklabel *lp; { register int i; int flag; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); if (rflag) { /* * First set the kernel disk label, * then write a label to the raw disk. * If the SDINFO ioctl fails because it is unimplemented, * keep going; otherwise, the kernel consistency checks * may prevent us from changing the current (in-core) * label. Normally EFAULT would not be here - but the ioctl * maximum data length changed and old kernels would generate * an error prematurely in the ioctl dispatch. */ if (ioctl(f, DIOCSDINFO, lp) < 0 && errno != EFAULT && errno != ENODEV && errno != ENOTTY) { l_perror("ioctl DIOCSDINFO"); return (1); } (void)lseek(f, (off_t)0, L_SET); /* * write enable label sector before write (if necessary), * disable after writing. */ flag = 1; if (ioctl(f, DIOCWLABEL, &flag) < 0) perror("ioctl DIOCWLABEL"); /* * Write the boot block sector (512 bytes) followed immediately by the * label sector (512 bytes) = BBSIZE (1kb) total. */ if (write(f, boot, BBSIZE) != BBSIZE) { perror("write"); return (1); } flag = 0; (void) ioctl(f, DIOCWLABEL, &flag); } else if (ioctl(f, DIOCWDINFO, lp) < 0) { l_perror("ioctl DIOCWDINFO"); return (1); } return (0); } l_perror(s) char *s; { int saverrno = errno; fprintf(stderr, "disklabel: %s: ", s); switch (saverrno) { case ESRCH: fprintf(stderr, "No disk label on disk;\n"); fprintf(stderr, "use \"disklabel -r\" to install initial label\n"); break; case EINVAL: fprintf(stderr, "Label magic number or checksum is wrong!\n"); fprintf(stderr, "(disklabel or kernel is out of date?)\n"); break; case EBUSY: fprintf(stderr, "Open partition would move or shrink\n"); break; case EXDEV: fprintf(stderr, "Labeled partition or 'a' partition must start at beginning of disk\n"); break; default: errno = saverrno; perror((char *)NULL); break; } } /* * Fetch disklabel for disk. * Use ioctl to get label unless -r flag is given. * * We use the search logic for the label even though the label will be * in the second half of the bootarea. If there ever is a valid label * residing in the boot sector things are going to get weird. */ struct disklabel * readlabel(f) int f; { register struct disklabel *lp; register struct disklabel *xx = (struct disklabel *)(bootarea + BBSIZE - sizeof (struct disklabel)); if (rflag) { if (lseek(f, (daddr_t)0, L_SET) < 0) Perror(specname); if (read(f, bootarea, BBSIZE) < BBSIZE) Perror(specname); for (lp = (struct disklabel *)bootarea; lp <= xx; lp = (struct disklabel *)((char *)lp + 16)) if (lp->d_magic == DISKMAGIC && lp->d_magic2 == DISKMAGIC) break; if (lp > xx || lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || dkcksum(lp) != 0) { fprintf(stderr, "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); exit (1); } } else { lp = &lab; if (ioctl(f, DIOCGDINFO, lp) < 0) Perror("ioctl DIOCGDINFO"); } return (lp); } /* * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot'' * Returns a pointer to the disklabel portion of the bootarea. */ struct disklabel * makebootarea(boot, dp, f) char *boot; register struct disklabel *dp; int f; { struct disklabel *lp; register char *p; int b; char *dkbasename; struct stat sb; /* XXX */ /* * sectors are 512 bytes, filesystem blocks are DEV_BSIZE (1024) bytes. * We override the sector size so that things like the RL02 work * right. The RL drives use a hardware sector size of 256 bytes * which would wreck havoc in the calculation below. Actually the * disktab file should be "fixed" - all entries should omit 'se' and * use the default of 512. */ dp->d_secsize = 512; dp->d_bbsize = 512; lp = (struct disklabel *) (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET); bzero((char *)lp, sizeof *lp); /* * If we are not installing a boot program but we are installing a * label on disk then we must read the current bootarea so we don't * clobber the existing boot. */ if (!installboot) { if (rflag) { if (lseek(f, (daddr_t)0, L_SET) < 0) Perror(specname); if (read(f, boot, BBSIZE) < BBSIZE) Perror(specname); bzero((char *)lp, sizeof *lp); } return (lp); } /* * We are installing a boot program. Determine the name(s) and * read them into the appropriate places in the boot area. */ if (!xxboot) { dkbasename = np; if ((p = rindex(dkname, '/')) == NULL) p = dkname; else p++; while (*p && !isdigit(*p)) *np++ = *p++; *np++ = '\0'; (void)sprintf(np, "%s/%suboot", _PATH_BOOTDIR, dkbasename); if (access(np, F_OK) < 0 && dkbasename[0] == 'r') dkbasename++; xxboot = np; (void)sprintf(xxboot, "%s/%suboot", _PATH_BOOTDIR, dkbasename); np += strlen(xxboot) + 1; } #ifdef DEBUG if (debug) fprintf(stderr, "bootstrap: xxboot = %s\n", xxboot); #endif /* * Rule: * 1. One-piece bootstrap up to 512 bytes is all that is supported. */ b = open(xxboot, O_RDONLY); if (b < 0) Perror(xxboot); if (read(b, boot, 512) < 0) Perror(xxboot); (void)fstat(b, &sb); if (sb.st_size > 512) Warning("boot > 512 bytes - filesystem likely not bootable"); (void)close(b); return (lp); } display(f, lp) FILE *f; register struct disklabel *lp; { register int i, j; register struct partition *pp; fprintf(f, "# %s:\n", specname); if ((unsigned) lp->d_type < DKMAXTYPES) fprintf(f, "type: %s\n", dktypenames[lp->d_type]); else fprintf(f, "type: %d\n", lp->d_type); fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename); fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname); fprintf(f, "flags:"); if (lp->d_flags & D_REMOVABLE) fprintf(f, " removeable"); if (lp->d_flags & D_ECC) fprintf(f, " ecc"); if (lp->d_flags & D_BADSECT) fprintf(f, " badsect"); fprintf(f, "\n"); fprintf(f, "bytes/sector: %d\n", lp->d_secsize); fprintf(f, "sectors/track: %d\n", lp->d_nsectors); fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks); fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl); fprintf(f, "cylinders: %d\n", lp->d_ncylinders); fprintf(f, "rpm: %d\n", lp->d_rpm); fprintf(f, "interleave: %d\n", lp->d_interleave); fprintf(f, "trackskew: %d\n", lp->d_trackskew); fprintf(f, "cylinderskew: %d\n", lp->d_cylskew); fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch); fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek); fprintf(f, "drivedata: "); for (i = NDDATA - 1; i >= 0; i--) if (lp->d_drivedata[i]) break; if (i < 0) i = 0; for (j = 0; j <= i; j++) fprintf(f, "%ld ", lp->d_drivedata[j]); fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions); fprintf(f, "# size offset fstype [fsize bsize]\n"); pp = lp->d_partitions; for (i = 0; i < lp->d_npartitions; i++, pp++) { if (pp->p_size) { fprintf(f, " %c: %8ld %8ld ", 'a' + i, pp->p_size, pp->p_offset); if ((unsigned) pp->p_fstype < FSMAXTYPES) fprintf(f, "%8.8s", fstypenames[pp->p_fstype]); else fprintf(f, "%8d", pp->p_fstype); switch (pp->p_fstype) { case FS_V71K: case FS_UNUSED: /* XXX */ fprintf(f, " %5d %5d ", pp->p_fsize, pp->p_fsize * pp->p_frag); break; default: fprintf(f, "%20.20s", ""); break; } fprintf(f, "\t# (Cyl. %4ld", pp->p_offset / lp->d_secpercyl); if (pp->p_offset % lp->d_secpercyl) putc('*', f); else putc(' ', f); fprintf(f, "- %ld", (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl - 1); if (pp->p_size % lp->d_secpercyl) putc('*', f); fprintf(f, ")\n"); } } fflush(f); } edit(lp, f) struct disklabel *lp; int f; { register int c; struct disklabel label; FILE *fd; char *mktemp(); (void) mktemp(tmpfil); fd = fopen(tmpfil, "w"); if (fd == NULL) { fprintf(stderr, "%s: Can't create\n", tmpfil); return (1); } (void)fchmod(fileno(fd), 0600); display(fd, lp); fclose(fd); for (;;) { if (!editit()) break; fd = fopen(tmpfil, "r"); if (fd == NULL) { fprintf(stderr, "%s: Can't reopen for reading\n", tmpfil); break; } bzero((char *)&label, sizeof(label)); if (getasciilabel(fd, &label)) { *lp = label; if (writelabel(f, bootarea, lp) == 0) { (void) unlink(tmpfil); return (0); } } printf("re-edit the label? [y]: "); fflush(stdout); c = getchar(); if (c != EOF && c != (int)'\n') while (getchar() != (int)'\n') ; if (c == (int)'n') break; } (void) unlink(tmpfil); return (1); } editit() { register int pid, xpid; int stat; long omask; extern char *getenv(); omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); while ((pid = fork()) < 0) { extern int errno; if (errno == EPROCLIM) { fprintf(stderr, "You have too many processes\n"); return(0); } if (errno != EAGAIN) { perror("fork"); return(0); } sleep(1); } if (pid == 0) { register char *ed; sigsetmask(omask); setgid(getgid()); setuid(getuid()); if ((ed = getenv("EDITOR")) == (char *)0) ed = DEFEDITOR; execlp(ed, ed, tmpfil, 0); perror(ed); exit(1); } while ((xpid = wait(&stat)) >= 0) if (xpid == pid) break; sigsetmask(omask); return(!stat); } char * skip(cp) register char *cp; { while (*cp != '\0' && isspace(*cp)) cp++; if (*cp == '\0' || *cp == '#') return ((char *)NULL); return (cp); } char * word(cp) register char *cp; { register char c; while (*cp != '\0' && !isspace(*cp) && *cp != '#') cp++; if ((c = *cp) != '\0') { *cp++ = '\0'; if (c != '#') return (skip(cp)); } return ((char *)NULL); } /* * Read an ascii label in from fd f, * in the same format as that put out by display(), * and fill in lp. */ getasciilabel(f, lp) FILE *f; register struct disklabel *lp; { register char **cpp, *cp; register struct partition *pp; char *tp, *s, line[BUFSIZ]; int lineno = 0, errors = 0; long v; lp->d_bbsize = 512; /* XXX */ lp->d_sbsize = SBSIZE; while (fgets(line, sizeof(line) - 1, f)) { lineno++; if (cp = index(line,'\n')) *cp = '\0'; cp = skip(line); if (cp == NULL) continue; tp = index(cp, ':'); if (tp == NULL) { fprintf(stderr, "line %d: syntax error\n", lineno); errors++; continue; } *tp++ = '\0', tp = skip(tp); if (streq(cp, "type")) { if (tp == NULL) tp = "unknown"; cpp = dktypenames; for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) if ((s = *cpp) && streq(s, tp)) { lp->d_type = cpp - dktypenames; goto next; } v = atoi(tp); if ((unsigned)v >= DKMAXTYPES) fprintf(stderr, "line %d:%s %d\n", lineno, "Warning, unknown disk type", v); lp->d_type = v; continue; } if (streq(cp, "flags")) { for (v = 0; (cp = tp) && *cp != '\0';) { tp = word(cp); if (streq(cp, "removeable")) v |= D_REMOVABLE; else if (streq(cp, "ecc")) v |= D_ECC; else if (streq(cp, "badsect")) v |= D_BADSECT; else { fprintf(stderr, "line %d: %s: bad flag\n", lineno, cp); errors++; } } lp->d_flags = v; continue; } if (streq(cp, "drivedata")) { register int i; for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { lp->d_drivedata[i++] = atol(cp); tp = word(cp); } continue; } if (sscanf(cp, "%ld partitions", &v) == 1) { if (v == 0 || (unsigned)v > MAXPARTITIONS) { fprintf(stderr, "line %d: bad # of partitions\n", lineno); lp->d_npartitions = MAXPARTITIONS; errors++; } else lp->d_npartitions = v; continue; } if (tp == NULL) tp = ""; if (streq(cp, "disk")) { strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); continue; } if (streq(cp, "label")) { strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); continue; } /* * ARGH! Have to fix the 'se#256' entries in disktab after all or this * check will cause errors. */ if (streq(cp, "bytes/sector")) { v = atoi(tp); if (v <= 0 || (v % 512) != 0) { fprintf(stderr, "line %d: %s: bad sector size\n", lineno, tp); errors++; } else lp->d_secsize = v; continue; } if (streq(cp, "sectors/track")) { v = atoi(tp); if (v <= 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_nsectors = v; continue; } if (streq(cp, "sectors/cylinder")) { v = atoi(tp); if (v <= 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_secpercyl = v; continue; } if (streq(cp, "tracks/cylinder")) { v = atoi(tp); if (v <= 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_ntracks = v; continue; } if (streq(cp, "cylinders")) { v = atoi(tp); if (v <= 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_ncylinders = v; continue; } if (streq(cp, "rpm")) { v = atoi(tp); if (v <= 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_rpm = v; continue; } if (streq(cp, "interleave")) { v = atoi(tp); if (v <= 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_interleave = v; continue; } if (streq(cp, "trackskew")) { v = atoi(tp); if (v < 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_trackskew = v; continue; } if (streq(cp, "cylinderskew")) { v = atoi(tp); if (v < 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_cylskew = v; continue; } if (streq(cp, "headswitch")) { v = atoi(tp); if (v < 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_headswitch = v; continue; } if (streq(cp, "track-to-track seek")) { v = atoi(tp); if (v < 0) { fprintf(stderr, "line %d: %s: bad %s\n", lineno, tp, cp); errors++; } else lp->d_trkseek = v; continue; } if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { unsigned part = *cp - 'a'; if (part > lp->d_npartitions) { fprintf(stderr, "line %d: bad partition name '%c' %d %d\n", lineno, *cp, part, lp->d_npartitions); errors++; continue; } pp = &lp->d_partitions[part]; #define NXTNUM(n) { \ cp = tp, tp = word(cp); \ if (tp == NULL) \ tp = cp; \ (n) = atol(cp); \ } NXTNUM(v); if (v < 0) { fprintf(stderr, "line %d: %s: bad partition size\n", lineno, cp); errors++; } else pp->p_size = v; NXTNUM(v); if (v < 0) { fprintf(stderr, "line %d: %s: bad partition offset\n", lineno, cp); errors++; } else pp->p_offset = v; cp = tp, tp = word(cp); cpp = fstypenames; for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) if ((s = *cpp) && streq(s, cp)) { pp->p_fstype = cpp - fstypenames; goto gottype; } if (isdigit(*cp)) v = atoi(cp); else v = FSMAXTYPES; if ((unsigned)v >= FSMAXTYPES) { fprintf(stderr, "line %d: %s %s\n", lineno, "Warning, unknown filesystem type", cp); v = FS_UNUSED; } pp->p_fstype = v; gottype: switch (pp->p_fstype) { case FS_UNUSED: /* XXX */ case FS_V71K: NXTNUM(pp->p_fsize); if (pp->p_fsize == 0) break; NXTNUM(v); pp->p_frag = v / pp->p_fsize; break; default: break; } continue; } fprintf(stderr, "line %d: %s: Unknown disklabel field\n", lineno, cp); errors++; next: ; } errors += checklabel(lp); return (errors == 0); } /* * Check disklabel for errors and fill in * derived fields according to supplied values. */ checklabel(lp) register struct disklabel *lp; { register struct partition *pp; int i, errors = 0; char part; if (lp->d_secsize == 0) { fprintf(stderr, "sector size %d\n", lp->d_secsize); return (1); } if (lp->d_nsectors == 0) { fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); return (1); } if (lp->d_ntracks == 0) { fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); return (1); } if (lp->d_ncylinders == 0) { fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); errors++; } if (lp->d_rpm == 0) Warning("revolutions/minute %d", lp->d_rpm); if (lp->d_secpercyl == 0) lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; if (lp->d_secperunit == 0) lp->d_secperunit = (long) lp->d_secpercyl * lp->d_ncylinders; if (lp->d_bbsize == 0) { fprintf(stderr, "boot block size %d\n", lp->d_bbsize); errors++; } else if (lp->d_bbsize % lp->d_secsize) Warning("boot block size %% sector-size != 0"); if (lp->d_sbsize == 0) { fprintf(stderr, "super block size %d\n", lp->d_sbsize); errors++; } else if (lp->d_sbsize % lp->d_secsize) Warning("super block size %% sector-size != 0"); if (lp->d_npartitions > MAXPARTITIONS) Warning("number of partitions (%d) > MAXPARTITIONS (%d)", lp->d_npartitions, MAXPARTITIONS); for (i = 0; i < lp->d_npartitions; i++) { part = 'a' + i; pp = &lp->d_partitions[i]; if (pp->p_size == 0 && pp->p_offset != 0) Warning("partition %c: size 0, but offset %ld", part, pp->p_offset); #ifdef notdef if (pp->p_size % lp->d_secpercyl) Warning("partition %c: size %% cylinder-size != 0", part); if (pp->p_offset % lp->d_secpercyl) Warning("partition %c: offset %% cylinder-size != 0", part); #endif if (pp->p_offset > lp->d_secperunit) { fprintf(stderr, "partition %c: offset past end of unit %ld %ld\n", part, pp->p_offset, lp->d_secperunit); errors++; } if (pp->p_offset + pp->p_size > lp->d_secperunit) { fprintf(stderr, "partition %c: extends past end of unit %ld %ld %ld\n", part, pp->p_offset, pp->p_size, lp->d_secperunit); errors++; } } for (; i < MAXPARTITIONS; i++) { part = 'a' + i; pp = &lp->d_partitions[i]; if (pp->p_size || pp->p_offset) Warning("unused partition %c: size %ld offset %ld", 'a' + i, pp->p_size, pp->p_offset); } return (errors); } /*VARARGS1*/ Warning(fmt, a1, a2, a3, a4, a5) char *fmt; { fprintf(stderr, "Warning, "); fprintf(stderr, fmt, a1, a2, a3, a4, a5); fprintf(stderr, "\n"); } Perror(str) char *str; { fputs("disklabel: ", stderr); perror(str); exit(4); } usage() { fprintf(stderr, "%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n", "usage: disklabel [-r] disk", "(to read label)", "or disklabel -w [-r] disk type [ packid ]", "(to write label with existing boot program)", "or disklabel -e [-r] disk", "(to edit label)", "or disklabel -R [-r] disk protofile", "(to restore label with existing boot program)", "or disklabel -B [ -b bootprog ] disk [ type ]", "(to install boot program with existing on-disk label)", "or disklabel -w -B [ -b bootprog ] disk type [ packid ]", "(to write label and install boot program)", "or disklabel -R -B [ -b bootprog ] disk protofile [ type ]", "(to restore label and install boot program)", "or disklabel [-NW] disk", "(to write disable/enable label)"); exit(1); } d = getenv("EDITOR")) == (char *)0) ed = DEFEDITOR; execlp(ed, ed, tmpfil, 0); perror(ed); exit(1); } while ((xpid = wait(&statbin/disklabel/pathnames.h 644 0 12 3677 5742402157 10706 /* * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)pathnames.h 8.1.1 (2.11BSD) 4/10/95 */ #include #define _PATH_BOOTDIR "/mdec" #undef _PATH_TMP #define _PATH_TMP "/tmp/EdDk.aXXXXXX" ar *)NULL); } /* * Read an ascii label in from fd f, * in the bin/ps.c 444 0 24 51417 5675670571 5441 /* * 12/20/94 - Missing casts caused errors in reporting on swapped * processes - sms * 1/7/93 - Heavily revised when the symbol table format changed - sms * * ps - process status * Usage: ps [ acgklnrtuwxU# ] [ corefile [ swapfile [ system ] ] ] */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define within(x,y,z) (((unsigned)(x) >= (y)) && ((unsigned)(x) < (z))) #define round(x,y) ((long) ((((long) (x) + (long) (y) - 1L) / (long) (y)) * (long) (y))) struct nlist nl[4]; #define X_PROC 0 #define X_NPROC 1 #define X_HZ 2 /* * This is no longer the size of a symbol's name, symbols can be much * larger now. This define says how many characters of a symbol's name * to save in the wait channel name. A new define has been created to * limit the size of symbol string read from the string table. */ #define NNAMESIZ 8 #define MAXSYMLEN 32 struct proc *mproc, proc[8]; struct user u; int hz; int chkpid = 0; char aflg; /* -a: all processes, not just mine */ char cflg; /* -c: not complete listing of args, just comm. */ char gflg; /* -g: complete listing including group headers, etc */ char kflg; /* -k: read from core file instead of real memory */ char lflg; /* -l: long listing form */ char nflg; /* -n: numeric wchans */ char rflg; /* -r: raw output in style */ char uflg; /* -u: user name */ char wflg; /* -w[w]: wide terminal */ char xflg; /* -x: ALL processes, even those without ttys */ char Uflg; /* -U: update the private list */ char *tptr, *mytty; char *uname; int file; int nproc; int nchans; int nttys; #ifndef PSFILE char *psdb = "/etc/psdatabase"; #else char *psdb = PSFILE; #endif int npr; /* number of processes found so far */ int twidth; /* terminal width */ int cmdstart; /* start position for command field */ char *memf; /* name of kernel memory file */ char *kmemf = "/dev/kmem"; /* name of physical memory file */ char *swapf; /* name of swap file to use */ char *nlistf; /* name of symbol table file to use */ int kmem, mem, swap; /* * Structure for the unix wchan table */ typedef struct wchan { char cname[NNAMESIZ]; unsigned caddr; } WCHAN; WCHAN *wchand; extern char *calloc(), *malloc(), *realloc(), *ttyname(); char *gettty(), *getptr(), *getchan(); int pscomp(), wchancomp(); extern off_t lseek(); /* * 256 terminals was not only wasteful but unrealistic. For one thing * 2.11BSD uses bit 7 of the minor device (for almost all terminal interfaces) * to indicate direct/modem status - this means that 128 terminals is * a better maximum number of terminals, for another thing the system can't * support 256 terminals - other resources (memory, files, processes) will * have been exhausted long ago. If 'ps' complains about too many terminals * it is time to clean up /dev! */ #define MAXTTYS 160 /* 128 plus a few extra */ struct ttys { char name[14]; /* MAXNAMLEN uses too much memory, besides */ /* device names tend to be very short */ dev_t ttyd; } allttys[MAXTTYS]; struct map { off_t b1, e1; off_t f1; off_t b2, e2; off_t f2; }; struct winsize ws; struct map datmap; struct psout *outargs; /* info for first npr processes */ main (argc, argv) char **argv; { int uid, euid, puid, nread; register int i, j; char *ap; register struct proc *procp; /* * Can't initialize unions and we need the macros from a.out.h, so the * namelist is set up at run time. */ nl[X_PROC].n_un.n_name = "_proc"; nl[X_NPROC].n_un.n_name = "_nproc"; nl[X_HZ].n_un.n_name = "_hz"; if ((ioctl(fileno(stdout), TIOCGWINSZ, &ws) != -1 && ioctl(fileno(stderr), TIOCGWINSZ, &ws) != -1 && ioctl(fileno(stdin), TIOCGWINSZ, &ws) != -1) || ws.ws_col == 0) twidth = 80; else twidth = ws.ws_col; argc--, argv++; if (argc > 0) { ap = argv [0]; while (*ap) switch (*ap++) { case '-': break; case 'a': aflg++; break; case 'c': cflg++; break; case 'g': gflg++; break; case 'k': kflg++; break; case 'l': lflg = 1; break; case 'n': nflg++; lflg = 1; break; case 'r': rflg++; break; case 't': if (*ap) tptr = ap; else if ((tptr = ttyname(0)) != 0) { tptr = strcpy(mytty, tptr); if (strncmp(tptr, "/dev/", 5) == 0) tptr += 5; } if (strncmp(tptr, "tty", 3) == 0) tptr += 3; aflg++; gflg++; if (tptr && *tptr == '?') xflg++; while (*ap) ap++; break; case 'u': uflg = 1; break; case 'U': Uflg++; break; case 'w': if (wflg) twidth = BUFSIZ; else if (twidth < 132) twidth = 132; wflg++; break; case 'x': xflg++; break; default: if (!isdigit(ap[-1])) break; chkpid = atoi(--ap); *ap = '\0'; aflg++; xflg++; break; } } openfiles(argc, argv); getkvars(argc, argv); lseek(kmem,(off_t)nl[X_PROC].n_value,0); uid = getuid(); euid = geteuid(); mytty = ttyname(0); if (!strncmp(mytty,"/dev/",5)) mytty += 5; if (!strncmp(mytty,"tty",3)) mytty += 3; printhdr(); for (i = 0; i < nproc; i += 8) { j = nproc - i; if (j > 8) j = 8; j *= sizeof (struct proc); if ((nread = read(kmem, (char *) proc, j)) != j) { cantread("proc table", kmemf); if (nread == -1) break; } for (j = nread / sizeof (struct proc) - 1; j >= 0; j--) { mproc = &proc[j]; procp = mproc; /* skip processes that don't exist */ if (procp->p_stat == 0) continue; /* skip those without a tty unless -x */ if (procp->p_pgrp == 0 && xflg == 0) continue; /* skip group leaders on a tty unless -g, -x, or -t.. */ if (!tptr && !gflg && !xflg && procp->p_ppid == 1 && (procp->p_flag & SDETACH) == 0) continue; /* -g also skips those where **argv is "-" - see savcom */ puid = procp->p_uid; /* skip other peoples processes unless -a or a specific pid */ if ((uid != puid && euid != puid && aflg == 0) || (chkpid != 0 && chkpid != procp->p_pid)) continue; if (savcom(puid)) npr++; } } fixup(npr); for (i = 0; i < npr; i++) { register int cmdwidth = twidth - cmdstart - 2; register struct psout *a = &outargs[i]; if (rflg) { if (write(1, (char *) a, sizeof (*a)) != sizeof (*a)) perror("write"); continue; } else if (lflg) lpr(a); else if (uflg) upr(a); else spr(a); if (cmdwidth < 0) cmdwidth = 80 - cmdstart - 2; if (a->o_stat == SZOMB) printf("%.*s", cmdwidth, " "); else if (a->o_pid == 0) printf("%.*s", cmdwidth, " swapper"); else printf(" %.*s", twidth - cmdstart - 2, cflg ? a->o_comm : a->o_args); putchar('\n'); } exit(!npr); } getdev() { register DIR *df; register struct direct *dbuf; if (chdir("/dev") < 0) { perror("/dev"); exit(1); } if ((df = opendir(".")) == NULL) { fprintf(stderr, "Can't open . in /dev\n"); exit(1); } while (dbuf = readdir(df)) maybetty(dbuf->d_name); closedir(df); } /* * Attempt to avoid stats by guessing minor device * numbers from tty names. Console is known, * know that r(hp|up|mt) are unlikely as are different mem's, * floppy, null, tty, etc. */ maybetty(cp) register char *cp; { register struct ttys *dp; struct stat stb; switch (cp[0]) { case 'c': if (!strcmp(cp, "console")) break; /* cu[la]? are possible!?! don't rule them out */ break; case 'd': if (!strcmp(cp, "drum")) return; break; case 'f': if (!strcmp(cp, "floppy")) return; break; case 'k': if (!strcmp(cp, "kUmem") || !strcmp(cp, "kmem")) return; if (!strcmp(cp, "klog")) return; break; case 'r': #define is(a,b) cp[1] == 'a' && cp[2] == 'b' if (is(h,p) || is(r,a) || is(u,p) || is(h,k) || is(x,p) || is(r,b) || is(r,l) || is(m,t)) { if (isdigit(cp[3])) return; } break; case 'm': if (!strcmp("mem", cp)) return; if (cp[1] == 't') return; break; case 'n': if (!strcmp(cp, "null")) return; if (!strncmp(cp, "nrmt", 4)) return; break; case 'p': if (cp[1] == 't' && cp[2] == 'y') return; break; } if (nttys >= MAXTTYS) { fprintf(stderr, "ps: tty table overflow\n"); exit(1); } dp = &allttys[nttys++]; (void)strcpy(dp->name, cp); if (Uflg) { if (stat(dp->name, &stb) == 0 && (stb.st_mode&S_IFMT)==S_IFCHR) dp->ttyd = stb.st_rdev; else { nttys--; return; } } else dp->ttyd = -1; } savcom(puid) { char *tp; off_t addr; off_t daddr, saddr; register struct psout *a; register struct proc *procp = mproc; register struct user *up = &u; long txtsiz, datsiz, stksiz; int septxt; if (procp->p_flag & SLOAD) { addr = ctob((off_t) procp->p_addr); daddr = ctob((off_t) procp->p_daddr); saddr = ctob((off_t) procp->p_saddr); file = mem; } else { addr = (off_t)procp->p_addr << 9; daddr = (off_t)procp->p_daddr << 9; saddr = (off_t)procp->p_saddr << 9; file = swap; } lseek(file, addr, 0); if (read(file, (char *) up, sizeof (u)) != sizeof (u)) return(0); txtsiz = ctob(up->u_tsize); /* set up address maps for user pcs */ datsiz = ctob(up->u_dsize); stksiz = ctob(up->u_ssize); septxt = up->u_sep; datmap.b1 = (septxt ? 0 : round(txtsiz, TXTRNDSIZ)); datmap.e1 = datmap.b1 + datsiz; datmap.f1 = daddr; datmap.f2 = saddr; datmap.b2 = stackbas(stksiz); datmap.e2 = stacktop(stksiz); tp = gettty(); if ((tptr && strncmp(tptr,tp,2)) || (strncmp(mytty, tp, 2) && !aflg)) return(0); a = &outargs[npr]; /* saving com starts here */ a->o_uid = puid; a->o_pid = procp->p_pid; a->o_flag = procp->p_flag; a->o_ppid = procp->p_ppid; a->o_cpu = procp->p_cpu; a->o_pri = procp->p_pri; a->o_nice = procp->p_nice; a->o_addr0 = procp->p_addr; a->o_size = ctod(procp->p_dsize + procp->p_ssize + USIZE); a->o_wchan = procp->p_wchan; a->o_pgrp = procp->p_pgrp; strncpy(a->o_tty, tp, sizeof (a->o_tty)); a->o_ttyd = tp[0] == '?' ? -1 : up->u_ttyd; a->o_stat = procp->p_stat; a->o_flag = procp->p_flag; if (a->o_stat == SZOMB) return(1); a->o_utime = up->u_ru.ru_utime; a->o_stime = up->u_ru.ru_stime; a->o_cutime = up->u_cru.ru_utime; a->o_cstime = up->u_cru.ru_stime; a->o_sigs = (int)up->u_signal[SIGINT] + (int)up->u_signal[SIGQUIT]; a->o_uname[0] = 0; strncpy(a->o_comm, up->u_comm, MAXCOMLEN); if (cflg) return (1); else return(getcmd(a,saddr)); } char * gettty() { register int tty_step; register char *p; if (u.u_ttyp) for (tty_step = 0;tty_step < nttys;++tty_step) if (allttys[tty_step].ttyd == u.u_ttyd) { p = allttys[tty_step].name; if (!strncmp(p,"tty",3)) p += 3; return(p); } return("?"); } /* * fixup figures out everybodys name and sorts into a nice order. */ fixup(np) register int np; { register int i; register struct passwd *pw; if (uflg) { /* * If we want names, traverse the password file. For each * passwd entry, look for it in the processes. * In case of multiple entries in /etc/passwd, we believe * the first one (same thing ls does). */ while ((pw = getpwent()) != (struct passwd *) NULL) { for (i = 0; i < np; i++) if (outargs[i].o_uid == pw->pw_uid) { if (outargs[i].o_uname[0] == 0) strcpy(outargs[i].o_uname, pw->pw_name); } } } qsort(outargs, np, sizeof (outargs[0]), pscomp); } pscomp(x1, x2) register struct psout *x1, *x2; { register int c; c = (x1)->o_ttyd - (x2)->o_ttyd; if (c == 0) c = (x1)->o_pid - (x2)->o_pid; return(c); } wchancomp(x1, x2) register WCHAN *x1, *x2; { if (x1->caddr > x2->caddr) return(1); else if (x1->caddr == x2->caddr) return(0); else return(-1); } char * getptr(adr) char **adr; { char *ptr = 0; register char *p, *pa; register int i; pa = (char *)adr; p = (char *)&ptr; for (i = 0; i < sizeof (ptr); i++) *p++ = getbyte(pa++); return(ptr); } getbyte(adr) register char *adr; { register struct map *amap = &datmap; char b; off_t saddr; if (!within(adr, amap->b1, amap->e1)) if (within(adr, amap->b2, amap->e2)) saddr = (unsigned) adr + amap->f2 - amap->b2; else return(0); else saddr = (unsigned) adr + amap->f1 - amap->b1; if (lseek(file, saddr, 0) == (off_t) -1 || read (file, &b, 1) < 1) return(0); return((unsigned) b); } addchan(name, caddr) char *name; unsigned caddr; { static int left = 0; register WCHAN *wp; if (left == 0) { if (wchand) { left = 50; wchand = (WCHAN *)realloc(wchand, (nchans + left) * sizeof (struct wchan)); } else { left = 300; wchand = (WCHAN *)malloc(left * sizeof (struct wchan)); } if (!wchand) { fprintf(stderr, "ps: out of wait channel memory\n"); nflg++; return; } } wp = &wchand[nchans++]; left--; strncpy(wp->cname, name, NNAMESIZ - 1); wp->cname[NNAMESIZ-1] = '\0'; wp->caddr = caddr; } char * getchan(chan) register unsigned int chan; { register int i; register char *prevsym; prevsym = ""; if (chan) for (i = 0; i < nchans; i++) { if (wchand[i].caddr > chan) return (prevsym); prevsym = wchand[i].cname; } return(prevsym); } nlist() { register FILE *nlistf_fp; FILE *strfp; register struct nlist *nnn; int flag, nsyms; struct nlist nbuf; struct xexec hbuf; char name[MAXSYMLEN + 2]; int nllen; off_t sa, stroff; bzero(name, sizeof (name)); nllen = sizeof(nl) / sizeof(struct nlist); if (!(nlistf_fp = fopen(nlistf,"r"))) perrexit(nlistf); strfp = fopen(nlistf, "r"); if (fread(&hbuf,sizeof(hbuf),1,nlistf_fp) != 1) { fputs("Invalid symbol table\n",stderr); exit(1); } if (N_BADMAG(hbuf.e)) { fprintf(stderr,"%s: bad magic number\n",nlistf); exit(1); } nsyms = hbuf.e.a_syms / sizeof (struct nlist); if (nsyms == 0) { fprintf(stderr,"%s: no symbols\n",nlistf); exit(1); } sa = N_SYMOFF(hbuf); stroff = N_STROFF(hbuf); fseek(nlistf_fp, sa, L_SET); addchan("u", 0140000); /* XXX - see comment below */ while (nsyms--) { fread(&nbuf,sizeof(nbuf),1,nlistf_fp); if ((nbuf.n_type & N_EXT) == 0) continue; flag = nbuf.n_type & N_TYPE; /* * Now read the symbol string. Can't rely on having enough memory to * hold the entire string table, so we do a seek+read for each name. Luckily * this is only done for global symbols, which cuts down the work done. */ fseek(strfp, nbuf.n_un.n_strx + stroff, L_SET); fread(name, MAXSYMLEN, 1, strfp); /* * Skip over anything which isn't an external data or bss symbol. * Advantage was taken of the facts that 1) 'ps' is highly machine * dependent and 2) _u on a pdp-11 is not likely to change _ever_. * The reason behind this is to avoid matching on absolute symbols created * during the unix/netnix cross binding. */ if (!(flag == N_DATA || flag == N_BSS)) continue; if (!nflg) addchan(name + 1, nbuf.n_value); if (nllen) { for (nnn = nl; *nnn->n_un.n_name; nnn++) { if (!strcmp(nnn->n_un.n_name, name)) { nnn->n_value = nbuf.n_value; nnn->n_type = nbuf.n_type; nnn->n_ovly = nbuf.n_ovly; --nllen; break; } } } } fclose(nlistf_fp); fclose(strfp); if (!nflg) qsort(wchand,nchans,sizeof(WCHAN),wchancomp); } perrexit(msg) char *msg; { perror(msg); exit(1); } writepsdb() { register FILE *fp; int nllen; setuid(getuid()); if (!(fp = fopen (psdb, "w"))) perrexit(psdb); else fchmod(fileno(fp),0644); nllen = sizeof(nl) / sizeof(struct nlist); fwrite(nlistf,strlen(nlistf) + 1,1,fp); fwrite((char *)&nllen,sizeof(nllen),1,fp); fwrite((char *)&nttys,sizeof(nttys),1,fp); fwrite((char *)&nchans,sizeof(nchans),1,fp); fwrite((char *)nl,sizeof(struct nlist),nllen,fp); fwrite((char *)allttys,sizeof(struct ttys),nttys,fp); fwrite((char *)wchand,sizeof(WCHAN),nchans,fp); fclose(fp); } char * readpsdb() { register int i; register FILE *fp; register WCHAN *ccc; static char unamebuf[MAXPATHLEN + 1]; char *p = unamebuf; int nllen; if ((fp = fopen(psdb, "r")) == NULL) perrexit(psdb); while ((*p= getc(fp)) != '\0') p++; fread(&nllen, sizeof nllen, 1, fp); fread(&nttys, sizeof nttys, 1, fp); fread(&nchans, sizeof nchans, 1, fp); fread(nl, sizeof (struct nlist), nllen, fp); fread(allttys, sizeof (struct ttys), nttys, fp); if (!nflg) if (!(wchand = (WCHAN *)calloc(nchans, sizeof(WCHAN)))) { fputs("Too many symbols\n",stderr); exit(1); } else for (i = 0, ccc = wchand; i < nchans; i++) { fread((char *) ccc, sizeof(WCHAN), 1, fp); ccc++; } return(unamebuf); } openfiles(argc, argv) char **argv; { if (kflg) kmemf = argc > 1 ? argv[1] : "/usr/sys/core"; kmem = open(kmemf, 0); if (kmem < 0) perrexit(kmemf); if (!kflg) memf = "/dev/mem"; else memf = kmemf; mem = open(memf, 0); if (mem < 0) perrexit(memf); swapf = argc > 2 ? argv[2] : "/dev/swap"; swap = open(swapf, 0); if (swap < 0) perrexit(swapf); } getkvars(argc,argv) int argc; char **argv; { struct stat st; nlistf = argc > 3 ? argv[3] : "/unix"; if (Uflg) { nlist(); getdev(); writepsdb(); exit(0); } else if (stat(psdb, &st) == 0) { uname = readpsdb(); if (strcmp(uname,nlistf)) { /* * Let addchan() do the work. */ nchans = 0; free((char *)wchand); nlist(); } } else { nlist(); getdev(); } /* find number of procs */ if (nl[X_NPROC].n_value) { lseek(kmem,(off_t)nl[X_NPROC].n_value,0); if (read(kmem,(char *)&nproc,sizeof(nproc)) != sizeof(nproc)) { perror(kmemf); exit(1); } } else { fputs("nproc not in namelist\n",stderr); exit(1); } outargs = (struct psout *)calloc(nproc, sizeof(struct psout)); if (!outargs) { fputs("ps: not enough memory for saving info\n",stderr); exit(1); } /* find value of hz */ lseek(kmem,(off_t)nl[X_HZ].n_value,0); read(kmem,(char *)&hz,sizeof(hz)); } char *uhdr = "USER PID NICE SZ TTY TIME"; upr(a) register struct psout *a; { printf("%-8.8s%6u%4d%4d %-2.2s",a->o_uname,a->o_pid,a->o_nice,a->o_size,a->o_tty); ptime(a); } char *shdr = " PID TTY TIME"; spr (a) register struct psout *a; { printf("%6u %-2.2s",a->o_pid,a->o_tty); ptime(a); } char *lhdr = " F S UID PID PPID CPU PRI NICE ADDR SZ WCHAN TTY TIME"; lpr(a) register struct psout *a; { static char clist[] = "0SWRIZT"; printf("%3o %c%6u%6u%6u%4d%4d%4d%7o%4d", 0377 & a->o_flag,clist[a->o_stat],a->o_uid,a->o_pid, a->o_ppid,a->o_cpu & 0377,a->o_pri,a->o_nice,a->o_addr0,a->o_size); if (nflg) if (a->o_wchan) printf("%*.*o",NNAMESIZ, NNAMESIZ, a->o_wchan); else fputs(" ",stdout); else printf(" %-*.*s",NNAMESIZ, NNAMESIZ, getchan(a->o_wchan)); printf(" %-2.2s",a->o_tty); ptime(a); } ptime(a) struct psout *a; { time_t tm; tm = (a->o_utime + a->o_stime + 30) / hz; printf("%3ld:",tm / 60); tm %= 60; printf(tm < 10 ? "0%ld" : "%ld",tm); } getcmd(a,addr) off_t addr; register struct psout *a; { /* amount of top of stack to examine for args */ #define ARGLIST (1024/sizeof(int)) register int *ip; register char *cp, *cp1; char c, **ap; int cc, nbad, abuf [ARGLIST]; a->o_args[0] = 0; /* in case of early return */ addr += ctob((off_t) mproc->p_ssize) - ARGLIST*sizeof(int); /* look for sh special */ lseek(file, addr + ARGLIST*sizeof(int) - sizeof (char **), 0); if (read(file, (char *) &ap, sizeof (char *)) != sizeof (char *)) return (1); if (ap) { char b[82]; char *bp = b; while ((cp = getptr(ap++)) && cp && (bp < b+sizeof (a->o_args)) ) { nbad = 0; while ((c = getbyte(cp++)) && (bp < b+sizeof (a->o_args))) { if (c<' ' || c > '~') { if (nbad++ > 3) break; continue; } *bp++ = c; } *bp++ = ' '; } *bp++ = 0; (void)strcpy(a->o_args, b); return(1); } lseek(file, addr, 0); if (read(file, (char *) abuf, sizeof (abuf)) != sizeof (abuf)) return (1); abuf[ARGLIST-1] = 0; for (ip = &abuf[ARGLIST-2]; ip > abuf;) { if (*--ip == -1 || *ip == 0) { cp = (char *) (ip + 1); if (*cp == '\0') cp++; nbad = 0; for (cp1 = cp; cp1 < (char *) &abuf[ARGLIST]; cp1++) { cc = *cp1 & 0177; if (cc == 0) *cp1 = ' '; else if (cc < ' ' || cc > 0176) { if (++nbad >= 5) { *cp1++ = ' '; break; } *cp1 = '?'; } else if (cc == '=') { *cp1 = '\0'; while (cp1 > cp && *--cp1 != ' ') *cp1 = '\0'; break; } } while (*--cp1 == ' ') *cp1 = 0; (void)strcpy(a->o_args, cp); garbage: cp = a->o_args; if (cp[0] == '-' && cp[1] <= ' ' || cp[0] == '?' || cp[0] <= ' ') { strcat(cp, " ("); strcat(cp, u.u_comm); strcat(cp, ")"); } cp[63] = 0; /* max room in psout is 64 chars */ if (xflg || gflg || tptr || cp[0] != '-') return(1); return(0); } } goto garbage; } printhdr() { register char *hdr, *cmdstr = " COMMAND"; if (rflg) return; if (lflg && uflg) { fputs("ps: specify only one of l and u.\n",stderr); exit(1); } hdr = lflg ? lhdr : (uflg ? uhdr : shdr); fputs(hdr,stdout); cmdstart = strlen(hdr); if (cmdstart + strlen(cmdstr) >= twidth) cmdstr = " CMD"; printf("%s\n", cmdstr); fflush(stdout); } cantread(what, fromwhat) char *what, *fromwhat; { fprintf(stderr, "ps: error reading %s from %s\n", what, fromwhat); } it in the processes. * In case of multiple entries in /etc/passwd, we believe * the first one (same thing ls does). */ while ((pw = getpwent()) != (struct passwd *) NULL) { for (i = 0; i < np; i++) if (outargs[i].o_uid == pbin/cc.c 444 0 12 16640 4017345423 5360 static char sccsid[] = "@(#)cc.c 4.13 9/18/85"; /* * cc - front end for C compiler */ #include #include #include #include #include char *cpp = "/lib/cpp"; char *ccom = "/lib/c0"; char *ccom1 = "/lib/c1"; char *c2 = "/lib/c2"; char *as = "/bin/as"; char *ld = "/bin/ld"; char *crt0 = "/lib/crt0.o"; char tmp0[30]; /* big enough for /tmp/ctm%05.5d */ char *tmp1, *tmp2, *tmp3, *tmp4, *tmp5; char *outfile; char *savestr(), *strspl(), *setsuf(); int idexit(); char **av, **clist, **llist, **plist; int cflag, eflag, oflag, pflag, sflag, wflag, exflag, proflag; int Mflag, debug; int exfail; char *chpass; char *npassname; int nc, nl, np, nxo, na; #define cunlink(s) if (s) unlink(s) main(argc, argv) char **argv; { char *t; char *assource; int i, j, c; /* ld currently adds upto 5 args; 10 is room to spare */ av = (char **)calloc(argc+10, sizeof (char **)); clist = (char **)calloc(argc, sizeof (char **)); llist = (char **)calloc(argc, sizeof (char **)); plist = (char **)calloc(argc, sizeof (char **)); for (i = 1; i < argc; i++) { if (*argv[i] == '-') switch (argv[i][1]) { case 'S': sflag++; cflag++; continue; case 'o': if (++i < argc) { outfile = argv[i]; switch (getsuf(outfile)) { case 'c': error("-o would overwrite %s", outfile); exit(8); } } continue; case 'O': oflag++; continue; case 'p': proflag++; crt0 = "/lib/mcrt0.o"; if (argv[i][2] == 'g') crt0 = "/usr/lib/gcrt0.o"; continue; case 'w': wflag++; continue; case 'E': exflag++; case 'P': pflag++; if (argv[i][1]=='P') fprintf(stderr, "cc: warning: -P option obsolete; you should use -E instead\n"); plist[np++] = argv[i]; case 'c': cflag++; continue; case 'M': exflag++; pflag++; Mflag++; /* and fall through */ case 'D': case 'I': case 'U': case 'C': plist[np++] = argv[i]; continue; case 'L': llist[nl++] = argv[i]; continue; case 't': if (chpass) error("-t overwrites earlier option", 0); chpass = argv[i]+2; if (chpass[0]==0) chpass = "012p"; continue; case 'B': if (npassname) error("-B overwrites earlier option", 0); npassname = argv[i]+2; if (npassname[0]==0) npassname = "/usr/c/o"; continue; case 'd': if (argv[i][2] == '\0') { debug++; continue; } continue; } t = argv[i]; c = getsuf(t); if (c=='c' || c=='s' || exflag) { clist[nc++] = t; t = setsuf(t, 'o'); } if (nodup(llist, t)) { llist[nl++] = t; if (getsuf(t)=='o') nxo++; } } if (npassname && chpass ==0) chpass = "012p"; if (chpass && npassname==0) npassname = "/usr/new"; if (chpass) for (t=chpass; *t; t++) { switch (*t) { case '0': ccom = strspl(npassname, "c0"); continue; case '1': ccom1 = strspl(npassname, "c1"); continue; case '2': c2 = strspl(npassname, "c2"); continue; case 'p': cpp = strspl(npassname, "cpp"); continue; } } if (nc==0) goto nocom; if (signal(SIGINT, SIG_IGN) != SIG_IGN) signal(SIGINT, idexit); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) signal(SIGTERM, idexit); if (signal(SIGHUP, SIG_IGN) != SIG_IGN) signal(SIGHUP, idexit); if (pflag==0) sprintf(tmp0, "/tmp/ctm%05.5d", getpid()); tmp1 = strspl(tmp0, "1"); tmp2 = strspl(tmp0, "2"); tmp3 = strspl(tmp0, "3"); if (pflag==0) tmp4 = strspl(tmp0, "4"); if (oflag) tmp5 = strspl(tmp0, "5"); for (i=0; i 1 && !Mflag) { printf("%s:\n", clist[i]); fflush(stdout); } if (!Mflag && getsuf(clist[i]) == 's') { assource = clist[i]; goto assemble; } else assource = tmp3; if (pflag) tmp4 = setsuf(clist[i], 'i'); av[0] = "cpp"; av[1] = clist[i]; na = 2; if (!exflag) av[na++] = tmp4; for (j = 0; j < np; j++) av[na++] = plist[j]; av[na++] = 0; if (callsys(cpp, av)) { exfail++; eflag++; } if (pflag || exfail) { cflag++; continue; } if (sflag) { if (nc==1 && outfile) tmp3 = outfile; else tmp3 = setsuf(clist[i], 's'); assource = tmp3; } av[0] = "c0"; av[1] = tmp4; av[2] = tmp1; av[3] = tmp2; na = 4; if (proflag) av[na++] = "-P"; if (wflag) av[na++] = "-w"; av[na] = 0; if (callsys(ccom, av)) { cflag++; eflag++; continue; } av[0] = "c1"; av[1] = tmp1; av[2] = tmp2; av[3] = oflag ? tmp5 : tmp3; av[4] = 0; if (callsys(ccom1, av)) { cflag++; eflag++; continue; } if (oflag) { av[0] = "c2"; av[1] = tmp5; av[2] = tmp3; av[3] = 0; if (callsys(c2, av)) { unlink(tmp3); tmp3 = assource = tmp5; } else unlink(tmp5); } if (sflag) continue; assemble: cunlink(tmp1); cunlink(tmp2); cunlink(tmp4); av[0] = "as"; av[1] = "-V"; av[2] = "-u"; av[3] = "-o"; if (cflag && nc==1 && outfile) av[4] = outfile; else av[4] = setsuf(clist[i], 'o'); av[5] = assource; av[6] = 0; if (callsys(as, av) > 1) { cflag++; eflag++; continue; } } nocom: if (cflag==0 && nl!=0) { i = 0; av[0] = "ld"; av[1] = "-X"; av[2] = crt0; na = 3; if (outfile) { av[na++] = "-o"; av[na++] = outfile; } while (i < nl) av[na++] = llist[i++]; if (proflag) av[na++] = "-lc_p"; else av[na++] = "-lc"; av[na++] = 0; eflag |= callsys(ld, av); if (nc==1 && nxo==1 && eflag==0) unlink(setsuf(clist[0], 'o')); } dexit(); } idexit() { eflag = 100; dexit(); } dexit() { if (!pflag) { cunlink(tmp1); cunlink(tmp2); if (sflag==0) cunlink(tmp3); cunlink(tmp4); cunlink(tmp5); } exit(eflag); } error(s, x) char *s, *x; { FILE *diag = exflag ? stderr : stdout; fprintf(diag, "cc: "); fprintf(diag, s, x); putc('\n', diag); exfail++; cflag++; eflag++; } getsuf(as) char as[]; { register int c; register char *s; register int t; s = as; c = 0; while (t = *s++) if (t=='/') c = 0; else c++; s -= 3; if (c <= MAXNAMLEN && c > 2 && *s++ == '.') return (*s); return (0); } char * setsuf(as, ch) char *as; { register char *s, *s1; s = s1 = savestr(as); while (*s) if (*s++ == '/') s1 = s; s[-1] = ch; return (s1); } callsys(f, v) char *f, **v; { int t, status; char **cpp; if (debug) { fprintf(stderr, "%s:", f); for (cpp = v; *cpp != 0; cpp++) fprintf(stderr, " %s", *cpp); fprintf(stderr, "\n"); } t = vfork(); if (t == -1) { printf("No more processes\n"); return (100); } if (t == 0) { execv(f, v); printf("Can't find %s\n", f); fflush(stdout); _exit(100); } while (t != wait(&status)) ; if ((t=(status&0377)) != 0 && t!=14) { if (t!=2) { printf("Fatal error in %s\n", f); eflag = 8; } dexit(); } return ((status>>8) & 0377); } nodup(l, os) char **l, *os; { register char *t, *s; register int c; s = os; if (getsuf(s) != 'o') return (1); while (t = *l++) { while (c = *s++) if (c != *t++) break; if (*t==0 && c==0) return (0); s = os; } return (1); } #define NSAVETAB 1024 char *savetab; int saveleft; char * savestr(cp) register char *cp; { register int len; len = strlen(cp) + 1; if (len > saveleft) { saveleft = NSAVETAB; if (len > saveleft) saveleft = len; savetab = (char *)malloc(saveleft); if (savetab == 0) { fprintf(stderr, "ran out of memory (savestr)\n"); exit(1); } } strncpy(savetab, cp, len); cp = savetab; savetab += len; saveleft -= len; return (cp); } char * strspl(left, right) char *left, *right; { char buf[BUFSIZ]; strcpy(buf, left); strcat(buf, right); return (savestr(buf)); } p0, "5"); for (i=0; i 1 && !Mflag) { printf("%s:\n", clist[i]); fflbin/tar.c 444 0 12 64473 4512205423 5563 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)tar.c 5.7 (Berkeley) 4/26/86"; #endif not lint /* * Tape Archival Program */ #include #include #include #include #include #include #include #include #include #include #define TBLOCK 512 #define NBLOCK 20 #define NAMSIZ 100 #define writetape(b) writetbuf(b, 1) #define min(a,b) ((a) < (b) ? (a) : (b)) #define max(a,b) ((a) > (b) ? (a) : (b)) union hblock { char dummy[TBLOCK]; struct header { char name[NAMSIZ]; char mode[8]; char uid[8]; char gid[8]; char size[12]; char mtime[12]; char chksum[8]; char linkflag; char linkname[NAMSIZ]; } dbuf; }; struct linkbuf { ino_t inum; dev_t devnum; int count; char pathname[NAMSIZ]; struct linkbuf *nextp; }; union hblock dblock; union hblock *tbuf; struct linkbuf *ihead; struct stat stbuf; int rflag; int xflag; int vflag; int tflag; int cflag; int mflag; int fflag; int iflag; int oflag; int pflag; int wflag; int hflag; int Bflag; int Fflag; int mt; int term; int chksum; int recno; int first; int prtlinkerr; int freemem = 1; int nblock = 0; int onintr(); int onquit(); int onhup(); #ifdef notdef int onterm(); #endif daddr_t low; daddr_t high; daddr_t bsrch(); FILE *vfile = stdout; FILE *tfile; char tname[] = "/tmp/tarXXXXXX"; char *usefile; char magtape[] = "/dev/rmt8"; char *malloc(); long time(); off_t lseek(); char *mktemp(); char *sprintf(); char *strcat(); char *strcpy(); char *rindex(); char *getcwd(); char *getwd(); char *getmem(); main(argc, argv) int argc; char *argv[]; { char *cp; if (argc < 2) usage(); tfile = NULL; usefile = magtape; argv[argc] = 0; argv++; for (cp = *argv++; *cp; cp++) switch(*cp) { case 'f': if (*argv == 0) { fprintf(stderr, "tar: tapefile must be specified with 'f' option\n"); usage(); } usefile = *argv++; fflag++; break; case 'c': cflag++; rflag++; break; case 'o': oflag++; break; case 'p': pflag++; break; case 'u': mktemp(tname); if ((tfile = fopen(tname, "w")) == NULL) { fprintf(stderr, "tar: cannot create temporary file (%s)\n", tname); done(1); } fprintf(tfile, "!!!!!/!/!/!/!/!/!/! 000\n"); /*FALL THRU*/ case 'r': rflag++; break; case 'v': vflag++; break; case 'w': wflag++; break; case 'x': xflag++; break; case 't': tflag++; break; case 'm': mflag++; break; case '-': break; case '0': case '1': case '4': case '5': case '7': case '8': magtape[8] = *cp; usefile = magtape; break; case 'b': if (*argv == 0) { fprintf(stderr, "tar: blocksize must be specified with 'b' option\n"); usage(); } nblock = atoi(*argv); if (nblock <= 0) { fprintf(stderr, "tar: invalid blocksize \"%s\"\n", *argv); done(1); } argv++; break; case 'l': prtlinkerr++; break; case 'h': hflag++; break; case 'i': iflag++; break; case 'B': Bflag++; break; case 'F': Fflag++; break; default: fprintf(stderr, "tar: %c: unknown option\n", *cp); usage(); } if (!rflag && !xflag && !tflag) usage(); if (rflag) { if (cflag && tfile != NULL) usage(); if (signal(SIGINT, SIG_IGN) != SIG_IGN) (void) signal(SIGINT, onintr); if (signal(SIGHUP, SIG_IGN) != SIG_IGN) (void) signal(SIGHUP, onhup); if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) (void) signal(SIGQUIT, onquit); #ifdef notdef if (signal(SIGTERM, SIG_IGN) != SIG_IGN) (void) signal(SIGTERM, onterm); #endif mt = openmt(usefile, 1); dorep(argv); done(0); } mt = openmt(usefile, 0); if (xflag) doxtract(argv); else dotable(argv); done(0); } usage() { fprintf(stderr, "tar: usage: tar -{txru}[cvfblmhopwBi] [tapefile] [blocksize] file1 file2...\n"); done(1); } int openmt(tape, writing) char *tape; int writing; { if (strcmp(tape, "-") == 0) { /* * Read from standard input or write to standard output. */ if (writing) { if (cflag == 0) { fprintf(stderr, "tar: can only create standard output archives\n"); done(1); } vfile = stderr; setlinebuf(vfile); mt = dup(1); } else { mt = dup(0); Bflag++; } } else { /* * Use file or tape on local machine. */ if (writing) { if (cflag) mt = open(tape, O_RDWR|O_CREAT|O_TRUNC, 0666); else mt = open(tape, O_RDWR); } else mt = open(tape, O_RDONLY); if (mt < 0) { fprintf(stderr, "tar: "); perror(tape); done(1); } } return(mt); } dorep(argv) char *argv[]; { register char *cp, *cp2; char wdir[MAXPATHLEN], tempdir[MAXPATHLEN], *parent; if (!cflag) { getdir(); do { passtape(); if (term) done(0); getdir(); } while (!endtape()); backtape(); if (tfile != NULL) { char buf[200]; sprintf(buf, "sort +0 -1 +1nr %s -o %s; awk '$1 != prev {print; prev=$1}' %s >%sX; mv %sX %s", tname, tname, tname, tname, tname, tname); fflush(tfile); system(buf); freopen(tname, "r", tfile); fstat(fileno(tfile), &stbuf); high = stbuf.st_size; } } (void) getcwd(wdir); while (*argv && ! term) { cp2 = *argv; if (!strcmp(cp2, "-C") && argv[1]) { argv++; if (chdir(*argv) < 0) { fprintf(stderr, "tar: can't change directories to "); perror(*argv); } else (void) getcwd(wdir); argv++; continue; } if (*argv[0] == '/'){ parent = ""; } else { parent = wdir; } for (cp = *argv; *cp; cp++) if (*cp == '/') cp2 = cp; if (cp2 != *argv) { *cp2 = '\0'; if (chdir(*argv) < 0) { fprintf(stderr, "tar: can't change directories to "); perror(*argv); continue; } parent = getcwd(tempdir); *cp2 = '/'; cp2++; } putfile(*argv++, cp2, parent); if (chdir(wdir) < 0) { fprintf(stderr, "tar: cannot change back?: "); perror(wdir); } } putempty(); putempty(); flushtape(); if (prtlinkerr == 0) return; for (; ihead != NULL; ihead = ihead->nextp) { if (ihead->count == 0) continue; fprintf(stderr, "tar: missing links to %s\n", ihead->pathname); } } endtape() { return (dblock.dbuf.name[0] == '\0'); } getdir() { register struct stat *sp; int i; top: readtape((char *)&dblock); if (dblock.dbuf.name[0] == '\0') return; sp = &stbuf; sscanf(dblock.dbuf.mode, "%o", &i); sp->st_mode = i; sscanf(dblock.dbuf.uid, "%o", &i); sp->st_uid = i; sscanf(dblock.dbuf.gid, "%o", &i); sp->st_gid = i; sscanf(dblock.dbuf.size, "%lo", &sp->st_size); sscanf(dblock.dbuf.mtime, "%lo", &sp->st_mtime); sscanf(dblock.dbuf.chksum, "%o", &chksum); if (chksum != (i = checksum())) { fprintf(stderr, "tar: directory checksum error (%d != %d)\n", chksum, i); if (iflag) goto top; done(2); } if (tfile != NULL) fprintf(tfile, "%s %s\n", dblock.dbuf.name, dblock.dbuf.mtime); } passtape() { long blocks; char *bufp; if (dblock.dbuf.linkflag == '1') return; blocks = stbuf.st_size; blocks += TBLOCK-1; blocks /= TBLOCK; while (blocks-- > 0) (void) readtbuf(&bufp, TBLOCK); } putfile(longname, shortname, parent) char *longname; char *shortname; char *parent; { int infile = 0; long blocks; char buf[TBLOCK]; char *bigbuf; register char *cp; struct direct *dp; DIR *dirp; register int i; long l; char newparent[NAMSIZ+64]; extern int errno; int maxread; int hint; /* amount to write to get "in sync" */ if (!hflag) i = lstat(shortname, &stbuf); else i = stat(shortname, &stbuf); if (i < 0) { fprintf(stderr, "tar: "); perror(longname); return; } if (tfile != NULL && checkupdate(longname) == 0) return; if (checkw('r', longname) == 0) return; if (Fflag && checkf(shortname, stbuf.st_mode, Fflag) == 0) return; switch (stbuf.st_mode & S_IFMT) { case S_IFDIR: for (i = 0, cp = buf; *cp++ = longname[i++];) ; *--cp = '/'; *++cp = 0 ; if (!oflag) { if ((cp - buf) >= NAMSIZ) { fprintf(stderr, "tar: %s: file name too long\n", longname); return; } stbuf.st_size = 0; tomodes(&stbuf); strcpy(dblock.dbuf.name,buf); sprintf(dblock.dbuf.chksum, "%6o", checksum()); (void) writetape((char *)&dblock); } sprintf(newparent, "%s/%s", parent, shortname); if (chdir(shortname) < 0) { perror(shortname); return; } if ((dirp = opendir(".")) == NULL) { fprintf(stderr, "tar: %s: directory read error\n", longname); if (chdir(parent) < 0) { fprintf(stderr, "tar: cannot change back?: "); perror(parent); } return; } while ((dp = readdir(dirp)) != NULL && !term) { if (dp->d_ino == 0) continue; if (!strcmp(".", dp->d_name) || !strcmp("..", dp->d_name)) continue; strcpy(cp, dp->d_name); l = telldir(dirp); closedir(dirp); putfile(buf, cp, newparent); dirp = opendir("."); seekdir(dirp, l); } closedir(dirp); if (chdir(parent) < 0) { fprintf(stderr, "tar: cannot change back?: "); perror(parent); } break; case S_IFLNK: tomodes(&stbuf); if (strlen(longname) >= NAMSIZ) { fprintf(stderr, "tar: %s: file name too long\n", longname); return; } strcpy(dblock.dbuf.name, longname); if (stbuf.st_size + 1 >= NAMSIZ) { fprintf(stderr, "tar: %s: symbolic link too long\n", longname); return; } i = readlink(shortname, dblock.dbuf.linkname, NAMSIZ - 1); if (i < 0) { fprintf(stderr, "tar: can't read symbolic link "); perror(longname); return; } dblock.dbuf.linkname[i] = '\0'; dblock.dbuf.linkflag = '2'; if (vflag) fprintf(vfile, "a %s symbolic link to %s\n", longname, dblock.dbuf.linkname); sprintf(dblock.dbuf.size, "%11lo", 0L); sprintf(dblock.dbuf.chksum, "%6o", checksum()); (void) writetape((char *)&dblock); break; case S_IFREG: if ((infile = open(shortname, 0)) < 0) { fprintf(stderr, "tar: "); perror(longname); return; } tomodes(&stbuf); if (strlen(longname) >= NAMSIZ) { fprintf(stderr, "tar: %s: file name too long\n", longname); close(infile); return; } strcpy(dblock.dbuf.name, longname); if (stbuf.st_nlink > 1) { struct linkbuf *lp; int found = 0; for (lp = ihead; lp != NULL; lp = lp->nextp) if (lp->inum == stbuf.st_ino && lp->devnum == stbuf.st_dev) { found++; break; } if (found) { strcpy(dblock.dbuf.linkname, lp->pathname); dblock.dbuf.linkflag = '1'; sprintf(dblock.dbuf.chksum, "%6o", checksum()); (void) writetape( (char *) &dblock); if (vflag) fprintf(vfile, "a %s link to %s\n", longname, lp->pathname); lp->count--; close(infile); return; } lp = (struct linkbuf *) getmem(sizeof(*lp)); if (lp != NULL) { lp->nextp = ihead; ihead = lp; lp->inum = stbuf.st_ino; lp->devnum = stbuf.st_dev; lp->count = stbuf.st_nlink - 1; strcpy(lp->pathname, longname); } } blocks = (stbuf.st_size + (TBLOCK-1)) / TBLOCK; if (vflag) fprintf(vfile, "a %s %ld blocks\n", longname, blocks); sprintf(dblock.dbuf.chksum, "%6o", checksum()); hint = writetape((char *)&dblock); maxread = max(stbuf.st_blksize, (nblock * TBLOCK)); if ((bigbuf = malloc((unsigned)maxread)) == 0) { maxread = TBLOCK; bigbuf = buf; } while ((i = read(infile, bigbuf, min((hint*TBLOCK), maxread))) > 0 && blocks > 0) { register int nblks; nblks = ((i-1)/TBLOCK)+1; if (nblks > blocks) nblks = blocks; hint = writetbuf(bigbuf, nblks); blocks -= nblks; } close(infile); if (bigbuf != buf) free(bigbuf); if (i < 0) { fprintf(stderr, "tar: Read error on "); perror(longname); } else if (blocks != 0 || i != 0) fprintf(stderr, "tar: %s: file changed size\n", longname); while (--blocks >= 0) putempty(); break; default: fprintf(stderr, "tar: %s is not a file. Not dumped\n", longname); break; } } doxtract(argv) char *argv[]; { long blocks, bytes; int ofile, i; extern int errno; for (;;) { if ((i = wantit(argv)) == 0) continue; if (i == -1) break; /* end of tape */ if (checkw('x', dblock.dbuf.name) == 0) { passtape(); continue; } if (Fflag) { char *s; if ((s = rindex(dblock.dbuf.name, '/')) == 0) s = dblock.dbuf.name; else s++; if (checkf(s, stbuf.st_mode, Fflag) == 0) { passtape(); continue; } } if (checkdir(dblock.dbuf.name)) { /* have a directory */ if (mflag == 0) dodirtimes(&dblock); continue; } if (dblock.dbuf.linkflag == '2') { /* symlink */ /* * only unlink non directories or empty * directories */ if (rmdir(dblock.dbuf.name) < 0) { if (errno == ENOTDIR) unlink(dblock.dbuf.name); } if (symlink(dblock.dbuf.linkname, dblock.dbuf.name)<0) { fprintf(stderr, "tar: %s: symbolic link failed: ", dblock.dbuf.name); perror(""); continue; } if (vflag) fprintf(vfile, "x %s symbolic link to %s\n", dblock.dbuf.name, dblock.dbuf.linkname); #ifdef notdef /* ignore alien orders */ chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); if (mflag == 0) setimes(dblock.dbuf.name, stbuf.st_mtime); if (pflag) chmod(dblock.dbuf.name, stbuf.st_mode & 07777); #endif continue; } if (dblock.dbuf.linkflag == '1') { /* regular link */ /* * only unlink non directories or empty * directories */ if (rmdir(dblock.dbuf.name) < 0) { if (errno == ENOTDIR) unlink(dblock.dbuf.name); } if (link(dblock.dbuf.linkname, dblock.dbuf.name) < 0) { fprintf(stderr, "tar: can't link %s to %s: ", dblock.dbuf.name, dblock.dbuf.linkname); perror(""); continue; } if (vflag) fprintf(vfile, "%s linked to %s\n", dblock.dbuf.name, dblock.dbuf.linkname); continue; } if ((ofile = creat(dblock.dbuf.name,stbuf.st_mode&0xfff)) < 0) { fprintf(stderr, "tar: can't create %s: ", dblock.dbuf.name); perror(""); passtape(); continue; } chown(dblock.dbuf.name, stbuf.st_uid, stbuf.st_gid); blocks = ((bytes = stbuf.st_size) + TBLOCK-1)/TBLOCK; if (vflag) fprintf(vfile, "x %s, %ld bytes, %ld tape blocks\n", dblock.dbuf.name, bytes, blocks); for (; blocks > 0;) { register int nread; char *bufp; register int nwant; nwant = NBLOCK*TBLOCK; if (nwant > (blocks*TBLOCK)) nwant = (blocks*TBLOCK); nread = readtbuf(&bufp, nwant); if (write(ofile, bufp, (int)min(nread, bytes)) < 0) { fprintf(stderr, "tar: %s: HELP - extract write error", dblock.dbuf.name); perror(""); done(2); } bytes -= nread; blocks -= (((nread-1)/TBLOCK)+1); } close(ofile); if (mflag == 0) setimes(dblock.dbuf.name, stbuf.st_mtime); if (pflag) chmod(dblock.dbuf.name, stbuf.st_mode & 07777); } if (mflag == 0) { dblock.dbuf.name[0] = '\0'; /* process the whole stack */ dodirtimes(&dblock); } } dotable(argv) char *argv[]; { register int i; for (;;) { if ((i = wantit(argv)) == 0) continue; if (i == -1) break; /* end of tape */ if (vflag) longt(&stbuf); printf("%s", dblock.dbuf.name); if (dblock.dbuf.linkflag == '1') printf(" linked to %s", dblock.dbuf.linkname); if (dblock.dbuf.linkflag == '2') printf(" symbolic link to %s", dblock.dbuf.linkname); printf("\n"); passtape(); } } putempty() { char buf[TBLOCK]; bzero(buf, sizeof (buf)); (void) writetape(buf); } longt(st) register struct stat *st; { register char *cp; char *ctime(); pmode(st); printf("%3d/%1d", st->st_uid, st->st_gid); printf("%7ld", st->st_size); cp = ctime(&st->st_mtime); printf(" %-12.12s %-4.4s ", cp+4, cp+20); } #define SUID 04000 #define SGID 02000 #define ROWN 0400 #define WOWN 0200 #define XOWN 0100 #define RGRP 040 #define WGRP 020 #define XGRP 010 #define ROTH 04 #define WOTH 02 #define XOTH 01 #define STXT 01000 int m1[] = { 1, ROWN, 'r', '-' }; int m2[] = { 1, WOWN, 'w', '-' }; int m3[] = { 2, SUID, 's', XOWN, 'x', '-' }; int m4[] = { 1, RGRP, 'r', '-' }; int m5[] = { 1, WGRP, 'w', '-' }; int m6[] = { 2, SGID, 's', XGRP, 'x', '-' }; int m7[] = { 1, ROTH, 'r', '-' }; int m8[] = { 1, WOTH, 'w', '-' }; int m9[] = { 2, STXT, 't', XOTH, 'x', '-' }; int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; pmode(st) register struct stat *st; { register int **mp; for (mp = &m[0]; mp < &m[9];) selectbits(*mp++, st); } selectbits(pairp, st) int *pairp; struct stat *st; { register int n, *ap; ap = pairp; n = *ap++; while (--n>=0 && (st->st_mode&*ap++)==0) ap++; putchar(*ap); } /* * Make all directories needed by `name'. If `name' is itself * a directory on the tar tape (indicated by a trailing '/'), * return 1; else 0. */ checkdir(name) register char *name; { register char *cp; /* * Quick check for existence of directory. */ if ((cp = rindex(name, '/')) == 0) return (0); *cp = '\0'; if (access(name, 0) == 0) { /* already exists */ *cp = '/'; return (cp[1] == '\0'); /* return (lastchar == '/') */ } *cp = '/'; /* * No luck, try to make all directories in path. */ for (cp = name; *cp; cp++) { if (*cp != '/') continue; *cp = '\0'; if (access(name, 0) < 0) { if (mkdir(name, 0777) < 0) { perror(name); *cp = '/'; return (0); } chown(name, stbuf.st_uid, stbuf.st_gid); if (pflag && cp[1] == '\0') /* dir on the tape */ chmod(name, stbuf.st_mode & 07777); } *cp = '/'; } return (cp[-1]=='/'); } onintr() { (void) signal(SIGINT, SIG_IGN); term++; } onquit() { (void) signal(SIGQUIT, SIG_IGN); term++; } onhup() { (void) signal(SIGHUP, SIG_IGN); term++; } #ifdef notdef onterm() { (void) signal(SIGTERM, SIG_IGN); term++; } #endif tomodes(sp) register struct stat *sp; { register char *cp; for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) *cp = '\0'; sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); sprintf(dblock.dbuf.mtime, "%11lo ", sp->st_mtime); } checksum() { register i; register char *cp; for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++) *cp = ' '; i = 0; for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) i += *cp; return (i); } checkw(c, name) char *name; { if (!wflag) return (1); printf("%c ", c); if (vflag) longt(&stbuf); printf("%s: ", name); return (response() == 'y'); } response() { char c; c = getchar(); if (c != '\n') while (getchar() != '\n') ; else c = 'n'; return (c); } checkf(name, mode, howmuch) char *name; int mode, howmuch; { int l; if ((mode & S_IFMT) == S_IFDIR){ if ((strcmp(name, "SCCS")==0) || (strcmp(name, "RCS")==0)) return(0); return(1); } if ((l = strlen(name)) < 3) return (1); if (howmuch > 1 && name[l-2] == '.' && name[l-1] == 'o') return (0); if (strcmp(name, "core") == 0 || strcmp(name, "errs") == 0 || (howmuch > 1 && strcmp(name, "a.out") == 0)) return (0); /* SHOULD CHECK IF IT IS EXECUTABLE */ return (1); } /* Is the current file a new file, or the newest one of the same name? */ checkupdate(arg) char *arg; { char name[100]; long mtime; daddr_t seekp; daddr_t lookup(); rewind(tfile); for (;;) { if ((seekp = lookup(arg)) < 0) return (1); fseek(tfile, seekp, 0); fscanf(tfile, "%s %lo", name, &mtime); return (stbuf.st_mtime > mtime); } } done(n) { unlink(tname); exit(n); } /* * Do we want the next entry on the tape, i.e. is it selected? If * not, skip over the entire entry. Return -1 if reached end of tape. */ wantit(argv) char *argv[]; { register char **cp; getdir(); if (endtape()) return (-1); if (*argv == 0) return (1); for (cp = argv; *cp; cp++) if (prefix(*cp, dblock.dbuf.name)) return (1); passtape(); return (0); } /* * Does s2 begin with the string s1, on a directory boundary? */ prefix(s1, s2) register char *s1, *s2; { while (*s1) if (*s1++ != *s2++) return (0); if (*s2) return (*s2 == '/'); return (1); } #define N 200 int njab; daddr_t lookup(s) char *s; { register i; daddr_t a; for(i=0; s[i]; i++) if (s[i] == ' ') break; a = bsrch(s, i, low, high); return (a); } daddr_t bsrch(s, n, l, h) daddr_t l, h; char *s; { register i, j; char b[N]; daddr_t m, m1; njab = 0; loop: if (l >= h) return ((daddr_t) -1); m = l + (h-l)/2 - N/2; if (m < l) m = l; fseek(tfile, m, 0); fread(b, 1, N, tfile); njab++; for(i=0; i= h) return ((daddr_t) -1); m1 = m; j = i; for(i++; i 0) { l = m1; goto loop; } return (m); } cmp(b, s, n) char *b, *s; { register i; if (b[0] != '\n') exit(2); for(i=0; i s[i]) return (-1); if (b[i+1] < s[i]) return (1); } return (b[i+1] == ' '? 0 : -1); } readtape(buffer) char *buffer; { char *bufp; if (first == 0) getbuf(); (void) readtbuf(&bufp, TBLOCK); bcopy(bufp, buffer, TBLOCK); return(TBLOCK); } readtbuf(bufpp, size) char **bufpp; int size; { register int i; if (recno >= nblock || first == 0) { if ((i = bread(mt, (char *)tbuf, TBLOCK*nblock)) < 0) mterr("read", i, 3); if (first == 0) { if ((i % TBLOCK) != 0) { fprintf(stderr, "tar: tape blocksize error\n"); done(3); } i /= TBLOCK; if (i != nblock) { fprintf(stderr, "tar: blocksize = %d\n", i); nblock = i; } first = 1; } recno = 0; } if (size > ((nblock-recno)*TBLOCK)) size = (nblock-recno)*TBLOCK; *bufpp = (char *)&tbuf[recno]; recno += (size/TBLOCK); return (size); } writetbuf(buffer, n) register char *buffer; register int n; { int i; if (first == 0) { getbuf(); first = 1; } if (recno >= nblock) { i = write(mt, (char *)tbuf, TBLOCK*nblock); if (i != TBLOCK*nblock) mterr("write", i, 2); recno = 0; } /* * Special case: We have an empty tape buffer, and the * users data size is >= the tape block size: Avoid * the bcopy and dma direct to tape. BIG WIN. Add the * residual to the tape buffer. */ while (recno == 0 && n >= nblock) { i = write(mt, buffer, TBLOCK*nblock); if (i != TBLOCK*nblock) mterr("write", i, 2); n -= nblock; buffer += (nblock * TBLOCK); } while (n-- > 0) { bcopy(buffer, (char *)&tbuf[recno++], TBLOCK); buffer += TBLOCK; if (recno >= nblock) { i = write(mt, (char *)tbuf, TBLOCK*nblock); if (i != TBLOCK*nblock) mterr("write", i, 2); recno = 0; } } /* Tell the user how much to write to get in sync */ return (nblock - recno); } backtape() { static int mtdev = 1; static struct mtop mtop = {MTBSR, 1}; struct mtget mtget; if (mtdev == 1) mtdev = ioctl(mt, MTIOCGET, (char *)&mtget); if (mtdev == 0) { if (ioctl(mt, MTIOCTOP, (char *)&mtop) < 0) { fprintf(stderr, "tar: tape backspace error: "); perror(""); done(4); } } else lseek(mt, (daddr_t) -TBLOCK*nblock, 1); recno--; } flushtape() { int i; i = write(mt, (char *)tbuf, TBLOCK*nblock); if (i != TBLOCK*nblock) mterr("write", i, 2); } mterr(operation, i, exitcode) char *operation; int i; { fprintf(stderr, "tar: tape %s error: ", operation); if (i < 0) perror(""); else fprintf(stderr, "unexpected EOF\n"); done(exitcode); } bread(fd, buf, size) int fd; char *buf; int size; { int count; static int lastread = 0; if (!Bflag) return (read(fd, buf, size)); for (count = 0; count < size; count += lastread) { lastread = read(fd, buf, size - count); if (lastread <= 0) { if (count > 0) return (count); return (lastread); } buf += lastread; } return (count); } char * getcwd(buf) char *buf; { if (getwd(buf) == NULL) { fprintf(stderr, "tar: %s\n", buf); exit(1); } return (buf); } getbuf() { if (nblock == 0) { fstat(mt, &stbuf); if ((stbuf.st_mode & S_IFMT) == S_IFCHR) nblock = NBLOCK; else { nblock = stbuf.st_blksize / TBLOCK; if (nblock == 0) nblock = NBLOCK; } } tbuf = (union hblock *)malloc((unsigned)nblock*TBLOCK); if (tbuf == NULL) { fprintf(stderr, "tar: blocksize %d too big, can't get memory\n", nblock); done(1); } } /* * Save this directory and its mtime on the stack, popping and setting * the mtimes of any stacked dirs which aren't parents of this one. * A null directory causes the entire stack to be unwound and set. * * Since all the elements of the directory "stack" share a common * prefix, we can make do with one string. We keep only the current * directory path, with an associated array of mtime's, one for each * '/' in the path. A negative mtime means no mtime. The mtime's are * offset by one (first index 1, not 0) because calling this with a null * directory causes mtime[0] to be set. * * This stack algorithm is not guaranteed to work for tapes created * with the 'r' option, but the vast majority of tapes with * directories are not. This avoids saving every directory record on * the tape and setting all the times at the end. */ char dirstack[NAMSIZ]; #define NTIM (NAMSIZ/2+1) /* a/b/c/d/... */ time_t mtime[NTIM]; dodirtimes(hp) union hblock *hp; { register char *p = dirstack; register char *q = hp->dbuf.name; register int ndir = 0; char *savp; int savndir; /* Find common prefix */ while (*p == *q) { if (*p++ == '/') ++ndir; q++; } savp = p; savndir = ndir; while (*p) { /* * Not a child: unwind the stack, setting the times. * The order we do this doesn't matter, so we go "forward." */ if (*p++ == '/') if (mtime[++ndir] >= 0) { *--p = '\0'; /* zap the slash */ setimes(dirstack, mtime[ndir]); *p++ = '/'; } } p = savp; ndir = savndir; /* Push this one on the "stack" */ while (*p = *q++) /* append the rest of the new dir */ if (*p++ == '/') mtime[++ndir] = -1; mtime[ndir] = stbuf.st_mtime; /* overwrite the last one */ } setimes(path, mt) char *path; time_t mt; { struct timeval tv[2]; tv[0].tv_sec = time((time_t *) 0); tv[1].tv_sec = mt; tv[0].tv_usec = tv[1].tv_usec = 0; if (utimes(path, tv) < 0) { fprintf(stderr, "tar: can't set time on %s: ", path); perror(""); } } char * getmem(size) { char *p = malloc((unsigned) size); if (p == NULL && freemem) { fprintf(stderr, "tar: out of memory, link and directory modtime info lost\n"); freemem = 0; } return (p); } { register int **mp; for (mp = &m[0]; mp < &m[9];) selectbits(*mp++, st); } selectbits(pairp, st) int *pairp; struct stat *st; { register int n, *ap; ap = pairp; n = *ap++; while (--n>bin/kill.c 444 0 12 3205 4013202664 5672 static char *sccsid = "@(#)kill.c 4.4 (Berkeley) 4/20/86"; /* * kill - send signal to process */ #include #include char *signm[] = { 0, "HUP", "INT", "QUIT", "ILL", "TRAP", "IOT", "EMT", "FPE", /* 1-8 */ "KILL", "BUS", "SEGV", "SYS", "PIPE", "ALRM", "TERM", "URG", /* 9-16 */ "STOP", "TSTP", "CONT", "CHLD", "TTIN", "TTOU", "IO", "XCPU", /* 17-24 */ "XFSZ", "VTALRM", "PROF", "WINCH", 0, "USR1", "USR2", 0, /* 25-31 */ }; main(argc, argv) char **argv; { register signo, pid, res; int errlev; extern char *sys_errlist[]; extern errno; errlev = 0; if (argc <= 1) { usage: printf("usage: kill [ -sig ] pid ...\n"); printf("for a list of signals: kill -l\n"); exit(2); } if (*argv[1] == '-') { if (argv[1][1] == 'l') { for (signo = 0; signo <= NSIG; signo++) { if (signm[signo]) printf("%s ", signm[signo]); if (signo == 16) printf("\n"); } printf("\n"); exit(0); } else if (isdigit(argv[1][1])) { signo = atoi(argv[1]+1); if (signo < 0 || signo > NSIG) { printf("kill: %s: number out of range\n", argv[1]); exit(1); } } else { char *name = argv[1]+1; for (signo = 0; signo <= NSIG; signo++) if (signm[signo] && !strcmp(signm[signo], name)) goto foundsig; printf("kill: %s: unknown signal; kill -l lists signals\n", name); exit(1); foundsig: ; } argc--; argv++; } else signo = SIGTERM; argv++; while (argc > 1) { if (!(isdigit(**argv) || **argv == '-')) goto usage; res = kill(pid = atoi(*argv), signo); if (res<0) { printf("%u: %s\n", pid, sys_errlist[errno]); errlev = 1; } argc--; argv++; } return(errlev); } nal(SIGTERM, SIG_IGN); term++; } #endif tomodes(sp) register struct stat *sp; { register char *cp; for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) *cp = '\0'; sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); bin/sync.c 444 0 12 120 4013202664 5664 static char *sccsid = "@(#)sync.c 4.1 (Berkeley) 10/1/80"; main() { sync(); } s.ådate.ces.ä tee.c«wall.ces.ªchmod.cs.© od.c.¨chgrp.cs.§expr.ys.¦ rcp.c¥ testžMakefile.mkdir.c.œ mt.c.›nice.c.š pagesize.c5™ pwd.c˜rmdir.c.c— who.c–chpass.cŽMANIFEST. nm.c.use.diskŒ pathnames.hk‹ PORTa† ls.Zsysctlcs}hostnamesy nmfivrmail.ccu$chflagscbin/size.c 444 0 12 3135 5514436245 5726 #if defined(DOSCCS) && !defined(lint) static char *sccsid = "@(#)size.c 4.4.1 (2.11BSD GTE) 1/1/94"; #endif /* * size */ #include #include int header; main(argc, argv) char **argv; { struct exec buf; long sum; int gorp,i; int err = 0; FILE *f; #ifdef pdp11 struct ovlhdr ovlbuf; /* overlay structure */ long coresize; /* total text size */ short skip; /* skip over overlay sizes of 0 */ #endif if (argc==1) { *argv = "a.out"; argc++; --argv; } gorp = argc; while(--argc) { ++argv; if ((f = fopen(*argv, "r"))==NULL) { printf("size: %s not found\n", *argv); err++; continue; } if (fread((char *)&buf, sizeof(buf), 1, f) != 1 || N_BADMAG(buf)) { printf("size: %s not an object file\n", *argv); fclose(f); err++; continue; } if (header == 0) { printf("text\tdata\tbss\tdec\thex\n"); header = 1; } printf("%u\t%u\t%u\t", buf.a_text,buf.a_data,buf.a_bss); sum = (long) buf.a_text + (long) buf.a_data + (long) buf.a_bss; printf("%ld\t%lx", sum, sum); if (gorp>2) printf("\t%s", *argv); #ifdef pdp11 if (buf.a_magic == A_MAGIC5 || buf.a_magic == A_MAGIC6) { fread(&ovlbuf,sizeof(ovlbuf),1,f); coresize = buf.a_text; for (i = 0; i < NOVL; i++) coresize += ovlbuf.ov_siz[i]; printf("\ttotal text: %ld\n\toverlays: ", coresize); for (i = 0,skip = 0; i < NOVL; i++) { if (!ovlbuf.ov_siz[i]) { ++skip; continue; } for (;skip;--skip) fputs(",0",stdout); if (i > 0) putchar(','); printf("%u", ovlbuf.ov_siz[i]); } } #endif printf("\n"); fclose(f); } exit(err); } argc--; argv++; } return(errlev); } nal(SIGTERM, SIG_IGN); term++; } #endif tomodes(sp) register struct stat *sp; { register char *cp; for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++) *cp = '\0'; sprintf(dblock.dbuf.mode, "%6o ", sp->st_mode & 07777); sprintf(dblock.dbuf.uid, "%6o ", sp->st_uid); sprintf(dblock.dbuf.gid, "%6o ", sp->st_gid); sprintf(dblock.dbuf.size, "%11lo ", sp->st_size); bin/date.c 444 0 12 20223 4263536637 5714 /* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1985 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)date.c 4.20 (Berkeley) 3/24/87"; #endif not lint /* * Date - print and set date */ #include #include #include #include #include #include #include #include #include #include #define WTMP "/usr/adm/wtmp" #define ATOI2(ar) (ar[0] - '0') * 10 + (ar[1] - '0'); ar += 2; static struct timeval tv; static int retval; static int dmsize[] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static struct utmp wtmp[2] = { { "|", "", "", 0 }, { "{", "", "", 0 } }; main(argc,argv) int argc; char **argv; { extern int optind; extern char *optarg; static char usage[] = "usage: date [-nu] [-d dst] [-t timezone] [yymmddhhmm[.ss]]\n"; struct timezone tz; char *ap, /* time string */ *tzn; /* time zone */ int ch, /* getopts char */ uflag, /* do it in GMT */ nflag, /* only set time locally */ wf; /* wtmp file descriptor */ long time(); uid_t getuid(); char *username, *getlogin(); nflag = uflag = 0; tz.tz_dsttime = tz.tz_minuteswest = 0; while ((ch = getopt(argc,argv,"d:nut:")) != EOF) switch((char)ch) { case 'd': tz.tz_dsttime = atoi(optarg) ? 1 : 0; break; case 'n': nflag = 1; break; case 't': tz.tz_minuteswest = atoi(optarg); break; case 'u': uflag = 1; break; default: fputs(usage,stderr); exit(1); } argc -= optind; argv += optind; if (argc > 1) { fputs(usage,stderr); exit(1); } if ((tz.tz_minuteswest || tz.tz_dsttime) && settimeofday((struct timeval *)NULL,&tz)) { perror("settimeofday"); retval = 1; goto display; } if (gettimeofday(&tv,&tz)) { perror("gettimeofday"); exit(1); } if (!argc) goto display; wtmp[0].ut_time = tv.tv_sec; if (gtime(*argv)) { fputs(usage,stderr); retval = 1; goto display; } if (!uflag) { /* convert to GMT assuming local time */ tv.tv_sec += (long)tz.tz_minuteswest * SECS_PER_MIN; /* now fix up local daylight time */ if (localtime((time_t *)&tv.tv_sec)->tm_isdst) tv.tv_sec -= SECS_PER_HOUR; } if (nflag || !netsettime(tv)) { if (settimeofday(&tv,(struct timezone *)0)) { perror("settimeofday"); retval = 1; goto display; } if ((wf = open(WTMP,O_WRONLY|O_APPEND)) < 0) fputs("date: can't write wtmp file.\n",stderr); else { (void)time((time_t *)&wtmp[1].ut_time); /*NOSTRICT*/ (void)write(wf,(char *)wtmp,sizeof(wtmp)); (void)close(wf); } } username = getlogin(); if (!username || *username == '\0') /* single-user or no tty */ username = "root"; syslog(LOG_AUTH | LOG_NOTICE,"date set by %s",username); display: if (gettimeofday(&tv,(struct timezone *)0)) { perror("gettimeofday"); exit(1); } if (uflag) { ap = asctime(gmtime((time_t *)&tv.tv_sec)); tzn = "GMT"; } else { struct tm *tp; tp = localtime((time_t *)&tv.tv_sec); ap = asctime(tp); tzn = tp->tm_zone; } printf("%.20s%s%s",ap,tzn,ap + 19); exit(retval); } /* * gtime -- * convert user's time into number of seconds */ static gtime(ap) register char *ap; /* user argument */ { register int year, month; register char *C; /* pointer into time argument */ struct tm *L; int day, hour, mins, secs; for (secs = 0, C = ap;*C;++C) { if (*C == '.') { /* seconds provided */ if (strlen(C) != 3) return(1); *C = NULL; secs = (C[1] - '0') * 10 + (C[2] - '0'); break; } if (!isdigit(*C)) return(-1); } L = localtime((time_t *)&tv.tv_sec); year = L->tm_year; /* defaults */ month = L->tm_mon + 1; day = L->tm_mday; switch ((int)(C - ap)) { /* length */ case 10: /* yymmddhhmm */ year = ATOI2(ap); case 8: /* mmddhhmm */ month = ATOI2(ap); case 6: /* ddhhmm */ day = ATOI2(ap); case 4: /* hhmm */ hour = ATOI2(ap); mins = ATOI2(ap); break; default: return(1); } if (*ap || month < 1 || month > 12 || day < 1 || day > 31 || mins < 0 || mins > 59 || secs < 0 || secs > 59) return(1); if (hour == 24) { ++day; hour = 0; } else if (hour < 0 || hour > 23) return(1); tv.tv_sec = 0; year += TM_YEAR_BASE; if (isleap(year) && month > 2) ++tv.tv_sec; for (--year;year >= EPOCH_YEAR;--year) tv.tv_sec += isleap(year) ? DAYS_PER_LYEAR : DAYS_PER_NYEAR; while (--month) tv.tv_sec += dmsize[month]; tv.tv_sec += day - 1; tv.tv_sec = HOURS_PER_DAY * tv.tv_sec + hour; tv.tv_sec = MINS_PER_HOUR * tv.tv_sec + mins; tv.tv_sec = SECS_PER_MIN * tv.tv_sec + secs; return(0); } #include #include #include #define TSPTYPES #include #define WAITACK 2 /* seconds */ #define WAITDATEACK 5 /* seconds */ extern int errno; /* * Set the date in the machines controlled by timedaemons * by communicating the new date to the local timedaemon. * If the timedaemon is in the master state, it performs the * correction on all slaves. If it is in the slave state, it * notifies the master that a correction is needed. * Returns 1 on success, 0 on failure. */ static netsettime(ntv) struct timeval ntv; { int s, length, port, timed_ack, found, err; long waittime; fd_set ready; char hostname[MAXHOSTNAMELEN]; struct timeval tout; struct servent *sp; struct tsp msg; struct sockaddr_in sin, dest, from; sp = getservbyname("timed", "udp"); if (sp == 0) { fputs("udp/timed: unknown service\n",stderr); retval = 2; return (0); } dest.sin_port = sp->s_port; dest.sin_family = AF_INET; dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY); s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { if (errno == EPROTONOSUPPORT) return(0); perror("date: socket"); goto bad; } bzero((char *)&sin, sizeof (sin)); sin.sin_family = AF_INET; for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { sin.sin_port = htons((u_short)port); if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0) break; if (errno != EADDRINUSE) { if (errno != EADDRNOTAVAIL) perror("date: bind"); goto bad; } } if (port == IPPORT_RESERVED / 2) { fputs("date: All ports in use\n",stderr); goto bad; } msg.tsp_type = TSP_SETDATE; msg.tsp_vers = TSPVERSION; if (gethostname(hostname, sizeof (hostname))) { perror("gethostname"); goto bad; } (void) strncpy(msg.tsp_name, hostname, sizeof (hostname)); msg.tsp_seq = htons((u_short)0); msg.tsp_time.tv_sec = htonl((u_long)ntv.tv_sec); msg.tsp_time.tv_usec = htonl((u_long)ntv.tv_usec); length = sizeof (struct sockaddr_in); if (connect(s, &dest, length) < 0) { perror("date: connect"); goto bad; } if (send(s, (char *)&msg, sizeof (struct tsp), 0) < 0) { if (errno != ECONNREFUSED) perror("date: send"); goto bad; } timed_ack = -1; waittime = WAITACK; loop: tout.tv_sec = waittime; tout.tv_usec = 0; FD_ZERO(&ready); FD_SET(s, &ready); found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout); length = sizeof(err); if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&err, &length) == 0 && err) { errno = err; if (errno != ECONNREFUSED) perror("date: send (delayed error)"); goto bad; } if (found > 0 && FD_ISSET(s, &ready)) { length = sizeof (struct sockaddr_in); if (recvfrom(s, (char *)&msg, sizeof (struct tsp), 0, &from, &length) < 0) { if (errno != ECONNREFUSED) perror("date: recvfrom"); goto bad; } msg.tsp_seq = ntohs(msg.tsp_seq); msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec); msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec); switch (msg.tsp_type) { case TSP_ACK: timed_ack = TSP_ACK; waittime = WAITDATEACK; goto loop; case TSP_DATEACK: (void)close(s); return (1); default: fprintf(stderr, "date: Wrong ack received from timed: %s\n", tsptype[msg.tsp_type]); timed_ack = -1; break; } } if (timed_ack == -1) fputs("date: Can't reach time daemon, time set locally.\n", stderr); bad: (void)close(s); retval = 2; return (0); } egister int i; if (recno >= nblock || first == 0) { if ((i = bread(mt, (char *)tbuf, TBLOCK*nblock)) < 0) mterr("read", i, 3); if (first == 0) { if ((i % TBLOCK) != 0) { fprintf(stderr, "tar: tape blocksize error\n"); done(3); } i /= TBLOCK; if (i != nblock) { fprintf(stderr, "tar: blocksize = %d\n", i); nblock = i; } fibin/tee.c 444 0 12 2647 4013202665 5526 #ifndef lint static char *sccsid = "@(#)tee.c 5.4 (Berkeley) 12/14/85"; #endif /* * tee-- pipe fitting */ #include #include #include #include #define BUFSIZ 8192 int openf[20] = { 1 }; int n = 1; int t = 0; int aflag; char in[BUFSIZ]; char out[BUFSIZ]; extern errno; long lseek(); main(argc,argv) char **argv; { int register r,w,p; struct stat buf; while(argc>1&&argv[1][0]=='-') { switch(argv[1][1]) { case 'a': aflag++; break; case 'i': case 0: signal(SIGINT, SIG_IGN); } argv++; argc--; } fstat(1,&buf); t = (buf.st_mode&S_IFMT)==S_IFCHR; if(lseek(1,0L,1)==-1&&errno==ESPIPE) t++; while(argc-->1) { if(aflag) { openf[n] = open(argv[1],1); if(openf[n] < 0) openf[n] = creat(argv[1],0666); lseek(openf[n++],0L,2); } else openf[n++] = creat(argv[1],0666); if(stat(argv[1],&buf)>=0) { if((buf.st_mode&S_IFMT)==S_IFCHR) t++; } else { puts("tee: cannot open "); puts(argv[1]); puts("\n"); n--; } argv++; } r = w = 0; for(;;) { for(p=0;p=w) { if(t>0&&p>0) break; w = read(0,in,BUFSIZ); r = 0; if(w<=0) { stash(p); exit(0); } } out[p++] = in[r++]; } stash(p); } } stash(p) { int k; int i; int d; d = t ? 16 : p; for(i=0; i 2) ++tv.tv_sec; for (--year;year >= EPOCH_YEAR;--year) tv.tv_sebin/wall.c 444 0 12 6232 5511210706 5701 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)wall.c 5.3.1 (2.11BSD GTE) 12/31/93"; #endif /* * wall.c - Broadcast a message to all users. * * This program is not related to David Wall, whose Stanford Ph.D. thesis * is entitled "Mechanisms for Broadcast and Selective Broadcast". */ #include #include #include #include #include #include #include #include #define IGNOREUSER "sleeper" char hostname[32]; char mesg[3000]; int msize,sline; struct utmp *utmp; char *strcpy(); char *strcat(); char *malloc(); char who[UT_NAMESIZE + 1] = "???"; long clock, time(); struct tm *localtime(); struct tm *localclock; extern errno; main(argc, argv) char *argv[]; { register int i, c; register struct utmp *p; int f; struct stat statb; (void) gethostname(hostname, sizeof (hostname)); if ((f = open("/etc/utmp", O_RDONLY, 0)) < 0) { fprintf(stderr, "Cannot open /etc/utmp\n"); exit(1); } clock = time( 0 ); localclock = localtime( &clock ); sline = ttyslot(); /* 'utmp' slot no. of sender */ (void) fstat(f, &statb); utmp = (struct utmp *)malloc((unsigned)statb.st_size); c = read(f, (char *)utmp, (int)statb.st_size); (void) close(f); c /= sizeof(struct utmp); if (sline) strncpy(who, utmp[sline].ut_name, sizeof(utmp[sline].ut_name)); sprintf(mesg, "\n\007\007Broadcast Message from %s@%s (%.*s) at %d:%02d ...\r\n\n" , who , hostname , sizeof(utmp[sline].ut_line) , utmp[sline].ut_line , localclock -> tm_hour , localclock -> tm_min ); msize = strlen(mesg); if (argc >= 2) { /* take message from unix file instead of standard input */ if (freopen(argv[1], "r", stdin) == NULL) { perror(argv[1]); exit(1); } } while ((i = getchar()) != EOF) { if (i == '\n') mesg[msize++] = '\r'; if (msize >= sizeof mesg) { fprintf(stderr, "Message too long\n"); exit(1); } mesg[msize++] = i; } fclose(stdin); for (i=0; iut_name[0] == 0 || strncmp(p->ut_name, IGNOREUSER, sizeof(p->ut_name)) == 0) continue; sendmes(p->ut_line); } exit(0); } sendmes(tty) char *tty; { register f, flags; static char t[50] = "/dev/"; int e, i; strcpy(t + 5, tty); if ((f = open(t, O_WRONLY|O_NDELAY)) < 0) { if (errno != EWOULDBLOCK) perror(t); return; } if ((flags = fcntl(f, F_GETFL, 0)) == -1) { perror(t); return; } if (fcntl(f, F_SETFL, flags | FNDELAY) == -1) goto oldway; i = write(f, mesg, msize); e = errno; (void) fcntl(f, F_SETFL, flags); if (i == msize) { (void) close(f); return; } if (e != EWOULDBLOCK) { errno = e; perror(t); (void) close(f); return; } oldway: while ((i = fork()) == -1) if (wait((int *)0) == -1) { fprintf(stderr, "Try again\n"); return; } if (i) { (void) close(f); return; } (void) write(f, mesg, msize); exit(0); } hostname, sizeof (hostname)); if ((f = open("/etc/utmp", O_RDONLY, 0)) < 0) { fprintf(stderr, "Cannot open /etc/utmp\n"); exit(1); } clock = time( 0 ); localclock = localtime( &clock ); sline = ttyslot(); /* 'utmp' slot no. of sender */ (void) fstat(f, &statb); utmp = (struct utmp *)malloc((unsigned)statb.st_size); c = read(f, (char *)utmp, (inbin/chmod.c 444 0 12 11722 5656611555 6075 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)chmod.c 5.5.1 (2.11BSD GTE) 11/4/94"; #endif /* * chmod options mode files * where * mode is [ugoa][+-=][rwxXstugo] or an octal number * options are -Rf */ #include #include #include #include #include static char *fchdirmsg = "Can't fchdir() back to starting directory"; char *modestring, *ms; int um; int status; int fflag; int rflag; main(argc, argv) char *argv[]; { register char *p, *flags; register int i; struct stat st; int fcurdir; if (argc < 3) { fprintf(stderr, "Usage: chmod [-Rf] [ugoa][+-=][rwxXstugo] file ...\n"); exit(-1); } argv++, --argc; while (argc > 0 && argv[0][0] == '-') { for (p = &argv[0][1]; *p; p++) switch (*p) { case 'R': rflag++; break; case 'f': fflag++; break; default: goto done; } argc--, argv++; } done: modestring = argv[0]; um = umask(0); (void) newmode(0); if (rflag) { fcurdir = open(".", O_RDONLY); if (fcurdir < 0) fatal(255, "Can't open ."); } for (i = 1; i < argc; i++) { p = argv[i]; /* do stat for directory arguments */ if (lstat(p, &st) < 0) { status += Perror(p); continue; } if (rflag && (st.st_mode&S_IFMT) == S_IFDIR) { status += chmodr(p, newmode(st.st_mode), fcurdir); continue; } if ((st.st_mode&S_IFMT) == S_IFLNK && stat(p, &st) < 0) { status += Perror(p); continue; } if (chmod(p, newmode(st.st_mode)) < 0) { status += Perror(p); continue; } } close(fcurdir); exit(status); } chmodr(dir, mode, savedir) char *dir; int mode; int savedir; { register DIR *dirp; register struct direct *dp; struct stat st; int ecode; /* * Change what we are given before doing it's contents */ if (chmod(dir, newmode(mode)) < 0 && Perror(dir)) return (1); if (chdir(dir) < 0) { Perror(dir); return (1); } if ((dirp = opendir(".")) == NULL) { Perror(dir); return (1); } dp = readdir(dirp); dp = readdir(dirp); /* read "." and ".." */ ecode = 0; for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { if (lstat(dp->d_name, &st) < 0) { ecode = Perror(dp->d_name); if (ecode) break; continue; } if ((st.st_mode&S_IFMT) == S_IFDIR) { ecode = chmodr(dp->d_name, newmode(st.st_mode), dirfd(dirp)); if (ecode) break; continue; } if ((st.st_mode&S_IFMT) == S_IFLNK) continue; if (chmod(dp->d_name, newmode(st.st_mode)) < 0 && (ecode = Perror(dp->d_name))) break; } if (fchdir(savedir) < 0) fatal(255, fchdirmsg); closedir(dirp); return (ecode); } error(fmt, a) char *fmt, *a; { if (!fflag) { fprintf(stderr, "chmod: "); fprintf(stderr, fmt, a); putc('\n', stderr); } return (!fflag); } fatal(status, fmt, a) int status; char *fmt, *a; { fflag = 0; (void) error(fmt, a); exit(status); } Perror(s) char *s; { if (!fflag) { fprintf(stderr, "chmod: "); perror(s); } return (!fflag); } newmode(nm) unsigned nm; { register o, m, b; int savem; ms = modestring; savem = nm; m = abs(); if (*ms == '\0') return (m); do { m = who(); while (o = what()) { b = where(nm); switch (o) { case '+': nm |= b & m; break; case '-': nm &= ~(b & m); break; case '=': nm &= ~m; nm |= b & m; break; } } } while (*ms++ == ','); if (*--ms) fatal(255, "invalid mode"); return (nm); } abs() { register c, i; i = 0; while ((c = *ms++) >= '0' && c <= '7') i = (i << 3) + (c - '0'); ms--; return (i); } #define USER 05700 /* user's bits */ #define GROUP 02070 /* group's bits */ #define OTHER 00007 /* other's bits */ #define ALL 01777 /* all (note absence of setuid, etc) */ #define READ 00444 /* read permit */ #define WRITE 00222 /* write permit */ #define EXEC 00111 /* exec permit */ #define SETID 06000 /* set[ug]id */ #define STICKY 01000 /* sticky bit */ who() { register m; m = 0; for (;;) switch (*ms++) { case 'u': m |= USER; continue; case 'g': m |= GROUP; continue; case 'o': m |= OTHER; continue; case 'a': m |= ALL; continue; default: ms--; if (m == 0) m = ALL & ~um; return (m); } } what() { switch (*ms) { case '+': case '-': case '=': return (*ms++); } return (0); } where(om) register om; { register m; m = 0; switch (*ms) { case 'u': m = (om & USER) >> 6; goto dup; case 'g': m = (om & GROUP) >> 3; goto dup; case 'o': m = (om & OTHER); dup: m &= (READ|WRITE|EXEC); m |= (m << 3) | (m << 6); ++ms; return (m); } for (;;) switch (*ms++) { case 'r': m |= READ; continue; case 'w': m |= WRITE; continue; case 'x': m |= EXEC; continue; case 'X': if ((om & S_IFDIR) || (om & EXEC)) m |= EXEC; continue; case 's': m |= SETID; continue; case 't': m |= STICKY; continue; default: ms--; return (m); } } type]); timed_ack = -1; break; } } ibin/od.c 444 0 12 40645 4013202666 5374 static char *sccsid = "@(#)od.c 5.12 (Berkeley) 5/14/84"; /* * od -- octal, hex, decimal, character dump of data in a file. * * usage: od [-abBcdDefFhHiIlLopPs[n]vw[n]xX] [file] [[+]offset[.][b] [label]] * * where the option flags have the following meaning: * character object radix signed? * a byte (10) (n.a.) ASCII named byte stream * b byte 8 no byte octal * c byte (8) (no) character with octal non-graphic bytes * d short 10 no * D long 10 no * e,F double (10) double precision floating pt. * f float (10) single precision floating pt. * h,x short 16 no * H,X long 16 no * i short 10 yes * I,l,L long 10 yes * o,B short 8 no (default conversion) * O long 8 no * s[n] string (8) ASCII graphic strings * * p indicate EVEN parity on 'a' conversion * P indicate ODD parity on 'a' conversion * v show all data - don't skip like lines. * w[n] bytes per display line * * More than one format character may be given. * If {file} is not specified, standard input is read. * If {file} is not specified, then {offset} must start with '+'. * {Offset} may be HEX (0xnnn), OCTAL (0nn), or decimal (nnn.). * The default is octal. The same radix will be used to display the address. */ #include #define DBUF_SIZE BUFSIZ #define BIG_DBUF 32 #define NO 0 #define YES 1 #define EVEN -1 #define ODD 1 #define UNSIGNED 0 #define SIGNED 1 #define PADDR 1 #define MIN_SLEN 3 int a_put(); int b_put(); int c_put(); int s_put(); int us_put(); int l_put(); int f_put(); int d_put(); int st_put(); struct dfmt { int df_field; /* external field required for object */ int df_size; /* size (bytes) of object */ int df_radix; /* conversion radix */ int df_signed; /* signed? flag */ int df_paddr; /* "put address on each line?" flag */ int (*df_put)(); /* function to output object */ char *df_fmt; /* output string format */ } *conv_vec[32]; /* vector of conversions to be done */ struct dfmt ascii = { 3, sizeof (char), 10, 0, PADDR, a_put, 0}; struct dfmt byte = { 3, sizeof (char), 8, UNSIGNED, PADDR, b_put, 0}; struct dfmt cchar = { 3, sizeof (char), 8, UNSIGNED, PADDR, c_put, 0}; struct dfmt u_s_oct = { 6, sizeof (short), 8, UNSIGNED, PADDR, us_put, 0}; struct dfmt u_s_dec = { 5, sizeof (short), 10, UNSIGNED, PADDR, us_put, 0}; struct dfmt u_s_hex = { 4, sizeof (short), 16, UNSIGNED, PADDR, us_put, 0}; struct dfmt u_l_oct = {11, sizeof (long), 8, UNSIGNED, PADDR, l_put, 0}; struct dfmt u_l_dec = {10, sizeof (long), 10, UNSIGNED, PADDR, l_put, 0}; struct dfmt u_l_hex = { 8, sizeof (long), 16, UNSIGNED, PADDR, l_put, 0}; struct dfmt s_s_dec = { 6, sizeof (short), 10, SIGNED, PADDR, s_put, 0}; struct dfmt s_l_dec = {11, sizeof (long), 10, SIGNED, PADDR, l_put, 0}; struct dfmt flt = {14, sizeof (float), 10, SIGNED, PADDR, f_put, 0}; struct dfmt dble = {21, sizeof (double), 10, SIGNED, PADDR, d_put, 0}; struct dfmt string = { 0, 0, 8, 0, NO, st_put, 0}; char usage[] ="usage: od [-abcdfhilopswvx] [file] [[+]offset[.][b] [label]]"; char dbuf[DBUF_SIZE]; char lastdbuf[DBUF_SIZE]; int addr_base = 8; /* default address base is OCTAL */ long addr = 0L; /* current file offset */ long label = -1L; /* current label; -1 is "off" */ int dbuf_size = 16; /* file bytes / display line */ int _parity = NO; /* show parity on ascii bytes */ char fmt[] = " %s"; /* 12 blanks */ char *icvt(); char *scvt(); char *underline(); long get_addr(); /* * special form of _ctype */ #define A 01 #define G 02 #define D 04 #define P 010 #define X 020 #define isdigit(c) (_ctype[c] & D) #define isascii(c) (_ctype[c] & A) #define isgraphic(c) (_ctype[c] & G) #define isprint(c) (_ctype[c] & P) #define ishex(c) (_ctype[c] & (X|D)) char _ctype[256] = { /* 000 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 010 */ A, A, A, 0, A, A, 0, 0, /* 020 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 030 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 040 */ P|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, /* 050 */ P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, /* 060 */ P|G|D|A,P|G|D|A,P|G|D|A,P|G|D|A,P|G|D|A,P|G|D|A,P|G|D|A,P|G|D|A, /* 070 */ P|G|D|A,P|G|D|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, /* 100 */ P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, /* 110 */ P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, /* 120 */ P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, /* 130 */ P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, /* 140 */ P|G|A,X|P|G|A,X|P|G|A,X|P|G|A,X|P|G|A,X|P|G|A,X|P|G|A, P|G|A, /* 150 */ P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, /* 160 */ P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, /* 170 */ P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, P|G|A, 0, /* 200 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 210 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 220 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 230 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 240 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 250 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 260 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 270 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 300 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 310 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 320 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 330 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 340 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 350 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 360 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 370 */ 0, 0, 0, 0, 0, 0, 0, 0, }; main(argc, argv) int argc; char **argv; { register char *p; register char *l; register n, same; struct dfmt *d; struct dfmt **cv = conv_vec; int showall = NO; int field, llen, nelm; int max_llen = 0; argv++; argc--; if(argc > 0) { p = *argv; if(*p == '-') { while(*++p != '\0') { switch(*p) { case 'a': d = &ascii; break; case 'b': d = &byte; break; case 'c': d = &cchar; break; case 'd': d = &u_s_dec; break; case 'D': d = &u_l_dec; break; case 'e': case 'F': d = &dble; break; case 'f': d = &flt; break; case 'h': case 'x': d = &u_s_hex; break; case 'H': case 'X': d = &u_l_hex; break; case 'i': d = &s_s_dec; break; case 'I': case 'l': case 'L': d = &s_l_dec; break; case 'o': case 'B': d = &u_s_oct; break; case 'O': d = &u_l_oct; break; case 'p': _parity = EVEN; continue; case 'P': _parity = ODD; continue; case 's': d = &string; *(cv++) = d; while (isdigit(p[1])) d->df_size = (10 * d->df_size) + (*++p - '0'); if (d->df_size <= 0) d->df_size = MIN_SLEN; showall = YES; continue; case 'w': dbuf_size = 0; while (isdigit(p[1])) dbuf_size = (10 * dbuf_size) + (*++p - '0'); if (dbuf_size == 0) dbuf_size = BIG_DBUF; continue; case 'v': showall = YES; continue; default: printf("od: bad flag -%c\n", *p); puts(usage); exit(1); } *(cv++) = d; } argc--; argv++; } } /* * if nothing spec'd, setup default conversion. */ if(cv == conv_vec) *(cv++) = &u_s_oct; *cv = (struct dfmt *)0; /* * calculate display parameters */ for (cv = conv_vec; d = *cv; cv++) { nelm = (dbuf_size + d->df_size - 1) / d->df_size; llen = nelm * (d->df_field + 1); if (llen > max_llen) max_llen = llen; } /* * setup df_fmt to point to uniform output fields. */ for (cv = conv_vec; d = *cv; cv++) { if (d->df_field) /* only if external field is known */ { nelm = (dbuf_size + d->df_size - 1) / d->df_size; field = max_llen / nelm; d->df_fmt = fmt + 12 - (field - d->df_field); } } /* * input file specified ? */ if(argc > 0 && **argv != '+') { if (freopen(*argv, "r", stdin) == NULL) { perror(*argv); exit(1); } argv++; argc--; } /* * check for possible offset [label] */ if (argc > 0) { addr = get_addr(*argv); offset(addr); argv++; argc--; if (argc > 0) label = get_addr(*argv); } /* * main dump loop */ same = -1; while ((n = fread(dbuf, 1, dbuf_size, stdin)) > 0) { if (same>=0 && bcmp(dbuf, lastdbuf, dbuf_size) == 0 && !showall) { if (same==0) { printf("*\n"); same = 1; } } else { line(n); same = 0; p = dbuf; l = lastdbuf; for (nelm = 0; nelm < dbuf_size; nelm++) { *l++ = *p; *p++ = '\0'; } } addr += n; if (label >= 0) label += n; } /* * Some conversions require "flushing". */ n = 0; for (cv = conv_vec; *cv; cv++) { if ((*cv)->df_paddr) { if (n++ == 0) put_addr(addr, label, '\n'); } else (*((*cv)->df_put))(0, *cv); } } put_addr(a, l, c) long a; long l; char c; { fputs(icvt(a, addr_base, UNSIGNED, 7), stdout); if (l >= 0) printf(" (%s)", icvt(l, addr_base, UNSIGNED, 7)); putchar(c); } line(n) int n; { register i, first; register struct dfmt *c; register struct dfmt **cv = conv_vec; first = YES; while (c = *cv++) { if (c->df_paddr) { if (first) { put_addr(addr, label, ' '); first = NO; } else { putchar('\t'); if (label >= 0) fputs("\t ", stdout); } } i = 0; while (i < n) i += (*(c->df_put))(dbuf+i, c); if (c->df_paddr) putchar('\n'); } } s_put(n, d) short *n; struct dfmt *d; { printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field)); return(d->df_size); } us_put(n, d) unsigned short *n; struct dfmt *d; { printf(d->df_fmt, icvt((long)*n, d->df_radix, d->df_signed, d->df_field)); return(d->df_size); } l_put(n, d) long *n; struct dfmt *d; { printf(d->df_fmt, icvt(*n, d->df_radix, d->df_signed, d->df_field)); return(d->df_size); } d_put(f, d) double *f; struct dfmt *d; { char fbuf[24]; struct l { long n[2]; }; #if vax if ((((struct l *)f)->n[0] & 0xff00) == 0x8000) /* Vax illegal f.p. */ sprintf(fbuf, " %08x %08x", ((struct l *)f)->n[0], ((struct l *)f)->n[1]); else #endif sprintf(fbuf, "%21.14e", *f); printf(d->df_fmt, fbuf); return(d->df_size); } f_put(f, d) float *f; struct dfmt *d; { char fbuf[16]; #if vax if ((*(long *)f & 0xff00) == 0x8000) /* Vax illegal f.p. form */ sprintf(fbuf, " %08x", *(long *)f); else #endif sprintf(fbuf, "%14.7e", *f); printf(d->df_fmt, fbuf); return(d->df_size); } char asc_name[34][4] = { /* 000 */ "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", /* 010 */ " bs", " ht", " nl", " vt", " ff", " cr", " so", " si", /* 020 */ "dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", /* 030 */ "can", " em", "sub", "esc", " fs", " gs", " rs", " us", /* 040 */ " sp", "del" }; a_put(cc, d) char *cc; struct dfmt *d; { int c = *cc; register char *s = " "; register pbit = parity((int)c & 0377); c &= 0177; if (isgraphic(c)) { s[2] = c; if (pbit == _parity) printf(d->df_fmt, underline(s)); else printf(d->df_fmt, s); } else { if (c == 0177) c = ' ' + 1; if (pbit == _parity) printf(d->df_fmt, underline(asc_name[c])); else printf(d->df_fmt, asc_name[c]); } return(1); } parity(word) int word; { register int p = 0; register int w = word; if (w) do { p ^= 1; } while(w &= (~(-w))); return (p? ODD:EVEN); } char * underline(s) char *s; { static char ulbuf[16]; register char *u = ulbuf; while (*s) { if (*s != ' ') { *u++ = '_'; *u++ = '\b'; } *u++ = *s++; } *u = '\0'; return(ulbuf); } b_put(b, d) char *b; struct dfmt *d; { printf(d->df_fmt, icvt((long)*b & 0377, d->df_radix, d->df_signed, d->df_field)); return(1); } c_put(cc, d) char *cc; struct dfmt *d; { register char *s; register int n; register int c = *cc & 0377; s = scvt(c, d); for (n = d->df_field - strlen(s); n > 0; n--) putchar(' '); printf(d->df_fmt, s); return(1); } char *scvt(c, d) int c; struct dfmt *d; { static char s[2]; switch(c) { case '\0': return("\\0"); case '\b': return("\\b"); case '\f': return("\\f"); case '\n': return("\\n"); case '\r': return("\\r"); case '\t': return("\\t"); default: if (isprint(c)) { s[0] = c; return(s); } return(icvt((long)c, d->df_radix, d->df_signed, d->df_field)); } } /* * Look for strings. * A string contains bytes > 037 && < 177, and ends with a null. * The minimum length is given in the dfmt structure. */ #define CNULL '\0' #define S_EMPTY 0 #define S_FILL 1 #define S_CONT 2 #define SBUFSIZE 1024 static char str_buf[SBUFSIZE]; static int str_mode = S_EMPTY; static char *str_ptr; static long str_addr; static long str_label; st_put(cc, d) char *cc; struct dfmt *d; { register int c; if (cc == 0) { pr_sbuf(d, YES); return(1); } c = (*cc & 0377); if (str_mode & S_FILL) { if (isascii(c)) put_sbuf(c, d); else { *str_ptr = CNULL; if (c == NULL) pr_sbuf(d, YES); str_mode = S_EMPTY; } } else if (isascii(c)) { str_mode = S_FILL; str_addr = addr + (cc - dbuf); /* ugly */ if ((str_label = label) >= 0) str_label += (cc - dbuf); /* '' */ str_ptr = str_buf; put_sbuf(c, d); } return(1); } put_sbuf(c, d) int c; struct dfmt *d; { *str_ptr++ = c; if (str_ptr >= (str_buf + SBUFSIZE)) { pr_sbuf(d, NO); str_ptr = str_buf; str_mode |= S_CONT; } } pr_sbuf(d, end) struct dfmt *d; int end; { register char *p = str_buf; if (str_mode == S_EMPTY || (!(str_mode & S_CONT) && (str_ptr - str_buf) < d->df_size)) return; if (!(str_mode & S_CONT)) put_addr(str_addr, str_label, ' '); while (p < str_ptr) fputs(scvt(*p++, d), stdout); if (end) putchar('\n'); } /* * integer to ascii conversion * * This code has been rearranged to produce optimized runtime code. */ #define MAXINTLENGTH 32 static char _digit[] = "0123456789abcdef"; static char _icv_buf[MAXINTLENGTH+1]; static long _mask = 0x7fffffff; char * icvt (value, radix, signed, ndigits) long value; int radix; int signed; int ndigits; { register long val = value; register long rad = radix; register char *b = &_icv_buf[MAXINTLENGTH]; register char *d = _digit; register long tmp1; register long tmp2; long rem; long kludge; int sign; if (val == 0) { *--b = '0'; sign = 0; goto done; /*return(b);*/ } if (signed && (sign = (val < 0))) /* signed conversion */ { /* * It is necessary to do the first divide * before the absolute value, for the case -2^31 * * This is actually what is being done... * tmp1 = (int)(val % rad); * val /= rad; * val = -val * *--b = d[-tmp1]; */ tmp1 = val / rad; *--b = d[(tmp1 * rad) - val]; val = -tmp1; } else /* unsigned conversion */ { sign = 0; if (val < 0) { /* ALL THIS IS TO SIMULATE UNSIGNED LONG MOD & DIV */ kludge = _mask - (rad - 1); val &= _mask; /* * This is really what's being done... * rem = (kludge % rad) + (val % rad); * val = (kludge / rad) + (val / rad) + (rem / rad) + 1; * *--b = d[rem % rad]; */ tmp1 = kludge / rad; tmp2 = val / rad; rem = (kludge - (tmp1 * rad)) + (val - (tmp2 * rad)); val = ++tmp1 + tmp2; tmp1 = rem / rad; val += tmp1; *--b = d[rem - (tmp1 * rad)]; } } while (val) { /* * This is really what's being done ... * *--b = d[val % rad]; * val /= rad; */ tmp1 = val / rad; *--b = d[val - (tmp1 * rad)]; val = tmp1; } done: if (sign) *--b = '-'; tmp1 = ndigits - (&_icv_buf[MAXINTLENGTH] - b); tmp2 = signed? ' ':'0'; while (tmp1 > 0) { *--b = tmp2; tmp1--; } return(b); } long get_addr(s) register char *s; { register char *p; register long a; register int d; if (*s=='+') s++; if (*s=='x') { s++; addr_base = 16; } else if (*s=='0' && s[1]=='x') { s += 2; addr_base = 16; } else if (*s == '0') addr_base = 8; p = s; while(*p) { if (*p++=='.') addr_base = 10; } for (a=0; *s; s++) { d = *s; if(isdigit(d)) a = a*addr_base + d - '0'; else if (ishex(d) && addr_base==16) a = a*addr_base + d + 10 - 'a'; else break; } if (*s == '.') s++; if(*s=='b') a *= 512; if(*s=='B') a *= 1024; return(a); } offset(a) long a; { if (canseek(stdin)) { /* * in case we're accessing a raw disk, * we have to seek in multiples of a physical block. */ fseek(stdin, a & 0xfffffe00L, 0); a &= 0x1ffL; } dumbseek(stdin, a); } dumbseek(s, offset) FILE *s; long offset; { char buf[BUFSIZ]; int n; int nr; while (offset > 0) { nr = (offset > BUFSIZ) ? BUFSIZ : (int)offset; if ((n = fread(buf, 1, nr, s)) != nr) { fprintf(stderr, "EOF\n"); exit(1); } offset -= n; } } #include #include canseek(f) FILE *f; { struct stat statb; return( (fstat(fileno(f),&statb)==0) && (statb.st_nlink > 0) && /*!pipe*/ (!isatty(fileno(f))) ); } )) d->df_size = (10 * d->df_size) + (*++p - '0'); if (d->df_size <= 0) d->bin/chgrp.c 444 0 12 7504 5656615561 6072 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)chgrp.c 5.7.1 (2.11BSD GTE) 11/4/94"; #endif /* * chgrp -fR gid file ... */ #include #include #include #include #include #include #include #include struct group *gr, *getgrnam(), *getgrgid(); struct passwd *getpwuid(), *pwd; struct stat stbuf; gid_t gid; uid_t uid; int status; int fflag, rflag; static char *fchdirmsg = "Can't fchdir() back to starting directory"; main(argc, argv) int argc; char *argv[]; { register c, i; register char *cp; int fcurdir; argc--, argv++; while (argc > 0 && argv[0][0] == '-') { for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { case 'f': fflag++; break; case 'R': rflag++; break; default: fatal(255, "unknown option: %c", *cp); /*NOTREACHED*/ } argv++, argc--; } if (argc < 2) { fprintf(stderr, "usage: chgrp [-fR] gid file ...\n"); exit(255); } uid = getuid(); if (isnumber(argv[0])) { gid = atoi(argv[0]); gr = getgrgid(gid); if (uid && gr == NULL) fatal(255, "%s: unknown group", argv[0]); } else { gr = getgrnam(argv[0]); if (gr == NULL) fatal(255, "%s: unknown group", argv[0]); gid = gr->gr_gid; } pwd = getpwuid(uid); if (pwd == NULL) fatal(255, "Who are you?"); if (uid && pwd->pw_gid != gid) { for (i=0; gr->gr_mem[i]; i++) if (!(strcmp(pwd->pw_name, gr->gr_mem[i]))) goto ok; if (fflag) exit(0); fatal(255, "You are not a member of the %s group", argv[0]); } ok: fcurdir = open(".", O_RDONLY); if (fcurdir < 0) fatal(255, "Can't open ."); for (c = 1; c < argc; c++) { /* do stat for directory arguments */ if (lstat(argv[c], &stbuf)) { status += Perror(argv[c]); continue; } if (uid && uid != stbuf.st_uid) { status += error("You are not the owner of %s", argv[c]); continue; } if (rflag && ((stbuf.st_mode & S_IFMT) == S_IFDIR)) { status += chownr(argv[c], stbuf.st_uid, gid, fcurdir); continue; } if (chown(argv[c], -1, gid)) { status += Perror(argv[c]); continue; } } exit(status); } isnumber(s) char *s; { register int c; while (c = *s++) if (!isdigit(c)) return (0); return (1); } chownr(dir, uid, gid, savedir) char *dir; uid_t uid; gid_t gid; int savedir; { register DIR *dirp; register struct direct *dp; struct stat st; int ecode; /* * Change what we are given before doing its contents. */ if (chown(dir, -1, gid) < 0 && Perror(dir)) return (1); if (chdir(dir) < 0) { Perror(dir); return (1); } if ((dirp = opendir(".")) == NULL) { Perror(dir); return (1); } dp = readdir(dirp); dp = readdir(dirp); /* read "." and ".." */ ecode = 0; for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { if (lstat(dp->d_name, &st) < 0) { ecode = Perror(dp->d_name); if (ecode) break; continue; } if (uid && uid != st.st_uid) { ecode = error("You are not the owner of %s", dp->d_name); continue; } if ((st.st_mode & S_IFMT) == S_IFDIR) { ecode = chownr(dp->d_name, st.st_uid, gid, dirfd(dirp)); if (ecode) break; continue; } if (chown(dp->d_name, -1, gid) < 0 && (ecode = Perror(dp->d_name))) break; } if (fchdir(savedir) < 0) fatal(255, fchdirmsg); closedir(dirp); return (ecode); } error(fmt, a) char *fmt, *a; { if (!fflag) { fprintf(stderr, "chgrp: "); fprintf(stderr, fmt, a); putc('\n', stderr); } return (!fflag); } /* VARARGS */ fatal(status, fmt, a) int status; char *fmt, *a; { fflag = 0; (void) error(fmt, a); exit(status); } Perror(s) char *s; { if (!fflag) { fprintf(stderr, "chgrp: "); perror(s); } return (!fflag); } (fstat(fileno(f),&statb)==0) && (statb.st_nlink > 0) && /*!pipe*/ (!isatty(fileno(f))) ); } )) d->df_size = (10 * d->df_size) + (*++p - '0'); if (d->df_size <= 0) d->bin/expr.y 444 0 12 25252 4013202667 5774 /* Yacc productions for "expr" command: */ %token OR AND ADD SUBT MULT DIV REM EQ GT GEQ LT LEQ NEQ %token A_STRING SUBSTR LENGTH INDEX NOARG MATCH /* operators listed below in increasing precedence: */ %left OR %left AND %left EQ LT GT GEQ LEQ NEQ %left ADD SUBT %left MULT DIV REM %left MCH %left MATCH %left SUBSTR %left LENGTH INDEX %% /* a single `expression' is evaluated and printed: */ expression: expr NOARG = { printf("%s\n", $1); exit((!strcmp($1,"0")||!strcmp($1,"\0"))? 1: 0); } ; expr: '(' expr ')' = { $$ = $2; } | expr OR expr = { $$ = conj(OR, $1, $3); } | expr AND expr = { $$ = conj(AND, $1, $3); } | expr EQ expr = { $$ = rel(EQ, $1, $3); } | expr GT expr = { $$ = rel(GT, $1, $3); } | expr GEQ expr = { $$ = rel(GEQ, $1, $3); } | expr LT expr = { $$ = rel(LT, $1, $3); } | expr LEQ expr = { $$ = rel(LEQ, $1, $3); } | expr NEQ expr = { $$ = rel(NEQ, $1, $3); } | expr ADD expr = { $$ = arith(ADD, $1, $3); } | expr SUBT expr = { $$ = arith(SUBT, $1, $3); } | expr MULT expr = { $$ = arith(MULT, $1, $3); } | expr DIV expr = { $$ = arith(DIV, $1, $3); } | expr REM expr = { $$ = arith(REM, $1, $3); } | expr MCH expr = { $$ = match($1, $3); } | MATCH expr expr = { $$ = match($2, $3); } | SUBSTR expr expr expr = { $$ = substr($2, $3, $4); } | LENGTH expr = { $$ = length($2); } | INDEX expr expr = { $$ = index($2, $3); } | A_STRING ; %% /* expression command */ #include #define ESIZE 256 #define error(c) errxx(c) #define EQL(x,y) !strcmp(x,y) long atol(); char **Av; int Ac; int Argi; char Mstring[1][128]; char *malloc(); extern int nbra; main(argc, argv) char **argv; { Ac = argc; Argi = 1; Av = argv; yyparse(); } char *operators[] = { "|", "&", "+", "-", "*", "/", "%", ":", "=", "==", "<", "<=", ">", ">=", "!=", "match", "substr", "length", "index", "\0" }; int op[] = { OR, AND, ADD, SUBT, MULT, DIV, REM, MCH, EQ, EQ, LT, LEQ, GT, GEQ, NEQ, MATCH, SUBSTR, LENGTH, INDEX }; yylex() { register char *p; register i; if(Argi >= Ac) return NOARG; p = Av[Argi++]; if(*p == '(' || *p == ')') return (int)*p; for(i = 0; *operators[i]; ++i) if(EQL(operators[i], p)) return op[i]; yylval = p; return A_STRING; } char *rel(op, r1, r2) register char *r1, *r2; { register long i; if(ematch(r1, "-*[0-9]*$") && ematch(r2, "[0-9]*$")) i = atol(r1) - atol(r2); else i = strcmp(r1, r2); switch(op) { case EQ: i = i==0; break; case GT: i = i>0; break; case GEQ: i = i>=0; break; case LT: i = i<0; break; case LEQ: i = i<=0; break; case NEQ: i = i!=0; break; } return i? "1": "0"; } char *arith(op, r1, r2) char *r1, *r2; { long i1, i2; register char *rv; if(!(ematch(r1, "[0-9]*$") && ematch(r2, "[0-9]*$"))) yyerror("non-numeric argument"); i1 = atol(r1); i2 = atol(r2); switch(op) { case ADD: i1 = i1 + i2; break; case SUBT: i1 = i1 - i2; break; case MULT: i1 = i1 * i2; break; case DIV: i1 = i1 / i2; break; case REM: i1 = i1 % i2; break; } rv = malloc(16); sprintf(rv, "%D", i1); return rv; } char *conj(op, r1, r2) char *r1, *r2; { register char *rv; switch(op) { case OR: if(EQL(r1, "0") || EQL(r1, "")) if(EQL(r2, "0") || EQL(r2, "")) rv = "0"; else rv = r2; else rv = r1; break; case AND: if(EQL(r1, "0") || EQL(r1, "")) rv = "0"; else if(EQL(r2, "0") || EQL(r2, "")) rv = "0"; else rv = r1; break; } return rv; } char *substr(v, s, w) char *v, *s, *w; { register si, wi; register char *res; si = atol(s); wi = atol(w); while(--si) if(*v) ++v; res = v; while(wi--) if(*v) ++v; *v = '\0'; return res; } char *length(s) register char *s; { register i = 0; register char *rv; while(*s++) ++i; rv = malloc(8); sprintf(rv, "%d", i); return rv; } char *index(s, t) char *s, *t; { register i, j; register char *rv; for(i = 0; s[i] ; ++i) for(j = 0; t[j] ; ++j) if(s[i]==t[j]) { sprintf(rv = malloc(8), "%d", ++i); return rv; } return "0"; } char *match(s, p) { register char *rv; sprintf(rv = malloc(8), "%d", ematch(s, p)); if(nbra) { rv = malloc(strlen(Mstring[0])+1); strcpy(rv, Mstring[0]); } return rv; } #define INIT register char *sp = instring; #define GETC() (*sp++) #define PEEKC() (*sp) #define UNGETC(c) (--sp) #define RETURN(c) return #define ERROR(c) errxx(c) ematch(s, p) char *s; register char *p; { static char expbuf[ESIZE]; char *compile(); register num; extern char *braslist[], *braelist[], *loc2; compile(p, expbuf, &expbuf[ESIZE], 0); if(nbra > 1) yyerror("Too many '\\('s"); if(advance(s, expbuf)) { if(nbra == 1) { p = braslist[0]; num = braelist[0] - p; strncpy(Mstring[0], p, num); Mstring[0][num] = '\0'; } return(loc2-s); } return(0); } errxx(c) { yyerror("RE error"); } #define CBRA 2 #define CCHR 4 #define CDOT 8 #define CCL 12 #define CDOL 20 #define CEOF 22 #define CKET 24 #define CBACK 36 #define STAR 01 #define RNGE 03 #define NBRA 9 #define PLACE(c) ep[c >> 3] |= bittab[c & 07] #define ISTHERE(c) (ep[c >> 3] & bittab[c & 07]) char *braslist[NBRA]; char *braelist[NBRA]; int nbra; char *loc1, *loc2, *locs; int sed; int circf; int low; int size; char bittab[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; char * compile(instring, ep, endbuf, seof) register char *ep; char *instring, *endbuf; { INIT /* Dependent declarations and initializations */ register c; register eof = seof; char *lastep = instring; int cclcnt; char bracket[NBRA], *bracketp; int closed; char neg; int lc; int i, cflg; lastep = 0; if((c = GETC()) == eof) { if(*ep == 0 && !sed) ERROR(41); RETURN(ep); } bracketp = bracket; circf = closed = nbra = 0; if (c == '^') circf++; else UNGETC(c); for (;;) { if (ep >= endbuf) ERROR(50); if((c = GETC()) != '*' && ((c != '\\') || (PEEKC() != '{'))) lastep = ep; if (c == eof) { *ep++ = CEOF; RETURN(ep); } switch (c) { case '.': *ep++ = CDOT; continue; case '\n': ERROR(36); case '*': if (lastep==0 || *lastep==CBRA || *lastep==CKET) goto defchar; *lastep |= STAR; continue; case '$': if(PEEKC() != eof) goto defchar; *ep++ = CDOL; continue; case '[': if(&ep[17] >= endbuf) ERROR(50); *ep++ = CCL; lc = 0; for(i = 0; i < 16; i++) ep[i] = 0; neg = 0; if((c = GETC()) == '^') { neg = 1; c = GETC(); } do { if(c == '\0' || c == '\n') ERROR(49); if(c == '-' && lc != 0) { if ((c = GETC()) == ']') { PLACE('-'); break; } while(lc < c) { PLACE(lc); lc++; } } lc = c; PLACE(c); } while((c = GETC()) != ']'); if(neg) { for(cclcnt = 0; cclcnt < 16; cclcnt++) ep[cclcnt] ^= -1; ep[0] &= 0376; } ep += 16; continue; case '\\': switch(c = GETC()) { case '(': if(nbra >= NBRA) ERROR(43); *bracketp++ = nbra; *ep++ = CBRA; *ep++ = nbra++; continue; case ')': if(bracketp <= bracket) ERROR(42); *ep++ = CKET; *ep++ = *--bracketp; closed++; continue; case '{': if(lastep == (char *) (0)) goto defchar; *lastep |= RNGE; cflg = 0; nlim: c = GETC(); i = 0; do { if ('0' <= c && c <= '9') i = 10 * i + c - '0'; else ERROR(16); } while(((c = GETC()) != '\\') && (c != ',')); if (i > 255) ERROR(11); *ep++ = i; if (c == ',') { if(cflg++) ERROR(44); if((c = GETC()) == '\\') *ep++ = 255; else { UNGETC(c); goto nlim; /* get 2'nd number */ } } if(GETC() != '}') ERROR(45); if(!cflg) /* one number */ *ep++ = i; else if((ep[-1] & 0377) < (ep[-2] & 0377)) ERROR(46); continue; case '\n': ERROR(36); case 'n': c = '\n'; goto defchar; default: if(c >= '1' && c <= '9') { if((c -= '1') >= closed) ERROR(25); *ep++ = CBACK; *ep++ = c; continue; } } /* Drop through to default to use \ to turn off special chars */ defchar: default: lastep = ep; *ep++ = CCHR; *ep++ = c; } } } step(p1, p2) register char *p1, *p2; { register c; if (circf) { loc1 = p1; return(advance(p1, p2)); } /* fast check for first character */ if (*p2==CCHR) { c = p2[1]; do { if (*p1 != c) continue; if (advance(p1, p2)) { loc1 = p1; return(1); } } while (*p1++); return(0); } /* regular algorithm */ do { if (advance(p1, p2)) { loc1 = p1; return(1); } } while (*p1++); return(0); } advance(lp, ep) register char *lp, *ep; { register char *curlp; char c; char *bbeg; int ct; for (;;) switch (*ep++) { case CCHR: if (*ep++ == *lp++) continue; return(0); case CDOT: if (*lp++) continue; return(0); case CDOL: if (*lp==0) continue; return(0); case CEOF: loc2 = lp; return(1); case CCL: c = *lp++ & 0177; if(ISTHERE(c)) { ep += 16; continue; } return(0); case CBRA: braslist[*ep++] = lp; continue; case CKET: braelist[*ep++] = lp; continue; case CCHR|RNGE: c = *ep++; getrnge(ep); while(low--) if(*lp++ != c) return(0); curlp = lp; while(size--) if(*lp++ != c) break; if(size < 0) lp++; ep += 2; goto star; case CDOT|RNGE: getrnge(ep); while(low--) if(*lp++ == '\0') return(0); curlp = lp; while(size--) if(*lp++ == '\0') break; if(size < 0) lp++; ep += 2; goto star; case CCL|RNGE: getrnge(ep + 16); while(low--) { c = *lp++ & 0177; if(!ISTHERE(c)) return(0); } curlp = lp; while(size--) { c = *lp++ & 0177; if(!ISTHERE(c)) break; } if(size < 0) lp++; ep += 18; /* 16 + 2 */ goto star; case CBACK: bbeg = braslist[*ep]; ct = braelist[*ep++] - bbeg; if(ecmp(bbeg, lp, ct)) { lp += ct; continue; } return(0); case CBACK|STAR: bbeg = braslist[*ep]; ct = braelist[*ep++] - bbeg; curlp = lp; while(ecmp(bbeg, lp, ct)) lp += ct; while(lp >= curlp) { if(advance(lp, ep)) return(1); lp -= ct; } return(0); case CDOT|STAR: curlp = lp; while (*lp++); goto star; case CCHR|STAR: curlp = lp; while (*lp++ == *ep); ep++; goto star; case CCL|STAR: curlp = lp; do { c = *lp++ & 0177; } while(ISTHERE(c)); ep += 16; goto star; star: do { if(--lp == locs) break; if (advance(lp, ep)) return(1); } while (lp > curlp); return(0); } } getrnge(str) register char *str; { low = *str++ & 0377; size = *str == 255 ? 20000 : (*str &0377) - low; } ecmp(a, b, count) register char *a, *b; register count; { if(a == b) /* should have been caught in compile() */ error(51); while(count--) if(*a++ != *b++) return(0); return(1); } static char *sccsid = "@(#)expr.y 4.4 (Berkeley) 5/21/84"; yyerror(s) { fprintf(stderr, "%s\n", s); exit(2); } efine SBUFSIZE 1024 static char str_buf[SBUFSIZE]; static int str_mode = S_EMPTY; static char *str_ptr; static long str_addr; static long str_label; st_put(cc, d) char *cc; struct dfmt *d; { register int c; if (cc == 0) { pr_sbuf(d, YES); return(1); } c = (*cc & 0377); if (str_mode & S_FILL) { if (isascii(c)) put_sbuf(cbin/rcp.c 644 0 12 43504 4500770015 5554 /* * Copyright (c) 1983 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)rcp.c 5.20 (Berkeley) 5/23/89"; #endif /* not lint */ /* * rcp */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" #ifdef KERBEROS #include char krb_realm[REALM_SZ]; int use_kerberos = 1, encrypt = 0; CREDENTIALS cred; Key_schedule schedule; #endif extern int errno; extern char *sys_errlist[]; struct passwd *pwd; int errs, pflag, port, rem, userid; int iamremote, iamrecursive, targetshouldbedirectory; #define CMDNEEDS 20 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ typedef struct _buf { int cnt; char *buf; } BUF; main(argc, argv) int argc; char **argv; { extern int optind; struct servent *sp; int ch, fflag, tflag; char *targ, *colon(); struct passwd *getpwuid(); int lostconn(); #ifdef KERBEROS sp = getservbyname("kshell", "tcp"); if (sp == NULL) { use_kerberos = 0; old_warning("kshell service unknown"); sp = getservbyname("kshell", "tcp"); } #else sp = getservbyname("shell", "tcp"); #endif if (!sp) { (void)fprintf(stderr, "rcp: shell/tcp: unknown service\n"); exit(1); } port = sp->s_port; if (!(pwd = getpwuid(userid = getuid()))) { (void)fprintf(stderr, "rcp: unknown user %d.\n", userid); exit(1); } fflag = tflag = 0; while ((ch = getopt(argc, argv, "dfkprtx")) != EOF) switch(ch) { case 'd': targetshouldbedirectory = 1; break; case 'f': /* "from" */ fflag = 1; break; #ifdef KERBEROS case 'k': strncpy(krb_realm, ++argv, REALM_SZ); break; #endif case 'p': /* preserve access/mod times */ ++pflag; break; case 'r': ++iamrecursive; break; case 't': /* "to" */ tflag = 1; break; #ifdef KERBEROS case 'x': encrypt = 1; des_set_key(cred.session, schedule); break; #endif case '?': default: usage(); } argc -= optind; argv += optind; if (fflag) { iamremote = 1; (void)response(); (void)setuid(userid); source(argc, argv); exit(errs); } if (tflag) { iamremote = 1; (void)setuid(userid); sink(argc, argv); exit(errs); } if (argc < 2) usage(); if (argc > 2) targetshouldbedirectory = 1; rem = -1; (void)sprintf(cmd, "rcp%s%s%s", iamrecursive ? " -r" : "", pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); (void)signal(SIGPIPE, lostconn); if (targ = colon(argv[argc - 1])) toremote(targ, argc, argv); else { tolocal(argc, argv); if (targetshouldbedirectory) verifydir(argv[argc - 1]); } exit(errs); } toremote(targ, argc, argv) char *targ; int argc; char **argv; { int i; char *bp, *host, *src, *suser, *thost, *tuser; char *colon(), *malloc(); *targ++ = 0; if (*targ == 0) targ = "."; if (thost = index(argv[argc - 1], '@')) { *thost++ = 0; tuser = argv[argc - 1]; if (*tuser == '\0') tuser = NULL; else if (!okname(tuser)) exit(1); } else { thost = argv[argc - 1]; tuser = NULL; } for (i = 0; i < argc - 1; i++) { src = colon(argv[i]); if (src) { /* remote to remote */ *src++ = 0; if (*src == 0) src = "."; host = index(argv[i], '@'); if (!(bp = malloc((u_int)(strlen(_PATH_RSH) + strlen(argv[i]) + strlen(src) + strlen(tuser) + strlen(thost) + strlen(targ)) + CMDNEEDS + 20))) nospace(); if (host) { *host++ = 0; suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; else if (!okname(suser)) continue; (void)sprintf(bp, "%s %s -l %s -n %s %s '%s%s%s:%s'", _PATH_RSH, host, suser, cmd, src, tuser ? tuser : "", tuser ? "@" : "", thost, targ); } else (void)sprintf(bp, "%s %s -n %s %s '%s%s%s:%s'", _PATH_RSH, argv[i], cmd, src, tuser ? tuser : "", tuser ? "@" : "", thost, targ); (void)susystem(bp); (void)free(bp); } else { /* local to remote */ if (rem == -1) { if (!(bp = malloc((u_int)strlen(targ) + CMDNEEDS + 20))) nospace(); (void)sprintf(bp, "%s -t %s", cmd, targ); host = thost; #ifdef KERBEROS if (use_kerberos) kerberos(bp, tuser ? tuser : pwd->pw_name); else #endif rem = rcmd(&host, port, pwd->pw_name, tuser ? tuser : pwd->pw_name, bp, 0); if (rem < 0) exit(1); if (response() < 0) exit(1); (void)free(bp); (void)setuid(userid); } source(1, argv+i); } } } tolocal(argc, argv) int argc; char **argv; { int i; char *bp, *host, *src, *suser; char *colon(), *malloc(); for (i = 0; i < argc - 1; i++) { if (!(src = colon(argv[i]))) { /* local to local */ if (!(bp = malloc((u_int)(strlen(_PATH_CP) + strlen(argv[i]) + strlen(argv[argc - 1])) + 20))) nospace(); (void)sprintf(bp, "%s%s%s %s %s", _PATH_CP, iamrecursive ? " -r" : "", pflag ? " -p" : "", argv[i], argv[argc - 1]); (void)susystem(bp); (void)free(bp); continue; } *src++ = 0; if (*src == 0) src = "."; host = index(argv[i], '@'); if (host) { *host++ = 0; suser = argv[i]; if (*suser == '\0') suser = pwd->pw_name; else if (!okname(suser)) continue; } else { host = argv[i]; suser = pwd->pw_name; } if (!(bp = malloc((u_int)(strlen(src)) + CMDNEEDS + 20))) nospace(); (void)sprintf(bp, "%s -f %s", cmd, src); #ifdef KERBEROS if (use_kerberos) kerberos(bp, suser); else #endif rem = rcmd(&host, port, pwd->pw_name, suser, bp, 0); (void)free(bp); if (rem < 0) continue; (void)setreuid(0, userid); sink(1, argv + argc - 1); (void)setreuid(userid, 0); (void)close(rem); rem = -1; } } #ifdef KERBEROS kerberos(bp, user) char *bp, *user; { struct servent *sp; char *host; again: rem = KSUCCESS; if (krb_realm[0] == '\0') rem = krb_get_lrealm(krb_realm, 1); if (rem == KSUCCESS) { if (encrypt) rem = krcmd_mutual(&host, port, user, bp, 0, krb_realm, &cred, schedule); else rem = krcmd(&host, port, user, bp, 0, krb_realm); } else { (void)fprintf(stderr, "rcp: error getting local realm %s\n", krb_err_txt[rem]); exit(1); } if (rem < 0 && errno == ECONNREFUSED) { use_kerberos = 0; old_warning("remote host doesn't support Kerberos"); sp = getservbyname("shell", "tcp"); if (sp == NULL) { (void)fprintf(stderr, "rcp: unknown service shell/tcp\n"); exit(1); } port = sp->s_port; goto again; } } #endif /* KERBEROS */ verifydir(cp) char *cp; { struct stat stb; if (stat(cp, &stb) >= 0) { if ((stb.st_mode & S_IFMT) == S_IFDIR) return; errno = ENOTDIR; } error("rcp: %s: %s.\n", cp, sys_errlist[errno]); exit(1); } char * colon(cp) register char *cp; { for (; *cp; ++cp) { if (*cp == ':') return(cp); if (*cp == '/') return(0); } return(0); } okname(cp0) char *cp0; { register char *cp = cp0; register int c; do { c = *cp; if (c & 0200) goto bad; if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') goto bad; } while (*++cp); return(1); bad: (void)fprintf(stderr, "rcp: invalid user name %s\n", cp0); return(0); } susystem(s) char *s; { int status, pid, w; register int (*istat)(), (*qstat)(); if ((pid = vfork()) == 0) { (void)setuid(userid); execl(_PATH_BSHELL, "sh", "-c", s, (char *)0); _exit(127); } istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); while ((w = wait(&status)) != pid && w != -1) ; if (w == -1) status = -1; (void)signal(SIGINT, istat); (void)signal(SIGQUIT, qstat); return(status); } source(argc, argv) int argc; char **argv; { struct stat stb; static BUF buffer; BUF *bp; off_t i; int x, readerr, f, amt; char *last, *name, buf[BUFSIZ]; BUF *allocbuf(); for (x = 0; x < argc; x++) { name = argv[x]; if ((f = open(name, O_RDONLY, 0)) < 0) { error("rcp: %s: %s\n", name, sys_errlist[errno]); continue; } if (fstat(f, &stb) < 0) goto notreg; switch (stb.st_mode&S_IFMT) { case S_IFREG: break; case S_IFDIR: if (iamrecursive) { (void)close(f); rsource(name, &stb); continue; } /* FALLTHROUGH */ default: notreg: (void)close(f); error("rcp: %s: not a plain file\n", name); continue; } last = rindex(name, '/'); if (last == 0) last = name; else last++; if (pflag) { /* * Make it compatible with possible future * versions expecting microseconds. */ (void)sprintf(buf, "T%ld 0 %ld 0\n", stb.st_mtime, stb.st_atime); (void)write(rem, buf, strlen(buf)); if (response() < 0) { (void)close(f); continue; } } (void)sprintf(buf, "C%04o %ld %s\n", stb.st_mode&07777, stb.st_size, last); (void)write(rem, buf, strlen(buf)); if (response() < 0) { (void)close(f); continue; } if ((bp = allocbuf(&buffer, f, BUFSIZ)) == 0) { (void)close(f); continue; } readerr = 0; for (i = 0; i < stb.st_size; i += bp->cnt) { amt = bp->cnt; if (i + amt > stb.st_size) amt = stb.st_size - i; if (readerr == 0 && read(f, bp->buf, amt) != amt) readerr = errno; (void)write(rem, bp->buf, amt); } (void)close(f); if (readerr == 0) (void)write(rem, "", 1); else error("rcp: %s: %s\n", name, sys_errlist[readerr]); (void)response(); } } rsource(name, statp) char *name; struct stat *statp; { DIR *d; struct direct *dp; char *last, *vect[1], path[MAXPATHLEN]; if (!(d = opendir(name))) { error("rcp: %s: %s\n", name, sys_errlist[errno]); return; } last = rindex(name, '/'); if (last == 0) last = name; else last++; if (pflag) { (void)sprintf(path, "T%ld 0 %ld 0\n", statp->st_mtime, statp->st_atime); (void)write(rem, path, strlen(path)); if (response() < 0) { closedir(d); return; } } (void)sprintf(path, "D%04o %d %s\n", statp->st_mode&07777, 0, last); (void)write(rem, path, strlen(path)); if (response() < 0) { closedir(d); return; } while (dp = readdir(d)) { if (dp->d_ino == 0) continue; if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) continue; if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) { error("%s/%s: name too long.\n", name, dp->d_name); continue; } (void)sprintf(path, "%s/%s", name, dp->d_name); vect[0] = path; source(1, vect); } closedir(d); (void)write(rem, "E\n", 2); (void)response(); } response() { register char *cp; char ch, resp, rbuf[BUFSIZ]; if (read(rem, &resp, sizeof(resp)) != sizeof(resp)) lostconn(); cp = rbuf; switch(resp) { case 0: /* ok */ return(0); default: *cp++ = resp; /* FALLTHROUGH */ case 1: /* error, followed by err msg */ case 2: /* fatal error, "" */ do { if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) lostconn(); *cp++ = ch; } while (cp < &rbuf[BUFSIZ] && ch != '\n'); if (!iamremote) (void)write(2, rbuf, cp - rbuf); ++errs; if (resp == 1) return(-1); exit(1); } /*NOTREACHED*/ } lostconn() { if (!iamremote) (void)fprintf(stderr, "rcp: lost connection\n"); exit(1); } sink(argc, argv) int argc; char **argv; { register char *cp; static BUF buffer; struct stat stb; struct timeval tv[2]; BUF *bp, *allocbuf(); off_t i, j; char ch, *targ, *why; int amt, count, exists, first, mask, mode; int ofd, setimes, targisdir, wrerr, cursize = 0; off_t size; char *np, *vect[1], buf[BUFSIZ], *malloc(), *namebuf = NULL; #define atime tv[0] #define mtime tv[1] #define SCREWUP(str) { why = str; goto screwup; } setimes = targisdir = 0; mask = umask(0); if (!pflag) (void)umask(mask); if (argc != 1) { error("rcp: ambiguous target\n"); exit(1); } targ = *argv; if (targetshouldbedirectory) verifydir(targ); (void)write(rem, "", 1); if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR) targisdir = 1; for (first = 1;; first = 0) { cp = buf; if (read(rem, cp, 1) <= 0) { if (namebuf) free(namebuf); return; } if (*cp++ == '\n') SCREWUP("unexpected "); do { if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) SCREWUP("lost connection"); *cp++ = ch; } while (cp < &buf[BUFSIZ - 1] && ch != '\n'); *cp = 0; if (buf[0] == '\01' || buf[0] == '\02') { if (iamremote == 0) (void)write(2, buf + 1, strlen(buf + 1)); if (buf[0] == '\02') exit(1); errs++; continue; } if (buf[0] == 'E') { (void)write(rem, "", 1); if (namebuf) free(namebuf); return; } if (ch == '\n') *--cp = 0; #define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0'); cp = buf; if (*cp == 'T') { setimes++; cp++; getnum(mtime.tv_sec); if (*cp++ != ' ') SCREWUP("mtime.sec not delimited"); getnum(mtime.tv_usec); if (*cp++ != ' ') SCREWUP("mtime.usec not delimited"); getnum(atime.tv_sec); if (*cp++ != ' ') SCREWUP("atime.sec not delimited"); getnum(atime.tv_usec); if (*cp++ != '\0') SCREWUP("atime.usec not delimited"); (void)write(rem, "", 1); continue; } if (*cp != 'C' && *cp != 'D') { /* * Check for the case "rcp remote:foo\* local:bar". * In this case, the line "No match." can be returned * by the shell before the rcp command on the remote is * executed so the ^Aerror_message convention isn't * followed. */ if (first) { error("%s\n", cp); exit(1); } SCREWUP("expected control record"); } mode = 0; for (++cp; cp < buf + 5; cp++) { if (*cp < '0' || *cp > '7') SCREWUP("bad mode"); mode = (mode << 3) | (*cp - '0'); } if (*cp++ != ' ') SCREWUP("mode not delimited"); size = 0; while (isdigit(*cp)) size = size * 10 + (*cp++ - '0'); if (*cp++ != ' ') SCREWUP("size not delimited"); if (targisdir) { int need; need = strlen(targ) + strlen(cp) + 250; if (need > cursize) { if (namebuf) free(namebuf); if (!(namebuf = malloc((u_int)need))) error("out of memory\n"); cursize = need; } (void)sprintf(namebuf, "%s%s%s", targ, *targ ? "/" : "", cp); np = namebuf; } else np = targ; exists = stat(np, &stb) == 0; if (buf[0] == 'D') { if (exists) { if ((stb.st_mode&S_IFMT) != S_IFDIR) { errno = ENOTDIR; goto bad; } if (pflag) (void)chmod(np, mode); } else if (mkdir(np, mode) < 0) goto bad; vect[0] = np; sink(1, vect); if (setimes) { setimes = 0; if (utimes(np, tv) < 0) error("rcp: can't set times on %s: %s\n", np, sys_errlist[errno]); } continue; } if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { bad: error("rcp: %s: %s\n", np, sys_errlist[errno]); continue; } if (exists && pflag) (void)fchmod(ofd, mode); (void)write(rem, "", 1); if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == 0) { (void)close(ofd); continue; } cp = bp->buf; count = 0; wrerr = 0; for (i = 0; i < size; i += BUFSIZ) { amt = BUFSIZ; if (i + amt > size) amt = size - i; count += amt; do { j = read(rem, cp, amt); if (j <= 0) { error("rcp: %s\n", j ? sys_errlist[errno] : "dropped connection"); exit(1); } amt -= j; cp += j; } while (amt > 0); if (count == bp->cnt) { if (wrerr == 0 && write(ofd, bp->buf, count) != count) wrerr++; count = 0; cp = bp->buf; } } if (count != 0 && wrerr == 0 && write(ofd, bp->buf, count) != count) wrerr++; if (ftruncate(ofd, size)) error("rcp: can't truncate %s: %s\n", np, sys_errlist[errno]); (void)close(ofd); (void)response(); if (setimes) { setimes = 0; if (utimes(np, tv) < 0) error("rcp: can't set times on %s: %s\n", np, sys_errlist[errno]); } if (wrerr) error("rcp: %s: %s\n", np, sys_errlist[errno]); else (void)write(rem, "", 1); } screwup: error("rcp: protocol screwup: %s\n", why); exit(1); } BUF * allocbuf(bp, fd, blksize) BUF *bp; int fd, blksize; { struct stat stb; int size; char *malloc(); if (fstat(fd, &stb) < 0) { error("rcp: fstat: %s\n", sys_errlist[errno]); return(0); } size = roundup(stb.st_blksize, blksize); if (size == 0) size = blksize; if (bp->cnt < size) { if (bp->buf != 0) free(bp->buf); bp->buf = (char *)malloc((u_int)size); if (!bp->buf) { error("rcp: malloc: out of memory\n"); return(0); } } bp->cnt = size; return(bp); } /* VARARGS1 */ error(fmt, a1, a2, a3) char *fmt; int a1, a2, a3; { static FILE *fp; ++errs; if (!fp && !(fp = fdopen(rem, "w"))) return; (void)fprintf(fp, "%c", 0x01); (void)fprintf(fp, fmt, a1, a2, a3); (void)fflush(fp); if (!iamremote) (void)fprintf(stderr, fmt, a1, a2, a3); } nospace() { (void)fprintf(stderr, "rcp: out of memory.\n"); exit(1); } #ifdef KERBEROS old_warning(str) char *str; { (void)fprintf(stderr, "rcp: warning: %s, using standard rcp\n", str); } #endif usage() { #ifdef KERBEROS (void)fprintf(stderr, "%s\n\t%s\n", "usage: rcp [-k realm] [-px] f1 f2", "or: rcp [-k realm] [-rpx] f1 ... fn directory"); #else (void)fprintf(stderr, "usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn directory\n"); #endif exit(1); } GN); while ((w = wait(&status)) != pid && w != -1) ; if (w == -1) status = -1; (void)signal(SIGINT, istat); (void)signal(SIGQUIT, qstat); return(status); } source(argc, argv) inbin/test/ 755 0 12 0 6024536010 5466 bin/test/TEST.csh 755 0 12 4514 5731210771 7047 # @(#)TEST.csh 5.2 (Berkeley) 4/30/93 # TEST.csh,v 1.3 1994/09/24 02:59:11 davidg Exp #alias t '/usr/src/bin/test/obj/test \!*; echo $status' alias t '/bin/test \!*; echo $status' #alias t '/u1/robin/progs/test/test \!*; echo $status' echo 't -b /dev/ttyp2' t -b /dev/ttyp2 echo 't -b /dev/jb1a' t -b /dev/jb1a echo 't -c test.c' t -c test.c echo 't -c /dev/tty' t -c /dev/tty echo 't -d test.c' t -d test.c echo 't -d /etc' t -d /etc echo 't -e noexist' t -e noexist echo 't -e test.c' t -e test.c echo 't -f noexist' t -f noexist echo 't -f /dev/tty' t -f /dev/tty echo 't -f test.c' t -f test.c echo 't -g test.c' t -g test.c echo 't -g /bin/ps' t -g /bin/ps echo 't -n ""' t -n "" echo 't -n "hello"' t -n "hello" echo 't -p test.c' t -p test.c echo 't -r noexist' t -r noexist echo 't -r /etc/master.passwd' t -r /etc/master.passwd echo 't -r test.c' t -r test.c echo 't -s noexist' t -s noexist echo 't -s /dev/null' t -s /dev/null echo 't -s test.c' t -s test.c echo 't -t 20' t -t 20 echo 't -t 0' t -t 0 echo 't -u test.c' t -u test.c echo 't -u /bin/rcp' t -u /bin/rcp echo 't -w noexist' t -w noexist echo 't -w /etc/master.passwd' t -w /etc/master.passwd echo 't -w /dev/null' t -w /dev/null echo 't -x noexist' t -x noexist echo 't -x /bin/ps' t -x /bin/ps echo 't -x /etc/motd' t -x /etc/motd echo 't -z ""' t -z "" echo 't -z "foo"' t -z "foo" echo 't "foo"' t "foo" echo 't ""' t "" echo 't "hello" = "hello"' t "hello" = "hello" echo 't "hello" = "goodbye"' t "hello" = "goodbye" echo 't "hello" != "hello"' t "hello" != "hello" echo 't "hello" != "goodbye"' t "hello" != "goodbye" echo 't 200 -eq 200' t 200 -eq 200 echo 't 34 -eq 222' t 34 -eq 222 echo 't 200 -ne 200' t 200 -ne 200 echo 't 34 -ne 222' t 34 -ne 222 echo 't 200 -gt 200' t 200 -gt 200 echo 't 340 -gt 222' t 340 -gt 222 echo 't 200 -ge 200' t 200 -ge 200 echo 't 34 -ge 222' t 34 -ge 222 echo 't 200 -lt 200' t 200 -lt 200 echo 't 34 -lt 222' t 34 -lt 222 echo 't 200 -le 200' t 200 -le 200 echo 't 340 -le 222' t 340 -le 222 echo 't 700 -le 1000 -a -n "1" -a "20" = "20"' t 700 -le 1000 -a -n "1" -a "20" = "20" echo 't ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)' t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \) echo 't -5 -eq 5' t -5 -eq 5 echo 't foo -a ""' t foo -a "" echo 't "" -a foo' t "" -a foo echo 't "" -a ""' t "" -a "" echo 't "" -o ""' t "" -o "" stconn(); cp = rbuf; switch(resp) { case 0: /* ok */ return(0); default: *cp++ = resp; /* FALLTHROUGH */ case 1: /* error, followed by err msg */ case 2: /* fbin/test/operators.c 644 0 12 6442 5731210775 7756 /*- * Copyright (c) 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * operators.c,v 1.3 1994/09/24 02:59:12 davidg Exp */ #if defined(DOSCCS) & !defined(lint) static char sccsid[] = "@(#)operators.c 8.3 (Berkeley) 4/2/94"; #endif /* not lint */ /* * Operators used in the test command. */ #include #include "operators.h" char unary_op[][4] = { "!", "-b", "-c", "-d", "-e", "-f", "-g", "-h", "-k", "-n", "-p", "-r", "-s", "-t", "-u", "-w", "-x", "-z", "ZZZ" }; char binary_op[][4] = { "-o", "|", "-a", "&", "=", "!=", "-eq", "-ne", "-gt", "-lt", "-le", "-ge", "ZZZ" }; char andor_op[][4] = { "-o", "|", "-a", "&", "ZZZ" }; int op_priority[] = { 3, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, }; int op_argflag[] = { 0, OP_FILE, OP_FILE, OP_FILE, OP_FILE, OP_FILE, OP_FILE, OP_FILE, OP_FILE, OP_STRING, OP_FILE, OP_FILE, OP_FILE, OP_INT, OP_FILE, OP_FILE, OP_FILE, OP_STRING, 0, 0, 0, 0, OP_STRING, OP_STRING, OP_INT, OP_INT, OP_INT, OP_INT, OP_INT, OP_INT, }; >"); do { if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) SCREWUP("lost connection"); *cp++ = ch; } while (cp < &buf[BUFSIZ - 1] && ch != '\n'); *cp = 0; if (buf[0] == '\01' || buf[0] == '\02') { if (iabin/test/operators.h 644 0 12 5134 5731216507 7757 /*- * Copyright (c) 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)operators.h 8.3 (Berkeley) 4/2/94 * operators.h,v 1.3 1994/09/24 02:59:13 davidg Exp */ #define NOT 0 #define ISBLOCK 1 #define ISCHAR 2 #define ISDIR 3 #define ISEXIST 4 #define ISFILE 5 #define ISSETGID 6 #define ISSYMLINK 7 #define ISSTICKY 8 #define STRLEN 9 #define ISFIFO 10 #define ISREAD 11 #define ISSIZE 12 #define ISTTY 13 #define ISSETUID 14 #define ISWRITE 15 #define ISEXEC 16 #define NULSTR 17 #define FIRST_BINARY_OP 18 #define OR1 18 #define OR2 19 #define AND1 20 #define AND2 21 #define STREQ 22 #define STRNE 23 #define EQ 24 #define NE 25 #define GT 26 #define LT 27 #define LE 28 #define GE 29 #define OP_INT 1 /* arguments to operator are integer */ #define OP_STRING 2 /* arguments to operator are string */ #define OP_FILE 3 /* argument is a file name */ 2, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, }; int op_argflag[] = { 0, OP_FILE, OP_FILE, OP_FILE, OP_FILE, OP_FILE, OP_FILE, OP_FILE, OP_FILE, bin/test/test.c 644 0 12 31343 5731216420 6726 /*- * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kenneth Almquist. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * test.c,v 1.9 1994/11/05 20:48:06 ache Exp */ #if defined(DOSCCS) & !defined(lint) static char copyright[] = "@(#) Copyright (c) 1992, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if defined(DOSCCS) & !defined(lint) static char sccsid[] = "@(#)test.c 8.3.1 (2.11BSD) 1995/03/13"; #endif /* not lint */ #include #include #include #include #include #include #include #include "operators.h" #define STACKSIZE 12 #define NESTINCR 16 /* data types */ #define STRING 0 #define INTEGER 1 #define BOOLEAN 2 #define IS_BANG(s) (s[0] == '!' && s[1] == '\0') /* * This structure hold a value. The type keyword specifies the type of * the value, and the union u holds the value. The value of a boolean * is stored in u.num (1 = TRUE, 0 = FALSE). */ struct value { int type; union { char *string; long num; } u; }; struct operator { short op; /* Which operator. */ short pri; /* Priority of operator. */ }; struct filestat { char *name; /* Name of file. */ int rcode; /* Return code from stat. */ struct stat stat; /* Status info on file. */ }; extern char unary_op[][4]; extern char binary_op[][4]; extern char andor_op[][4]; extern int op_priority[]; extern int op_argflag[]; extern long atol(); main(argc, argv) int argc; char *argv[]; { struct operator opstack[STACKSIZE]; register struct operator *opsp; struct value valstack[STACKSIZE + 1]; register struct value *valsp; struct filestat fs; char c, **ap, *opname, *p; int binary, nest, op, pri, ret_val, skipping; if ((p = argv[0]) == NULL) errx(2, "test: argc is zero"); if (*p != '\0' && p[strlen(p) - 1] == '[') { if (strcmp(argv[--argc], "]")) errx(2, "missing ]"); argv[argc] = NULL; } ap = argv + 1; fs.name = NULL; /* * Test(1) implements an inherently ambiguous grammer. In order to * assure some degree of consistency, we special case the POSIX 1003.2 * requirements to assure correct evaluation for POSIX scripts. The * following special cases comply with POSIX P1003.2/D11.2 Section * 4.62.4. */ switch(argc - 1) { case 0: /* % test */ return (1); break; case 1: /* % test arg */ return (argv[1] == NULL || *argv[1] == '\0') ? 1 : 0; break; case 2: /* % test op arg */ opname = argv[1]; if (IS_BANG(opname)) return (*argv[2] == '\0') ? 0 : 1; else { ret_val = posix_unary_op(&argv[1]); if (ret_val >= 0) return (ret_val); } break; case 3: /* % test arg1 op arg2 */ if (IS_BANG(argv[1])) { ret_val = posix_unary_op(&argv[1]); if (ret_val >= 0) return (!ret_val); } else { ret_val = posix_binary_op(&argv[1]); if (ret_val >= 0) return (ret_val); } break; case 4: /* % test ! arg1 op arg2 */ if (IS_BANG(argv[1]) && lookup_op(argv[3], andor_op) < 0 ) { ret_val = posix_binary_op(&argv[2]); if (ret_val >= 0) return (!ret_val); } break; default: break; } /* * We use operator precedence parsing, evaluating the expression as * we parse it. Parentheses are handled by bumping up the priority * of operators using the variable "nest." We use the variable * "skipping" to turn off evaluation temporarily for the short * circuit boolean operators. (It is important do the short circuit * evaluation because under NFS a stat operation can take infinitely * long.) */ opsp = opstack + STACKSIZE; valsp = valstack; nest = skipping = 0; if (*ap == NULL) { valstack[0].type = BOOLEAN; valstack[0].u.num = 0; goto done; } for (;;) { opname = *ap++; if (opname == NULL) syntax(); if (opname[0] == '(' && opname[1] == '\0') { nest += NESTINCR; continue; } else if (*ap && (op = lookup_op(opname, unary_op)) >= 0) { if (opsp == &opstack[0]) overflow(); --opsp; opsp->op = op; opsp->pri = op_priority[op] + nest; continue; } else { valsp->type = STRING; valsp->u.string = opname; valsp++; } for (;;) { opname = *ap++; if (opname == NULL) { if (nest != 0) syntax(); pri = 0; break; } if (opname[0] != ')' || opname[1] != '\0') { if ((op = lookup_op(opname, binary_op)) < 0) syntax(); op += FIRST_BINARY_OP; pri = op_priority[op] + nest; break; } if ((nest -= NESTINCR) < 0) syntax(); } while (opsp < &opstack[STACKSIZE] && opsp->pri >= pri) { binary = opsp->op; for (;;) { valsp--; c = op_argflag[opsp->op]; if (c == OP_INT) { if (valsp->type == STRING) get_int(valsp->u.string, &valsp->u.num); valsp->type = INTEGER; } else if (c >= OP_STRING) { /* OP_STRING or OP_FILE */ if (valsp->type == INTEGER) { if ((p = (char *)malloc(32)) == NULL) err(2, NULL); #ifdef SHELL fmtstr(p, 32, "%d", valsp->u.num); #else (void)sprintf(p, "%d", valsp->u.num); #endif valsp->u.string = p; } else if (valsp->type == BOOLEAN) { if (valsp->u.num) valsp->u.string = "true"; else valsp->u.string = ""; } valsp->type = STRING; if (c == OP_FILE && (fs.name == NULL || strcmp(fs.name, valsp->u.string))) { fs.name = valsp->u.string; fs.rcode = stat(valsp->u.string, &fs.stat); } } if (binary < FIRST_BINARY_OP) break; binary = 0; } if (!skipping) expr_operator(opsp->op, valsp, &fs); else if (opsp->op == AND1 || opsp->op == OR1) skipping--; valsp++; /* push value */ opsp++; /* pop operator */ } if (opname == NULL) break; if (opsp == &opstack[0]) overflow(); if (op == AND1 || op == AND2) { op = AND1; if (skipping || expr_is_false(valsp - 1)) skipping++; } if (op == OR1 || op == OR2) { op = OR1; if (skipping || !expr_is_false(valsp - 1)) skipping++; } opsp--; opsp->op = op; opsp->pri = pri; } done: return (expr_is_false(&valstack[0])); } int expr_is_false(val) register struct value *val; { if (val->type == STRING) { if (val->u.string[0] == '\0') return (1); } else { /* INTEGER or BOOLEAN */ if (val->u.num == 0) return (1); } return (0); } /* * Execute an operator. Op is the operator. Sp is the stack pointer; * sp[0] refers to the first operand, sp[1] refers to the second operand * (if any), and the result is placed in sp[0]. The operands are converted * to the type expected by the operator before expr_operator is called. * Fs is a pointer to a structure which holds the value of the last call * to stat, to avoid repeated stat calls on the same file. */ void expr_operator(op, sp, fs) int op; register struct value *sp; struct filestat *fs; { register int i; switch (op) { case NOT: sp->u.num = expr_is_false(sp); sp->type = BOOLEAN; break; case ISEXIST: exist: if (fs == NULL || fs->rcode == -1) goto false; else goto true; case ISREAD: if (geteuid() == 0) goto exist; i = S_IROTH; goto permission; case ISWRITE: if (geteuid() != 0) i = S_IWOTH; else { i = S_IWOTH|S_IWGRP|S_IWUSR; goto filebit; } goto permission; case ISEXEC: if (geteuid() != 0) { i = S_IXOTH; permission: if (fs->stat.st_uid == geteuid()) i <<= 6; else { gid_t grlist[NGROUPS]; int ngroups, j; ngroups = getgroups(NGROUPS, grlist); for (j = 0; j < ngroups; j++) if (fs->stat.st_gid == grlist[j]) { i <<= 3; goto filebit; } } } else i = S_IXOTH|S_IXGRP|S_IXUSR; goto filebit; /* true if (stat.st_mode & i) != 0 */ case ISFILE: i = S_IFREG; goto filetype; case ISDIR: i = S_IFDIR; goto filetype; case ISCHAR: i = S_IFCHR; goto filetype; case ISBLOCK: i = S_IFBLK; goto filetype; case ISSYMLINK: i = S_IFLNK; (void)lstat(sp->u.string, &fs->stat); goto filetype; case ISFIFO: i = S_IFIFO; goto filetype; filetype: if ((fs->stat.st_mode & S_IFMT) == i && fs->rcode >= 0) true: sp->u.num = 1; else false: sp->u.num = 0; sp->type = BOOLEAN; break; case ISSETUID: i = S_ISUID; goto filebit; case ISSETGID: i = S_ISGID; goto filebit; case ISSTICKY: i = S_ISVTX; filebit: if (fs->stat.st_mode & i && fs->rcode >= 0) goto true; goto false; case ISSIZE: sp->u.num = fs->rcode >= 0 ? fs->stat.st_size : 0L; sp->type = INTEGER; break; case ISTTY: sp->u.num = isatty(sp->u.num); sp->type = BOOLEAN; break; case NULSTR: if (sp->u.string[0] == '\0') goto true; goto false; case STRLEN: sp->u.num = strlen(sp->u.string); sp->type = INTEGER; break; case OR1: case AND1: /* * These operators are mostly handled by the parser. If we * get here it means that both operands were evaluated, so * the value is the value of the second operand. */ *sp = *(sp + 1); break; case STREQ: case STRNE: i = 0; if (!strcmp(sp->u.string, (sp + 1)->u.string)) i++; if (op == STRNE) i = 1 - i; sp->u.num = i; sp->type = BOOLEAN; break; case EQ: if (sp->u.num == (sp + 1)->u.num) goto true; goto false; case NE: if (sp->u.num != (sp + 1)->u.num) goto true; goto false; case GT: if (sp->u.num > (sp + 1)->u.num) goto true; goto false; case LT: if (sp->u.num < (sp + 1)->u.num) goto true; goto false; case LE: if (sp->u.num <= (sp + 1)->u.num) goto true; goto false; case GE: if (sp->u.num >= (sp + 1)->u.num) goto true; goto false; } } int lookup_op(name, table) char *name; char *table; { char *tp; char c; int i; c = name[1]; tp = table; for(i = 0; strcmp((char *)(tp + i),"ZZZ") ; i=i+4){ if ((char)(tp + i)[1] == c && !strcmp((char *)(tp + i), name)) return (i/4); } return (-1); } int posix_unary_op(argv) char **argv; { struct filestat fs; struct value valp; int op, c; char *opname; opname = *argv; if ((op = lookup_op(opname, unary_op)) < 0) return (-1); c = op_argflag[op]; opname = argv[1]; valp.u.string = opname; if (c == OP_FILE) { fs.name = opname; fs.rcode = stat(opname, &fs.stat); } else if (c != OP_STRING) return (-1); expr_operator(op, &valp, &fs); return (valp.u.num == 0); } int posix_binary_op(argv) char **argv; { struct value v[2]; int op, c; char *opname; opname = argv[1]; if ((op = lookup_op(opname, binary_op)) < 0) return (-1); op += FIRST_BINARY_OP; c = op_argflag[op]; if (c == OP_INT) { get_int(argv[0], &v[0].u.num); get_int(argv[2], &v[1].u.num); } else { v[0].u.string = argv[0]; v[1].u.string = argv[2]; } expr_operator(op, v, NULL); return (v[0].u.num == 0); } /* * Integer type checking. */ void get_int(v, lp) register char *v; long *lp; { for (; *v && isspace(*v); ++v); if(!*v) { *lp = 0; return; } if (isdigit(*v) || ((*v == '-' || *v == '+') && isdigit(*(v+1)))) { *lp = atol(v); return; } errx(2, "%s: expected integer", v); } void syntax() { err(2, "syntax error"); } void overflow() { err(2, "expression is too complex"); } red in u.num (1 = TRUE, 0 = FALSE). */ struct value { int type; union { char *string; long num; } u; }; struct operator { short op; /* Which operator. */ short pri; /* Priority of operator. */ }; struct filestat { char *name; /* Name of file. */ int rcode; /* Return bin/test/test.1 644 0 12 14150 5731216626 6651 .\" Copyright (c) 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" the Institute of Electrical and Electronics Engineers, Inc. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)test.1 8.1.2 (2.11BSD) 1995/03/13 .\" test.1,v 1.2 1994/09/24 02:59:14 davidg Exp .\" .TH TEST 1 "March 13, 1995" .AT 3 .SH NAME test \- condition evaluation utility .SH SYNOPSIS .B test .I expression .SH DESCRIPTION The .I test utility evaluates the expression and, if it evaluates to true, returns a zero (true) exit status; otherwise it returns 1 (false). If there is no expression, test also returns 1 (false). .PP All operators and flags are separate arguments to the .I test utility. .PP The following primaries are used to construct expression: .TP \fB \-b \fP \fI file \fP True if .I file exists and is a block special file. .TP \fB \-c \fP \fI file \fP True if .I file exists and is a character special file. .TP \fB \-d \fP \fI file \fP True if .I file exists and is a directory. .TP \fB \-e \fP \fI file \fP True if .I file exists (regardless of type). .TP \fB \-f \fP \fI file \fP True if .I file exists and is a regular file. .TP \fB \-g \fP \fI file \fP True if .I file exists and its set group ID flag is set. .TP \fB \-h \fP \fI file \fP True if .I file exists and is a symbolic link. .TP \fB \-n \fP \fI string \fP True if the length of .I string is nonzero. .TP \fB \-p \fP \fI file \fP True if .I file is a named pipe .Po Tn FIFO Pc . .TP \fB \-r \fP \fI file \fP True if .I file exists and is readable. .TP \fB \-s \fP \fI file \fP True if .I file exists and has a size greater than zero. .TP \fB \-t \fp \fI [file_descriptor] \fP True if the file whose file descriptor number is .I file_descriptor (default 1) is open and is associated with a terminal. .TP \fB \-u \fP \fI file \fP True if .I file exists and its set user ID flag is set. .TP \fB \-w \fP \fI file \fP True if .I file exists and is writable. True indicates only that the write flag is on. The file is not writable on a read-only file system even if this test indicates true. .TP \fB \-x \fP \fI file \fP True if .I file exists and is executable. True indicates only that the execute flag is on. If .I file is a directory, true indicates that .I file can be searched. .TP \fB \-z \fP \fI string \fP True if the length of .I string is zero. .TP \fI string \fP True if .I string is not the null string. .TP \fI s1 \fP \fB = \fP \fI s2 \fP True if the strings .I s1 and .I s2 are identical. .TP \fI s1 \fP \fB != \fP \fI s2 \fP True if the strings .I s1 and .I s2 are not identical. .TP \fI n1 \fP \fB \-eq \fP \fI n2 \fP True if the integers .I n1 and .I n2 are algebraically equal. .TP \fI n1 \fP \fB \-ne \fP \fI n2 \fP True if the integers .I n1 and .I n2 are not algebraically equal. .TP \fI n1 \fP \fB \-gt \fP \fI n2 \fP True if the integer .I n1 is algebraically greater than the integer .I n2 . .TP \fI n1 \fP \fB \-ge \fP \fI n2 \fP True if the integer .I n1 is algebraically greater than or equal to the integer .I n2 . .TP \fI n1 \fP \fB \-lt \fP \fI n2 \fP True if the integer .I n1 is algebraically less than the integer .I n2 . .TP \fI n1 \fP \fB \-le \fP \fI n2 \fP True if the integer .I n1 is algebraically less than or equal to the integer .I n2 . .TP .PP These primaries can be combined with the following operators: .TP .B ! expression True if .I expression is false. .TP \fI expression1 \fP \fB \-a \fP \fI expression2 \fP True if both .I expression1 and .I expression2 are true. .TP \fI expression1 \fP \fB \-o \fP \fI expression2 \fP True if either .I expression1 or .I expression2 are true. .TP \fI (expression) \fP True if expression is true. .TP .PP The .B \-a operator has higher precedence than the .B \-o operator. .SH GRAMMAR AMBIGUITY The .B test grammar is inherently ambiguous. In order to assure a degree of consistency, the cases described in the IEEE Std 1003.2 ("POSIX"), section D11.2/4.62.4, standard are evaluated consistently according to the rules specified in the standards document. All other cases are subject to the ambiguity in the command semantics. .SH RETURN VALUES The .B test utility exits with one of the following values: .TP .B 0 expression evaluated to true. .TP .B 1 expression evaluated to false or expression was missing. .TP .B >1 An error occurred. .SH BUGS Named pipes are not implemented in 2.11BSD. .SH STANDARDS The .B test function is expected to be IEEE Std 1003.2 ("POSIX") compatible. nest; break; } if ((nest -= NESTINCR) < 0) syntax(); } while (opsp < &opstack[STACKSIZE] && opsp->pri >= pri) { binary = opsp->op; for (;;) { valsp--; c = op_argflag[opsp->op]; if (c == OP_INT) { if (valsp->type == STRING) get_int(valsp->u.string, &valsp->u.num); valsp->type = INTEGER; } else if (c >= OP_STRING) { /* OP_Sbin/test/Makefile 644 0 12 756 5731232262 7211 # Makefile for test # # Robin Birch 11 march 1995 # # Version 1.1 # SEPFLAG= -i CFLAGS = -O SRCS = test.c operators.c OBJS = test.o operators.o all: test test.0 test: ${OBJS} ${CC} ${SEPFLAG} -o test ${OBJS} test.0: test.1 /usr/man/manroff test.1 > test.0 install: all install -s -m 755 -g bin -o bin test ${DESTDIR}/bin rm -f ${DESTDIR}/bin/[ ln ${DESTDIR}/bin/test ${DESTDIR}/bin/[ install -m 444 -g bin -o bin test.0 ${DESTDIR}/usr/man/cat1 clean: rm -f *.o test *.core test.0 bin/Makefile 644 0 12 6170 5766231350 6253 # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.19.7 (2.11BSD GTE) 1995/06/09 # DESTDIR= CFLAGS= -O SEPFLAG= -i # Programs that live in subdirectories, and have makefiles of their own. # SUBDIR= adb ar as awk chflags chpass csh diff disklabel hostname ld login \ ls make nm passwd sed sh sysctl test tp # Shell scripts that need only be installed and are never removed. # SCRIPT= false true # C programs that live in the current directory and do not need # explicit make lines. # STD= cat cc chgrp chmod cmp cp date dd du echo ed grep hostid \ kill ln mkdir mt mv nice od pagesize pr \ pwd rm rmail rmdir size stty sync tar tee time who # C programs that live in the current directory and need explicit make lines. # NSTD= expr # Programs that must run setuid to root # SETUID= mail rcp su # Programs that run set-group-id operator # OPERATOR= df # Programs that must run set-group-id kmem. # KMEM= ps # Programs that must run set-group-id tty. # TTY= wall write # 'strip' is handled specially because 'install -s' now uses 'strip' and # thus we can't do a 'install -s strip /bin/strip' without an error. # BINS= ${STD} ${NSTD} ${SETUID} ${OPERATOR} ${KMEM} ${TTY} strip all: ${SUBDIR} ${BINS} ${SUBDIR}: FRC cd $@; make ${MFLAGS} SEPFLAG=${SEPFLAG} FRC: ${STD} ${SETUID} ${KMEM} ${OPERATOR} ${TTY} strip: ${CC} ${CFLAGS} ${SEPFLAG} -o $@ $@.c install: ${BINS} install -s -m 751 -g staff ${STD} ${NSTD} ${DESTDIR}/bin -for i in ${SUBDIR}; do \ (cd $$i; make ${MFLAGS} DESTDIR=${DESTDIR} install); done -for i in ${SCRIPT}; do (install -c $$i.sh ${DESTDIR}/bin/$$i); done -for i in ${SETUID}; do \ (install -o root -m 4751 -s $$i ${DESTDIR}/bin/$$i); done -for i in ${OPERATOR}; do \ (install -g operator -m 2751 -s $$i ${DESTDIR}/bin/$$i); done -for i in ${KMEM}; do \ (install -g kmem -m 2751 -s $$i ${DESTDIR}/bin/$$i); done -for i in ${TTY}; do \ (install -g tty -m 2751 -s $$i ${DESTDIR}/bin/$$i); done -install -s -m 751 -g staff strip ${DESTDIR}/bin/xstrip -mv ${DESTDIR}/bin/xstrip ${DESTDIR}/bin/strip rm -f ${DESTDIR}/bin/e; ln ${DESTDIR}/bin/ed ${DESTDIR}/bin/e clean: rm -f ${BINS} expr.c a.out core *.s *.o errs for i in ${SUBDIR}; do (cd $$i; make ${MFLAGS} clean); done depend: expr.c for i in ${BINS}; do \ cc -M ${INCPATH} $$i.c | sed 's/\.o//' | \ awk ' { if ($$1 != prev) \ { if (rec != "") print rec; rec = $$0; prev = $$1; } \ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ else rec = rec " " $$2 } } \ END { print rec } ' >> makedep; done echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep echo '$$r makedep' >>eddep echo 'w' >>eddep cp Makefile Makefile.bak ed - Makefile < eddep rm eddep makedep echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile echo '# see make depend above' >> Makefile # Files listed in ${NSTD} have explicit make lines given below. expr: expr.o ${CC} ${CFLAGS} ${SEPFLAG} -o expr expr.o # DO NOT DELETE THIS LINE -- make depend uses it \fP \fI file \fP True if .I file is a named pipe .Po Tn FIFO Pc . .TP \fB \-r \fP \fI file \fP True if .I file exists and is readable. .TP \fB \-s \fP \fI file \fP True if .I file exists and has a size greater than zero. .TP \fB \-t \fp \fI [file_descriptor] \fP True if the file whose file descriptor number is .I file_descriptor (default 1) is open and is associated with a terminal. .TP \bin/mkdir.c 644 0 12 6331 5433575251 6066 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)mkdir.c 5.7 (Berkeley) 5/31/90"; #endif /* not lint */ #include #include #include #include #include extern int errno; main(argc, argv) int argc; char **argv; { extern int optind; int ch, exitval, pflag; pflag = 0; while ((ch = getopt(argc, argv, "p")) != EOF) switch(ch) { case 'p': pflag = 1; break; case '?': default: usage(); } if (!*(argv += optind)) usage(); for (exitval = 0; *argv; ++argv) if (pflag) exitval |= build(*argv); else if (mkdir(*argv, 0777) < 0) { (void)fprintf(stderr, "mkdir: %s: %s\n", *argv, strerror(errno)); exitval = 1; } exit(exitval); } build(path) char *path; { register char *p; struct stat sb; int create, ch; for (create = 0, p = path;; ++p) if (!*p || *p == '/') { ch = *p; *p = '\0'; if (stat(path, &sb)) { if (errno != ENOENT || mkdir(path, 0777) < 0) { (void)fprintf(stderr, "mkdir: %s: %s\n", path, strerror(errno)); return(1); } create = 1; } if (!(*p = ch)) break; } if (!create) { (void)fprintf(stderr, "mkdir: %s: %s\n", path, strerror(EEXIST)); return(1); } return(0); } usage() { (void)fprintf(stderr, "usage: mkdir [-p] dirname ...\n"); exit(1); } ue if .I file exists and is readable. .TP \fB \-s \fP \fI file \fP True if .I file exists and has a size greater than zero. .TP \fB \-t \fp \fI [file_descriptor] \fP True if the file whose file descriptor number is .I file_descriptor (default 1) is open and is associated with a terminal. .TP \bin/mt.c 644 0 12 10470 5416435450 5414 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * Modified to handle pdp11 930707 /BQT */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)mt.c 2.0 (2.11BSD) 7/6/93"; #endif not lint /* * mt -- * magnetic tape manipulation program */ #include #include #include #include #include #define equal(s1,s2) (strcmp(s1, s2) == 0) struct commands { char *c_name; int c_code; int c_ronly; } com[] = { { "weof", MTWEOF, 0 }, { "eof", MTWEOF, 0 }, { "fsf", MTFSF, 1 }, { "bsf", MTBSF, 1 }, { "fsr", MTFSR, 1 }, { "bsr", MTBSR, 1 }, { "rewind", MTREW, 1 }, { "offline", MTOFFL, 1 }, { "rewoffl", MTOFFL, 1 }, { "status", MTNOP, 1 }, { 0 } }; int mtfd; struct mtop mt_com; struct mtget mt_status; char *tape; main(argc, argv) char **argv; { char line[80], *getenv(); register char *cp; register struct commands *comp; if (argc > 2 && (equal(argv[1], "-t") || equal(argv[1], "-f"))) { argc -= 2; tape = argv[2]; argv += 2; } else if ((tape = getenv("TAPE")) == NULL) tape = MT_DEF; if (argc < 2) { fprintf(stderr, "usage: mt [ -f device ] command [ count ]\n"); exit(1); } cp = argv[1]; for (comp = com; comp->c_name != NULL; comp++) if (strncmp(cp, comp->c_name, strlen(cp)) == 0) break; if (comp->c_name == NULL) { fprintf(stderr, "mt: don't grok \"%s\"\n", cp); exit(1); } if ((mtfd = open(tape, comp->c_ronly ? 0 : 2)) < 0) { perror(tape); exit(1); } if (comp->c_code != MTNOP) { mt_com.mt_op = comp->c_code; mt_com.mt_count = (argc > 2 ? atoi(argv[2]) : 1); if (mt_com.mt_count < 0) { fprintf(stderr, "mt: negative repeat count\n"); exit(1); } if (ioctl(mtfd, MTIOCTOP, &mt_com) < 0) { fprintf(stderr, "%s %s %d ", tape, comp->c_name, mt_com.mt_count); perror("failed"); exit(2); } } else { if (ioctl(mtfd, MTIOCGET, (char *)&mt_status) < 0) { perror("mt"); exit(2); } status(&mt_status); } } #ifdef vax #include #include #include #include #undef b_repcnt /* argh */ #include #endif #ifdef sun #include #include #endif #ifdef pdp11 #include #include #undef b_repcnt /* argh */ #include #define NRSP 0 #define NCMD 0 #include #endif struct tape_desc { short t_type; /* type of magtape device */ char *t_name; /* printing name */ char *t_dsbits; /* "drive status" register */ char *t_erbits; /* "error" register */ } tapes[] = { #ifdef vax { MT_ISTS, "ts11", 0, TSXS0_BITS }, { MT_ISHT, "tm03", HTDS_BITS, HTER_BITS }, { MT_ISTM, "tm11", 0, TMER_BITS }, { MT_ISMT, "tu78", MTDS_BITS, 0 }, { MT_ISUT, "tu45", UTDS_BITS, UTER_BITS }, #endif #ifdef sun { MT_ISCPC, "TapeMaster", TMS_BITS, 0 }, { MT_ISAR, "Archive", ARCH_CTRL_BITS, ARCH_BITS }, #endif #ifdef pdp11 { MT_ISTS, "ts11", 0, TSXS0_BITS }, { MT_ISHT, "tm03", HTFS_BITS, HTER_BITS }, { MT_ISTM, "tm11", 0, TMER_BITS }, { MT_ISTMSCP, "tmscp", 0, 0 }, #endif { 0 } }; /* * Interpret the status buffer returned */ status(bp) register struct mtget *bp; { register struct tape_desc *mt; for (mt = tapes; mt->t_type; mt++) if (mt->t_type == bp->mt_type) break; if (mt->t_type == 0) { printf("unknown tape drive type (%d)\n", bp->mt_type); return; } printf("%s tape drive, residual=%d\n", mt->t_name, bp->mt_resid); printreg("ds", bp->mt_dsreg, mt->t_dsbits); printreg("\ner", bp->mt_erreg, mt->t_erbits); putchar('\n'); } /* * Print a register a la the %b format of the kernel's printf */ printreg(s, v, bits) char *s; register char *bits; register unsigned short v; { register int i, any = 0; register char c; if (bits && *bits == 8) printf("%s=%o", s, v); else printf("%s=%x", s, v); bits++; if (v && bits) { putchar('<'); while (i = *bits++) { if (v & (1 << (i-1))) { if (any) putchar(','); any = 1; for (; (c = *bits) > 32; bits++) putchar(c); } else for (; *bits > 32; bits++) ; } putchar('>'); } } rue if .I file exists and is executable. True indicates only that the execute flag is on. If .I file is a directory, true indicates that .I file can be searched. .TP \fB \-z \fP \fI string \fP True ibin/nice.c 444 0 12 1621 4013202670 5652 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)nice.c 5.2 (Berkeley) 1/12/86"; #endif not lint #include #include #include main(argc, argv) int argc; char *argv[]; { int nicarg = 10; if (argc > 1 && argv[1][0] == '-') { nicarg = atoi(&argv[1][1]); argc--, argv++; } if (argc < 2) { fputs("usage: nice [ -n ] command\n", stderr); exit(1); } if (setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS, 0) + nicarg) < 0) { perror("setpriority"); exit(1); } execvp(argv[1], &argv[1]); perror(argv[1]); exit(1); } ]\n"); exit(1); } cp = argv[1]; for (comp = com; comp->c_name != NULL; comp++) if (strncmp(cp, comp->c_nbin/pagesize.c 444 0 12 734 4013202670 6527 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)pagesize.c 5.1 (Berkeley) 4/30/85"; #endif not lint main() { printf("%d\n", getpagesize()); } rmail.ccu$chflagscbin/pwd.c 444 0 12 1273 4013202670 5531 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)pwd.c 5.1 (Berkeley) 4/30/85"; #endif not lint /* * Print working (current) directory */ #include #include char *getwd(); main() { char pathname[MAXPATHLEN + 1]; if (getwd(pathname) == NULL) { fprintf(stderr, "pwd: %s\n", pathname); exit(1); } printf("%s\n", pathname); exit(0); } and\n", stderr); exit(1); } if (setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS, 0) + nicarg) < 0) { perror("setpriority"); exit(1); } execvp(argv[1], &argv[1]); perror(argv[1]); exit(1); } ]\n"); exit(1); } cp = argv[1]; for (comp = com; comp->c_name != NULL; comp++) if (strncmp(cp, comp->c_nbin/rmdir.c 444 0 12 1366 4013202670 6057 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)rmdir.c 5.1 (Berkeley) 4/30/85"; #endif not lint /* * Remove directory */ #include main(argc,argv) int argc; char **argv; { int errors = 0; if (argc < 2) { fprintf(stderr, "usage: %s directory ...\n", argv[0]); exit(1); } while (--argc) if (rmdir(*++argv) < 0) { fprintf(stderr, "rmdir: "); perror(*argv);; errors++; } exit(errors != 0); } S, 0, getpriority(PRIO_PROCESS, 0) + nicarg) < 0) { perror("setpriority"); exit(1); } execvp(argv[1], &argv[1]); perror(argv[1]); exit(1); } ]\n"); exit(1); } cp = argv[1]; for (comp = com; comp->c_name != NULL; comp++) if (strncmp(cp, comp->c_nbin/who.c 444 0 12 3530 5514435715 5551 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)who.c 5.1.1 (2.11BSD GTE) 12/31/93"; #endif /* * who */ #include #include #include #include #define NMAX sizeof(utmp.ut_name) #define LMAX sizeof(utmp.ut_line) #define HMAX sizeof(utmp.ut_host) struct utmp utmp; struct passwd *pw; struct passwd *getpwuid(); char hostname[32]; char *ttyname(), *rindex(), *ctime(), *strcpy(); main(argc, argv) int argc; char **argv; { register char *tp, *s; register FILE *fi; extern char _sobuf[]; setbuf(stdout, _sobuf); s = "/etc/utmp"; if(argc == 2) s = argv[1]; if (argc == 3) { tp = ttyname(0); if (tp) tp = rindex(tp, '/') + 1; else { /* no tty - use best guess from passwd file */ pw = getpwuid(getuid()); strncpy(utmp.ut_name, pw ? pw->pw_name : "?", NMAX); strcpy(utmp.ut_line, "tty??"); time(&utmp.ut_time); putline(); exit(0); } } if ((fi = fopen(s, "r")) == NULL) { puts("who: cannot open utmp"); exit(1); } while (fread((char *)&utmp, sizeof(utmp), 1, fi) == 1) { if (argc == 3) { gethostname(hostname, sizeof (hostname)); if (strcmp(utmp.ut_line, tp)) continue; printf("%s!", hostname); putline(); exit(0); } if (utmp.ut_name[0] == '\0' && argc == 1) continue; putline(); } } putline() { register char *cbuf; printf("%-*.*s %-*.*s", NMAX, NMAX, utmp.ut_name, LMAX, LMAX, utmp.ut_line); cbuf = ctime(&utmp.ut_time); printf("%.12s", cbuf+4); if (utmp.ut_host[0]) printf("\t(%.*s)", HMAX, utmp.ut_host); putchar('\n'); } axuba/tsreg.h> #endif #ifdef sun #include #include #endif #ifdef pdp11 #include #include #undef b_bin/chpass/ 755 0 12 0 6024535751 6003 bin/chpass/Makefile 644 0 12 3440 5326557237 7540 # # Copyright (c) 1988 The Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that the above copyright notice and this paragraph are # duplicated in all such forms and that any documentation, # advertising materials, and other materials related to such # distribution and use acknowledge that the software was developed # by the University of California, Berkeley. The name of the # University may not be used to endorse or promote products derived # from this software without specific prior written permission. # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # @(#)Makefile 5.1 (Berkeley) 2/22/89 # CFLAGS= -I. -O SEPFLAG= -i LIBC= /lib/libc.a SRCS= chpass.c field.c util.c OBJS= chpass.o field.o util.o MAN= chpass.0 MANSRC= chpass.1 all: chpass chpass: ${LIBC} ${OBJS} ${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS} chpass.0: ${MANSRC} /usr/man/manroff ${MANSRC} > ${MAN} clean: rm -f ${OBJS} ${MAN} core chpass cleandir: clean rm -f tags .depend depend: ${SRCS} mkdep ${CFLAGS} ${SRCS} install: ${MAN} chpass install -s -o root -g bin -m 4755 chpass ${DESTDIR}/bin/chpass rm -f ${DESTDIR}/bin/chfn; ln ${DESTDIR}/bin/chpass ${DESTDIR}/bin/chfn rm -f ${DESTDIR}/bin/chsh; ln ${DESTDIR}/bin/chpass ${DESTDIR}/bin/chsh install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat1 rm -f ${DESTDIR}/usr/man/cat1/chfn.0 rm -f ${DESTDIR}/usr/man/cat1/chsh.0 -ln ${DESTDIR}/usr/man/cat1/chpass.0 ${DESTDIR}/usr/man/cat1/chfn.0 -ln ${DESTDIR}/usr/man/cat1/chpass.0 ${DESTDIR}/usr/man/cat1/chsh.0 lint: ${SRCS} lint ${CFLAGS} ${SRCS} tags: ${SRCS} ctags ${SRCS} intf("\t(%.*s)", HMAX, utmp.ut_host); putchar('\n'); } axuba/tsreg.h> #endif #ifdef sun #include #include #endif #ifdef pdp11 #include #include #undef b_bin/chpass/chpass.1 644 0 12 11400 4433455561 7451 .\" Copyright (c) 1988 The Regents of the University of California. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms are permitted .\" provided that the above copyright notice and this paragraph are .\" duplicated in all such forms and that any documentation, .\" advertising materials, and other materials related to such .\" distribution and use acknowledge that the software was developed .\" by the University of California, Berkeley. The name of the .\" University may not be used to endorse or promote products derived .\" from this software without specific prior written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .\" @(#)chpass.1 5.6 (Berkeley) 3/12/89 .\" .TH CHPASS 1 "March 12, 1989" .UC 4 .SH NAME chpass \- add or change user database information .SH SYNOPSIS chpass [ -a list ] [ user ] .SH DESCRIPTION .I Chpass allows editing of the user database information associated with .I user or, by default, the current user. The information is formatted and supplied to an editor for changes. The .I vi editor will be used unless the environmental variable EDITOR selects an alternate editor. When the editor terminates, the information is re-read and used to update the user database itself. Only the user, or the super-user, may edit the information associated with the user. .PP Only the information that the user is allowed to change is displayed. .PP Possible display items are as follows: .PP .RS Login: user's login name Password: user's encrypted password Uid: user's id Gid: user's login group id Change: password change time Expire: account expiration time Class: user's general classification Home Directory: user's home directory Shell: user's login shell Full Name: user's real name Location: user's normal location Home Phone: user's home phone Office Phone: user's office phone .RE .PP .PP The .I login field is the user name used to access the computer account. .PP The .I password field contains the encrypted form of the user's password. .PP The .I uid field is the number associated with the .I login field. Both of these fields should be unique across the system (and often across a group of systems) as they control file access. .PP While it is possible to have multiple entries with identical login names and/or identical user id's, it is usually a mistake to do so. Routines that manipulate these files will often return only one of the multiple entries, and that one by random selection. .PP The .I group field is the group that the user will be placed in upon login. Since this system supports multiple groups (see .IR groups (1)) this field currently has little special meaning. This field may be filled in with either a number or a group name (see .IR group (5)). .PP The .I change field is the date by which the password must be changed. .PP The .I expire field is the date on which the account expires. .PP Both the .I change and .I expire fields should be entered in the form ``month day year'' where .I month is the month name (the first three characters are sufficient), .I day is the day of the month, and .I year is the year. .PP The .I class field is currently unused. In the near future it will be a key to a .IR termcap (5) style database of user attributes. .PP The user's home directory is the full UNIX path name where the user will be placed on login. .PP The shell field is the command interpreter the user prefers. If the .I shell field is empty, the Bourne shell (\fI/bin/sh\fP) is assumed. .PP When altering a login shell, and not the super-user, the user must select an approved shell from the list in .IR /etc/shells . .PP The last four fields are for storing the user's full name, office location, and home and work telephone numbers. .PP The super-user is also allowed to directly supply a user database entry, in the format specified by .IR passwd (5), as an argument to the .I -a option. This argument must be a colon (``:'') separated list of all the user database fields, although they may be empty. .PP Once the information has been verified, .I chpass uses .IR mkpasswd (8) to update the user database. This is run in the background, and, at very large sites could take several minutes. Until this update is completed, the password file is unavailable for other updates and the new information will not be available to programs. .SH FILES .DT /etc/master.passwd The user database /etc/shells The list of approved shells .RE .SH "SEE ALSO" login(1), finger(1), getusershell(3), passwd(5), mkpasswd(8), vipw(8) .br Robert Morris and Ken Thompson, .I UNIX password security .SH BUGS User information should (and eventually will) be stored elsewhere. uch forms and that any documentation, .\" advertising materials, and other materials related to such .\" distribution and use acknowledge that the software was developed .\" by the University of California, Berkeley. The name of the .\" University may notbin/chpass/chpass.c 644 0 12 25362 4433455562 7550 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1988 The Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)chpass.c 5.10 (Berkeley) 3/26/89"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include char e1[] = ": "; char e2[] = ":,"; int p_change(), p_class(), p_expire(), p_gecos(), p_gid(), p_hdir(); int p_login(), p_passwd(), p_shell(), p_uid(); struct entry list[] = { { "Login", p_login, 1, 5, e1, }, { "Password", p_passwd, 1, 8, e1, }, { "Uid", p_uid, 1, 3, e1, }, { "Gid", p_gid, 1, 3, e1, }, { "Class", p_class, 1, 5, e1, }, { "Change", p_change, 1, 6, NULL, }, { "Expire", p_expire, 1, 6, NULL, }, #define E_NAME 7 { "Full Name", p_gecos, 0, 9, e2, }, #define E_BPHONE 8 { "Office Phone", p_gecos, 0, 12, e2, }, #define E_HPHONE 9 { "Home Phone", p_gecos, 0, 10, e2, }, #define E_LOCATE 10 { "Location", p_gecos, 0, 8, e2, }, { "Home directory", p_hdir, 1, 14, e1, }, { "Shell", p_shell, 0, 5, e1, }, { NULL, 0, }, }; uid_t uid; main(argc, argv) int argc; char **argv; { extern int errno, optind; extern char *optarg; register char *p; struct passwd lpw, *pw; struct rlimit rlim; FILE *temp_fp; int aflag, ch, fd; char *fend, *passwd, *temp, *tend; char from[MAXPATHLEN], to[MAXPATHLEN]; char *getusershell(); uid = getuid(); aflag = 0; while ((ch = getopt(argc, argv, "a:")) != EOF) switch(ch) { case 'a': if (uid) { (void)fprintf(stderr, "chpass: %s\n", strerror(EACCES)); exit(1); } loadpw(optarg, pw = &lpw); aflag = 1; break; case '?': default: usage(); } argc -= optind; argv += optind; if (!aflag) switch(argc) { case 0: if (!(pw = getpwuid(uid))) { (void)fprintf(stderr, "chpass: unknown user: uid %u\n", uid); exit(1); } break; case 1: if (!(pw = getpwnam(*argv))) { (void)fprintf(stderr, "chpass: unknown user %s.\n", *argv); exit(1); } if (uid && uid != pw->pw_uid) { (void)fprintf(stderr, "chpass: %s\n", strerror(EACCES)); exit(1); } break; default: usage(); } (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGTSTP, SIG_IGN); rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; (void)setrlimit(RLIMIT_CPU, &rlim); (void)setrlimit(RLIMIT_FSIZE, &rlim); (void)umask(0); temp = _PATH_PTMP; if ((fd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0) { if (errno == EEXIST) { (void)fprintf(stderr, "chpass: password file busy -- try again later.\n"); exit(1); } (void)fprintf(stderr, "chpass: %s: %s; ", temp, strerror(errno)); goto bad; } if (!(temp_fp = fdopen(fd, "w"))) { (void)fprintf(stderr, "chpass: can't write %s; ", temp); goto bad; } if (!aflag && !info(pw)) goto bad; /* root should have a 0 uid and a reasonable shell */ if (!strcmp(pw->pw_name, "root")) { if (pw->pw_uid) { (void)fprintf(stderr, "chpass: root uid should be 0."); exit(1); } setusershell(); for (;;) if (!(p = getusershell())) { (void)fprintf(stderr, "chpass: warning, unknown root shell."); break; } else if (!strcmp(pw->pw_shell, p)) break; } passwd = _PATH_MASTERPASSWD; if (!freopen(passwd, "r", stdin)) { (void)fprintf(stderr, "chpass: can't read %s; ", passwd); goto bad; } if (!copy(pw, temp_fp)) goto bad; (void)fclose(temp_fp); (void)fclose(stdin); switch(fork()) { case 0: break; case -1: (void)fprintf(stderr, "chpass: can't fork; "); goto bad; /* NOTREACHED */ default: exit(0); /* NOTREACHED */ } if (makedb(temp)) { (void)fprintf(stderr, "chpass: mkpasswd failed; "); bad: (void)fprintf(stderr, "%s unchanged.\n", _PATH_MASTERPASSWD); (void)unlink(temp); exit(1); } /* * possible race; have to rename four files, and someone could slip * in between them. LOCK_EX and rename the ``passwd.dir'' file first * so that getpwent(3) can't slip in; the lock should never fail and * it's unclear what to do if it does. Rename ``ptmp'' last so that * passwd/vipw/chpass can't slip in. */ (void)setpriority(PRIO_PROCESS, 0, -20); fend = strcpy(from, temp) + strlen(temp); tend = strcpy(to, _PATH_PASSWD) + strlen(_PATH_PASSWD); bcopy(".dir", fend, 5); bcopy(".dir", tend, 5); if ((fd = open(from, O_RDONLY, 0)) >= 0) (void)flock(fd, LOCK_EX); /* here we go... */ (void)rename(from, to); bcopy(".pag", fend, 5); bcopy(".pag", tend, 5); (void)rename(from, to); bcopy(".orig", fend, 6); (void)rename(from, _PATH_PASSWD); (void)rename(temp, passwd); /* done! */ exit(0); } info(pw) struct passwd *pw; { struct stat begin, end; FILE *fp; int fd, rval; char *tfile; tfile = "/tmp/passwd.XXXXXX"; if ((fd = mkstemp(tfile)) == -1 || !(fp = fdopen(fd, "w+"))) { (void)fprintf(stderr, "chpass: no temporary file"); return(0); } print(fp, pw); (void)fflush(fp); /* * give the file to the real user; setuid permissions * are discarded in edit() */ (void)fchown(fd, getuid(), getgid()); for (rval = 0;;) { (void)fstat(fd, &begin); if (edit(tfile)) { (void)fprintf(stderr, "chpass: edit failed; "); break; } (void)fstat(fd, &end); if (begin.st_mtime == end.st_mtime) { (void)fprintf(stderr, "chpass: no changes made; "); break; } (void)rewind(fp); if (check(fp, pw)) { rval = 1; break; } (void)fflush(stderr); if (prompt()) break; } (void)fclose(fp); (void)unlink(tfile); return(rval); } check(fp, pw) FILE *fp; struct passwd *pw; { register struct entry *ep; register char *p; static char buf[256]; while (fgets(buf, sizeof(buf), fp)) { if (!buf[0] || buf[0] == '#') continue; if (!(p = index(buf, '\n'))) { (void)fprintf(stderr, "chpass: line too long.\n"); return(0); } *p = '\0'; for (ep = list;; ++ep) { if (!ep->prompt) { (void)fprintf(stderr, "chpass: unrecognized field.\n"); return(0); } if (!strncasecmp(buf, ep->prompt, ep->len)) { if (ep->restricted && uid) break; if (!(p = index(buf, ':'))) { (void)fprintf(stderr, "chpass: line corrupted.\n"); return(0); } while (isspace(*++p)); if (ep->except && strpbrk(p, ep->except)) { (void)fprintf(stderr, "chpass: illegal character in the \"%s\" field.\n", ep->prompt); return(0); } if ((ep->func)(p, pw, ep)) return(0); break; } } } /* * special checks... * * there has to be a limit on the size of the gecos fields, * otherwise getpwent(3) can choke. * ``if I swallow anything evil, put your fingers down my throat...'' * -- The Who */ if (strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) + strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) > 128) { (void)fprintf(stderr, "chpass: gecos field too large.\n"); exit(1); } (void)sprintf(pw->pw_gecos = buf, "%s,%s,%s,%s", list[E_NAME].save, list[E_LOCATE].save, list[E_BPHONE].save, list[E_HPHONE].save); return(1); } copy(pw, fp) struct passwd *pw; FILE *fp; { register int done; register char *p; char buf[256]; for (done = 0; fgets(buf, sizeof(buf), stdin);) { /* skip lines that are too big */ if (!index(buf, '\n')) { (void)fprintf(stderr, "chpass: line too long; "); return(0); } if (done) { (void)fprintf(fp, "%s", buf); continue; } if (!(p = index(buf, ':'))) { (void)fprintf(stderr, "chpass: corrupted entry; "); return(0); } *p = '\0'; if (strcmp(buf, pw->pw_name)) { *p = ':'; (void)fprintf(fp, "%s", buf); continue; } (void)fprintf(fp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos, pw->pw_dir, pw->pw_shell); done = 1; } if (!done) (void)fprintf(fp, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos, pw->pw_dir, pw->pw_shell); return(1); } makedb(file) char *file; { int status, pid, w; if (!(pid = vfork())) { execl(_PATH_MKPASSWD, "mkpasswd", "-p", file, NULL); _exit(127); } while ((w = wait(&status)) != pid && w != -1); return(w == -1 || status); } edit(file) char *file; { int status, pid, w; char *p, *editor, *getenv(); if (editor = getenv("EDITOR")) { if (p = rindex(editor, '/')) ++p; else p = editor; } else p = editor = "vi"; if (!(pid = vfork())) { (void)setgid(getgid()); (void)setuid(getuid()); execlp(editor, p, file, NULL); _exit(127); } while ((w = wait(&status)) != pid && w != -1); return(w == -1 || status); } loadpw(arg, pw) char *arg; register struct passwd *pw; { register char *cp; long atol(); char *strsep(); pw->pw_name = strsep(arg, ":"); pw->pw_passwd = strsep((char *)NULL, ":"); if (!(cp = strsep((char *)NULL, ":"))) goto bad; pw->pw_uid = atoi(cp); if (!(cp = strsep((char *)NULL, ":"))) goto bad; pw->pw_gid = atoi(cp); pw->pw_class = strsep((char *)NULL, ":"); if (!(cp = strsep((char *)NULL, ":"))) goto bad; pw->pw_change = atol(cp); if (!(cp = strsep((char *)NULL, ":"))) goto bad; pw->pw_expire = atol(cp); pw->pw_gecos = strsep((char *)NULL, ":"); pw->pw_dir = strsep((char *)NULL, ":"); pw->pw_shell = strsep((char *)NULL, ":"); if (!pw->pw_shell || strsep((char *)NULL, ":")) { bad: (void)fprintf(stderr, "chpass: bad password list.\n"); exit(1); } } prompt() { register int c; for (;;) { (void)printf("re-edit the password file? [y]: "); (void)fflush(stdout); c = getchar(); if (c != EOF && c != (int)'\n') while (getchar() != (int)'\n'); return(c == (int)'n'); } /* NOTREACHED */ } usage() { (void)fprintf(stderr, "usage: chpass [-a list] [user]\n"); exit(1); } 6, NULL, }, #define E_NAME 7 { "Full Name", p_gecos, 0, 9, e2, }, #define E_BPHONE 8 { "Office Phone", p_gecos, 0, 12, e2, }, #define E_HPHONE 9 { "Home Phone", p_gecos, 0, 10, e2, }, #define E_LOCATE 10 { "Location", p_gecos, 0, 8, e2, }, bin/chpass/chpass.h 644 0 12 1717 4433455562 7533 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)chpass.h 5.1 (Berkeley) 2/22/89 */ struct entry { char *prompt; int (*func)(), restricted, len; char *except, *save; }; extern uid_t uid; = atoi(cp); pw->pw_class = strsep((char *)NULL, bin/chpass/field.c 644 0 12 11467 4433455562 7353 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static char sccsid[] = "@(#)field.c 5.8 (Berkeley) 3/16/89"; #endif /* not lint */ #include #include #include #include #include #include #include #include "pathnames.h" /* ARGSUSED */ p_login(p, pw, ep) char *p; struct passwd *pw; struct entry *ep; { if (!*p) { (void)fprintf(stderr, "chpass: empty login field.\n"); return(1); } if (*p == '-') { (void)fprintf(stderr, "chpass: login names may not begin with a hyphen.\n"); return(1); } if (!(pw->pw_name = strdup(p))) { (void)fprintf(stderr, "chpass: can't save entry.\n"); return(1); } if (index(p, '.')) (void)fprintf(stderr, "chpass: \'.\' is dangerous in a login name.\n"); for (; *p; ++p) if (isupper(*p)) { (void)fprintf(stderr, "chpass: upper-case letters are dangerous in a login name.\n"); break; } return(0); } /* ARGSUSED */ p_passwd(p, pw, ep) char *p; struct passwd *pw; struct entry *ep; { if (!*p) pw->pw_passwd = ""; /* "NOLOGIN"; */ else if (!(pw->pw_passwd = strdup(p))) { (void)fprintf(stderr, "chpass: can't save password entry.\n"); return(1); } return(0); } /* ARGSUSED */ p_uid(p, pw, ep) register char *p; struct passwd *pw; struct entry *ep; { int id; if (!*p) { (void)fprintf(stderr, "chpass: empty uid field.\n"); return(1); } if (!isdigit(*p)) { (void)fprintf(stderr, "chpass: illegal uid.\n"); return(1); } id = atoi(p); if ((u_int)id > USHRT_MAX) { (void)fprintf(stderr, "chpass: %d > max uid value (%d).\n", id, USHRT_MAX); return(1); } pw->pw_uid = id; return(0); } /* ARGSUSED */ p_gid(p, pw, ep) register char *p; struct passwd *pw; struct entry *ep; { struct group *gr; int id; if (!*p) { (void)fprintf(stderr, "chpass: empty gid field.\n"); return(1); } if (!isdigit(*p)) { if (!(gr = getgrnam(p))) { (void)fprintf(stderr, "chpass: unknown group %s.\n", p); return(1); } pw->pw_gid = gr->gr_gid; return(0); } id = atoi(p); if ((u_int)id > USHRT_MAX) { (void)fprintf(stderr, "chpass: %d > max gid value (%d).\n", id, USHRT_MAX); return(1); } pw->pw_gid = id; return(0); } /* ARGSUSED */ p_class(p, pw, ep) char *p; struct passwd *pw; struct entry *ep; { if (!*p) pw->pw_class = ""; else if (!(pw->pw_class = strdup(p))) { (void)fprintf(stderr, "chpass: can't save entry.\n"); return(1); } return(0); } /* ARGSUSED */ p_change(p, pw, ep) char *p; struct passwd *pw; struct entry *ep; { if (!atot(p, &pw->pw_change)) return(0); (void)fprintf(stderr, "chpass: illegal date for change field.\n"); return(1); } /* ARGSUSED */ p_expire(p, pw, ep) char *p; struct passwd *pw; struct entry *ep; { if (!atot(p, &pw->pw_expire)) return(0); (void)fprintf(stderr, "chpass: illegal date for expire field.\n"); return(1); } /* ARGSUSED */ p_gecos(p, pw, ep) char *p; struct passwd *pw; struct entry *ep; { if (!*p) ep->save = ""; else if (!(ep->save = strdup(p))) { (void)fprintf(stderr, "chpass: can't save entry.\n"); return(1); } return(0); } /* ARGSUSED */ p_hdir(p, pw, ep) char *p; struct passwd *pw; struct entry *ep; { if (!*p) { (void)fprintf(stderr, "chpass: empty home directory field.\n"); return(1); } if (!(pw->pw_dir = strdup(p))) { (void)fprintf(stderr, "chpass: can't save entry.\n"); return(1); } return(0); } /* ARGSUSED */ p_shell(p, pw, ep) register char *p; struct passwd *pw; struct entry *ep; { register char *sh, *t; char *getusershell(); if (!*p) { pw->pw_shell = _PATH_BSHELL; return(0); } setusershell(); for (;;) { if (!(sh = getusershell())) { /* only admin can set "restricted" shells */ if (!uid) break; (void)fprintf(stderr, "chpass: %s: non-standard shell.\n", p); return(1); } if (!strcmp(p, sh)) break; /* allow just shell name */ if ((t = rindex(sh, '/')) && !strcmp(p, t)) { p = t; break; } } if (!(pw->pw_shell = strdup(p))) { (void)fprintf(stderr, "chpass: can't save entry.\n"); return(1); } return(0); } id)unlink(temp); exit(1); } /* * possible race; have to rename four files, and someone could slip * in between them. LOCK_EX and rename the ``passwd.dir'' file first * so that getpwent(3) cbin/chpass/pathnames.h 644 0 12 1605 4433455562 10226 /* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)pathnames.h 5.1 (Berkeley) 3/5/89 */ #define _PATH_BSHELL "/bin/sh" that the software was developed * by the University of California, Berkeley. The name of the * University may not be usebin/chpass/util.c 644 0 12 10106 4433455563 7233 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static char sccsid[] = "@(#)util.c 5.9 (Berkeley) 3/27/89"; #endif /* not lint */ #include #include #include #include #include #include #include #include "pathnames.h" static int dmsize[] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static char *months[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", NULL }; char * ttoa(tval) time_t tval; { struct tm *tp; static char tbuf[50]; if (tval) { tp = localtime(&tval); (void)sprintf(tbuf, "%s %d, 19%d", months[tp->tm_mon], tp->tm_mday, tp->tm_year); } else *tbuf = '\0'; return(tbuf); } atot(p, store) char *p; time_t *store; { register char *t, **mp; static struct tm *lt; time_t tval, time(); int day, month, year; if (!*p) { *store = 0; return(0); } if (!lt) { unsetenv("TZ"); (void)time(&tval); lt = localtime(&tval); } if (!(t = strtok(p, " \t"))) goto bad; for (mp = months;; ++mp) { if (!*mp) goto bad; if (!strncasecmp(*mp, t, 3)) { month = mp - months + 1; break; } } if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t)) goto bad; day = atoi(t); if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t)) goto bad; year = atoi(t); if (day < 1 || day > 31 || month < 1 || month > 12 || !year) goto bad; #define TM_YEAR_BASE 1900 #define EPOCH_YEAR 1970 #define DAYSPERNYEAR 365 #define DAYSPERLYEAR 366 #define HOURSPERDAY 24 #define MINSPERHOUR 60 #define SECSPERMIN 60 #define isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0) if (year < 100) year += TM_YEAR_BASE; if (year <= EPOCH_YEAR) bad: return(1); tval = isleap(year) && month > 2; for (--year; year >= EPOCH_YEAR; --year) tval += isleap(year) ? DAYSPERLYEAR : DAYSPERNYEAR; while (--month) tval += dmsize[month]; tval += day; tval = tval * HOURSPERDAY * MINSPERHOUR * SECSPERMIN; tval -= lt->tm_gmtoff; *store = tval; return(0); } print(fp, pw) FILE *fp; struct passwd *pw; { register char *p; char *getusershell(), *ttoa(); fprintf(fp, "#Changing user database information for %s.\n", pw->pw_name); if (!uid) { fprintf(fp, "Login: %s\n", pw->pw_name); fprintf(fp, "Password: %s\n", pw->pw_passwd); fprintf(fp, "Uid [#]: %d\n", pw->pw_uid); fprintf(fp, "Gid [# or name]: %d\n", pw->pw_gid); fprintf(fp, "Change [month day year]: %s\n", ttoa(pw->pw_change)); fprintf(fp, "Expire [month day year]: %s\n", ttoa(pw->pw_expire)); fprintf(fp, "Class: %s\n", pw->pw_class); fprintf(fp, "Home directory: %s\n", pw->pw_dir); fprintf(fp, "Shell: %s\n", *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL); } else { /* only admin can change "restricted" shells */ setusershell(); for (;;) if (!(p = getusershell())) break; else if (!strcmp(pw->pw_shell, p)) { fprintf(fp, "Shell: %s\n", *pw->pw_shell ? pw->pw_shell : _PATH_BSHELL); break; } } p = strsep(pw->pw_gecos, ","); fprintf(fp, "Full Name: %s\n", p ? p : ""); p = strsep((char *)NULL, ","); fprintf(fp, "Location: %s\n", p ? p : ""); p = strsep((char *)NULL, ","); fprintf(fp, "Office Phone: %s\n", p ? p : ""); p = strsep((char *)NULL, ","); fprintf(fp, "Home Phone: %s\n", p ? p : ""); } derr, "chpass: can't save entry.\n"); return(1); } return(0); } /* ARGSUSED */ p_shell(p, pw, ep) register char *p; struct passwd *pw; struct entry *ep; { register char *sh, *t; char *getusershell(); if (!*p) { pw->pw_shell = _PATH_BSHELL; return(0); } setusershell(); for (;;) { if (!(sh = getusershell())) { /* only admin can set "restricted" shells */ if (!uid) break; (void)fprintf(stderr, "chpassbin/MANIFEST 444 0 12 4033 4263535420 5732 Application Version ----------- ------- Makefile 4.3 (small mods for load type (separate I&D or pure)) adb/ 2.10 (impossible to convert - PDP11 specific) ar.c 2.10 (see PORT; unclear it's worth the effort) as/ 2.10 (impossible to convert - PDP11 specific) awk/ 4.3 (small mods to Makefile for sep/nonsep loading) cat.c 4.3 cc.c 4.3 chgrp.c 4.3 chmod.c 4.3 cmp.c 4.4 cp.c 4.3 csh/ 4.3 (2.10BSD malloc & doprnt, long/int fixes, shorter names) date.c 4.4 (timed code disabled for now) dd.c 4.3 df.c 4.3 (small mods for 2.10BSD super block format) diff/ 4.3 (small mods to Makefile and shorter names in diffreg.c) du.c 4.3 echo.c 4.3 ed.c 4.3 expr.y 4.3 false.sh 4.3 grep.c 4.3 hostid.c 4.3 (some long/int fixes, fix lack of %#x in 2.10BSD printf) hostname.c 4.3 (small mods for shorter names) kill.c 4.3 ld.c 2.10 (not convertible, but fairly close to 4.3's) ln.c 4.3 login.c 4.3+ (minor mods for shorter names) ls.c 4.3 (minor long/int fixes and shorter names) mail.c 4.3+ (minor long/int fixes, include short_name.h. make/ 4.3 (small mods to Makefile and smaller sizes in defs) mkdir.c 4.3 mt.c 4.3 mv.c 4.3 nice.c 4.3 nm.c 2.10 (see PORT; but not clear worth the effort) od.c 4.3 pagesize.c 4.3 passwd.c 4.3 (small mods for shorter names) pr.c 4.3 ps.c 2.10 (too hard to convert now) pwd.c 4.3 rcp.c 4.3 rm.c 4.3 rmail.c 4.3 rmdir.c 4.3 sed/ 4.3 (small mods to Makefile for sep/nonsep loading) sh/ 4.3 (small mods to Makefile for sep/nonsep loading) size.c 4.3 (small mods for 2.10BSD a.out format) strip.c 4.3 (small mods for 2.10BSD a.out format) stty.c 4.3 su.c 4.3 sync.c 4.3 tar.c 4.3 tee.c 4.3 test.c 4.3 time.c 4.3 true.sh 4.3 tp/ 4.3 (small mods to Makefile for sep/nonsep loading) wall.c 4.3 (small mods for shorter names) who.c 4.3 (small mods for shorter names) write.c 4.3 (small mods for shorter names) The directory PORT is special. It contains source code from the 4.3BSD distribution that should probably be ported to 2.10 as soon as someone has the time and inclination to do so. day = atoi(t); if (!(t = strtok((char *)NULL, " \t,")) || !isdigit(*t)) goto bad; year = atoi(t); if (day < 1 || day > 31 || month < 1 || month > 12 || !year) goto bad; #define TM_YEAR_BASE 1900 #define EPOCH_YEAR 1970 #define DAYSPERNYEAR 365 #define DAYSPERLYEAR 366 #define HOURSPERDAY 24 #define MINSPERHOUR 60 #define SECSPERMIN 60 #define isleap(y) (((y) % 4) == 0 && ((y) % 100) != 0 || ((y) % 400) == 0) if (year < 100) year += TM_YEAR_BASE; if (year <= EPOCH_YEbin/nm.c.use.disk 664 3 12 21012 4724105323 7123 /* * This version of nm will use a disk file, rather than trying to store * the entire symbol table in memory. Useful for some sites. * * 11/25/90 - The ASCII version of archives has been implemented, but this * program was NOT updated. the normal version of 'nm' not only handles * .a files correctly but can even process /unix. so this program is of even * less value than before, this program is extremely slow even for cases * which the regular 'nm' works well. */ /* * print symbol tables for * object or archive files * * nm [-fgoprun] [name ...] */ #include #include #include #include #include #include #include #include struct nnlist { /* symbol table entry */ char n_name[8]; /* symbol name */ char nn_type; /* type flag */ char nn_ovno; unsigned int n_value; /* value */ }; #define SYMFILE "/tmp/nm.sym.XXXXXX" #define SELECT arch_flg ? arp.ar_name : *argv int numsort_flg; int undef_flg; int revsort_flg = 1; int globl_flg; int nosort_flg; int arch_flg; int prep_flg; int file_flg; struct ar_hdr arp; struct exec exp; FILE *fi; long off; long ftell(); char *malloc(); char *realloc(); char *mktemp(); int symfile = -1; char *symfname; long lseek(); long save_sym(); struct nnlist *get_sym(); int cleanup(); main(argc, argv) char **argv; { int narg; int compare(); int fcompare(); signal(SIGINT,cleanup); signal(SIGHUP,cleanup); signal(SIGTERM,cleanup); signal(SIGQUIT,cleanup); if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) { argv++; while (*++*argv) switch (**argv) { case 'n': /* sort numerically */ numsort_flg++; continue; case 'g': /* globl symbols only */ globl_flg++; continue; case 'u': /* undefined symbols only */ undef_flg++; continue; case 'r': /* sort in reverse order */ revsort_flg = -1; continue; case 'p': /* don't sort -- symbol table order */ nosort_flg++; continue; case 'o': /* prepend a name to each line */ prep_flg++; continue; case 'f': /* use a file insted of memory - slow */ file_flg++; continue; default: /* oops */ fprintf(stderr, "nm: invalid argument -%c\n", *argv[0]); cleanup(1); } argc--; } if (argc == 0) { argc = 1; argv[1] = "a.out"; } narg = argc; while(argc--) { fi = fopen(*++argv,"r"); if (fi == NULL) { fprintf(stderr, "nm: cannot open %s\n", *argv); continue; } off = sizeof(exp.a_magic); fread((char *)&exp, 1, sizeof(exp.a_magic), fi); /* get magic no. */ if (exp.a_magic == ARMAG) arch_flg++; else if (N_BADMAG(exp)) { fprintf(stderr, "nm: %s-- bad format\n", *argv); continue; } fseek(fi, 0L, L_SET); if (arch_flg) { (void) nextel(fi); if (narg > 1) printf("\n%s:\n", *argv); } do { long o; register i, n, c; struct nnlist sym; struct nnlist *symp = NULL; long *idxsymfile = NULL; unsigned ovsizes[1 + NOVL]; fread((char *)&exp, 1, sizeof(struct exec), fi); if (N_BADMAG(exp)) /* archive element not in */ continue; /* proper format - skip it */ if (exp.a_magic == A_MAGIC5 || exp.a_magic == A_MAGIC6) { fread((char *)ovsizes, 1, sizeof ovsizes, fi); o = 0L; for (i = 1; i <= NOVL; i++) o += (long) ovsizes[i]; fseek(fi, o, L_INCR); } o = (long)exp.a_text + exp.a_data; if ((exp.a_flag & 01) == 0) o *= 2; fseek(fi, o, L_INCR); if (file_flg) set_sym(); i = 0; while (fread((char *)&sym, sizeof(sym), 1, fi) == 1) { if (globl_flg && (sym.nn_type&N_EXT)==0) continue; switch (sym.nn_type&N_TYPE) { case N_UNDF: c = 'u'; if (sym.n_value) c = 'c'; break; default: case N_ABS: c = 'a'; break; case N_TEXT: c = 't'; break; case N_DATA: c = 'd'; break; case N_BSS: c = 'b'; break; case N_FN: c = 'f'; break; case N_REG: c = 'r'; break; } if (undef_flg && c!='u') continue; if (sym.nn_type&N_EXT) c = toupper(c); sym.nn_type = c; if (file_flg) { if (idxsymfile==NULL) idxsymfile = (long *)malloc(sizeof(long)); else idxsymfile = (long *)realloc(idxsymfile, (i+1)*sizeof(long)); } else { if (symp==NULL) symp = (struct nnlist *)malloc(sizeof(struct nnlist)); else symp = (struct nnlist *)realloc(symp, (i+1)*sizeof(struct nnlist)); } if (file_flg) { if (idxsymfile == NULL) { fprintf(stderr, "nm: out of memory on %s\n", *argv); cleanup(2); } } else { if (symp == NULL) { fprintf(stderr, "nm: try using the '-f' option.\n"); cleanup(2); } } if (file_flg) idxsymfile[i++] = save_sym(&sym); else symp[i++] = sym; } if (i == 0) { fprintf(stderr, "nm: %s-- no name list\n", SELECT); continue; } if (nosort_flg==0) if (file_flg) qsort(idxsymfile, i, sizeof(long), fcompare); else qsort(symp, i, sizeof(struct nnlist), compare); if ((arch_flg || narg>1) && prep_flg==0) printf("\n%s:\n", SELECT); for (n=0; nnn_type; } else c = symp[n].nn_type; if (!undef_flg) { if (c=='u' || c=='U') printf(" "); else { if (file_flg) printf(N_FORMAT, tt->n_value); else printf(N_FORMAT, symp[n].n_value); } printf(" %c ", c); } if (file_flg) { if (tt->nn_ovno) printf("%-8.8s %d", tt->n_name, tt->nn_ovno); else printf("%.8s", tt->n_name); } else { if (symp[n].nn_ovno) printf("%-8.8s %d", symp[n].n_name, symp[n].nn_ovno); else printf("%.8s", symp[n].n_name); } printf("\n"); if (file_flg) free(tt); } if (file_flg) if (idxsymfile) free((char *)idxsymfile); else if (symp) free((char *)symp); } while(arch_flg && nextel(fi)); fclose(fi); } cleanup(0); } compare(p1, p2) register struct nnlist *p1, *p2; { register i; if (numsort_flg) { if (p1->n_value > p2->n_value) return(revsort_flg); if (p1->n_value < p2->n_value) return(-revsort_flg); } for(i=0; in_name); i++) if (p1->n_name[i] != p2->n_name[i]) { if (p1->n_name[i] > p2->n_name[i]) return(revsort_flg); else return(-revsort_flg); } return(0); } nextel(af) register FILE *af; { register r; fseek(af, off, L_SET); r = fread((char *)&arp, 1, sizeof(struct ar_hdr), af); /* read archive header */ if (r <= 0) return(0); if (arp.ar_size & 1) ++arp.ar_size; off = ftell(af) + arp.ar_size; /* offset to next element */ return(1); } fcompare(fi1, fi2) register long *fi1, *fi2; { register i; register struct nnlist *p1, *p2; p1 = get_sym(*fi1); p2 = get_sym(*fi2); if (numsort_flg) { if (p1->n_value > p2->n_value) { free((char *)p1); free((char *)p2); return(revsort_flg); } if (p1->n_value < p2->n_value) { free((char *)p1); free((char *)p2); return(-revsort_flg); } } for(i=0; in_name); i++) if (p1->n_name[i] != p2->n_name[i]) { if (p1->n_name[i] > p2->n_name[i]) { free((char *)p1); free((char *)p2); return(revsort_flg); } else { free((char *)p1); free((char *)p2); return(-revsort_flg); } } free((char *)p1); free((char *)p2); return(0); } /* * Save a symbol in symfile */ long save_sym(sym) struct nlist *sym; { long ret_val; if ((ret_val = lseek(symfile,0L,L_INCR)) < 0) { perror("lseek:save_sym"); cleanup(1); } if (write(symfile,sym,sizeof(struct nlist)) < 0) { perror("write:save_sym"); cleanup(1); } return(ret_val); } /* * Retrieve a symbol from symfile */ struct nnlist * get_sym(offset) long offset; { struct nnlist *temp; if(lseek(symfile,offset,L_SET) < 0) { perror("lseek:get_sym"); cleanup(1); } temp = (struct nnlist *) malloc(sizeof(struct nnlist)); if(read(symfile,temp,sizeof(struct nnlist)) != sizeof (struct nnlist)) { perror("read:get_sym"); cleanup(1); } return(temp); } /* * Open The symfile */ set_sym() { if (symfile != -1) close(symfile); else symfname = mktemp(SYMFILE); if ((symfile = open(symfname,O_CREAT|O_RDWR|O_TRUNC,0666)) < 0) { perror("open:symfile"); cleanup(1); } } /* * Cleanup Routine */ int cleanup(n) int n; { if (file_flg) unlink(symfname); exit(n); } lds, * otherwise getpwent(3) can choke. * ``if I swallow anything evil, put your fingers down my throat...'' * -- The Who */ if (strlen(list[E_NAME].save) + strlen(list[E_BPHONE].save) + strlen(list[E_HPHONE].save) + strlen(list[E_LOCATE].save) > 128) { (void)fprintf(stderr, "chpass: gecos field too large.\n"); exit(1); } (void)sprintf(pw->pw_gecos = buf, "%s,%s,%s,%s", list[E_NAME].save, list[E_LOCATE].save, list[E_BPHONE].save, list[E_HPHONE].save); return(1);bin/pathnames.h 444 0 12 1702 4437151230 6726 /* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)pathnames.h 5.2 (Berkeley) 5/10/89 */ #define _PATH_BSHELL "/bin/sh" #define _PATH_CP "/bin/cp" #define _PATH_RSH "/usr/ucb/rsh" 'o': /* prepend a name to each line */ prep_flg++; conbin/PORT/ 755 0 0 0 4634750507 5266 bin/PORT/ar.c.Z 444 0 0 14270 4634750201 6342 Œ/T(¡Ä7pòÈIs (Ƥ# ¤”9SÆ 9 Þ˜AMUܤ±SFÎœ4tò„9$ ›4fÞÈQÆÅÀ‚AØ°±°áG¢eæ´dIÆTL‚ÒrM6edÎIçN9'™¤ÓQ)ˆ gÀ–iÓ‘ÎOsà”ƒ3MR’Ré´l2Œ2 Ƽù 3Í`9å %“f…bêÐ1ìÆ'Á ŒÀù·ÌÈ›83yL`4_áŽó’Ì–. z€ň_]ŒIPÃ… ˆTåXÅšg"2f¼ÀQCÄÍtóæ!h·š9“ñ ⺂1¨ NXÔáëØ hÛžxFà’ªðUáŒß["äß ®mÀQxûö;Û ˜Ãñ‚X”^ºÆ‘3z ›Cüyè£Ç`úé§~yæ2´î¹ g>º ³czåÓaå _nëHÚn|îÍo´X¥^ø¥™nÊö Î†Ý=×ÆÇ€xÏÇ÷sZL%² ã¹EA`!ÄÉZ¡}ØpîHêœ'PHk ÉH’¿1 _9ƒÈÚêuÄR Qf¤§º…´!o–kÃô’9 6NNi` Õ £¡ chYíéd…¯yŽ£\9¦% H§jؽˆ'<žó¨Ä  =€ÁàÂ, ›Êá VÐBÎá«°ØD‘mŠ4CÙP愉„@6/ãÊø(ÎeÑ&\™ÁÈÄ3Í]ZKÀQ$Ì Š ¨ÃÂÀªA ±A Î`Li/Fb"aƒ(ÊmˆÃ«8‡;À ÚFW<Ü'7BŠ±c·Ìxwv»×ýn" ¸C£ʽ3P}?y#=Ä¡³ì'9‘$„e°ƒMHbZí=7àZdÁǼå.cEáaNÕ¯{E6÷ º x³ÄÓ<ç‡ß4‘c i²ëå–±ºY.èÕ¯~dÝàîüÍjûœbB¯x¼>}±y öÆ/ŽNû¼õ2i/WúÒtàÖ°éNŸ¼ŸgùÍݲt§kسšµ7ˆ•5 ƒ.¸`õ¨šKhYÉ×Û!öÊ]–Zí§W#«äc½ëa/HÙËfõŽ´}«”’{%ŠZ2Hdz_ÎÂÊÿ™¤$×ö£&ßí“‹Ûž+×x²— u<Ú° Øì=Åu/ñ¯Àbì9ÿÙ¿ÖåÔU-œQŸó›§P7pœ3ugu_–u[gv]—\mv’5v×wYÕX´”zfÇ9…Æb" <À^> ‡•f{#HiV&FüÕiäÖrœG1gs›†}¿·k~.¸qäg~Ðrú—,™!RþGeþ–GOgø—GÏÃV?¶AkaorU8yÄ#o@kŠ·vOˆ$-6Öå„fð²ÑPeX8-#FÈSϳw×…Swh‚—h‹†x²…›UZN%UAó_†pW·p£uØFfgd—~‰Ø?'÷Q™'~è&1ÈnWs"ÇQÖFÞ—rà—q9ørž'sŸ/2Hdzä9·E–5„Ø€J˜Xu §ˆ Wv)¶€jÓ€bG‰Âøg¸UjÀg4g`eü•<%’f!/gAl'‚ç$`-¸y:؉=¨[ÆRþGC@e9ÔyúTzÙÕXÂÄ]oVX•%XsHvcBEx(’ àh:ö<žT ƒd…8d6x(ú£«…eçcHF„DJTGNôEQ”›ÔFo´EY4G]FG Fe$,JÃ4çó…lІyT‘I´DiÀŠ#“›dv”HÂ¥‘’˜“_ç]ׇmÙÇ‹HÒHP”HÎÇ9'—RçTgp¡YxvNzÇgt†äu‡ûHT†ÇhŽ†† ‚ äx3(”5(`Æ“HçsMÓf.[4zmt>¡5tûÇ1UÖd!F>ÇÓ[Qˆ •9VÈ)X¨…jgeÆÆ:†cÈ)gy†¦††é†œrEgI•8i•§çÅ•{8˜'ˆa‰ ÙFBvsêw ¡jØ2A ðs4³š­iFh›Ap€dš?µs  ‹û)@Ôî3´yNÇ=‰ä•¤e˜ù÷\æ&‡mtP;aˆ‘©~j75/œÍòš¬Y›²é2Ãé€O¹QcoÚynÃɱyux•˜Ix†çh¢Hàá ¤gæc¼Õ„è.Ô ‹Ð)n€Ëia©e½i/?œÃYœî¸RN‰œûé’A™ÃÈS!PXÈ”zF‡â•ƒ·hƒÙ!gPxs Ÿ;$R©~Švƒ™œ^x˜6`eg¡j™.öžyØh›¹x'qO¥Hy Ùm䎦 B³’gÑ® žNúÂ¥†›/fHÊrfáŽ× ¡ú…'êé%6›NÚFoö&;ÒAç©šN¦¶Éžêž!j¢ÿ¸!óùõÉ÷)ù –ûÙŸTEŽ™!H„$4-4Cø(1¸UD•ëÕ^šcPÓezê@ á˜êcùÒ2ã`Eªd™Ñ‹ûVD8ŠhYI§@sŽVxÐC(:¤ýõ©@(?Sˆ‡ú(B&†µ¨þ%£Š]…©¢md7 Á4ÁÊŸÕ©†ÌßÃêŪ¬°*™k(¬œC¬b¬ÓŠ¬Âªþ& ª–f—e>´Žÿ¨OG¦3œ“9“5)ETt¤V”Y•íy™sŸ"®ác; Eüå«eƒ:wó­óǖ䊎6t®iÐ2n ®HÙ®:qD1™C4™\69¯°ƒÕ?»;Oº~»*oôfo·ê°A§Û@úä‘$[Dk‘2¹±jÓ±sèe:i¯PÔ“@û“Ö”#Wƒ [±¤˜à&LM™Hw¦fSyb}硆&§xH§šù^‚eŠ/Ur¤øÔÖrniƒ8w":·«k«c k®8¤C&å®K’O´‘éFMGx«‘$i’oxlÎ qÚXêŒ~§úºµ|H¢&úª* ˜¡wlyÔœ²Á‡0Ú_8£4š¬Íi£‹›µ{ª]œ¹~š¢ÚÊ9£ùƒÀš—üivISK“š:Ó’ÞuMˆ(4G”H] sEµ ?òC?EPvíw´ýƒ¤§)4/¦9ô/"jVJu°+­su]µ{»ÏÃ’_xN½‹¿+Á[†-#½Æ;?IP?Ê ”Í[šÏërÃ{n/2¦Ók½`q¥¤ ­*J»)©¬à»»m4¾å‹a05ᓾĻ¾Èû¾Ì h‘¤¨½Ä{¿&V½Àw½X:« B9$‹-ñ%q9ytoÑ1TÂ$1…:ñ2á@8BBfË°Ö– @ä>ÆR"AZx’+PIúu(½Ö¨l60% l2ÀdÐÄ6PRLÅ-€oÐÄ1PÜÄ20Oõ(OA@£Ei, ÆOAjpwjmjgœcŒ§²+´’jl¦F­ò*oÇs<+*xÇyü¸B}œÆw²Æz1K BÓ¢öÏ%Zwê6hzT°·7]w3ç×oØ&`WÔ¥ÑÂÀöK½¶%{Eï8Ø.ra´¶å¼Jš]@-½oð¡­¿¹yNa½ÖÇM²ÑÕõ“½<%€h !Om  Lj÷ü°8ÄÉšV®ø<·í¼ó†çBíÉ lÔl­¥œ¬þhbK=Ò\‡Ëc…èÇ7tjå”á³iá“Ht«}œÃÍÿ©¶ê‡ÉäÒf #gÀ¦•\›Ê},¤<Ò.à'ëMHs§¤›£s*#l#÷EŸ”z'ô%Å)àcÝË4/LÐ2U¨å½mˆ´\¥VÒ'±L$ß Mßî‹*7®%DÍÑmÄ)*0E’$Ó*×D·# ±~–¢B~Ñ3¾á>ÜánãlaÊET´ÿh)—ü0®É§á{ãGÎãa›GsÐ"~¡ãp×{¤TNAjM.*¤åRîTNÒ¡â*†<%([ÞåfæŒ6æõ}+|ŒæjÍ]^Èn>å@\å¡ÂÈX®*k®Ö~ÂÈy.æ{Næ¨ÂÖXÅNߨ¶%«ÌZ AˆŒ½ Ì9$Ì9Ñ<»8ò:Ý2n8Ùf¶åÑôÚSåD…Ú²)ÐyŽGêè“A.êCûgK[]›FÞ iƒzEÞ”®ˆfqûÛÁlRôIi–Y_îgÝt1ÐmWô&å¹L"ƒñ¿&Áؼפì›%2ГðØUŠ»íkR¼$Ýæí'ëbUÝz©A|¹V“[Í»/>ʉ˜>~vŒ™†ú£yê{FÍýƒµ,¦µ¦«‡Á‡ó5ƒˆSšýÃÍ£¸Ý1—qå”r9«²MÛäJªùÊß[+Û·ôS=ª¤”¦°N·ú\…ÕŒöxê¦ab('ž3Oî‚íWU–¨LM+ß2)ô™>«œ¬¢uAsÐBœ<2äÛºýC©¡p@~Xî&õ?S Zˆô%:Š’*w!A8;fY/µK„õâC"1°· À)ãÛöí÷ô ÈS*àZmó/ÀÒýƒÓó¦Óœ÷RmaþSFÐ!€qö ?N“Ã@úa$%±D@S§¡aöRaùhpfËöogoŸõK”õtEˆÿ“'ø‘]ú®ßY"p\TP@t=94‘7@ÐÈ©Î*¥ÇcŠt@¹~K üNb\1Õh(¤ANq'1c2w@5pxŇŽ! _1ý94¾ôs #´!a !@ °KW¡OnÐ!#/̧B*d þ×3NN`»€ñüÜêþš%H1ê<ƒ©>±û චyOa&¡îþx:à{zf˜ê»{4{@ð7žX1 ¤?y¿ÜpþáD×)†ð€Gò§ê@Àox4K*€8@AJúç¤õ¾ä.}=1"qÍâ+}Mx$o' –¤¿Í&;¤¿«#À-îâ-•L †b(†ìÒ-I0¥G0°ÅbÈ.Ý«yE0°ÅbìÒ-Sp3â4 †0À.Ý20#.0 bìÒ-RðWà 4 †ìÒ-WðWà 2 †ìÒ-XðWà [ ìÒ-RpR€-0@0À.ÝrG Ø2ìÒ-XpR€-0°ÅìÒ-RðT€ ë2Üâ. pO@H0@.#À-î’XðT€ Ú2Üâ.ÔBX@ [,†™ÒxéÄ~WßÛ£ÏȆ$ô3@/P1 ån'èe>çwþ*y$ô7Àèn'ècÍÖWXá‘j(Àå‚*¾—G‰ZxNì1ðÅ…×4à4A*D+@F¯I2ðë=Ó1@2(ƒñWà-l'Ð2ä^;ÛÓ2@2(ƒ pOpNÐ2'p'Ð2ä^;ÛÓ3@2(œè27C-ssp-ƒOpNÐ2'ÐO-Cîµ³=m@$ƒb0˜G ,ƒKßÔ2ä^;ÛÓ5@2(ƒ pG ,ƒKwp-Cîµ³=m`$ƒb À‰.3DÐ2'0'Ð2XpRÀ2¸ÔO-Cîµ³=mp$ƒb0˜O@HÐ2Áv-Cîµ³=m€$ƒb0WðT€-swp-Cîµ³=m$ƒb À‰.CX3 u-ƒO@HÐ2'ÐO-CîµC—s‚/$ƒb?F~mÀ‰?6úEúUúeúuú…ú•£pÀÈÃ^õ!ü*€/CT·qÐ#ÓzK”9}d#“›HJr7™³IߪX!'u1rÆÏX1r0D—Nì!ünU¯OŸHF¢uCô(ëê8št³Sm€áZnÑÑåŒlŽ£ITôuÜù«’a/qÓù»ÊÁ-+/v±û>-ÿ/¦"à©þ9dW%zeof(p1->n_name); i++) if (p1->n_name[i] != p2->n_name[i]) { if (p1->n_name[i] > p2->n_name[i]) { free((char *)p1); free((char *)p2); return(revsort_flg); } else { free((char *)p1); free((char *)p2); return(-revsort_flg); } } free((char *)p1); free((char *)p2); return(0bin/PORT/ld.c.Z 444 0 0 61615 4634750254 6354 Œ/T(¡Ä7pòÈIs (Ƥ# ¤”9SÆ 9 Þ˜AMUܤ±SFÎœ4tò„9$ ›4fÞÈQÆÅÀ‚AØ°±°áG¢eæ´dIÆTL‚ÒrM6edÎIçN9'™¤ÓQ)ˆ gÀ–iÓ‘ÎOsà”ƒ3MR’Ré´l2Œ2 Ƽù 3Í`9å %“f…bêÐ1ìÆ'Á ŒÀù·ÌÈ›ŒAó50B… n颇@PŒ˜x0aQ‡%R´ˆQ#G Eâ=™reË—1g´‰S'O\Üptèí£`•Êa ݈š;2éæÍCÐn5s&ãzŽÃL˜´â9cƼ$³º5ز¥ÀFSc$Pƒ 4@D•Va•ÇD1Äð‚ 6¼€C ß…Gyæ¹—Fh ôÖ€ ´×cžARb`K.QBb X?a¦žc°Q{ ð0Gs¼ÇWa´á>ìØã' É6-Ùäf<ú¤t0ö†•Njå1É&–OnùÕ™¦eOoHÆf–P)‡_7‰1§›AYd|tì)fŸD¾`FX¢@MÆKô9v§^gä¡ÃOoEuo„Ážbt„aU_ ¸QGb´¤Ü¡Xõõ—‡bܹÐ]‚ðÕ§¶5‡e@͘†K9Heà‘ä‡w•Æh¾ºø!IuìäNèÔ†MÍÒ Ö[uð8c“ f2qêid°`ë«%„B±zídÓDC¢ú µ+{‡ºq’_€G¿–ñÖW'•§`϶ Wöj‹eL ‚X±~eW_`Á¥¬£¡«.ÀØFÆrÈĪÇpc¡¿È–Zºè>1Ç'µrª`‘ñÖ³aÀ%]Ø’!_Ñ’ÖAf´'m5œLcøBªcEf΃ ç±`½%ì®OM±÷‚D³¿€‘,0ÁA_]îɲª¼Ð<ÛŠïo%˜ì5…i£A˜¯×‡ ÂØê:lî§ ¬QÞùJõ’' ç°ŽE¼o)êȯŠ1¬Çg°ÜŒr¼Ñ†×sœªœÃ—ߥ¹Tm¼AF­º óhoÝÑRÏe \pSO%ñi Ö’‰<£N (Ë,`8Ÿ»'œ 3Úl4nÒ[×â‘F²×®œ_2eÆð<žDÇ ÀD:`íšU/øy·ë†­ÃšºÞâ„#îyCÕÂ冾NUíú\Ò€¹¼…ph]Ó Ÿ«´/N\£4•Às)fr‘›\_„2Á NTR)Kü/ê-SÀm|}‰Ȥ¨zk„±-]Tà¶l³A.2K™W¿NÞáÌ“ÙÄJ ‚+ïoø“Jâs02!; !Ú«¶üO}SÌÃÑVØÉu($‹ò[¦\[\ÖÁ,¦ìÙ kV/.; s‚‡ø«”ÿEÂب!Ô+½‹{RóE?‡A¦m2Q7Oð4J?Ko |0¤/y ØæËF¶ÝmR“5×t˜¿t)ä9pê!§þ—Pð¹0¼ÝjUóŽ=nnçá ænM¨õXfú.fyÔIfýÍPÏ{ÿR˜Iä@À7ªêe)™]Øw:üVÑrÓ!n¸‰cÒm2ï`¼kæF"Ý"ñ9Sr1Sr ’ å*¯q·G阗üz¯º§i¬.¹á ’òsˆ€TÿÛÜF'¯€nM {êOycj¬‚n£ÁåG—¹r¢|qñ-]E`79ÐÇN²ÿ D§ÃËÉ+žµ?JÊŠä!^Þ~à>è,½[ðnÔ¥‚p§<7¡,=há¶nÒ‡&5Hæ©Iy,QžÖi+pþËê¤èÿþ–ÁôÒ©‰„d0;©D&Õe8JžÛnÉ—ÄÏkr6uàëçu?ÔrIZx6ݱ‹?¡'¹–UJÖ(¶O›4,!É7ÉÀ<²ïjN³ÊQ¢;ñu¬–Óv·yˆÚ¨Ýë\•×Ä’vz—[Ã[*§÷¼êËÀö†Å_0òf@HC?ý¢OÕó<Éq{âW?4g94F|¥Ò!fÀ;p¶OÓ(µtM 3`‘]õ•`Ü…SZP  W¥2X‘WXP/0#G~Ã÷!ŒñR(`EƒTôcƒ·ʶS.±MfÓ~†öñ)Åj¨*\÷?œ‚sðƒn@ƒ}T„ñfÑlŽ1svƒ_ÈL9xwöc´“mÑ5 h_xP/(àƒ)r[P‡)ð%Ö]à-÷+Ž±( ‡%Ї)XZ1x€?H*È# ¤.Û©Â)wp`ð!wb·rÏæ“uñ‰3%d!vAGyW/¢èòµ$UqsŠœ˜Š*°nŠ*†‹¶’Iˆ2|Bè"m‘a´ès'׉5ff¬¨bd¦3¾4b€±; RÌ4Šñ8Vu ¤‹*662 ¥ò_öøEoæ…¶â7t`䵯³:Óˆ¸X/È|àã|ê#?暈Št§*P…•çˆŒWv\Žþ¸r*_{ðÂx‰.K#‘ùŒ7Œyz—8UD`…qèEcêÔ54‚avÃbt¶M§¥í¥’¹†t‚Ñ-‡Ó5Â3IL€“lH%Mô3.ä“X.qpÌÂpˆ2؈“i2 JIa~WVLSµD­”{ìW@è5_1ÆapŽC7‡¥G xÓ‚1²²1OE@ep$“l^3m;GÃAC!Wù™ä#'Ñ1]xù'w_ð!0‘x F] r—'È6r ˜'iàm‚Ø‘Tç @˜XGrUÇ™$àaxŽÙ†ŠçI˜†Iê­io}Àx=r2È6p¥y÷‘  S‹Ó:Öõcík™lMI{³†>+ÊD<FN“4J“‘}ÓÔDòbŽ;•fM+õRöÄ“ÆÔ~uOIÔ5èd-'ù?µ¢œê$ôƒYBf*–•ôgÀ6Ãå5ÔùD­æ;á5‰MÍùäUhpgS”ÉDojˆ;ºC['lÆyÖ¨,–U4t<¿#3ו•Ì”Tÿ'ŽÌ&mÃ7Œ³MAPVç|×6&=2]hYE¢·„ƒcQ[H=Æ“j $h„v;*Lq(‚ À$h‚ 01°‰Æ¸™åù™…ÙxЊ8X,÷¹ÿGq÷¤È¨ŠP÷f{W *AhqÓö¥A¥5_kЊl'§…§Š e[€¤%¨‹ç0£txY‹é¤mŠDIrçžù– ,à‘™ƒ ©Iš „x§9p©¨ö0 ±I=’©‘›ŒRh©1Ú"?9ã"‘(ñMmf¡Ã'`£Àao¢PÌ’nZv™ˆÅbÂQ42i«ŽT—زCoqU'ñ_àEE`–´«„Ô@¥—ŠÂQKÐ*Ÿ$£¬@Æ,è·JyY{›"–F–F)3Û%Ÿ0•%9š7xù2|ÓÔ£kÐKzÁBÀ*32I–âÚ1(@„¼:±:¤Vl@¯6‘TÑ)xÅr,*Ak(†ÂwK“캒@£.µ­ÛKê—‰)y+æç•,±+ESp3v‚''c%¸ä0k3’ÿ#¤DA³b Vžqú´[xPT²L<+­ÔúVÖŠ­q”N’# PutŸ­Ÿçõ­ç–¹:»ª+Ù¨™¤­¨>ߊ";|42mº: Åئw"v?«S¦qÙµ0õ¶QUW«Z¥7ËIb£ñ `·,")x+)j¨¶Ôö^ë¶`kcºie!!ÿÓ^rPq„Z)'ƒAOøOÄ9,zo0S@ ‘Uä2 æ:pá4á”-¶ò´7,.E+÷—q]lAçS1O¡)·eŒNÕkA%«S»¯So`JC$¾Z$ƒBÚ‘}®'Ó´@×Pà3ò5 PO`ݳM¼I•hê}Ó—/ðyTEÕÃJca}½ùv@ryuË-fá0±\ØÒ" ¤jêžfŸs (ŽX¤#6L°}ZŒ%4 e‚3frRʨf%“9€Vq¦“ZubP1¬™*fPÃÇHjr0©‡+‰‹Ã9왚‰Ãµ3š ApEyJÌÄ p$±2p¨Uç-²G<µš‰Ål Å0c8àqÅ_Å×2sš– ·Â-,*mù:œ3üs|Ãu0Ä”Šr<ŒÄf Åey%Ì/@ËÆ?œ¸0LÄ'WÇw|2y<©œR GALr‘|Q|½“úÄ(Ø4,ª0KRPAÐ7¢LÊMz¡KàÊ£\Ê  œ „ªoÊ9ÔË•êÈj$ã0] 3Ù7R®f»(€ëò ÙõqÅ2Í‚_ƘOú_ÍŠÌÑ,bÈ’ORÐK ª1p7P4P™ª ð©DÙEµwBc¬™x`£„›*Æøñ…¥bU‡ö|@­¨ÏUÓ“˜åu¡ÂÂ?F®'ÀÞК9ÏGgÐü,¸¹D™@YõZ pœÂ9ø"Ñ''ÝŠ•Û‘ ãù?bs@‰¼öÛem°=a{r_‘Ò*¦ ñ!Ø" ¡(}Ï; r>}ÑqÐmÃBÿŒU×KM^ÄR@ÅótXظ¡IÝL÷¬ÒêëG„¥¾&dPÕqÓÚÓ52ÔŸäzÔ”Ôz Ö¾t-¯È€q`—œhpÄ*f¶#aV.‚kYô!«"ÂO÷‰5sÀys`€qÖ…Öù\„*Ò&>ÓGÔ)“-Õšéví,u>ÐÓ1pÂjg‰ŒRx;»?ÆÚÉçÍŠ('A#š½œ­”žÔy`×X `ûo$Ï9c¸ö‘¸*w«bË?š¨›Ì+•^ólè_Y;3í1¨ÛP²—Pz0ô1`)©½<¹¬*/ÓŸ€fBØ/!Ù€ÉJ‚ÉʵC‰÷}5ùýùýeù=¶•ü‚0kq´üÒà8? œÈ4YuÛË2?Š°Ä×esŸVsVâyž÷ 64Ød÷é/™Ø-2mmZéÊKÌ^ã»ðÃ}©Ò7ó?:E±EÛ„Qa È,Ôʬ ª oh¦E3$7%BÛDKSçz5 ÇçCO`î:9”3©‚ –púHÞ˜]}íç2G‰‹®pr^_õèffw±¶“w.ø‘îµT$c:Å\½ãsmÐÆRÿ¹é*ÂöDèý9—Ôn@Ó3Žž¥ÔZTi>˜<ìËnìÄ®QÊþ!¥¾¾r ˜$åá˜Ó:ü¹¹Ù® }™“P#B y·²àÿcÚ7Ae¦Z¹ÂRÓä0\3ìæã¿š¡»\#î­#Ó‚¹»سïí>p-¡í2Ô=ª¿môFD+Ó‹¾èKÏ%y•&î¿í^00 œpL}ÑOl C¶Ks!f)µU7ò24Ï'Çðª•G×þU†Ã@«¾$“F ÄA #iœ77MÄû¡ô3·ó¸VR--u`CŠmQSOQBñch£¹ÁN¥Óž•ÇE~Xéá„õuØÃöf@ R3¼F3uÁ5¬äJÓ’q’põ?¤¦ð` Q¯0±¥wŸCcÐ=s„BÅJõ$[S”î÷ÊÒê‚>ÌrÓ‡=fùe0ù¯Âú˜ÿ¾oAö ¡"b`Ïw¯w²E½9y¬R ÝU€ÊU¾k‡véú[,ó*µÇöD™‘­‹ü)çz§bv^&³qAJÎ…ý'eìö!F^:UÌ9½)hvk0]þ­DÉ̤þZÕ8¿BJ“aÌQŸç¥Ùc€bæ‰ÈÅ‹ly’IÇxéJÒܦÐoþó#Œ·k’ÁxqCŒ÷e7Äx[!Œ')7tíOPø¹'Ζë—®TÞw>*²Cð«{‚j—/buÀœZsEôàxkH)»5CB«'ü°Cÿ<ë¸i{K¸Ö.X´ˆýc<ë¸i{KÇò3‘®2}f)0ßfPßxéJþQ;Â’™Wu"(fð­Øôìn°!!Qßd¹“}»ŽÓtÞvÈ* ¶ ­þ!{CRu"aÛ£È*–Gó§ò(ªöÖ]J=ÝòH€ä°î¡÷p Ú'‡NˆbtGö¥ížóìÑciÀ‘ԃ܈«¬­­H22]*ɧ‰!8bÝEI Sà`è‚ìMKI SûutÁ=ŽÏþ43C&@}ÏÂ.Ñȸ*À.‘xDR0‹™ÏC&@½ê ‹2Zñ1ÌrÖ„ÑÃâutÁ=Ž3S0dÔwa¹ê,γŽ›¶û€šë¢Õ .r°i¤“$ã)]‡ÜxѸéŒcD¢¯³†ã¡t@QCÉ#-,ȵóÎ]|@IAÉ÷à •\¼óWÁüt¢‘Üe-û )É­o„D ™×ò!;¨Zc02ªe€õÃuw+v ZäPŠT!²;ŠŽm0©`¡E¥?LTpàÃöaÀGu#ôùD(P‚GN@êR‚GðIpN0!0p%x_Gà™“\Ÿ6%xIàT@‰WÁüt“:Éõi(P‚G@EðÍ”xÌO)0©}à™#±ƒªE=0p1XâÅüt€4“ Èê3pȵ“™qt$×(P`«‹Ã,Œá7Þ>‘–4þ;AJg0;+°™ pAþq+vn‡*^ȼƒp°0À=0p'ÐÞc&`+p°1À=0p}™â…Ì;TÌ=0p'Or╯(ê"-Ààx$%­yÔ¾w"“*^ÈŒ„¡>0pN@I SP"ÔÒ´DR0€%^âõð:1 ."ÐLŽóC?x½/C&@"“*^Œá[@r°+ÀgDŇ*^}@r}@räefÏþä1Á<3C&@}SÇ.±„!+°¬1p"ðy’!h-ˆ[@r°+À'/pgrðy’!h-ˆ[@r°+À'/pgrð˜õy’!$'\w+v°10©"’2?”-Áñ{Ót€üy~[kO•è p` @#Ñ1°Á·2;+°™T7(ð¤XâÅÓHf€"Ps Ñ!™“š¬­þ“šä ¹+0©T7( !0p'Ð'0)^·²ƒp“*^»ú!uPÉâÕ$—4rÌ=;`+p°i°˜õ³+@/¶Ê,;[]0#Gr P5fqop—"^T7(°+@>0p·"$'^ ðð:1 ."Ðô³Þ`ñ"“*^"aÛÐê ¹+0©â%ˆb±+0©âµ«R•,^Uc'P'p)âU5fs'p)âEu#+°ôáw+Ar╯(ê"-P2^"cŽí>DR"“*^²ˆê¤p€ ¹+ˆ“*^ȼƒp°iÐ=Ð8w€%^⥑m›¯ÈŠ$'^»ú!uPÉâU5fqHp—"^T7(°+@>0p·"$'^ ðð:1 ."ÐHŽí>DR"“*^ÈŒAÉ!Ð'Or╯(ê"-€à8?íÙAê²Çëçz3»åâÙè")0©âõ×ô?pò¡l(Ð+°)0©âµ«R•,^Uc''p)âEu#+°ôáw+Ar╯(ê"-àØîC@ %)0©â…Ì(PÙ4$'^ ðð:1 ."ÐAŽoõŽnq4.o g:ô?p00©âµæWáa®à7p>“*^¬ýc“*^Ê1þ1¡Hr⵫R•,^Uc'@'p)âEu#+°ôáw+Ar╯(ê"-@àØîC@ %)0©âŸþáʆ ¹+“*^ÈŒd >>ŽmXâ%^¯(ê"-@à8?AøFl )0©âEê3pVKr⵫R•,^Uc'@'p)âEu#+°ôáw+Ar╯(ê"-@àØîC@ %)0©â…Ì(ð”=pò$'^ ðð:1 ."ÐTŽóÓž¤.[q¼~®7³[.ž."“*^ þèçʆ ¹+“*^»ú!uPÉâU5fqlp—"^ Ù7p´-Ði°˜ @râuA[]Ð'Ð'0©âõ81p+(`´iÐ)° @râuA[]Ð×Å“*^g`ôƒ‹“šUc'Ð'p)â•T}Ï+°“*^»ú!uPÉâU5fqxp—"^ PÏ÷¼+0©âµ«R•,^Uc'€'p)â•}Ï+°“*^»ú!uPÉâU5fqSp—"^ @Ñ÷¼+° @r⵫R•,^Uc' 'p)â5˽+0©âÕÓ÷¼+0©âµ«R•,^Uc'0'p)â¥Ô÷¼+0©âUÏ÷¼+0©âµ«R•,^Uc'À=—"^(WÑ+°“*^¢ÔW×H=p00©âµ«R•,^Uc'à'p)âÕ]½+0©âÖs=puÔ“*^»ú!uPÉâU5fqz)â…Ö½+0©âµ«R•,^Uc''p)âÅÓHf€"0 àØiP?õYEd"“*^»ú!uPÉâU5fÑk'p)âÅÊƽ+0©âµ«R•,^Uc''p)âEu#±ƒp°i°1À=0p'Or╯(ê"-`)ï™|yÔ¾w"“*^ÈŒ¿Ô=0p'ÏÆâ•ÌÍ"þöQw)» ´ƒª5êR;ÂöQw‰8©âEu#ÌÍ"ª€%^╯(ê"s»j!+£2-ð "“*^}@râÅÜ,²¿}Ï+°¬1p&pA[+‡*^ pæA?¸8© P5fqzp—"^ P×÷¼+0©â%ÚH=p`=ד*^»ú!uPÉâU5fñÐ'p)â•g`ôƒ‹“ŠÖžþt)╬­þq]-û( -€"xÛ¯?‚@S'^¬­[¬1p´i°˜*Ö¯?‚@S'^ØlðÔ ­[¬1p0Њýú#4uâõð:1 ."À9´{Ï"“š} ¸x)â5©}à™#r­"=0pa&@--p€n&P*-p  XâU×÷¼+0©âñ8;¨Zc02ªe)0©ÌO(pò£™Îµ?^4BiðS ðÓUVZÜÿUH†ÞT`I-@™Ë@.{`¡l X³¼c§*?Lp ZäPŠT¡.ny(ç00© å"á ¹+0‰rAÂ??©T7Ç<Œ¡Et‰Hrâõ?+0pôa"''0© px6>0p'Þc&A2p'`'Xâ…r °×å Q" pap)0© px6>0p'Þc&A2p'ྀ%^(+0p]ð%''“šW¡$'^¯(ê"œC½äL9c~Ür )0©}@r-ÿƒn£™ûÎütàˆ ý( ('‚Ãìì-TÉ ðÃá0yt¬û‘$—o²( {C"“*" Ð(˜kî÷¹Eêk^“wWƒDªÆ³@Nc$×~6GoS5#ˆF¡>œjN‘x—Öä’"$×(qä'zñ:ãBo«~'gP9¸fOsðFXCVÈ÷Mrõ4#ßn€I™3€¬>죿F#Š5ãBo9G?$gj¤åý‰âì×_t@Òã0z=þH¤jd~$WO¤A ÑA½Ä*Xäúí×ë p` ÐJ¡B(€÷é&à8œ“ª>wyŽÃ€HPGÉêȵ“1<(r­"&`-t>p"8 ˆtu”<¹™JQk€xŸ.-Ô—Ñš)0©T7(àú(€÷é&0ê€%^hÍîª|ðó“Úž9(ÀógÐ=€&`gQÑ=Ð'Or)hÊF¸õ1Z( ¶ ­ê"¶=Ze“Êü<)0š™!³ƒª5#£ZvX” Jg0;$÷Ãuw+v ZäPŠT!²;–ìì3cµ$ZäPŠñÃqA —³i:á·9©¬­þ“:D^† ɨ¹\7”$'\w+v°10©4=;‘¢•ä0’»·`K22=ŸIŸO?õ¸ã Ð(PД%qy á52™÷2ÀÔ¸u((]Ôx¸ •$×(4b5mQ0Þ  ¯¼jVŠÒ¹g+^ÁQjjkà=©ƒ•$÷ïì-åÓå|m»SÀ€•–UcßHr@§@þ1Þ ÎGðX;±ƒ cÍ)0©h­e°(`~®.)§@êR;ÂU{*‰8© ÐUˆ?L)`U{*êR;ÂU{*) .&àç)0©@§@ °W;ÂU{*)0©¬Ì"þk<·yB)ðFH„U{*)0©T7(01ª€%^ ðð:1 ."0·«ö±2:!(0?!)0©h­e°(`~®.)§@Ÿ)0© ÐUˆ?L)01Ÿêb~ž“ t +0pU{*“ÊÊð /0pµ#(°Æs›')0©h­e°(`~®.)§@êR;Âc›ˆ“šmQ…øÑ&0¶êR;Âc›êb~ž“ t +0pµ#(0¶)0©¬¼¸áa‘o„D(0¶)0©T7(01’"p  X╯(ê"s»j!+£2ó£‘"“ŠÖJQk€&àçê’r ¤.c›“šmQ…øÑ#)ê2¶êb~ž“š4‚8ä&01[Pµ§²˜%Ò8>0pw;)^ÈŒ8´ms p•1·P÷~Æ€Î|@râõOCÛ6·Ws uág>0pc Xâ%^¯(ê"x-ÒS2Â,?zûµÀ!)0©â…CÛ6·WskýÉç#) 8´ms p•1·P÷WJr Ð$— å"(0 sKŽXâ•»ú!uPÉâÕýePˆ?L)01)0© Ðýe€#))0©(/y(à—)0©t, iLr"’#¤·_»:×´Ž‹ÝAê"5JÌ$WO¤RñGº(°¸i \£´Õz­Ù’>‘–Uc3p)âõð:~io"à;‘"à(¹{ ¶4Ì_yMë¸Ø´HTÿ3·y‚1"“ t äSàÍà|“ŠÖ|#^@§@ °W;"±ƒ cͱ$'^Oñ—÷;8?l°ƒ cÍ.@͵“êR;"Óω8©  P.‚(r ”ˆ“JÇšÆ Ð$WªJqÌÍ„()0šéüA@™ô{÷.¼Ì_I–à½Pí×—®T*HTÞ++ÌÊ»›}DÉP Ë;êâMæ\ Jžá™'©ø†ÛÒ(4Òø•FOùMðªæ0}dzÁü•Ï’'ˆ²räZ4~¹Ìz(r X‘Iß¾†Dà1r$GJQk€&àçê’r ¤.(pÉôBÉÇ 2Öœ1<(àç€Hÿ<0p'ÏÆ(/y(à—)0©³œ{Ñò?(pò“Ú$Q_aÍ é™#(ê’r ðˆµs¬ c͉Xâ…‹y(r ”“JÁÑò?()0šéüe^cä]s¬® J,}D¹Me?æ—ÞÇ Þw±Cµ¾. Ä²ÓhëÚ"tä&§¾×ä·Ç»[¥Kâ‘3å—]¸˜'p€{ X‘Ißzià1rž9q›Ûš9Ó·W}õWlLu#+°³i:!p `·I¨ÈÕ€%^ ðð:1 ."0?ôƒ×2±CÎåÙ9³Ë¶1"“š³i:ýF˜Í8p( ™‘o„Dz•˜HÉÂ’™ˆ“Ju#·¹m„ÙŒ=0p'Orâõð:1 ."0·«ö±2:!(€‹y) )0©}@r³i:ýF˜ß6›¦Óo ‰.+°¬1p{Ã#{ !0p~ &` @Õ÷ XâuÕt`( \@%0Ñ!#2ÖìÔ ­)0šé,F‡&l¬*D2¼pj«;¹;Û¤îªnâˆ^[ öÑK•¸½Ãñ?°{"m)ºÅŠ7ïú£ªæGCä{*rÌ!?g¤aÓ"Xzµ$á-šë4µUºÄS{i"H¸ðKwŸq¢á&!QøÀÖe3t°ôß—;çwŽa3.€PñB2r¸!ƒ"…‚= È)s&Í:e䀸(§Î: Ü°±RÅ8,ª@gGĉ/fÜH§ãG E¦3ÊžpØ„¹è2Á3f¾€dófLÑ4n@º™“§ È«âAᦠ:TÛ¤pѧЋ °š FÌ:nê´i£KQ3o4¢ð™[1;üÂÁ«Ù¡tû\±"ˆ ¤1 –}ç0}³¦œ½pZøÈù¥Ž¤Ý„iS&…ãXa€àÃg fØ `8Œœ`Ì›¨Pë”)šàdß•-#J¦Œâ¤h7JóÀ)"V'_Š`¡²{'DŒìŽìxÜáÊe~ö)šôQ3c•3Ó—ýh…_Þ¿ƒ& ê &ØY ™`Be‹ÅB{ø½—Vó—Àb+ÕÇKeÐQ‡nTÖV]}–cÖ…ñ]¨À *¤Eà±TÔ…±Tgü‚þQ—aÈ1FvPÇZbÌôp 514PAL…AF (Œ$†lœ‘R„½§ó¹L$ÍÄ‘GR„–IÉW›!¹YÒaØbbA%e˜‘’HM…ÁFJtHWFJs¤¡Ç¢&VŧD¥©‘Ÿ ¤Q”˜ µúE´æM…ÒE€)€¡•h ”eSñ-Wl´*‡ a|Ö“¸éö˜r“Í꟭¸*å+ÐJl®d˜jc¯N¤!‡•éF\Frä…B )‰àÆ!­V†"Äz¡¬YîÄåãy *R}™ú(9$B¸Ê¡«£­5îÔA–€¥ÒT´¦dª±&ஃX¡êÂEû>jaŸÌa7RÆãƒn‚ë‰ÓW2ã›W5Ç W£ :RJ±nr-ôÎ\èH·]S_k£ä@)è<_süÆìÚÊk„›U0ÁÌrd+ǶÝ~»Q“cP‡—FáèW[ÿÑ襳-G¼{þ{R(¢N¼ñû ^ëÆ«¢ð§G:ÖÄøäÆ1£ŸÁš÷<¤Àö ‹ÿÔ6ª6‘Dx‡ûJî—Áª¸:¦9¡®j‚*]%lƒ SŽà\ÝløðBøðim3! OSC²lu/L@ÌÆ73ˆÁJ4‘ƒûþ¢#¨ •iÒž¤ ùñ&†3$âTÚ¾dpy%ãUhCâœkBŠ2ceDM‡8×Û‹¢L€íP!°ñ•ÀÐ….…á Ü!ï'ÄÒˆ‘ŒeØ º`0á;ìáíHiŒ A‚„@¨1œjÃCY ‰Ó›ßÐ!8è‰ÌÃ⺆à‘9eˆJF^ÅÏ4Ä5/,Ï+ÏsËÊ4g0B̈žéTç:ÙÙNw¾ððHH˜°,&öIÇfRg{ÑäŽwÀ#ž_ñ†„sT¡ %œž™ëdƒpFé@'žíÄŠ¿€ÏX’Ç•ÙTίWÏ{²“:%’ròAy ç4©àÇk”˜Ê ›Cœ‚zSŽÜt¨¢:{òó  m¨AåËs]OKëJ$mB(ø˜sBWÃîŒõâX¨Ì–i²Óf±eƒÌaŠØÕ0¯+B]HÈ2w«\ymH­ŒR™ÚÑœ¢²”†"NM¼Š•Ž•_>½ßS1W+Í}!_sÌ0TI#_y"À˜g’Ítæ3"øB.ÉP®™´ŸÄ™Š¤2£®ËmÊY_eÒÀØ6ln{K¦¤X«& Œq!oŒƒ<„å` +NI×Hf&OeàÈ1™IÃ1Š«ao4ÃDÊ°MŽ4LZêжÌEd yÃYUÄ0¯'Õ”Fdòà—þ1è(—5ICl´œÄ6CÕ¥NX˜Ë3*–! ˜’¨ª¢ÛÁ5'O™½Ën{[“X—C(°–TÔ†4 ÿiÈC0Œ°oN7ÑÉ›Nb·ßœái§óKJ|#ÅŠ¸!%M‰«d¢’¡¦„Cd@šóØW4ÉäR4ÖTŸhÜY>•%/ipñØ2 Yɱar˜Ûb¨,YU €ƒ`ñz•hæfEA`3t,/j¹ F}–—ýêË1§ÙÌ‚­/Vú æ6Ç™°±2n€_”Êœ7#5š}©;Ô@A7+Hj.£`›_ûší•KCÀ`“òD•Ñc«b=æÈÁˆì #û£ƒ-y³<ˆ”g3Ú›ª¶/¦­ jYIÐÕz6}”æ8Â…z´Ÿ‰4&}x뜹¾¾†ƒ±›æ^¨Ø=83—EË›O å M"@}eÞLy"aX+ßx.—zÔŽI·±¢‡uç¦(zFn¶˜äù¦ mXÒ£Óð›9Tš CN£Œ±Ê„ èVŽ•¬V•Êì ’ìÂÄòðÝoRiÖë7qB^©‚…_+à²ÆYpÜrÔ´i÷µÀ¤CÆ–:HeRMìšÀ9KãxCƒŒ¯·ík+ÒÚ‡ $µÂMHq~Iq®ÅùŠn§aD?í™Óœ’Ÿ>*%KŸ&‚J¨ÃUÖÇ&CJœzõˆúqšB˜Â&YSG¬± wªUV7ÆÕ¤A¬Û0ëæq=ð('Ùƒ¬ïÚÎ6‚2cë~¦À:£ööõ@Â2™WÆÉupokF)9[˜×|j•È†½N¾óœViÎy£-u«_êèÿU†$v>º©‡}sб²7çøP×–bþ×(Õ§ŒGkë‡BóìØšЄßǘÊGk’(ðµNJ–~WÃélŸ Y€BøòÏaü %µ#ƒ|–öåúK¢à㈕æÀ”¢4•ax_ }Ô—Zäço/âop_ûÕ\~.–Á#ªÁ3ýô]|Ø'|RÕ}eg<±ÇUGVebÇ¢qEád*Ø7±ÄbIfeUódVV2VKTvƒ+ø4:Ø!i$cqáydE–iŽ%"œv¥FYogYõrar—Ù‰G.V”G™”wÆÿÄ¥";yHÙUÁï0("* æA#V%¶T Еb&X6ZI…#" R… 'îW7aŽïˆhÉ'*u²v)Oˆ¢(»ácEt"bw'[ñ¤–!IZ{¨æOAˆ ‰PÏ·th‰wPŒx ‡n7…‹ª(f»s¾øN&Œ·u-á£-0Ð-u0a*Ñp`^à2ÛF#•c%ÑÏÕÑ5l0‹—y1ßhRÎç#%*¡iX™¦*œ’w-Há4eü&uàgäE©¢^éç©a)Wõ6aI¦Bäiþòao;æey0‚>v²vDzŸ™BcØò-da´Rù(csÚk àr1…#aây¸÷4àf0GÑ#”0`(j¡#úÚ/!)i* ‘70þáZ|ù ´‘Á" °òD¤ci `/Ë¢/qK¶£/â£u¤Ôp‘±Dä“Ú‡$± ú]0 À£Lꤖv.ãf v½†*åÉ¥]ú"sàpð{õ  à$U Ð&¥…žå91tð-j¡0† Am -ú%ÑeaàsÀrPÚh¡¿C¢âÂ(~j€*¨o ¡r¢(Ú0+ ¡ŸºqjÊ©ӢιSžRônÀm,çMGC1‡*wH ÀrZp«¹º«17}¸ª«±bVr#«´št0Wr>U ñqe÷«'ÆrMB:9s&ø*²·¬TU,ÍÆnÏJ­ —bÛúrâ1׃EqU}AvÔÑÂÒVUõVÎöÚƒ6‰òšjº¡òJp4Š¯ÅR°ÒµEw1®¹rVRj•»,o5±W-Y±nµ+™j,½Jo[2Ô{5iE7œö¯ð¥]½Im×ó²ÒAÌÄIÖA€N÷G/$¥µI34Ë$o€)ßVÆe³H{/´SA‹4Û›zÙRuZzµLÚÕmf…±ÌcˆÁê«ZT\Û^Ërû(b+6S^}±ç™*SöÓá{qž&ª©÷٩¯Ý9i¼EAaA&ð7Y5Uø* ‡ßÔ]3ÔÆܦßRhPôgˆÆ_íõ7†”yAS„^5†$#K2Êù$’µ“îs r6‘<Ééãom'…ï6wL€SZ°…!M¡^h°iÐÝVÊ1F}1‡4†}ÊÒü±Ümaa>Ü,ˆq7¨¤†žû1 ;2/9²Ãeµ“,­Ëe °Ìâ,+Y¡±£m±i[«Ý±ºƒT„"¢sŦÃ/²½: 3m›=¹åüÙÌú¯¯ivÚV›ÚW3ÜäªÚ;µ+ù“:³Í:éÁ@ö @ÈpÙÃfé_Yä$ *\Ä`rðÜü9*ã?Å£?Þk¼Ýdœ»H7Êý°ÇÒà®Æͱùê»ÞÚ¬KÚº¢;±âÅÂe ±4£ýd¼ß„ =4G¹=ŸŒ Bá­RŽÄF,´É̱OµeC8¤?:DŠ§ãbdCGT=I„ÞÝòDÉ_ó ?ÔaE^Qß[tßùLéÄZ¶UFú”Ýitå5^Dr€É£P1]Q§xÐ$SÁoÖUQKŽ1©s †ÀÌ^½ÕHª1poˆŽrÈÛAö¨³Ýhå!µR{ù451.¬ôÍጾŽA è }_ éÞ¸Oý¤‘@Ýèà&nžŒ©v”þç–ž™î囎JcPÔžΠîç¢nétèŽë ðŒÑ8wxçÝÄIãWQÜçåÑ©Œi7æ/2X jæÔájÞ(KâæmçBûÄIÚ”ܶPB®B¸´Qxj”•jÚ~mx=J<ê¨h1$H¹?£2]Û]ÄB*ãÌ‘á×]°uAÊ^›¬áï€-lÞöCÕÁcÀ›( ïmÁï+ðt[¬9øw/Èõ­ Ò®ñ{œÌù–úЂøºœÞ#L%œµkÓ÷UΚOÒo ÷ÑlúØÌÌ/÷ŒMÍdpͬDÒŸüPŽESÈ Ç\Rl°á‰¶4çsýàÿfîî²×CÑ×%%s]×Z€Í‘1|½ïÿóo×€ !qRP¯ôrõöÄ~†‘å‘rõöÄ®(Ö±™Š¤éeü8¨‰Åª9¬ñ‡þåYá³ÝÒ».^l@]ljf³Xn!yÓXíô‘ÑœîÛž}ÎNºÇ;äL;ç á¢]TΒᤋ±±âÐtÀ;}(ƒö*r4ˆ(»Ë¾Ž›ë þÛç ážÍ»Ä퉽MδsÎ.ÚEeÚ[{:Òʻı±âÐtÀP£4U7„ü 30U·»È[^nÆRTûŠ†´U ¢ Ô†¿åå“?«ºE©áÅ]!=”J†JÁqCˆ7èZTÎ’¸[uû1•DUGT­{U‰»U·ïÖ vF€ƒÃªÂÀ‰IOòžQG'ÅR:$œ(YŽ} 4Úqx,"Phˆf¾رŒ,"ÐÚ+Oá‹¡†~Ä P3eFr €’Î oFr €ùÈ àD[ä‹aÔÇ ÷–o²Hr P› P›F5áÞ§ågÒщÉÀ‰IO¢>Ñ hÿëgQ9ͨ‰Åª9­I+ÂXÓ…x/øœå‘4IãšX,f(°‹F“÷œ/Yî¢Y–ŠX,f¬ù¯¾.RÓq~é·~Õ~Ü®ê¢yš©ˆÅbvœ“Ææë-„ø¶$»8<ðO½Hr.ÿC5Ÿå¢é¢IÍYÐmdž‘4ŠQR‰’åXC!ã1y%•('eýwí{¤†é·~rëEšXl×¾Gj˜~ë÷µ"pœ“Ææë-¼J3i=”L6ãEhÿë{òÊšX,fhîaèE“WR‰’å­¡¨‰ÅbÿsКö‘(Yî¢Y–ŠX,fðÏ‹²ñ‡þåYî¢*b\ÈEÖ%|ÃôÞdJñ$PÝ(K¥#\v–ÑlÇ4ÖÃr_Rò"O€^)ÖÙÒhîaÕ$ï[óR$Ñ5]@raYMˆ\(Õf½QÝ\.àCè-`Öh_’<”hÔáF…f$cà¦A.òî¦4¦²ÈFòËl¾Þöp¬O²6‹~(OÔ)á.à)à>Ôg.$ŽV(Ö!w0L2- 4¦²ÈògrÔáFõä¾i_\‚”æ…^.¢Ä ¤G«ÕqÚ(æîƒ2Pýp¬O2]@raYMX}B‘>¬.²Þ–ÖAÉhgÀ4¦É™y5AïYMX}B‘>¬Ac(óg.²HAcÇ4¶6®“RÒ"ÈÕgyhú•'YýÞdJÖ!4¦Â戂^rONÉà0.R§EÌ^®c*lF%@ra1åÓ%ÂsqÚ(Ö!G«Õ]ÇQ!%çÐtÀc@;BÛ(öbÒ53b€ß“mb J@èÜ—ò™Ñ üœÀ3“À2pÄ&ýÑíe%ÝщYû‹?$]–'FwÀÑüaíh…iÐ0à¢rð* u›c`™ÑŽV(.* 4q²Ýá€RÒ˜Û=UŒ)J3z°b§:zРJ3zЮⱤ4Èä!óé:¦ÂæÚ?«àbA®J3z+¾(s õ¡@2怂Lo¿Äݽ3ì€2zð¯J³Á¹¡H¾(ü@çýûÝ¢Þ$lªÄïÐt@ÇâÛ =JóJ3z0@4ýuû¡³3.p°J3z2Iûóé:¦ÂæÚ?«oؼ߾(?á€2z°ÛDz¬¥&Èäh-ƒ‘jrP·9†c|w3ÅútªƒQ2rPRú²pÁ°Ê¡g{PcàîžÁ$aüv›‰Rõ¹oKb3ÒõÞdJA¶gXtN†( %¥/ÿ±TçÕ网"«¤Ò¥ïOú‘A8gU·Þ ½‘1 Jš§W}ïts¶{½=U·Þ ½‘2 JZ9f9©s®'fAU·Þ ¹(Ð(Þ˜øMÑÅ\usJN&¹tç5‹o¤g{}æh¦²ÈÔa3ô…æ¶yÚdh pœhFr.ÿ"¡½lÀÈ6$7›ÿ¡k`Eëm_’<”üäògÊ\ñ¦ÒÈVÿåC}Öhf½™ò$…¦h–jp›t ÈUo^ZÝøqÁÕa3\­(ógÊ1ûaÏ3G«Õñ¦ÒÈV5R_ÿÁh“…¦h`{öµ[RúbÖn0zæò/2à,ÐÆ×SMD†ž×µø=ä¦aÏ3qÁÕ÷SQ-öþõ$/+_sÐC/r´ZÝC㶠`.?©  üë?ÄëµrPRú¢œqÑð/ÿtíÿ¬äáZuþÛÿL8QRú¢œqA—¢¯ürþéûIµÁäûâ³ËªßøÌUç¬ùy‡ýÒ,þü5ˆex³jÓÔöI$%¥/Êm07aÁ;u©E{‘(%¥/ÊmÀx7{†µ†Eð{tæ[QrPRúbÖA˜’à'Kƒ¬_tN†( %¥/Êm`¡j˜~ëwSz¶gLM@¦ibŽf*‹L6Óh}ŒfBÛ(æÊ\(£¿Œ^ìC¬.àCUFEÓÕhC¼TOÞ!qÚ(æÊ\(s^õùp¬¶gع³ÞHÈê‹Î¯þè²Q˜þBt¬Þé/tëÇH¨þBt¬îê/tëÇHËhëŸîSÒè‰ï:¦Âæï4¾\çöýe˜ÇŸÔJíòàE@¦ibLBJc*‹ü»à(cn{Õ®c*l®È5]¶g^Zm?AcÇAæ\îM¶g•Q.pbÁrV#Žf*‹üÞ¢ÖÔa3@âr³o¿¡È¥[oÐ Ðlí>0\#†f¦¿àfzÕ\$6[¤ÈÕoP$)¡É™y5A樂àfzm¾!—ç‰@ra±EÊ\è5_ÎvÕÔÑ 1ÄKEP­4¦²ÈÔ1ÄKõäògÊ\qÚ(æîƒ2ä¥\F_ÑÕlÇQáoã!¤×#%¥/p0JsWØúä:Ä¡g{Pà¶P½éO4î~´Zýp¬$çò/âáJÜîî#Yoðø\ò€¶gXtN†( %¥/ÿ±TçÕ网"«¤Ò¥ïOúøŽ ˜jt!8 Ht2ÀçG®Ë?ëDúNX}B‘>¬Acoðø\ù©ÅÄÈäwðê.ëP¢Jš§W}ï“©Ö3 7`8 Ht42p6ÀçG®Ë?+wpÕ €Õ'!éÃ4öÏ%‘ŸZ*°{½=Slwðê.ë÷­JZ9f9© ®'fASlwðê~JªÈÕgyhú•'îã:¦Âæ º>AÃæ$çò/rFr› Qo^Z½p1åG«ÕÇ4¦[oÐÊ\P=/Ñ54lõäQ. $6S~´Zýp¬dn ÈÕ]a04í;]@raYMqÚ(Öæ”A^r ³O¬dÕ]B!¤Ã>ÁQ`{öµk’‘!%¥/ 7SŽJqÚ(†™-BÏ[¾(?á€2z0v RÓ(`»+ô¼¥4?¡4s c‡ß f`)nAJÄ f`¾(AŒÃª¢Á{ååž–ĘÂÒD{" JPÒ+jÔ¶„S¨iN(ÄñÖâÎY'rîûXBÏ[_˜£½åÕTBÏ[&ЗYÕ—F_^Ä….!°¢f°Ôfé/fa04åuöI…ÃËCS^­)a04åU.2šõ¿ß-ˆ\´ŠúŒÌCã¶6$CS^³Xª6J3a04å%Î (B!~_§Zvð‚ãb§ÃÐ @ϧ5B¼ÄspÀ5’Ôk’”2-˜‰Ý‡þåYŽªÉsèŹ~”<‡~RÖYä8`m ô¼µâÜdôåÅÐ ðÎrÏq&˜Û=M ß² Â< e³Ûf`Ί.l±Ôá@õ”S3Ó 0çŒ(áÖÏô>kÐ=ûûÝ‚Šj*BEà1³HÙ†nþÔ!-`áæOõ”S-`áæOõ§O"ŽáæOã\8‚Y†¢!ß²1°{neà> e³Ûf@Û<ÀZ6»ýaæÜÍÄq¿ltëœ#݌Ѷ}±âƘgðËH·8¬*A/EC/˜ÒÄ`™ÑuB^'ìÀ”¡ÁGlÒ º¹ÄѬÛíe5Ñ Áx´5ñ¬QÓÍÑ`7åQ;ÎB÷‡^Éǹ”5ñvë[—#Ù‘!BÏ[ñ%¹¤©B帑їxó˜YÐb ô¼%˜Ÿ'ƒ¿±âQª5ê2Î…#˜çÌ(aÒ °1RPAÐ^–M9spÄ& P€«E0%Ýщ)0öDÖ <±þcà> e³Ûf0)à²þc`ZÖ·ž2±~=o`… >â³Ë}<KŸ]}éEn\Opð-ÏAÍrPÓ–L½¶®gXbð-ÖÁ eto»®oXbð-Ö!ãq=«EÍr0½Yô¶ëq†¸y½½¾®wBÔ,Áv ëJð'DÍr`Š¢Xߤq. æ“jëJð. ßÂyÈÔkëq¬TRbÙÒuý Ž0þQ;êàÊ.ZÖ·ž2k`¢©•GAÓ 0L"÷)(LòáÛ®Ž!°£„)«µ,«n4ÈUÛÁâ³ËÌUç1g>—ëEŒ±ZÔ,oSRbÙÒõ6%Í$5ÝÏį òõ|sõ§¼ònçRO½©=o¿Ä)`t¢qŸå{–ÿ:[ö´Œ«µåÙoà…ñ@éQR(‰Ãª²Ý `ÛCÄ °1RPAÐ1Éq&˜#EMàeÉAñBb!9[ö´Ü¹÷ß„{õKmã\8‚iL[•³åbð-+  <ÀZ6»ýaý“ÎÝLRϱܹ÷ß„K\R_O9Õ¹÷ß„{õ…ñ@7Uk¢‘S›õ¿ß-¨¡¦²!ÔQ3‹ŒaëzBÔ,ÄáÆõßòÔ,$%pÙ•¸ZÐÓkf°®ÎYOqú$æ«?Ûí`\.\O½ÙßêrÅY¬ÆB¼Äj|Ä&  áןöòª[0A ĺu!ŸMŸ§‚ž zÏù’å‘4I}q\'аl`£@RÅ×C+G:Iu-€I E+Gúï¸ql@ÇÀ¢Ðä¯%t›KŠëZ%#)ñ_ DðNÀY+J+ã Mþt›KŠ[¢ ð_ DðNÀYð¯ã2 >â³Ëˆ\´gY·^4¦¦’Ð “¦è+ëq. Ýr¤Cð. ͯ’e.q'DÍÚÓr¤Cð'DÍÚƒù½‘è¼ÃK±$ÄÅŠ´6º6ü %WŸPÔÆ£Ô º.Ó)”Q´@"´w $~và2©± BÀK@ÿEàœ×£eá±%ò:§ùá±úDZÖ·ž2êÿ4ü %ÄÑvZ6»ýa]F6OãN1¡e³Ûf€,yýE Ty’ïõM:ç÷I%Â=Þ#!Æ[ëq.pŸðAëq.pŸ”ÑÛ ÁÞ-ÁZ¾íªMëq.pŸ”±=åõ¿ ! A¦JüWü Ç.ëJð.pŸ”Q"Üã=R`¼µ®ï÷ ı®ï÷Iý·ÝìݬeáÛ®Ú´®ï÷IÛSÞYÿû ¬" $lªÄÅzüçâpÙŽÖ.]P€«E=½fëzëzBÔ¬=÷ÝÛäìÙ¹Á)1A Äú¯ žS…ñ@çýûÝ‚Šj*BEà1^„âÛ =öòª)1A ĺÛÇ+öòª[0A Äúÿ˜/‰5±ðŸa/¯šA Äúó”2-ÂÅ¡ãÜÙH7A ÄšU÷ü¯ žS…ñ@–™!ÁU Rï,ñü¯AÉ Ïù’åX_àvßDPFК}/øœå›÷Ld™\•¡ =-Â%1«úJeä@òB/÷œ/®Û_;¼Jå8¬*Æ…\SÎýî@B&;‘]ÔEçìUEÒ!ä" p›YMX=aÂH¤@>aRpZB·¹Ä™ºÞ×6»±Ý‘£CGqmspÄ&­ÄôL\Ò˜˜ÂÒ“ô±ÝÒUž[p«X\‡LPN°uñ4v¦}A z=*`£Xq\tÌ<úDc°w$V#„¼YŸ“j£4"…z×d3w8­ u¦Eç~šóZžÄÑvS\5ÏÏïÁÄ-1c\2sÄ¡õBÄ¡c\2X!Ç'@m7ÅXÁË;!ÁÄ-1c\2sÄ¡õBÄÑvS,«âLÜ1Æ%3g@Z/tŒÈD3¸"ûaÆ¢c\2sÄ¡õBÄq¦÷×Â÷ c 6Ä….gúLüª ¨Í6*]åÉÑÓ"\gÊÐêéâv¢QgV?Ñ& §‚RfÒ­Ñ*Á À±ÝÄ)ÁÄp ÙHìÑ ¼+„­gPÒ˜˜"d¢Â^ÛvS¼å‡þåYŽ5LÜxÉ^ ‰<À r9L<Æ"*ìÅìªxpHHaSñO×v]P¨g€LˆvØ pƒ‘j £;!ø„oøqc|ws=gPRTQqÏúäjgPRTQqÏßeÍáâv²ú¼ð¦´3 ûM¸ üâî\RTñhÀûââv¢‚ð¦´3L×v]‰ËÀŒ =©u=gPRTQqÏú¹¡HgPRTñhÀû̉Âê Öè£>?Òøþ%ÌgPRTþˆÑgPRTQqÏ%ûÕ÷BgPRTñh@ }q%E_€§_2tm×Eð‘ø^g0$pºC×´+„g' p p%E_€§_2ë…G}!ÙÎ.ƒt=Èõ‘x=gPRTA÷×a÷MÀy·þ{—Y,1Œ_1ÀW,aXXž£ îz1Å[~è_žåXÃÄ<@5J×ÃÄc\2½Ë—Y,‘Z˜J,-ãx#ƒX˜QygPRTñh@ £„-€tm×EàFyjÆ2î @×v½~ÚDYD×v½~=ûûÝÂ×SMÌUç^t.‰ßøôýÏ%‘Ÿg*àOÀ1EC€E@§"aQ`¼7« –]'$áe°•cmÒÒmðpq%ÝщÉÀŒéeÉáÖ¥vÈ„bºCqƒQy»Bq¡Ñ+¶+§ÜÔ–wgPRTQqÏ%s%E±¬M”¹°EóDzmÀx¬ÔœEjzá-ÆQygPRTQqÏ_wÎÑów%E_€Ÿ¯ÿ¶Æ×ÿù¼q%E±ìƃX†7«‰,ÛŒ÷{Í™ùUÐ[¸ÇÁ”2-˜i ¿ß-aQ`ÔÁ\u.?*ÂÀŒ©êYõͱÛíe\óYŽªÉsèµöÓD‡Ésè'e˜O)Ó"\UÿK8¬*ðµK,á&ýÑ­,qÄ&ýÑíeÉ’Èq½rU˜‘j§;ŠM_€§?S˜Qy§;ŠM_€’õ¿ß-ð5ÌU糈…­L 1È„bº£ØTQqÏE¨;ŠM±|Œ»¢ØTËdìQ¿q5Ÿåþ´™)•ö/M¶Æ×}ö*pº£ØTñhðù$µ)ÕHˆ•Q›Ö…­L W2’—9\‚L{7E /9g,A—aU©*qy»ÁÀŒéeÉq&˜ ¼+„­g“¹Ád™\Õ²¬¥vÈ„bºCqƒQy»Bq¡ÑãÁ£…‘)OòepÔ¥½!±im§þÁ3†raðŸyšî>©µ†z p%E÷üòlƒQ p%EèÑ’!ÁeLg0Õ­;çyc÷Mp9Æa¯gPRTQqÏ︹,>»ü!¾\ç^Ä"NðSA0HPDp*BKä“ñžŸsÓX-{ö5-˜)*tN†¾.R™{ÞçƒèTÐŒƒ^‘;+誎R¬¾èl@͉eƒ~é\7éWéÛˆép¨ê(Åên™\RL¨p•¾¨‡ªŽR¬îê–™!Á%Å•î™äD͉eº.Ôˆö¿¾G!oè4^칌ÄÑœ ©"Rúb!ÄK<<³Zv`Š‘šX,f¡^t=´"Œ§™ŠX¬šsК´"ŒÚÔ!%BåwÏù’å‘4I‚šX,f(°‹F“÷œ/YšX,f¬I\Y–ŠX¬š¼(‹Œò¯+ÙãÑœ!éã(ÿ“&Ϲ,~Ø2€ÃªÓ3 + À)ç|ÀãÜÙ N9àÊ.ô7·??¶½{½§âˆ+s™ 8»},ÿŠBD@¬™ 82;W­ûªi°Í ðA Äšõ¿ß-ó]Š\$IûûIE¯šô\-^½™]áÇb…ªHEå,&P¨à#>»Ìe/Ðl9õ©xVÓ™¯¯šÛœ7Ī«Šäª‡”Û Ú¬C@mP³5ÜŒ®ÁmΗ;¿½QÔfÔüÊ»Äí,‚L{™2W­ûªi°Í €¬ÅJmP³5ÜÜß×ê[£O@ͯ¼KÜÎ"ÈJÛÁâ³ËJþîA#?*‚®vpc»)vPu€þ&†,n\TEñ‡&€~®ì"=-vk ­#pœeƒVP˜89  °Ý 7Ò.á'Å[ÿaF¶Ý¡ž°%[aÌaI¼ÝÑÄgÒщ‰)ÿ™XöAÈÿa·a|9’.ÿÑ!7ã((rSp3.ÒeƒVP¨MÿÑ!7ã(_9Z°õfÐeÿ™é[Ñ®`Eòfà¸øî!°õXß³¿ ! A¦Jüp[ æEç” yp`Eò+öÿá±2Å[ñ6°õxó˜)*°õf-!¹ÄÑÓ"\{œ À¹°?ñ2ì¿&ýÑ qÁ”¡ÁŒ¿¢!_ЛÚ#]%%_@À-ãÝ|ŸàÍø+bð½9Þo¿Ä)0°,>»ÂêM¦Jü,œKÇ¿¢!_pŸÁwŸ2†¿¢!côfÐe÷™Söº?ð/]ý;¿ø+b›»Þøø+b€þP¡þ ü÷9ñêÀ3¯É¡"~2eݹDd!BÏ[?1Q1vAÌaI¼ÝQÒ˜˜2QÁÑüaÝÀo@À|Ä&  åÅѬÛÝo@6ÍHB4Öû‘Ñœ/ZRb0Fÿa(ršnÛ5%%côfð}×në@cn«OQAø+b0Fÿa ÑXå%VàÒ5%%_Лr@bàpF‡(o`¹åÕT%%_ЛJpP^Ä1¨åuŒ4ÖXåEgðËH·ÎIB4Vyø+bð÷©Cs=ø+bð½©%‚¿¢!_pŸ²%ò´^X‚¿ n«O4f¯c@cñ¿¢!_pŸËw=Ì…^ùLÒURb/sÌ n¦hŠ¿¢!ù&:BÌ!ô¼e¦húpP^$‚pP^ó'ݹD}!Ù¼‘øç n+ôÍîÁ³øFø+bð‚JpP^ÄÁ\Há•óZRbß©ƒJpP^ÇHc-€pP^Äq¿ltëœ["Oë…%ø+gðËH·8¬*["Oëåž–ÄìÀ”¡Á z=bÐK4ÍéÖ¥¦À]ãÀ,]È$]%%èk¹\r›h€%øËÐ °%ò´^X‚¿‡ÙщiÁL|Ä&  14Ö5%%_Лa¯ø+bð÷Ù $Dc½Íù¢}ùLÒURb/# n¦hŠ¿¢!ù&ú¯BÏ[fŠ¦ø+bð÷¹bQA"úÔ&ݹD}!Ù,>»|žpà¶BßììEç‚¿¢!ù/¬ñÚ—óZRbßø+bð½©=ÒURbð÷¯%%côfÐeø+bð÷W*²%ò´^>‰¿+v˜˜ìÀ”¡Á¼%ò´^X‚¿+ åå“茿 ­’9ø c/ÃaIlÁLÌѬœ²Þø9Ñ["Oë…%ø+¿¢!côfÐeø+bð÷™Söº?ð/]%%_pŸ´‹¿¢!ù±¹ëŸÙ‰ºqjÊ©ӢιSžRônÀm,çMGC1‡*wH ÀrZp«¹º«17}¸ª«±bVr#«´št0Wr>U ñqe÷«'ÆrMB:9s&ø*²·¬TU,ÍÆnÏJ­ —bÛúrâ1׃EqU}Abin/PORT/nm.c.Z 444 0 0 6615 4634750220 6337 Œ#Ò˜qC¦ŒlÒ¸¡£`0tÒŒI0M9 æŒ3' ™-]@ô!Š)Ü´q1 7@Ôx#Ç 6DìP0¢ A ^¨PB• Z€€#G!£aÚ”A˜ÆáV‚`ÉH§©›3 Ša3ÕN9߸!ªâO…cØÔ)‚ÇœrxbžD•=(È` Àƒõ$„ú‚„\p£9ç !’ˆHFR¤A~2[ýî'¶7° ¹"ŽY­3ôï èwÂæQ(ôÐ o¢ÇH(”‚`9«prbHlqNø‚‚@„#EQ…n`a s”ÒÏ~ø#‰"ðÉCžœé€D%‚CfxWր܀Lx¤ _ ³àÐ 3S™Jh­Å‰> O©.¦µ…pMr+Át 7ºUgT|KؼÊ,ô"½4€Gƒ ƒµ^”™£ìî)|Êãæã>ø ³+02¦ò2¢Ìg¨˜²áŠ®—3@P‚Ô1˜Â)ÎpØ`Ó ‡r˜O™QFØÇ4jd£3(GÑq” {šÑ˜HÉ0fo*û"ÖdÓÈÖñ¯¡ô4CÄ 8$Ž$SÈBž`#¼ÑœþDç³”âAô¼ ž ç—È2,²¡çÙ à*4~¶/¼Kæ‚d„îì4‹é†cÞó„4Ýs(‡æqlHDUBDœ Ôe‰#( 0J)pÔ£6='žµ‚Ÿ¶Ó¤(¸å³Ã.¼TŒÇI¢—@@‰ºÀ!_ð`%7?ⱇ?ìcý ‚мŠ\ñ XÄB–gÕ/," DÊDÜ¥ªÕV£•†ùp³MìÊXëåM— Ucí h=k-Öm V-¨”Ê×n~s‚TÁuªN³U§ôäd½w0°Üê¤Êt´Ä—2˜ EÀºØ,€f¶h.Ój×’»\Í8—«A³Ž‹‚0Í;|àCqÓ›±3Ô±^û®¾§S8«™ñƒo}çsÚhušº…¯[×Ć6u ¨ DéRG}é]úU&ø«àcZPÀxƒ ¶û¨º]Œ](HƒŠRÀ'¿s¨OY0<Ü&Jx† À¯u™ºC’¤sríQÚP¿<`ÖEÞ‚ˆW’‘èÔZY]\%§rÜ0i“ö\AI¹¦VPŽKK½#I‚Ø)d±ªy­+;Xˆö ?HÁ‰æ1$ƒöU¥ nÅ©[‰"Š,˜òi5B–ÌemµüÔ.wåËa ³ëÆ,Ø?š94iþñ 97³«OüÍm làñ¹“¡E-Œe\/-ÛXrC…plR©ðX>>*œoÛ')›xÏ졧ÙÙ=ïZ}fÁŸëšZlwÁ7íå¯$z,eÀ¬_¥ÖV¯.Ó»Š¨e]úY ]P.Å] ≮¾[·¸W¸\©öÃwC·º—Ëî¼v (kŸlÆ2DøQé7½ãØnéhîsìZ\ͼãEëÆaõ ^}ÁãKß&ÅÒd0xö¨HÉz‚KAz¡ÒÛXrexuëUJ:œ2•«l¥{ó›éZ :‡Ó9½×׺¥•T8O¥ÛŸwðÅÛõIE ô9 ]Ó}¢'¦“:¸VR!?.&ñ Iˆâ©sW3C\Þð.ˆî¨68W¦Î'~”œòyÑÃH…\ßQÏ 9_†àÎKŒÜ}ã×›6 ÜЬ«¸xW»á¹ÍWÇQàn8sû¢t Ú*Æ_˜»ÔÅͽµÕê’gL3¯¸"P¥\Y>pé«ô[C½ê]ÉßGp¾#¥éOYàßJé½ ðÝ{¿.¨OU)s»á Ý‘÷ÙäR·õùAŽþrû‡éá xðÒÑ!/ù‚häòà÷’øoAA_òÞEøÍ0Bö?[Ðþ¸ .ܳjÑ’d'ä8õFàÖåx'`'`-6âB.æBAÏõTPP³Ã3“FUàD`W2óA1 ØbÈE~ÒW'þ2c 8'x1bAk1=“Fá5#H%¨4ú2ƒtRƒ8iDÑE;¨€tƒì„a „GÓ_@A°yIX‚dÀ„ à„Pø2D¨FS ƒ S‚b …\515Us…#q?`†4hiZÕ^(7Ìb‚ xU•÷ywB£_-Ç{«Äz¶ƒ{({ƒ8s¶gsøf;—ð×\x„ 8„TpÐö³R•íÕ‡¯2Áb‚"ÇÁ4ŠUp3vˆ"àVnõcˆ»·Uø Dã‡ú7}-¨/¬pC'8YÅŠÌ77¹‰ëFpÐ!xÂ1 ì‚@ÆÃq2'(6Ó§bE¡à¡ܨwΣKq—mµ¡U÷â8¤p1Ð>°\¼8¡ÄòH,XÖ5@4>&ã^•§ùøõˆmø8¹ýXd@°±´wù¯E‘XcE©õ†<à‘'nÈÃbƳu]Ç4¥"%¾‘7f`Ž|'&‘[cà'ç¸K2©l-R`ÎvxŠÄHLsâ9|ƒ#gà¤i& ÌÑ[¾†qÏÁ ô¤’vwBhQyMO1•Ìñ^%S‘é,ÝóX4a¤cPÌá ‚Ú¡<šyLN@¢$1Ez¤4†£;ú¡™÷1ú4Ê?Š¥B*¥S𑔤^J£Pð£cº¥)úEà]•b“¦kz¥B A0bÃq:§4*wJ§$¡§r:4*CðM ¡$!¨„Ú4ú‰Ú¦ƒZ¨‹ú¨_*ŒÚLp¥izuš©bʧ"€êayº)¹åªÓÇ<‰“ÒƒRJ E16)2TAL!ì±3 ,²Ž‚G«ó«Ò1WA«òØ Òq¬¹E_p¬t°Ôc«Z/þh@'­> ¬ý×"´:‹¹Êô ÃçJ«Ú"ÙZ!Ù(ºJg×_íõ7†”yAS„^5†$#K2Êù$’µ“îs r6‘<Ééãom'…ï6wL€SZ°…!M¡^h°iÐÝVÊ1F}1‡4†}ÊÒü±Ümaa>Ü,ˆq7¨¤†žû1 ;2/9²Ãebin/PORT/ps.c.Z 444 0 0 45675 4634750131 6401 Œ/T(¡Ä7pòÈIs (Ƥ# ¤”9SÆ 9 Þ˜AMUܤ±SFÎœ4tò„9$ ›4fÞÈQÆÅÀ‚AØ°±°áG¢eæ´dIÆTL‚ÒrM6edÎIçN9'™¤ÓQ)ˆ gÀ–iÓ‘ÎOsà”ƒ3MR’Ré´l2Œ2 Ƽù 3Í`9å %“f…bêÐ1ìÆ'Á ŒÀù·ÌÈ›ŒAó50B… n颇@PŒ˜x0aQ‡%R´ˆQ#G Eâ=™reË—1g´‰S'O\Üptèí£`•Êa ݈š;2éæÍCÐn5s&ãzŽÃL˜´â9cƼ$³º5ز¥Ç.Œ‘@ .äUrX…UÕðÚð]x„‘gž{i„¦žc°Q{ ðàco¸€††8âI<Œ“\*²¸ˆ"’ÈCOoHVc‹9ÂÇM­ä‹%ΑÇ/ÀñUmüx£‹:*ɤa2²!e‡TÂhå tÄ´%ŽHš¸ä ŒÉ1f—IžY‡vkÙ&“pÈñÆq–ÙF£uXF“zåYå™vDiä”ršÉ¤^xÐ!¨—gÆçè¡\&úe‘™ñh‰{–´)-픢‘¢ÙGl|á”Iõ×{(€_Ôy§,hÆž~&€ÅPHñÄ $ƒ¬´V1‡pб'¸êêY¯¿V1…PPÑDP$²_¼É,ÑŽ°+µ_X‹-ÅÊ.£äæjî´n”áëT» Ì®sx­¼çÖ{¯S\Ám±4€»'s°1°´¼üë¶XLÁD·5€›u”[°½¿1Uk¸sµ‡Èô’üEC4E±7ükë0W,³Á[,ÿÂÛ3ºNä»o±9€KFmtx´Å_ÑDI8Ql ÇÎúÅÓO-³Õoý­×S,ù¬Ø÷N‘ÅÛvƒ»h/ù’e°ý«ÛSL‘„Exë¯×¾ÁžØ üšõDîmÃ^óŠâ¿‘ŽÇб×c˜¡å_ a„Ed¾2ç6±Ñc¼û™xèA0ÁÄU°CÎ^kóë s··D{ýÕ½·^ïëAHqÄðkÕNW%?¯Ï¯/Q„NÁÄð2tM+¦ÖüzB Ÿ€ gÓº*[cðièN D»tÓGæ…zUx‚ЮÁÑŠ û3èˆ@¶ r´ X¦@—0!TÁíÚ­&è;ìýÊ‚\ßéh5†òý®dê“î6X3˜á8 ¡¶7…õO"P@ÀŸÇÔAF @Uc¢Tí X R1Ì% o:ÉN?7œà!‚ ê ’Ã\Fzª°â†#"Q‰#PŽ‚¶,ä.*ÀLåðC:$`a°ƒ`Ú+Yq‘2},–cè(£°v ˆÄÀS,3¨N> ¨C­d41òŽ>,¤I;Àá’a¼ãæp7Fö.á*£¬YÇ„“*ØxN©D¬,ä+óÈÑ|%±üB ÉðIY…2 _pdÎÀÈ9 A'vD¦¤X°Äp¥ ÔD&®™MU¥ ݬSº±f¥-Ýœ [š™¼}!š£l'8«é’9¤ónélT=›ùL9Àùé‘GéK9¸ò1ÙÆœ„&`Î +ˆAÉ;¼ó aÊ©Î2\™•¬;Ý Ï‡íS‡<,(0Ù€2È<¡¼ÃîpÍ’˜Q‰4%CI”S)úÒ àÕU“¸ˆÓ#fˆã[yH^ÆêŽý´cªà°ÍÊJ¥© )#C™ª0Á¥õªK/š*™’F•;ÌŒJUP‡–¾´T¿¬¥[Sj`Úa®KÕ$'Ÿ*ÉPZtOjp$FêQ;Z4`õ¤¦EéÐ(Ä’’‘Ž|$- JZ¥™¹^¯€&,bÅ`eyµãÎ@°³-pvX-–ÃÔ2ÜšEÅ )Ფø $JÍ¥híD´agàÑmàExñðƒ ¤p£¨æ´®upGæ°…*@!G(º`Z!@áÕáµÍ.¯‘„s3»Ï$ S°æàjP ˆ bHÀ«Dð‚2Ða Mšä1¼2o彊Rè Ìûæ÷Uð•oœ¡Ì„r4k¨ªZ˜zÄ•Ž<5;Ç·1ÄÔ<ŠA°†³aÅnXñPìÇÛaÅxXqBìa;‚è¬s0£j B‡þ %ÂñŠZ¯C~q­thÖ[×Ê‘0Å) ¦ ªtœ§U·î‘¸r­M‡7}IÍd:”^Ä{V¼*`CÊÎÀ¼éEí)m1õ†›ÐGÉaòU@Сœüä-W¹vÿÆvˆýa @òH ’2F8bWÙͳúgÀŠ_Ê@†·xî |{˜o⧀À :5ò@ÍÁlW˜‚Üý¦…%‚…´pÖ `:4÷ æ ŽÏ¼|¨ÉEÙÚ=/{éM _S4Ôñ`Y³bJrø+Pô¼ge”jޓĽ¡sׂ·ÜÕ|Ћú¤OÀʪoüì'  máÚ˺ÊTU¬ÚÂó›ýOQ‰‚CÙÇDV}1ñûªÞ9~aŠõ¥C¶DúÇv@µlÁGJEK†ç-%dIT‡÷rZMŒ×D2q~ùçR_¤<'áW0YÓ87Ã5xòÄSRÑh÷fz(J%ÿÇ ø,ˆ¦‚#¨/©õ€ãuEfTepJñ£G˜áuQl”§z `§÷'QaͲD võáM-ÐxÑ¿E€„omð,Á„wA|i7fE¤eObc'N‡ `>b'Êáo!ˆò…»#@„NÔFû³{A(yV—‡e·|˜QPQƒŽ_ð„®H"P˜R`-³"Š&¦(¶uN0aŠNP²ƒYâæcu²p6LñáOñÖ½gn­DS“‚Âxhqe€kaZv€ÊHfÓŒEô„foÈØÒ¶ÔmÖaµ˜(S “¢¨U¶lc p0Ýx<ÿÇCÍ÷kgPd°)(€ôø(À52@/àÞu)™±'‚rpcM i‰¦¢±ÔàñT`qCÔˆEÔ¤Œt‘©˜KÅ”q±E×ÄH²Æ;S’—S6•7(€%tÀûHMTÃrW5S ÔdÂ8=ð*öÓ¾÷*ÁH V?ç‹:Õ”!Œ.ps Leׯ‚?:À{•¡•\Ém&+Ç3aÈg`+°[E“m >00OåJpàÇc[áU,w€i€A’001‹¹;sÉ—2‰'0' ?çaŽu0——”yVa°—?fqS°™9ã2¢Ù™¥yš£¤f!§Á|ЙOñ¸ë–»[+iñ—ÀÛ¦o:«^Ù¥J*Ñ! ;š:ʦÍ릈gÛû¼Þû•ÎK¼Å{¼ºË»T…¯¯^J½“á×+¥4¹¯ °¢ `¾ÉK¿Ü[¦gp”{9½ƒñ¾ñ‹D:Šaf¿æ¼õѬ€a¿ø‹¾×Ô¾l½ '¿A©g Àg½Á½Ð ¼­«¦(ðÀ½{ˆr”O€> ¼JZ¼÷»3ç›LZw&0ú’Tà¥ø7Áð[Á9z»0œ¼åÔQx £1P0¾.êÂ#ļ+)ÑÛ7˜SIÌÂKìÂ$ Å'<TðP€¬.ê¾ ¥¯™GlvIá®Léª*†º¨fþ¶2P—WÙ{%"½†iÇ©++q°þt#Ù˜# yõV'7‹7"±£ƒÜƒy¬ÔÄl‡¡>«5)´H›E{‹l7™€ ’Ž¡‘H·³dƼmº³[µ«£ýyµ)1r°£’üs ª£œ¡žôÊqQ­³<¿!–¡Ñ…˱ü¡PûšuËrºp »»£Ì%ü»¯‚Âè“¡GEf@¸%²+\$#> º µ! q¡ÌÉìȤLü¦6Œ8,Í©WÍ"P"Žû¾g°ÍÝlS:ÎËLε¢¾x\,ÓìÎp!0r!Ü|I» ÎøŒÏû rªùÏÖ,]Œk1-ËÃŒDýÎ%àµT¤mm@»øb(Ù˜ÐÌO&àb0žú¿‚DbàŽñm@Ä{ÜãM®€Œ·¥Ìç~N€ÞQU>v¾è~Nó´sn~›^îä‡^*0&0FñèA$¡Þæ]^èb¶ÕœN³l ê& ákDênÀå8šé†®êŠÑé,wØnK“U4³Ôdé§þ图ëžÞpK"êÊn‡Ä~ë?[µ¿ë[·$ €´SwíIçS§»õÒ(J‰ë©È&Ðí> q®ŽtiÏY¨~ì*Û¦?ævøëAôSÎnëînìºï ØRéÎt 8ëø®ïKþîýÎë5xƒ®¾û'ëÔ‚"è$hð="o DØ @·÷æ¬Âß òëtÔ²âÉz¡ið‘þÉŠaà*€àÏU\Ä*™²¬ú7…9’p _[f™2óŠ_RÞöåE?…ÊnçEéü‡_NéPÙ(-T*åq›šàþqâ‘â&AJÐd-§/ÎM«£Z¿ÜrJrO@r9\ÚþuÚaÕ?'ã:!öøeã8Ž£:ý€²²„Dðo(Åm®÷+ å?æ?0øJÕãƒKôY^럋È#aùß­åí^Ù!U:¢Wžô˜ÏùSŽùG_ú—Æ pæ±Ü†qyª˜÷h_û_DÞ·˜É0P§yœph>JòóTól‘)®ûŒèU5¸ ïéRïè™Ö›/SN¦þæ¡çÆ?”vŽçýéžý'1èpÞçåOÄö;ý”®”Ì/ûÎ/“žcšüýòNêªÖ´>ì*%‹t±ïšw'AëKhï¯^G£>D=»äÐÈ£ð°þ„³®ÿ_ÿ^ï¼ì ÏqìnñõïUðÎ럎îÕ/ÍîÿAÌÕ¯òêuôt¸•šGj¿þêuôtsE´îW]í ö²¨ö€‹àíl²ì!r¤R–5aE¡ywbT|ra—‡‹1í÷‚–ã²®õïUðÎëÕ^ïgýêuôts0ëèT]ý,ï_ýÂ1ïãÿAÌÿÎÐà,ðäÇëšGjó0Khï¯^GãwV= ú(ðï ¶²¨ö€‹àíl²ì!r¤R–5aE¡ywbT|rEÅ…jwH1]­J«—d¯àQýz4‹ïKhï¯^GãwVìø;¾`ý<~gðÕÿ¶ÿSd_ÿ^ï ÿS6g ?ƒy:Hñúbñ>®:é'_÷;¹<4ûê㪣ñ—~òu¿(€÷:M®1¦§ñÚ–ê*òœ>‘qIÙLÍŒþ!¤e`/P"—­”Š ˜ Iy) –¹2ÀeÉ_…"`q!N{€þA®n€Š[ÕÜqç1ÎÖ¯¬¸~/h9.+᪣—=€{€þQ—ÄŒþ¡¸:¢}ÉŒþ!¤e`/p€R,èäê#œŒU}Ìq€w¼—€ûklýÊÌȸ5ã?—Æ —ÍÁ+ÌôJy¹¥€ m#ñ*mé3a˜[0]P–BZv€&tÔ"Hãäê;úŒU}Ìà,0w¼—€ûklËÏȸ5ã?—Æ:”íú®.!¯ê*òœ>‘qàŒ ßlPÜ©{FDFG'a¡÷E`fÏ*ñfßX“¯q+/“±>¯r—y –ér¬Q–üU(þ}!"ü›˜Ý—YÄè±Þ¯òö„+õ¦–—TezdýúúþUQýš¨~ß±¾¸}ãx/®;nÏ4?ö+dÝ—YÄè±Þ¯"—¡û|7 ë°\Ô±aæ8tIfßlPÜë{I±n°ÒXojyIÍŽ­—TeÕ¯¯£K˜;#çÏ¢€‹àíl²ì!r¤%0e‰ynø„v=êC´¸}ã‚–ã²®:zÙM«DWpìÍF»ÖzV²øÉ+.ñN?t8دöƒ ¡E“oH¯çJúw› €p)ø*û|CzEÀ° ±œ÷,% ·—¡,kgø ³2;'OáÍ"±Ç ÷,Ñ›ö­‹àíl²ì!r¤O Ê|rEEpÏÓŒ[Ó9þs’û%+Õ£Ž°_À7qð ±ìJh¯â0€00Ùús(°Ú­ µ¯†vûU]­Y Õw»ê @pí—‚aï¯^G¤¥=++᪣fßlÐ÷?WezdýúnÓþêuDZ—›.×’- ë°;ÀëÖ,ÏR²p+p)±ér-Ù7 ë°;Àƒýj( ÕR±_€0  ë° ²UÍý‘ÕP}·«þéÐæê#0dm¿ön°ÐFÖ}YEaÿ„ 0“¸Ìè÷‚–ã²®ƒýj( ÕR±_pÄð ± [ÕÜY Õw»ê&0mãêÓ&1dm¿ö>ÂþVNdÝ—UôöO¸Ó&1‰ËŒ~/h9.+á:د†Z-Õ:'S ë° ²UÍý‘ÕP}·«nàÖð!EÖökïRdÝ—UôöO¸à–¸Ìè÷‚–ã²®ƒýj( ÕR±3S3XÀ° ± [ÕÜY Õw»ê&@n®Nndm¿öŽäFÖ}YEaÿ„Kn‰ËŒ~/h9.+᪣‰šÁ µ ¸öÖ(¹±l€°_4úB ë° ²ÕJ\¯òêuÄÜ¢²É²v†ß0+³4 /áðÒ³?—½“€Ûã}"¡¤åAo²a7‰‡‹1͸5ã?'¹kÖ(%«î“Øé<±ø¢/TÀ° ± [­ƒýj( ÕR½fRÕÇ Y Õw»êðRoØVýoËtðâú.l¿öÖ(Khï¯^GÌ î­[Eaÿ„K\‡;9Ô¤¸Œ[Ó9þsi,+úTùz±Ë[5W“5 ë° ²8ÚoxûË[5W“i ë° ²·­¹xþÕz[g'pÓÓd ð® Q`²eÜ÷‘ƒG\¨v‡”Ý;í_zdXfò&É‘$ñ[\O“ÊÊÅbÚ;áŽæ#VvP“áJ_õS(ðélpÊ ë°\Ô±'Q)v±Ë§Ì° ± Æbe( 8NÀ8E€£be(P9—S8*Vv€ ÛY8*Vv€¿¢49ÌHbe(P2£S:8*Vv€%;³S;8*Vv€{£0P78*Vv€¿Ò<ÏÃ-8*Vv€¿¢=Üã=qƒ£be(p1éÃ-8*Vv€k?Üû 4@ ë° ²eÝ¥°âƒ=eT˜w8±+ Ð@t®ôUv€¿Ò@T­be(ð+ @9lJlùUv€{s „£be(ðA„£be(€BÜ‚£be(ðA4CR08ÚÇЄÿ~Øó0áOM ˆlÐNÉi€­—|Ç¿ƒXpɜܗÎBÊi°„ó0—´ðqvÊãýïüá,鹿ƒXÀ°ØŽ²¥#ÀE»"€d`:¤Ó °ùT#‰W ¿£Ì¹Ê+€Á+¨œ—ì ¸ÞÎ&Ër A: es2áy21à é,Ðê‰Äq[Ó~/h9.+áªÊ½œÙ4i ¬ŒD2µÆ¯bíÍÙ»ÆyÙ}“¡2µÆH¹~ÑgÐ<ž2µÆHz£÷7b (àVþ¡y¤6HeÎR.¥æ 7zsöi+‹j¸=Ñ'*A: e¹:Êq€:‘1͸5ã?'¹qÑÎ(àVwíVÔ$SL¤!ˆAà2}JµüsnåwV4íÍ:š¨˜Ý—«õUmTuÐ!T[aˆX”v‡÷Llp†RíÜDWñÛ÷'Â(àVþ¡y¤6HeÞV.¥æ‘¢Ñ›ö­‹àíl²ì!r¤R–«£¨yÓŒ[Ó9þs’íŒnE{nUoÖ–ï\I@ï\–"`-ÛãÂ2}J¨Z,n£x%«¼¼‰Š¦šÁ üsn¥´mKæa/}Cw2ýÆ_1íƒTæn…£] 1)¼-o×QèR8Š«ÝÚ.$"Îd²Ü&ë_Eaÿ(p˜³TvÒ‡)"Ïé‡9{n'mp˜òAÙKÑ'*A: eÉÖŠáÖD]ˆa'|Ts`×…Gt[vÒ‡)· pi2D„_-”oi`¦ZIAJ½[19dÝ—ÝŠ­£ÿ}8OôhüsJ4u°Z×aI…¤•ñ/ám!ð!ЇƒqEDQŠÙS|´:÷¡·zUÑIÉé«2꣕¤.%Š-N÷{½—ôžWfœ¾*£>ZIAYT•-N÷{½—ôžWóÉ«•Ôœ:ª•½» üHTIÍÿ$!yp€·Ÿrœ•4›Õ×øÈwpÐÈÑ{È©À•är0÷*' 'ðs:Ú(€,€¡+Ìu‡Õ,@+Ìuç²,€¡+Ìu‡hÀk0?çÂÂ[wXÍw¾Â|Pw#̲޺•¤´¯2Ç\“Æ«•äéoZI[ 0—¤.jÚ;Æ?÷žWmàš‘È« ½'Ð' À•är0÷*'ž \I[ 0÷*'Ð' À•´3sIŠD¦½b›pÐÈÑ{mp \I.s¯rEÀD¦½—ôžWús¾*£>ZIA ¿BÑât¿×;!¶T꣕¤n ^¤Iž¡¦½—ôžWpœ .ÇÜ[I.s¯rE' À•´2s¯ryüHdÚ;qIïyUÑ騼ªÙ•är0÷*'€œ+Ì.s¯rpP§ ¬ ñ¸•´2p¬Jœ.\I[00—¤HdÚ;qI‹®•äøÕBºKèÇJÛ‡™¢»d€~m@F`+©x€­W]IÅ*QÑ{dP§™M“Œafrš”€+Â’B¸EZç|Î¥zŽDŒafm«èþ×eHo ·sª<^,ŒafH9Ç?'¹:Ê6a`f!§-àÐH„ØjÐ<Þ­‘*©áZÀ™—øÕBºKèÇ ¬ ñ¸•T¬åéo ¬ ñ¸*PI®J»¾QÅ*Q`{˜©æ ¶'ðûPéÍ:ª•„—¯rÈ©À*PI%ò*'`À_,x ´ë‹k®•¶'€œPéÍ: ¬ ñ¸*PI®Jû**PI`{¿•<ŽÛ»V/ÁN e÷U¤LLEʯ^GIÇà) y¤öë¯^GIçp= ú(@LÑ›öM‹àíl²ì!r¤R–5aE¡ywbT|ra—‡‹1í÷‚–ã²®ª\í ö²¨ö?§uB¡t¯BLŒÔìÂO“e÷Uúse÷UãüíÓNL5Îß>íiÏH(°Ú­-£ Ĥ»×°¬Âo™¢»d€~i~Õ¿‰Ù} ç…FLº+q Ë*àÏç\ÚÁ&ðsÅk²êÏè@^5üI`MÃG9_F`?R¡Ä¤»ççx£Šþç]v`ÐÞÜ—ò&qaˆ½4©uB¡trJL^ªuB¡ti+‹L0šõ/fÄĸÄäe÷U*ÂÄä¥Ää퓘¶²È£iÚ;ƲrJ¨Z,Ĥ»ç·WÑKÚÅbÚ;ÁHxЦ_y;5ÎW çÁ¾x°ó·x0ÞÍÎa?’;í_…e&/àéò]¸ë%‰ò ÌtTGLQáPìôÆt’ÿú.ë’”QÌ›¤ÅbÚ;A¸? Óxàuà’tqmª—·3ÉALþaÕN]Á¾xÐÕ‡i¿&PíÔe¬ŒäÂ}HÊ&PíÔELºìÇšÙ4ILº{qÑ›”€+Â’‚Ääí¬þ|Î¥lä Ί^þ†S5üI`MÃG9_F`?Rà¥Ä¤»£Šþç]vpª<^,Ĥ»·asüs’«£Ä¤»½uà’tqÿÆÍE®J4kp™KL€)*ׇé©&PíÔÕìÕ‡pÀÉ}©£Ä¤»½I ¸",)(@LÞÎ*àÏç\ÚÁ&@¾à¬èåo8ePÃ_FÐ9|”SðI`ö#^JLº{q1ªèþ×e`§ÊãÅBLº{q6Ç?'¹:JLº{qÑ[. I—¡ñoÜ\„qájÚ}M¸?pÑ9ÁEd@ ¤LLÞà Ÿâ|”Wt .×GyE' Àp°2ÐGyyüþ¬´¯2¦'_÷}â· fŒe&/àéòá¢\K%‰ò Ìt»”H$Éòéò]¸ë•Äòéòá؆%9’¥µ*ÀÒ\ļÃPl¿Ð,\÷X†Ó?gÚ;ÁQ3’ûÕ¯:úÁâ˽½'@§+Ì$£ÜK¥>z¥O§µ¡ª”¦½ÍDÊu¾È[@±;?Ò¤Ìe#ݯ<ÒÌ›¤ÅbÚ;ÑL Ý¡%‹t»”Hβv¶söþêu¤…yÔ³«¤ÒúÌÒþÁÒåe>b,pçK„Ïþ¿b@Óø(ÃËôÈ2¼LmÖFøØÌÜÌmÖFøèMdñÈÞD8*fÈ´¯lM€ÝFø¸Ð¼ÐmÖFøX+ ñȵ²8*fÒ$1ÔÿÄÓQmÖFøøN”þÈïôþŒ”ÏÈti„ÉÆ3ÒÈŒ”ÏÈtiÅÆ3âr¬–.Çey˜yÕù,M~ÂZÂBдù R ƒ­:¢}™ÏÒ”‚¯BÂ$‚kžÅ gÐøø‰EZ_POòÔf‡ªœ }qþQ. IwIù R ãuà’DG.@GáÒQ.@‡5J»E. ItätÔ»”îtpXs!¶à›u¡ù R £´¯R. Ic@G.@GáÒQ.@‡5J»E. Ic@G.@G½Ké.@‡5b $ /ɽðÒºx@Ê&/[@Âðò—b¸fR»~ÉÌÑNþãŒñ„7dªÐŒõ³õ*x0Îxðõ$OdªÐ%\4íx0Îx L‚ÁEžÚQ:\´+mÄ– mR³õ*$lRúUÛËÜò)áÞT‰”uÅôsáì[ÉE. 1ÜNʯ^G®ÍKÞ™,kg;gï¯^G®G=ëm„,pçîÏþ¿b ËU[+UõȵRUmÖFU+LáHZÂ2Ç ù,Mn¿Ð,*feõSü_^\´+môs£»]5€¯RY討âºãöL“µÜÉ-Ÿòá›ÄK*àI·yG㼕\äžäžT²H·I¼Ôéɲv¶söþêu›”G=ëm„,pç àIÊìø+?§£ù,Mn¿Ð,­+f‡EߤôÈ£Dߤĸž¤»•í¯R. ItätèaXS‡½@Ì[1 /ª¤ž¤»‹ÕXô=[¯‚㌣Dßõs’ëIºKY–Uþlu€j#ÀE»ÒF²rJí²½üsáì[ÉE. I•õ_ ãÀVýzÐ;ÚË™m— Åö ÍBк™[I%Èuà’cpž à•tÇ&À\.]ËÔ*Ö…]ÚÅ]„‰´^ª£*PI“©¤z«HÎ>°•\äç£t7%kÌåѵL­b]Ø¥]ÜE˜`[I‘++O±³©ÓÜæm 0lm€zò-Ÿòá»”H$àÜæmA5%´‘ýs Í2"æÁõ"šÏå<Ã5<;A@\ªç”Ï'ˆ­.­4íÍ}9zÐ,#²!¯b]Ø¥]Jl°ü*#1¬ p+ÏÈôíÔ³˜;%´%[Ø$ëùŒLõ´s Í2"æ‘/0L@zEÐ_%ôo¶ ùŒL%\$ëé9|r€Jû*÷Yò‘ùŒLŒõ¤”/0L@zE€HäÂùŒL%\DýUBÿ–Ú¦Ý×û0àQžÃ'xÛÛÆkX¡ÀVXfòÃõÑQ·)è/Ì[1ÜQW-èâ+¼AÂæ\óDÀ¥z.à{Ý×(.€÷"ü!¥”¦Ý×û0àQ$\Yÿ2y]÷}½0.€A•õ_ Ó¹.€bxoVJéK¨:g!5=«C™¡¯Xfò^G¤%pÍbÿ.•MÍâÃp›nÇS’ÁÕu]Ù5+0L@zEP˜(¯‘·òÆt’8òÕž‚mka)#o (`]Ø¥]Q–öþêuôƒrÀýÑļÃæܦ  1ODÀ¥{™Ù¡+0w¬çÅbÚ}x_,(°Ú­ µ¯¶£Õ¯—:õbÐļú£E~Ì1¸ÐFµäÎ\.À\_Íû ׺ÞÎ&Ër A: eYEîmÿ[dÜŠ¡a%@TvÂG%0vM¾ÆëÄ Ïȸ¦Ý×(€÷Å"¹•…Ž#1è®”ÿ‡­—dÚ} ¹¦$+Íbÿ»ëÖ,ϲb .ÓļÃpy¦æ/Ì[1<z…¥[˜ƒýj( ÕRÝ,öïRUÍý‘ÕP}·«n»£ŽÍ"±¼ÿëøØ,ãíL¸R–UäÞöO€iBZé„U¶EÆ­VDe'|Ts`×?‡ÅN¼ÐÔ¤¸ÕjÚ}xŸÚPûj#Œƒ_¼²}µ2òb€ÍR.gP+f¿mQ¤ Ö…]ÚµCÀ¤WQöþêuDZz‘e?‡÷"<¸P}·«~°•\ä‹$“]7€%@dP6P%`uP3@%@dP3@%PxP4@%Pd`Š.œÏå<ÃÙ¤Ðûš+ àÂù¬MÜäãJwƒ£]52Ù¤ÐU…£ ó_ö'€™8Ú,W–ÏÈ”Q8ºÑ P4à40E*)bF­8jNl±¬Ó#ÙCk†zò-Ÿòá»”H$à˜8M®çUõöMÙTmuòA˜˜[PáµJ4õ_¾‡ -)”yU—Ù7] ¼ªÅ˜I'pIïyU—)Å¥¼ª£ù¬M —8Â’¡:šÏÒ$1DŒºFœiHì¥ZŒ™Ip§Êã{n˜ٚíÍ:šÏå<Ãm Sp]Ù•¡ZŒ™PpÍã˜d˜I'pIïyU—<8L Æy-Uàjœ~CLÀ«ZŒ™Rp—ôžWu™Ð,¼ªÅ˜©'pIï)+¹Z»úsZ<§'`J²òH ½D mÎm óA@ –ø¨ÐõDÎ mR³–'à'@–˜‰™Q–'p'pÕùŒL*Awì€#,J©dá'À'•Þ¬£ùŒL*AEì€#,J©dá'à'•<®dá'€™Œä)û*ø¨Ðæ\ÃUN–''@– mÎ5<EjaÉš'@–˜‰™yÝ*„£¾‹´ÙárãýH…Ô%ã­d´Ù±30Þ~y,¿×}ÕIqÛ Û pÆT¬e`Jñ GZð­ò@eiàOu°{ÚH…a+KhÚ}ÍZ·¶$c±{¦/p¤ߊ‘§I†=õU{:;7ýàu‹Lf;WKslòŽ‘.¿‘a+“:š¨¬\,¦Ý×;*º»•\ä’TYÿ2E<1 »[ÉE. I•õ_ adÉsÜÁ½üs¦Ý×(°Iò´£¡ ¶›$O;ʾo£1 ÎÌ|q`;2 ÎÌ|qW8ýsi£1 Î̬ab82 ÎÌ\U,¿×}]“·­›$OƼJ'»È£à(ÊL·K‰t­m›Ð,‘.á¾I¼¤ž£ã¼•\äžÄH  mÎm óA@JiÚ} ]OJûs.œÏÈÄX1[ž‹ P‚ÁE–ùŒL%\ôeɾy]÷}ž¤»‡Eß³µæø¨Ð%\ôa‰eéIº»XEߤԳ:Ä^d¢#’ñ[?p’ñ[[ä,ÅôŽNP6;zÖ.ë,pà’~iNÕ7'“N€Ôtç" ÔDö—‡1é—WI@Ú×0âGhGH¡´¯B/oéçã~â"¦UI@᥹ WTÙ<ÉõJ°Ù„†øbç$¤$ÖTzú{¤áLŒ÷(ð³[ÁpñCh0AèÛwT¯ô|B³e`Jñw@ÅZôky`‰ôE;í_“¶¯i‘-ŸòáNBJDBCuî$¤D$QeCÒýŠò©q•TõÑýŠò©q•TõtÊÈq": ¾À¹óe0yÞÀ)ãf‡ 2tQ"E=@Ä°¨`D3 P¨tR% ‘ L€XÙò%ˆ"SÀ F Œcà€Q' %f²t™Ââˆ2læ”*4dÑ£2i2½™Ó)E2'1žœy„ž1eº³%he{X5šÄÚ¶pÞº Ó¦Ì]~&H § :gÞuëboߦ=cxáUW!'‹"ÄBÁ„ #&ˆÂ§Å‹óÂ¥;—Ìé)C dq‚"µ^¾eX€XØÂÇÂ/ŽËh.|8qm¶ŒƒCîsq š0r@¨P0'Œ2å *Ø9téA-îÁXøL‡‰º™“挛2GÙP<]þ|ÀèÞ£« ‡dù…”€ÛÁ¡Cm÷œ~)Œl¼1 ®ƒnìéQÆfÌ”ŸN§¡`ÇFÁ”]Py ÀŸnÜÑ'šqü-wÑ ÓIhœ‚oÔA‡Ae€pGs€àЂ`m€b€@ÇF¦ÑFl„}µñ†ypÆ^”õu6¾AhiEX¸€¦ /(À¡_С€SÂFsP(áOºqÆŠG^æ¡'Gýatgž¨•qG„cø÷Þ¥…iL øcÀ`ê©0œVbôY›¥˜jÆ™ c€:j©¨š “\ øÂxƒ™‡Ña ‘!º‰`EŸΡƒ”rŒ9G–?j—š-¬!Ð{l8I…Í1nˆ YhŹ¡Ò¤tÀÔB š1·Y‡(uSš¡p¿b”€°Ätl²Ë6û¬DÑN G”Ð#B²Ú£G¡Pgmœº"° 0¤ºõkn®KÜhïšg¼7Ñ{š½œ™ÜFpl¡g|aH=adBV6ã¬ó[<aÆGñÁ¿€ÞœóÎ=Ãa†u4É«O0;ð°ÅL‡²r0 ‚³Ðê0ÄAºñBvg#¡K©M 0Ïu’t¨Tóú¥ã&¸@@ÀxR›.Ï ½þ“ˆÇ"××r ”#?ªÕGåc„Ø6dPwðsÒq€…f*ÐAÓgù2ÈM Ñ'_ v ¸Y©ôhwÇ•$qfI¡jΖÐ&m%(>Ë„CÅj¥ÆqœÇeø’k‘xé·P WàAÐE0ky„42†T95KÓ:d ć:?µt4ƒ/üç’·øc‚diQ81`*©f…n€…4”U7†Ò¡ÄC†Xhl¬vÜT$Ž…0Dnƒdˆ;?—DrPÑ;^óeÐCa^82lx#€¨C7£†2ˆzÂj `‡í…‡ˆæsÜć¾Ç‰hiÝiSd0UD6f#Y4-ÓE\R^&N¢†d¤-C¢MÝj42Ouª$„v³FÁ‡Qxm|´*&ˆ[°qhJrV ´p"ØH\#a9¸ƒ=øƒÅHc@\[<èƒz5šÄIÝèÕX»µ~òg­D}A„`ER?¼ÖSÊS+µHâç}ðS6ØjÆD%?O¥ÄVu{¨ˆ^GS?'PYº‘_Q QÃRvÀk€y¨‰cR€ Ø‘¹SC!ö"@„°”[e$;T"ŒbÁÆ&KÇ{xwg‡i X›”_æW0IàD°nCZ#3+­Ã?ï‘…ÛT’_†ëÑS `ø¡,x°i·{v6‰1C‘ă3A”„”sëw:a“†„K7Ї’ Ée_!!¡ŒÖb\ùMt”I¹”X`\€i?dh †ipˆ©”L)0XGÈ8–kô“ 0”^VY%$iP™•î\¹wëèufAª¹•Ué£f–©Æ—*Ó¨Žßø~Œì2»Q)¹gñøJ¼CM8Ù=LÕsõ³µ9~ÐQ-yOÅ¢`?‰7w@Qw ?ÁˆÜT€¥áI‘7©@Q©•Ô45u¤ Òž«I•ßé_ÀŽ§!Ÿ÷9›¬)$2ÀŸþ)øŸ±)Ÿ }#$ #include #include #include #include #include #include #define kbytes(size) (((size) + 1023) / 1024) struct afile { char ftype; /* file type, e.g. 'd', 'c', 'f' */ ino_t fnum; /* inode number of file */ short fmode; /* mode&~S_IFMT, perhaps ISARG */ u_short fflags; /* st_flags (uappnd, uchg, schg, ...) */ short fnl; /* number of links */ uid_t fuid; /* owner id */ gid_t fgid; /* group id */ off_t fsize; /* file size */ long fblks; /* number of blocks used */ time_t fmtime; /* time (modify or access or create) */ char *fname; /* file name */ char *flinkto; /* symbolic link value */ }; #define ISARG 0x8000 /* extra ``mode'' */ struct subdirs { char *sd_name; struct subdirs *sd_next; } *subdirs; char aflg, dflg, gflg, lflg, sflg, tflg, uflg, iflg, fflg, cflg, rflg = 1; char oflg, qflg, Aflg, Cflg, Fflg, Lflg, Rflg, usetabs; time_t now, sixmonthsago; char *dotp = "."; struct winsize win; int twidth; struct afile *gstat(); int fcmp(); char *cat(), *savestr(); char *fmtentry(); char *getname(), *getgroup(); main(argc, argv) int argc; char *argv[]; { extern int optind; struct afile *fp0, *fplast; register struct afile *fp; struct sgttyb sgbuf; int ch, i; time_t time(); Aflg = !getuid(); (void) time(&now); sixmonthsago = now - 6L*30L*24L*60L*60L; now += 60; twidth = 80; if (isatty(1)) { qflg = Cflg = 1; (void) gtty(1, &sgbuf); if (ioctl(1, TIOCGWINSZ, &win) != -1) twidth = (win.ws_col == 0 ? 80 : win.ws_col); if ((sgbuf.sg_flags & XTABS) != XTABS) usetabs = 1; } else usetabs = 1; while ((ch = getopt(argc, argv, "1ACLFRacdfgiloqrstu")) != EOF) switch((char)ch) { case '1': Cflg = 0; break; case 'A': Aflg++; break; case 'C': Cflg = 1; break; case 'L': Lflg++; break; case 'F': Fflg++; break; case 'R': Rflg++; break; case 'a': aflg++; break; case 'c': cflg++; break; case 'd': dflg++; break; case 'f': fflg++; break; case 'g': gflg++; break; case 'i': iflg++; break; case 'l': lflg++; break; case 'o': oflg++; break; case 'q': qflg = 1; break; case 'r': rflg = -1; break; case 's': sflg++; break; case 't': tflg++; break; case 'u': uflg++; break; case '?': default: fputs("usage: ls [ -1ACLFRacdfgiloqrstu ] [ file ]\n", stderr); exit(1); } if (!lflg) oflg = 0; if (fflg) { aflg++; lflg = 0; sflg = 0; tflg = 0; } if (lflg) Cflg = 0; argc -= optind; argv += optind; if (argc == 0) { argc++; argv = &dotp; } fp = (struct afile *)calloc((u_int)argc, sizeof (struct afile)); if (fp == 0) { fputs("ls: out of memory\n", stderr); exit(1); } fp0 = fp; for (i = 0; i < argc; i++) { if (gstat(fp, *argv, 1, (int *)0)) { fp->fname = *argv; fp->fmode |= ISARG; fp++; } argv++; } fplast = fp; qsort(fp0, fplast - fp0, sizeof (struct afile), fcmp); if (dflg) { formatf(fp0, fplast); exit(0); } if (fflg) fp = fp0; else { for (fp = fp0; fp < fplast && fp->ftype != 'd'; fp++) continue; formatf(fp0, fp); } if (fp < fplast) { if (fp > fp0) putchar('\n'); for (;;) { formatd(fp->fname, argc > 1); while (subdirs) { struct subdirs *t; t = subdirs; subdirs = t->sd_next; putchar('\n'); formatd(t->sd_name, 1); cfree(t->sd_name); cfree((char *)t); } if (++fp == fplast) break; putchar('\n'); } } exit(0); } formatd(name, title) char *name; int title; { register struct afile *fp; register struct subdirs *dp; struct afile *dfp0, *dfplast; long nkb, getdir(); nkb = getdir(name, &dfp0, &dfplast); if (dfp0 == 0) return; if (fflg == 0) qsort(dfp0, dfplast - dfp0, sizeof (struct afile), fcmp); if (title) printf("%s:\n", name); if (lflg || sflg) printf("total %ld\n", nkb); formatf(dfp0, dfplast); if (Rflg) for (fp = dfplast - 1; fp >= dfp0; fp--) { if (fp->ftype != 'd' || !strcmp(fp->fname, ".") || !strcmp(fp->fname, "..")) continue; dp = (struct subdirs *)malloc(sizeof (struct subdirs)); dp->sd_name = savestr(cat(name, fp->fname)); dp->sd_next = subdirs; subdirs = dp; } for (fp = dfp0; fp < dfplast; fp++) { if ((fp->fmode&ISARG) == 0 && fp->fname) cfree(fp->fname); if (fp->flinkto) cfree(fp->flinkto); } cfree((char *)dfp0); } long getdir(dir, pfp0, pfplast) char *dir; struct afile **pfp0, **pfplast; { register struct afile *fp; DIR *dirp; register struct direct *dp; long nb; int nent = 20; dirp = opendir(dir); if (dirp == NULL) { *pfp0 = *pfplast = NULL; printf("%s unreadable\n", dir); /* not stderr! */ return (0); } fp = *pfp0 = (struct afile *)calloc(nent, sizeof (struct afile)); *pfplast = *pfp0 + nent; nb = 0; while (dp = readdir(dirp)) { if (dp->d_ino == 0) continue; if (aflg == 0 && dp->d_name[0]=='.' && (Aflg == 0 || dp->d_name[1]==0 || dp->d_name[1]=='.' && dp->d_name[2]==0)) continue; if (gstat(fp, cat(dir, dp->d_name), Fflg+Rflg, &nb) == 0) continue; fp->fnum = dp->d_ino; fp->fname = savestr(dp->d_name); fp++; if (fp == *pfplast) { *pfp0 = (struct afile *)realloc((char *)*pfp0, 2 * nent * sizeof (struct afile)); if (*pfp0 == 0) { fputs("ls: out of memory\n", stderr); exit(1); } fp = *pfp0 + nent; *pfplast = fp + nent; nent *= 2; } } closedir(dirp); *pfplast = fp; return (kbytes(dbtob(nb))); } int stat(), lstat(); struct afile * gstat(fp, file, statarg, pnb) register struct afile *fp; char *file; int statarg; long *pnb; { int (*statf)() = Lflg ? stat : lstat; char buf[BUFSIZ]; int cc; static struct afile azerofile; *fp = azerofile; fp->fmode = 0; fp->fnum = 0; fp->ftype = '-'; if (statarg || sflg || lflg || tflg) { struct stat stb, stb1; if ((*statf)(file, &stb) < 0) { if (statf == lstat || lstat(file, &stb) < 0) { fprintf(stderr, "%s not found\n", file); return (0); } } fp->fblks = stb.st_blocks; fp->fsize = stb.st_size; switch (stb.st_mode & S_IFMT) { case S_IFDIR: fp->ftype = 'd'; break; case S_IFBLK: fp->ftype = 'b'; fp->fsize = stb.st_rdev; break; case S_IFCHR: fp->ftype = 'c'; fp->fsize = stb.st_rdev; break; case S_IFSOCK: fp->ftype = 's'; fp->fsize = 0; break; case S_IFLNK: fp->ftype = 'l'; if (lflg) { cc = readlink(file, buf, BUFSIZ); if (cc >= 0) { buf[cc] = 0; fp->flinkto = savestr(buf); } break; } if (stat(file, &stb1) < 0) break; if ((stb1.st_mode & S_IFMT) == S_IFDIR) { stb = stb1; fp->ftype = 'd'; fp->fsize = stb.st_size; fp->fblks = stb.st_blocks; } break; } fp->fnum = stb.st_ino; fp->fmode = stb.st_mode & ~S_IFMT; fp->fflags = stb.st_flags; fp->fnl = stb.st_nlink; fp->fuid = stb.st_uid; fp->fgid = stb.st_gid; if (uflg) fp->fmtime = stb.st_atime; else if (cflg) fp->fmtime = stb.st_ctime; else fp->fmtime = stb.st_mtime; if (pnb) *pnb += stb.st_blocks; } return (fp); } formatf(fp0, fplast) struct afile *fp0, *fplast; { register struct afile *fp; register int i, j, w; int width = 0, nentry = fplast - fp0; int columns, lines, maxflags; char *cp; if (fp0 == fplast) return; maxflags = 0; if (oflg) { for (fp = fp0; fp < fplast; fp++) { i = strlen(flags_to_string(fp->fflags, "-")); if (i > maxflags) maxflags = i; } } if (lflg || Cflg == 0) columns = 1; else { for (fp = fp0; fp < fplast; fp++) { int len = strlen(fmtentry(fp, maxflags)); if (len > width) width = len; } if (usetabs) width = (width + 8) &~ 7; else width += 2; columns = twidth / width; if (columns == 0) columns = 1; } lines = (nentry + columns - 1) / columns; for (i = 0; i < lines; i++) { for (j = 0; j < columns; j++) { fp = fp0 + j * lines + i; cp = fmtentry(fp, maxflags); fputs(cp, stdout); if (fp + lines >= fplast) { putchar('\n'); break; } w = strlen(cp); while (w < width) if (usetabs) { w = (w + 8) &~ 7; putchar('\t'); } else { w++; putchar(' '); } } } } fcmp(f1, f2) register struct afile *f1, *f2; { if (dflg == 0 && fflg == 0) { if ((f1->fmode&ISARG) && f1->ftype == 'd') { if ((f2->fmode&ISARG) == 0 || f2->ftype != 'd') return (1); } else { if ((f2->fmode&ISARG) && f2->ftype == 'd') return (-1); } } if (tflg) { if (f2->fmtime == f1->fmtime) return (0); if (f2->fmtime > f1->fmtime) return (rflg); return (-rflg); } return (rflg * strcmp(f1->fname, f2->fname)); } char * cat(dir, file) char *dir, *file; { static char dfile[BUFSIZ]; register int dlen; if ((dlen = strlen(dir))+1+strlen(file)+1 > BUFSIZ) { fputs("ls: filename too long\n", stderr); exit(1); } if (!dir[0] || dir[0] == '.' && !dir[1]) return(strcpy(dfile, file)); (void) strcpy(dfile, dir); if (dir[dlen - 1] != '/' && *file != '/') dfile[dlen++] = '/'; (void) strcpy(dfile + dlen, file); return (dfile); } char * savestr(str) char *str; { register char *cp = strdup(str); if (cp == NULL) { fputs("ls: out of memory\n", stderr); exit(1); } return(cp); } char *fmtinum(), *fmtsize(), *fmtlstuff(), *fmtmode(); char * fmtentry(fp, maxflags) register struct afile *fp; int maxflags; { static char fmtres[BUFSIZ]; register char *cp, *dp; (void) sprintf(fmtres, "%s%s%s", iflg ? fmtinum(fp) : "", sflg ? fmtsize(fp) : "", lflg ? fmtlstuff(fp, maxflags) : ""); dp = &fmtres[strlen(fmtres)]; for (cp = fp->fname; *cp; cp++) if (qflg && (*cp < ' ' || *cp >= 0177)) *dp++ = '?'; else *dp++ = *cp; if (Fflg) { if (fp->ftype == 'd') *dp++ = '/'; else if (fp->ftype == 'l') *dp++ = '@'; else if (fp->ftype == 's') *dp++ = '='; else if (fp->fmode & 0111) *dp++ = '*'; } if (lflg && fp->flinkto) { (void) strcpy(dp, " -> "); dp += 4; for (cp = fp->flinkto; *cp; cp++) if (qflg && (*cp < ' ' || *cp >= 0177)) *dp++ = '?'; else *dp++ = *cp; } *dp++ = 0; return (fmtres); } char * fmtinum(p) register struct afile *p; { static char inumbuf[8]; (void) sprintf(inumbuf, "%6u ", p->fnum); return (inumbuf); } char * fmtsize(p) register struct afile *p; { static char sizebuf[16]; (void) sprintf(sizebuf, "%4ld ", kbytes(dbtob(p->fblks))); return (sizebuf); } char * fmtlstuff(p, maxflags) register struct afile *p; int maxflags; { static char lstuffbuf[256]; char gname[32], uname[32], fsize[32], ftime[32], fflags[64]; register char *lp = lstuffbuf; /* type mode uname gname fsize ftime */ /* get uname */ { char *cp = getname(p->fuid); if (cp) (void) sprintf(uname, "%-9.9s", cp); else (void) sprintf(uname, "%-9u", p->fuid); } /* get gname */ if (gflg) { char *cp = getgroup(p->fgid); if (cp) (void) sprintf(gname, "%-9.9s", cp); else (void) sprintf(gname, "%-9u", p->fgid); } /* get flags */ if (oflg) (void) sprintf(fflags, "%-*s ", maxflags, flags_to_string(p->fflags, "-")); /* get fsize */ if (p->ftype == 'b' || p->ftype == 'c') (void) sprintf(fsize, "%3d,%4d", major(p->fsize), minor(p->fsize)); else if (p->ftype == 's') (void) sprintf(fsize, "%8ld", 0L); else (void) sprintf(fsize, "%8ld", p->fsize); /* get ftime */ { char *cp = ctime(&p->fmtime); if ((p->fmtime < sixmonthsago) || (p->fmtime > now)) (void) sprintf(ftime, " %-7.7s %-4.4s ", cp+4, cp+20); else (void) sprintf(ftime, " %-12.12s ", cp+4); } /* splat */ *lp++ = p->ftype; lp = fmtmode(lp, p->fmode); (void) sprintf(lp, "%3d %s%s%s%s%s", p->fnl, uname, gflg ? gname : "", oflg ? fflags : "", fsize, ftime); return (lstuffbuf); } int m1[] = { 1, S_IREAD>>0, 'r', '-' }; int m2[] = { 1, S_IWRITE>>0, 'w', '-' }; int m3[] = { 3, S_ISUID|(S_IEXEC>>0), 's', S_ISUID, 'S', S_IEXEC>>0, 'x', '-' }; int m4[] = { 1, S_IREAD>>3, 'r', '-' }; int m5[] = { 1, S_IWRITE>>3, 'w', '-' }; int m6[] = { 3, S_ISGID|(S_IEXEC>>3), 's', S_ISGID, 'S', S_IEXEC>>3, 'x', '-' }; int m7[] = { 1, S_IREAD>>6, 'r', '-' }; int m8[] = { 1, S_IWRITE>>6, 'w', '-' }; int m9[] = { 3, S_ISVTX|(S_IEXEC>>6), 't', S_ISVTX, 'T', S_IEXEC>>6, 'x', '-' }; int *m[] = { m1, m2, m3, m4, m5, m6, m7, m8, m9}; char * fmtmode(lp, flags) char *lp; register int flags; { int **mp; for (mp = &m[0]; mp < &m[sizeof(m)/sizeof(m[0])]; ) { register int *pairp = *mp++; register int n = *pairp++; while (--n >= 0 && (flags&*pairp) != *pairp) pairp += 2; *lp++ = pairp[n>=0]; } return (lp); } /* rest should be done with nameserver or database */ #include #include #include struct utmp utmp; #define NMAX (sizeof (utmp.ut_name)) #define SCPYN(a, b) strncpy(a, b, NMAX) #define NCACHE 64 /* power of 2 */ #define CAMASK NCACHE - 1 char * getname(uid) uid_t uid; { static struct ncache { uid_t uid; char name[NMAX+1]; } c_uid[NCACHE]; register struct passwd *pw; register struct ncache *cp; setpassent(1); cp = c_uid + (uid & CAMASK); if (cp->uid == uid && *cp->name) return(cp->name); if (!(pw = getpwuid(uid))) return((char *)0); cp->uid = uid; SCPYN(cp->name, pw->pw_name); return(cp->name); } char * getgroup(gid) gid_t gid; { static struct ncache { gid_t gid; char name[NMAX+1]; } c_gid[NCACHE]; register struct group *gr; register struct ncache *cp; cp = c_gid + (gid & CAMASK); if (cp->gid == gid && *cp->name) return(cp->name); if (!(gr = getgrgid(gid))) return((char *)0); cp->gid = gid; SCPYN(cp->name, gr->gr_name); return(cp->name); } '); formatd(t->sd_name, 1); cfree(t->sd_name); cfree((char *)t); } if (++fp == fplast) break; putchar('\n'); } } exit(0); } formatd(name, title) char *name; int title; { register strubin/ls/Makefile 644 0 12 704 5670255570 6652 # # Public Domain. 12/3/1994 - Steven Schultz # # @(#)Makefile 1.0 (2.11BSD GTE) 12/3/94 # CFLAGS= -O SEPFLAG= -i SRCS= ls.c stat_flags.c strsep.c OBJS= ls.o stat_flags.o strsep.o all: ls ls: ${OBJS} ${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS} clean: rm -f ${OBJS} ls tags depend: ${SRCS} mkdep ${CFLAGS} ${SRCS} install: ls install -s -o root -g bin -m 755 ls ${DESTDIR}/bin/ls lint: ${SRCS} lint -hax ${SRCS} tags: ${SRCS} ctags ${SRCS} bin/ls/stat_flags.c 444 0 12 10513 5670264034 7535 /*- * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)stat_flags.c 8.1.1 (2.11BSD GTE) 12/3/94"; #endif /* * Modified from the 4.4-Lite version for 2.11BSD. Main change was to * use 'u_short' instead of 'u_long' for the flags word. */ #include #include #include #include #define SAPPEND(s) { \ if (prefix != NULL) \ (void)strcat(string, prefix); \ (void)strcat(string, s); \ prefix = ","; \ } /* * flags_to_string -- * Convert stat flags to a comma-separated string. If no flags * are set, return the default string. */ char * flags_to_string(flags, def) register u_short flags; char *def; { static char string[64]; register char *prefix; string[0] = '\0'; prefix = NULL; if (flags & UF_APPEND) SAPPEND("uappnd"); if (flags & UF_IMMUTABLE) SAPPEND("uchg"); if (flags & UF_NODUMP) SAPPEND("nodump"); if (flags & SF_APPEND) SAPPEND("sappnd"); if (flags & SF_ARCHIVED) SAPPEND("arch"); if (flags & SF_IMMUTABLE) SAPPEND("schg"); return (prefix == NULL && def != NULL ? def : string); } #define TEST(a, b, f) { \ if (!memcmp(a, b, sizeof(b))) { \ if (clear) { \ if (clrp) \ *clrp |= (f); \ } else if (setp) \ *setp |= (f); \ break; \ } \ } /* * string_to_flags -- * Take string of arguments and return stat flags. Return 0 on * success, 1 on failure. On failure, stringp is set to point * to the offending token. */ u_short string_to_flags(stringp, setp, clrp) char **stringp; register u_short *setp, *clrp; { int clear; char *string; register char *p; if (setp) *setp = 0; if (clrp) *clrp = 0; string = *stringp; while ((p = strsep(&string, "\t ,")) != NULL) { *stringp = p; if (*p == '\0') continue; if (p[0] == 'n' && p[1] == 'o') { clear = 1; p += 2; } else clear = 0; /* This was done only once on entry! */ switch (p[0]) { case 'a': TEST(p, "arch", SF_ARCHIVED); TEST(p, "archived", SF_ARCHIVED); return (1); case 'd': clear = !clear; TEST(p, "dump", UF_NODUMP); return (1); case 's': TEST(p, "sappnd", SF_APPEND); TEST(p, "sappend", SF_APPEND); TEST(p, "schg", SF_IMMUTABLE); TEST(p, "schange", SF_IMMUTABLE); TEST(p, "simmutable", SF_IMMUTABLE); return (1); case 'u': TEST(p, "uappnd", UF_APPEND); TEST(p, "uappend", UF_APPEND); TEST(p, "uchg", UF_IMMUTABLE); TEST(p, "uchange", UF_IMMUTABLE); TEST(p, "uimmutable", UF_IMMUTABLE); /* FALLTHROUGH */ default: return (1); } } return (0); } = stb.st_ctime; else fp->fmtime = stb.st_mtime; if (pnb) *pnb += stb.st_blocks; } return (fp); } formatf(fp0, fplast) struct afile *fp0, *fplast; { register struct abin/ls/strsep.c 444 0 12 6015 5670255517 6716 /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93"; #endif /* * Copied from 4.4-Lite and slightly modified for 2.11BSD. The version of * strsep in 2.11's libc.a was incompatible with 'ls' and 'chflags'. Rather * than break (or have to convert) existing programs we use this file in * 'ls' and 'chflags'. */ /* * Get next token from string *stringp, where tokens are possibly-empty * strings separated by characters from delim. * * Writes NULs into the string at *stringp to end tokens. * delim need not remain constant from call to call. * On return, *stringp points past the last NUL written (if there might * be further tokens), or is NULL (if there are definitely no more tokens). * * If *stringp is NULL, strsep returns NULL. */ char * strsep(stringp, delim) register char **stringp; register char *delim; { register char *s; char *spanp; int c, sc; char *tok; if ((s = *stringp) == NULL) return (NULL); for (tok = s;;) { c = *s++; spanp = delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; *stringp = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ } claimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specifibin/sysctl/ 755 0 12 0 6045322463 6040 bin/sysctl/Makefile 644 0 12 1340 5714624573 7574 # # Public Domain. 1/15/1995 - Steven Schultz # # @(#)Makefile 1.1 (2.11BSD GTE) 2/3/95 # CFLAGS= -O SEPFLAG= -i VPATH= ../ls SRCS= sysctl.c strsep.c OBJS= sysctl.o strsep.o MAN= sysctl.0 MANSRC= sysctl.8 all: sysctl sysctl.0 sysctl: ${OBJS} ${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS} sysctl.0: ${MANSRC} /usr/man/manroff ${MANSRC} > ${MAN} clean: rm -f ${OBJS} ${MAN} sysctl tags depend: ${SRCS} mkdep ${CFLAGS} ${SRCS} install: all install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat8 install -s -o root -g bin -m 755 sysctl ${DESTDIR}/bin/sysctl lint: ${SRCS} lint -hax ${SRCS} tags: ${SRCS} ctags ${SRCS} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ent: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specifibin/sysctl/sysctl.8 644 0 12 14701 5707645016 7570 .\" Copyright (c) 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)sysctl.8 8.1.2 (2.11BSD GTE) 1/19/95 .\" .TH SYSCTL 8 "June 6, 1993" .UC 4 .SH NAME sysctl \- get or set kernel state .SH SYNOPSIS .B sysctl [ .B \-n ] .I name ... .br .B sysctl [ .B \-n ] .B \-w .I name=value ... .br .B sysctl [ .B \-n ] .B \-aA .SH DESCRIPTION The .B sysctl utility retrieves kernel state and allows processes with appropriate privilege to set kernel state. The state to be retrieved or set is described using a ``Management Information Base'' (``MIB'') style name, described as a dotted set of components. The .B \-a flag can be used to list all the currently available string or integer values. The .B \-A flag will list all the known MIB names including tables. Those with string or integer values will be printed as with the .B \-a flag; for the table values, the name of the utility to retrieve them is given. .PP The .B \-n flag specifies that the printing of the field name should be suppressed and that only its value should be output. This flag is useful for setting shell variables. For example, to save the pagesize in variable psize, use: .sp .in +1.0 set psize=`sysctl -n hw.pagesize` .in -1.0 .PP If just a MIB style name is given, the corresponding value is retrieved. If a value is to be set, the .B \-w flag must be specified and the MIB name followed by an equal sign and the new value to be used. .PP The information available from .B sysctl consists of integers, strings, and tables. The tabular information can only be retrieved by special purpose programs such as \fBps\fP, \fBsystat\fP, and \fBnetstat\fP. The string and integer information is summaried below. For a detailed description of these variable see \fBsysctl(3)\fP. The changeable column indicates whether a process with appropriate privilege can change the value. .sp .ta 0.5i 3.0i 4.0i .nf Name Type Changeable kern.ostype string no kern.osrelease string no kern.osrevision long no kern.version string no kern.maxinodes integer no kern.maxproc integer no kern.maxfiles integer no kern.maxtext integer no kern.argmax integer no kern.securelevel integer raise only kern.hostname string yes kern.hostid long yes kern.clockrate struct no kern.posix1version integer no kern.ngroups integer no kern.job_control integer no kern.saved_ids integer no .\" kern.link_max integer no .\" kern.max_canon integer no .\" kern.max_input integer no .\" kern.name_max integer no .\" kern.path_max integer no .\" kern.pipe_buf integer no .\" kern.chown_restricted integer no .\" kern.no_trunc integer no .\" kern.vdisable integer no kern.boottime struct no vm.loadavg struct no machdep.console_device dev_t no net.inet.ip.forwarding integer yes net.inet.ip.redirect integer yes net.inet.ip.ttl integer yes net.inet.icmp.maskrepl integer yes net.inet.udp.checksum integer yes hw.machine string no hw.model string no hw.ncpu integer no hw.byteorder integer no hw.physmem long no hw.usermem long no hw.pagesize integer no user.cs_path string no user.bc_base_max integer no user.bc_dim_max integer no user.bc_scale_max integer no user.bc_string_max integer no user.coll_weights_max integer no user.expr_nest_max integer no user.line_max integer no user.re_dup_max integer no user.posix2_version integer no user.posix2_c_bind integer no user.posix2_c_dev integer no user.posix2_char_term integer no user.posix2_fort_dev integer no user.posix2_fort_run integer no user.posix2_localedef integer no user.posix2_sw_dev integer no user.posix2_upe integer no .fi .SH EXAMPLES .PP For example, to retrieve the maximum number of processes allowed in the system, one would use the follow request: .sp .in +1.0i sysctl kern.maxproc .br .in -1.0i .PP To set the hostname of the system to foo.bar.com, one would use the follow request: .sp .in +1.0i sysctl -w kern.hostname=foo.bar.com .in -1.0i .br .PP Information about the system clock rate may be obtained with: .sp .in +1.0i sysctl kern.clockrate .br .in -1.0i .PP Information about the load average history may be obtained with .sp .in +1.0i sysctl vm.loadavg .br .in -1.0i .SH FILES .TP 15 definitions for top level identifiers, second level kernel and hardware identifiers, and user level identifiers .TP 15 definitions for second level network identifiers .TP 15 definitions for third level profiling identifiers .TP 15 definitions for second level virtual memory identifiers .TP 15 definitions for third level Internet identifiers and fourth level IP identifiers .TP 15 definitions for fourth level ICMP identifiers .TP 15 definitions for fourth level UDP identifiers .SH SEE ALSO sysctl(3) .SH HISTORY .B sysctl first appeared in 4.4BSD. up(str); if (cp == NULL) { fputs("ls: out of memory\n", stdbin/sysctl/sysctl.c 644 0 12 30506 6037102163 7630 /* * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if !defined(lint) && defined(DOSCCS) static char copyright[] = "@(#) Copyright (c) 1993\n\ The Regents of the University of California. All rights reserved.\n"; static char sccsid[] = "@(#)sysctl.c 8.1.3 (2.11BSD GTE) 1995/10/11"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct ctlname topname[] = CTL_NAMES; struct ctlname kernname[] = CTL_KERN_NAMES; struct ctlname vmname[] = CTL_VM_NAMES; #ifdef CTL_NET_NAMES struct ctlname netname[] = CTL_NET_NAMES; #endif struct ctlname hwname[] = CTL_HW_NAMES; struct ctlname username[] = CTL_USER_NAMES; struct ctlname debugname[CTL_DEBUG_MAXID]; #ifdef CTL_MACHDEP_NAMES struct ctlname machdepname[] = CTL_MACHDEP_NAMES; #endif char names[BUFSIZ]; struct list { struct ctlname *list; int size; }; struct list toplist = { topname, CTL_MAXID }; struct list secondlevel[] = { { 0, 0 }, /* CTL_UNSPEC */ { kernname, KERN_MAXID }, /* CTL_KERN */ { vmname, VM_MAXID }, /* CTL_VM */ { 0, 0 }, /* CTL_FS */ #ifdef CTL_NET_NAMES { netname, NET_MAXID }, /* CTL_NET */ #else { 0, 0 }, #endif { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */ { hwname, HW_MAXID }, /* CTL_HW */ #ifdef CTL_MACHDEP_NAMES { machdepname, CPU_MAXID }, /* CTL_MACHDEP */ #else { 0, 0 }, /* CTL_MACHDEP */ #endif { username, USER_MAXID }, /* CTL_USER_NAMES */ }; int Aflag, aflag, nflag, wflag; extern char *optarg; extern int optind, errno; /* * Variables requiring special processing. */ #define CLOCK 0x0001 #define BOOTTIME 0x0002 #define CONSDEV 0x0004 int main(argc, argv) int argc; char *argv[]; { int ch, lvl1; while ((ch = getopt(argc, argv, "Aanw")) != EOF) { switch (ch) { case 'A': Aflag = 1; break; case 'a': aflag = 1; break; case 'n': nflag = 1; break; case 'w': wflag = 1; break; default: usage(); } } argc -= optind; argv += optind; if (Aflag || aflag) { debuginit(); for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) listall(topname[lvl1].ctl_name, &secondlevel[lvl1]); exit(0); } if (argc == 0) usage(); while (argc-- > 0) parse(*argv, 1); exit(0); } /* * List all variables known to the system. */ listall(prefix, lp) char *prefix; struct list *lp; { int lvl2; char *cp, name[BUFSIZ]; if (lp->list == 0) return; strcpy(name, prefix); cp = &name[strlen(name)]; *cp++ = '.'; for (lvl2 = 0; lvl2 < lp->size; lvl2++) { if (lp->list[lvl2].ctl_name == 0) continue; strcpy(cp, lp->list[lvl2].ctl_name); parse(name, Aflag); } } /* * Parse a name into a MIB entry. * Lookup and print out the MIB entry if it exists. * Set a new value if requested. */ parse(string, flags) char *string; int flags; { int indx, type, state, size, len; int special = 0; void *newval = (void *)0; int intval, newsize = 0; long longval; struct list *lp; int mib[CTL_MAXNAME]; char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ]; bufp = buf; strcpy(buf, string); if ((cp = strchr(string, '=')) != NULL) { if (!wflag) { fprintf(stderr, "Must specify -w to set variables\n"); exit(2); } *strchr(buf, '=') = '\0'; *cp++ = '\0'; while (isspace(*cp)) cp++; newval = (void *)cp; newsize = strlen(cp); } if ((indx = findname(string, "top", &bufp, &toplist)) == -1) return; mib[0] = indx; if (indx == CTL_DEBUG) debuginit(); lp = &secondlevel[indx]; if (lp->list == 0) { fprintf(stderr, "%s: class is not implemented\n", topname[indx]); return; } if (bufp == NULL) { listall(topname[indx].ctl_name, lp); return; } if ((indx = findname(string, "second", &bufp, lp)) == -1) return; mib[1] = indx; type = lp->list[indx].ctl_type; len = 2; switch (mib[0]) { case CTL_KERN: switch (mib[1]) { case KERN_PROF: fprintf(stderr, "kern.prof = not supported in 2.11BSD\n"); return; case KERN_INODE: case KERN_FILE: case KERN_TEXT: if (flags == 0) return; fprintf(stderr, "Use pstat to view %s information\n", string); return; case KERN_PROC: if (flags == 0) return; fprintf(stderr, "Use ps to view %s information\n", string); return; case KERN_CLOCKRATE: special |= CLOCK; break; case KERN_BOOTTIME: special |= BOOTTIME; break; } break; case CTL_HW: break; case CTL_VM: if (mib[1] == VM_LOADAVG) { double loads[3]; getloadavg(loads, 3); if (!nflag) fprintf(stdout, "%s: ", string); fprintf(stdout, "%.2f %.2f %.2f\n", loads[0], loads[1], loads[2]); return; } if (flags == 0) return; fprintf(stderr, "Use vmstat or pstat to view %s information\n", string); return; case CTL_NET: if (mib[1] == PF_INET) { len = sysctl_inet(string, &bufp, mib, flags, &type); if (len >= 0) break; return; } if (flags == 0) return; fprintf(stderr, "Use netstat to view %s information\n", string); return; case CTL_DEBUG: mib[2] = CTL_DEBUG_VALUE; len = 3; break; case CTL_MACHDEP: #ifdef CPU_CONSDEV if (mib[1] == CPU_CONSDEV) special |= CONSDEV; #endif break; case CTL_FS: case CTL_USER: break; default: fprintf(stderr, "Illegal top level value: %d\n", mib[0]); return; } if (bufp) { fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); return; } if (newsize > 0) { switch (type) { case CTLTYPE_INT: intval = atoi(newval); newval = (void *)&intval; newsize = sizeof intval; break; case CTLTYPE_LONG: sscanf(newval, "%ld", &longval); newval = (void *)&longval; newsize = sizeof longval; break; } } size = BUFSIZ; if (sysctl(mib, len, buf, &size, newsize ? newval : (void *)0, newsize) == -1) { if (flags == 0) return; switch (errno) { case EOPNOTSUPP: fprintf(stderr, "%s: value is not available\n", string); return; case ENOTDIR: fprintf(stderr, "%s: specification is incomplete\n", string); return; case ENOMEM: fprintf(stderr, "%s: type is unknown to this program\n", string); return; default: perror(string); return; } } if (special & CLOCK) { struct clockinfo *clkp = (struct clockinfo *)buf; if (!nflag) fprintf(stdout, "%s: ", string); fprintf(stdout, "hz = %d, tick = %d, profhz = %d, stathz = %d\n", clkp->hz, clkp->tick, clkp->profhz, clkp->stathz); return; } if (special & BOOTTIME) { struct timeval *btp = (struct timeval *)buf; if (!nflag) fprintf(stdout, "%s = %s", string, ctime(&btp->tv_sec)); else fprintf(stdout, "%d\n", btp->tv_sec); return; } if (special & CONSDEV) { dev_t dev = *(dev_t *)buf; if (!nflag) fprintf(stdout, "%s = %s\n", string, devname(dev, S_IFCHR)); else fprintf(stdout, "0x%x\n", dev); return; } switch (type) { case CTLTYPE_INT: if (newsize == 0) { if (!nflag) fprintf(stdout, "%s = ", string); fprintf(stdout, "%d\n", *(int *)buf); } else { if (!nflag) fprintf(stdout, "%s: %d -> ", string, *(int *)buf); fprintf(stdout, "%d\n", *(int *)newval); } return; case CTLTYPE_STRING: if (newsize == 0) { if (!nflag) fprintf(stdout, "%s = ", string); fprintf(stdout, "%s\n", buf); } else { if (!nflag) fprintf(stdout, "%s: %s -> ", string, buf); fprintf(stdout, "%s\n", newval); } return; case CTLTYPE_LONG: if (newsize == 0) { if (!nflag) fprintf(stdout, "%s = ", string); fprintf(stdout, "%ld\n", *(long *)buf); } else { if (!nflag) fprintf(stdout, "%s: %ld -> ", string, *(long *)buf); fprintf(stdout, "%ld\n", *(long *)newval); } return; case CTLTYPE_STRUCT: fprintf(stderr, "%s: unknown structure returned\n", string); return; default: case CTLTYPE_NODE: fprintf(stderr, "%s: unknown type returned\n", string); return; } } /* * Initialize the set of debugging names */ debuginit() { int mib[3], size, loc, i; if (secondlevel[CTL_DEBUG].list != 0) return; secondlevel[CTL_DEBUG].list = debugname; mib[0] = CTL_DEBUG; mib[2] = CTL_DEBUG_NAME; for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) { mib[1] = i; size = BUFSIZ - loc; if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1) continue; debugname[i].ctl_name = &names[loc]; debugname[i].ctl_type = CTLTYPE_INT; loc += size; } } struct ctlname inetname[] = CTL_IPPROTO_NAMES; struct ctlname ipname[] = IPCTL_NAMES; struct ctlname icmpname[] = ICMPCTL_NAMES; struct ctlname udpname[] = UDPCTL_NAMES; struct list inetlist = { inetname, IPPROTO_MAXID }; struct list inetvars[] = { { ipname, IPCTL_MAXID }, /* ip */ { icmpname, ICMPCTL_MAXID }, /* icmp */ { 0, 0 }, /* igmp */ { 0, 0 }, /* ggmp */ { 0, 0 }, { 0, 0 }, { 0, 0 }, /* tcp */ { 0, 0 }, { 0, 0 }, /* egp */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* pup */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { udpname, UDPCTL_MAXID }, /* udp */ }; /* * handle internet requests */ sysctl_inet(string, bufpp, mib, flags, typep) char *string; char **bufpp; int mib[]; int flags; int *typep; { struct list *lp; int indx; if (*bufpp == NULL) { listall(string, &inetlist); return (-1); } if ((indx = findname(string, "third", bufpp, &inetlist)) == -1) return (-1); mib[2] = indx; if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL) lp = &inetvars[indx]; else if (!flags) return (-1); else { fprintf(stderr, "%s: no variables defined for this protocol\n", string); return (-1); } if (*bufpp == NULL) { listall(string, lp); return (-1); } if ((indx = findname(string, "fourth", bufpp, lp)) == -1) return (-1); mib[3] = indx; *typep = lp->list[indx].ctl_type; return (4); } /* * Scan a list of names searching for a particular name. */ findname(string, level, bufp, namelist) char *string; char *level; char **bufp; struct list *namelist; { char *name; int i; if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { fprintf(stderr, "%s: incomplete specification\n", string); return (-1); } for (i = 0; i < namelist->size; i++) if (namelist->list[i].ctl_name != NULL && strcmp(name, namelist->list[i].ctl_name) == 0) break; if (i == namelist->size) { fprintf(stderr, "%s level name %s in %s is invalid\n", level, name, string); return (-1); } return (i); } usage() { (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", "sysctl [-n] -a", "sysctl [-n] -A"); exit(1); } P_NAMES; #endif char names[BUFSIZ]; struct list { struct ctlname *list; int size; }; struct list toplist = { topname, CTL_MAXID }; struct list secondlevel[] = { { 0, 0 }, /* CTL_UNbin/hostname/ 755 0 12 0 6024535764 6344 bin/hostname/hostname.1 644 0 12 5037 5731217634 10333 .\" Copyright (c) 1983, 1988, 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)hostname.1 8.1 (Berkeley) 5/31/93 .\" hostname.1,v 1.2 1994/09/24 02:55:40 davidg Exp .\" hostname.1,v 1.2.1 29/1/95 Robin Birch .\" .TH HOSTNAME 1 "January 29, 1995" .SH NAME hostname \- set or print name of current host system .SH SYNOPSIS .B hostname [ .B \-s ] [ .B nameofhost ] .PP .SH DESCRIPTION .I Hostname prints the name of the current host. The super-user can set the hostname by supplying an argument; this is usually done in the network initialization script .I /etc/netstart , normally run at boot time. .PP Options: .TP .B \-\^s Trims off any domain information from the printed name. .br .sp .SH SEE ALSO gethostname(2), sethostname(2) .SH HISTORY The .I hostname command appeared in BSD 4.2 . , "%s level name %s in %s is invalid\n", level, name, string); return (-1); } return (i); } usage() { (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", "sysctl [-n] -a", "sysctl [-n] -A"); exit(1); } P_NAMES; #endif char names[BUFSIZ]; struct list { struct ctlname *list; int size; }; struct list toplist = { topname, CTL_MAXID }; struct list secondlevel[] = { { 0, 0 }, /* CTL_UNbin/hostname/hostname.c 644 0 12 5541 5731217636 10417 /* * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * hostname.c,v 1.2 1994/09/24 02:55:40 davidg Exp */ #if defined(DOSCCS) & !defined(lint) static char copyright[] = "@(#) Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if defined(DOSCCS) & !defined(lint) static char sccsid[] = "@(#)hostname.c 8.1.1 (R.Birch) 8/2/95"; #endif /* not lint */ #include #include #include int main(argc,argv) int argc; char *argv[]; { extern int optind; int ch, sflag; char *p, hostname[MAXHOSTNAMELEN]; sflag = 0; while ((ch = getopt(argc, argv, "s")) != EOF) switch (ch) { case 's': sflag = 1; break; case '?': default: (void)fprintf(stderr, "usage: hostname [-s] [hostname]\n"); exit(1); } argc -= optind; argv += optind; if (*argv) { if (sethostname(*argv, strlen(*argv))) err(1, "sethostname"); } else { if (gethostname(hostname, sizeof(hostname))) err(1, "gethostname"); if (sflag && (p = strchr(hostname, '.'))) *p = '\0'; (void)printf("%s\n", hostname); } exit(0); } onditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the fbin/hostname/Makefile 640 0 12 1130 5731220156 10046 # # Public Domain. 1995/03/13 - Steven Schultz # # @(#)Makefile 1.0 (2.11BSD GTE) 1995/03/13 # CFLAGS= -O SEPFLAG= -i SRCS= hostname.c OBJS= hostname.o all: hostname hostname.0 hostname: ${OBJS} ${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS} hostname.0: hostname.1 /usr/man/manroff hostname.1 > hostname.0 clean: rm -f ${OBJS} tags hostname hostname.0 depend: ${SRCS} mkdep ${CFLAGS} ${SRCS} install: all install -s -o bin -g bin -m 755 hostname ${DESTDIR}/bin install -c -o bin -g bin -m 444 hostname.0 ${DESTDIR}/usr/man/cat1 lint: ${SRCS} lint -hax ${SRCS} tags: ${SRCS} ctags ${SRCS} distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specificbin/nm/ 755 0 12 0 6024535776 5143 bin/nm/nm.c 644 0 12 16305 5525114615 6021 #if !defined(lint) && !defined(DOSCCS) static char sccsid[] = "@(#)nm.c 2.11BSD 1/22/94"; #endif /* * nm - print name list. string table version */ #include #include #include #include #include #include #include #include "archive.h" #include CHDR chdr; #define SELECT archive ? chdr.name : *xargv char aflg, gflg, nflg, oflg, pflg, uflg, rflg = 1, archive; char **xargv; char *strp; union { char mag_armag[SARMAG+1]; struct xexec mag_exp; } mag_un; off_t off, skip(); extern off_t ftell(); extern char *malloc(); extern long strtol(); int compare(), narg, errs; main(argc, argv) int argc; char **argv; { if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) { argv++; while (*++*argv) switch (**argv) { case 'n': nflg++; continue; case 'g': gflg++; continue; case 'u': uflg++; continue; case 'r': rflg = -1; continue; case 'p': pflg++; continue; case 'o': oflg++; continue; case 'a': aflg++; continue; default: fprintf(stderr, "nm: invalid argument -%c\n", *argv[0]); exit(2); } argc--; } if (argc == 0) { argc = 1; argv[1] = "a.out"; } narg = argc; xargv = argv; while (argc--) { ++xargv; namelist(); } exit(errs); } namelist() { char ibuf[BUFSIZ]; register FILE *fi; archive = 0; fi = fopen(*xargv, "r"); if (fi == NULL) { error(0, "cannot open"); return; } setbuf(fi, ibuf); off = 0; fread((char *)&mag_un, 1, sizeof(mag_un), fi); if (strncmp(mag_un.mag_armag, ARMAG, SARMAG)==0) { archive++; off = SARMAG; } else if (N_BADMAG(mag_un.mag_exp.e)) { error(0, "bad format"); goto out; } rewind(fi); if (archive) { nextel(fi); if (narg > 1) printf("\n%s:\n", *xargv); } do { off_t o, curpos, stroff; long strsiz; register i, n; struct nlist *symp = NULL; struct nlist sym; curpos = ftell(fi); fread((char *)&mag_un.mag_exp, 1, sizeof(struct xexec), fi); if (N_BADMAG(mag_un.mag_exp.e)) continue; o = N_SYMOFF(mag_un.mag_exp); fseek(fi, curpos + o, L_SET); n = mag_un.mag_exp.e.a_syms / sizeof(struct nlist); if (n == 0) { error(0, "no name list"); continue; } i = 0; if (strp) free(strp), strp = 0; while (--n >= 0) { fread((char *)&sym, 1, sizeof(sym), fi); if (sym.n_un.n_strx == 0) continue; if (gflg && (sym.n_type & N_EXT) == 0) continue; if (uflg && (sym.n_type & N_TYPE) == N_UNDF && sym.n_value) continue; i++; } fseek(fi, curpos + o, L_SET); symp = (struct nlist *)malloc(i * sizeof (struct nlist)); if (symp == 0) error(1, "out of memory"); i = 0; n = mag_un.mag_exp.e.a_syms / sizeof(struct nlist); while (--n >= 0) { fread((char *)&sym, 1, sizeof(sym), fi); if (sym.n_un.n_strx == 0) continue; if (gflg && (sym.n_type & N_EXT) == 0) continue; if (uflg && (sym.n_type & N_TYPE) == N_UNDF && sym.n_value) continue; symp[i++] = sym; } stroff = curpos + N_STROFF(mag_un.mag_exp); fseek(fi, stroff, L_SET); if (fread(&strsiz, sizeof (long), 1, fi) != 1) error(1, "no string table"); strp = (char *)malloc((int)strsiz); if (strp == NULL || strsiz > 48 * 1024L) error(1, "ran out of memory"); if (fread(strp+sizeof(strsiz),(int)strsiz-sizeof(strsiz),1,fi) != 1) error(1, "error reading strings"); for (n = 0; n < i; n++) symp[n].n_un.n_name = strp + (int)symp[n].n_un.n_strx; if (pflg==0) qsort(symp, i, sizeof(struct nlist), compare); if ((archive || narg>1) && oflg==0) printf("\n%s:\n", SELECT); psyms(symp, i); if (symp) free((char *)symp), symp = NULL; if (strp) free((char *)strp), strp = NULL; } while(archive && nextel(fi)); out: fclose(fi); } psyms(symp, nsyms) register struct nlist *symp; int nsyms; { register int n, c; for (n=0; nn_value > p2->n_value) return(rflg); if (p1->n_value < p2->n_value) return(-rflg); } return (rflg * strcmp(p1->n_un.n_name, p2->n_un.n_name)); } nextel(af) FILE *af; { fseek(af, off, L_SET); if (get_arobj(af) < 0) return(0); off += (sizeof (struct ar_hdr) + chdr.size + (chdr.size + chdr.lname & 1)); return(1); } error(n, s) char *s; { fprintf(stderr, "nm: %s:", *xargv); if (archive) { fprintf(stderr, "(%s)", chdr.name); fprintf(stderr, ": "); } else fprintf(stderr, " "); fprintf(stderr, "%s\n", s); if (n) exit(2); errs = 1; } /* * "borrowed" from 'ar' because we didn't want to drag in everything else * from 'ar'. The error checking was also ripped out, basically if any * of the criteria for being an archive are not met then a -1 is returned * and the rest of 'ld' figures out what to do. */ typedef struct ar_hdr HDR; static char hb[sizeof(HDR) + 1]; /* real header */ /* Convert ar header field to an integer. */ #define AR_ATOI(from, to, len, base) { \ bcopy(from, buf, len); \ buf[len] = '\0'; \ to = strtol(buf, (char **)NULL, base); \ } /* * read the archive header for this member. Use a file pointer * rather than a file descriptor. */ get_arobj(fp) FILE *fp; { HDR *hdr; register int len, nr; register char *p; char buf[20]; nr = fread(hb, 1, sizeof(HDR), fp); if (nr != sizeof(HDR)) return(-1); hdr = (HDR *)hb; if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1)) return(-1); /* Convert the header into the internal format. */ #define DECIMAL 10 #define OCTAL 8 AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL); AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL); AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL); AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL); AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL); /* Leading spaces should never happen. */ if (hdr->ar_name[0] == ' ') return(-1); /* * Long name support. Set the "real" size of the file, and the * long name flag/size. */ if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) { chdr.lname = len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1); if (len <= 0 || len > MAXNAMLEN) return(-1); nr = fread(chdr.name, 1, (size_t)len, fp); if (nr != len) return(-1); chdr.name[len] = 0; chdr.size -= len; } else { chdr.lname = 0; bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name)); /* Strip trailing spaces, null terminate. */ for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p); *++p = '\0'; } return(1); } clude #include #include #include #include #include "archive.h" #include CHDR chdr; #define SELECT archive ? chdr.name : *xargv char aflg, gflg, nflg, oflg, pflg, uflg, rflg = 1, archive; char **xargv; char *strp; union { char mag_armag[SARMAG+1bin/nm/Makefile 644 0 12 324 5470072474 6642 SRCS= nm.c OBJS= nm.o CFLAGS= -O -I../ar all: nm nm: ${OBJS} cc -z -o nm ${OBJS} install: install -c -s -o bin -g bin -m 755 nm ${DESTDIR}/bin/nm lint: lint -havx -I../ar ${SRCS} clean: rm -f *.o *.0 nm bin/rmail.c 444 0 12 4771 4013202665 6055 #ifndef lint static char sccsid[] = "@(#)rmail.c 4.8 (Berkeley) 5/15/86"; #endif /* ** RMAIL -- UUCP mail server. ** ** This program reads the >From ... remote from ... lines that ** UUCP is so fond of and turns them into something reasonable. ** It calls sendmail giving it a -f option built from these ** lines. */ # include # include typedef char bool; #define TRUE 1 #define FALSE 0 extern FILE *popen(); extern char *index(); extern char *rindex(); bool Debug; # define MAILER "/usr/lib/sendmail" main(argc, argv) char **argv; { FILE *out; /* output to sendmail */ char lbuf[1024]; /* one line of the message */ char from[512]; /* accumulated path of sender */ char ufrom[512]; /* user on remote system */ char sys[512]; /* a system in path */ char junk[1024]; /* scratchpad */ char cmd[2000]; register char *cp; register char *uf = ufrom; /* ptr into ufrom */ int i; # ifdef DEBUG if (argc > 1 && strcmp(argv[1], "-T") == 0) { Debug = TRUE; argc--; argv++; } # endif DEBUG if (argc < 2) { fprintf(stderr, "Usage: rmail user ...\n"); exit(EX_USAGE); } (void) strcpy(from, ""); (void) strcpy(ufrom, "/dev/null"); for (;;) { (void) fgets(lbuf, sizeof lbuf, stdin); if (strncmp(lbuf, "From ", 5) != 0 && strncmp(lbuf, ">From ", 6) != 0) break; (void) sscanf(lbuf, "%s %s", junk, ufrom); cp = lbuf; for (;;) { cp = index(cp+1, 'r'); if (cp == NULL) { register char *p = rindex(uf, '!'); if (p != NULL) { *p = '\0'; (void) strcpy(sys, uf); uf = p + 1; break; } cp = "remote from somewhere"; } #ifdef DEBUG if (Debug) printf("cp='%s'\n", cp); #endif if (strncmp(cp, "remote from ", 12)==0) break; } if (cp != NULL) (void) sscanf(cp, "remote from %s", sys); (void) strcat(from, sys); (void) strcat(from, "!"); #ifdef DEBUG if (Debug) printf("ufrom='%s', sys='%s', from now '%s'\n", uf, sys, from); #endif } (void) strcat(from, uf); (void) sprintf(cmd, "%s -ee -f%s -i", MAILER, from); while (*++argv != NULL) { (void) strcat(cmd, " '"); if (**argv == '(') (void) strncat(cmd, *argv + 1, strlen(*argv) - 2); else (void) strcat(cmd, *argv); (void) strcat(cmd, "'"); } #ifdef DEBUG if (Debug) printf("cmd='%s'\n", cmd); #endif out = popen(cmd, "w"); fputs(lbuf, out); while (fgets(lbuf, sizeof lbuf, stdin)) fputs(lbuf, out); i = pclose(out); if ((i & 0377) != 0) { fprintf(stderr, "pclose: status 0%o\n", i); exit(EX_OSERR); } exit((i >> 8) & 0377); } pos + obin/chflags/ 755 0 12 0 6024535747 6136 bin/chflags/chflags.c 644 0 12 6713 5670270757 10010 /* * Program Name: symcompact.c * Date: December 3, 1994 * Author: S.M. Schultz * * ----------------- Modification History --------------- * Version Date Reason For Modification * 1.0 03Dec94 1. Initial release into the public domain. */ #include #include #include #include #include #include static char *fmsg = "Can't fchdir() back to starting directory"; static int oct, status, fflag, rflag; static u_short set, clear; static struct stat st; static void usage(); extern long strtol(); extern int optind, errno; extern u_short string_to_flags(); /* from ../ls */ main(argc, argv) int argc; char *argv[]; { register char *p; char *flags, *ep; int ch, fcurdir; long tmp; while ((ch = getopt(argc, argv, "Rf")) != EOF) { switch (ch) { case 'R': rflag++; break; case 'f': fflag++; break; case '?': default: usage(); } } argv += optind; argc += optind; if (argc < 2) usage(); flags = *argv++; if (*flags >= '0' && *flags <= '7') { tmp = strtol(flags, &ep, 8); if (tmp < 0 || tmp >= 64L*1024*1024 || *ep) die("invalid flags: %s", flags); oct = 1; set = tmp; } else { if (string_to_flags(&flags, &set, &clear)) die("invalid flag: %s", flags); clear = ~clear; oct = 0; } if (rflag) { fcurdir = open(".", O_RDONLY); if (fcurdir < 0) die("Can't open ."); } while (p = *argv++) { if (lstat(p, &st) < 0) { status |= warning(p); continue; } if (rflag && (st.st_mode&S_IFMT) == S_IFDIR) { status |= recurse(p, fcurdir); continue; } if ((st.st_mode&S_IFMT) == S_IFLNK && stat(p, &st) < 0) { status |= warning(p); continue; } if (chflags(p, newflags(st.st_flags)) < 0) { status |= warning(p); continue; } } close(fcurdir); exit(status); } recurse(dir, savedir) char *dir; int savedir; { register DIR *dirp; register struct direct *dp; int ecode; if (chdir(dir) < 0) { warning(dir); return(1); } if ((dirp = opendir(".")) == NULL) { warning(dir); return(1); } dp = readdir(dirp); dp = readdir(dirp); /* read "." and ".." */ ecode = 0; for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { if (lstat(dp->d_name, &st) < 0) { ecode = warning(dp->d_name); if (ecode) break; continue; } if ((st.st_mode&S_IFMT) == S_IFDIR) { ecode = recurse(dp->d_name, dirfd(dirp)); if (ecode) break; continue; } if ((st.st_mode&S_IFMT) == S_IFLNK) continue; if (chflags(dp->d_name, newflags(st.st_flags)) < 0 && (ecode = warning(dp->d_name))) break; } /* * Lastly change the flags on the directory we are in before returning to * the previous level. */ if (fstat(dirfd(dirp), &st) < 0) die("can't fstat ."); if (fchflags(dirfd(dirp), newflags(st.st_flags)) < 0) ecode = warning(dir); if (fchdir(savedir) < 0) die(fmsg); closedir(dirp); return(ecode); } /* VARARGS1 */ die(fmt, va_alist) char *fmt; va_dcl { va_list ap; va_start(ap); vfprintf(stderr, fmt, ap); fputc('\n', stderr); va_end(ap); exit(1); } warning(msg) char *msg; { if (!fflag) fprintf(stderr, "chflags: %s: %s\n", msg, strerror(errno)); return(!fflag); } newflags(flags) u_short flags; { if (oct) flags = set; else { flags |= set; flags &= clear; } return(flags); } static void usage() { fputs("usage: chflags [-Rf] flags file ...\n", stderr); exit(1); } ); if ((archive || narg>1) && oflg==0) printf("\bin/chflags/Makefile 644 0 12 1413 5677667274 7700 # # Public Domain. 12/3/1994 - Steven Schultz # # @(#)Makefile 1.1 (2.11BSD GTE) 12/26/94 # CFLAGS= -O SEPFLAG= -i VPATH= ../ls SRCS= chflags.c stat_flags.c strsep.c OBJS= chflags.o stat_flags.o strsep.o MAN= chflags.0 MANSRC= chflags.1 all: chflags chflags.0 chflags: ${OBJS} ${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS} chflags.0: ${MANSRC} /usr/man/manroff ${MANSRC} > ${MAN} clean: rm -f ${OBJS} ${MAN} chflags tags depend: ${SRCS} mkdep ${CFLAGS} ${SRCS} install: chflags install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat1 install -s -o root -g bin -m 755 chflags ${DESTDIR}/bin/chflags lint: ${SRCS} lint -hax ${SRCS} tags: ${SRCS} ctags ${SRCS} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. lags: ${OBJS} ${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS} chflags.0: ${MANSRC} /usr/man/manroff ${MANSRC} > ${MAN} clean: rm -f ${OBJS} ${MAN} chflags tags depend: ${SRCS} mkdep ${CFLAGS} ${SRCS} install: chflags install -c -o bin -g bin bin/chflags/chflags.1 644 0 12 6707 5673464206 7726 .\" Copyright (c) 1989, 1990, 1993, 1994 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" the Institute of Electrical and Electronics Engineers, Inc. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)chflags.1 8.2.1 (2.11BSD GTE) 11/28/94 .\" .TH CHFLAGS 1 "November 28, 1994" .UC 4 .SH NAME chflags \- change file flags .SH SYNOPSIS chflags [-R] [-f]\fBflags\fP \fBfile\fP ... .SH DESCRIPTION The .B chflags utility modifies the file flags of the listed files as specified by the .B flags operand. .PP The options are as follows: .TP 15 -R Change the file flags for the file hierarchies rooted in the files instead of just the files themselves. .PP -f \fBchflags\fP will not complain if it fails to change the flags on a file. .PP Flags are a comma separated list of keywords. The following keywords are currently defined: .TP 20 arch No effect. This bit is defined and will be set/cleared as requested but nothing in the system makes use of it yet. .TP 20 dump Set the dump flag .TP 20 sappnd Set the system append-only flag (super-user only) .TP 20 schg Set the system immutable flag (super-user only) .TP 20 uappnd Set the user append-only flag (owner or super-user only) .TP 20 uchg Set the user immutable flag (owner or super-user only) .PP Putting the letters .B no before an option causes the flag to be turned off. For example: .TP 20 nodump the file should never be dumped .PP Symbolic links do not have flags and are silently ignored by .B chflags. When the -R option is given and symbolic links are encountered they are not traversed. This is the same behaviour as \fBchmod(1)\fP. .PP The .B chflags utility exits 0 on success, and >0 if an error occurs. .SH SEE ALSO chflags(2), stat(2), symlink(7) } ); if ((archive || narg>1) && oflg==0) printf("\etc/ 755 0 12 0 6024524325 4520 etc/fsck/ 755 0 0 0 6024536031 5420 etc/fsck/Makefile 640 0 0 2606 4613634745 7162 # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.8 (Berkeley) 9/7/85 # DESTDIR= CFLAGS= -O LFLAGS= -i # The program itself # PROG= fsck # Sources # SRCS= dir.c inode.c main.c pass1.c pass1b.c pass2.c \ pass3.c pass4.c pass5.c setup.c utilities.c # Objects # OBJS= ${LOCOBJS} LOCOBJS=dir.o inode.o main.o pass1.o pass1b.o pass2.o \ pass3.o pass4.o pass5.o setup.o utilities.o # Header files # HDRS= fsck.h ${PROG}: ${OBJS} ${HDRS} cc ${LFLAGS} -o ${PROG} ${OBJS} ${LOCOBJS}: cc ${CFLAGS} -c $*.c install: ${PROG} install -s ${PROG} ${DESTDIR}/etc/${PROG} clean: rm -f a.out core ${OBJS} ${PROG} lint: lint ${INCPATH} ${SRCS} depend: cc -M ${INCPATH} ${SRCS} | \ awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ else rec = rec " " $$2 } } \ END { print rec } ' > makedep echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep echo '$$r makedep' >>eddep echo 'w' >>eddep cp Makefile Makefile.bak ed - Makefile < eddep rm eddep makedep echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile echo '# see make depend above' >> Makefile # DO NOT DELETE THIS LINE -- make depend uses it TNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIetc/fsck/dir.c 640 0 0 31170 4674567173 6471 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)dir.c 5.1 (Berkeley) 6/5/85"; #endif not lint #include #include #include #include #include "fsck.h" #define MINDIRSIZE (sizeof (struct dirtemplate)) char *endpathname = &pathname[MAXPATHLEN - 2]; char *lfname = "lost+found"; struct dirtemplate emptydir = { 0, DIRBLKSIZ }; struct dirtemplate dirhead = { 0, 8, 1, ".", 0, DIRBLKSIZ - 8, 2, ".." }; DIRECT *fsck_readdir(); descend(parentino, inumber) struct inodesc *parentino; ino_t inumber; { register DINODE *dp; struct inodesc curino; bzero((char *)&curino, sizeof(struct inodesc)); if (getstate(inumber) != DSTATE) errexit("BAD INODE %u TO DESCEND", getstate(inumber)); setstate(inumber, DFOUND); dp = ginode(inumber); if (dp->di_size == 0) { direrr(inumber, "ZERO LENGTH DIRECTORY"); if (reply("REMOVE") == 1) setstate(inumber, DCLEAR); return; } if (dp->di_size < MINDIRSIZE) { direrr(inumber, "DIRECTORY TOO SHORT"); dp->di_size = MINDIRSIZE; if (reply("FIX") == 1) inodirty(); } if ((dp->di_size & (DIRBLKSIZ - 1)) != 0) { pwarn("DIRECTORY %s: LENGTH %ld NOT MULTIPLE OF %d", pathname, dp->di_size, DIRBLKSIZ); dp->di_size = roundup(dp->di_size, DIRBLKSIZ); if (preen) printf(" (ADJUSTED)\n"); if (preen || reply("ADJUST") == 1) inodirty(); } curino.id_type = DATA; curino.id_func = parentino->id_func; curino.id_parent = parentino->id_number; curino.id_number = inumber; (void)ckinode(dp, &curino); } dirscan(idesc) register struct inodesc *idesc; { register DIRECT *dp; int dsize, n, *ii; char dbuf[DIRBLKSIZ]; if (idesc->id_type != DATA) errexit("wrong type to dirscan %d\n", idesc->id_type); if (idesc->id_entryno == 0 && (idesc->id_filesize & (DIRBLKSIZ - 1)) != 0) idesc->id_filesize = roundup(idesc->id_filesize, DIRBLKSIZ); if (outrange(idesc->id_blkno)) { idesc->id_filesize -= DEV_BSIZE; return (SKIP); } idesc->id_loc = 0; for (dp = fsck_readdir(idesc); dp != NULL; dp = fsck_readdir(idesc)) { dsize = dp->d_reclen; bcopy((char *)dp, dbuf, dsize); idesc->id_dirp = (DIRECT *)dbuf; if ((n = (*idesc->id_func)(idesc)) & ALTERED) { getblk(&fileblk, idesc->id_blkno); if (fileblk.b_errs != NULL) { n &= ~ALTERED; } else { bcopy(dbuf, (char *)dp, dsize); dirty(&fileblk); sbdirty(); } } if (n & STOP) return (n); } return (idesc->id_filesize > 0 ? KEEPON : STOP); } /* * get next entry in a directory. */ DIRECT * fsck_readdir(idesc) register struct inodesc *idesc; { register DIRECT *dp, *ndp; u_int size; getblk(&fileblk, idesc->id_blkno); if (fileblk.b_errs != NULL) { idesc->id_filesize -= DEV_BSIZE - idesc->id_loc; return NULL; } if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 && idesc->id_loc < DEV_BSIZE) { dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); if (dircheck(idesc, dp)) goto dpok; idesc->id_loc += DIRBLKSIZ; idesc->id_filesize -= DIRBLKSIZ; dp->d_reclen = DIRBLKSIZ; dp->d_ino = 0; dp->d_namlen = 0; dp->d_name[0] = '\0'; if (dofix(idesc, "DIRECTORY CORRUPTED")) dirty(&fileblk); return (dp); } dpok: if (idesc->id_filesize <= 0 || idesc->id_loc >= DEV_BSIZE) return NULL; dp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); idesc->id_loc += dp->d_reclen; idesc->id_filesize -= dp->d_reclen; if ((idesc->id_loc % DIRBLKSIZ) == 0) return (dp); ndp = (DIRECT *)(dirblk.b_buf + idesc->id_loc); if (idesc->id_loc < DEV_BSIZE && idesc->id_filesize > 0 && dircheck(idesc, ndp) == 0) { size = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); dp->d_reclen += size; idesc->id_loc += size; idesc->id_filesize -= size; if (dofix(idesc, "DIRECTORY CORRUPTED")) dirty(&fileblk); } return (dp); } /* * Verify that a directory entry is valid. * This is a superset of the checks made in the kernel. */ dircheck(idesc, dp) struct inodesc *idesc; register DIRECT *dp; { register int size; register char *cp; int spaceleft; size = DIRSIZ(dp); spaceleft = DIRBLKSIZ - (idesc->id_loc % DIRBLKSIZ); if (dp->d_ino < imax && dp->d_reclen != 0 && dp->d_reclen <= spaceleft && (dp->d_reclen & 0x3) == 0 && dp->d_reclen >= size && idesc->id_filesize >= size && dp->d_namlen <= MAXNAMLEN) { if (dp->d_ino == 0) return (1); for (cp = dp->d_name, size = 0; size < dp->d_namlen; size++) if (*cp == 0 || (*cp++ & 0200)) return (0); if (*cp == 0) return (1); } return (0); } direrr(ino, s) ino_t ino; char *s; { register DINODE *dp; pwarn("%s ", s); pinode(ino); printf("\n"); if (ino < ROOTINO || ino > imax) { pfatal("NAME=%s\n", pathname); return; } dp = ginode(ino); if (ftypeok(dp)) pfatal("%s=%s\n", DIRCT(dp) ? "DIR" : "FILE", pathname); else pfatal("NAME=%s\n", pathname); } adjust(idesc, lcnt) register struct inodesc *idesc; short lcnt; { register DINODE *dp; dp = ginode(idesc->id_number); if (dp->di_nlink == lcnt) { if (linkup(idesc->id_number, (ino_t)0) == 0) clri(idesc, "UNREF", 0); } else { pwarn("LINK COUNT %s", (lfdir == idesc->id_number) ? lfname : (DIRCT(dp) ? "DIR" : "FILE")); pinode(idesc->id_number); printf(" COUNT %u SHOULD BE %u", dp->di_nlink, dp->di_nlink-lcnt); if (preen) { if (lcnt < 0) { printf("\n"); pfatal("LINK COUNT INCREASING"); } printf(" (ADJUSTED)\n"); } if (preen || reply("ADJUST") == 1) { dp->di_nlink -= lcnt; inodirty(); } } } mkentry(idesc) struct inodesc *idesc; { register DIRECT *dirp = idesc->id_dirp; DIRECT newent; int newlen, oldlen; newent.d_namlen = 11; newlen = DIRSIZ(&newent); if (dirp->d_ino != 0) oldlen = DIRSIZ(dirp); else oldlen = 0; if (dirp->d_reclen - oldlen < newlen) return (KEEPON); newent.d_reclen = dirp->d_reclen - oldlen; dirp->d_reclen = oldlen; dirp = (struct direct *)(((char *)dirp) + oldlen); dirp->d_ino = idesc->id_parent; /* ino to be entered is in id_parent */ dirp->d_reclen = newent.d_reclen; dirp->d_namlen = strlen(idesc->id_name); bcopy(idesc->id_name, dirp->d_name, dirp->d_namlen + 1); return (ALTERED|STOP); } chgino(idesc) struct inodesc *idesc; { register DIRECT *dirp = idesc->id_dirp; if (bcmp(dirp->d_name, idesc->id_name, dirp->d_namlen + 1)) return (KEEPON); dirp->d_ino = idesc->id_parent;; return (ALTERED|STOP); } linkup(orphan, pdir) ino_t orphan; ino_t pdir; { register DINODE *dp; int lostdir, len; ino_t oldlfdir; struct inodesc idesc; char tempname[MAXPATHLEN]; extern int pass4check(); bzero((char *)&idesc, sizeof(struct inodesc)); dp = ginode(orphan); lostdir = DIRCT(dp); pwarn("UNREF %s ", lostdir ? "DIR" : "FILE"); pinode(orphan); if (preen && dp->di_size == 0) return (0); if (preen) printf(" (RECONNECTED)\n"); else if (reply("RECONNECT") == 0) return (0); pathp = pathname; *pathp++ = '/'; *pathp = '\0'; if (lfdir == 0) { dp = ginode(ROOTINO); idesc.id_name = lfname; idesc.id_type = DATA; idesc.id_func = findino; idesc.id_number = ROOTINO; (void)ckinode(dp, &idesc); if (idesc.id_parent >= ROOTINO && idesc.id_parent < imax) { lfdir = idesc.id_parent; } else { pwarn("NO lost+found DIRECTORY"); if (preen || reply("CREATE")) { lfdir = allocdir(ROOTINO, 0); if (lfdir != 0) { if (makeentry(ROOTINO, lfdir, lfname) != 0) { if (preen) printf(" (CREATED)\n"); } else { freedir(lfdir, ROOTINO); lfdir = 0; if (preen) printf("\n"); } } } } if (lfdir == 0) { pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY"); printf("\n\n"); return (0); } } dp = ginode(lfdir); if (!DIRCT(dp)) { pfatal("lost+found IS NOT A DIRECTORY"); if (reply("REALLOCATE") == 0) return (0); oldlfdir = lfdir; if ((lfdir = allocdir(ROOTINO, 0)) == 0) { pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); return (0); } idesc.id_type = DATA; idesc.id_func = chgino; idesc.id_number = ROOTINO; idesc.id_parent = lfdir; /* new inumber for lost+found */ idesc.id_name = lfname; if ((ckinode(ginode(ROOTINO), &idesc) & ALTERED) == 0) { pfatal("SORRY. CANNOT CREATE lost+found DIRECTORY\n\n"); return (0); } inodirty(); idesc.id_type = ADDR; idesc.id_func = pass4check; idesc.id_number = oldlfdir; adjust(&idesc, getlncnt(oldlfdir) + 1); setlncnt(oldlfdir, 0); dp = ginode(lfdir); } if (getstate(lfdir) != DFOUND) { pfatal("SORRY. NO lost+found DIRECTORY\n\n"); return (0); } len = strlen(lfname); bcopy(lfname, pathp, len + 1); pathp += len; len = lftempname(tempname, orphan); if (makeentry(lfdir, orphan, tempname) == 0) { pfatal("SORRY. NO SPACE IN lost+found DIRECTORY"); printf("\n\n"); return (0); } declncnt(orphan); *pathp++ = '/'; bcopy(idesc.id_name, pathp, len + 1); pathp += len; if (lostdir) { dp = ginode(orphan); idesc.id_type = DATA; idesc.id_func = chgino; idesc.id_number = orphan; idesc.id_fix = DONTKNOW; idesc.id_name = ".."; idesc.id_parent = lfdir; /* new value for ".." */ (void)ckinode(dp, &idesc); dp = ginode(lfdir); dp->di_nlink++; inodirty(); inclncnt(lfdir); pwarn("DIR I=%u CONNECTED. ", orphan); printf("PARENT WAS I=%u\n", pdir); if (preen == 0) printf("\n"); } return (1); } /* * make an entry in a directory */ makeentry(parent, ino, name) ino_t parent, ino; char *name; { DINODE *dp; struct inodesc idesc; if (parent < ROOTINO || parent >= imax || ino < ROOTINO || ino >= imax) return (0); bzero(&idesc, sizeof(struct inodesc)); idesc.id_type = DATA; idesc.id_func = mkentry; idesc.id_number = parent; idesc.id_parent = ino; /* this is the inode to enter */ idesc.id_fix = DONTKNOW; idesc.id_name = name; dp = ginode(parent); if (dp->di_size % DIRBLKSIZ) { dp->di_size = roundup(dp->di_size, DIRBLKSIZ); inodirty(); } if ((ckinode(dp, &idesc) & ALTERED) != 0) return (1); if (expanddir(dp) == 0) return (0); return (ckinode(dp, &idesc) & ALTERED); } /* * Attempt to expand the size of a directory */ expanddir(dp) register DINODE *dp; { daddr_t lastbn, newblk; char *cp, firstblk[DIRBLKSIZ]; lastbn = lblkno(dp->di_size); if (lastbn >= NDADDR - 1) return (0); if ((newblk = allocblk()) == 0) return (0); dp->di_addr[lastbn + 1] = dp->di_addr[lastbn]; dp->di_addr[lastbn] = newblk; dp->di_size += DEV_BSIZE; getblk(&fileblk, dp->di_addr[lastbn + 1]); if (fileblk.b_errs != NULL) goto bad; bcopy(dirblk.b_buf, firstblk, DIRBLKSIZ); getblk(&fileblk, newblk); if (fileblk.b_errs != NULL) goto bad; bcopy(firstblk, dirblk.b_buf, DIRBLKSIZ); for (cp = &dirblk.b_buf[DIRBLKSIZ]; cp < &dirblk.b_buf[DEV_BSIZE]; cp += DIRBLKSIZ) bcopy((char *)&emptydir, cp, sizeof emptydir); dirty(&fileblk); getblk(&fileblk, dp->di_addr[lastbn + 1]); if (fileblk.b_errs != NULL) goto bad; bcopy((char *)&emptydir, dirblk.b_buf, sizeof emptydir); pwarn("NO SPACE LEFT IN %s", pathname); if (preen) printf(" (EXPANDED)\n"); else if (reply("EXPAND") == 0) goto bad; dirty(&fileblk); inodirty(); return (1); bad: dp->di_addr[lastbn] = dp->di_addr[lastbn + 1]; dp->di_addr[lastbn + 1] = 0; dp->di_size -= DEV_BSIZE; fr_blk(newblk); return (0); } /* * allocate a new directory */ allocdir(parent, request) ino_t parent, request; { ino_t ino; char *cp; DINODE *dp; int st; ino = allocino(request, IFDIR|0755); dirhead.dot_ino = ino; dirhead.dotdot_ino = parent; dp = ginode(ino); getblk(&fileblk, dp->di_addr[0]); if (fileblk.b_errs != NULL) { freeino(ino); return (0); } bcopy((char *)&dirhead, dirblk.b_buf, sizeof dirhead); for (cp = &dirblk.b_buf[DIRBLKSIZ]; cp < &dirblk.b_buf[DEV_BSIZE]; cp += DIRBLKSIZ) bcopy((char *)&emptydir, cp, sizeof emptydir); dirty(&fileblk); dp->di_nlink = 2; inodirty(); if (ino == ROOTINO) { setlncnt(ino, dp->di_nlink); return(ino); } st = getstate(parent); if (st != DSTATE && st != DFOUND) { freeino(ino); return (0); } setstate(ino, st); if (st == DSTATE) { setlncnt(ino, dp->di_nlink); inclncnt(parent); } dp = ginode(parent); dp->di_nlink++; inodirty(); return (ino); } /* * free a directory inode */ freedir(ino, parent) ino_t ino, parent; { DINODE *dp; if (ino != parent) { dp = ginode(parent); dp->di_nlink--; inodirty(); } freeino(ino); } /* * generate a temporary name for the lost+found directory. */ lftempname(bufp, ino) char *bufp; ino_t ino; { register ino_t in; register char *cp; int namlen; cp = bufp + 2; for (in = imax; in > 0; in /= 10) cp++; *--cp = 0; namlen = cp - bufp; in = ino; while (cp > bufp) { *--cp = (in % 10) + '0'; in /= 10; } *cp = '#'; return (namlen); } get next entry in a directory. */ DIRECT * fsck_readdir(idesc) register struct inodesc *idesc; { register DIRECT *dp, *ndp; u_int size; getblk(&fileblk, idesc->id_blkno); if (fileblk.b_errs != NULL) { idesc->id_filesize -= DEV_BSIZE - idesc->id_loc; return NULL; } if (idesc->id_loc % DIRBLKSIZ == 0 && idesc->id_filesize > 0 && idesc->id_loc < DEV_BSIZE) { dp = (DIRECT *etc/fsck/fsck.h 640 0 0 15525 4615630435 6637 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)fsck.h 5.1 (Berkeley) 6/5/85 */ #define MAXDUP 10 /* limit on dup blks (per inode) */ #define MAXBAD 10 /* limit on bad blks (per inode) */ #define STEPSIZE 7 /* default step for freelist spacing */ #define CYLSIZE 400 /* default cyl size for spacing */ #define MAXCYL 500 /* maximum cylinder size */ typedef int (*SIG_TYP)(); #ifndef BUFSIZ #define BUFSIZ 1024 #endif #define USTATE 01 /* inode not allocated */ #define FSTATE 02 /* inode is file */ #define DSTATE 03 /* inode is directory */ #define DFOUND 04 /* directory found during descent */ #define DCLEAR 05 /* directory is to be cleared */ #define FCLEAR 06 /* file is to be cleared */ #define BITSPB 8 /* number bits per byte */ #define BITSHIFT 3 /* log2(BITSPB) */ #define BITMASK 07 /* BITSPB-1 */ #define LSTATE 4 /* bits per inode state */ #define STATEPB (BITSPB/LSTATE) /* inode states per byte */ #define SMASK 017 /* mask for inode state */ typedef struct dinode DINODE; typedef struct direct DIRECT; #define ALLOC(dip) (((dip)->di_mode & IFMT) != 0) #define DIRCT(dip) (((dip)->di_mode & IFMT) == IFDIR) #define SPECIAL(dip) \ (((dip)->di_mode & IFMT) == IFBLK || ((dip)->di_mode & IFMT) == IFCHR) #define MAXNINDIR (MAXBSIZE / sizeof (daddr_t)) #define MAXINOPB (MAXBSIZE / sizeof (struct dinode)) #define SPERB (MAXBSIZE / sizeof(short)) struct bufarea { struct bufarea *b_next; /* must be first */ daddr_t b_bno; int b_size; int b_errs; union { char b_buf[MAXBSIZE]; /* buffer space */ short b_lnks[SPERB]; /* link counts */ daddr_t b_indir[MAXNINDIR]; /* indirect block */ struct fs b_fs; /* super block */ struct fblk b_fb; /* free block */ struct dinode b_dinode[MAXINOPB]; /* inode block */ } b_un; char b_dirty; }; typedef struct bufarea BUFAREA; BUFAREA inoblk; /* inode blocks */ BUFAREA fileblk; /* other blks in filesys */ BUFAREA sblk; /* file system superblock */ BUFAREA *poolhead; /* ptr to first buffer in pool */ #define initbarea(x) (x)->b_dirty = 0;(x)->b_bno = (daddr_t)-1 #define dirty(x) (x)->b_dirty = 1 #define inodirty() inoblk.b_dirty = 1 #define fbdirty() fileblk.b_dirty = 1 #define sbdirty() sblk.b_dirty = 1 #define dirblk fileblk.b_un #define freeblk fileblk.b_un.b_fb #define sblock sblk.b_un.b_fs struct filecntl { int rfdes; int wfdes; int mod; } dfile, sfile; /* file descriptors for filesys/scratch files */ enum fixstate {DONTKNOW, NOFIX, FIX}; struct inodesc { enum fixstate id_fix; /* policy on fixing errors */ int (*id_func)(); /* function to be applied to blocks of inode */ ino_t id_number; /* inode number described */ ino_t id_parent; /* for DATA nodes, their parent */ daddr_t id_blkno; /* current block number being examined */ long id_filesize; /* for DATA nodes, the size of the directory */ off_t id_loc; /* for DATA nodes, current location in dir */ u_long id_entryno; /* for DATA nodes, current entry number */ DIRECT *id_dirp; /* for DATA nodes, ptr to current entry */ char *id_name; /* for DATA nodes, name to find or enter */ char id_type; /* type of descriptor, DATA or ADDR */ }; /* file types */ #define DATA 1 #define ADDR 2 /* * Linked list of duplicate blocks. * * The list is composed of two parts. The first part of the * list (from duplist through the node pointed to by muldup) * contains a single copy of each duplicate block that has been * found. The second part of the list (from muldup to the end) * contains duplicate blocks that have been found more than once. * To check if a block has been found as a duplicate it is only * necessary to search from duplist through muldup. To find the * total number of times that a block has been found as a duplicate * the entire list must be searched for occurences of the block * in question. The following diagram shows a sample list where * w (found twice), x (found once), y (found three times), and z * (found once) are duplicate block numbers: * * w -> y -> x -> z -> y -> w -> y * ^ ^ * | | * duplist muldup */ #define DUPTBLSIZE 100 daddr_t duplist[DUPTBLSIZE]; /* head of dup list */ daddr_t *enddup; /* next entry in dup table */ daddr_t *muldup; /* multiple dups part of table */ /* * List of inodes with zero link counts. */ #define MAXLNCNT 50 ino_t zlnlist[MAXLNCNT]; /* zero link count table */ ino_t *zlnp; #define MAXDATA ((unsigned)56 * 1024) #define MEMUNIT 64 #define NINOBLK 4 /* number of blocks of inodes to read at once */ char inobuf[NINOBLK*INOPB*sizeof (struct dinode)]; /* allocate now */ daddr_t startib; unsigned int memsize; char rawflg; char *devname; char nflag; /* assume a no response */ char yflag; /* assume a yes response */ char sflag; /* rebuild free list */ int debug; /* output debugging info */ char preen; /* just fix normal inconsistencies */ char hotroot; /* checking root device */ char fixfree; /* force rebuild of freelist */ char *membase; /* base of memory we get */ char *blockmap; /* ptr to primary blk allocation map */ char *freemap; /* ptr to secondary blk allocation map */ char *statemap; /* ptr to inode state table */ short *lncntp; /* ptr to link count table */ char pathname[MAXPATHLEN]; /* current pathname */ char scrfile[80]; /* scratchfile name */ int cylsize; /* num blocks per cylinder */ int stepsize; /* num blocks for spacing purposes */ char *pathp; /* pointer to pathname position */ char *endpathname; daddr_t fmin; /* block number of the first data block */ daddr_t fmax; /* number of blocks in the volume */ ino_t imax; /* number of inodes */ ino_t lastino; /* hiwater mark of inodes */ ino_t lfdir; /* lost & found directory inode number */ char *lfname; /* lost & found directory name */ off_t bmapsz; /* num chars in blockmap */ daddr_t bmapblk; /* starting blk of block map */ daddr_t smapblk; /* starting blk of state map */ daddr_t lncntblk; /* starting blk of link cnt table */ daddr_t fmapblk; /* starting blk of free map */ daddr_t n_blks; /* number of blocks used */ daddr_t n_files; /* number of files seen */ daddr_t n_free; /* number of free blocks */ int badblk, dupblk; #define outrange(x) (x < fmin || x >= fmax) #define zapino(x) (*(x) = zino) struct dinode zino; #define setlncnt(x,n) dolncnt(x,0,n) #define getlncnt(x) dolncnt(x,1,0) #define declncnt(x) dolncnt(x,2,0) #define inclncnt(x) dolncnt(x,3,0) #define setbmap(x) domap(x,0) #define getbmap(x) domap(x,1) #define clrbmap(x) domap(x,2) #define setfmap(x) domap(x,0+4) #define getfmap(x) domap(x,1+4) #define clrfmap(x) domap(x,2+4) #define setstate(x,y) dostate(x,y,0) #define getstate(x) dostate(x,0,1) #define ALTERED 010 #define KEEPON 04 #define SKIP 02 #define STOP 01 time_t time(); DINODE *ginode(); BUFAREA *getblk(); int findino(); daddr_t allocblk(); if (lostdir) { dp = ginode(orphan); idesc.id_type = DATA; idesc.id_func = chgino; idesc.id_number = orphan; idesc.id_fix = DONTKNOW; idesc.id_name = ".."; ietc/fsck/inode.c 640 0 0 13553 4674567334 7015 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)inode.c 5.2 (Berkeley) 7/17/85"; #endif not lint #include #include #include #include #include #include "fsck.h" ckinode(dp, idesc) DINODE *dp; register struct inodesc *idesc; { register daddr_t *ap; int ret, n; DINODE dino; idesc->id_fix = DONTKNOW; idesc->id_entryno = 0; idesc->id_filesize = dp->di_size; if (SPECIAL(dp)) return (KEEPON); dino = *dp; for (ap = &dino.di_addr[0]; ap < &dino.di_addr[NDADDR]; ap++) { if (*ap == 0) continue; idesc->id_blkno = *ap; if (idesc->id_type == ADDR) ret = (*idesc->id_func)(idesc); else ret = dirscan(idesc); if (ret & STOP) return (ret); } for (ap = &dino.di_addr[NDADDR], n = 1; n <= NIADDR; ap++, n++) { if (*ap) { idesc->id_blkno = *ap; ret = iblock(idesc, n, dino.di_size - DEV_BSIZE * NDADDR); if (ret & STOP) return (ret); } } return (KEEPON); } iblock(idesc, ilevel, isize) struct inodesc *idesc; register ilevel; long isize; { register daddr_t *ap; register daddr_t *aplim; int i, n, (*func)(), nif; long sizepb; BUFAREA ib; char buf[128]; extern int pass1check(), dirscan(); if (idesc->id_type == ADDR) { func = idesc->id_func; if (((n = (*func)(idesc)) & KEEPON) == 0) return (n); } else func = dirscan; if (outrange(idesc->id_blkno)) /* protect thyself */ return (SKIP); initbarea(&ib); getblk(&ib, idesc->id_blkno); if (ib.b_errs != NULL) return (SKIP); ilevel--; for (sizepb = DEV_BSIZE, i = 0; i < ilevel; i++) sizepb *= NINDIR; nif = isize / sizepb + 1; if (nif > NINDIR) nif = NINDIR; if (idesc->id_func == pass1check && nif < NINDIR) { aplim = &ib.b_un.b_indir[NINDIR]; for (ap = &ib.b_un.b_indir[nif]; ap < aplim; ap++) { if (*ap == 0) continue; sprintf(buf, "PARTIALLY TRUNCATED INODE I=%u", idesc->id_number); if (dofix(idesc, buf)) { *ap = 0; dirty(&ib); } } flush(&dfile, &ib); } aplim = &ib.b_un.b_indir[nif]; for (ap = ib.b_un.b_indir, i = 1; ap < aplim; ap++, i++) if (*ap) { idesc->id_blkno = *ap; if (ilevel > 0) n = iblock(idesc, ilevel, isize - i * sizepb); else n = (*func)(idesc); if (n & STOP) return (n); } return (KEEPON); } DINODE * ginode(inumber) register ino_t inumber; { daddr_t iblk; register DINODE *dp; if (inumber < ROOTINO || inumber > imax) errexit("bad inode number %u to ginode\n", inumber); iblk = itod(inumber); if (iblk < startib || iblk >= startib + NINOBLK) { if (inoblk.b_dirty) { bwrite(&dfile, inobuf, startib, NINOBLK * DEV_BSIZE); inoblk.b_dirty = 0; } if (bread(&dfile, inobuf, iblk, NINOBLK * DEV_BSIZE)) return(NULL); startib = iblk; } dp = (DINODE *) &inobuf[(unsigned)((iblk-startib)<id_number); if (flg == 1) { pwarn("%s %s", s, DIRCT(dp) ? "DIR" : "FILE"); pinode(idesc->id_number); } if (preen || reply("CLEAR") == 1) { if (preen) printf(" (CLEARED)\n"); n_files--; (void)ckinode(dp, idesc); zapino(dp); setstate(idesc->id_number, USTATE); inodirty(); } } findname(idesc) struct inodesc *idesc; { register DIRECT *dirp = idesc->id_dirp; if (dirp->d_ino != idesc->id_parent) return (KEEPON); bcopy(dirp->d_name, idesc->id_name, dirp->d_namlen + 1); return (STOP); } findino(idesc) struct inodesc *idesc; { register DIRECT *dirp = idesc->id_dirp; if (dirp->d_ino == 0) return (KEEPON); if (strcmp(dirp->d_name, idesc->id_name) == 0 && dirp->d_ino >= ROOTINO && dirp->d_ino <= imax) { idesc->id_parent = dirp->d_ino; return (STOP); } return (KEEPON); } pinode(ino) ino_t ino; { register DINODE *dp; register char *p; struct passwd *pw; char *ctime(); printf(" I=%u ", ino); if (ino < ROOTINO || ino > imax) return; dp = ginode(ino); printf(" OWNER="); if ((pw = getpwuid((int)dp->di_uid)) != 0) printf("%s ", pw->pw_name); else printf("%u ", dp->di_uid); printf("MODE=%o\n", dp->di_mode); if (preen) printf("%s: ", devname); printf("SIZE=%ld ", dp->di_size); p = ctime(&dp->di_mtime); printf("MTIME=%12.12s %4.4s ", p+4, p+20); } blkerr(ino, s, blk) ino_t ino; char *s; daddr_t blk; { pfatal("%ld %s I=%u", blk, s, ino); printf("\n"); switch (getstate(ino)) { case FSTATE: setstate(ino, FCLEAR); return; case DSTATE: setstate(ino, DCLEAR); return; case FCLEAR: case DCLEAR: return; default: errexit("BAD STATE %d TO BLKERR", getstate(ino)); /* NOTREACHED */ } } /* * allocate an unused inode */ ino_t allocino(request, type) ino_t request; int type; { register ino_t ino; register DINODE *dp; if (request == 0) request = ROOTINO; else if (getstate(request) != USTATE) return (0); for (ino = request; ino < imax; ino++) if (getstate(ino) == USTATE) break; if (ino == imax) return (0); switch (type & IFMT) { case IFDIR: setstate(ino, DSTATE); break; case IFREG: case IFLNK: setstate(ino, FSTATE); break; default: return (0); } dp = ginode(ino); dp->di_addr[0] = allocblk(); if (dp->di_addr[0] == 0) { setstate(ino, USTATE); return (0); } dp->di_mode = type; time(&dp->di_atime); dp->di_mtime = dp->di_ctime = dp->di_atime; dp->di_size = DEV_BSIZE; n_files++; inodirty(); return (ino); } /* * deallocate an inode */ freeino(ino) ino_t ino; { struct inodesc idesc; extern int pass4check(); DINODE *dp; bzero((char *)&idesc, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass4check; idesc.id_number = ino; dp = ginode(ino); (void)ckinode(dp, &idesc); zapino(dp); inodirty(); setstate(ino, USTATE); n_files--; } */ char preen; /* just fix normal inconsistencies */ char hotroot; /* checking root device */ char fixfree; /* force rebuild of freelist */ char etc/fsck/main.c 640 0 0 15736 4635457350 6641 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)main.c 5.4 (Berkeley) 3/5/86"; #endif not lint #include #include #include #include #include #include #include #include "fsck.h" #include char *rawname(), *unrawname(), *blockcheck(); int catch(), catchquit(), voidquit(); int returntosingle; int (*signal())(); main(argc, argv) int argc; char *argv[]; { struct fstab *fsp; int pid, passno, anygtr, sumstatus; char *name, inbuf[128], outbuf[128]; setbuffer(stdin, inbuf, sizeof (inbuf)); setbuffer(stdout, outbuf, sizeof (outbuf)); setlinebuf(stdout); sync(); while (--argc > 0 && **++argv == '-') { switch (*++*argv) { case 's': sflag++; stype(++*argv); argc--; break; case 't': case 'T': if (**++argv == '-' || --argc <= 0) errexit("Bad -t option"); strcpy(scrfile, *argv); break; case 'p': preen++; break; case 'd': debug++; break; case 'n': /* default no answer flag */ case 'N': nflag++; yflag = 0; break; case 'y': /* default yes answer flag */ case 'Y': yflag++; nflag = 0; break; default: errexit("%c option?\n", **argv); } } /* * fsck has a problem under a 4BSD C library in that if its done * its sbrk's before it accesses FSTAB, there's no space left * for stdio. There may be other problems like this. Enjoy. */ if (!getfsent()) errexit("Can't open checklist file: %s\n",FSTAB); setpassent(1); memsize = sbrk(0); memsize = MAXDATA - memsize - sizeof(int); while (memsize >= 2 * sizeof(BUFAREA) && (membase = (char *)sbrk(memsize)) == (char *)-1) memsize -= MEMUNIT; if (memsize < 2 * sizeof(BUFAREA)) errexit("Can't get memory\n"); if (signal(SIGINT, SIG_IGN) != SIG_IGN) (void)signal(SIGINT, catch); if (preen) (void)signal(SIGQUIT, catchquit); if (argc) { while (argc-- > 0) { hotroot = 0; checkfilesys(*argv++); } exit(0); } sumstatus = 0; passno = 1; do { anygtr = 0; if (setfsent() == 0) errexit("Can't open checklist file: %s\n", FSTAB); while ((fsp = getfsent()) != 0) { if (strcmp(fsp->fs_type, FSTAB_RW) && strcmp(fsp->fs_type, FSTAB_RO) && strcmp(fsp->fs_type, FSTAB_RQ)) continue; if (preen == 0 || passno == 1 && fsp->fs_passno == passno) { name = blockcheck(fsp->fs_spec); if (name != NULL) checkfilesys(name); else if (preen) exit(8); } else if (fsp->fs_passno > passno) { anygtr = 1; } else if (fsp->fs_passno == passno) { pid = fork(); if (pid < 0) { perror("fork"); exit(8); } if (pid == 0) { (void)signal(SIGQUIT, voidquit); name = blockcheck(fsp->fs_spec); if (name == NULL) exit(8); checkfilesys(name); exit(0); } } } if (preen) { union wait status; while (wait(&status) != -1) sumstatus |= status.w_retcode; } passno++; } while (anygtr); if (sumstatus) exit(8); (void)endfsent(); if (returntosingle) exit(2); exit(0); } checkfilesys(filesys) char *filesys; { daddr_t n_ffree, n_bfree; register ino_t *zp; devname = filesys; if (setup(filesys) == 0) { if (preen) pfatal("CAN'T CHECK FILE SYSTEM."); return; } /* * 1: scan inodes tallying blocks used */ if (preen == 0) { printf("** Last Mounted on %s\n", sblock.fs_fsmnt); if (hotroot) printf("** Root file system\n"); printf("** Phase 1 - Check Blocks and Sizes\n"); } pass1(); /* * 1b: locate first references to duplicates, if any */ if (enddup != duplist) { if (preen) pfatal("INTERNAL ERROR: dups with -p"); printf("** Phase 1b - Rescan For More DUPS\n"); pass1b(); } /* * 2: traverse directories from root to mark all connected directories */ if (preen == 0) printf("** Phase 2 - Check Pathnames\n"); pass2(); /* * 3: scan inodes looking for disconnected directories */ if (preen == 0) printf("** Phase 3 - Check Connectivity\n"); pass3(); /* * 4: scan inodes looking for disconnected files; check reference counts */ if (preen == 0) printf("** Phase 4 - Check Reference Counts\n"); pass4(); flush(&dfile, &fileblk); /* * 5: check and repair resource counts in cylinder groups */ if (preen == 0) printf("** Phase 5 - Check Free List\n"); pass5(); /* * print out summary statistics */ pwarn("%ld files, %ld used, %ld free\n", n_files, n_blks, sblock.fs_tfree); if (debug && (n_files -= imax - ROOTINO - sblock.fs_tinode)) printf("%ld files missing, imax: %u tinode: %u\n", n_files, imax,sblock.fs_tinode); if (debug) { if (enddup != duplist) { printf("The following duplicate blocks remain:"); for (; enddup > duplist; enddup--) printf(" %ld,", *enddup); printf("\n"); } for (zp = zlnlist; zp < zlnp; zp++) if (*zp) break; if (zp < zlnp) { printf("The following zero link count inodes remain:"); for (zp = zlnlist; zp < zlnp; zp++) if (*zp) printf(" %ld,", *zp); printf("\n"); } } bzero(zlnlist, sizeof zlnlist); bzero(duplist, sizeof duplist); if (dfile.mod) { (void)time(&sblock.fs_time); sbdirty(); } ckfini(); if (!dfile.mod) return; if (!preen) { printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); if (hotroot) printf("\n***** REBOOT UNIX *****\n"); } if (hotroot) { sync(); exit(4); } } char * blockcheck(name) char *name; { struct stat stslash, stblock, stchar; char *raw; int looped = 0; hotroot = 0; if (stat("/", &stslash) < 0){ printf("Can't stat root\n"); return (0); } retry: if (stat(name, &stblock) < 0){ printf("Can't stat %s\n", name); return (0); } if (stblock.st_mode & S_IFBLK) { raw = rawname(name); if (stat(raw, &stchar) < 0){ printf("Can't stat %s\n", raw); return (0); } if (stchar.st_mode & S_IFCHR) { if (stslash.st_dev == stblock.st_rdev) { hotroot++; raw = unrawname(name); } return (raw); } else { printf("%s is not a character device\n", raw); return (0); } } else if (stblock.st_mode & S_IFCHR) { if (looped) { printf("Can't make sense out of name %s\n", name); return (0); } name = unrawname(name); looped++; goto retry; } printf("Can't make sense out of name %s\n", name); return (0); } char * unrawname(cp) char *cp; { char *dp = rindex(cp, '/'); struct stat stb; if (dp == 0) return (cp); if (stat(cp, &stb) < 0) return (cp); if ((stb.st_mode&S_IFMT) != S_IFCHR) return (cp); if (*(dp+1) != 'r') return (cp); (void)strcpy(dp+1, dp+2); return (cp); } char * rawname(cp) char *cp; { static char rawbuf[32]; char *dp = rindex(cp, '/'); if (dp == 0) return (0); *dp = 0; (void)strcpy(rawbuf, cp); *dp = '/'; (void)strcat(rawbuf, "/r"); (void)strcat(rawbuf, dp+1); return (rawbuf); } cmp(fsp->fs_type, FSTAB_RO) && etc/fsck/pass1.c 640 0 0 10626 5153211533 6720 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) /* static char sccsid[] = "@(#)pass1.c 5.3 (Berkeley) 5/13/86"; */ static char sccsid[] = "@(#)pass1.c 1.0 (2.11BSD) 9/13/90"; #endif not lint #include #include #include #include "fsck.h" int pass1check(); pass1() { register int j; register DINODE *dp; daddr_t ndb, lj; struct inodesc idesc; register ino_t inumber; /* * Set file system reserved blocks in used block map. */ for (j = 0; j < fmin; j++) setbmap((daddr_t)j); /* * Find all allocated blocks. */ bzero((char *)&idesc, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass1check; n_files = n_blks = n_free = 0; for (inumber = ROOTINO; inumber < imax; inumber++) { dp = ginode(inumber); if (!ALLOC(dp)) { if (bcmp((char *)dp->di_addr, (char *)zino.di_addr, NADDR * sizeof(daddr_t)) || dp->di_mode || dp->di_size) { pfatal("PARTIALLY ALLOCATED INODE I=%u", inumber); if (reply("CLEAR") == 1) { zapino(dp); inodirty(); } } setstate(inumber, USTATE); continue; } lastino = inumber; if (dp->di_size < 0) { printf("bad size %ld:", dp->di_size); goto unknown; } if (!preen && (dp->di_mode & IFMT) == IFMT && reply("HOLD BAD BLOCK") == 1) { dp->di_size = sblock.fs_fsize; dp->di_mode = IFREG|0600; inodirty(); } ndb = howmany(dp->di_size, DEV_BSIZE); if (SPECIAL(dp)) ndb++; /* * This check is not in 4.3BSD and is due to the fact that pipes in 2.11BSD * are still implemented using the filesystem. Zero length files with blocks * (typically only the first direct block) allocated are the symptom. It is * safe to clear the inode as the blocks will end up missing and be reclaimed * in pass5. */ else if (dp->di_size == 0 && bcmp(dp->di_addr, zino.di_addr,NADDR* sizeof (daddr_t))) { pwarn("SIZE=0 FILE HAS ALLOCATED BLOCKS. I=%u",inumber); if (preen) printf(" (CLEARED)\n"); if (preen || reply("CLEAR") == 1) { setstate(inumber, USTATE); zapino(dp); inodirty(); continue; } } for (lj = ndb; lj < NDADDR; lj++) { j = lj; if (dp->di_addr[j] != 0) { if (debug) printf("bad direct di_addr[%d]: %ld\n", j, dp->di_addr[j]); goto unknown; } } for (j = 0, ndb -= NDADDR; ndb > 0; j++) ndb /= NINDIR; for (; j < NIADDR; j++) if (dp->di_addr[NDADDR + j] != 0) { if (debug) printf("bad indirect addr: %ld\n", dp->di_addr[NDADDR + j]); goto unknown; } if (ftypeok(dp) == 0) goto unknown; n_files++; setlncnt(inumber, dp->di_nlink); if (dp->di_nlink <= 0) { if (zlnp >= &zlnlist[MAXLNCNT]) { pfatal("LINK COUNT TABLE OVERFLOW"); if (reply("CONTINUE") == 0) errexit(""); } else *zlnp++ = inumber; } setstate(inumber, DIRCT(dp) ? DSTATE : FSTATE); badblk = dupblk = 0; idesc.id_number = inumber; (void)ckinode(dp, &idesc); continue; unknown: pfatal("UNKNOWN FILE TYPE I=%u mode: %o", inumber, dp->di_mode); setstate(inumber, FCLEAR); if (reply("CLEAR") == 1) { setstate(inumber, USTATE); zapino(dp); inodirty(); } } } pass1check(idesc) register struct inodesc *idesc; { int res = KEEPON; daddr_t blkno = idesc->id_blkno; register daddr_t *dlp; if (outrange(blkno)) { blkerr(idesc->id_number, "BAD", blkno); if (++badblk >= MAXBAD) { pwarn("EXCESSIVE BAD BLKS I=%u", idesc->id_number); if (preen) printf(" (SKIPPING)\n"); else if (reply("CONTINUE") == 0) errexit(""); return (STOP); } return (SKIP); } if (!getbmap(blkno)) { n_blks++; setbmap(blkno); } else { blkerr(idesc->id_number, "DUP", blkno); if (++dupblk >= MAXDUP) { pwarn("EXCESSIVE DUP BLKS I=%u", idesc->id_number); if (preen) printf(" (SKIPPING)\n"); else if (reply("CONTINUE") == 0) errexit(""); return (STOP); } if (enddup >= &duplist[DUPTBLSIZE]) { pfatal("DUP TABLE OVERFLOW"); if (reply("CONTINUE") == 0) errexit(""); return(STOP); } for (dlp = duplist; dlp < muldup; dlp++) { if (*dlp == blkno) { *enddup++ = blkno; break; } } if ( dlp >= muldup) { *enddup++ = *muldup; *muldup++ = blkno; } } /* * count the number of blocks found in id_entryno */ idesc->id_entryno++; return (res); } lush(&dfile, &fileblk); /* * 5: check and repair resource counts in cylinder groups */ if (preen ==etc/fsck/pass1b.c 640 0 0 2413 4614470730 7044 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)pass1b.c 5.1 (Berkeley) 6/5/85"; #endif not lint #include #include #include #include "fsck.h" int pass1bcheck(); pass1b() { register int c, i; register DINODE *dp; struct inodesc idesc; ino_t inumber; bzero((char *)&idesc, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass1bcheck; for (inumber = ROOTINO; inumber < lastino; inumber++) { if (inumber < ROOTINO) continue; dp = ginode(inumber); if (dp == NULL) continue; idesc.id_number = inumber; if (getstate(inumber) != USTATE && (ckinode(dp, &idesc) & STOP)) goto out1b; } out1b: flush(&dfile, &inoblk); } pass1bcheck(idesc) register struct inodesc *idesc; { register daddr_t *dlp; daddr_t blkno = idesc->id_blkno; if (outrange(blkno)) return (SKIP); for (dlp = duplist; dlp < muldup; dlp++) { if (*dlp == blkno) { blkerr(idesc->id_number, "DUP", blkno); *dlp = *--muldup; *muldup = blkno; return (muldup == duplist ? STOP : KEEPON); } } return (KEEPON); } astino = inumber; if (dp->di_size < 0) { printf("bad size %ld:", dp->di_size); goto unknown; } if (!preen && (dp->di_mode & IFMT) == IFMT && reply("HOLD BAD BLOCK") == 1) { dp->di_size = sblock.fs_fsize; dp->di_mode = IFRetc/fsck/pass2.c 640 0 0 14641 4674567372 6750 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)pass2.c 5.2 (Berkeley) 3/5/86"; #endif not lint #include #include #include #include #include #include "fsck.h" int pass2check(); pass2() { register DINODE *dp; struct inodesc rootdesc; bzero((char *)&rootdesc, sizeof(struct inodesc)); rootdesc.id_type = ADDR; rootdesc.id_func = pass2check; rootdesc.id_number = ROOTINO; pathp = pathname; switch (getstate(ROOTINO)) { case USTATE: pfatal("ROOT INODE UNALLOCATED"); if (reply("ALLOCATE") == 0) errexit(""); if (allocdir(ROOTINO, ROOTINO) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); descend(&rootdesc, ROOTINO); break; case DCLEAR: pfatal("DUPS/BAD IN ROOT INODE"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); descend(&rootdesc, ROOTINO); break; } if (reply("CONTINUE") == 0) errexit(""); setstate(ROOTINO, DSTATE); descend(&rootdesc, ROOTINO); break; case FSTATE: case FCLEAR: pfatal("ROOT INODE NOT DIRECTORY"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); descend(&rootdesc, ROOTINO); break; } if (reply("FIX") == 0) errexit(""); dp = ginode(ROOTINO); dp->di_mode &= ~IFMT; dp->di_mode |= IFDIR; inodirty(); setstate(ROOTINO, DSTATE); /* fall into ... */ case DSTATE: descend(&rootdesc, ROOTINO); break; default: errexit("BAD STATE %d FOR ROOT INODE", getstate(ROOTINO)); } } pass2check(idesc) struct inodesc *idesc; { register DIRECT *dirp = idesc->id_dirp; char *curpathloc; int n, entrysize, ret = 0; DINODE *dp; static DIRECT proto; static char namebuf[MAXPATHLEN]; /* * check for "." */ if (idesc->id_entryno != 0) goto chk1; if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") == 0) { if (dirp->d_ino != idesc->id_number) { direrr(idesc->id_number, "BAD INODE NUMBER FOR '.'"); dirp->d_ino = idesc->id_number; if (reply("FIX") == 1) ret |= ALTERED; } goto chk1; } direrr(idesc->id_number, "MISSING '.'"); proto.d_ino = idesc->id_number; proto.d_namlen = 1; (void)strcpy(proto.d_name, "."); entrysize = DIRSIZ(&proto); if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") != 0) { pfatal("CANNOT FIX, FIRST ENTRY IN DIRECTORY CONTAINS %s\n", dirp->d_name); } else if (dirp->d_reclen < entrysize) { pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '.'\n"); } else if (dirp->d_reclen < 2 * entrysize) { proto.d_reclen = dirp->d_reclen; bcopy((char *)&proto, (char *)dirp, entrysize); if (reply("FIX") == 1) ret |= ALTERED; } else { n = dirp->d_reclen - entrysize; proto.d_reclen = entrysize; bcopy((char *)&proto, (char *)dirp, entrysize); idesc->id_entryno++; declncnt(dirp->d_ino); dirp = (DIRECT *)((char *)(dirp) + entrysize); bzero((char *)dirp, n); dirp->d_reclen = n; if (reply("FIX") == 1) ret |= ALTERED; } chk1: if (idesc->id_entryno > 1) goto chk2; proto.d_ino = idesc->id_parent; proto.d_namlen = 2; (void)strcpy(proto.d_name, ".."); entrysize = DIRSIZ(&proto); if (idesc->id_entryno == 0) { n = DIRSIZ(dirp); if (dirp->d_reclen < n + entrysize) goto chk2; proto.d_reclen = dirp->d_reclen - n; dirp->d_reclen = n; idesc->id_entryno++; declncnt(dirp->d_ino); dirp = (DIRECT *)((char *)(dirp) + n); bzero((char *)dirp, n); dirp->d_reclen = n; } if (dirp->d_ino != 0 && strcmp(dirp->d_name, "..") == 0) { if (dirp->d_ino != idesc->id_parent) { direrr(idesc->id_number, "BAD INODE NUMBER FOR '..'"); dirp->d_ino = idesc->id_parent; if (reply("FIX") == 1) ret |= ALTERED; } goto chk2; } direrr(idesc->id_number, "MISSING '..'"); if (dirp->d_ino != 0 && strcmp(dirp->d_name, ".") != 0) { pfatal("CANNOT FIX, SECOND ENTRY IN DIRECTORY CONTAINS %s\n", dirp->d_name); } else if (dirp->d_reclen < entrysize) { pfatal("CANNOT FIX, INSUFFICIENT SPACE TO ADD '..'\n"); } else { proto.d_reclen = dirp->d_reclen; bcopy((char *)&proto, (char *)dirp, entrysize); if (reply("FIX") == 1) ret |= ALTERED; } chk2: if (dirp->d_ino == 0) return (ret|KEEPON); if (dirp->d_namlen <= 2 && dirp->d_name[0] == '.' && idesc->id_entryno >= 2) { if (dirp->d_namlen == 1) { direrr(idesc->id_number, "EXTRA '.' ENTRY"); dirp->d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; return (KEEPON | ret); } if (dirp->d_name[1] == '.') { direrr(idesc->id_number, "EXTRA '..' ENTRY"); dirp->d_ino = 0; if (reply("FIX") == 1) ret |= ALTERED; return (KEEPON | ret); } } curpathloc = pathp; *pathp++ = '/'; if (pathp + dirp->d_namlen >= endpathname) { *pathp = '\0'; errexit("NAME TOO LONG %s%s\n", pathname, dirp->d_name); } bcopy(dirp->d_name, pathp, dirp->d_namlen + 1); pathp += dirp->d_namlen; idesc->id_entryno++; n = 0; if (dirp->d_ino > imax || dirp->d_ino <= 0) { direrr(dirp->d_ino, "I OUT OF RANGE"); n = reply("REMOVE"); } else { again: switch (getstate(dirp->d_ino)) { case USTATE: direrr(dirp->d_ino, "UNALLOCATED"); n = reply("REMOVE"); break; case DCLEAR: case FCLEAR: direrr(dirp->d_ino, "DUP/BAD"); if ((n = reply("REMOVE")) == 1) break; dp = ginode(dirp->d_ino); setstate(dirp->d_ino, DIRCT(dp) ? DSTATE : FSTATE); goto again; case DFOUND: if (idesc->id_entryno > 2) { getpathname(namebuf, dirp->d_ino, dirp->d_ino); pwarn("%s %s %s\n", pathname, "IS AN EXTRANEOUS HARD LINK TO DIRECTORY", namebuf); if (preen) printf(" (IGNORED)\n"); else if ((n = reply("REMOVE")) == 1) break; } /* fall through */ case FSTATE: declncnt(dirp->d_ino); break; case DSTATE: descend(idesc, dirp->d_ino); if (getstate(dirp->d_ino) == DFOUND) { declncnt(dirp->d_ino); } else if (getstate(dirp->d_ino) == DCLEAR) { dirp->d_ino = 0; ret |= ALTERED; } else errexit("BAD RETURN STATE %d FROM DESCEND", getstate(dirp->d_ino)); break; default: errexit("BAD STATE %d FOR INODE I=%u", getstate(dirp->d_ino), dirp->d_ino); } } pathp = curpathloc; *pathp = '\0'; if (n == 0) return (ret|KEEPON); dirp->d_ino = 0; return (ret|KEEPON|ALTERED); } dolncnt(x,3,0) #define setbmap(x) domap(x,0) #define getbmap(x) domap(x,1) #define clrbmap(x)etc/fsck/pass3.c 640 0 0 2337 4614470777 6724 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)pass3.c 5.1 (Berkeley) 6/5/85"; #endif not lint #include #include #include #include "fsck.h" int pass2check(); pass3() { register DINODE *dp; struct inodesc idesc; ino_t inumber, orphan; bzero((char *)&idesc, sizeof(struct inodesc)); idesc.id_type = DATA; for (inumber = ROOTINO; inumber <= lastino; inumber++) { if (getstate(inumber) == DSTATE) { pathp = pathname; *pathp++ = '?'; *pathp = '\0'; idesc.id_func = findino; idesc.id_name = ".."; idesc.id_parent = inumber; do { orphan = idesc.id_parent; if (orphan < ROOTINO || orphan > imax) break; dp = ginode(orphan); idesc.id_parent = 0; idesc.id_number = orphan; (void)ckinode(dp, &idesc); if (idesc.id_parent == 0) break; } while (getstate(idesc.id_parent) == DSTATE); if (linkup(orphan, idesc.id_parent) == 1) { idesc.id_func = pass2check; idesc.id_number = lfdir; descend(&idesc, orphan); } } } } cend(&rootdesc, ROOTINO); break; case FSTATE: case FCLEAR: pfatal("ROOT INODE NOT DIRECTORY"); if (reply("REALLOCATE")) { freeino(ROOTINO); if (allocdir(ROOTINO, ROOTINO) != ROOTINO) errexit("CANNOT ALLOCATE ROOT INODE\n"); descend(&rootdesc, ROOTINO); break; } etc/fsck/pass4.c 640 0 0 3111 4674567411 6712 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)pass4.c 5.3 (Berkeley) 3/5/86"; #endif not lint #include #include #include #include "fsck.h" int pass4check(); pass4() { register ino_t inumber, *zp; struct inodesc idesc; int n; bzero((char *)&idesc, sizeof(struct inodesc)); idesc.id_type = ADDR; idesc.id_func = pass4check; for (inumber = ROOTINO; inumber <= lastino; inumber++) { idesc.id_number = inumber; switch (getstate(inumber)) { case FSTATE: case DFOUND: n = getlncnt(inumber); if (n) adjust(&idesc, (short)n); else { zp = zlnlist; for (zp = zlnlist; zp < zlnp; zp++) { if (*zp == 0) continue; if (*zp == inumber) { clri(&idesc, "UNREF", 1); *zp = 0; break; } } } break; case DSTATE: clri(&idesc, "UNREF", 1); break; case DCLEAR: case FCLEAR: clri(&idesc, "BAD/DUP", 1); break; case USTATE: break; default: errexit("BAD STATE %d FOR INODE I=%u", getstate(inumber), inumber); } } } pass4check(idesc) register struct inodesc *idesc; { register daddr_t *dlp; daddr_t blkno = idesc->id_blkno; if (outrange(blkno)) return (SKIP); if (getbmap(blkno)) { for (dlp = duplist; dlp < enddup; dlp++) if (*dlp == blkno) { *dlp = *--enddup; return (KEEPON); } clrbmap(blkno); n_blks--; } return (KEEPON); } for (inumber = ROOTINO; inumber <= lastino; inumber++) { idesc.id_number = inumber; switch (getstate(inumber)) { case FSTATE: case DFOUND: n = getlncnt(inumber); if (n) adjust(&idesc, (short)n); else { zp = zlnlist; for (zp = zlnlist; zp < zlnp; zp++) { if (*zp == 0) continue; if (*zp == inumber) { clri(&idesc, "UNREF", 1); *zp = 0; break; } } } break; case DSetc/fsck/pass5.c 640 0 0 10706 4656061506 6735 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)pass5.c 5.2 (Berkeley) 3/5/86"; #endif not lint #include #include #include #include "fsck.h" pass5() { struct inodesc idesc; daddr_t blkno; int n; BUFAREA *bp1, *bp2; extern int debug; bzero(&idesc, sizeof (idesc)); idesc.id_type = ADDR; if(sflag) fixfree = 1; else { ifreechk(); if(freemap) bcopy(blockmap, freemap, (int)bmapsz); else { for(blkno = 0; blkno < fmapblk-bmapblk; blkno++) { bp1 = getblk((BUFAREA *)NULL,blkno+bmapblk); bp2 = getblk((BUFAREA *)NULL,blkno+fmapblk); bcopy(bp1->b_un.b_buf,bp2->b_un.b_buf,DEV_BSIZE); dirty(bp2); } } badblk = dupblk = 0; freeblk.df_nfree = sblock.fs_nfree; for(n = 0; n < NICFREE; n++) freeblk.df_free[n] = sblock.fs_free[n]; freechk(); if(badblk) pfatal("%d BAD BLKS IN FREE LIST\n",badblk); if(dupblk) pwarn("%d DUP BLKS IN FREE LIST\n",dupblk); if (debug) printf("n_files %ld n_blks %ld n_free %ld fmax %ld fmin %ld ninode: %u\n", n_files, n_blks, n_free, fmax, fmin,sblock.fs_ninode); if(fixfree == 0) { if ((n_blks+n_free) != (fmax-fmin) && dofix(&idesc, "BLK(S) MISSING")) fixfree = 1; else if (n_free != sblock.fs_tfree && dofix(&idesc,"FREE BLK COUNT WRONG IN SUPERBLOCK")) { sblock.fs_tfree = n_free; sbdirty(); } } if(fixfree && !dofix(&idesc, "BAD FREE LIST")) fixfree = 0; } if(fixfree) { if (preen == 0) printf("** Phase 6 - Salvage Free List\n"); makefree(); n_free = sblock.fs_tfree; sblock.fs_ronly = 0; sblock.fs_fmod = 0; sbdirty(); } } ifreechk() { register int i; ino_t inum; for (i=0; i NICFREE) { pfatal("BAD FREEBLK COUNT"); printf("\n"); fixfree = 1; return; } ap = &freeblk.df_free[freeblk.df_nfree]; while(--ap > &freeblk.df_free[0]) { if(pass5check(*ap) == STOP) return; } if(*ap == (daddr_t)0 || pass5check(*ap) != KEEPON) return; } while(getblk(&fileblk,*ap) != NULL); } makefree() { register i, cyl, step; int j; char flg[MAXCYL]; short addr[MAXCYL]; daddr_t blk, baseblk; sblock.fs_nfree = 0; sblock.fs_flock = 0; sblock.fs_fmod = 0; sblock.fs_tfree = 0; sblock.fs_ninode = 0; sblock.fs_ilock = 0; sblock.fs_ronly = 0; if(cylsize == 0 || stepsize == 0) { step = sblock.fs_step; cyl = sblock.fs_cyl; } else { step = stepsize; cyl = cylsize; } if(step > cyl || step <= 0 || cyl <= 0 || cyl > MAXCYL) { printf("Default free list spacing assumed\n"); step = STEPSIZE; cyl = CYLSIZE; } sblock.fs_step = step; sblock.fs_cyl = cyl; bzero(flg,sizeof(flg)); i = 0; for(j = 0; j < cyl; j++) { while(flg[i]) i = (i + 1) % cyl; addr[j] = i + 1; flg[i]++; i = (i + step) % cyl; } baseblk = (daddr_t)roundup(fmax,cyl); bzero((char *)&freeblk,DEV_BSIZE); freeblk.df_nfree++; for( ; baseblk > 0; baseblk -= cyl) for(i = 0; i < cyl; i++) { blk = baseblk - addr[i]; if(!outrange(blk) && !getbmap(blk)) { sblock.fs_tfree++; if(freeblk.df_nfree >= NICFREE) { fbdirty(); fileblk.b_bno = blk; flush(&dfile,&fileblk); bzero((char *)&freeblk,DEV_BSIZE); } freeblk.df_free[freeblk.df_nfree] = blk; freeblk.df_nfree++; } } sblock.fs_nfree = freeblk.df_nfree; for(i = 0; i < NICFREE; i++) sblock.fs_free[i] = freeblk.df_free[i]; sbdirty(); } pass5check(blk) daddr_t blk; { if(outrange(blk)) { fixfree = 1; if (preen) pfatal("BAD BLOCKS IN FREE LIST."); if(++badblk >= MAXBAD) { printf("EXCESSIVE BAD BLKS IN FREE LIST."); if(reply("CONTINUE") == 0) errexit(""); return(STOP); } return(SKIP); } if(getfmap(blk)) { fixfree = 1; if(++dupblk >= DUPTBLSIZE) { printf("EXCESSIVE DUP BLKS IN FREE LIST."); if(reply("CONTINUE") == 0) errexit(""); return(STOP); } } else { n_free++; setfmap(blk); } return(KEEPON); } tryno >= 2) { if (dirp->d_namlen == 1) { direrr(idescetc/fsck/setup.c 640 0 0 10070 4635457653 7045 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)setup.c 5.3 (Berkeley) 5/15/86"; #endif not lint #include #include #include #include #include #include #include "fsck.h" setup(dev) char *dev; { dev_t rootdev; off_t smapsz, totsz, lncntsz; daddr_t bcnt, nscrblk; struct stat statb; u_int msize; char *mbase; int i, j, n; long size; BUFAREA *bp; if (stat("/", &statb) < 0) errexit("Can't stat root\n"); rootdev = statb.st_dev; if (stat(dev, &statb) < 0) { printf("Can't stat %s\n", dev); return (0); } rawflg = 0; if ((statb.st_mode & S_IFMT) == S_IFBLK) ; else if ((statb.st_mode & S_IFMT) == S_IFCHR) rawflg++; else { if (reply("file is not a block or character device; OK") == 0) return (0); } if (rootdev == statb.st_rdev) hotroot++; if ((dfile.rfdes = open(dev, 0)) < 0) { printf("Can't open %s\n", dev); return (0); } if (preen == 0) printf("** %s", dev); if (nflag || (dfile.wfdes = open(dev, 1)) < 0) { dfile.wfdes = -1; if (preen) pfatal("NO WRITE ACCESS"); printf(" (NO WRITE)"); } if (preen == 0) printf("\n"); dfile.mod = 0; lfdir = 0; initbarea(&sblk); initbarea(&fileblk); initbarea(&inoblk); /* * Read in the super block and its summary info. */ if (bread(&dfile, (char *)&sblock, SBLOCK, SBSIZE) != 0) return (0); sblk.b_bno = SBLOCK; sblk.b_size = SBSIZE; imax = ((ino_t)sblock.fs_isize - (SUPERB+1)) * INOPB; fmin = (daddr_t)sblock.fs_isize; /* first data blk num */ fmax = sblock.fs_fsize; /* first invalid blk num */ startib = fmax; if(fmin >= fmax || (imax/INOPB) != ((ino_t)sblock.fs_isize-(SUPERB+1))) { pfatal("Size check: fsize %ld isize %d", sblock.fs_fsize,sblock.fs_isize); printf("\n"); ckfini(); return(0); } if (preen == 0) printf("File System: %.12s\n\n", sblock.fs_fsmnt); /* * allocate and initialize the necessary maps */ bmapsz = roundup(howmany(fmax,BITSPB),sizeof(*lncntp)); smapsz = roundup(howmany((long)(imax+1),STATEPB),sizeof(*lncntp)); lncntsz = (long)(imax+1) * sizeof(*lncntp); if(bmapsz > smapsz+lncntsz) smapsz = bmapsz-lncntsz; totsz = bmapsz+smapsz+lncntsz; msize = memsize; mbase = membase; bzero(mbase,msize); muldup = enddup = duplist; zlnp = zlnlist; if((off_t)msize < totsz) { bmapsz = roundup(bmapsz,DEV_BSIZE); smapsz = roundup(smapsz,DEV_BSIZE); lncntsz = roundup(lncntsz,DEV_BSIZE); nscrblk = (bmapsz+smapsz+lncntsz)>>DEV_BSHIFT; if(scrfile[0] == 0) { pfatal("\nNEED SCRATCH FILE (%ld BLKS)\n",nscrblk); do { printf("ENTER FILENAME: "); if((n = getline(stdin,scrfile,sizeof(scrfile))) == EOF) errexit("\n"); if(stat(scrfile,&statb) == 0 && (statb.st_mode & S_IFMT) != S_IFREG) errexit("Not a good scratch filename"); } while(n == 0); } sfile.wfdes=open(scrfile, O_CREAT|O_TRUNC|O_WRONLY, 0666); if ((sfile.wfdes < 0) || ((sfile.rfdes = open(scrfile,0)) < 0)) { printf("Can't create %s\n",scrfile); ckfini(); return(0); } unlink(scrfile); /* make it invisible incase we exit */ if (hotroot && (stat(scrfile,&statb)==0) && ((statb.st_mode & S_IFMT) == S_IFREG) && (statb.st_dev==rootdev)) pfatal("TMP FILE (%s) ON ROOT WHEN CHECKING ROOT",scrfile); bp = &((BUFAREA *)mbase)[(msize/sizeof(BUFAREA))]; poolhead = NULL; while(--bp >= (BUFAREA *)mbase) { initbarea(bp); bp->b_next = poolhead; poolhead = bp; } bp = poolhead; for(bcnt = 0; bcnt < nscrblk; bcnt++) { bp->b_bno = bcnt; dirty(bp); flush(&sfile,bp); } blockmap = freemap = statemap = (char *) NULL; lncntp = (short *) NULL; bmapblk = 0; smapblk = bmapblk + bmapsz / DEV_BSIZE; lncntblk = smapblk + smapsz / DEV_BSIZE; fmapblk = smapblk; } else { poolhead = NULL; blockmap = mbase; statemap = &mbase[bmapsz]; freemap = statemap; lncntp = (short *)&statemap[smapsz]; } return(1); } tatb; u_int msize; char *mbase; int i, j, n; long size; BUFAREA *bp; if (stat("/", &statb) < 0) errexit("Can't stat root\n"); rootdev = statb.st_dev; if (stat(dev, &statb) < 0) { printf("Can't stat %s\n", dev); return (0); } rawflg = 0; if ((statb.st_mode & S_IFMT) == S_IFBLK) ; else if ((statb.st_mode & S_IFMT) == S_IFCHR) rawflg++; else { if (reply("file is not a block or character device; OK") == 0) return (0); } if (retc/fsck/utilities.c 640 0 0 23036 4674567455 7733 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)utilities.c 5.2 (Berkeley) 9/10/85"; #endif not lint #include #include #include #include #include #include #include "fsck.h" long lseek(); ftypeok(dp) DINODE *dp; { switch (dp->di_mode & IFMT) { case IFDIR: case IFREG: case IFBLK: case IFCHR: case IFLNK: case IFSOCK: return (1); default: if (debug) printf("bad file type 0%o\n", dp->di_mode); return (0); } } reply(s) char *s; { char line[80]; if (preen) pfatal("INTERNAL ERROR: GOT TO reply()"); printf("\n%s? ", s); if (nflag || dfile.wfdes < 0) { printf(" no\n\n"); return (0); } if (yflag) { printf(" yes\n\n"); return (1); } if (getline(stdin, line, sizeof(line)) == EOF) errexit("\n"); printf("\n"); if (line[0] == 'y' || line[0] == 'Y') return (1); else return (0); } getline(fp, loc, maxlen) FILE *fp; char *loc; { register n; register char *p, *lastloc; p = loc; lastloc = &p[maxlen-1]; while ((n = getc(fp)) != '\n') { if (n == EOF) return (EOF); if (!isspace(n) && p < lastloc) *p++ = n; } *p = 0; return (p - loc); } BUFAREA * getblk(bp, blk) register BUFAREA *bp; daddr_t blk; { register struct filecntl *fcp; extern BUFAREA *search(); if(bp == NULL) { bp = search(blk); fcp = &sfile; } else fcp = &dfile; if(bp->b_bno == blk) return(bp); flush(fcp,bp); bp->b_errs = bread(fcp,bp->b_un.b_buf,blk,DEV_BSIZE); bp->b_bno = blk; bp->b_size = DEV_BSIZE; return(bp); } flush(fcp, bp) struct filecntl *fcp; register BUFAREA *bp; { if (!bp->b_dirty) return; if (bp->b_errs != 0) pfatal("WRITING ZERO'ED BLOCK %ld TO DISK\n", bp->b_bno); bp->b_dirty = 0; bp->b_errs = 0; if (bp == &inoblk) bwrite(fcp, inobuf, startib, NINOBLK * DEV_BSIZE); else bwrite(fcp, bp->b_un.b_buf, bp->b_bno, DEV_BSIZE); } rwerr(s, blk) char *s; daddr_t blk; { if (preen == 0) printf("\n"); pfatal("CANNOT %s: BLK %ld", s, blk); if (reply("CONTINUE") == 0) errexit("Program terminated\n"); } ckfini() { flush(&dfile, &fileblk); flush(&dfile, &sblk); if (sblk.b_bno != SBLOCK) { sblk.b_bno = SBLOCK; sbdirty(); flush(&dfile, &sblk); } flush(&dfile, &inoblk); if (dfile.rfdes) (void)close(dfile.rfdes); if (dfile.wfdes) (void)close(dfile.wfdes); if (sfile.rfdes) (void)close(sfile.rfdes); if (sfile.wfdes) (void)close(sfile.wfdes); } bread(fcp, buf, blk, size) register struct filecntl *fcp; char *buf; daddr_t blk; int size; { char *cp; register int i, errs; if (lseek(fcp->rfdes, blk << DEV_BSHIFT, 0) < 0) rwerr("SEEK", blk); else if (read(fcp->rfdes, buf, size) == size) return (0); rwerr("READ", blk); if (lseek(fcp->rfdes, blk << DEV_BSHIFT, 0) < 0) rwerr("SEEK", blk); errs = 0; pfatal("THE FOLLOWING SECTORS COULD NOT BE READ:"); for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE) { if (read(fcp->rfdes, cp, DEV_BSIZE) < 0) { printf(" %ld,", blk + i / DEV_BSIZE); bzero(cp, DEV_BSIZE); errs++; } } printf("\n"); return (errs); } bwrite(fcp, buf, blk, size) register struct filecntl *fcp; char *buf; daddr_t blk; int size; { int i; char *cp; if (fcp->wfdes < 0) return; if (lseek(fcp->wfdes, blk << DEV_BSHIFT, 0) < 0) rwerr("SEEK", blk); else if (write(fcp->wfdes, buf, size) == size) { fcp->mod = 1; return; } rwerr("WRITE", blk); if (lseek(fcp->wfdes, blk << DEV_BSHIFT, 0) < 0) rwerr("SEEK", blk); pfatal("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:"); for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE) if (write(fcp->wfdes, cp, DEV_BSIZE) < 0) printf(" %ld,", blk + i / DEV_BSIZE); printf("\n"); return; } /* * allocate a data block */ daddr_t allocblk() { daddr_t i; for (i = 0; i < fmax; i++) { if (getbmap(i)) continue; setbmap(i); n_blks++; return (i); } return (0); } /* * Free a previously allocated block */ fr_blk(blkno) daddr_t blkno; { struct inodesc idesc; idesc.id_blkno = blkno; pass4check(&idesc); } /* * Find a pathname */ getpathname(namebuf, curdir, ino) char *namebuf; ino_t curdir, ino; { int len, st; register char *cp; struct inodesc idesc; extern int findname(); st = getstate(ino); if (st != DSTATE && st != DFOUND) { strcpy(namebuf, "?"); return; } bzero(&idesc, sizeof(struct inodesc)); idesc.id_type = DATA; cp = &namebuf[MAXPATHLEN - 1]; *cp-- = '\0'; if (curdir != ino) { idesc.id_parent = curdir; goto namelookup; } while (ino != ROOTINO) { idesc.id_number = ino; idesc.id_func = findino; idesc.id_name = ".."; if ((ckinode(ginode(ino), &idesc) & STOP) == 0) break; namelookup: idesc.id_number = idesc.id_parent; idesc.id_parent = ino; idesc.id_func = findname; idesc.id_name = namebuf; if ((ckinode(ginode(idesc.id_number), &idesc) & STOP) == 0) break; len = strlen(namebuf); cp -= len; if (cp < &namebuf[MAXNAMLEN]) break; bcopy(namebuf, cp, len); *--cp = '/'; ino = idesc.id_number; } if (ino != ROOTINO) { strcpy(namebuf, "?"); return; } bcopy(cp, namebuf, &namebuf[MAXPATHLEN] - cp); } catch() { ckfini(); exit(12); } /* * When preening, allow a single quit to signal * a special exit after filesystem checks complete * so that reboot sequence may be interrupted. */ catchquit() { extern returntosingle; printf("returning to single-user after filesystem check\n"); returntosingle = 1; (void)signal(SIGQUIT, SIG_DFL); } /* * Ignore a single quit signal; wait and flush just in case. * Used by child processes in preen. */ voidquit() { sleep(1); (void)signal(SIGQUIT, SIG_IGN); (void)signal(SIGQUIT, SIG_DFL); } /* * determine whether an inode should be fixed. */ dofix(idesc, msg) register struct inodesc *idesc; char *msg; { switch (idesc->id_fix) { case DONTKNOW: if (idesc->id_type == DATA) direrr(idesc->id_number, msg); else pwarn(msg); if (preen) { printf(" (SALVAGED)\n"); idesc->id_fix = FIX; return (ALTERED); } if (reply("SALVAGE") == 0) { idesc->id_fix = NOFIX; return (0); } idesc->id_fix = FIX; return (ALTERED); case FIX: return (ALTERED); case NOFIX: return (0); default: errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix); } /* NOTREACHED */ } /* VARARGS1 */ errexit(s1, s2, s3, s4) char *s1; { printf(s1, s2, s3, s4); exit(8); } /* * An inconsistency occured which shouldn't during normal operations. * Die if preening, otherwise just printf. */ /* VARARGS1 */ pfatal(s, a1, a2, a3, a4) char *s; { if (preen) { printf("%s: ", devname); printf(s, a1, a2, a3, a4); printf("\n"); printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n", devname); exit(8); } printf(s, a1, a2, a3, a4); } /* * Pwarn is like printf when not preening, * or a warning (preceded by filename) when preening. */ /* VARARGS1 */ pwarn(s, a1, a2, a3, a4, a5, a6) char *s; { if (preen) printf("%s: ", devname); printf(s, a1, a2, a3, a4, a5, a6); } stype(p) register char *p; { if(*p == 0) return; if (*(p+1) == 0) { if (*p == '3') { cylsize = 200; stepsize = 5; return; } if (*p == '4') { cylsize = 418; stepsize = 9; return; } } cylsize = atoi(p); while(*p && *p != ':') p++; if(*p) p++; stepsize = atoi(p); if(stepsize <= 0 || stepsize > cylsize || cylsize <= 0 || cylsize > MAXCYL) { printf("Invalid -s argument, defaults assumed\n"); cylsize = stepsize = 0; } } dostate(ino, s,flg) ino_t ino; int s, flg; { register char *p; register unsigned byte, shift; BUFAREA *bp; byte = ino / STATEPB; shift = LSTATE * (ino % STATEPB); if(statemap != NULL) { bp = NULL; p = &statemap[byte]; } else { bp = getblk(NULL,(daddr_t)(smapblk+(byte/DEV_BSIZE))); if (bp->b_errs) errexit("Fatal I/O error\n"); else p = &bp->b_un.b_buf[byte%DEV_BSIZE]; } switch(flg) { case 0: *p &= ~(SMASK<<(shift)); *p |= s << shift; if(bp != NULL) dirty(bp); return(s); case 1: return((*p >> shift) & SMASK); } return(USTATE); } domap(blk,flg) daddr_t blk; int flg; { register char *p; register unsigned n; register BUFAREA *bp; off_t byte; byte = blk >> BITSHIFT; n = 1<<((unsigned)(blk & BITMASK)); if(flg & 04) { p = freemap; blk = fmapblk; } else { p = blockmap; blk = bmapblk; } if(p != NULL) { bp = NULL; p += (unsigned)byte; } else { bp = getblk((BUFAREA *)NULL,blk+(byte>>DEV_BSHIFT)); if (bp->b_errs) errexit("Fatal I/O error\n"); else p = &bp->b_un.b_buf[(unsigned)(byte&DEV_BMASK)]; } switch(flg&03) { case 0: *p |= n; break; case 1: n &= *p; bp = NULL; break; case 2: *p &= ~n; } if(bp != NULL) dirty(bp); return(n); } dolncnt(ino, flg, val) ino_t ino; short val, flg; { register short *sp; register BUFAREA *bp; if(lncntp != NULL) { bp = NULL; sp = &lncntp[ino]; } else { bp = getblk((BUFAREA *)NULL,(daddr_t)(lncntblk+(ino/SPERB))); if (bp->b_errs) errexit("Fatal I/O error\n"); else sp = &bp->b_un.b_lnks[ino%SPERB]; } switch(flg) { case 0: *sp = val; break; case 1: bp = NULL; break; case 2: (*sp)--; break; case 3: (*sp)++; break; default: abort(); } if(bp != NULL) dirty(bp); return(*sp); } BUFAREA * search(blk) daddr_t blk; { register BUFAREA *pbp, *bp; for(bp = (BUFAREA *) &poolhead; bp->b_next; ) { pbp = bp; bp = pbp->b_next; if(bp->b_bno == blk) break; } pbp->b_next = bp->b_next; bp->b_next = poolhead; poolhead = bp; return(bp); } ' || line[0] == 'Y') return (1); else return (0); } getline(fp, loc, maxlen) FILE *fp; char *loc; { register n; register char *p, *lastloc; p = loc; lastloc = &p[maxlen-1]; while ((n = getc(fp)) != '\n') { if (n == EOF) return (EOF); if (!isspace(n) && p < lastloc) *p++ = n; } *p = 0; return (p - loc); } BUFAREA * getblk(bp, blk) register BUFAREA *bp; daddr_t blk; { register struct filecntl *fcp; extern BUFAREA *search(); if(bp == NULL) { bp etc/termcap/ 755 0 12 0 6024523072 6151 etc/termcap/tabset/ 755 0 12 0 4015515234 7432 etc/termcap/tabset/aed512 444 0 12 1113 4015515231 10412 \EG1MMM.`40K0001202080K8001????00^L\EC80L80{80^L\EK010100????K0601??0000c818100\EG1HHH.\07210000019A27FD006A280D002A200A52429FE8524861086118612861360N031B4C3F3F1800N041B0C1B4C38301800N001B3B313030301800N011B3B313030341800N021B3B313030381800N050800N061B3B313335301800\07211000015A58E8D5011A58F8D5111A5908D5211A5918D531160\07212000015AD5011858EAD5111858FAD52118590AD5311859160\0721300004B2071C5858E0A18658E0A0A858EA900858F268FA5278590A50A29018591A9F51865908590A90165918591A59038E58E8590A591E58F290185912071C5180A0A0A0901858EA900858F268F60\0721350000BA9472031DEA9502031DE60\E\E\E\EG1MMM.^A ase 0þƒ *sp = val; break; case 1: bp = NULL; break; case 2: (*sp)--; break; case 3: (*sp)++; break; default: abort(); } if(bp != NULL) dirty(bp); return(*sp); } BUFAREA * search(blk) daddr_t blk; { register BUFAREA *pbp, *bp; for(bp = (BUFAREA *) &poolhead; bp->b_next; ) { pbp = bp; bp = pbp->b_next; if(bp->b_bno == blk) break; } pbp->b_next = bp->b_next; bp->b_next = poolhead; etc/termcap/tabset/dtc382 444 0 12 244 4015515232 10425  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 beehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/ibm3101 444 0 12 135 4015515232 10471 H 0 0 0 0 0 0 0 0 0 \ xerox1730[ xerox1730-lmZzenith29-Y wyse-addsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/tandem653 444 0 12 140 4015515232 11117 3 1 1 1 1 1 1 1 1 1 1  xerox1730[ xerox1730-lmZzenith29-Y wyse-addsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/xerox1730 444 0 12 336 4015515232 11100  P?">\  9 2 1 1 1 !1 )1 11 91 A1 I1 Q1 Y1 a1 i1 q1 y1 T vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/xerox1730-lm 444 0 12 340 4015515232 11501  P?">\ 9 2 1 1 1 !1 )1 11 91 A1 I1 Q1 Y1 a1 i1 q1 y1 9 vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/zenith29 444 0 12 142 4015515233 11070  H H H H H H H H H H xerox1730[ xerox1730-lmZzenith29-Y wyse-addsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/wyse-adds 444 0 12 403 4015515233 11314 Setting tabs... 2 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 1tQ aasetPøstdcrt0etc/termcap/tabset/beehive 444 0 12 244 4015515233 11026                                                                                 beehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/diablo 444 0 12 130 4015515233 10643  9 2 1 1 1 !1 )1 11 91 A1 I1 Q1 Y1 a1 i1 q1 y1 9 em653\ xerox1730[ xerox1730-lmZzenith29-Y wyse-addsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/std 444 0 12 207 4015515233 10210 3 1 1 1 1 1 1 1 1 1 1 1 1 1 zenith29-Y wyse-addsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/teleray 444 0 12 71 4015515233 11042 GY9(FY90FY98FY9@FY9HFY9PFY9XFY9`FY9hF 2s.^ibm3101s.] tandem653\ xerox1730[ xerox1730-lmZzenith29-Y wyse-addsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/vt100 444 0 12 237 4015515233 10273  H H H H H H H H H H H H H H H H dsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/xerox1720 444 0 12 243 4015515233 11075 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 beehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/3101 444 0 12 135 4015515234 10003 H 0 0 0 0 0 0 0 0 0 \ xerox1730[ xerox1730-lmZzenith29-Y wyse-addsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/aa 444 0 12 151 4015515234 7776  1 1 1 1 1 1 1 1 1  1730[ xerox1730-lmZzenith29-Y wyse-addsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/tabset/stdcrt 444 0 12 137 4015515234 10724 3 1 1 1 1 1 1 1 1 1  xerox1730[ xerox1730-lmZzenith29-Y wyse-addsXbeehivesWdiablosV stdetUteleraysT vt100S xerox1720R 3101tQ aasetPøstdcrt0etc/termcap/README 444 0 12 3761 4015515234 7122 To install this directory on your system: First determine a list of "common terminals" for your system. This list will probably be small, and can be empty if you like, but you should probably put your own terminal in it. Second, edit the editor script "reorder" to use this list instead of the list built in to it. The changes will be evident from looking at the script. Notice that the script contains the terminals in order from least common to most common, since the move commands will move them to the front in that order, the effect will be to put the most common at the front of termcap since that's moved last. The s.* terminals are specials, and although they don't have to go to the front, they are probably quite common and really should go near the front. Third, if you are not a super user and cannot create the directory /usr/lib/tabset, make a corresponding directory somewhere you can and add a line to reorder to globally change all /usr/lib/tabset's to your own path name. This change is better than just changing the termcap.src file because it makes it easier to diff it from newer distributed versions. Try to keep the source as is whenever possible, and put mungings into reorder. Now you can run "make install" which will create an /etc/termcap. Again, if you aren't a super user change the cp command to put it where you can. In this case you will have to redefine E_TERMCAP in "local/uparm.h", which will probably be in subdirectories with the other UCB software. Finally, if you make additions or fixes to termcap, please mail a note explaining what you did with the fixed termcap entry (not the whole file, please!) to me at one of the addresses below, so it can be incorporated back into the original source. I will normally include anything unless there is a good reason not to, but I reserve the right to redo it differently. ucbvax!termcap (uucp) termcap@berkeley (Arpanet) or Kevin Layer Computer Science Division Evans Hall University of California Berkeley, California 94720 BSIZE); else etc/termcap/termcap.src 640 0 12 432472 5344067253 10462 # ------------------------ # # Termcap source file @(#)termcap.src 5.40 (Berkeley) 8/22/88 # John Kunze, Berkeley # Craig Leres, Berkeley # # Please mail changes to (arpanet): termcap@berkeley # See DESCRIPTION section for information about contents. # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # DESCRIPTION: # This file describes capabilities of various terminals, as needed by # software such as screen editors. It does not attempt to describe # printing terminals very well, nor graphics terminals. Someday. # See termcap(5) in the Unix Programmers Manual for documentation. # # Conventions: First entry is two chars, first char is manufacturer, # second char is canonical name for model or mode. # Third entry is the one the editor will print with "set" command. # Last entry is verbose description. # Others are mnemonic synonyms for the terminal. # # Terminal naming conventions: # Terminal names look like - # Certain abbreviations (e.g. c100 for concept100) are also allowed # for upward compatibility. The part to the left of the dash, if a # dash is present, describes the particular hardware of the terminal. # The part to the right can be used for flags indicating special ROM's, # extra memory, particular terminal modes, or user preferences. # All names are always in lower case, for consistency in typing. # # The following are conventionally used flags: # rv Terminal in reverse video mode (black on white) # 2p Has two pages of memory. Likewise 4p, 8p, etc. # w Wide - in 132 column mode. # pp Has a printer port which is used. # na No arrow keys - termcap ignores arrow keys which are # actually there on the terminal, so the user can use # the arrow keys locally. # # There are some cases where the same name is used for two different # terminals, e.g. "teleray" or "2621" or "vt100". In these cases, # if a site has one of these, they should choose a local default and # bring that terminal to the front in the reorder script. This works # because tgetent picks the first match in /etc/termcap. # The list of names intentionally duplicated is: # 2621, c108, dtc, hp2621, teleray, tvi, vt100. # # To easily test a new terminal description, put it in $HOME/.termcap # and programs will look there before looking in /etc/termcap. # You can also setenv TERMPATH to a list of full pathnames (separated # by spaces or colons) to be searched by tgetent() in the order listed. # The TERMCAP environment variable is usually set to the termcap # entry itself to avoid reading files when starting up a program. # # If you absolutely MUST check for a specific terminal (this is discouraged) # check for the 2nd entry (the canonical form) since all other codes are # subject to change. The two letter codes are there for version 6 and are # EXTREMELY subject to change, or even to go away if version 6 becomes for # all practical purposes obsolete. We would much rather put in special # capabilities to describe your terminal rather than having you key on the # name. # # Special manufacturer codes: # A: hardcopy daisy wheel terminals # M: Misc. (with only a few terminals) # q: Homemade # s: special (dialup, etc.) # # Comments in this file begin with # - they cannot appear in the middle # of a termcap entry. Individual entries are commented out by # placing a period between the colon and the capability name. # # This file is to be installed with an editor script (reorder) # that moves the most common terminals to the front of the file. # If the source is not available, it can be constructed by sorting # the above entries by the 2 char initial code. # # -------------------------------- # # A: DAISY WHEEL PRINTERS # # The A manufacturer represents Diablo, DTC, Xerox, Qume, and other Daisy # wheel terminals until such time as termcap distinguishes between them # enough to justify separate codes. # This is an "experimental" entry for the SRI Agiles. # It has been tried in a minimal way -- the Agile did not blow up! # However, it has not been exhaustively tested. # Anyone who tries it and finds it wanting should get in touch with: # Ralph Keirstead (ralph@sri-unix); # EK352; SRI International; 333 Ravenswood Avenue; Menlo Park, CA 94025 Aa|agile|agiles|sri agiles:\ :bs:hc:os:pl:co#132:do=^J:kb=^H:up=\E\n:\ :hu=\E0:hd=\E9:if=/usr/lib/tabset/std:is=\EE\EF\EJ: A6|1620|1720|450|ipsi|diablo 1620:\ :do=^J:ct=\E2:st=\E1:ch=\E\t%i%.:\ :if=/usr/lib/tabset/xerox1720:\ :kb=^H:le=^H:bs:co#132:hc:hu=\EU:hd=\ED:os:pt:up=\E\n: A7|1620-m8|1640-m8|diablo 1620 w/8 column left margin:\ :do=^J:co#124:is=\r \E9:tc=1620: A8|1640|1740|630|1730|x1700|diablo|xerox|diablo 1640:\ :if=/usr/lib/tabset/xerox1730:\ :us=\EE:ue=\ER:so=\EW:se=\E&:tc=1620: Am|1640-lm|1740-lm|630-lm|1730-lm|x1700-lm|diablo-lm|xerox-lm|\ diablo 1640 with idented left margin:\ :if=/usr/lib/tabset/xerox1730-lm:\ :co#124:us=\EE:ue=\ER:so=\EW:se=\E&:tc=1620: # DTC 382 with VDU. Has no cd so we fake it with ce. Standout works but # won't go away without dynamite. The terminal has tabs, but I'm getting # tired of fighting the braindamage. If no tab is set or the terminal's # in a bad mood, it glitches the screen around all of memory. Note that # return puts a blank ("a return character") in the space the cursor was # at, so we use ^P return (and thus ^P newline for newline). Note also # that if you turn off pt and let Unix expand tabs, curses won't work # (current version) because it doesn't turn off this bit, and cursor # addressing sends a tab for row/column 9. What a losing terminal! I # have been unable to get tabs set in all 96 lines - it always leaves at # least one line with no tabs in it, and once you tab through that line, # it completely weirds out. Ac|dtc|ps|dtc382|382:\ :do=^J:al=^P^Z:am:le=^H:\ :bs:co#80:ce=^P^U:cl=20^P^]:cm=%r^P^Q%.%.:dc=^X:\ :dl=^P^S:ei=^Pi:ho=^P^R:im=^PI:ve=^Pb:vs=^PB:pc=\177:te=20^P^]:\ :li#24:nd=^PR:.se=^P \200:.so=^P \002^PF:us=^P \020:ue=^P \200:\ :up=^P^L:nc:xr:xs:da:db:.pt:cr=^P^M:cd=^P^U^P^S^P^S:\ :if=/usr/lib/tabset/dtc382: Ad|dtc300s|300|300s|dtc 300s:\ :ct=\E3:st=\E1:do=^J:\ :kb=^h:le=^H:bs:co#132:hc:hu=\EH:hd=\Eh:os:pt:up=^Z: Ag|gsi:\ :le=^H:bs:co#132:hc:hd=\Eh:hu=\EH:os:pt:up=^Z:do=^J: # This used to have :pl: - maybe they meant :pt:? Aj|aj830|aj832|aj|anderson jacobson:\ :do=^J:le=^H:bs:hc:hd=\E9:hu=\E8:os:up=\E7: # From Chris Torek Thu, 7 Nov 85 18:21:58 EST AJ|aj510|AJ510|Anderson-Jacobson model 510:\ :ic=:ip=.1*:so=\E"I:us=\E"U:cd=\E'P:ce=\E'L:cl=^L:cm=\E#%+ %+ :\ :dl=2*\E&D:ue=\E"U:co#80:li#24:se=\E"I:al=2*\E&I:im=\E'I:ei=\E'J:\ :dc=.1*\E'D:up=\EY:nd=\EX:bs:am:mi:ti=\E"N:te=\E"N:\ :ku=\EY:kd=\EZ:kl=\EW:kr=\EX:pc=\177: # From cbosg!ucbvax!pur-ee!cincy!chris Thu Aug 20 09:09:18 1981 # This is incomplete, but it's a start. An|5520|nec|spinwriter|nec 5520:\ :ct=\E3:st=\E1:do=^J:kb=^h:le=^H:bs:co#132:hc:hu=\E]s\E9\E]W:\ :hd=\E]s\n\E]W:os:pt:up=\E9: Aq|qume5|qume|Qume Sprint 5:\ :ct=\E3:st=\E1:do=^J:\ :kb=^h:le=^H:bs:co#80:hc:hu=\EH:hd=\Eh:os:pt:up=^Z: Ar|q102|qume102|Qume 102:\ :al=\EE:am:bs:bt=\EI:\ :cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :co#80:ct=\E3:\ :dc=\EW:dl=\ER:do=^J:ei=:ho=^^:ic=\EQ:im=:\ :k0=^A@\r:k1=^AA\r:k2=^AB\r:k3=^AC\r:kd=^J:kl=^H:kr=^L:ku=^K:\ :le=^H:li#24:ma=^K^P^L :nd=^L:\ :se=\EG0:sg#1:so=\EG4:st=\E1:\ :ue=\EG0:ug#1:up=^K:us=\EG8: # From ucbvax!mtxinu!sybase!tim (Tim Wood) Fri Sep 27 10:25:24 PDT 1985 # This entry supports line and character insert and delete, scroll up and # down and the arrow keys. To use it, perform the following on your qvt-101 # 1) enter SET-UP mode, select the SET 3 line; # 2) move the cursor to the EMULATION item and hit SPACE # until QVT-101B appears # 3) enter SHIFT-S # 4) exit SET-UP - the terminal is now configured Aq|q101|qvt101|qvt-101|Qume 101 $310 special:\ :al=\EE:am:bt=\EI:ce=\Et:cl=\E*:dc=\EW:\ :dl=\ER:do=^J:ic=\EQ:ei=:im=:md=\E(:me=\EG0:mh=\E):\ :le=^H:bs:cm=\E=%+ %+ :cl=1^Z:co#80:ho=^^:li#24:ma=^K^P:nd=^L:ku=^K:\ :vs=\EM4\040\200\200\200:mr=\EG4:ms:so=\EG4:se=\EG1: # I suspect the xerox1720 is the same as the diablo 1620. Ax|x1720|x1700|1700|x1750|xerox 1720:\ :co#132:le=^H:bs:hc:os:pt:do=^J:ct=\E2:st=\E1: # # -------------------------------- # # B: AT&T ATT # # AT&T Teletype 5410 Terminal (a.k.a. 4410) # From: carvalho%kepler@Berkeley.EDU (Marcio de Carvalho) # Date: Thu, 26 Feb 87 09:16:50 PST # # Although the 5410 supports labels, it blanks the screen after # each label is programmed creating to much visual activity. # To use the labels, use FL=\E[%d;00q%-16s # Ba|5410|4410|tty5410|att4410|AT&T Teletype 5410 terminal with 80 columns:\ :al=\E[L:am:bs:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\ :cm=5\E[%i%2;%2H:co#80:dc=\E[P:dl=\E[M:im=:ei=:ic=\E[@:\ :kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\ :li#24:nd=\E[C:se=\E[m:so=\E[2;7m:sr=\EM:\ :ue=\E[m:up=\E[A:us=\E[4m:EE=\E[m:BO=\E[0;7m:DS=\E[2m:\ :KM=/usr/lib/ua/kmap.5410:is=\E[0m^O\E[?6l:kn#8:\ :k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:k4=\EOg:k6=\EOh:\ :k7=\EOi:k8=\EOj:ko=nd,up,ho: # AT&T Teletype 5420 Terminal (a.k.a. 4415) June 5, 1985 Bb|5420|4415|tty5420|att4415|AT&T Teletype 5420 terminal:\ :al=\E[L:am:bs:cd=\E[J:ce=\E[K:cl=\E[H\E[J:\ :cm=\E[%i%2;%2H:co#80:dc=\E[P:dl=\E[M:im=\E[4h:ei=\E[4l:\ :kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:\ :li#24:nd=\E[C:se=\E[m:so=\E[2;7m:sr=\EM:\ :ue=\E[m:up=\E[A:us=\E[4m:EE=\E[m:BO=\E[0;7m:DS=\E[2m:\ :KM=/usr/lib/ua/kmap.5420:\ :is=\E[0m^O\E[1;2;3;4;6l\E[12;13;14;20l\E[?6;97;99l\E[?7h\E[4i\Ex\E[25;1j\212\E[8;0j\E[9;0j\E[10;0j\E[19;1j:\ :db:mi:pt:kn#8:k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:k5=\EOg:k6=\EOh:\ :k7=\EOi:k8=\EOj:ve=\E[11;0j:\ :vs=\E[11;1j:ko=bt,nd,up,dc,dl,ho,im,al: # AT&T Teletype 5425 Terminal (a.k.a 4425) June 5, 1985 Bc|5425|4425|tty5425|att4425|AT&T Teletype 5425:\ :FL=\E[%d;00q%-16s\E~:FE=\E|:KM=/usr/lib/ua/kmap.5425:\ :is=\E[0m^O\E[1;2;3;4;6l\E[12;13;14;20l\E[?6l\E[?7h\E[4i\E[9;0j\E[10;0j\E[11;0j\E[21;1j\E[25;1j\212:\ :ve=\E[12;0j:vs=\E[12;1j:tc=5420: Bd|t4|4420|tty4420|Teletype 4420:\ :vs=\ER:ve=\ER:am:da:db:mi:cr=\EG:\ :im=:ei=:dm=:ed=:nl=\EG\EB:li#23:\ :co#80:cl=\EH\EJ:cd=\EJ:cm=\EY%+ %+ :\ :bs:up=\E7:do=\EB:nd=\EC:al=\EL:\ :dl=\EM:dc=\EP:ic=\E\136:sf=\EH\EM\EY5 :sr=\ET:kb=^H: Be|pc6300plus|6300|6300plus:\ :al=\E[1L:am:bs:cd=\E[0J:ce=\E[0K:cl=\E[2J\E[H:cm=\E[%i%2;%2H:co#80:\ :dc=\E[1P:dl=\E[1M:do=\E[B:ei=:ho=\E[H:\ :ic=\E[1@:im=:kb=\10:kd=\E[B:kl=\E[D:kr=\E[C:ku=\E[A:li#24:\ :k1=\EOc:k2=\EOd:k3=\EOe:k4=\EOf:k5=\EOg:k6=\EOh:k7=\EOi:k8=\EOj:\ :k9=\EOk:k10=\EOu:nd=\E[C:se=\E[m:so=\E[7m:ue=\E[m:up=\E[A:us=\E[4m:\ :EE=\E[m:BO=\E[0;7m:CV=\E[=C:CI=\E[=1C:KM=/usr/lib/ua/kmap.s5: Bf|s4|PC7300|unixpc|pc7300|7300|3b1|Safari 4:\ :so=\E[2;7m:DS=\E[2m:XS=\E[9m:KM=/usr/lib/ua/kmap.s4:tc=pc6300plus: # AT&T Teletype 610 Terminal Bg|b610|610|610bct|tty610:\ :CV=\E[25h:CI=\E[25l:KM=/usr/lib/ua/kmap.s4:\ :FL=\E[%d;00q%-16s\E[0p:FE=\E[2p:cl=\E[1;1H\E[J:\ :is=\E[0m^O\E[25;1|^J\E[8;0|\E[4;13;20l\E[?5l\E[12h\E[?7h\E[?4i:\ :ve=\E[?12l:vs=\E[?12h:tc=5420: # # -------------------------------- # # C: CONTROL DATA # Ca|cdc456|cdc:\ :do=^J:li#24:co#80:cl=^Y^X:nd=^L:up=^Z:le=^H:bs:\ :cm=\E1%+ %+ :ho=^Y:al=\E\114:dl=\E\112:ce=^V:cd=^X:am: Cc|cdc456tst:\ :do=^J:li#24:co#80:cl=^y^x:le=^H:bs:cm=\E1%+ %+ :am: # # -------------------------------- # # D: DATAMEDIA # D0|dm1520|dm1521|1521|1520|datamedia 1520:\ :do=^J:am:le=^H:bs:cd=^K:ce=^]:cl=^L:cm=^^%r%+ %+ :co#80:ho=^Y:\ :ku=^_:kd=^J:kl=^H:kr=^\:kh=^Y:\ :li#24:nd=^\:up=^_:xn:ma=^\ ^_^P^YH:pt: D2|dm2500|datamedia2500|2500|datamedia 2500:\ :do=^J:al=15^P\n^X^]^X^]:le=^H:bs:ce=^W:cl=^^^^\177:\ :cm=^L%r%n%.%.:co#80:dc=10*^P\b^X^]:dl=10*^P^Z^X^]:\ :dm=^P:ed=^X^]:ei=10\377\377^X^]:ho=^B:ic=10*^P^\^X^]:\ :im=^P:li#24:nc:nd=^\:pc=\377:so@=^N:se=^X^]:up=^Z: D3|dm3025|datamedia 3025a:\ :MT:is=\EQ\EU\EV:do=^J:\ :al=130\EP\n\EQ:le=^H:bs:cd=2\EJ:ce=\EK:cl=2\EM:cm=\EY%r%+ %+ :\ :co#80:dc=6\b:dl=130\EP\EA\EQ:dm=\EP:ed=\EQ:ei=\EQ:ho=\EH:\ :im=\EP:ip=6:li#24:nd=\EC:pt:so=\EO1:se=\EO0:up=\EA: D4|3045|dm3045|datamedia 3045a:\ :is=\EU\EV:do=^J:\ :am:le=^H:bs:cd=2\EJ:ce=\EK:cl=2\EM:cm=\EY%r%+ %+ :co#80:\ :dc=6\EB:dm=:ed=:ei=\EP:ho=\EH:ic=:im=\EP:ip=6:\ :k0=\Ey\r:k1=\Ep\r:k2=\Eq\r:k3=\Er\r:k4=\Es\r:\ :k5=\Et\r:k6=\Eu\r:k7=\Ev\r:k8=\Ew\r:k9=\Ex\r:\ :kh=\EH:ku=\EA:kr=\EC:li#24:nd=\EC:pc=\177:pt:eo:ul:up=\EA:xn: # dt80/1 is a vt100 lookalike, but it doesn't seem to need any padding. D5|dt80|dmdt80|dm80|datamedia dt80/1:\ :do=^J:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:cm=%i\E[%d;%dH:ho=\E[H:\ :nd=\E[C:sr=\EM:so=\E[7m:se=\E[m:up=\E[A:us=\E[4m:ue=\E[m:tc=vt100: # except in 132 column mode, where it needs a little padding. # This is still less padding than the vt100, and you can always turn on # the ^S/^Q handshaking, so you can use vt100 flavors for things like # reverse video. D6|dt80w|dmdt80w|dm80w|datamedia dt80/1 in 132 char mode:\ :do=^J:cd=20\E[0J:co#132:ce=20\E[0K:\ :cm=5\E[%i%d;%dH:cl=50\E[H\E[2J:up=5\E[A:tc=dmdt80: # # -------------------------------- # # H: HAZELTINE # # Since nd is blank, when you want to erase something you # are out of luck. You will have to do ^L's a lot to # redraw the screen. h1000 is untested. It doesn't work in # vi - this terminal is too dumb for even vi. (The code is # there but it isn't debugged for this case.) H1|h1000|hazeltine 1000:\ :le=^H:bs:ho=^K:cl=^L:nd= :co#80:li#12:do=^J: # Note: the h1552 appears to be the first Hazeltine terminal which # is not braindamaged. It has tildes and backprimes and everything! # Be sure the auto lf/cr switch is set to cr. H2|h1552|hazeltine 1552:\ :do=^J:al=\EE:dl=\EO:k1=\EP:l1=blue:k2=\EQ:\ :l2=red:k3=\ER:l3=green:tc=vt52: H3|h1552rv|hazeltine 1552 reverse video:\ :do=^J:so=\ES:se=\ET:tc=h1552: # From cbosg!ucbvax!pur-ee!cincy!chris Thu Aug 20 09:09:18 1981 H4|h1420|hazeltine 1420:\ :do=^J:le=^H:bs:am:li#24:co#80:al=\E^Z:dl=\E^S:cd=\E^X:cl=\E\034:\ :up=\E^L:nd=^P:ce=\E^O:ta=^N:cm=\E^Q%r%.%+ :so=\E\037:se=\E^Y: H5|h1500|hazeltine 1500:\ :do=^J:al=40~^Z:am:le=^H:bs:cd=10~^X:ce=~^O:cl=~^\:cm=~^Q%r%.%.:\ :co#80:dl=40~^S:do=~^K:hz:li#24:nd=^P:.se=~^_:.so=~^Y:up=~^L: # h1510 assumed to be in sane escape mode. Else use h1500. H6|h1510|hazeltine 1510:\ :do=^J:al=\E^Z:am:le=^H:bs:cd=\E^X:ce=\E^O:cl=\E^\:cm=\E^Q%r%.%.:\ :co#80:dl=\E^S:do=\E^K:hz:li#24:nd=^P:.se=\E^_:.so=\E^Y:up=\E^L: H8|h1520|hazeltine 1520:\ :do=^J:al=~^Z:am:le=^H:bs:cd=~^X:ce=~^O:cl=~\034:cm=~^Q%r%.%.\200:\ :co#80:dl=~^S:do=~^K:hz:li#24:nd=^P:se=~^Y:so=~\037:up=~^L:ho=~^R: # Note: h2000 won't work well because of a clash between upper case and ~'s. H7|h2000|hazeltine 2000:\ :do=^J:al=6~^z:am:le=^H:bs:cl=6~^\:cm=~^q%r%.%.:co#74:\ :dl=6~^s:ho=~^r:li#27:nc:pc=\177: # Hazeltine esprit entries from Univ of Utah Tue Feb 1 06:39:37 1983 # J.Lepreau, lepreau@utah-cs, harpo!utah-cs!lepreau HE|esprit|hazeltine esprit:\ :al=40\E^Z:bs:cd=5\E^X:ce=\E^O:cl=\E^\:cm=\E^Q%r%>^^ %+`%+`:co#80:\ :dl=40\E^S:do=\E^K:ho=\E^R:li#24:nd=^P:se=\E^Y:so=\E^_:up=\E^L: HF|esprit-am|hazeltine esprit auto-margin:\ :am:tc=esprit: # # -------------------------------- # # I: IBM # # ibm61 and ibm63 from Warren Gish (cswarren@violet.berkeley.edu). # installed 12-17-86. # 3161 only opens a new line if a null line exists on the screen. # To ensure a null line exists, an SBA is performed, positioning the # Buffer Address in column 0 of the last line. The last line is then # cleared to nulls, BA mode is cancelled, and the new line is opened # at the cursor position. I1|ibm61|ibm3161|3161|IBM 3161-11:\ :am:bs:bw:cl=\EL:li#24:co#80:cd=\EJ:al=\EX7 \EI\E Z\EN:\ :ce=\EI:cm=\EY%+\040%+\040:nd=\EC:up=\EA:do=\EB:\ :dl=\EO:dc=\EQ:kd=\EB:ku=\EA:kl=\ED:kr=\EC:kh=\EH:\ :us=\E4\102:ue=\E4\100:so=\E4\110:se=\E4\100: I3|ibm63|ibm3163|3163|i3163|IBM 3163:\ :tc=ibm61: I4|ibm|ibm3101|3101|i3101|IBM 3101-10:\ :do=^J:ct=\EH:st=\E0:\ :if=/usr/lib/tabset/ibm3101:\ :am:le=^H:bs:cl=\EK:li#24:co#80:nd=\EC:up=\EA:cd=\EJ:ce=\EI:\ :kd=\EB:kl=\ED:kr=\EC:ku=\EA:ho=\EH:cm=\EY%+\40%+\40:pt: Ia|ibm-apl|apl|IBM apl terminal simulator:\ :li#25:tc=dm1520: # ibmapa* and ibmmono entries come from ACIS 4.3 distribution Ib|rtpc|ibmapa16|ibm6155|IBM 6155 Extended Monochrome Graphics Display:\ :ts=\Ej\EY@%+ \Eo:ds=\Ej\EY@\40\EI\Ek:li#32:tc=ibmconsole: # Advanced Monochrome (6153) and Color (6154) Graphics Display: Ic|ibmapa8c|ibmapa8|ibm6154|ibm6153|IBM 6153/4 Advanced Graphics Display:\ :ts=\Ej\EY?%+ \Eo:ds=\Ej\EY?\40\EI\Ek:li#31:tc=ibmconsole: Id|ibmapa8c-c|ibm6154-c|IBM 6154 Advanced Color Graphics Display color termcap:\ :ts=\Ej\EY?%+ \Eo:ds=\Ej\EY?\40\EI\Ek:li#31:mh=\EF\Ef7;:tc=ibmega-c: Ie|ibmmono|ibmconsole|ibm5151|IBM workstation monochrome:\ :se=\Ez:so=\EZ:sr=\EA:al=\EL:dl=\EM:\ :kb=^H:us=\EW:ue=\Ew:\ :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:k6=\EP:k7=\EQ:k8=\ER:k9=\EY:\ :k0=\E<:I0=f10:kI=\000:kh=\EH:kR=\EG:kP=\Eg:kF=\EE:kN=\EE:\ :md=\EZ:me=\Ew\Eq\Ez\EB:mk=\EF\Ef0;\Eb0;:mr=\Ep:\ :ts=\Ej\EY8%+ \Eo:fs=\Ek:ds=\Ej\EY8\40\EI\Ek:es:hs:sb:tc=ibm3101: If|ibmega-c|ibm5154-c|IBM Enhanced Color Display color termcap:\ :se=\EB:so=\EF\Ef3;:ue=\EB:us=\EF\Ef2;:tc=ibmconsole: # # -------------------------------- # # M: MISCELLANEOUS TERMINALS # # The tab 132 uses xon/xoff, so no padding needed. # ks/ke have nothing to do with arrow keys. # is sets 80 col mode, normal video, autowrap on (for am). # Seems to be no way to get rid of status line. M0|abm80|amtek business machines 80:\ :do=^J:al=\E^Z:am:le=^H:bs:cd=\E^X:ce=\E^O:cl=\E^\:cm=\E^Q%r%+ %+ :\ :co#80:dl=\E^S:do=\E^K:li#24:nd=^P:.so=\E^_:.se=\E^Y:up=\E^L:\ :bw:bt=^T:ho=\E^R: M1|tab132|tab|tab132/15|tab 132/15:\ :is=\E[?7h\E[?3l\E[?5l:dN@:ks@:ke@:do=^J:\ :da:db:al=\E[L:dl=\E[M:dc=\E[P:ei=\E[4l:im=\E[4h:cm=\E[%i%d;%dH:\ :ku=\E[A:kd=\E[B:kl=\E[D:tc=vt100: M2|tab132w:\ :co#132:is=\E[?7h\E[?3h\E[?5l:tc=tab132: M3|tab132rv:\ :is=\E[?7h\E[?3l\E[?5h:tc=tab132: M4|tab132wrv:\ :is=\E[?7h\E[?3h\E[?5h:tc=tab132w: # This used to say "de#001202" which presumably refers to the stty bits # that need to be set for some version of Unix. We need the real delay # requirements in MS. M5|mw2|Multiwriter 2:\ :do=^J:co#132:hc:os: M6|trs80|trs-80|radio shack trs-80 Model I:\ :do=^J:am:le=^H:bs:co#64:li#16: M7|d800|Direct 800/A:\ :do=^J:co#80:li#24:am:cl=\E[1;1H\E[2J:le=^H:bs:cm=\E[%i%d;%dH:\ :nd=\E[C:up=\E[A:ce=\E[K:cd=\E[J:\ :so=\E[7m:se=\E[0m:us=\E[4m:ue=\E[0m:xs:vs=\E[>12l:ve=\E[>12h:\ :sf=\ED:sr=\EM:da:db:as=\E[1m:ae=\E[0m:ms:pt:\ :kl=\E[D:kr=\E[C:ku=\E[A:kd=\E[B:\ :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\ :k5=\EOT:k6=\EOU:k7=\EOV:k8=\EOW: M8|vc404|volker-craig 404:\ :do=^J:am:le=^H:bs:cd=40^W:ce=20^V:cl=40^X:cm=^P%+ %+ :co#80:\ :ho=40^Y:kd=^J:kl=^H:kr=^U:ku=^Z:li#24:ma=^Z^P^U :nd=^U:up=^Z: M9|vc404-s|volker-craig 404 w/standout mode:\ :do=^J:se=^O:so=^N:tc=vc404: MA|vc404-na|volker-craig 404 w/no arrow keys:\ :ma@:kr@:ku@:tc=vc404: MB|vc404-s-na|volker-craig 404 w/standout mode and no arrow keys:\ :se=^O:so=^N:tc=vc404-na: # missing in vc303a and vc303 descriptions: they scroll 2 lines at a time MC|vc303a|vc403a|volker-craig 303a:\ :do=^J:am:le=^H:bs:ce=20^V:cl=40^X:co#80:ho=40^Y:kd=^J:kl=^H::kr=^U:\ :ku=^Z:li#24:ll=^P^@W:nd=^U:ns:up=^Z: MD|vc303|vc103|vc203|volker-craig 303:\ :do=^J:am:le=^H:bs:cl=40^L:co#80:ho=40^K:kd=^J:kl=^H:\ :kr=^I:ku=^N:li#24:ll=^O\200W:nd=^I:ns:up=^N: # Test version for Falco ts-1. See "arpavax.hickman@ucb" for info ME|falco|ts1|ts-1|falco ts-1:is=\Eu\E3:\ :do=^J:al=\EE:am:bs:ce=\ET\EG0^h:cm=\E=%+ %+ :cl=\E*:cd=\EY:co#80:\ :dc=\EW:dl=\ER:ei=\Er:ho=^^:im=\Eq:k0=^A0\r:kd=^J:kl=^H:pt:\ :kr=^L:ku=^K:li#24:nd=^L:se=\Eg0:so=\Eg1:up=^K:us=\Eg1:ue=\Eg0: MF|falco-p|falco ts-1sp|falco with paging option:\ :is=\EZ\E3\E_c:\ :al=\EE:am:bs:ce=\ET\EG0^H\Eg0:cl=\E*:cd=\EY:co#80:dc=\EW:\ :dl=\ER:kd=\E[B:kl=\E[D:ei=\Er:im=\Eq:pt:db:\ :kr=\E[C:ku=\E[A:li#24:nd=\E[C:se=\Eg0:so=\Eg4:\ :up=\E[A:us=\Eg1:ti=\E_d:te=\E_b:\ :ue=\Eg0:do=\E[B:cm=\E=%+ %+ :ms:kh=\E[H:da:mi:bt=\EI: #NOTE: bg can scroll, it just would rather not (ns) - rwells 3/13/81. # (Shouldn't you take out ns and put in an nl instead? - mrh) MG|bg|bitgraph|BBN BitGraph terminal:\ :do=^J:al=2*\E[L:bs:cd=150\E[J:ce=2\E[K:\ :cl=150\E[H\E[J:cm=%i\E[%d;%dH:co#85:\ :dl=2*\E[M:k0=\EP:k1=\EQ:k2=\ER:k3=\ES:kd=\EB:ke=\E>:kl=\ED:kr=\EC:\ :ks=\E=:ku=\EA:li#64:nd=\E[C:ns:pt:se=\E[0m:so=\E[7m:up=\E[A:sf=280\n: MH|d132|datagraphix|datagraphix 132a:\ :do=^J:co#80:li#30:cl=^l:ho=\Et:da:db:sf=\Ev:sr=\Ew:\ :up=\Ek:nd=\El:vs=\ex:ve=\Em\En:\ :al=\E3:ic=\E5:dc=\E6:in:ic=\E5: MI|soroc|Soroc 120:\ :do=^J:cd=\EY:ce=\ET:cl=2\E*:ma=^K^P^R^L^L :\ :kl=^H:ku=^K:kr=^L:kd=^J:tc=adm3a: # From: ma179abu%sdcc3@sdcsvax.ucsd.edu (Bill Houle) MI|iq140|soroc140|Soroc IQ140 with inverse & dim:\ :ic=\EQ:dc=\EW:al=\EE:dl=\ER:ce=\ET:cd=\EY:cl=\E+:cm=\E=%+ %+ :\ :up=^K:do=^J:le=^H:nd=^L:ho=^^:ta=\Ei:ma=^Kk^Jj^Hh^Ll^^h:am:bs:\ :co#80:li#24:ei=:im=:kb=^H:kh=^^:ku=^K:kd=^J:kl=^H:kr=^L:\ :k0=^AI:k1=^A@:k2=^AA:k3=^AB:k4=^AC:k5=^AD:k6=^AE:k7=^AF:\ :k8=^AG:k9=^AH:se=\E:so=\E:us=\E):ue=\E(: # tec is untested, and taken from CB/Unix virtual terminal driver. # Upper case terminal, uses lower case for control sequences!!! # The driver shows the C ~ operator used on CM coordinates. # Without the terminal in front of me, I can't figure out what's # going on, so I've dotted out the cm. Note there is no ~ in tgoto. MJ|tec400|tec scope:\ :do=^J:.cm=l%r%.%.:up=x:do=h:nd=g:le=w:ho=i:so={:se=|:sg#1:\ :cl=f:al=e:dl=u:ic=d:dc=t:ce=c:cd=s: # From ucbvax!geoff Mon Sep 21 21:15:45 1981 # This entry has been tested. MK|tec500|tec 500:\ :do=^J:am:le=^H:bs:cm=\E=%+ %+ :cl=20^Z:\ :co#80:ho=^^:li#24:nd=^L:up=^K:so=^]:se=^\: # I would appreciate more information on this terminal, such as the # manufacturer and the model number. There are too many tecs in here. ML|tec:\ :li#24:co#80:cl=^l:up=^k:nd=\037:\ :am:le=^H:bs:ho=\036:ma=^K^P^_ :do=^J: MM|teletec|Teletec Datascreen:\ :do=^J:am:le=^H:bs:co#80:cl=^l:ho=^^:li#24:nd=^_:up=^k: # From cbosg!ucbvax!SRC:george Fri Sep 11 22:38:32 1981 MN|ampex|d80|dialogue|dialogue80|ampex dialogue 80:\ :ct=\E3:st=\E1:do=^J:is=\EA:us=\El:ue=\Em:\ :am:le=^H:bs:pt:cl=75\E*:cm=\E=%+ %+ :\ :al=5*\EE:bt=\EI:ic=\EQ:im=:ei=:dl=5*\ER:dc=\EW:\ :ce=\Et:cd=\Ey:so=\Ej:se=\Ek:li#24:co#80:nd=^L:up=^K: # From: atd!dsd!rcb@ucbvax.berkeley.edu (Richard Bascove) A2|a210|210|ampex210|ampex a210:\ :am:bs:cl=\E*:cm=\E=%+ %+ :al=\EE:bt=\EI:ic=\EQ:im=:ei=:\ :dl=\ER:dc=\EW:ho=^^:xn:ce=\Et:cd=\Ey:li#24:co#80:nd=^L:up=^K:\ :pt:if=/usr/lib/tabset/std:is=\EC\Eu\E'\E(\El\EA\E%\E{\E.2\EG0\Ed\En:\ :kl=^H:kr=^L:kd=^V:ku=^K:kh=^^:hs:ts=\E.0\Eg\E}\Ef:fs=\E.2:\ :kn#10:k0=^A0^M:k1=^A1^M:k2=^A2^M:k3=^A3^M:k4=^A4^M:k5=^A5^M:\ :vb=\EU\EX\EU\EX\EU\EX\EU\EX:k6=^A6^M:k7=^A7^M:k8=^A8^M:k9=^A9^M:\ :so=\EG4:se=\EG0:us=\EG8:ue=\EG0:ug#1:sg#1: MO|digilog|333|digilog 333:\ :le=^H:bs:co#80:ce=\030:ho=^n:li#16:nd=^i:up=^o:do=^J: MP|ep48|ep4080|execuport 4080:\ :am:le=^H:bs:os:co#80:hu=\036:hd=\034:do=^J: MQ|ep40|ep4000|execuport 4000:\ :am:le=^H:bs:os:co#136:hu=\036:hd=\034:do=^J: MR|terminet1200|terminet300|tn1200|tn300|terminet|GE terminet 1200:\ :co#120:hc:os:do=^J: # AED 512 # by giles Billingsley (gilesb%ucbcad@berkeley) # rewritten 8/82 for newer AEDs and better operation of vi,etc. MS|aed|AED|aed512|AED512|aed 512:\ :db:co#64:li#40:cl=^L:bs:nd=\Ei0800\001:\ :up=^K:ve=\E\E\E\E\E\E\E\072004=000200??\001:\ :vb=\EK0001??0000K0001202080\001:\ :us=\E\07200>8000140\001:ue=\E\07200>8000100\001:\ :uc=\Ei???>l0800i0102\001:\ :ti=\E\07200>8000140{<04<0??00001010L<0\072004=0002??00\001:\ :te=\E\07200>8000100{804<0??00001000L80\072004=000200??\001:\ :so=\E\07200>8000140[80C00\001:se=\E[00C80\001:\ :is=\EG1MMM.`40K0001202080K8001????00^L\EC80L80{80^L\EK010100????K060\ 1??0000c818100\EG1HHH.\07210000019A27FD006A280D002A200A52429FE852486108611861\ 2861360N031B4C3F3F1800N041B0C1B4C38301800N001B3B313030301800N011B3B3130303418\ 00N021B3B313030381800N050800N061B3B313335301800\07211000015A58E8D5011A58F8D51\ 11A5908D5211A5918D531160\07212000015AD5011858EAD5111858FAD52118590AD531185916\ 0\0721300004B2071C5858E0A18658E0A0A858EA900858F268FA5278590A50A29018591A9F518\ 65908590A90165918591A59038E58E8590A591E58F290185912071C5180A0A0A0901858EA9008\ 58F268F60\0721350000BA9472031DEA9502031DE60\E\E\E\EG1MMM.^A: zL|aed-ucb|AED-UCB|aed512-ucb|AED512-UCB|aed 512 w/o UCB ROM:\ :db:co#64:li#40:cl=^L:bs:nd=\Ei0800\001:up=^K:\ :ve=\E\E\E\E\E\E\E\072004=000200??\001:\ :vb=\EK0001??0000K0001202080\001:\ :us=\E\07200>8000140\001:ue=\E\07200>8000100\001:\ :uc=\Ei???>l0800i0102\001:\ :ti=\E\07200>8000140{<04<0??00001010L<0\072004=0002??00\001:\ :te=\E\07200>8000100{804<0??00001000L80\072004=000200??\001:\ :so=\E\07200>8000140[80C00\001:se=\E[00C80\001:\ :if=/usr/lib/tabset/aed512: # CIT 80 - vt 100 emulator, the termcap has been modified to remove # the delay times and do an auto tab set rather than the indirect # file used in vt100. MT|cit80|cit 80|Citoh 80:\ :co#80:li#24:am:cl=\E[;H\EJ:bs:cm=\E[%i%2;%2H:nd=\E[C:up=\E[A:\ :ce=\EK:cd=\EJ:is=\E>:ks=\E[?1h\E=:ke=\E[?1l\E>:\ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD: # From mtxinu!sybase!tim (Tim Wood) Fri Sep 27 09:39:12 PDT 1985 # Alternate cit101 (vt100 em) file used in vt100. # Uses 23 lines so can run citsys (like h19sys). # 24 May 85 (mtxinu!sybase!tim) - removed 2-byte limit on 'cm' cursor # coordinates otherwise there is garbling on long lines in # co#132 mode; also added support for multipage memory on the Itoh. MU|citc|Citoh fast vt100:\ :co#80:li#23:am:cl=\E[;H\E[2J:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\ :is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[3g\E[>5g:\ :ks=\E[?1h\E=:ke=\E[?1l\E>:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:\ :vb=\E[?5h\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\E[?5l:\ :dc=\E[P:al=\E[L:im=:ei=:dl=\E[M:ic=\E[@:vs=\E7\E[U:ve=\E[V\E8:xn: MV|cita|:\ :co#80:li#23:am:cl=\E[;H\E[2J:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\ :is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[3g\E[>5g:\ :ks=\E[?1h\E=:ke=\E[?1l\E>:\ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:vs=\E7\E[U:ve=\E[V\E8:\ :vb=\E[?5h\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\E[?5l:xn: MW|cit101:li#24:vb@:tc=citc MX|cit101b:li#24:tc=citc Mh|cit500|cit-500|cit 500:\ :co#80:li#40:cl=50\E[;H\E[2J:bs:am:cm=5\E[%i%2;%2H:nd=2\E[C:up=2\E[A:\ :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\ :is=\E(B\E)0\E>\E[?3l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\ :if=/usr/lib/tabset/vt100:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:\ :kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=5\EM:xn:\ :do=\ED:al=\E[L:dc=\E[P:dl=\E[M: # Note several versions of blit. I don't know exactly what is what # so please send me any corrections to this -- mrh # From research!ikeya!rob Tue Aug 31 23:41 EDT 1982 MY|blit|jerq|blit-pb|blit running teletype rom:\ :do=^J:IC=\Ef%+ :DC=\Ee%+ :AL=\EF%+ :DL=\EE%+ :\ :mi:dl=\EE!:ic=\Ef!:dc=\Ee!:al=\EF!:\ :ce=\EK:cl=^L:cm=\EY%r%+ %+ :co#87:li#72:nd=\EC:\ :up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H:am:ul:pt:eo: MZ|cbblit|columbus enhanced tty blit:\ :vb=\E^G:so=\EU!:se=\EV!:us=\EU":ue=\EV":cd=\EJ:\ :im=\EQ:ei=\ER:ic@:co#88:sf=\EG:tc=blit: Ma|oblit|ojerq|first version of blit rom:\ :do=^J:AL=\Ef%+ :DL=\Ee%+ :mi:dl=\EE:ei=\ER:im=\EQ:dc=\EO:da:db:\ :al=\EF:cd=\EJ:ce=\EK:cl=^L:cm=\EY%r%+ %+ :co#88:li#72:nd=\EC:\ :up=\EA:vb=\E^G:am:ul:pt:eo: Mb|daleblit|daleterm|blit running Dale DeJager's ROM:\ :ku=\EA:kd=\EB:kr=\EC:kl=\ED:so=\EU!:se=\EV!:us=\EU":ue=\EV":\ :da@:db@:tc=oblit: Mc|datapoint|dp3|dp3360|datapoint 3360:\ :do=^J:am:le=^H:bs:cd=^_:ce=^^:cl=^]^_:co#82:ho=^]:li#25:nd=^x:up=^z: #From: cbosgd!utcs!romwa@ucbvax.berkeley.edu (mark dornfeld) # This termcap is for the LANPAR Technologies VISION 3220 # terminal. The function key definitions k0-k5 represent the # edit keypad: FIND, INSERT HERE, REMOVE, SELECT, PREV SCREEN, # NEXT SCREEN. The key definitions k6-k9 represent the PF1 to # PF4 keys. v0|v3220|LANPAR Vision II model 3220/3221/3222:\ :co#80:li#24:cl=\E[H\E[J:bs:am:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\ :is=\E>\E[?3l\E[?7h\E[?8h\E[p:ks=\E=:ke=\E>:\ :kn#10:k0=\E[1~:k1=\E[2~:k2=\E[3~:k3=\E[4~:k4=\E[5~:k5=\E[6~:\ :k6=\E[OP:k7=\E[OQ:k8=\E[OR:k9=\E[OS:\ :ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:\ :kh=\E[H:pt:sr=\EM:xn:\ :dl=\E[M:dc=\E[P:ei=\E[4l:al=\E[L:im=\E[4h:mi: # From ucbvax!faletti (Faletti@Berkeley) # FREEDOM 100 by Liberty Electronics USA, SF. # :kh=^^: left out because it precludes using change-to-alternate-file in vi. # Basic Freedom 100 entry, works with VI at 1200 baud. Md|f100|freedom100|freedom|freedom 100 no padding:\ :am:bs:bw:mi:ms:pt:co#80:kn#20:li#24:\ :ct=\E3:st=\E1:is=\Eg\Ef\r\Ed:kr=^L:\ :cl=^Z:do=^J:ho=^^:kb=^H:kl=^H:\:kd=^V:\ :ko=dc,al,dl,cl,bt,ce,cd:ku=^K:le=^H:nd=^L:\ :ch=\E]%+ :cm=\E=%+ %+ :cv=\E[%+ :sr=\Ej:up=^K:\ :al=\EE:bt=\EI:cd=\EY:ce=\ET:dc=\EW:dl=\ER:ei=\Er:im=\Eq:\ :se=\EG0:so=\EG4:ue=\EG0:us=\EG8:as=\E$:ae=\E%:\ :vb=\Eb\200\200\Ed:\ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:\ :k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:k0=^AI\r:\ :hs:ts=\Eg\Ef:fs=\r:ds=\Eg\Ef\r: Me|f100-rv|freedom100-rv|freedom-rv|freedom100 with reverse video at 1200:\ :is=\Eg\Ef\r\Eb:vb=\Ed\200\200\Eb:tc=freedom100: # VI at 9600 baud (or EMACS at 1200 -- but may be more than is needed for emacs) Mf|f100-v|freedom100-v|freedom-v|freedom100 for 9600 vi or 1200 emacs:\ :al=6.5*\EE:dl=11.5*\ER:\ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\ :tc=freedom100: Mx|f100-v-rv|freedom100-v-rv|freedom-v-rv|freedom100 rev. vid. for 9600 vi:\ :al=6.5*\EE:dl=11.5*\ER:is=\Eg\Ef\r\Eb:\ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\ :tc=freedom100: # EMACS at 9600 baud -- this still needs some more work on the padding My|f100-e|freedom100-e|freedom-e|freedom100 for 9600 emacs:\ :al=8.5*\EE:dl=11.5*\ER:ip=6:\ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\ :tc=freedom100: Mz|f100-e-rv|freedom100-e-rv|freedom-e-rv|freedom100 rev. vid. for emacs 9600:\ :al=8.5*\EE:dl=11.5*\ER:ip=6:is=\Eg\Ef\r\Eb:\ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\ :tc=freedom100: zM|f110-v|freedom110-v|freedom110 for 9600 vi or 1200 emacs:\ :is=\Eg\Ef\r\Ed\EO:dc=\EO\EW:im=\EO\Eq:\ :al=6.5*\EE:dl=11.5*\ER:\ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\ :tc=freedom100: # (from kerch@lll-crg) Q1|f200|freedom200| Freedom 200 VDT by Liberty Electronics :\ :if=/usr/lib/tabset/stdcrt:al=\EE:am:bs:bt=\EI:cd=\EY:\ :ce=\ET:cl=^Z:cm=\E=%+ %+ :co#80:dc=\EW:dl=\ER:do=^V:\ :ds=\Eh:ei=\Er:im=\Eq:is=\Eg\El\E\041\062:\ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:\ :k6=^AE\r:k7=^AE\r:k8=^AF\r:k9=^AG\r:kd=^V:kr=L:\ :ku=^K:li#24:ms:nd=^L:se=\EG0:so=\EG4:sr=\Ej:\ :te=\EJ\E\\2\E|\041\061^L^Y:ti=\E\\1\EK\E|\041\061L^Y:\ :ts=\Ef:ue=\EG0:up=^K:us=\EG8:vb=\Eb\Ed:hs:i2=\E^O\Eg:\ :ts=\Ef:fs=^M:ds=\E^N: Mg|dg|dg6053|data general 6053:\ :do=^J:am:le=^H:bs:cm=^P%r%.%.:cl=^L:ho=^H:nd=^S:\ :up=^W:ce=^K:co#80:li#24: # dg450 and dg200 from cornell Mj|dg450|dg6134|data general 6134:\ :nd=\030:bs@:tc=dg200: Mk|dg200|data general Dasher 200:\ :am:bc=^Y:bs=0:ce=^K:cl=^L:cm=^P%r%+\200%+\200:co#80:do=^Z:\ :ho=^H:li#24:\ :ll=\036FP0017:se=\036E:so=\036D:up=^W:\ :is=\036O\036FQ2\036FB000\036FE\036FA\036FQ2: # Note: lesser Dasher terminals will not work with vi because vi insists upon # having a command to move straight down from any position on the bottom line # and scroll the screen up, or a direct vertical scroll command. The 460 and # above have both, the D210/211, for instance, has neither. We must use ANSI # mode rather than DG mode because standard UNIX tty drivers assume that ^H is # backspace on all terminals. This is not so in DG mode. zF|dg460-ansi|Data General Dasher 460, ANSI-mode:\ :al=\E[L:am:bs:cd=\E[J:ce=\E[K:cl=\E[2J:\ :cm=\E[%i%2;%2H:co#80:dc=\E[P:dl=\E[M:do=\E[B:\ :ei=:ho=\E[H:ic=\E[@:im=:ue=\E[05:ul:up=\E[A:us=\E[4m:is=\036F@:\ :k0=\E[001z:k1=\E[002z:k2=\E[003z:k3=\E[004z:k4=\E[005z:k5=\E[006z:\ :k6=\E[007z:k7=\E[008z:k8=\E[009z:k9=\E[00\:z:\ :kb=\E[D:kd=\E[B:kh=\E[H:kl=\E[D:kr=\E[C:ku=\E[A:kn#6:\ :l0=f1:l1=f2:l2=f3:l3=f4:l4=f5:l5=f6:l6=f7:l7=f8:l9=f10:\ :le=^H:li#24:mb=\E[5m:me=\E[0m:mh=\E[2m:mr=\E[7m:ms:mu=\EW:\ :nd=\E[C:nl=\ED:pt:se=\E[0m:sf=\E[S:so=\E[7m:sr=\E[T: Mi|cdi|cdi1203:\ :am:le=^H:bs:hc:os:co#80:dC#200:do=^J: # ^S is an arrow key! Boy is this guy in for a surprise on v7! Ml|sol:\ :do=^J:am:le=^Y:ho=^H:bs:cm=\E^1%.\E^2%.:cl=^K:ho=^N:co#64:li#16:\ :nd=^S:up=^W:kl=^A:kr=^S:ku=^W:kd=^Z:ma=^A^H^S ^W^P^Z^N: Mn|xl83|Cybernex XL-83:\ :do=^J:am:le=^H:bs:cd=62^P:ce=3^O:cl=62^L:cm=^W%+ %+ :co#80:ho=^K:\ :kd=^J:kl=^H:ku=^N:li#24:up=^N:nd=^I: Mo|omron|Omron 8025AG:\ :do=^J:al=\EL:am:le=^H:bs:cd=\ER:co#80:ce=\EK:cl=\EJ:\ :da:db:dc=\EP:dl=\EM:ho=\EH:li#24:nd=\EC:se=\E4:sf=\ES:\ :so=\Ef:sr=\ET:up=\EA:ve=:vs=\EN: Mp|plasma|plasma panel:\ :am:le=^H:bs:cl=^L:co#85:ho=^^:li#45:nd=\030:up=\026:do=^J: Mq|pty|psuedo teletype:\ :do=^J:co#80:li#24:am:cl=\EJ:le=^H:bs:cm=\EG%+ %+ :nd=\EC:\ :up=\EA:ce=\EK:cd=\EL:al=\EP:dl=\EN:ic=\EO:\ :so=\Ea$:se=\Eb$:us=\Ea!:ue=\Eb!: Mr|remote|virtual remote terminal:\ :co#79:am@:nl@:tc=virtual: Ms|swtp|ct82|southwest technical products ct82:\ :do=^J:am:le=^d:bc=^d:\ :al=^\^y:cd=^v:ce=^F:cl=^L:cm=%r^k%.%.:co#82:li#20:\ :dl=^z:nd=^s:up=^a:so=^^^v:se=^^^F:dc=^\^h:ic=^\^x:ho=^p:\ :ei=:sf=^n:sr=^o:ll=^c:im=:\ :is=^\^r^^^s^^^d^]^w^i^s^^^]^^^o^]^w^r^i: Mt|terak|Terak emulating Datamedia 1520:\ :tc=dm1520: Mu|sun|Sun Microsystems Workstation console:\ :li#34:co#80:cl=^L:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :am:bs:mi:ms:pt:\ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:\ :kd=\E[B:kl=\E[D:ku=\E[A:kr=\E[C:kh=\E[H:\ :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\ :al=\E[L:dl=\E[M:im=:ei=:ic=\E[@:dc=\E[P:\ :AL=\E[%dL:DL=\E[%dM: # From john@ucbrenoir Tue Sep 24 13:14:44 1985 Mu|sun-s|Sun Microsystems Workstation window with status line:\ :hs:ts=\E]l:fs=\E\\:ds=\E]l\E\\:tc=sun: Mu|sun-e-s|sun-s-e|Sun Microsystems Workstation with status hacked for emacs:\ :hs:ts=\E]l:fs=\E\\:ds=\E]l\E\\:tc=sun-e: M0|sun-48|Sun 48-line window:\ :li#48:co#80:tc=sun: M1|sun-34|Sun 34-line window:\ :li#34:co#80:tc=sun: M2|sun-24|Sun 24-line window:\ :li#24:co#80:tc=sun: M3|sun-17|Sun 17-line window:\ :li#17:co#80:tc=sun: M4|sun-12|Sun 12-line window:\ :li#12:co#80:tc=sun: M5|sun-1|Sun 1-line window for sysline:\ :li#1:co#80:es:hs:ts=\r:fs=\E[K:ds=^L:tc=sun: M6|sun-e|sun-nic|sune|Sun Microsystems Workstation without insert character:\ :ic@:im@:ei@:tc=sun: LS|apollo:\ :al=\EI:am:bs:cd=\EJ:ce=\EK:ch=\EN%d:cl=^L:cm=\EM%+ %d):\ :cv=\EO+ :dc=\EP:dl=\EL:do=\EB:ei=\ER:im=\EQ:mi:nd=\EC:se=\ET:sf=\EE:\ :so=\ES:sr=\ED:te=\EX:ti=\EW:ue=\EV:up=\EA:us=\EU:co#88:li#53: # Apollo termcaps from Gary Darland, goodmanc@garnet LP|apollo_15P|apollo 15 inch display:\ :dN@:tc=vt132: LQ|apollo_19L|apollo 19 inch display:\ :dN@:tc=vt132: LR|apollo_color|apollo color display:\ :dN@:tc=vt132: Mv|virtual|VIRTUAL|cb unix virtual terminal:\ :do=^J:co#80:li#24:am:cl=\E\112:le=^H:bs:cm=\E\107%r%.%.:nd=\E\103:\ :up=\E\101:ce=\E\113:cd=\E\114:al=\E\120:dl=\E\116:im=:ei=:ic=\E\117:\ :da:db:kl=\E\104:kr=\E\103:ku=\E\101:kd=\E\102:kh=\E\105:\ :so=\E\141\004:se=\E\142\004:us=\E\141\001:ue=\E\142\001: Mw|it2|intertube2|intertec data systems intertube 2:\ :do=^J:am:bs:cl=^L:co#80:ho=^A:li#25:up=^Z:ce=\EK:\ :cm=^N%+ %+ :ch=^P%\102%.:cv=^K%.:nd=^F:do=\n:ll=^K^X\r:\ :so=\E0P:se=\E0@: Mx|delta|dd5000|delta data 5000:\ :do=^J:am:le=^H:bs:cl=^NR:cm=^O%\068%+9%\068%+9:co#80:li#27:\ :ho=^NQ:nc:nd=^Y:up=^Z:ce=^NU:dc=^NV:ma=^K^J^Z^P^Y :xr: My|mdl110|cybernex mdl-110:\ :cm=^P%+ %+ :co#80:li#24:am:cl=70^X:le=^H:bs:do=^J:\ :nd=^U:up=^Z:ho=^Y:ce=145^N@^V:cd=145^NA^W:al=65^NA^N^]:\ :dl=40^NA^N^^:im=:ei=:ic=3.5^NA^]:dm=:ed=:dc=3.5^NA^^:\ :so=^NF:se=^NG:ta=43\t:ma=^Z^P:cd=6^N@^V Mz|zen30|z30|zentec 30:\ :do=^J:mi:co#80:li#24:ma=^L ^R^L^K^P:ul:\ :al=1.5*\EE:le=^H:bs:ce=1.0*\ET:cm=\E=%+ %+ :cl=\E*:\ :ho=^^:nd=^L:se=\EG0:so=\EG6:up=^K:im=\Eq:ei=\Er:\ :am:dc=\EW:dl=1.5*\ER:cd=\EY: m0|modgraph|mod|Modgraph terminal emulating vt100, 24x80:\ :xn@:rf@:sr=5\EM\E[K:vs=\E\^9;0s\E\^7;1s:\ :is=\E\^9;0s\E\^7;1s\E[3g\E\^11;9s\E\^11;17s\E\^11;25s\E\^11;33s\E\^11;41s\E\^11;49s\E\^11;57s\E\^11;65s\E\^11;73s\E\^11;81s\E\^11;89s:\ :tc=vt100: # dmchat is like DM2500, but DOES need "all that padding" (jcm 1/31/82) # also, has a meta-key (MT) # from goldberger@su-csli.arpa MX|dmchat|dmchat version of datamedia 2500:\ :al=1*^P\n^X^]^X^]:\ :MT:km:\ :dl=2^P^Z^X^]:\ :tc=dm2500: #from Carol Block at ear (cblock@ear) # m7|mt70|m70|morrow mt70:\ :is=EGO\E"5:\ :cl=^Z:\ :cm=\E=%+ %+ :\ :do=^J:\ :im=:ic=\EQ:ei:\ :dm=:dc=\EW:ed=:\ :kl=\034L:kr=\034M:ku=\034J:kd=\034K:\ :so=\EG4:se=\EGO:\ :us=\EG1:ue=\EGO:\ :vs=\E"2:ve=\E"5\E(:\ :tc=adm31: # from keith bostic (bostic@monet) # m2|mod2|Modgraph GX-1000, set to 80x24, keypad not enabled:\ :is=\E<\E\^5;2s\E\^7;1s\E[3g\E\^11;9s\E\^11;17s\E\^11;25s\E\^11;33s\E\^11;41s\E\^11;49s\E\^11;57s\E\^11;65s\E\^11;73s\E\^11;81s\E\^11;89s\E\^12;0s\E\^14;2s\E\^15;9s\E\^25;1s\E\^9;1s\E\^27;1:\ :bs:cd=50\EJ:ce=3\EK:cl=50\EH\EJ:cm=5\EY%+ %+ :co#80:li#24:nd=2\EC:\ :pt:sr=5\EI:up=2\EA:da:db:am: S1|wsiris|iris40|iris emulating a 40 line visual 50 (approximately):\ :am:al=\EL:is=\E7B0\E7F7\E7C2\E7R3:\ :bs:cd=\EJ:ce=\EK:cl=\EH\EJ:ho=\EH:cm=\EY%+ %+ :co#80:li#40:nd=\EC:\ :pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:\ :k0=\E0:k1=\E1:k2=\E2:k3=\E3:k4=\E4:k5=\E5:k6=\E6:k7=\E7:k8=\E8:k9=\E9:\ :vs=\E;:ve=\E>:cl=\Ev:ho=\EH:dl=\EM:so=\E9P:se=\E0@:\ :HS=\E7F2:HE=\E7F7:\ :us=\E7R2\E9P:ue=\E7R3\E0@:\ :CT#2:CZ=*Bblack,red,green,yellow,blue,magenta,cyan,*Fwhite: # # -------------------------------- # # N: ANN ARBOR # # Needs function keys added. # Originally from Mike O'Brien@Rand and Howard Katseff at Bell Labs. # Highly modified 6/22 by Mike O'Brien. # split out into several for the various screen sizes by dave-yost@rand # Modifications made 3/82 by Mark Horton # Modified by Tom Quarles at UCB for greater efficiency and more diversity # status line moved to top of screen, vb removed 5/82 # # assumes the following setup: # A menu: 0000 1010 0001 0000 # B menu: 9600 0100 1000 0000 0000 1000 0000 17 19 # C menu: 56 66 0 0 9600 0110 1100 # D menu: 0110 1001 1 0 # # Briefly, the settings are for the following modes: # (values are for bit set/clear with * indicating our preference # and the value used to test these termcaps) # Note that many of these settings are irelevent to the termcap # and are just set to the default mode of the terminal as shipped # by the factory. # # A menu: 0000 1010 0001 0000 # Block/underline cursor* # blinking/nonblinking cursor* # key click/no key click* # bell/no bell at column 72* # # key pad is cursor control*/key pad is numeric # return and line feed/return for key * # repeat after .5 sec*/no repeat # repeat at 25/15 chars per sec. * # # hold data until pause pressed/process data unless pause pressed* # slow scroll/no slow scroll* # Hold in area/don't hold in area* # functions keys have default*/function keys disabled on powerup # # show/don't show position of cursor during page transmit* # unused # unused # unused # # B menu: 9600 0100 1000 0000 0000 1000 0000 17 19 # Baud rate (9600*) # # 2 bits of parity - 00=odd,01=even*,10=space,11=mark # 1 stop bit*/2 stop bits # parity error detection off*/on # # keyboard local/on line* # half/full duplex* # disable/do not disable keyboard after data transmission* # # transmit entire page/stop transmission at cursor* # transfer/do not transfer protected characters* # transmit all characters/transmit only selected characters* # transmit all selected areas/transmit only 1 selected area* # # transmit/do not transmit line seperators to host* # transmit/do not transmit page tab stops tabs to host* # transmit/do not transmit column tab stop tabs to host* # transmit/do not transmit graphics control (underline,inverse..)* # # enable*/disable auto XON/XOFF control # require/do not require receipt of a DC1 from host after each LF* # pause key acts as a meta key/pause key is pause* # unused # # unused # unused # unused # unused # # XON character (17*) # XOFF character (19*) # # C menu: 56 66 0 0 9600 0110 1100 # number of lines to print data on (printer) (56*) # # number of lines on a sheet of paper (printer) (66*) # # left margin (printer) (0*) # # number of pad chars on new line to printer (0*) # # printer baud rate (9600*) # # printer parity: 00=odd,01=even*,10=space,11=mark # printer stop bits: 2*/1 # print/do not print guarded areas* # # new line is: 01=LF,10=CR,11=CRLF* # unused # unused # # D menu: 0110 1001 1 0 # LF is newline/LF is down one line, same column* # wrap to preceeding line if move left from col 1*/don't wrap # wrap to next line if move right from col 80*/don't wrap # backspace is/is not destructive* # # display*/ignore DEL character # display will not/will scroll* # page/column tab stops* # erase everything*/erase unprotected only # # editing extent: 0=display,1=line*,2=field,3=area # # unused # NA|aaa-unk|ann arbor ambassador (internal - don't use this directly):\ :do=^J:al=3\E[L:am:le=^H:bs:\ :cd=\E[J:ce=5\E[K:cl=156\E[H\E[J:cm=\E[%i%d;%dH:co#80:\ :dc=4\E[P:dl=3\E[M:ho=\E[H:ic=4\E[@:\ :md=\E[1m:mr=\E[7m:mb=\E[5m:mk=\E[8m:me=\E[m:\ :ku=\EM:kd=\ED:kl=\E[D:kr=\E[C:kh=\E[H:ko=cl,dc,dl,ce,cd:\ :ks=\EP`?z~[H~[[J`>z~[[J`8xz~[M`4xz~[[D`6xz~[[C`2xz~[D\E\\:\ :ke=\EP`?y~[H~[[J`>y~[[2J`8xy~[M`4xy~[[D`6xy~[[C`2xy~[D\E\\:\ :ch=\E[%i%d`:ei=:im=:pt:bw:bt=\E[Z:\ :mi:nd=\E[C:se=\E[m:so=\E[7m:ue=\E[m:us=\E[4m:up=\EM: NB|aaa-18|ann arbor ambassador/18 lines:\ :ti=\E[2J\E[18;0;0;18p:te=\E[60;0;0;18p\E[18;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;18p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#18:tc=aaa-unk: NC|aaa-20|ann arbor ambassador/20 lines:\ :ti=\E[2J\E[20;0;0;20p:te=\E[60;0;0;20p\E[20;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;20p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#20:tc=aaa-unk: ND|aaa-22|ann arbor ambassador/22 lines:\ :ti=\E[2J\E[22;0;0;22p:te=\E[60;0;0;22p\E[22;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;22p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#22:tc=aaa-unk: NE|aaa-24|ann arbor ambassador/24 lines:\ :ti=\E[2J\E[24;0;0;24p:te=\E[60;0;0;24p\E[24;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;24p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#24:tc=aaa-unk: NF|aaa-26|ann arbor ambassador/26 lines:\ :ti=\E[2J\E[26;0;0;26p:te=\E[60;0;0;26p\E[26;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;26p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#26:tc=aaa-unk: NG|aaa-28|ann arbor ambassador/28 lines:\ :ti=\E[2J\E[28;0;0;28p:te=\E[60;0;0;28p\E[28;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;28p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#28:tc=aaa-unk: NH|aaa|aaa-30|ambas|ambassador|ann arbor ambassador/30 lines:\ :ti=\E[2J\E[30;0;0;30p:te=\E[60;0;0;30p\E[30;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#30:tc=aaa-unk: NI|aaa-36|ann arbor ambassador/36 lines:\ :ti=\E[2J\E[36;0;0;36p:te=\E[60;0;0;36p\E[36;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;36p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#36:tc=aaa-unk: NJ|aaa-40|ann arbor ambassador/40 lines:\ :ti=\E[2J\E[40;0;0;40p:te=\E[60;0;0;40p\E[40;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;40p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#40:tc=aaa-unk: NK|aaa-48|ann arbor ambassador/48 lines:\ :ti=\E[2J\E[48;0;0;48p:te=\E[60;0;0;48p\E[48;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;48p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#48:tc=aaa-unk: NL|aaa-60|ann arbor ambassador/60 lines:\ :ti=\E[2J\E[60;0;0;60p:te=\E[60;0;0;60p\E[60;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;0;0;60p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#60:tc=aaa-unk: NS|aaa-unk-s|ann arbor ambassador unknown with/status:\ :es:hs:i2=\E7\E[>51h\E[H\E[2K\E[>51l\E8:\ :ts=\E7\E[>51h\E[H\E[2K\E[%i%d`:fs=\E[>51l\E8:\ :ds=\E7\E[>51h\E[H\E[2K\E[>51l\E8:\ :tc=aaa-unk: NM|aaa-18-s|ambassador|ann arbor ambassador/18 lines + status line:\ :ti=\E[2J\E[18;1;0;18p:\ :te=\E[60;1;0;18p\E[17;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;18p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#17:tc=aaa-unk-s: NN|aaa-20-s|ambassador|ann arbor ambassador/20 lines + status line:\ :ti=\E[2J\E[20;1;0;20p:\ :te=\E[60;1;0;20p\E[19;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;20p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#19:tc=aaa-unk-s: NO|aaa-22-s|ambassador|ann arbor ambassador/22 lines + status line:\ :ti=\E[2J\E[22;1;0;22p:\ :te=\E[60;1;0;22p\E[21;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;22p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#21:tc=aaa-unk-s: NP|aaa-24-s|ambassador|ann arbor ambassador/24 lines + status line:\ :ti=\E[2J\E[24;1;0;24p:\ :te=\E[60;1;0;24p\E[23;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;24p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#23:tc=aaa-unk-s: NQ|aaa-26-s|ambassador|ann arbor ambassador/26 lines + status line:\ :ti=\E[2J\E[26;1;0;26p:\ :te=\E[60;1;0;26p\E[25;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;26p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#25:tc=aaa-unk-s: NR|aaa-28-s|ambassador|ann arbor ambassador/28 lines + status line:\ :ti=\E[2J\E[28;1;0;28p:\ :te=\E[60;1;0;28p\E[27;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;28p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#27:tc=aaa-unk-s: NT|aaa-30-s|ambassador|ann arbor ambassador/30 lines + status line:\ :ti=\E[2J\E[30;1;0;30p:\ :te=\E[60;1;0;30p\E[29;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#29:tc=aaa-unk-s: NU|aaa-36-s|ambassador|ann arbor ambassador/36 lines + status line:\ :ti=\E[2J\E[36;1;0;36p:\ :te=\E[60;1;0;36p\E[35;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;36p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#35:tc=aaa-unk-s: NV|aaa-40-s|ambassador|ann arbor ambassador/40 lines + status line:\ :ti=\E[2J\E[40;1;0;40p:\ :te=\E[60;1;0;40p\E[39;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;40p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#39:tc=aaa-unk-s: NW|aaa-48-s|ann arbor ambassador/48 lines+sl:\ :ti=\E[2J\E[48;1;0;48p:te=\E[60;1;0;48p\E[47;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\EP`?y~[[2J~[[H\E7\E[60;1;0;48p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#47:tc=aaa-unk-s: NX|aaa-60-s|ambassador|ann arbor ambassador/60 lines + status line:\ :ti=\E[2J\E[60;1;0;60p:te=\E[60;1;0;60p\E[59;1H\E[J:\ :is=\EP`+x~M\E\\\E[m\E7\E[60;1;0;60p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#59:tc=aaa-unk-s: NY|aaa-18-rv|ambassador/18 lines+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;18p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-18: NZ|aaa-20-rv|ambassador/20 lines+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;20p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-20: Na|aaa-22-rv|ambassador/22 lines+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;22p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-22: Nb|aaa-24-rv|ambassador/24 lines+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;24p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-24: Nc|aaa-26-rv|ambassador/26 lines+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;26p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-26: Nd|aaa-28-rv|ambassador/28 lines+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;28p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-28: Ne|aaa-30-rv|ann arbor ambassador/30 lines in reverse video:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-30: Nf|aaa-36-rv|ann arbor ambassador/36 lines in reverse video:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;36p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-36: Ng|aaa-40-rv|ann arbor ambassador/40 lines in reverse video:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;40p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-40: Nh|aaa-48-rv|ann arbor ambassador/48 lines in reverse video:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;48p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-48: Ni|aaa-60-rv|ann arbor ambassador/60 lines in reverse video:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;60p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-60: Nj|aaa-18-rv-s|aaa-18-s-rv|ambassador/18 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[18;1;0;18p:te=\E[60;1;0;18p\E[17;1H\E[J:li#17:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;18p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: Nk|aaa-20-rv-s|aaa-20-s-rv|ambassador/20 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[20;1;0;20p:te=\E[60;1;0;20p\E[19;1H\E[J:li#19:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;20p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: Nl|aaa-22-rv-s|aaa-22-s-rv|ambassador/22 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[22;1;0;22p:te=\E[60;1;0;22p\E[21;1H\E[J:li#21:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;22p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: Nm|aaa-24-rv-s|aaa-24-s-rv|ambassador/24 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[24;1;0;24p:te=\E[60;1;0;24p\E[23;1H\E[J:li#23:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;24p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: Nn|aaa-26-rv-s|aaa-26-s-rv|ambassador/26 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[26;1;0;26p:te=\E[60;1;0;26p\E[25;1H\E[J:li#25:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;26p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: No|aaa-28-rv-s|aaa-28-s-rv|ambassador/28 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[28;1;0;28p:te=\E[60;1;0;28p\E[27;1H\E[J:li#27:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;28p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: Np|aaa-rv|aaa-30-rv-s|aaa-30-s-rv|ambassador/30 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[30;1;0;30p:te=\E[60;1;0;30p\E[29;1H\E[J:li#29:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: Nq|aaa-36-rv-s|aaa-36-s-rv|ambassador/36 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[36;1;0;36p:te=\E[60;1;0;36p\E[35;1H\E[J:li#35:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;36p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: Nr|aaa-40-rv-s|aaa-40-s-rv|ambassador/40 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[40;1;0;40p:te=\E[60;1;0;40p\E[39;1H\E[J:li#39:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;40p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: Ns|aaa-48-rv-s|aaa-48-s-rv|ambassador/48 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[48;1;0;48p:te=\E[60;1;0;48p\E[47;1H\E[J:li#47:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;48p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: Nt|aaa-60-rv-s|aaa-60-s-rv|ambassador/60 lines+sl+rv:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :ti=\E[2J\E[60;1;0;60p:te=\E[60;1;0;60p\E[59;1H\E[J:li#59:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;60p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :tc=aaa-unk-s: NL|aaa-24-ctxt|ann arbor ambassador/24 lines:\ :ti=\E[30;1H\E[K\E[24;0;0;24p:te=\E[60;1;0;24p\E[60;1H\E[K:tc=aaa-24: NL|aaa-24-rv-ctxt|ambassador/24+rv:\ :ti=\E[30;1H\E[K\E[24;0;0;24p:te=\E[60;1;0;24p\E[60;1H\E[K:tc=aaa-24-rv: NL|aaa-s-ctxt|aaa-30-s-ctxt|hairy aaa:\ :ti=\E[30;1H\E[K\E[30;1;0;30p:te=\E[60;1;0;30p\E[59;1H\E[K:tc=aaa-30-s: NL|aaa-s-rv-ctxt|aaa-30-s-rv-ctxt|hairy aaa:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;1;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :ti=\E[30;1H\E[K\E[30;1;0;30p:te=\E[60;1;0;30p\E[59;1H\E[K:\ :li#29:tc=aaa-unk-s: NH|aaa-ctxt|aaa-30-ctxt|ann arbor ambassador/30 lines:\ :ti=\E[30;0;0;30p:te=\E[60;0;0;30p\E[60;1H\E[K:tc=aaa-30: NH|aaa-rv-ctxt|aaa-30-rv-ctxt|ann arbor ambassador/30 lines:\ :ti=\E[30;0;0;30p:te=\E[60;0;0;30p\E[60;1H\E[K:\ :md=\E[1;7m:mr=\E[m:mb=\E[5;7m:mk=\E[7;8m:me=\E[7m:\ :us=\E[4;7m:ue=\E[7m:se=\E[7m:so=\E[m:\ :is=\EP`+x~M\E\\\E[7m\E7\E[60;0;0;30p\E[3g\E[f\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E[8a\EH\E8\E[>6h\E[1Q:\ :li#30:tc=aaa-unk: Nd|aaa-db|ann arbor ambassador 30/destructive backspace:\ :ti=\E[H\E[J\E[30;0;0;30p:te=\E7\E[60;0;0;30p\E8:li#30:\ :is=\E[60;0;0;30p\E[H\E[J\E[1Q\E[m\E[20l\E[>30h:le=\E[D:bc=\E[D:bs@:\ :tc=aaa-unk: N1|aa|annarbor|4080|ann arbor 4080:\ :do=^J:pt:ct=^\^P^P:st=^]^P1:cm=^O%r%\066%.%>^S^L%+@:\ :co#80:li#40:le=^H:bs:cl=2^L:up=^N:nd=^_:ho=^K:am:\ :kb=^^:kd=^J:ku=^N:kl=^H:kr=^_:kh=^K:ma=^_ ^N^P: # # -------------------------------- # # P: PC entries for use with kermit # # greg small (gts@populi) # # Cannot use :pt:, it does not work (why?). :ho: seems required (why?). [gts] # Caution: 4.3 BSD tset does not pass li#25 to stty rows except during login? # :cl: clears attributes and sets wrap at margin before clearing the screen. P1|ansi.sys|ansisys|PC-DOS 3.1 ANSI.SYS:\ :am:bs:ce=\E[K:cl=\E[m\E[7h\E[2J:cm=\E[%i%d;%dH:co#80:\ :ku=^K:kd=^J:kl=^H:kr=^L:kh=^^:ma=^Hh\012j^Kk^Ll^^H:\ :ho=\E[H:li#25:nd=\E[C:up=\E[A:\ :ms:md=\E[1m:me=\E[m:mr=\E[7m:se=\E[m:so=\E[1m:ue=\E[m:us=\E[4m:\ :is=U1 PC-DOS 3.1 ANSI.SYS 9-23-86\n\E[m\E[7h: # # Define IBM PC keypad keys for vi as per MS-Kermit while using ANSI.SYS. # This should only be used when the terminal emulator cannot redefine the keys. # Since redefining keys with ansi.sys also affects PC-DOS programs, the key # definitions must be restored. If the terminal emulator is quit while in vi # or others using :ks:ke:, the keypad keys will not be defined as per PC-DOS. # The PgUp and PgDn are prefixed with ESC so that tn3270 can be used on Unix # (^U and ^D are already defined for tn3270). The ESC is safe for vi but it # does "beep". ESC ESC i is used for Ins to avoid tn3270 ESC i for coltab. # Left arrow is always BS, because PC-dos can tolerate this change. # Caution: vi is limited to 256 string bytes, longer crashes or wierds vi. # Consequently the End keypad key could not be set (it is relatively safe and # actually useful because it sends ^@ O, which beeps and opens a line above). P2|ansi.sysk|ansisysk|PC-DOS 3.1 ANSI.SYS with keypad redefined for vi:\ :ks=\E[;71;30p\E[;72;11p\E[;73;27;21p\E[;77;12p\E[;80;10p\E[;81;27;4p\E[;82;27;27;105p\E[;83;127p:\ :ke=\E[;71;0;71p\E[;72;0;72p\E[;73;0;73p\E[;77;0;77p\E[;80;0;80p\E[;81;0;81p\E[;82;0;82p\E[;83;0;83p:\ :is=U2 PC-DOS 3.1 ANSI.SYS with keypad redefined for vi 9-29-86\n\E[;75;8p:\ :tc=ansi.sys # # Adds ins/del line/character, hence vi reverse scrolls/inserts/deletes nicer. P3|nansi.sys|nansisys||PC-DOS Public Domain NANSI.SYS:\ :al=\E[1L:dl=\E[1M:ic=\E[1@:dc=\E[1P:\ :is=U3 PC-DOS Public Domain NANSI.SYS 9-23-86\n:\ :tc=ansi.sys: # # See U2 ansi.sysk and U3 nansi.sys above. P4|nansi.sysk|nansisysk|PC-DOS Public Domain NANSI.SYS with keypad redefined for vi:\ :al=\E[1L:dl=\E[1M:ic=\E[1@:dc=\E[1P:\ :is=U4 PC-DOS Public Domain NANSI.SYS with keypad redefined for vi 9-29-86\n\E[;75;8p:\ :tc=ansi.sysk: # # -------------------------------- # # T: TELETYPE # # We need descriptions for the model 40. There are known to be at least three # flavors of the 40, both seem more like IBM half duplex forms fillers than # ASCII terminals. They have lots of awful braindamage, such as printing # a visible newline indicator after each newline. The 40-1 is a half duplex # terminal and is hopeless. The 40-2 is braindamaged but has hope and is # described here. The 40-4 is a 3270 lookalike and beyond hope. # The terminal has visible bell but I don't know it - it's # null here to prevent it from showing the BL character. # There is an \EG in nl because of a bug in vi (if stty says you have # a "newline" style terminal (-crmode) vi figures all it needs is nl # to get crlf, even if cr is not ^M.) T0|40|tty40|ds40|ds40/2|ds40-2|dataspeed40|teletype dataspeed 40/2:\ :cl=160\ER:cd=160\EJ:al=160\EL:dl=160\EM:dc=50\EP:im=:ei=:ic=50\E\^:\ :nd=\EC:up=\E7:bs:cr=\EG:nl=\EG\EB:do=\EB:co#80:li#24:vb=:\ :so=\E3:se=\E4: T3|33|tty33|tty|model 33 teletype:\ :do=^J:co#72:hc:os: T4|43|tty43|model 43 teletype:\ :do=^J:kb=^h:am:le=^H:bs:hc:os:co#132: T7|37|tty37|model 37 teletype:\ :do=^J:le=^H:bs:hc:hu=\E8:hd=\E9:up=\E7:os: # From jwb Wed Mar 31 13:25:09 1982 remote from ihuxp # This entry appears to avoid the top line - I have no idea why. TT|4424|tty4424|teletype 4424M:\ :al=\EL:da:db:ip=2:im=:ei=:ic=\E\^:dc=\EP:dl=\EM:\ :co#80:li#23:am:cl=\E[2;H\E[J:bs:cm=\E[%i%2;%2H\E[B:\ :nd=\E[C:up=\E[A:pt:mi:sr=\ET:\ :ce=\E[K:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\ :is=\E[m\E[2;24r:\ :kd=\E[B:kl=\E[D:ku=\E[A:kr=\E[C:\ :kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS: # Teletype blit. TD|dmd|5620|ttydmd|tty5620|5620 terminal 88 columns:\ :co#88:li#70:am:bs:pt:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :cl=\E[H\E[J:cd=\E[J:ce=\E[K:al=\E[L:dl=\E[M:do=^J:\ :im=:ei=:ic=\E[@:dc=\E[P:sr=\E[T:sf=\E[S:le=^H:kb=^H:\ :kl=\E[D:kr=\E[C:ku=\E[A:kd=\E[B:kh=\E[H:ho=\E[H:ll=\E[70;1H:\ :AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:rc=\E8:rs=\Ec:sc=\E7:\ :so=\E[7m:se=\E[0m:us=\E[4m:ue=\E[0m:ms:me=\E[0m:mr=\E[7m: # # -------------------------------- # # V: VISUAL # # The Visual 200 beeps when you type a character in insert mode. # This is a horribly obnoxious misfeature, and some of the entries # below try to get around the problem by ignoring the feature or # turning it off when inputting a character. They are said not to # work well at 300 baud. (You could always cut the wire to the bell!) #From mike@brl-vgr Mon Nov 14 08:34:29 1983 V2|vi200|vis200|visual 200 with function keys:\ :so=\E4:se=\E3:ms:do=^J:\ :al=\EL:am:le=^H:bs:cd=\Ey:ce=\Ex:cl=\Ev:\ :cm=\EY%+ %+ :co#80:dc=\EO:dl=\EM:ho=\EH:\ :im=:ei=:ic=\Ei \b\Ej:\ :is=\E3\Eb\Ej\E\\\El\EG\Ec\Ek:\ :k0=\EP:k1=\EQ:k2=\ER:k3=\E :k4=\E!:k5=\E":k6=\E#:\ :k7=\E$:k8=\E%:k9=\E&:kl=\ED:kr=\EC:ku=\EA:kd=\EB:kh=\EH:\ :li#24:nd=\EC:pt:sr=\EI:up=\EA:vs=\Ed:ve=\Ec: VR|vi200-rv-ic|visual 200 reverse video using insert char:\ :ei=\Ej:im=\Ei:ic@:tc=vi200-rv: # The older Visuals didn't come with function keys. This entry uses # ks and ke so that the keypad keys can be used as function keys. # If your version of vi doesn't support function keys you may want # to use V2. Vf|vi200-f|visual|visual 200 no function keys:\ :do=^J:al=\EL:am:le=^H:bs:cd=\Ey:ce=4*\Ex:cl=\Ev:\ :cm=\EY%+ %+ :co#80:dc=4*\EO:dl=4*\EM:ho=\EH:\ :im=:ei=:ic=\Ei \b\Ej:\ :is=\E3\Eb\Ej\E\\\El\EG\Ed\Ek:ks=\E=:ke=\E>:\ :k0=\E?p:k1=\E?q:k2=\E?r:k3=\E?s:k4=\E?t:k5=\E?u:k6=\E?v:\ :k7=\E?w:k8=\E?x:k9=\E?y:kl=\ED:kr=\EC:ku=\EA:kd=\EB:kh=\EH:\ :li#24:nd=\EC:pt:sr=\EI:up=\EA:vs=\Ed:ve=\Ec: Vr|vi200-rv|visual 200 reverse video:\ :so=\E4:se=\E3:sr@:vs@:ve@:tc=vi200: Vt|vi200-ic|visual 200 using insert char:\ :ei=\Ej:im=\Ei:ic@:tc=vi200: # From: jbs@athena.mit.edu Jeff Siegal V5|vi55|Visual 55:\ :im=\Ea:ei=\Eb:mi:dc=\Ew:dm=:ed=:al=\EL:dl=\EM:cs=\E_%+A%+A:\ :ho=\EH:cl=\Ev:is=\Ev\E_AX\Eb\EW\E9P\ET:so=\EU:se=\ET:ms:\ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cm=\EY%+ %+ :co#80:li#24:\ :nd=\EC:pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H: # # -------------------------------- # # X: TEKTRONIX # Xa|tek|tek4012|4012|tektronix 4012:\ :do=^J:is=\E^O:le=^H:bs:cl=1000\E^L:co#75:ns:li#35:os: Xb|tek4013|4013|tektronix 4013:\ :as=\E^N:ae=\E^O:dF#1000:tc=4012: Xc|tek4014|4014|tektronix 4014:\ :is=\E^O\E9:co#81:li#38:dF#1000:tc=tek4012: Xd|tek4015|4015|tektronix 4015:\ :as=\E^N:ae=\E^O:tc=4014: Xe|tek4014-sm|4014-sm|tektronix 4014 in small font:\ :is=\E^O\E\072:co#121:li#58:tc=tek4014: Xf|tek4015-sm|4015-sm|tektronix 4015 in small font:\ :as=\E^N:ae=\E^O:tc=4014-sm: # I think the 1000UP is supposed to be so expensive it never happens. X4|tek4023|4023|tex|tektronix 4023:\ :do=^J:so=^_P:se=^_@:cm=\034%r%+ %+ :nd=\t:le=^H:\ :bs:cl=4\E^L:co#80:li#24:am:up=1000UP:vt#4: # Can't use cursor motion because it's memory relative, and because # it only works in the workspace, not the monitor. Same for home. # Likewise, standout only works in the workspace. # 145 ms padding on al and AL taken out since it doesn't seem to be needed much. X5|4025|4027|4024|tek4025|tek4027|tek4024|4025cu|4027cu|tektronix 4024/4025/4027:\ :sf=^F^J:do=^F^J:is=\41com 31\r\n^_sto 9 17 25 33 41 49 57 65 73\r:\ :ks=^_lea p4 /h/\r^_lea p8 /k/\r^_lea p6 / /\r^_lea p2 /j/\r^_lea f5 /H/\r^_lea p5 /H/\r:\ :ke=^_lea p2\r^_lea p4\r^_lea p6\r^_lea p8\r^_lea p5\r^_lea f5\r:\ :am:le=^H:bs:da:db:pt:li#34:co#80:cl=^_era\r\n\n:up=^K:nd=^_rig\r:\ :al=^_up\r^_ili\r:dl=^_dli\r^F:\ :dc=^_dch\r:im=^_ich\r:ei=^F^_dow\r^K:nl=^F\n:\ :cd=^_dli 50\r:CC=^_:AL=^_up\r^_ili %d\r:DL=^_dli %d\r^F:\ :UP=^_up %d\r:DO=^_dow %d\r:LE=^_lef %d\r:RI=^_rig %d\r: X7|4025-17|4027-17|tek 4025 17 line window:\ :li#17:tc=4025: X8|4025-17ws|4027-17ws|tek 4025 17 line window in workspace:\ :is=\41com 31\r\n^_sto 9,17,25,33,41,49,57,65,73\r^_wor 17\r^_mon 17\r:\ :ti=^_wor h\r:te=^_mon h\r:so=^_att e\r:se=^_att s\r:tc=4025-17: X9|4025ex|4027ex|tek 4025 w/!:\ :ti=\41com 31\r:te=^_com 33\r:\ :is=^_com 33\r\n\41sto 9,17,25,33,41,49,57,65,73\r:tc=4025: # From jcoker@ucbic Xp|4107|tek4107|Tektronix 4107 graphics terminal with memory:\ :ti=\E[?6l\E[H\E[J:te=\E[?6h\E%!0\ELBP0\E%!1\E[32;1f:\ :is=\E%!0\ELBP0\E%!1\E[H\E[2g\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[J:\ :li#32:do=^J:al=3\E[L:xn:am:le=^H:bs:cd=\E[J:\ :ce=5\E[K:cl=156\E[H\E[J:cm=\E[%i%d;%dH:co#80:dc=4\E[P:dl=3\E[M:\ :ho=\E[H:ic=4\E[@:md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:ku=\EM:\ :kd=\ED:kl=\E[D:kr=\E[C:kh=\E[H:\ :ei=:im=:pt:bw:bt=\E[Z:mi:nd=\E[C:se=\E[m:so=\E[7m:\ :ue=\E[m:us=\E[4m:up=\EM: # Tektronix 4107 with sysline Xq|4107-s|tek4107-s|Tektronix 4107 with sysline but no memory:\ :is=\E%!1\E[2;32r\E[132D\E[2g\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[8C\EH\E[J:\ :es:hs:i2=\E7\E[?6l\E[2K\E[?6h\E8:ts=\E7\E[?6l\E[2K\E[;%i%df:\ :fs=\E[?6h\E8:ds=\E7\E[?6l\E[2K\E[?6h\E8:tc=4107: # From cbosg!teklabs!davem Wed Sep 16 21:11:41 1981 # Here's the comamnd file that I use to get rogue to work on the 4025. # It should work with any program using the old curses (e.g. it better # not try to scroll, or cursor addressing won't work. Also, you can't # see the cursor.) # (This "learns" the arrow keys for rogue. I have adapted it for termcap - mrh) Xr|4025-cr|tek 4025 for curses and rogue:\ :is=\41com 31\r\n^_sto 9 17 25 33 41 49 57 65 73\r:\ :am:le=^H:bs:pt:li#33:co#80:cm=^_jum%i%d,%d;:up=^K:\ :do=^F^J:cl=^_era;:nd=^_rig;:nl=^F\n:ti=^_wor 33h:te=^_wor 0: # next two lines commented out since curses only allows 128 chars, sigh. # :ti=^_lea p1/b/^_lea p2/j/^_lea p3/n/^_lea p4/h/^_lea p5/ /^_lea p6/l/^_lea p7/y/^_lea p8/k/^_lea p9/u/^_lea p./f/^_lea pt/`era w/13^_lea p0/s/^_wor 33h:\ # :te=^_lea p1^_lea p2^_lea p3^_lea p4^_lea pt^_lea p5^_lea p6^_lea p7^_lea p8^_lea p9/la/13^_lea p.^_lea p0^_wor 0: # The 4110 series may be a wonderful graphics series, but they make the 4025 # look good for screen editing. In the dialog area, you can't move the cursor # off the bottom line. Out of the dialog area, ^K moves it up, but there # is no way to scroll. Xs|4112|4114|tek4112|tektronix 4110 series:\ :is=\E3!1:li#34:co#80:am:al=\E[L:bs:bt=\E[Z:\ :cd=\E[0J:ce=\E[0K:cl=\E[2J\E[0;0H:cm=\E[%i%d;%dH:\ :db:dc=\E[P:dl=\E[M:ic=\E[@:im=:nd=\E[C:se=\E[m:\ :so=\E[7m:ue=\E[m:up=\EM:us=\E[4m:vs=:ve=:\ :sr=\E7\E[0;0H\E[L\E8:sf=\E7\E[0;0H\E[M\E8: Xt|4112-nd|4112 not in dialog area:up=^K:ns:tc=4112: Xu|4112-5|4112 in 5 line dialog area:li#5:tc=4112: Xv|4113|tek4113|tektronix 4113 color graphics, 5 line dialog area:\ :le=^H:do=^J:eo:da:bs:am:li#5:co#80:is=\EKA1\ELL5\ELV0\ELV1:\ :vb=\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERB0:\ :cl=\ELZ:uc=^H\ELM1_\ELM0:nd=\LM1 \LM0:\ :.as=\E^N:.ae=\E^O: Xw|4113-34|tek4113-34|tektronix 4113 color graphics, 34 line dialog area:\ :is=\EKA1\ELLB2\ELV0\ELV1:li#34:tc=tek4113: # ns hidden from vi to allow visual mode. APL font (as, ae) not supported here. # uc is slow, but looks nice. Suggest setenv MORE -up . vb needs enough delay # to let you see the background color being toggled. Xy|4113-nd|tek4113-nd|tektronix 4113 color graphics, no dialog area:\ :le=^H:do=^J:nd=\t:up=^K:ll=\ELF hl @:ho=\ELF7l\177 @:\ :eo:bs:am:li#34:co#80:is=\ELZ\EKA0\ELF7l\177 @:vs=\ELZ\EKA0:\ :vb=\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERBA4\ERB0:\ :cl=\E\f:uc=^H\EMG1_\EMG0:so=\EMT2:se=\EMT1:\ :.ns:.as=\E^N:.ae=\E^O: Xz|4105|tek4105:\ :al=\E[1L:am:bs:cd=\E[J:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%2;%2H:co#80:\ :dc=\E[1P:dl=\E[1M:dn=\E[1B:ho=\E[H:im=\E[4h:li#30:mi:nd=\E[1C:\ :as=\E[1m:ae=\E[0m:ms:pt:se=\E[0m:so=\E[7m:up=\E[1A:kb=^h:ku=\E[1A:\ :kd=\E[1B:kl=\E[1D:kr=\E[1C:us=\E[4m:ue=\E[0m:is=\E%!1\E[?6l\E[0m:\ :mr=\E[<3m:md=\E[<4m:mh=\E[<6m:mb=\E[<7m:me=\E[<1m:ti=\E%!1\E[?6l:xt: # This entry is from Tek. Inc. (Brian Biehl) Xz|4115|tek4115|Tektronix 4115:\ :co#80:li#34:\ :al=\E[L:am:bc=\E[D:bs:bt=\E[Z:cd=\E[J:ce=\E[K:\ :cl=\E[;H\E[2J:cm=\E[%i%d;%dH:da:db:dc=\E[P:dl=\E[M:do=\E[B:\ :ei=\E[4l:eo:ho=\E[;H:im=\E[4h:if=/usr/lib/tabset/vt100:\ :is=\E%\0410\E%\014\ELV0\EKA1\ELBB2\ENU@\075\ELLB2\ELM0\ELV1\EKYA?\E%\0411\E[<1l\E[?7h\E[?8h\E[34;1H\E[34B\E[0m:\ :kb=^H:ke=\E>:ks=\E=:nd=\E[C:pt:se=\E[m:so=\E[7m:sr=\EM:\ :te=\E%\0410\ELBG8\E%\0411\E[34;1H\E[J: :ti=\E%\0410\ELBB2\E%\0411:\ :ue=\E[m:up=\E[A:us=\E[4m:\ :ve=\E%\0410\ELBG8\E%\0411\E[34;1H:\ :vs=\E%\0410\ELBB2\E%\0411: # The tek4125 emulates a vt100 incorrectly - the scrolling region # command is ignored. The following entry replaces the cs with the # needed al, dl, and im; removes some cursor pad commands that the tek4125 # chokes on; and adds a lot of initialization for the tek dialog area. # Note that this entry uses all 34 lines and sets the cursor color to green. # Steve Jacobson 8/85 XB|tek4125:\ :ks=\E=:li#34:\ :is=\E%\!0\EQD1\EUX03\EKA\ELBB2\ELCE0\ELI100\ELJ2\ELLB2\ELM0\ELS1\ELX00\ELV1\E%\!1\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:dl=\E[1M:\ :al=\E[1L:cs@:sc@:rc@:im=\E1:tc=vt100: # From carolyn@dali.berkeley.edu Thu Oct 31 12:54:27 1985 XA|4404|tek4404:\ :al=\E[1L:bs:cd=\E[J:ce=\E[K:cl=\E[;H\E[2J:cm=\E[%i%d;%dH:co#80:\ :cs=\E[%i%d;%dr:dc=\E[P:dl=\E[1M:do=^J:ei=\E[4l:ho=\E[H:im=\E[4h:\ :kd=\E[B:ke=\E[?1h:kl=\E[D:kr=\E[C:ks=\E[?1l:ku=\E[A:li#32::mb=\E[5m:\ :md=\E[1m:me=\E[m:nd=\E[C:pt:rc=\E8:sc=\E7:se=\E[27m:so=\E[7m:\ :ta=\E[2I:ti=\E%\!1\E[1;32r\E[?6l\E>:te=\E[1;1H\E[0J\E[?6h\E[?1l:\ :ue=\E[m:up=\E[A:us=\E[4m: # # -------------------------------- # # Z: Miscellaneous # # These compucolors appear similar, but they at least have different # sized screens. I don't know what's going on here. Z1|8001|ISC8001|compucolor|intecolor:\ :do=^J:al=\EU:am:le=^Z:bc=^Z:cl=3*^L:cm=^C%r%.%.:\ :co#80:cd=\EQ:dm=\EQ:ed=\EF:dc=\177:dl=\EV:ei=\EF:\ :im=\EQ:li#40:nd=1^Y:ta=8\t:up=^\:ho=1^H:pc=^@: Z2|compucolor2|compucolorII:\ :do=^J:pt:am:cm=%r^C%.%.:le=^Z:bc=^Z:li#32:co#64:\ :cl=^L:ho=^H:nd=^Y:up=^\: # From cithep!eric Wed Sep 16 08:06:44 1981 Z3|intext|Interactive Systems Corporation modified owl 1200:\ :do=^J:al=5.5*\020:am:le=^_:bc=^_:le=^H:bs:bt=^Y:cd=5.5*\026J:\ :ce=^K\160^R:cl=132\014:cm=\017%+ %+ :co#80:dc=5.5*\022:dl=5.5*\021:\ :ei=\026\074:im=\026\073:ip=5.5*:li#24:nd=\036:pt:up=\034:\ :se=^V# :sg#1:so=^V$,:ma=^K^P^R^L^L :\ :kl=^_:kd=^J:kr=^^:ku=\034:kb=^H:kh=^Z:\ :k1=^VA\r:k2=^VB\r:k3=^VC\r:k4=^VD\r:k5=^VE\r:\ :k6=^VF\r:k7=^VG\r:k8=^VH\r:k9=^VI\r:k0=^VJ\r: # # -------------------------------- # # a: ADDS # # Regent: lowest common denominator, works on all regents. a0|regent|Adds Regent Series:li#24:co#80:am:cl=^L:ll=^A:up=^Z:\ :bs:bc=^U:nd=^F:do=^J:ho=\EY : # Regent 100 has a bug where if computer sends escape when user is holding # down shift key it gets confused, so we avoid escape. a1|regent100|Adds Regent 100:k0=^B1^M:k1=^B2^M:k2=^B3^M:k3=^B4^M:\ :k4=^B5^M:k5=^B6^M:k6=^B7^M:k7=^B8^M:\ :l0=F1:l1=F2:l2=F3:l3=F4:l4=F5:l5=F6:l6=F7:l7=F8:\ :so=\E0P:ue=\E0@:us=\E0`:se=\E0@:\ :cm=^K%+ %B^P%.:ug#1:sg#1:tc=regent: a2|regent20|Adds Regent 20:cd=\Ek:ce=\EK:cm=\EY%+ %+ :tc=regent: a3|regent25|Adds Regent 25:kh=^A:kl=^U:kr=^F:ku=^Z:kd=^J:tc=regent20: a4|regent40|Adds Regent 40:k0=^B1^M:k1=^B2^M:k2=^B3^M:k3=^B4^M:\ :k4=^B5^M:k5=^B6^M:k6=^B7^M:k7=^B8^M:\ :l0=F1:l1=F2:l2=F3:l3=F4:l4=F5:l5=F6:l6=F7:l7=F8:\ :al=2*\EM:dl=2*\El:\ :so=\E0P:ue=\E0@:us=\E0`:se=\E0@:ug#1:sg#1:tc=regent25: a5|regent40+|Adds Regent 40+:is=\EB:tc=regent40: a6|regent60|regent200|Adds Regent 60:se=\ER\E0@\EV:so=\ER\E0P\EV:dc=\EE:ei=\EF:\ :im=\EF:is=\EV\EB:ko=dc,im,ei:tc=regent40+: a7|regent60na|regent 60 w/no arrow keys:\ kl@:kr@:ku@:kd@:tc=regent60: # # adds viewpoint 90 - from cornell # Note: emacs sends ei occasionally to insure the terminal is out of # insert mode. This unfortunately puts the viewpoint90 IN insert # mode. A hack to get around this is: ic=\EF \EF^U. (Also, # - ei=:im=: must be present.) # - xs indicates glich that attributes stick to location # - bs save to move in standout mode # - cl=\EG\Ek clears screen and visual attributes without affecting # the status line a9|vp90|viewpoint90|adds viewpoint 90:\ :bs:bw:cd=\Ek:ce=\EK:cl=\EG\Ek:cm=\EY%+ %+ :co#80:\ :dc=\EE:dl=\El:dm=:do=^J:ed=:ei=:im=:ic=\EF \EF^U:ho=\EY :\ :nd=^F:up=^Z:\ :kb=^H:kd=^J:kh=^A:kl=^U:kr=^F:ku=^Z:li#24:ll=^A:\ :so=\ER\E0Q\EV:se=\ER\E0@\EV:\ :us=\ER\E0`\EV:ue=\ER\E0@\EV:\ :xs:ms: # Note: if return acts weird on a980, check internal switch #2 # on the top chip on the CONTROL pc board. ac|a980|adds consul 980:\ :do=^J:al=13\E^N:am:le=^H:bs:cl=^L\200^K@:cm=^K%+@\E^E%2:co#80:\ :dl=13\E^O:k0=\E0:k1=\E1:k2=\E2:k3=\E3:k4=\E4:k5=\E5:k6=\E6:k7=\E7:\ :k8=\E8:k9=\E9:li#24:nd=\E^E01:so=^Y^^^N:se=^O:up=9: as|viewpt60|viewpoint60|addsviewpoint60|adds viewpoint60:\ :tc=regent40: # From Onyx:edward Thu Jul 9 09:27:33 1981 av|viewpoint|addsviewpoint|adds viewpoint:\ :do=^J:am:le=^H:bs:li#24:co#80:cm=\EY%+ %+ :cd=\Ek:ce=\EK:\ :up=^Z:cl=^L:ll=^A:kl=^U:kd=^J:ku=^Z:kh=^A:\ :so=^N:se=^O:us=^N:ue=^O:is=^O\E0`:vs=^O\E0P:ve=^O\E0`: # # -------------------------------- # # b: BEEHIVE # # Reports are that most of these Beehive entries (except superbee) have not been # tested and do not work right. se is a trouble spot. Be warned. b2|sb2|sb3|fixed superbee:\ :xb@:tc=superbee: # set tab is ^F, clear (one) tab is ^V, no way to clear all tabs. # good grief - does this entry make sg/ug when it doesn't have to? # look at those spaces in se/so. Seems strange to me... bh|bh3m|beehiveIIIm:\ :if=/usr/lib/tabset/beehive:do=^J:\ :al=160^S:am:le=^H:bs:cd=^R:ce=^P:cl=^E^R:\ :co#80:dl=350^Q:ho=^E:li#20:ll=^E^K:\ :nd=^L:pt:se= ^_:so=^] :up=^K: # This loses on lines > 80 chars long, use at your own risk bi|superbeeic|super bee with insert char:\ :ic=:im=\EQ:ei=\ER:tc=superbee: bm|microb|microbee|micro bee series:\ :do=^J:am:le=^H:bs:cd=\EJ:ce=\EK:cl=\EE:co#80:cm=\EF%+ %+ :\ :k1=\Ep:k2=\Eq:k3=\Er:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:k9=\Ex:\ :kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:\ :li#24:nd=\EC:pt:se=\Ed@ :so= \EdP:ue=\Ed@:up=\EA:us=\Ed`: # Superbee - f1=escape, f2=^C. # Note: there are at least 3 kinds of superbees in the world. The sb1 # holds onto escapes and botches ^C's. The sb2 is the best of the 3. # The sb3 puts garbage on the bottom of the screen when you scroll with # the switch in the back set to CRLF instead of AEP. This description # is tested on the sb2 but should work on all with either switch setting. # The f1/f2 business is for the sb1 and the :xb: can be taken out for # the other two if you want to try to hit that tiny escape key. # This description is tricky: being able to use cm depends on there being # 2048 bytes of memory and the hairy nl string. bs|sb1|superbee|superb|beehive super bee:\ :ct=\E3:st=\E1:is=\EH\EJ:do=^J:\ :sf=\n\200\200\200\n\200\200\200\EA\EK\200\200\200\ET\ET:\ :am:le=^H:bs:cd=3\EJ:ce=3\EK:cl=3\EH\EJ:co#80:cm=\EF%r%3%3:cr=1000\r:\ :dC#10:da:db:xb:dc=3\EP:dl=100\EM:so=\E_1:se=\E_3:\ :li#25:nl=\n\200\200\200\n\200\200\200\EA\EK\200\200\200\ET\ET:\ :nd=\EC:pt:up=\EA:ho=\EH:ve=\n:\ :k1=\Ep:k2=\Eq:k3=\Er:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:k8=\Ew:\ :kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA: # 8675, 8686, and bee from Cyrus Rahman b7|8675|harris 8675:\ :k1=^F:k2=^P:k3=^N:k4=^V:k5=^J:k6=^T:k7=^H:k8=\177:k9=\Ee:k10=\Ed:\ :k11=^W:k12=\ER:k13=\EE:k14=\EI:k15=\Ei:k16=\Eg:\ :is=\ES\E#\E*\Eh\Em\E?\E1\E9\E@\EX\EU:\ :tc=bee: b8|8686|harris 8686:\ :k1=^B^[p^C:k2=^B^[q^C:k3=^B^[r^C:k4=^B^[s^C:k5=\E3:\ :k6=\EI:k7=\ER:k8=\EJ:k9=\E(:k10=\Ej:k11=\EW:\ :k12=^B^[{^C:k13=^B^[|^C:k14=^B^[}^C:k15=^B^[~^C:k16=^B^[\177^C:\ :is=\ES\E#\E*\Eh\Em\E?\E1\E9\E@\EX\EU\E"*Z01\ \E"8F35021B7C83#\E"8F45021B7D83#\E"8F55021B7E83#\E"8F65021B7F83#\ \E"8F75021B7383#\E"8F851BD7#\E"8F95021B7083#\E"8FA5021B7183#\ \E"8FB5021B7283#:\ :tc=bee: be|bee|harris beehive:\ :co#80:li#24:am:bs:cd=\EJ:ce=\EK:cl=\EE:nd=\EC:\ :cm=\EF%+ %+ :up=\EA:do=\EB:ho=\EH:bt=\E>:\ :al=\EL:dc=\EP:dl=\EM:ei=\E@:im=\EQ:ic=:mi:\ :kl=\ED:kr=\EC:ku=\EA:kd=\EB:kh=\EH:kb=^H:\ :us=\Ed`:ue=\Ed@:so=\EdP:se=\Ed@:\ :ko=al,bt,ce,cl,dc,dl,ei,ho,ic,im: # # -------------------------------- # # c: CONCEPT (HUMAN DESIGNED SYSTEMS) # # From vax135!hpk Sat Jun 27 07:41:20 1981 # Extensive changes to c108 by arpavax:eric Feb 1982 # # There seem to be a number of different versions of the C108 PROMS # (with bug fixes in its Z-80 program). # The first one that we had would lock out the keyboard of you # sent lots of short lines (like /usr/dict/words) at 9600 baud. # Try that on your C108 and see if it sends a ^S when you type it. # If so, you have an old version of the PROMs. # The old one also messed up running vi with a 132-character line-length. # You should configure the C108 to send ^S/^Q before running this. # It is much faster (at 9600 baud) than the c100 because the delays # are not fixed. # new status line display entries for c108: # hs - has status capability # es - escape sequences are OK on status line # i2 - second init str - setup term for status display - set programmer mode, # select window 2, define window at last line of memory, # set bkgnd stat mesg there, select window 0. # ts - to status line - select window 2, home cursor, erase to end-of-window, # 1/2 bright on, goto(line#0, col#?) # fs - from status line - 1/2 bright off, select window 0 # ds - disable status display - set bkgnd status mesg with illegal window # # # the following two entries are for emacs -- they are just like the regular # entries except that they have buffer overflow control OFF c0|e108-8p:\ :i2=\EU\E z"\Ev^A\177 !p\E ;"\E z \Ev ^A\177p\Ep\n:\ :te=\Ev ^A\177p\Ep\r\n:tc=e108-4p: c1|e108-4p:\ :is=\EU\E f\Ef\E7\E5\E8\El\ENH\EK\E\200\Eo&\200\Eo\47\E\E!\E^G!\E^HA@ :\ :tc=c108-4p: c2|c108|c108-8p|concept108-8p|concept 108 w/8 pages:\ :i2=\EU\E z"\Ev^A\177 !p\E ;"\E z \Ev ^A\177p\Ep\n:\ :te=\Ev ^A\177p\Ep\r\n:tc=c108-4p: c3|c108-4p|concept108-4p|concept 108 w/4 pages:\ :es:hs:ts=\E z"\E?\E^C\Ea %+ :fs=\E z :ds=\E ;\177:\ :i2=\EU\E z"\Ev\177 !p\E ;"\E z \Ev \177p\Ep\n:do=^J:pt:\ :is=\EU\E F\Ef\E7\E5\E8\El\ENH\EK\E\200\Eo&\200\Eo\47\E\E!\E^G!\E^HA@ :\ :ti=\EU\Ev 8p\Ep\r:te=\Ev \177p\Ep\r\n:\ :al=\E^R:le=^H:bs:cd=\E^C:ce=\E^S:cl=\E?\E^E:cm=\Ea%+ %+ :co#80:\ :dc=\E^Q:dl=\E^B:ei=\E\200:eo:im=\E^P:li#24:mi:nd=\E=:\ :kb=^h:up=\E;:db:us=\EG:ue=\Eg:vs=\EW:ve=\Ew:am:xn:\ :vb=\Ek\200\200\200\200\200\200\200\200\200\200\200\200\200\200\EK:\ :ks=\EX:ke=\Ex:ku=\E;:kd=\E<:kl=\E>:kr=\E=:kh=\E?:\ :k1=\E5:k2=\E6:k3=\E7:k4=\E8:k5=\E9:k6=\E\72:\ :so=\ED:se=\Ed:mh=\EE:md=\ED:mr=\ED:me=\Ee\Ed\Eg\Ec: c4|c108-rv-8p|concept108-rv-8p|concept 108 w/8 pages, in reverse video:\ :vb=\EK\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ek:\ :is=\EU\E F\Ef\E7\E5\E8\El\ENH\Ek\E\200\Eo&\200\Eo\47\E\E!\E^G!\E^HA@ :\ :ts=\E z"\E?\E^C\EE\Ea %+ :fs=\Ee\E z :tc=c108-8p: c5|c108-rv-4p|concept108-rv-4p|concept 108 w/4 pages, in reverse video:\ :vb=\EK\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ek:\ :is=\EU\E F\Ef\E7\E5\E8\El\ENH\Ek\E\200\Eo&\200\Eo\47\E\E!\E^G!\E^HA@ :\ :ts=\E z"\E?\E^C\EE\Ea %+ :fs=\Ee\E z :tc=c108-4p: c6|c108-na|c108-na-8p|concept108-na-8p|concept 108 w/8 pages, no arrows:\ :ks@:ke@:k7=\E;:k8=\E<:k9=\E=:tc=c108-8p c7|c108-rv-na|c108-rv-na-8p|concept 108 w/8 pages, no arrows in rev video:\ :ts=\E z"\E?\E^C\EE\Ea %+ :fs=\Ee\E z :\ :ks@:ke@:k7=\E;:k8=\E<:k9=\E=:tc=c108-rv-8p # this needs new frotz in the cm capability for 2-char addrs when > 95.... c8|c108-w|c108-w-8p|concept108-w-8p|concept 108 w/8 pages in wide mode:\ :is=\EU\E F\Ef\E7\E5\E8\El\ENH\EK\E\200\Eo&\200\Eo\47\E\E"\E^G!\E^HA@ :\ :ti=\EU\Ev 8^AD\Ep\r:te=\Ev ^A0^AD\Ep\r\n:pt@:cm@:\ :co#132:tc=c108-8p cA|avt-w|avtw|HDS concept avt w/4 or 8 pages; 132 columns:\ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;119l\E[=103;107;118;207h\E)1\E[1Q\EW\E[7!y\E[0\0720\07232!r\E[w\E2\r\n:\ :ch=\E[%i%3G:cm=\E[%i%2;%3H:co#132:tc=avt: cB|avt-8p-s|concept avt w/8 pages & 80 cols running sysline:\ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;103;119l\E[=107;118;207h\E)1\E[1Q\EW\E[0!y\E[0\0720\07232!r\E[2!w\E[192w\E[2*w\E[!w\E[1;191w\E2\r\n:\ :hs:es:ts=\E[2!w\E[H\E[J\E[%i%dG:fs=\E[!w:\ :ds=\E[2!w\E[2J\E[!w\E[*w:te=\E[1;191w\E2\n:tc=avt: cC|avt-4p-s|concept avt w/4 pages & 80 cols running sysline:\ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;103;119l\E[=107;118;207h\E)1\E[1Q\EW\E[0!y\E[0\0720\07232!r\E[2!w\E[96w\E[2*w\E[!w\E[1;95w\E2\r\n:\ :hs:es:ts=\E[2!w\E[H\E[J\E[%i%dG:fs=\E[!w:\ :ds=\E[2!w\E[2J\E[!w\E[*w:te=\E[1;95w\E2\n:tc=avt: cD|avt-rv|HDS concept avt w/4 or 8 pages, 80 columns, reverse video:\ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;103;119l\E[=107;118;205;207h\E)1\E[1Q\EW\E[0!y\E[0\0720\07232!r\E[w\E2\r\n:\ :ve=\E[4l:vs=\E[4l:tc=avt cE|avt|HDS concept avt w/4 or 8 pages, 80 columns:\ :is=\E[1*q\E[2!t\E[7!t\E[=4;101;103;119;205l\E[=107;118;207h\E)1\E[1Q\EW\E[0!y\E[0\0720\07232!r\E[w\E2\r\n\E[*w:\ :ae=^O:al=\E[L:am:as=^N:bs:bt=\E[Z:cd=\E[J:ce=\E[K:\ :ch=\E[%i%2G:cl=\E[H\E[J:cm=\E[%i%2;%2H:co#80:cv=\E[%i%2d:\ :dc=\E[P:dl=\E[M:do=\E[B:ei=\E1:eo:ho=\E[H:im=\E1:kb=^H:kd=\E[B:\ :kh=\E[H:kl=\E[D:ko=do,ho,nd,up:kr=\E[C:\ :ks=\E[1;4!z\E[1;8!z\E[1;10!z\E[1;11!z\E[1;12!z\E[1;14!z\E[3;7!z\E[3;9!z:\ :ke=\E[;4!z\E[;8!z\E[;10!z\E[;11!z\E[;12!z\E[3;14!z\E[;7!z\E[;9!z:\ :ku=\E[A:li#24:mi:nd=\E[C:pt:se=\E[7!{:so=\E[7m:\ :te=\E[w\E2\n:ti=\E[1;24w\E2\n:ue=\E[4!{:\ :up=\E[A:us=\E[4m:ve=\E[=4;119l:vs=\E[4l\E[=119h:xn: # # Concepts have only window relative cursor addressing, not screen relative. # To get it to work right here, ti/te (which were invented for the concept) # lock you into a one page window for screen style programs. To get out of # the one page window, we use a clever trick: we set the window size to zero # ("\Ev " in te) which the terminal recognizes as an error and resets the # window to all of memory. # # Some tty drivers use cr3 for concept, others use nl3, hence dN/dC below. # This padding is only needed at 9600 baud. # 2 nulls padding on te isn't always enough. 6 works fine. Maybe less # than 6 but more than 2 will work. ca|c100|concept|c1004p|c100-4p|concept100|concept 100:\ :is=\EU\Ef\E7\200\200\E5\E8\200\200\El\ENH\EK\E\200\Eo&\200\Eo\47\E\E^G\041\E^HA@ :\ :ti=\EU\Ev 8p\Ep\r:te=\Ev \200\200\200\200\200\200\Ep\r\n:\ :al=3*\E^R:am:le=^H:bs:cd=16*\E^C:ce=16\E^U:cl=2*^L:cm=\Ea%+ %+ :co#80:\ :dc=16\E^Q:dl=3*\E^B:ei=\E\200:eo:im=\E^P:ip=16*:li#24:mi:nd=\E=:\ :pt:kb=^h:ta=8\t:up=\E;:db:us=\EG:ue=\Eg:xn:\ :vb=\Ek\200\200\200\200\200\200\200\200\200\200\200\200\200\200\EK:\ :.dN#9:dC#9:pb#9600:vt#8:us=\EG:ue=\Eg:so=\EE\ED:se=\Ed\Ee:\ :mh=\EE:mr=\ED:mb=\EC:mp=\EI:mk=\EH:me=\EN\200:do=^J:\ :ks=\EX:ke=\Ex:ku=\E;:kd=\E<:kl=\E>:kr=\E=:kh=\E?:k1=\E5:k2=\E6:k3=\E7: cb|c100-rv-pp|c100-rv-4p-pp|concept100-rv-pp|c100rv4ppp|w/ printer port:\ :is=\EU\Ef\E7\200\200\E5\E8\200\200\El\ENH\Ek\E\200\Eo&\200\Eo\041\200\EQ"\EY(^W\Eo\47\E\E^G\041\E^HA@ :\ :tc=c100-rv: cc|c100-rv-na|c100-rv-4p-na|concept100-rv-na|c100rv4pna|c100 with no arrows:\ :ks@:ke@:tc=c100-rv: cd|c100-rv|c100-rv-4p|concept100-rv|c100rv4p|c100rv|c100 rev video:\ :is=\EU\Ef\E7\200\200\E5\E8\200\200\El\ENH\Ek\E\200\Eo&\200\Eo\47\E\E^G\041\E^HA@ :\ :vb=\EK\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ek:\ :so=\EE:se=\Ee:tc=c100: # This is useful at 1200 baud. ce|c100-s|concept-s|concept100-s|slow concept 100:\ :vb=\Ek\200\EK:pt:dC@:dN@:tc=c100: cf|c100-rv-s|concept-rv-s|concept100-rv-s|c100rvs|slow reverse concept 100:\ :vb=\EK\200\Ek:pt:dC@:dN@:tc=c100-rv: # # -------------------------------- # # d: DEC (DIGITAL EQUIPMENT CORPORATION) # # Note that xn glitch in vt100 is not quite the same as concept, since # the cursor is left in a different position while in the weird state # (concept at beginning of next line, vt100 at end of this line) so # all versions of vi before 3.7 don't handle xn right on vt100. # I assume you have smooth scroll off or are at a slow enough baud # rate that it doesn't matter (1200? or less). Also this assumes # that you set auto-nl to "on", if you set it off use vt100-nam below. # # Since there are two things here called vt100, the installer can make # a local decision to make either one standard "vt100" by including # it in the list of terminals in reorder, since the first vt100 in # /etc/termcap is the one that it will find. The choice is between # nam (no automatic margins) and am (automatic margins), as determined # by the wrapline switch (group 3 #2). I presonally recommend turning # on the bit and using vt100-am, since having stuff hammer on the right # margin is sort of hard to read. However, the xn glitch does not occur # if you turn the bit off. # # I am unsure about the padding requirements listed here. I have heard # a claim that the vt100 needs no padding. It's possible that it needs # padding only if the xon/xoff switch is off. For UNIX, this switch # should probably be on. # # The vt100 uses rs and rf rather than is/ct/st because the tab settings # are in non-volatile memory and don't need to be reset upon login. # You can type "reset" to get them set. dp|vt100-np|vt100 with no padding (for psl games):\ :cl=\E[H\E[2J:sr=\EM:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\ :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:tc=vt100: d0|vt100|vt100-am|vt100am|dec vt100:\ :do=^J:co#80:li#24:cl=50\E[;H\E[2J:sf=2*\ED:\ :le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\ :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\ :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[1;24r\E[24;1H:\ :rf=/usr/lib/tabset/vt100:\ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\ :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=2*\EM:vt#3:xn:\ :sc=\E7:rc=\E8:cs=\E[%i%d;%dr: d1|vt100-nam|vt100nam|vt100 w/no am:\ :am@:xn@:\ :is=\E>\E[?3l\E[?4l\E[?5l\E[?7l\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\ :tc=vt100-am: d2|gt42|dec gt42:\ :do=^J:le=^H:bs:co#72:ns:li#40:os: d3|vt132|vt132:\ :al=99\E[L:dl=99\E[M:ip=7:dc=7\E[P:ei=\E[4l:im=\E[4h:xn:dN#30:tc=vt100: d4|gt40|dec gt40:\ :do=^J:le=^H:bs:co#72:ns:li#30:os: d5|vt50|dec vt50:\ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:co#80:li#12:nd=\EC:pt:up=\EA: d6|vt125|vt125-am|DEC vt125:\ :xn:do=^J:co#80:li#24:cl=50\E[H\E[2J:dC=10:dN=10:\ :le=^H:am:bs:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:ce=3\E[K:cd=50\E[J:\ :so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:md=2\E[1m:mr=2\E[7m:mb=2\E[5m:\ :me=2\E[m:is=\E[1;24r\E[24;1H\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\ :ks=\E[?1h\E=:ke=\E[?1l\E>:if=/usr/lib/tabset/vt100:ku=\EOA:kd=\EOB:\ :kr=\EOC:kl=\EOD:kb=^H:ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:\ :pt:sr=5\EM:vt#3:sc=\E7:rc=\E8:cs=\E[%i%d;%dr: d9|vt125-nam|DEC vt125 no automatic margin:\ :am@:tc=vt125-am: # DEC gigi color graphic terminal, same as vt52 d7|gigi|dec gigi terminal:\ :co#80:is=200\E>\E[?4l\E[?5l\E[?7h\E[?8h:\ :li#24:cl=100\E[;H\E[2J:bs:cm=50\E[%i%2;%2H:nd=200\E[C:up=100\E[A:\ :ce=120\E[K:cd=100\E[J:so=20\E[7m:se=20\E[m:us=20\E[4m:ue=20\E[m:\ :ks=200\E[?1h\E=:ke=200\E[?1l\E>:\ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:\ :kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=200\EM:\ :dC=50:dF=200:dN=50:dT=50: dI|dw1|decwriter I:\ :do=^J:le=^H:bs:co#72:hc:os: # From tut@Topaz.CC Thu May 12 14:49:02 1983 dJ|dw3|la120|decwriter III:\ :bs:kb=^H:co#132:hc:os:pt:\ :is=\E(B\E[20l\E[w\E[1;132s\E[2g\E[9;17;25;33;41;49;57;65;73;81;89;97;105;113;121;129u\E[z\E[66t\E[1;66r\E[4g\E>\r: # From tut@topaz.CC Thu Sep 24 22:10:46 1981 df|dw4|decwriter IV:\ :do=^J:le=^H:bs:co#132:hc:os:am:\ :pt:is=\Ec:k0=\EOP:k1=\EOQ:k2=\EOR:k3=\EOS:kb=^H: dh|vt50h|dec vt50h:\ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :\ :co#80:li#12:nd=\EC:pt:sr=\EI:up=\EA: di|vt100-s|vt100 with status line at top:\ :li#23:i2=\E[2;24r\E[24;1H:cm@:ho=\E[H^J:cl=50\E[;H^J\E[0J:\ :hs:es:ts=\E7\E[1;%dH\E[1K:fs=\E8:tc=vt100-am: dj|vt100-s-bot|vt100 with status line at bottom:\ :li#23:i2=\E[1;23r\E[23;1H:\ :hs:es:ts=\E7\E[24;%dH\E[1K:fs=\E8:tc=vt100-am: ds|vt100-nav|dec vt100 132 cols 14 lines (w/o advanced video option):\ :li#14:tc=vt100-w: dt|vt100-w|dec vt100 132 cols (w/advanced video):\ :co#132:li#24:rs=\E>\E[?3h\E[?4l\E[?5l\E[?8h:tc=vt100-am: dv|vt100-w-nam|dec vt100 132 cols (w/advanced video), no am:\ :co#132:li#24:rs=\E>\E[?3h\E[?4l\E[?5l\E[?8h:vt@:tc=vt100-nam: d8|vt102|vt100 w/adv. video:\ :al=\E[1L:dl=\E[1M:im=\E[4h:ei=\E[4l:mi:dc=\E[1P:ku=\EOA:kd=\EOB:\ :kr=\EOC:kl=\EOD:k0=\EOp:k1=\EOq:k2=\EOr:k3=\EOs:k4=\EOt:k5=\EOu:\ :k6=\EOv:k7=\EOw:k8=\EOx:k9=\EOy:as=\E(0:ae=\E(B:am@:xn@:tc=vt100am: # (from lai@decwrl) should be a vt102, but have heard enough # unsubstantiated complaints to make it an alternate (obsolete) version dy|vt102-obs|dec vt102:\ :do=^J:co#80:li#24:cl=50\E[;H\E[2J:\ :le=^H:bs:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\ :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\ :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:is=\E[1;24r\E[24;1H:\ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:ks=\E[?1h\E=:ke=\E[?1l\E>:\ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\ :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=5\EM:vt#3:\ :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:vs=\E[?7l:ve=\E[?7h: dw|vt52|dec vt52:\ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#80:li#24:\ :nd=\EC:pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:kb=^H: # vt61 created by Roger Sacilotto Massachusetts Computer Associates, Inc # Similar to vt52 but add al and dl # dq|vt61|dec vt61:\ :al=\EPf:dl=\EPd:tc=vt52: dx|dw2|decwriter II:\ :do=^J:kb=^h:le=^H:bs:co#132:hc:os: # DEC PRO-350 console (VT220-style) dP|pro350|decpro|dec pro console:\ :bs:cd=\EJ:ce=\EK:cl=\EH\EJ:\ :cm=\EY%+ %+ :co#80:ho=\EH:\ :kl=\ED:kr=\EC:ku=\EA:kd=\EB:kh=\EH:\ :k0=\EE:k1=\EF:k2=\EG:k3=\EH:k4=\EI:k5=\EJ:k6=\Ei:k7=\Ej:\ :li#24:nd=\EC:pt:sr=\EI:up=\EA:do=\EB:\ :se=\E^N:so=\E^H:us=\E^D:ue=\E^C:\ :ae=\EG:as=\EF: # # From: Bracy H. Elton dl|vt200|vt220|vt200-js|vt220-js|dec vt200 series with jump scroll:\ :im=\E[4h:ei=\E[4l:mi:dc=\E[P:dm=:ed=:al=\E[L:dl=\E[M:\ :cs=\E[%i%d;%dr:sf=\ED:sr=\EM:sb=\EM:\ :ce=\E[K:cl=\E[H\E[J:cd=\E[J:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :so=\E[7m:se=\E[27m:us=\E[4m:ue=\E[24m:\ :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:\ :is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\ :tc=vt100: dm|vt200-ss|vt220-ss|dec vt200 series with smooth scroll:\ :is=\E>\E[?3l\E[?4h\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\ :rs=\E>\E[?3l\E[?4h\E[?5l\E[?7h\E[?8h:\ :tc=vt200: dn|vt200-w|vt220-w|vt200-wj|vt220-wj|dec vt200 series; 132 col.; jump scroll:\ :is=\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\ :rs=\E>\E[?3h\E[?4l\E[?5l\E[?7h\E[?8h:\ :co#132:tc=vt200: do|vt200-ws|vt220-ws|dec vt200 series; 132 col.; smooth scroll:\ :is=\E>\E[?3h\E[?4h\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\ :rs=\E>\E[?3h\E[?4h\E[?5l\E[?7h\E[?8h:\ :co#132:tc=vt200: dl|vt300|vt320|vt340|dec vt300 series with jump scroll:\ :im=\E[4h:ei=\E[4l:mi:dc=\E[P:dm=:ed=:al=\E[L:\ :cs=\E[%i%d;%dr:sf=\ED:sr=\EM:sb=\EM:\ :ce=\E[K:cl=\E[H\E[J:cd=\E[J:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :so=\E[7m:se=\E[27m:us=\E[4m:ue=\E[24m:\ :md=\E[1m:mr=\E[7m:mb=\E[5m:me=\E[m:\ :is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;24r\E[24;1H:\ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h:\ :tc=vt100: # @(#)termcap X10/6.6 11/7/86, minus alternate screen, plus :cs vs|xterm|vs100|xterm terminal emulator (X window system):\ :do=^J:le=^H:ho=\E[H:\ :co#80:li#65:cl=\E[H\E[2J:bs:am:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\ :md=\E[1m:mr=\E[7m:me=\E[m:\ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\ :k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sf=\n:sr=\EM:\ :al=\E[L:dl=\E[M:im=\E[4h:ei=\E[4l:mi:dc=\E[P:\ :MT:ks=\E[?1h\E=:ke=\E[?1l\E>:xn:\ :AL=\E[%dL:DL=\E[%dM:IC=\E[%d@:DC=\E[%dP:\ :hs:ts=\E[?E\E[?%i%dT:fs=\E[?F:es:ds=\E[?E:\ :is=\E\E[m\E[?7h\E[?1;4l:cs=\E[%i%d;%dr:\ :rs=\E[r\E<\E[m\E[H\E[2J\E[?7h\E[?1;3;4;6l: v2|xterms|vs100s|xterm terminal emulator (small)(X window system):\ :co#80:li#24:tc=xterm: # vs100 emulator using tsim (from lai@decwrl) vt|vs100t|tsim|vs100-tsim:\ :bs:cm=\EM%+ %+ :ho=\EH:do=^J:up=^K:cl=\EE:ce=\EL:cs=\ES%+ %+ :\ :so=\Eh:se=\Er:us=\Eu:ue=\Ev:al=\EI:Al=\E+%+ :dl=\ED:Dl=\E-%+ :\ :ic=\Ei:dc=\Ed:is=\ER:rs=\ER:am:cd=\EQ:pt:nd=\En:li#24:co#80: # # -------------------------------- # # h: HEWLETT PACKARD # # Note: no "ho" on HP's since that homes to top of memory, not screen. # Due to severe 2621 braindamage, the only way to get the arrow keys to # transmit anything at all is to turn on the function key labels # (f1-f8) with ks, and even then the poor user has to hold down shift! # The default 2621 turns off the labels except when it has to to enable # the function keys. If your installation prefers labels on all the time, # or off all the time (at the "expense" of the function keys) move the # 2621-nl or 2621-wl labels to the front using reorder. # Note: there are newer ROM's for 2621's that allow you to set strap A # so the regular arrow keys xmit \EA, etc, as with the 2645. However, # even with this strap set, the terminal stops xmitting if you reset it, # until you unset and reset the strap! Since there is no way to set/unset # the strap with an escape sequence, we don't use it in the default. # If you like, you can use 2621-ba (braindamaged arrow keys). h1|2621-ba|2621 w/new rom, strap A set:\ :ks@:ke@:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\Eh:tc=hp2621: # 2621 with function labels. Most of the time they are off, # but inside vi, the function key labels appear. You have to # hold down shift to get them to xmit. h2|2621|hp2621|hp2621a|hp2621p|2621a|2621p|2621-pb|hp2621-fl|hp 2621:\ :is=\E&j@\r:bt=\Ei:cm=\E&a%r%dc%dY:dc=2\EP:ip=2:pb#19200:\ :so=\E&dD:se=\E&d@:us=\E&dD:ue=\E&d@:me=\E&d@:\ :kh=\Ep\r:ku=\Et\r:kl=\Eu\r:kr=\Ev\r:kd=\Ew\r:\ :kn#8:k1=\Ep\r:k2=\Eq\r:k3=\Er\r:k4=\Es\r:k5=\Et\r:k6=\Eu\r:k7=\Ev\r:\ :k8=\Ew\r:ks=\E&jB:ke=\E&j@:ta=2^I:tc=hp: # 2621k45: untested # 2622: unsure if this is quite it, have only heard about the terminal. h3|2621k45|hp2621k45|k45|2622|hp2622|hp 2621 with 45 keyboard:\ :kb=^H:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\Eh:ks=\E&s1A:ke=\E&s0A:tc=2621: h4|hp2645|2645|hp45:\ :mh=\E&dH:mr=\E&dB:us=\E&dD:mb=\E&dA:me=\E&d@:\ :ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\Eh:ks=\E&s1A:ke=\E&s0A:tc=hp: h5|hp|hewlett-packard:\ :ct=\E3:st=\E1:do=^J:al=\EL:am:le=^H:bs:\ :cd=\EJ:ce=\EK:ch=\E&a%dC:cl=\EH\EJ:cm=6\E&a%r%dc%dY:\ :co#80:cv=\E&a%dY:da:db:dc=\EP:dl=\EM:ei=\ER:im=\EQ:\ :kb=^H:li#24:mi:nd=\EC:pt:se=\E&d@:so=\E&dJ:\ :us=\E&dD:ue=\E&d@:up=\EA:xs:vt#6:pb#9600: # This entry does not use any of the fancy windowing stuff of the 2621. # Indeed, termcap does not yet handle such stuff. We are looking at it. h6|hp2626|hp2626a|hp2626p|2626|2626a|2626p|hp 2626:\ :dc=2\EP:ip=2:se=\E&d@:so=\E&dB:cd=500\EJ:\ :mr=\E&dB:us=\E&dD:mb=\E&dA:mk=\E&dS:me=\E&d@:ue=\E&d@:\ :kh=\Eh:ku=\EA:kl=\ED:kr=\EC:kd=\EB:ks=\E&s1A:ke=\E&s0A:\ :sf=\ES:ta=2^I:xs:tc=2621: # cD is a pain - but it only screws up at 9600 baud. # You should use this terminal at 4800 baud or less. h8|hp2648|hp2648a|2648a|2648|HP 2648a graphics terminal:\ :cl=50\EH\EJ:cm=20\E&a%r%dc%dY:dc=7\EP:ip=5:tc=2645: # This terminal should be used at 4800 baud or less. h9|hp2645-np|2645 w/no padding:cm=\E&a%r%dc%dY:tc=hp2645: # 2640a doesn't have the Y cursor addressing feature, and C is memory relative # instead of screen relative, as we need. ha|2640|hp2640a|2640a|hp 2640a:\ :cm@:ks@:ke@:tc=2645: hb|2640b|hp2640b|2644a|hp2644a|hp 264x series:\ :ks@:ke@:tc=2645: # 2621 using all 48 lines of memory, only 24 visible at any time. Untested. hl|2621-48|48 line 2621:\ :li#48:ho=\EH:cm=\E&a%r%dc%dR:tc=2621: # Hp 110 computer is the same as 2621 except has 16 lines hm|hp110|110|hp 110 computer:\ :li#16:tc=2621: # 2621 with no labels ever. Also prevents vi delays on escape. hn|2621-nl|hp2621nl|2621nl|hp2621-nl|hp 2621 with no labels:\ :ks@:ke@:kh@:ku@:kl@:kr@:kd@:tc=hp2621-fl: # Needed for UCB ARPAVAX console, since lsi-11 expands tabs (wrong). ht|hp2621-nt|2621nt|2621-nt|hp2621nt|hp 2621 w/no tabs:\ :pt@:tc=hp2621: # 2621 with labels on all the time - normal outside vi, function inside vi. hw|hp2621wl|2621wl|2621-wl|hp2621-wl|hp 2621 w/labels:\ :is=\E&jA\r:ke=\E&jA:tc=hp2621-fl: # 2392 (from haddix@arpa?) hz|2392|hp2392|hp2392a:\ :bt=\Ei:ip=2:is=\E&j@\E3\r:if=/usr/lib/tabset/stdcrt:\ :ml=\El:MT:mu=\Em:km:\ :mh=\E&dH:mr=\E&dB:us=\E&dD:mb=\E&dA:me=\E&d@:\ :ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\Eh:ks=\E&s1A:ke=\E&s0A:tc=hp: #HP 236 console #from ddavis@ic.berkeley.edu h7|236|hp236|HP236 internal terminal emulator:\ :am:bs:li#24:co#80:cl=\EF:cm=\EE%+ %+ :\ :dc=\EJ:dl=\EH:ic=\EI:al=\EG:up=^K:im=:ei=:\ :so=\EBI:se=\ECI:vs=\EDB:ve=\EDE: # hp150 from ddavis@ic.berkeley.edu h0|150|hp150|hp150a|150a:\ :is=\E&s1A\E&f0a1k2L\Ep\r\E&k0K\E&f0a2k2L\Eq\r\E&f0a3k2L\Er\r\E&f0a4k2L\Es\r\E&f0a5k2L\Et\r\E&f0a6k2L\Eu\r\E&f0a7k2L\Ev\r\E&f0a8k2L\Ew\r\E&k0D\E&s0A:\ :bt=\Ei:li#24:cm=\E&a%r%dc%dY:dc=2\EP:ip=2:pb#19200:so=\E&dJ:\ :se=\E&d@:us=\E&dD:ue=\E&d@:me=\E&d@:kh=\Eh:ku=\EA:kl=\ED:kr=\EC:\ :kd=\EB:kn#8:k1=\Ep:k2=\Eq:k3=\Er:k4=\Es:k5=\Et:k6=\Eu:k7=\Ev:\ :k8=\Ew:ta=2^I:ct=\E3:st=\E1:do=^J:al=\EL:am:le=^H:\ :bs:cd=\EJ:ce=\EK:ch=\E&a%dC:cl=\Eh\EJ:co#80:cv=\E&a%dY:da:db:dl=\EM:\ :ei=\ER:im=\EQ:kb=^H:mi:nd=\EC:pt:up=\EA:xs:vt#6:sf=\ES:sr=\ET:\ :vs=\E&s1A:ve=\E&s0A:ks=\E&jB\E&j@:ke=\E&j@: # # -------------------------------- # # i: INFOTON (GENERAL TERMINAL) # # Infoton is now called General Terminal Corp. or some such thing. # gt100 sounds like something DEC would come out with. Lets hope they don't. i1|i100|gt100|gt100a|General Terminal 100A (formerly Infoton 100):\ :do=^J:cl=^L:cd=\EJ:ce=\EK:li#24:co#80:\ :al=\EL:dl=\EM:up=\EA:nd=\EC:ho=\EH:cm=\Ef%r%+ %+ :vb=\Eb\Ea:\ :am:le=^H:bs:so=\Eb:se=\Ea: i4|i400|400|infoton 400:\ :do=^J:al=\E[L:am:le=^H:bs:ce=\E[N:cl=\E[2J:cm=%i\E[%3;%3H:co#80:\ :dl=\E[M:li#25:nd=\E[C:up=\E[A:im=\E[4h\E[2Q:ei=\E[4l\E[0Q:\ :dc=\E[4h\E[2Q\E[P\E[4l\E[0Q: ia|addrinfo:\ :do=^J:li#24:co#80:cl=^L:ho=^H:nd=^Y:cd=^K:\ :up=^\:am:le=^Z:bc=^Z:cm=\037%+\377%+\377:ll=^H^\: ik|infotonKAS:\ :do=^J:am:le=^Z:bc=^Z:cd=^K:cl=^L:co#80:li#24:nd=^Y:up=^\:ll=^H^\: # # -------------------------------- # # k: HEATHKIT (ZENITH) # kA|h19-a|h19a|heath-ansi|heathkit-a|heathkit h19 ansi mode:\ :\ :al=1*\E[1L:am:le=^H:bs:cd=\E[J:ce=\E[K:cl=\E[2J:cm=\E[%i%2;%2H:co#80:\ :dc=\E[1P:dl=1*\E[1M:do=\E[1B:ei=\E[4l:ho=\E[H:im=\E[4h:li#24:mi:\ :nd=\E[1C:as=\E[10m:ae=\E[11m:ms:pt:se=\E[0m:so=\E[7m:up=\E[1A:\ :vs=\E[>4h:ve=\E[>4l:kb=^h:ku=\E[1A:kd=\E[1B:kl=\E[1D:kr=\E[1C:\ :kh=\E[H:kn#8:k1=\EOS:k2=\EOT:k3=\EOU:k4=\EOV:k5=\EOW:l6=blue:\ :l7=red:l8=white:k6=\EOP:k7=\EOQ:k8=\EOR:\ :sr=\EM:is=\E<\E[>1;2;3;4;5;6;7;8;9l\E[0m\E[11m\E[?7h: kB|h19-bs|h19bs|heathkit w/keypad shifted:\ :ks=\Et:ke=\Eu:tc=h19-b: #written by David Shewmake, UCSF Medical Information Science #ucbvax!ucsfmis!shewmake kC|h29|heath-29|z29|zenith-29:\ :am:bc=\ED:bt=\E-:do=^J:\ :al=\EL:le=^H:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:dc=\EN:\ :dl=1*\EM:do=\EB:ei=\EO:ho=\EH:im=\E@:li#24:mi:nd=\EC:as=\EF:ae=\EG:\ :ms:pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4:\ :kb=^H:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH:kn#1:k0=\E~:l0=HOME:\ :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:k6=\EP:k7=\EQ:k8=\ER:k9=\E0I:\ :es:hs:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1:us=\Es8:ue=\Es0: #the z29-e entry sucks...but it works with emacs kD|z29-e|zenith 29 hacked for emacs:\ :ip=1.5:ks=\Et:ke=\Eu:vs@:ve@:al=1*\EL:am:le=^H:\ :bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:dc=\EN:dl=1*\EM:\ :do=\EB:ho=\EH:li#24:nd=\EC:as=\EF:ae=\EG:ms:\ :pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4:kb=^h:\ :ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH:kn#8:k1=\ES:k2=\ET:k3=\EU:\ :k4=\EV:k5=\EW:l6=blue:l7=red:l8=white:k6=\EP:k7=\EQ:k8=\ER:es:hs:\ :ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1: # z29 in ansi mode. Assumes that the cursor is in the correct state, and that # the world is stable. `rs' causes the terminal to be reset to the state # indicated by the name. kc -> key click, nkc -> no key click, uc -> underscore # cursor, bc -> block cursor. # from Mike Meyers kF|z29a|z29a-kc-bc|h29a-kc-bc|heath/zenith 29 in ansi mode:\ :do=^J:co#80:li#24:cl=\E[2J:pt:ho=\E[H:\ :le=^H:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:mb=\E[5m:mr=\E7m:\ :ce=\E[K:cd=\E[J:so=\E[7;2m:se=\E[m:us=\E[4m:ue=\E[m:mh=\E[2m:\ :md=\E[2m:mr=\E[7m:mb=\E[5m:me=\E[m:\ :rs=\E<\E[1;24r\E[24;1H\E[?7h\E[>4h\E[>1;2;3;5;6;7;8;9l\E[m\E[11m:\ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\ :k1=\EOS:k2=\EOT:k3=\EOU:k4=\EOV:k5=\EOW:k6=\EOP:k7=\EOQ:k8=\EOR:\ :k9=\EOX:k0=\E[~:l0=help:kn#2:ko=ho,cd:if=/usr/lib/tabset/zenith29:\ :es:hs:ts=\E[s\E[>5;1h\E[25;%i%dH\E[1K:fs=\E[u\E[>5l:ds=\E[>1l:\ :cs=\E[%i%d;%dr:sr=\EM:sf=\ED:DO=\E[%dB:UP=\E[%dA:LE=\E[%dD:\ :RI=\E[%dC:AL=\E[%dL:DL=\E[%dM:sc=\E[s:rc=\E[r:dc=\E[1P:DC=\E[%dP:\ :kC=\E[J:ct=\E[3g:st=\EH:ti=\E[?7l:te=\E[?7h:ps=\E#7: kG|z29a-kc-uc|h29a-kc-uc|heath/zenith 29 in ansi mode:\ :rs=\E<\E[1;24r\E[24;1H\E[?7h\E[>1;2;3;4;5;6;7;8;9l\E[m\E[11m:\ :tc=z29a: kH|z29a-nkc-bc|h29a-nkc-bc|heath/zenith 29 in ansi mode:\ :rs=\E<\E[1;24r\E[24;1H\E[?7h\E[>2;4h\E[>1;3;5;6;7;8;9l\E[m\E[11m:\ :tc=z29a: kI|z29a-nkc-uc|h29a-nkc-uc|heath/zenith 29 in ansi mode:\ :rs=\E<\E[1;24r\E[24;1H\E[?7h\E[>2h\E[>1;3;4;5;6;7;8;9l\E[m\E[11m:\ :tc=z29a: #z100 entry from Brad Brahms at TRW (Brahms@USC-ECLC) # usenet: {decvax,ucbvax}!trwrb!trwspp!brahms kc|z100|h100|z110|z-100|h-100|heath/zenith z-100 pc with color monitor:\ :vs=\Ex4\Em71:ve=\Ey4\Em70:tc=z100bw: kY|z100bw|h100bw|z110bw|z-100bw|h-100bw|heath/zenith z-100 pc:\ :al=5*\EL:bs:cd=\EJ:ce=\EK:cl=5*\EE:cm=1*\EY%+ %+ :co#80:dc=1*\EN:\ :dl=5*\EM:do=\EB:ei=\EO:ho=\EH:im=\E@:li#24:mi:nd=\EC:as=\EF:ae=\EG:\ :ms:pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4:\ :kb=^h:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH:kn#10:\ :k0=\EJ:k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:\k6=\EP:k7=\EQ:\ :k8=\ER:k9=\EOI: kp|p19:\ :al=2*\EL:dl=2*\EM:tc=h19-b: kU|h19-us|h19us|heathkit w/keypad shifted/underscore cursor:\ :ks=\Et:ke=\Eu:tc=h19-u: kb|h19|heath|h19-b|h19b|heathkit|heath-19|z19|zenith|heathkit h19:\ :al=1*\EL:am:le=^H:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:dc=\EN:\ :dl=1*\EM:do=\EB:ei=\EO:ho=\EH:im=\E@:li#24:mi:nd=\EC:as=\EF:ae=\EG:\ :ms:pt:sr=\EI:se=\Eq:so=\Ep:up=\EA:vs=\Ex4:ve=\Ey4:\ :kb=^h:ku=\EA:kd=\EB:kl=\ED:kr=\EC:kh=\EH:kn#8:ke=\E>:ks=\E=:\ :k1=\ES:k2=\ET:k3=\EU:k4=\EV:k5=\EW:\ :l6=blue:l7=red:l8=white:k6=\EP:k7=\EQ:k8=\ER:\ :es:hs:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1: ke|h19-e|h19e|h19 for emacs:ip=1.5:tc=h19-us: ku|h19-u|h19u|heathkit with underscore cursor:\ :vs@:ve@:tc=h19-b: kg|h19-g|h19g|heathkit w/block cursor:\ :ve=\Ex4:tc=h19-b: # from ucscc!B.fiatlux@ucbvax.berkeley.edu zx|ztx|ztx11|zt-1|htx11|ztx-1-a|ztx-10/11:\ :al=\EL:am:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:\ :dl=\EM:do=^J:ho=\EH:is=\Ej\EH\Eq\Ek\Ev\Ey1\Ey5\EG\Ey8\Ey9\Ey>:\ :k0=\ES:k1=\EB:k2=\EU:k3=\EV:k4=\EW:k5=\EP:k6=\EQ:k7=\ER:kb=^H:kd=\EB:\ :kl=\ED:kr=\EC:ku=\EA:le=^H:li#24:nd=\EC:pt:se=\Eq:so=\Es5:\ :sr=\EI:sr=\EI:ue=\Eq:up=\EA:us=\Es2:\ :es:hs:ts=\Ej\Ex5\Ex1\EY8%+ \Eo:fs=\Ek\Ey5:ds=\Ey1: # # -------------------------------- # # l: LEAR SIEGLER (ADM) # # If the adm31 gives you trouble with standout mode, check the DIP switch # in position 6, bank @c11, 25% from back end of pc. Should be OFF. # If there is no such switch, you have an old adm31 and must use oadm31 l1|adm31|31|lsi adm31:\ :is=\Eu\E0:do=^J:al=\EE:am:le=^H:bs:ce=\ET:cm=\E=%+ %+ :\ :cl=\E*:cd=\EY:co#80:dc=\EW:dl=\ER:ei=\Er:ho=^^:im=\Eq:\ :k0=^A0\r:k1=^A1\r:k2=^A2\r:k3=^A3\r:k4=^A4\r:\ :k5=^A5\r:k6=^A6\r:k7=^A7\r:k8=^A8\r:k9=^A9\r:kd=^J:kl=^H:kr=^L:ku=^K:\ :li#24:ma=j^Jk^P^K^Pl ^R^L^L :mi:nd=^L:\ :se=\EG0:so=\EG1:up=^K:us=\EG1:ue=\EG0: l2|adm2|lsi adm2:\ :do=^J:al=\EE:am:le=^H:bs:cd=\EY:ce=\ET:cl=\E;:\ :cm=\E=%+ %+ :co#80:dc=\EW:dl=\ER:\ :ei=:ho=^^:ic=\EQ:im=:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:li#24:nd=^L:up=^K: l3|adm3|3|lsi adm3:\ :do=^J:am:le=^H:bs:cl=^Z:li#24:ma=^K^P:co#80: l4|adm42|42|lsi adm42:\ :vs=\EC\E3 \E3(:do=^J:al=270\EE:am:le=^H:bs:cd=\EY:ce=\ET:cl=\E;:\ :cm=\E=%+ %+ :co#80:dc=\EW:dl=\ER:ei=\Er:im=\Eq:ip=6*:li#24:\ :bt=\EI:nd=^L:se=\EG0:so=\EG4:up=^k:ma=^K^P:pc=\177: l5|adm5|5|lsi adm5:\ :do=^J:cd=\EY:ce=\ET:do=^J:kb=^H:kh=^^:\ :ma=^Hh^Jj^Kk^Ll^^H:se=\EG:sg#1:so=\EG:tc=adm3aplus: l7|adm20|lear siegler adm20:\ :am:li#24:co#80:bs:cl=^Z:cm=\E=%i%r%+^_%+^_:nd=^L:up=^K:ho=^^:ce=\ET:\ :cd=\EY:al=\EE:dl=\ER:im=:ei=:ic=\EQ:dm=:ed=:dc=\EW:so=\E):se=\E(:\ :bt=\EI:pt:kn#7:k1=^A:k2=^B:k3=^W:k4=^D:k5=^E:k6:^X:k7=^Z: # From Andrew Scott Beals l8|adm12|12|lsi adm12:\ :is=\Eq:do=^J:al=\EE:am:le=^H:bs:ce=\ET:cm=\E=%+ %+ :cl=^Z:cd=\EY:\ :co#80:dc=\EW:dl=\ER:ei=\Er:ho=^^:im=\Eq:\ :k0=^A0\r:k1=^A1\r:k2=^A2\r:k3=^A3\r:k4=^A4\r:\ :k5=^A5\r:k6=^A6\r:k7=^A7\r:k8=^A8\r:k9=^A9\r:kd=^J:kl=^H:kr=^L:ku=^K:\ :li#24:ma=j^Jk^P^K^Pl ^R^L^L :mi:nd=^L:\ :se=\EG0:so=\EG4:up=^K:us=\EG1:ue=\EG0: la|adm3a|3a|lsi adm3a:\ :am:do=^J:le=^H:bs:cm=\E=%+ %+ :cl=1^Z:co#80:ho=^^:\ :li#24:ma=^K^P:nd=^L:up=^K: lb|adm3a+|3a+|adm3aplus:\ :kl=^H:kd=^J:ku=^K:kr=^L:tc=adm3a: lc|adm22|22|lsi adm22:\ :is=\E%\014\014\014\016\003\000\003\002\003\002\000\000\000\000\000\000\000\000\000\000\000:\ :al=\EE:am:bs:bt=\EI:cd=\Ey:ce=\Et:cl=\E+:cm=\000\E=%+ %+ :co#80:\ :dc=\EW:dl=\ER:do=^J:em=:ho=^^:ic=\EQ:im=:\ :k1=\001@\015:k2=\001A\015:k3=\001B\015:k4=\001C\015:\ :k5=\001D\015:k6=\001E\015:k7=\001F\015:kn#7:\ :ko=ho:l1=F1:l2=F2:l3=F3:l4=F4:l5=F5:l6=F6:l7=F7:\ :kb=^H:kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:li#24:\ :ma=j^Jk^P^K^Pl ^R^L^L :nd=^L:se=\E(:so=\E):ta=\Ei:up=^K: #From: stephen%comp.lancs.ac.uk@ucl-cs.arpa le|adm11|lsi adm11:\ :do=^J:bs:\ :cd=\EY:ce=\ET:kb=^H:kh=^^:\ :ma=^Hh^Jj^Kk^Ll^^H:so=\E):se=\E(:\ :kl=^H:kd=^J:ku=^K:kr=^L:\ :am:cm=\E=%+ %+ :cl=^Z:co#80:li#24:nd=^L:up=^K:\ :hs:ts=\EF\E):fs=\E(^M:ds=\Eh: # # -------------------------------- # # m: MICROTERM # # These mime1 entries refer to the Microterm Mime I or Mime II. # The default mime is assumed to be in enhanced act iv mode. m3|mime3a|mime1 emulating 3a:\ :am@:ma=^X ^K^J^Z^P:ku=^Z:kd=^K:kl=^H:kr=^X:tc=adm3a: m4|microterm|act4|microterm act iv:\ :am:do=^J:le=^H:bs:cd=^_:ce=^^:cl=^L:cm=^T%.%.:\ :co#80:li#24:nd=^X:up=^Z:ho=^]: # The padding on sr and ta for act5 and mime is a guess and not final. # The act 5 has hardware tabs, but they are in columns 8, 16, 24, 32, 41 (!)... m5|microterm5|act5|microterm act v:\ :uc=^H\EA:sr=3\EH:ku=^Z:kd=^K:kl=^H:kr=^X:ma=^Z^P^Xl^Kj:tc=act4: # Act V in split screen mode. act5s is not tested and said not to work. mS|act5s|skinny act5:\ :ti=\EP:te=\EQ:li#48:co#39:tc=act5: # Mimes using brightness for standout. Half bright is really dim unless # you turn up the brightness so far that lines show up on the screen. # uc is disabled to get around a curses bug, should be put back in someday. mf|mime-fb|full bright mime1:\ :so=^Y:se=^S:is=^S\E:tc=mime: mh|mime-hb|half bright mime1:\ :so=^S:se=^Y:is=^Y\E:tc=mime: mm|mime|mime1|mime2|mimei|mimeii|microterm mime1:\ :do=^J:al=80^A:am:le=^H:bs:cd=^_:ce=^^:cl=\035^C:cm=^T%+^X%> 0%+P:\ :co#80:dl=80^W:ta=2^I:li#24:nd=^X:pt:uc=^U:up=^z:ho=\035:do=^K:\ :is=^S\E^Q:ma=^X ^K^J^Z^P:ku=^Z:kd=^K:kl=^H:kr=^X:sr=3^R:vt#9: # These termcaps (for mime 2a) put the terminal in low intensity mode # since high intensity mode is so obnoxious. ms|mime2a-s|microterm mime2a (emulating an enhanced soroc iq120):\ :do=^J:\ :al=20*^A:am:le=^H:bs:cd=20*\EJ:ce=\EK:cl=\EL:cm=\E=%+ %+ :co#80:dc=\ED:\ :dl=20*^W:kl=^H:kr=^L:ku=^K:kd=^J:ho=^^:is=\E):sr=\EI\ :im=\EE:ei=^Z:ip=2:li#24:nd=^L:so=\E\072:se=\E;:up=\EI:\ :us=\E6:ue=\E7: # This is the preferred mode (but ^X can't be used as a kill character) mv|mime2a|mime2a-v|microterm mime2a (emulating an enhanced vt52):\ :do=^J:al=20*^A:le=^H:bs:cd=20*\EQ:co#80:ce=\EP:cl=\EL:cm=\EY%+ %+ :\ :is=^Ydc=^N:dl=20*^W:ip=2:ei=^Z:ho=\EH:im=^O:kd=\EB:kl=\ED:kr=\EC:\ :ku=\EA:li#24:nd=\EC:pt:se=\E9:so=\E8:up=\EA:sr=\EA:us=\E4:ue=\E5: mx|mime3ax|mime-3ax|mime1 emulating enhanced 3a:\ :al=80^A:dl=80^W:pt:ce=^X:cd=^_:tc=mime3a: # # -------------------------------- # # p: PERKIN ELMER # pe|pe550|bantam|perkin elmer 550:\ :do=^J:le=^H:bs:co#80:ce=20\EI:cl=20\EK:cm=\EX%+ \EY%+ :\ :ho=\EH:li#24:ll=\EH\EA:nd=\EC:up=\EA:ma=^Z^P:cd=6^N@^V: pf|fox|perkin elmer 1100:\ :ct=\E3:st=\E1:do=^J:\ :am:le=^H:bs:cd=5.5*\EJ:ce=\EI:cl=132\EH\EJ:co#80:ho=\EH:li#24:\ :ll=\EH\EA:nd=\EC:cm=\EX%+ \EY%+ :up=\EA:vb=^P^B^P^C: po|owl|perkin elmer 1200:\ :ct=\E3:st=\E1:do=^J:al=5.5*\EL:am:le=^H:\ :bs:cd=5.5*\EJ:ce=5.5\EI:cl=132\EH\EJ:ho=\EH:ll=\EH\EA:\ :cm=\EX%+ \EY%+ :co#80:dc=5.5*\EO:dl=5.5*\EM:ei=:ic=\EN:im=:ip=5.5*:\ :kb=^h:in:li#24:nd=\EC:up=\EA:se?=\E!\200:so?=\E!^H:vb=^P^B^P^C:\ :k1=\ERA:k2=\ERB:k3=\ERC:k4=\ERD:k5=\ERE:k6=\ERF:\ :k7=\ERG:k8=\ERH:k9=\ERI:k0=\ERJ: # # -------------------------------- # # q: HOME MADE TERMINALS # qB|bc|bill croft homebrew:\ :do=^J:am:le=^H:bs:cm=\E=%+ %+ :cl=^Z:co#96:ho=^^:li#72:\ :nd=^L:up=^K:vb=: qN|nucterm|rayterm|NUC homebrew:\ :do=^J:am:le=^H:bs:cl=1^L:li#24:co#80:nd=^C:\ :up=^N:ho=^B:ll=^K:ce=^A:cd=^E: qb|ex3000:\ :do=^J:li#24:co#80:ho=^Q: qc|carlock|klc:\ :do=^J:al=^E:am:bs:ce=^U:cl=100^Z:cm=\E=%+ %+ :co#80:dc=\177:dl=^D:\ :dm=:ed=:ei=^T:ho=^^:im=^T:li#24:nd=^L:se=^V:so=^V:up=^K:vb=\EV\EV: # uVAX qd|qdss|qdcons|qdss glass tty:\ :am:do=^J:le=^H:bs:cm=\E=%.%.:cl=1^Z:co#128:li#57::nd=^L:up=^K: qe|exidy|exidy2500|exidy sorcerer as dm2500:\ :do=^J:al=^P^J^X:am:le=^H:bs:ce=^W:cl=^^:cm=^L%r%n%.%.:co#64:\ :dc=\b:dl=^P^Z^X:dm=^P:ed=^X:ei=^X:ho=^B:ic=^\:\ :im=^P:li#30:nd=^\:pt:so=^N:se=^X:up=^Z: qn|netx|netronics:\ :do=^J:le=^H:bs:cd=2000^F^E:ce=1600^E:cl=466^L:cm=\E=%+@%+@:\ :co#64:ho=^D:li#16:ma=j^Jk^Pl :nd=\E+@A:pc=\200:sr=\E=@@^K:up=^K: # This came from the comp ctr who got it from some user. Smart indeed! qs|sexidy|exidy smart:\ :do=^J:li#24:co#64:cl=^l:ho=^q:nd=^s:\ :up=^w:le=^H:bs:le=^a:bc=^a:ma=^x^J:kd=^S: qu|ubell|ubellchar:\ :if=/usr/lib/tabset/ubell:do=^J:am:le=^H:bs:pt:ce=\Ed:cl=^Z:\ :cm=\E=%+ %+ :co#80:li#24:nd=^L:up=^K:ma=j^Jk^P^K^Pl :ho=^^: qw|ttyWilliams:\ :do=^J:co#80:li#12:le=^Y:bc=^Y:do=^K:up=^Z:cl=^^:ce=^_:am:ho=^]:nd=^X: qx|xitex|xitex sct-100:\ :do=^J:le=^H:bs:cd=2000^F^E:ce=1600^E:cl=400^L:cm=\E=%+@%+@:co#64:\ :ho=^D:li#16:ma=j^Jk^Pl :nd=\E+@A:pc=\200:sr=\E=@@^K:up=^K: # # -------------------------------- # # s: SPECIALS # # Special "terminals". These are used to label tty lines when you don't # know what kind of terminal is on it. The characteristics of an unknown # terminal are the lowest common denominator - they look about like a ti 700. sa|network:\ :tc=unknown: sb|arpanet:\ :tc=unknown: sc|bussiplexer:\ :tc=unknown: sd|du|dialup:\ :tc=unknown: se|ethernet:\ :tc=unknown: sl|lpr|printer|print|printing|line printer:\ :do=^J:le=^H:bs:co#132:hc:os: sp|plugboard|patch|patchboard:\ :tc=unknown: su|dumb|un|unknown:\ :am:co#80:do=^J: sw|switch|intelligent switch:\ :tc=unknown: sx|ansi|any ansi terminal with pessimistic assumptions:\ :co#80:li#24:cl=50\E[;H\E[2J:bs:am:cm=\E[%i%d;%dH:\ :nd=\E[C:up=\E[A:ce=\E[K:ho=\E[H:pt: # # -------------------------------- # # t: TEXAS INSTRUMENTS # t3|ti|ti700|ti733|735|ti735|ti silent 700:\ :do=^J:le=^H:bs:co#80:hc:os:dC#162: t4|ti745|745|743|ti silent 745:\ :do=^J:le=^H:bs:co#80:hc:os: t8|ti800|ti omni 800:\ :do=^J:le=^H:bs:co#132:hc:os: # From lesleymw@topaz.berkeley.edu t9|ti931|ti 931:\ al=\EN:am:bs:cd=\EJ:ce=\EI:cl=\EL:cm=\EY%+ %+ :co=#80:dl=\EO:do=\EB:\ eo:ho=\EH:li=#24:ku=\EA:kd=\EB:kr=\EC:kl=\ED:mi:nd:sf=\Eb:sr=\Ea:up=\EA: # # -------------------------------- # # v: TELEVIDEO # # There are some tvi's that require incredible amounts of padding and # some that don't. I'm assuming 912 and 920 are the old slow ones, # and 912b, 912c, 920b, 920c are the new ones that don't need padding. v1|tvi912|912|920|tvi920|old televideo:\ :ct=\E3:st=\E1:do=^J:\ :al=33*\EE:le=^H:ce=\ET:cm=\E=%+ %+ :cl=^Z:co#80:dc=\EW:dl=33*\ER:ei=:\ :kb=^H:ku=^K:kd=^J:kl=^H:kr=^L:k0=^AI\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:\ :bs:am:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:\ :ho=^^:im=:ic=\EQ:li#24:nd=^L:pt:se=\Ek:so=\Ej:up=^K:us=\El:ue=\Em:\ :ma=^K^P^L :sg#1:ug#1:if=/usr/lib/tabset/stdcrt # the 912 has a key that's like shift: 8 xmits "^A8\r". # The 920 has this plus real function keys that xmit different things. # Termcap makes you use the funct key on the 912 but the real keys on the 920. v2|912b|912c|tvi912b|tvi912c|tvi|new televideo 912:\ :al=5*\EE:dl=5*\ER:tc=tvi912: v3|920b|920c|tvi920b|tvi920c|new televideo 920:\ :k0=^AI\r:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:\ :k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:al=5*\EE:dl=5*\ER:tc=tvi912: # set to page 1 when entering ex (\E-17 ) # reset to page 0 when exiting ex (\E-07 ) v4|tvi912-2p|tvi920-2p|912-2p|920-2p|tvi-2p|televideo w/2 pages:\ :ti=\E-17 :te=\E-07 :tc=tvi912: v5|tvi950-ap|tvi 950 w/alt pages:\ :is=\E\\1:ti=\E-06 :te=\E-16 :tc=tvi950: v6|tvi950-b|bare tvi950 no is:\ :is@:tc=tvi950: v7|tvi950-ns|tvi950 w/no standout:\ :so@:se@:us@:ue@:tc=tvi950: vi|tvi925|925|televideo model 925:\ :hs:xn:am:bs:co#80:li#24:cm=\E=%+ %+ :cl=\E*:cd=\Ey:ce=\Et:is=\El\E":\ :al=\EE:dl=\ER:im=:ei=:ic=\EQ:dc=\EW:if=/usr/lib/tabset/stdcrt:\ :ho=^^:nd=^L:bt=\EI:pt:so=\EG4:se=\EG0:sg#1:us=\EG8:ue=\EG0:ug#1:\ :up=^K:do=^V:kb=^H:ku=^K:kd=^V:kl=^H:kr=^L:kh=^^:ma=^V^J^L :\ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:\ :k8=^AG\r:k9=^AH\r:k0=^AI\r:ko=ic,dc,al,dl,cl,ce,cd,bt:\ :ts=\Ef:fs=^M\Eg:ds=\Eh:sr=\Ej: vj|tvi925vb|925vb|televideo model 925 visual bells:\ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\ :tc=tvi925: # Since the 925's uses a character position to store the escape sequences to go # in and out of both stand out and underline modes, screen positioning is # difficult. The following 925 entries don't use these modes. vn|tvi925n|925n|televideo model 925 no standout or underline:\ :so@:se@:us@:ue@:tc=tvi925: vk|tvi925vbn|925vbn|televideo model 925 visual bells no so or ul:\ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\ :tc=tvi925n: # entry by Tim Curry 5/21/82 Univ. of Central Fla. duke!ucf-cs!tim v9|925a|tvi925a|TeleVideo Model 925:\ :al=\EE:am:bs:bt=\EI:bw:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :co#80:dc=\EW:\ :dl=\ER:do=^V:ei=:ic=\EQ:if=/usr/lib/tabset/std:im=:kb=^H:kd=^V:\ :kh=^^:kl=^H:kn#12:kr=^L:ku=^K:li#24:nd=^L:pt:se=\EG0:sg=#1:so=\EG4:\ :ue=\EG0:ug#1:up=^K:us=\EG8:is=\El\ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\ :ve=\E.4:vs=\E.2: # The following tvi descriptions from B:pjphar and virus!mike # is for all 950's. It sets the following attributes: # full duplex (\EDF) write protect off (\E() # conversation mode (\EC) graphics mode off (\E%) # white on black (\Ed) auto page flip off (\Ew) # turn off status line (\Eg) clear status line (\Ef\r) # normal video (\E0) monitor mode off (\EX or \Eu) # edit mode (\Er) load blank char to space (\Ee\040) # line edit mode (\EO) enable buffer control (^O) # protect mode off (\E\047) duplex edit keys (\El) # program unshifted send key to send line all (\E016) # program shifted send key to send line unprotected (\E004) # set the following to nulls: # field delimiter (\Ex0\200\200) # line delimiter (\Ex1\200\200) # start-protected field delimiter (\Ex2\200\200) # end-protected field delimiter (\Ex3\200\200) # set end of text delimiter to carriage return/null (\Ex4\r\200) # CHANGED 4-29-87 to set tabs and keep status line --John Kunze (jak@opal) va|tvi950|950|televideo950:\ :ct=\E3:st=\E1:do=^J:\ :is=\EDF\EC\Ed\EG0\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\ \El\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\ \Ex3\200\200\Ex4\r\200\Ef\r:if=/usr/lib/tabset/stdcrt:\ :al=\EE:am:le=^H:bs:bt=\EI:cd=\Ey:ce=\Et:cl=\E*:cm=\E=%+ %+ :\ :co#80:dc=\EW:dl=\ER:do=^V:ei=\Er:ho=^^:im=\Eq:k0=^A0\r:\ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:\ :k7=^AF\r:k8=^AG\r:k9=^AH\r:kb=^H:kd=^V:kh=^^:kl=^H:\ :ko=ic\054dc\054al\054dl\054cl\054bt\054ce\054cd:kr=^L:\ :ku=^K:li#24:ma=^Vj^Kk^Hh^Ll^^H:mi:ms:nd=^L:pt:se=\EG0:\ :sg#1:so=\EG4:sr=\Ej:ue=\EG0:ug#1:up=^K:us=\EG8:\ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\ :xn:hs:ts=\Eg\Ef:fs=\r:ds=\Eg\Ef\r: # # is for 950 with two pages adds the following: # set 48 line page (\E\\2) # place cursor at page 0, line 24, column 1 (\E-07 ) # set local (no send) edit keys (\Ek) # # two page 950 adds the following: # when entering ex, set 24 line page (\E\\1) # when exiting ex, reset 48 line page (\E\\2) # place cursor at 0,24,1 (\E-07 ) # set duplex (send) edit keys (\El) when entering vi # set local (no send) edit keys (\Ek) when exiting vi # vb|tvi950-2p|950-2p|televideo950 w/2 pages:\ :is=\EDF\EC\Ed\EG0\Eg\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\ \Ek\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\ \Ex3\200\200\Ex4\r\200\E\\2\E-07 \ :te=\E\\2\E-07 :ti=\E\\1\E-07 :ks=\El:ke=\Ek:tc=tvi950: # # is for 950 with four pages adds the following: # set 96 line page (\E\\3) # place cursor at page 0, line 24, column 1 (\E-07 ) # # four page 950 adds the following: # when entering ex, set 24 line page (\E\\1) # when exiting ex, reset 96 line page (\E\\3) # place cursor at 0,24,1 (\E-07 ) # vc|tvi950-4p|950-4p|televideo950 w/4 pages:\ :is=\EDF\EC\Ed\EG0\Eg\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\ \Ek\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\ \Ex3\200\200\Ex4\r\200\E\\3\E-07 \ :te=\E\\3\E-07 :ti=\E\\1\E-07 :ks=\El:ke=\Ek:tc=tvi950: # # is for reverse video 950 changes the following: # set reverse video (\Ed) # # set vb accordingly (\Ed ...nulls... \Eb) # vd|tvi950-rv|950-rv|televideo950 rev video:\ :is=\EDF\EC\Eb\EG0\Eg\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\ \El\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\ \Ex3\200\200\Ex4\r\200:\ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\ :tc=tvi950: # # uses the appropriate entries from 950-2p and 950-rv # ve|tvi950-rv-2p|950-rv-2p|televideo950 rev video w/2 pages:\ :is=\EDF\EC\Eb\EG0\Eg\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\ \Ek\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\ \Ex3\200\200\Ex4\r\200\E\\2\E-07 :\ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\ :te=\E\\2\E-07 :ti=\E\\1\E-07 :ks=\El:ke=\Ek:tc=tvi950: # # uses the appropriate entries from 950-4p and 950-rv # vf|tvi950-rv-4p|950-rv-4p|televideo950 rev video w/4 pages:\ :is=\EDF\EC\Eb\EG0\Er\EO\E\047\E(\E%\Ew\EX\Ee ^O\ \Ek\E016\E004\Ex0\200\200\Ex1\200\200\Ex2\200\200\ \Ex3\200\200\Ex4\r\200\E\\3\E-07 :\ :vb=\Ed\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Eb:\ :te=\E\\3\E-07 :ti=\E\\1\E-07 :ks=\El:ke=\Ek:tc=tvi950: vg|tvi924|924|televideo model 924:\ :am:bs:xn:co#80:li#24:cm=\E=%+ %+ :cl=\E*0:cd=\Ey:ce=\Et:is=\Ek0\E"^O:\ :al=\EE:dl=\ER:im=:ei=:ic=\EQ:dc=\EW:if=/usr/lib/tabset/stdcrt:ho=^^:\ :nd=^L:bt=\EI:pt:so=\EG4:se=\EG0:us=\EG8:ue=\EG0:up=^K:do=^V:kb=^H:\ :ku=^K:kd=^V:kl=^H:kr=^L:kh=^^:ma=^Vj^Kk^Ll^^H^R^L:k1=^A@\r:k2=^AA\r:\ :k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:\ :k0=^AI\r:ko=ic,dc,al,dl,cl,ce,cd,bt:sr=\Ej:\ :hs:fs=^Y\Es1:ts=\Ef:ds=\Es0\Ef^Y: vo|tvi924vb|924vb|televideo model 924 visual bells:\ :vb=\Eb\200\200\200\200\200\200\200\200\200\200\200\200\200\200\200\Ed:\ :tc=tvi924: # tvipt termcap from armsis@amber (Gene Rochlin), 9/19/84. Works with vi and # rogue. NOTE: Esc v sets autowrap on, Esc u sets 80 char/line (rather than # 40), Esc K chooses the normal character set. Not sure padding is needed, but # adapted from the tvi920c termcap. so and us are klutzy, but at least use no # screen space. vp|tvipt|televideopt:if=/usr/lib/tabset/stdcrt:\ :is=\Ev\Eu\EK:al=5*\EE:am:bs:bt=\EI:ce=\ET:cm=\E=%+ %+ :cl=^Z:co#80:\ :dl=5*\ER:kb=^H:ku=^K:kd=^J:kl=^H:kr=^L:ho=^^:li#24:nd=^L:se=\EF:\ :so=\EG1@A\EH:ue=\EF:us=\EG1B@\EH:up=^K:ma=^Kk^Ll^R^L: # Vanilla tvi910 -- W. Gish (cswarren@violet) 10/29/86 vm|tvi910|910|televideo model 910:if=/usr/lib/tabset/stdcrt:\ :bs:bt=\EI:cd=\EY:ce=\ET:cm=\E=%+ %+ :cl=^Z:co#80:\ :kb=^H:ku=^K:kd=^J:kl=^H:kr=^L:k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:\ :k5=^AD\r:k6=^AE\r:k7=^AF\r:k8=^AG\r:k9=^AH\r:k0=^AI\r:\ :li#24:nd=^L:pt:se=\EG0:so=\EG4:up=^K:us=\EG8:ue=\EG0:\ :ho=\E=\001\001:ma=^Kk^Ll^R^L:sg#1: # from Alan R. Rogers (rogers%albany@csnet-relay) vh|tvi910+|910+|televideo 910+:\ :al=5*\EE:am:bs:bt=\EI:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+\040%+\040:\ :co#80:dc=\EW:dl=\ER:do=^J:ei=:ho=^^:ic=\EQ:\ :if=/usr/lib/tabset/stdcrt:im=:k0=^A@\r:k1=^AA\r:k2=^AB\r:k3=^AC\r:\ :k4=^AD\r:k5=^AE\r:k6=^AF\r:k7=^AG\r:k8=^AH\r:k9=^AI\r:kb=^H:\ :kd=^J:kh=^^:kl=^H:kr=^L:ku=^K:li#24:ll=\E=7\040:ma=^K^P^L\040:\ :nd=^L:pt:se=\EG0:sg#1:so=\EG4:ue=\EG0:up=^K:us=\EG8:xn: # From fair@ucbarpa Sun Oct 27 07:21:05 1985 v6|ims950-b|bare ims950 no is:\ :is@:tc=ims950: v7|ims950-ns|ims950 w/no standout:\ :so@:se@:us@:ue@:tc=ims950: va|ims950|ims televideo 950 emulation:\ :k0@:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:k9@:kb@:kd@:kh@:kl@:ko@:kr@:ku@:\ :vb@:xn@:tc=tvi950: vd|ims950-rv|ims tvi950 rev video:\ :k0@:k1@:k2@:k3@:k4@:k5@:k6@:k7@:k8@:k9@:kb@:kd@:kh@:kl@:ko@:kr@:ku@:\ :vb@:xn@:tc=tvi950-rv: vx|ims-ansi|ultima2|ultimaII|IMS Ultima II:\ :pt:am:bs:co#80:li#24:\ :is=\E[0m\E[>14l\E[?1;?5;20l\E>\E[1m^M:if=/usr/lib/tabset/vt100:\ :cl=\E[;H\E[2J:cd=\E[0J:ce=\E[0K:cm=\E[%i%2;%2H:up=\EM:do=\ED:\ :ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:kh=\E[H:\ :so=\E[7m:se=\E[0m\E[1m:us=\E[4m:ue=\E[0m\E[1m:sr=\EM: # # -------------------------------- # # y: TELERAY # # Note two things called "teleray". Reorder should move the common one # to the front if you have either. A dumb teleray with the cursor stuck # on the bottom and no obvious model number is probably a 3700. y1|t3700|teleray|dumb teleray 3700:\ :do=^J:le=^H:bs:cl=^L:co#80:li#24: y3|t3800|teleray 3800 series:\ :do=^J:le=^H:bs:cd=\EJ:ce=\EK:cl=^L:cm=\EY%+ %+ :co#80: \ :do=\n:ho=\EH:li#24:ll=\EY7 :nd=\EC:pt:up=^K: y6|t1061|teleray 1061:\ :if=/usr/lib/tabset/teleray:\ :ct=\EG:st=\EF:do=^J:\ :al=2*\EL:am:le=^H:bs:cd=1\EJ:ce=\EK:cl=1^L:cm=\EY%+ %+ :co#80:\ :dc=\EQ:dl=2*\EM:ei=:ho=\EH:ic=\EP:im=:ip=0.4*:\ :k1=^Z1:k2=^Z2:k3=^Z3:k4=^Z4:k5=^Z5:k6=^Z6:k7=^Z7:k8=^Z8:\ :li#24:nd=\EC:pt:se=\ER@:so= \ERD:\ :is=\Ee\EU01^Z1\EV\EU02^Z2\EV\EU03^Z3\EV\EU04^Z4\EV\EU05^Z5\EV\EU06^Z6\EV\EU07^Z7\EV\EU08^Z8\EV\Ef:\ :up=\EA:us=\ERH:ue=\ER@:xs:xt:sg#2:ug#1: # "Teleray Arpa Special", offically designated as # "Teleray Arpa network model 10" with "Special feature 720". # This is the new (1981) fast microcode updating the older "arpa" proms # (which gave meta-key and pgmmable-fxn keys). 720 is much much faster, # converts the keypad to programmable function keys, and has other goodies. # Standout mode is still broken (magic cookie, etc) so is suppressed as no # programs handle such lossage properly. # Note: this is NOT the old termcap's "t1061f with fast proms." # From Univ of Utah, J.Lepreau Tue Feb 1 06:39:37 1983 # lepreau@utah-cs, harpo!utah-cs!lepreau # y7|t10|teleray 10 special:\ :so@:se@:us@:ue@:\ :al=\EL:bs:cd=\EJ:ce=\EK:cl=30\Ej:cm=\EY%+ %+ :co#80:\ :dc=\EQ:dl=\EM:ei=:ho=\EH:ic=\EP:im=:km:li#24:nd=\EC:pc=\200:pt:\ :se=\ER@:so=\ERD:sf=\Eq:sg#2:sr=\Ep:up=\EA:ug#1:ue=\ER@:us=\ERH:\ :xs:xt: yf|t1061f|teleray 1061 with fast PROMs:\ :al=\EL:ip@:dl=\EM:tc=t1061: # Wyse 50 entry by Toni Guttman extended by Jeff Anton ye|w50|wyse50|Wyse 50:\ :al=\EE:am:bs:bt=\EI:cd=\EY:ce=\ET:cl=^Z:cm=\E=%+ %+ :co#80:\ :dc=\EW:dl=\ER:do=^J:ei=\Er:im=\Eq:is=\E`\072\200\EC\EDF\E0\E'\E(\EA21:\ :kd=^J:kl=^H:kr=^L:ku=^K:li#24:nd=^L:up=^K:us=\EG8:ue=\EG0:\ :so=\EG4:se=\EG0:sg#1:sr=\Ej:ho=^^:ug#1: # it is not known if the status line works with sysline yh|w50-s|wyse50-s|Wyse 50 for sysline:\ :hs:ts=\Ef:fs=\r:ds=\Ef\r:es:tc=w50: yg|w50-w|w50-132|wyse50-132|Wyse 50-132:\ :cm=\Ea%i%dR%dC:co#132:is=\E`;\200\EC\EDF\E0\E'\E(\EA21:tc=w50: w6|w60|wyse60|Wyse 60 in native mode:\ :ae=\EcD:al=\EE:am:as=\EcE:bs:bt=\EI:bw:cd=\Ey:ce=\Et:\ :cl=^Z:cm=\E=%+\040%+\040:co#80:ct=\E0:dc=\EW:dl=\ER:do=^J:\ :ei=\Er:im=\Eq:is=:kb=^?:kd=^N:ke=\E~2:kl=^B:kr=^F:ks=\E~3:ku=^P:\ :le=^H:li#43:ll=^^^K:mb=\EG2:me=\EG0:mh=\EGp:mi:mr=\EG4:ms:\ :nd=^L:pt:se=\EG0:sf=\n:so=\EG4:sr=\Ej:ue=\EG0:up=^K:us=\EG8: # from John Gillmore hoptoad!gnu@lll-crg.arpa wv|wyse-vp|wyse|Wyse 50 in ADDS Viewpoint emulation mode with "enhance" on:\ :am:do=^J:if=/usr/lib/tabset/wyse-adds:\ :le=^H:bs:li#24:co#80:cm=\EY%+ %+ :cd=\Ek:ce=\EK:nd=^F:\ :up=^Z:cl=^L:ho=^A:ll=^A^Z:kl=^U:kr=^F:kd=^J:ku=^Z:kh=^A:\ :pt:so=^N:se=^O:us=^N:ue=^O:dl=\El:al=\EM:im=\Eq:ei=\Er:dc=\EW:\ :is=\E`\072\E`9^O\Er:rs=\E`\072\E`9^O\Er: wk|wyse-vp-nk|Wyse 50 in ADDS Viewpoint enhanced mode with cursor keys gone:\ :kl@:kr@:kd@:ku@:kh@:tc=wyse-vp: vw|wyse925|Wyse-50 emulating tvi925:\ :xn@:tc=tvi925: # wyse 75 series from JLarson.pa@xerox.arpa wx|wyse75|wy75|wyse 75 terminal :\ :co#80:li#24:cl=50\E[H\E[2J:bs:cm=5\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :al=3\E[L:dl=3\E[M:ku=\E[A:kd=\E[B:kr=\E[C:kl=\E[D:do=\E[B:\ :ic=\E[@:ei=:im=:pt:bw:dc=\E[P:ce=3\E[K:ho=10\E[H:pt:\ :mi:nd=\E[C:bt=\E[Z:us=\E[8p:ue=\E[p:so=\E[5m:se=\E[m:\ :md=\E[1p:mr=\E[16p:mb=\E[2p:mk=\E[4p:me=\E[0p:hs:ll=\E[24;1H:\ :cd=50\E[J:cs=9\E[%i%d;%dr:ae=\E(B:as=\E(0:kh=\E[H:kb=^H:\ :k0=\EOP:k1=\EOQ:k2=\EOR:k3=\EOS:k4=\E[M:\ :k5=\E[17~:k6=\E[31~:k7=\E[18~:k8=\E[19~:k9=\E[20~:kn#10:\ :l0=PF1:l1=PF2:l2=PF3:l3=PF4:l4=F5:\ :l5=F6:l6=F7:l7=F8:l8=F9:l9=F10:\ :is=\E[1;24r\E[24;1H\E[35;?25h\E[4;?10;3;1l\E[m\E(B\E>:\ :ds=\E7\E[>,//\E8:ts=\E7\E[>,^A:fs=^A\E8: wx|wyse75-80|wy75-80|wyse 75 terminal with 80-column initialization:\ :is=\E[?3l:tc=wy75: wl|wyse75-132|wy75-132|wyse 75 terminal with 132 columns :\ :is=\E[?3h:co#132:tc=wy75: # # Wyse WY75 utilizing keypad # w5|wy75ap|wyse75ap|wy-75ap|wyse-75ap|Wyse WY-75 Applications and Cursor keypad:\ :is=\E[1;24r\E[?10;3l\E[?1;25h\E[4l\E[m\E(B\E=:\ :kd=\EOB:ke=10\E[?1l\E>:kh=\EOH:kl=\EOD:kr=\EOC:\ :ks=10\E[?1h\E=:ku=\EOA:\ :tc=wyse75: # from ucbvax!ucsfmis!shewmake Wc|wy85|wyse85|wyse-85:\ :do=^J:co#80:li#24:cl=\E[;H\E[2J:\ :le=^H:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :ce=\E[0K:cd=\E[0J:so=\E[7m:se=\E[27m:\ :us=\E[4m:ue=\E[24m:\ :is=\E[1;24r\E[24;1H\E[0m:\ :ks=\E[?1h\E=:ke=\E[?1l\E>:\ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\ :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:kh=\E[H"ta=^I:pt:sr=\EM:\ :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:as=^N:ae=^O:bt=\E[Z:\ :dc=\E[P:dl=\E[M:al=\E[L:ei=\E[4l:im=\E[4h:\ :vb=\E[?5h\E[?5l:\ :hs:es:ts=\E7\E[?25l\E[40h\E[25;%dH\E[2K:fs=\E[1;24r\E8\E[?25h: # # -------------------------------- # # z: Miscellaneous # z0|wind:\ :bs:cm=\Ep%r%.%.:cl=\En\120\030\Eo:co#80:\ :ho=\Ep\200\200:li#24:nd=^L:up=^K:nl=\035:\ :kl=\E3:kr=\E4:ku=\E1:kd=\E2:k1=\E5:k2=\E6:k3=\E7:k4=\E8:\ :so=\Em\014:se=\Em\003: z1|wind16:\ :bs:cm=\Ep%r%.%.:cl=\En\120\020\Eo:co#80:\ :ho=\Ep\200\200:li#16:nd=^L:up=^K:nl=\035:\ :so=\Em\014:se=\Em\003: z2|wind40:\ :bs:cm=\Ep%r%.%.:cl=\En\120\050\Eo:co#80:\ :ho=\Ep\200\200:li#40:nd=^L:up=^K:nl=\035:\ :so=\Em\014:se=\Em\003: z3|wind50:\ :bs:cm=\Ep%r%.%.:cl=\En\128\062\Eo:co#88:\ :ho=\Ep\200\200:li#50:nd=^L:up=^K:nl=\035:\ :kl=\E3:kr=\E4:ku=\E1:kd=\E2:k1=\E5:k2=\E6:k3=\E7:k4=\E8:\ :so=\Em\014:se=\Em\003: z4|cad68-3|cgc3|cad68 basic monitor transparent mode size 3 chars:\ :am:bs:cl=^Z:co#73:ho=\036:li#36:nd=^L:up=^K: z5|cad68-2|cgc2|cad68 basic monitor transparent mode size 2 chars:\ :am:bs:cl=^Z:co#85:ho=\036:li#39:nd=^L:up=^K:\ :kl=\E3:kr=\E4:ku=\E1:kd=\E2:k1=\E5:k2=\E6:k3=\E7:k4=\E8:\ :so=\Em\014:se=\Em\003: z6|v50|visual 50:\ :am:bs:al=\EL:dl=\EM:\ :cd=\Ek:ce=\EK:cl=^Z:cm=\E=%+\040%+\040:co#80:do=^J:ho=\EH:\ :kb=^H:kd=\EB:kh=\EH:kl=\ED:kr=\EC:ku=\EA:li#24:ms:nd=^L:pt:\ :so=\EU:se=\ET:up=^K: z7|trs2|trsII|trs80II|Radio Shack Model II using P&T CP/M:\ :nl=^_:al=^D:am:bs:cd=^B:ce=^A:cl=^L:cm=\EY%+ %+ :co#80:\ :dl=^K:do=^_:ho=^F:li#24:nd=^]:ms:pt:se=^O:so=^N:up:=^^:\ :kb=^H:kd=^_:kl=^\:kr=^]:ku=^^: z9|ps300|Picture System 300:us@:ue@:so@:se@:xt:pt@:tc=vt100: za|masscomp2:co#64:li#21:tc=masscomp: zb|masscomp1:co#104:li#36:tc=masscomp: zc|masscomp:\ :al=\E[L:bs:cd=\E[J:ce=\E[K:co#80:dc=\E[P:dl=\E[M:do=\E[B:\ :ei=\E[4l:im=\E[4h:is=\EGc\EGb\EGw:li#24:mi:MT:nd=\E[C:pt:se=\E[0m:\ :sg#0:so=\E[7m:cm=\E[%i%d;%dH:ue=\EGau:us=\EGu:up=\E[A:\ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^h:cl=\E[2J: # Kimtron TC entries include (undocumented) codes for: enter dim mode (mh), # enter bold mode (md), enter reverse mode (mr), turn off all attributes (me) # Kimtron ABM 85 added by Dual Systems zd|abm85|Kimtron ABM 85:\ :is=\EC\EX\Eg\En\E%\Er\E(\Ek\Em\Eq:if=/usr/lib/tabset/stdcrt:\ :li#24:co#80:am:bs:bw:ms:pt:\ :cl=\E*:cd=\Ey:dl=\ER:al=\EE:ce=\Et:dc=\EW:im=\EQ:ei=\Er:\ :cm=\E=%+ %+ :do=^J:nd=^L:up=^K:bt=\EI:\ :kh=^^:kb=^H:kd=^J:ku=^K:kd=^J:kl=^H:kr=^L:\ :so=\Ej:se=\Ek:sg#1:us=\El:ue=\Em:ug#1: # Kimtron ABM 85H added by Dual Systems. # Some notes about the 85h entries: # 1) there are several firmware revs of 85H in the world. Use o85h for # firmware revs prior to SP51 # 2) Make sure to use 85h entry if the terminal is in 85H mode and the # 85e entry if it is in 920 emulation mode. They are incompatible in # some places and NOT software settable i.e., `is' can't fix change it) # 3) In 85h mode, the arrow keys and special functions transmit when # the terminal is in dup-edit, and work only locally in local-edit. # Vi won't swallow `del char' for instance, but `vs' turns on # dup-edit anyway so that the arrow keys will work right. If the # arrow keys don't work the way you like, change `vs', `ve', and `is'. # 920E mode does not have software commands to toggle between dup # and local edit, so you get whatever was set last on the terminal. # 4) vb attribute is nice, but seems too slow to work correctly (\Eb\Ed) # 5) Make sure `hidden' attributes are selected. If `embedded' attributes # are selected, the entries :sg@: and :ug@: should be removed. # 6) auto new-line should be on (selectable from setup mode only) # # From fair@ucbarpa Sun Oct 27 07:21:05 1985 ze|85h|85H|abm85h|Kimtron ABM 85H, 85H mode:\ :is=\EC\EN\EX^T^N\EA\Ea\E%\E9\Ee\Er\En\E"\E}\E'\E(\Ef^M\EG0\Ed\E.4\El:\ :im=\EZ:kd=^V:so=\EG4:se=\EG0:us=\EG8:ue=\EG0:vb@:vs=\E.2:ve=\E.4:\ :mh=\E):mr=\EG4:me=\E(\EG0:sg@:ug@:ds=\Ee:fs=^M:hs:ts=\Eg\Ef:tc=abm85: zf|85e|85E|abm85e|Kimtron ABM 85H, 920E mode:\ :is=\EC\EX\EA\E%\E9\Ee\Er\En\E"\E}\E'\E(\Ef^M\Ek\Eq\Em:\ :mh=\E):mr=\Ej:me=\E(\Ek:im=\EZ:sg@:ug@:vb@:tc=abm85: zg|o85h|oabm85h|Kimtron ABM 85H, old firmware rev.:\ :is=\E}\EC\EX\Ee\En\E%\Er\E(\Ek\Em\Eq\Ed\ET\EC\E9\EF:\ :im=\EZ:sg@:ug@:vb=\200\200\200^G\200\200\200:\ :mh=\E):mr=\Ej:me=\E(\Ek:tc=abm85: #from malman@bbn-vax.arpa zE|kt7|kimtron model kt-7:\ :am:bs:co#80:li#24:cm=\E=%+ %+ :cl=^Z:cd=\EY:ce=\ET:is=\El\E":\ :al=\EE:dl=\ER:im=:ei=:ic=\EQ:dc=\EW:if=/usr/lib/tabset/stdcrt:\ :ho=^^:nd=^L:bt=\EI:pt:so=\EG4:se=\EG0:sg#0:us=\EG8:ue=\EG0:ug#0:\ :up=^K:do=^V:kb=^H:ku=^K:kd=^V:kl=^H:kr=^L:kh=^^:ma=^V^J^L :\ :k1=^A@\r:k2=^AA\r:k3=^AB\r:k4=^AC\r:k5=^AD\r:k6=^AE\r:k7=^AF\r:\ :k8=^AG\r:k9=^AH\r:k0=^AI\r:ko=ic,dc,al,dl,cl,ce,cd,bt:\ :ts=\Ef:fs=\Eg: zh|appleII|apple ii plus:vs=\024\103\066:ve=\024\103\062:\ :am:co#80:ce=\035:li#24:cl=\014:bs:nd=\034:up=\037:ho=\E\031:pt:\ :cd=\013:so=\017:se=\016:cm=\036%r%+ %+ :is=\024T1\016:do=^J:kd=^J:\ :vb=\024G1\024T1:kr=: # Gary Ford 21NOV83 # New version from ee178aci%sdcc7@SDCSVAX.ARPA Fri Oct 11 21:27:00 1985 zi|apple-80|apple II with smarterm 80 col:\ :am:bs:bt=^R:bw:cd=10*^K:ce=10^]:cl=10*^L:cm=^^%r%+ %+ :\ :co#80:cr=10*^M:do=^J:ho=^Y:le=^H:li#24:nd=^\\:up=^_: # zj|lisa|apple lisa xenix console display (white on black):\ :al=\E[L:am:bs:cd=\E[J:ce=\E[K:cl=^L:cm=\E[%i%d;%dH:co#88:\ :dc=\E[P:dl=\E[M:dn=\E[B:ei=:ho=\E[H:ic=\E[@:im=:li#32:\ :nd=\E[C:ms:pt:so=\E[m:se=\E[7m:us=\E[4m:ue=\E[7m:up=\E[A:\ :kb=^h:ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:eo:\ :is=\E[7m^L:GS=\E[11m:GE=\E[10m:GV=\140:GH=a:G1=c:\ :G2=f:G3=e:G4=d:GU=u:GD=s:GC=b:GL=v:GR=t: # The following is a version of the ibm-pc entry distributed with PC/IX, # (Interactive Systems' System 3 for the Big Blue), modified by Richard # McIntosh at UCB/CSM. The :pt: and :uc: have been removed from the original, # (the former is untrue, and the latter failed under UCB/man); standout and # underline modes have been added. Note: this entry describes the "native" # capabilities of the PC monochrome display, without ANY emulation; most # communications packages (but NOT PC/IX connect) do some kind of emulation. pc|ibmpc|ibm pc PC/IX:\ :li#24:co#80:am:bs:bw:eo:\ :cd=\E[J:ce=\E[K:cl=\Ec:cm=\E[%i%2;%2H:do=\E[B:ho=\E[;H:\ :nd=\E[C:up=\E[A:so=\E[7m:se=\E[0m:us=\E[4m:ue=\E[0m: pc3-bold|ibmpc3|IBM PC BSD/386 Console with bold instead of underline:\ :us=\E[=15F:ue=\E[=R:tc=pc3:\ pc3|ibmpc3|IBM PC BSD/386 Console:\ :li#25:al=\E[L:dl=\E[M:md=\E[=15F:me=\E[=R:mh=\E[=8F:\ :kh=\E[H:kH=\E[F:kP=\E[I:kN=\E[G:kI=\E[L:\ :ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:tc=pc: zk|ibmx|ibmpcx|IBM PC xenix console display:\ :al=\E[L:am:bs:cd=\E[J:ce=\E[K:cl=^L:cm=\E[%d;%dH:co#80:\ :dc=\E[P:dl=\E[M:dn=\E[B:ei=:ho=\E[H:ic=\E[@:im=:li#25:\ :nd=\E[C:ms:se=\E[0m:so=\E[7m:us=\E[4m:\ :ue=\E[m:up=\E[A:MR=\E[0m:\ :kb=^h:kh=\E[Y:ku=\E[A:kd=\E[B:kl=\E[D:kr=\E[C:eo:\ :GS=\E[11m:GE=\E[10m:\ :GC=b:GL=v:GR=t:RT=^J:\ :GH=\E[196g:GV=\E[179g:\ :GU=\E[193g:GD=\E[194g:\ :G1=\E[191g:G2=\E[218g:G3=\E[192g:G4=\E[217g:\ :CW=\E[E:NU=\E[F:RF=\E[G:RC=\E[H:\ :WL=\E[K:WR=\E[L:CL=\E[M:CR=\E[N:\ :HM=\E[Y:EN=\E[d:PU=\E[Z:PD=\E[e: zl|ibmc|ibmcpc|IBM PC xenix color console display:\ :tc=ibm: zl|ibmcx|ibmcpcx|IBM PC xenix color console display:\ :tc=ibmx: zm|kaypro|kaypro2|kaypro II:\ :am:bs:cm=\E=%+ %+ :cl=1^Z:co#80:ho=^^:li#24:ma=^K^P:nd=^L:up=^K:\ :kr= :kl=^H:ku= :kd=^J: # From Suk Lee ..!{decvax,linus,allegra,ihnp4}!utcsrgv!spoo zn|trs100|Radio Shack Model 100:\ :am:bs:le=^H:li#8:co#40:ku=^^:kd=^_:kl=^]:kr=^\:up=\EA:\ :nd=\EC:ho=\EH:ce=\EK:cd=\EJ:cl=\EE:xt:cm=\EY%+ %+ :\ :so=\Ep:se=\Eq:al=\EL:dl=\EM: zt|mac|macintosh|Macintosh with MacTerminal:\ :al=20\E[L:dl=20\E[M:ip=7:dc=7\E[P:ic=9\E[@:xn:dN#30:tc=vt100: zs|zen50|z50:zephyr:\ :cm=\E=%+ %+ :cd=\EY:co#80:li#24:\ :am:al=\EE:ce=\ET:dc=\EW:dl=\ER:ic=\EQ:im=:ei=:\ :cl=\E+:bs:ma=^Hh^Ll^Jj^Kk:sg#1:se=\EGO:so=\EG4:\ :kl=^H:kr=^L:ku=^K:kd=^J:kh=\036:up=^K:\ :BS=^U:CL=^V:CR=^B:RK=^L:UK=^K:LK=^H:DK=^J:HM=\036: zu|go140|graphon go-140:\ :co#80:li#24:cl=10\E[;H\E[2J:bs:cm=\E[%i%2;%2H:nd=\E[C:up=\E[A:\ :ce=\E[K:cd=10\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m:\ :is=\E<\E=\E[?3l\E[?7l\E(B\E[J\E7\E[;r\E8\E[m\E[q:\ :dl=\E[M:al=\E[L:dc=\E[P:im=\E[4h:ei=\E[4l:\ :ks=\E[?1h\E=:ke=\E[?1l\E>:\ :if=/usr/lib/tabset/vt100:ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:\ :kh=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=\EM: zv|go140w|graphon go-140 in 132 column mode:\ :co#132:is=\E<\E=\E[?3h\E[?7h\E(B\E[J\E7\E[;r\E8\E[m\E[q:\ :tc=go140: zw|sanyo55|sanyo|sanyo mbc-55x pc compatible:\ :co#80:li#25:am:cl=\E[H\E[J:bs:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :ce=\E[K:cd=\E[J:so=\E[7m:se=\E[m:us=\E[4m:ue=\E[m: #From: Simson L. Garfinkel zC|ST|atari st:\ :bs:cd=\EJ:ce=\EK:cl=\EH\EJ:cm=\EY%+ %+ :co#80:li#25:nd=\EC:\ :pt:sr=\EI:up=\EA:ku=\EA:kd=\EB:kr=\EC:kl=\ED:\ :do=\EB:\ :so=\Ep:se=\Eq:dl=\EM:al=\EL:am: # UniTerm terminal program for the Atari ST: 49-line VT220 emulation mode # From Paul M. Aoki, aoki@ucbvax.Berkeley.EDU zD|uniterm|uniterm49|UniTerm VT200 emulator, 49 lines:\ :li#49:is=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[1;49r\E[49;1H:\ :tc=vt200: # YTERM standard version 1.0. (gts 9-25-84) # Straight old ascii keyboard except function keys are Yale (e.g.,ASCII.KBD). # Only 80 tab columns (else yterm 1.1 bug). No :xn: in 1.0. # Cannot use termcap :sr=\EM: because vi will not work, too bad. # vi string is given so that yterm is reset each vi startup. Y0|yterm10|yterm 1.0 UCB ascii.kbd:\ :am:bs:cd=^K:ce=^]:cl=^L:cm=^^%r%+ %+ :co#80:EP:ho=^Y:li#24:nd=^\:pt:\ :rc=\E8:sc=\E7:so=\E[7m:se=\E[m:up=^_:us=\E[4m:ue=\E[m:\ :is=^O\E[7i\E[m\E[?7h\E[?3g\r\EHY0 for \EHYTERM 1.\EH0 with A\EHSCII.KBD\EH 9-13-84\EH \EH \EH \EH \EH\n:\ :ku=^K:kd=^J:kl=^H:kr=^L:kh=^^:ma=h\012j k lH:\ :k0=\E0:k1=\E1:k2=\E2:k3=\E3:k4=\E4:k5=\E5:k6=\E6:k7=\E7:k8=\E8:k9=\E9:\ :vs=^O\E[7i\E[m\E[?7h\E[?3g\r\EHY0 \EH \EH \EH \EH \EH \EH \EH \EH \EH\r: # YTERM varient version 1.1. (gts 9-13-84) Version 1.1 has :xn:. Y1|yterm11|yterm 1.1 UCB ascii.kbd:\ :xn:is=^O\E[7i\E[m\E[?7h\E[?3g\r\EHY1 for \EHYTERM 1.\EH1 with A\EHSCII.KBD\EH 9-13-84\EH \EH \EH \EH \EH\n:\ :tc=yterm10 # YTERM 1.0 varient no autowrap or tabs # X does not remember autowrap or tabs when T is deleted and restarted. Y2|yterm10nat|yterm 1.0 UCB ascii.kbd no autowrap or tabs:\ :am@:pt@:vs=^O\E[7i\E[m\E[?7l\E[?3g\rY2\r:\ :is=^O\E[7i\E[m\E[?7l\E[?3g\rY2 for YTERM 1.0 with ASCII.KBD 9-20-84 no autowrap or tabs\n:\ :tc=yterm10 # KERMIT standard all versions. (gts 9-25-84) # Straight ascii keyboard. :sr=\EI: not avail. many versions + bug prone in vi. K0|kermit|standard kermit:\ :bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:ho=\EH:li#24:nd=\EC:up=\EA:\ :ku=^K:kd=^J:kl=^H:kr=^L:kh=^^:ma=^Hh\012j^Kk^Ll^^H:\ :is=K0 Standard Kermit 9-25-84\n: K1|kermitam|standard kermit plus am:\ :am:is=K1 Standard Kermit plus Automatic Margins\n:tc=kermit: # IBMPC Kermit 1.2. (gts 8-30-84) # Bugs :cd:ce: do not work except at beginning of line! :cl: does not work, # but fake with :cl=\EH\EJ (since :cd=\EJ: works at beginning of line). K2|pckermit|pckermit12|UCB IBMPC Kermit 1.2:\ :am:li#25:cd@:ce@:cl=\EH\EJ:\ :is=K2 UCB IBMPC Kermit 1.2 8-30-84\n:tc=kermit: # IBMPC Kermit 1.20 (gts 12-19-84) # Cannot use line 25, now acts funny like ansi special scrolling region. # Initialization must escape from that region by cursor position to line 24. # Cannot use character insert because 1.20 goes crazy if insert at col 80. # Does not use am: because autowrap mode lost when kermit dropped and restarted. K3|pckermit120|UCB IBMPC Kermit 1.20:\ :al=\EL:am@:dc=\EN:dl=\EM:do=\EB:ei@:im@:li#24:pt:se=\Eq:so=\Ep:\ :is=\EO\Eq\EJ\EY7 K3 UCB IBMPC Kermit 1.20 12-19-84\n:\ :vs=\EO\Eq\EEK3:tc=kermit: # MS-DOS Kermit 2.27 for the IBMPC (UCB gts 3-17-85) # Straight ascii keyboard. :sr=\EI: not avail. many versions + bug prone in vi. # Cannot use line 25, now acts funny like ansi special scrolling region. # Initialization must escape from that region by cursor position to line 24. # Does not use am: because autowrap mode lost when kermit dropped and restarted. # Reverse video for standout like H19. K4|msk227|mskermit227|MS-DOS Kermit 2.27 for the IBMPC:\ :al=\EL:am@:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:\ :dc=\EN:dl=\EM:do=\EB:ei=\EO:im=\E@:\ :ho=\EH:li#24:nd=\EC:up=\EA:pt:rc=\Ek:sc=\Ej:se=\Eq:so=\Ep:\ :ku=^K:kd=^J:kl=^H:kr=^L:kh=^^:ma=^Hh\012j^Kk^Ll^^H:\ :is=\EO\Eq\EG\Ew\EJ\EY7 K4 MS Kermit 2.27 for the IBMPC 3-17-85\n:\ :vs=\EO\Eq\EG\EwK4: # MS-DOS Kermit 2.27 with automatic margins (UCB gts 3-17-85) K5|msk227am|mskermit227am|UCB MS-DOS Kermit 2.27 with automatic margins:\ :am:\ :is=\EO\Eq\EG\Ev\EJ\EY7 K5 MS Kermit 2.27 +automatic margins 3-17-85\n:\ :vs=\EO\Eq\EG\EvK5:tc=mskermit227: # MS-DOS Kermit 2.27 UCB 227.14 for the IBM PC (UCB gts 3-17-85) # Automatic margins now default. Use ansi set graphic rendition for standout, # underline and ul codes (md,me,mr). Define function keys. K6|msk22714|mskermit22714|UCB MS-DOS Kermit 2.27 UCB 227.14 IBM PC:\ :am:kn#10:\ :k0=\E0:k1=\E1:k2=\E2:k3=\E3:k4=\E4:k5=\E5:k6=\E6:k7=\E7:k8=\E8:k9=\E9:\ :md=\E[1m:me=\E[m:mr=\E[7m:se=\E[m:so=\E[1m:ue=\E[m:us=\E[4m:\ :is=\EO\Eq\EG\Ev\EJ\EY7 K6 MS Kermit 2.27 UCB 227.14 IBM PC 3-17-85\n:\ :vs=\EO\Eq\EG\EvK6:tc=mskermit227: # From earle@smeagol.UUCP 29 Oct 85 05:40:18 GMT # MS-Kermit with Heath-19 emulation mode enabled Kh|h19k|h19kermit|heathkit emulation provided by Kermit (no auto margin):\ :am@:ta@:pt@:xt:da:db:tc=h19-u: # rough draft of Amiga termcap by Mike Meyer AA|amiga|Amiga ANSI:\ :co#80:li#25:am:do=\E[B:ce=\E[K:cd=\E[J:\ :cl=\E[H\E[J:ku=\E[A:kd=\E[B:kl=\E[C:kr=\E[D:kb=^H:\ :al=\E[L:dl=\E[M:le=^H:cm=\E[%i%d;%dH:nd=\E[C:up=\E[A:\ :ce=\E[K:ho=\E[H:dc=\E[P:ic=\E[@:\ :so=\E[2m:se=\E[m:us=\E[4m:ue=\E[m:mr=\E[7m:mb=\E[7;2m:me=\E[m: # The pcplot IBM-PC terminal emulation program is really messed up. It is # supposed to emulate a vt-100, but emulates the wraparound bug incorrectly, # doesn't support scrolling regions, ignores add line commands, and ignores # delete line commands. Consequently, the resulting behavior looks like a # crude adm3a-type terminal. # Steve Jacobson 8/85 pp|pcplot:\ :cs@:sc@:rc@:xn@:tc=vt100: # From Joel Rubin, jmrubin@coral, a preliminary TERMCAP for VIDTEX, # a terminal program sold by Compuserve. Line and column numbers are # computer-dependent (I have a Commodore '64); you should use the meta-B # option to shut off clean-breaking of lines. No key codes included # since some of them are programmable and most are machine-specific. # Works on vi if you don't use clean-breaking. Very similar to the IBM 3101 # termcap. Escape-D used for backspace because control-H is destructive # backspace. There seem to be a few weirdnesses (especially at the beginning # of a wrapped line), and the cursor does not, unfortunately, flash. zQ|vid|vidtex|Compuserve vidtex program:\ :am:bc=\ED:cl=^L:li#25:co#40:nd=\EC:up=\EA:cd=\EJ:ce=\EK:\ :ho=\EH:cm=\EY%+\40%+\40:pt: # Fortune from c160-3bp@Coral (Robert Nathanson) via tut Wed Oct 5, 1983 zK|fos|fortune|Fortune system:\ :is=^_..:li#25:co#80:am:bs:bw:cl=20^L:cd=3*^\Y:\ :ic=5^\Q:dc=5^\W:dl=15^\R:al=15^\E:cm=^\C%+ %+ :ta=^Z:ho=10^^:do=3^J:\ :up=3^K:bs=^H:kb=^H:kd=^Ay\r:kh=^A?\r:kl=^Aw\r:kr=^Az\r:ku=^Ax\r:\ :nl=5^J:so=^\H`:se=^\I`:sg=0:us=^\HP:ue=^\IP:ug=0:ce=^\Z:rv=\EH:re=\EI:\ :rg=0:GS=\Eo:GE=^O:GG=0:GV=-:GH=&:GU=%:GD=#:G1=(:G2= :G3=":G4=*:CF=\E]:\ :CO=\E\\:WL=^Aa\r:WR=^Ab\r:CL=^Ac\r:CR=^Ad\r:DL=^Ae\r:RF=^Af\r:\ :RC=^Ag\r:CW=^Ah\r:NU=^Aj\r:EN=^Ak\r:HM=^Al:PL=^Am\r:PU=^An\r:PD=^Ao\r:\ :PR=^Ap\r:HP=^A@\r:RT=^Aq\r:TB=\r:CN=\177:MP=\E+F: # basis from Peter Harrison, Computer Graphics Lab, San Francisco # ucbvax!ucsfmis!harrison ...uucp / ucbvax!ucsfmis!harrison@BERKELEY ...ARPA ba|basis|BASIS108 computer with terminal translation table active:\ :do=5000^J:nl=5000*^J:\ :cd=\EY:ce=\ET:cl=300\E*:ma=^K^P^R^L^L :\ :kb=^H:kl=^H:ku=^K:kr=^L:kd=^J:so=\E(:se=\E):tc=adm3a: # From Peter Harrison, Computer Graphics Lab, San Francisco # ucbvax!ucsfmis!harrison .....uucp # ucbvax!ucsfmis!harrison@BERKELEY .......ARPA # "These two work. If you don't have the inverse video chip for the # Apple with videx then remove the so and se fields." zO|DaleApple|Apple with videx videoterm 80 column board with inverse video:\ :do=^J:am:le=^H:bs:cd=^K:ce=^]:cl=300^L:cm=^^%r%+ %+ :co#80:ho=^Y:\ :kd=^J:kl=^H:kr=^U:kh=^Y:\ :li#24:nd=^\:pt:so=^Z3:se=^Z2:up=^_:xn: zJ|ibmaed|IBM Experimental display:\ :al=\EN:am:bs:cd=\EJ:ce=\EI:cl=\EH\EK:cm=\EY%+\40%+\40:co#80:\ :dc=\EQ:dl=\EO:do=\EB:ei=:ho=\EH:ic=\EP:im=:li#52:\ :nd=\EC:ms:so=\E0:se=\E0:us=:ue=:up=\EA:\ :kb=^h:ku=\EA:kd=\EB:kl=\ED:kr=\EC:eo:vb=\EG:pt: # funny terminal that the TANDEM uses. zA|653|t653x|Tandem 653x multipage terminal:\ :li#24:co#80:ho=\EH:cm=\023%+ %+ :cl=\EI:cd=\EJ:ce=\EK:am:bs:\ :if=/usr/lib/tabset/tandem653:sb=\ES:sr=\ET:da:db:so=\E6$:se=\E6 :\ :us=\E60:ue=\E6 :sg#1:ug#1:up=\EA:do=\012:le=\010:nd=\EC:\ :hs:ts=\Eo:fs=\r:ds=\Eo\r:ws#64: # From Paul Leondis, unllab@amber.berkeley.edu zB|ifmr|Informer D304:\ :am:bs:cd=\E/:ce=\EQ:cl=\EZ:cm=\EY%r%+ %+ :co#80:dc=\E\\:\ :do=^J:im=:ei=:ic=\E[:li#24:nd=\EC:so=\EJ:se=\EK:up=\EA:\ :sr=\En:ho=\EH: # # END OF TERMCAP # ------------------------ |IBM PC xenix color console display:\ :tc=ibm: zl|ibmcx|ibmcpcx|IBM PC xenix color console display:\ :tc=ibmx: zm|kaypro|kaypro2|kaypro II:\ :am:bs:cm=\E=%+ %+ :cl=1^Z:co#80:ho=^^:li#24:ma=^K^P:netc/termcap/reorder 444 0 12 1602 4027123510 7612 $r termcap.local /|c100|/;.,/^[^ ]/-m9 /|c100-rv|/;.,/^[^ ]/-m9 /|c100-rv-pp|/;.,/^[^ ]/-m9 /|c108-4p|/;.,/^[^ ]/-m9 /|c108-rv-4p|/;.,/^[^ ]/-m9 /|c108-8p|/;.,/^[^ ]/-m9 /|c108-rv-8p|/;.,/^[^ ]/-m9 /|avt|/;.,/^[^ ]/-m9 /|avt-rv|/;.,/^[^ ]/-m9 /|avt-4p-s|/;.,/^[^ ]/-m9 /|avt-8p-s|/;.,/^[^ ]/-m9 /|sun-17|/;.,/^[^ ]/-m9 /|sun-24|/;.,/^[^ ]/-m9 /|sun-34|/;.,/^[^ ]/-m9 /|sun-48|/;.,/^[^ ]/-m9 /|sun-s-e|/;.,/^[^ ]/-m9 /|sun-s|/;.,/^[^ ]/-m9 /|sun-e|/;.,/^[^ ]/-m9 /|sun|/;.,/^[^ ]/-m9 /|xterms|/;.,/^[^ ]/-m9 /|xterm|/;.,/^[^ ]/-m9 /|adm3|/;.,/^[^ ]/-m9 /|adm31|/;.,/^[^ ]/-m9 /|adm3a|/;.,/^[^ ]/-m9 /|vt100|/;.,/^[^ ]/-m9 /|vt220|/;.,/^[^ ]/-m9 /|2645|/;.,/^[^ ]/-m9 /|2621-nl|/;.,/^[^ ]/-m9 /|2621|/;.,/^[^ ]/-m9 /|h29|/;.,/^[^ ]/-m9 /|h19|/;.,/^[^ ]/-m9 /|h19-u|/;.,/^[^ ]/-m9 /|h19-us|/;.,/^[^ ]/-m9 /|h19-e|/;.,/^[^ ]/-m9 /|h19-g|/;.,/^[^ ]/-m9 /|5620|/;.,/^[^ ]/-m9 /^s/;.,/^#/-m9 w! termcap q :so=\E[2m:se=\E[m:us=\E[4m:ue=\E[m:mr=\E[7m:mb=\E[7;2m:me=\E[m: # The pcplot IBM-PC terminal emulation program is really mesetc/termcap/Makefile 444 0 12 1333 5520441377 7703 # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.2.1 (2.11BSD GTE) 1/23/94 # # reorder gives an editor command for most common terminals # (in reverse order from n'th to 1'st most commonly used) # to move them to the front of termcap # DESTDIR = termcap: reorder termcap.src ex - termcap.src < reorder install: termcap tabset install -m 444 termcap ${DESTDIR}/etc/termcap tabset: FRC rm -fr ${DESTDIR}/usr/lib/tabset mkdir ${DESTDIR}/usr/lib/tabset chmod 755 ${DESTDIR}/usr/lib/tabset install -c -m 444 tabset/* ${DESTDIR}/usr/lib/tabset clean: rm -f termcap FRC: m9 /|h19|/;.,/^[^ ]/-m9 /|h19-u|/;.,/^[^ ]/-m9 /|h19-us|/;.,/^[^ ]/-m9 /|h19-e|/;.,/^[^ ]/-m9 /|h19-g|/;.,/^[^ ]/-m9 /|5620|/;.,/^[^ ]/-m9 /^s/;.,/^#/-m9 w! termcap q :so=\E[2m:se=\E[m:us=\E[4m:ue=\E[m:mr=\E[7m:mb=\E[7;2m:me=\E[m: # The pcplot IBM-PC terminal emulation program is really mesetc/termcap/termcap.local 444 0 12 66 4027123316 10643 # # END OF LOCAL TERMCAP # -------------------------- ADME0N termcap.srcMreordersrLMakefilerK˜ termcap.localetc/dump/ 755 0 12 0 6024536025 5465 etc/dump/Makefile 644 0 0 2532 5671244616 7202 # sccsid = "@(#)Makefile 1.4 (2.11BSD GTE) 12/6/94" # # dump.h header file # dumpitime.c reads /etc/ddate # dumpmain.c driver # dumpoptr.c operator interface # dumptape.c handles the mag tape and opening/closing # dumptraverse.c traverses the file system # unctime.c undo ctime # # dumpdir.c program to output tape directories # # DEBUG use local directory to find ddate and dumpdates # TDEBUG trace out the process forking CFLAGS= -O -I. SEPFLAG=-i HDRS= dump.h SRCS= dumpitime.c dumpmain.c dumpoptr.c dumptape.c dumptraverse.c unctime.c \ dumprmt.c OBJS= dumpitime.o dumpmain.o dumpoptr.o dumptape.o dumptraverse.o unctime.o ROBJS= dumpitime.o dumprmain.o dumpoptr.o dumprtape.o dumptraverse.o \ unctime.o dumprmt.o all: dump rdump dumpdir dump: ${OBJS} cc ${CFLAGS} ${SEPFLAG} ${OBJS} -o dump rdump: ${ROBJS} cc ${CFLAGS} ${SEPFLAG} ${ROBJS} -o rdump dumpdir: dumpdir.c cc ${CFLAGS} ${SEPFLAG} dumpdir.c -o dumpdir install: all install -s dump ${DESTDIR}/etc/dump install -s rdump ${DESTDIR}/etc/rdump install -s dumpdir ${DESTDIR}/etc/dumpdir clean: rm -f *.o dump rdump dumpdir lint: lint -chabx ${CFLAGS} -DRDUMP ${SRCS} ${OBJS}: dump.h ${ROBJS}: dump.h dumprmain.o: dumpmain.c cc -c -DRDUMP ${CFLAGS} dumpmain.c mv dumpmain.o dumprmain.o dumprtape.o: dumptape.c cc -c -DRDUMP ${CFLAGS} dumptape.c mv dumptape.o dumprtape.o ,/^[^ ]/-m9 /^s/;.,/^#/-m9 w! termcap q :so=\E[2m:se=\E[m:us=\E[4m:ue=\E[m:mr=\E[7m:mb=\E[7;2m:me=\E[m: # The pcplot IBM-PC terminal emulation program is really mesetc/dump/dump.h 644 0 0 6523 5671246257 6667 /* * "@(#)dump.h 1.2 (2.11BSD GTE) 12/6/94" */ #define NI 4 /* number of blocks of inodes per read */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define MWORD(m,i) (m[(unsigned)(i-1)/MLEN]) #define MBIT(i) (1<<((unsigned)(i-1)%MLEN)) #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) #define BIT(i,w) (MWORD(w,i) & MBIT(i)) short clrmap[MSIZ]; short dirmap[MSIZ]; short nodmap[MSIZ]; /* * All calculations done in 0.1" units! */ char *disk; /* name of the disk file */ char *tape; /* name of the tape file */ char *increm; /* name of the file containing incremental information*/ char incno; /* increment number */ int uflag; /* update flag */ int fi; /* disk file descriptor */ int to; /* tape file descriptor */ int pipeout; /* true => output to standard output */ ino_t ino; /* current inumber; used globally */ int lastlevel; int nonodump; int nsubdir; int newtape; /* new tape flag */ int nadded; /* number of added sub directories */ int dadded; /* directory added flag */ u_short density; /* density in 0.1" units */ long tsize; /* tape size in 0.1" units */ long esize; /* estimated tape size, blocks */ long asize; /* number of 0.1" units written on current tape */ int etapes; /* estimated number of tapes */ int notify; /* notify operator flag */ long blockswritten; /* number of blocks written on current tape */ int tapeno; /* current tape number */ time_t tstart_writing; /* when started writing the first tape block */ time_t time(); off_t lseek(); char *ctime(); char *prdate(); long atol(); int mark(); int add(); int dump(); int tapsrec(); int dmpspc(); int dsrch(); int nullf(); char *rawname(); int interrupt(); /* in case operator bangs on console */ #define HOUR (60L*60L) #define DAY (24L*HOUR) #define YEAR (365L*DAY) /* * Exit status codes */ #define X_FINOK 1 /* normal exit */ #define X_REWRITE 2 /* restart writing from the check point */ #define X_ABORT 3 /* abort all of dump; don't attempt checkpointing*/ #ifdef DEBUG #define OINCREM "./ddate" /*old format incremental info*/ #define NINCREM "./dumpdates" /*new format incremental info*/ #else not DEBUG #define OINCREM "/etc/ddate" /*old format incremental info*/ #define NINCREM "/etc/dumpdates" /*new format incremental info*/ #endif #define TAPE "/dev/rmt8" /* default tape device */ #define DISK "/dev/rxp0a" /* default disk */ #define OPGRENT "operator" /* group entry to notify */ #define DIALUP "ttyd" /* prefix for dialups */ /* * The contents of the file NINCREM is maintained both on * a linked list, and then (eventually) arrayified. */ struct itime{ struct idates it_value; struct itime *it_next; }; struct itime *ithead; /* head of the list version */ int nidates; /* number of records (might be zero) */ int idates_in; /* we have read the increment file */ struct idates **idatev; /* the arrayfied version */ #define ITITERATE(i, ip) for (i = 0,ip = idatev[0]; i < nidates; i++, ip = idatev[i]) /* * We catch these interrupts */ int sighup(); int sigquit(); int sigill(); int sigtrap(); int sigfpe(); int sigkill(); int sigbus(); int sigsegv(); int sigsys(); int sigalrm(); int sigterm(); videoterm 80 column board with inverse video:\ :do=^J:am:le=^H:bs:cd=^K:ce=^]:cl=300^L:cm=^^%r%+ %+ :co#80:ho=^Y:\ :kd=^J:kl=^H:kr=^U:kh=^Y:\ :li#24:nd=^\:pt:so=^Z3:se=^etc/dump/dumpdir.c 644 0 0 22053 4617126013 7357 #include #include #include #include #include #include #include #ifdef NONSEPARATE #define MAXINO 1000 #else #define MAXINO 3000 #endif #define BITS 8 #define MAXXTR 60 #define MWORD(m,i) (m[(unsigned)(i-1)/MLEN]) #define MBIT(i) (1<<((unsigned)(i-1)%MLEN)) #define BIS(i,w) (MWORD(w,i) |= MBIT(i)) #define BIC(i,w) (MWORD(w,i) &= ~MBIT(i)) #define BIT(i,w) (MWORD(w,i) & MBIT(i)) int mt; char tapename[] = DEFTAPE; char *magtape = tapename; daddr_t seekpt; int ofile; FILE *df; char dirfile[] = "/tmp/rstXXXXXX"; #define ODIRSIZ 14 struct odirect { ino_t d_ino; char d_name[ODIRSIZ]; }; struct { ino_t t_ino; daddr_t t_seekpt; } inotab[MAXINO]; int ipos; #define ONTAPE 1 #define XTRACTD 2 #define XINUSE 4 short dumpmap[MSIZ]; short clrimap[MSIZ]; int bct = NTREC+1; char tbf[NTREC*DEV_BSIZE]; char prebuf[MAXPATHLEN]; DIR drblock; u_int prev; int volno, cvtflag; main(argc, argv) char *argv[]; { extern char *ctime(); mktemp(dirfile); argv++; if (argc>=3 && *argv[0] == 'f') magtape = *++argv; df = fopen(dirfile, "w"); if (df == NULL) { printf("dumpdir: %s - cannot create directory temporary\n", dirfile); exit(1); } if ((mt = open(magtape, 0)) < 0) { printf("%s: cannot open tape\n", magtape); exit(1); } if (readhdr(&spcl) == 0) { printf("Tape is not a dump tape\n"); exit(1); } printf("Dump date: %s", ctime(&spcl.c_date)); printf("Dumped from: %s", ctime(&spcl.c_ddate)); if (checkvol(&spcl, 1) == 0) { printf("Tape is not volume 1 of the dump\n"); exit(1); } pass1(); /* This sets the various maps on the way by */ freopen(dirfile, "r", df); strcpy(prebuf, "/"); printem(prebuf, (ino_t) ROOTINO); unlink(dirfile); exit(0); } /* * Read the tape, bulding up a directory structure for extraction * by name */ pass1() { register i; struct dinode *ip; int putdir(), null(); struct direct nulldir; while (gethead(&spcl) == 0) { printf("Can't find directory header!\n"); } nulldir.d_ino = 0; nulldir.d_namlen = 1; strcpy(nulldir.d_name, "/"); nulldir.d_reclen = DIRSIZ(&nulldir); for (;;) { if (checktype(&spcl, TS_BITS) == 1) { readbits(dumpmap); continue; } if (checktype(&spcl, TS_CLRI) == 1) { readbits(clrimap); continue; } if (checktype(&spcl, TS_INODE) == 0) { finish: fflush(df); close(mt); return; } ip = &spcl.c_dinode; i = ip->di_mode & IFMT; if (i != IFDIR) { goto finish; } inotab[ipos].t_ino = spcl.c_inumber; inotab[ipos++].t_seekpt = seekpt; getfile(spcl.c_inumber, putdir, null, spcl.c_dinode.di_size); putent(&nulldir); flushent(); } } printem(prefix, inum) char *prefix; ino_t inum; { register struct direct *dp; register int i; struct direct *rddir(); for (i = 0; i < MAXINO; i++) if (inotab[i].t_ino == inum) { goto found; } printf("PANIC - can't find directory %u\n", inum); return; found: fseek(df, inotab[i].t_seekpt, 0); drblock.dd_loc = 0; for (;;) { dp = rddir(); if (dp == NULL || dp->d_ino == 0) return; if (search((ino_t)dp->d_ino) && strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) { int len; off_t savpos; u_int savloc; savpos = ftell(df) - DIRBLKSIZ; savloc = drblock.dd_loc; len = strlen(prefix); strncat(prefix, dp->d_name, sizeof(dp->d_name)); strcat(prefix, "/"); printem(prefix, (ino_t)dp->d_ino); prefix[len] = '\0'; fseek(df, savpos, 0); fread(drblock.dd_buf, DIRBLKSIZ, 1, df); drblock.dd_loc = savloc; } else if (BIT(dp->d_ino, dumpmap)) printf("%5u %s%-.14s\n", (ino_t)dp->d_ino, prefix, dp->d_name); } } dcvt(odp, ndp) register struct odirect *odp; register struct direct *ndp; { bzero(ndp, sizeof (struct direct)); ndp->d_ino = odp->d_ino; strncpy(ndp->d_name, odp->d_name, ODIRSIZ); ndp->d_namlen = strlen(ndp->d_name); ndp->d_reclen = DIRSIZ(ndp); } /* * Do the file extraction, calling the supplied functions * with the blocks */ getfile(n, f1, f2, size) ino_t n; int (*f2)(), (*f1)(); long size; { register i; struct spcl addrblock; char buf[DEV_BSIZE]; addrblock = spcl; goto start; for (;;) { if (gethead(&addrblock) == 0) { printf("Missing address (header) block\n"); goto eloop; } if (checktype(&addrblock, TS_ADDR) == 0) { spcl = addrblock; return; } start: for (i = 0; i < addrblock.c_count; i++) { if (addrblock.c_addr[i]) { readtape(buf); (*f1)(buf, size > DEV_BSIZE ? (long) DEV_BSIZE : size); } else { bzero(buf, DEV_BSIZE); (*f2)(buf, size > DEV_BSIZE ? (long) DEV_BSIZE : size); } if ((size -= DEV_BSIZE) <= 0) { eloop: while (gethead(&spcl) == 0) ; if (checktype(&spcl, TS_ADDR) == 1) goto eloop; return; } } } } /* * Do the tape i\/o, dealling with volume changes * etc.. */ readtape(b) char *b; { register i; struct spcl tmpbuf; if (bct >= NTREC) { for (i = 0; i < NTREC; i++) ((struct spcl *)&tbf[i*DEV_BSIZE])->c_magic = 0; bct = 0; if ((i = read(mt, tbf, NTREC*DEV_BSIZE)) < 0) { exit(1); } if (i == 0) { bct = NTREC + 1; volno++; loop: bct = NTREC+1; close(mt); printf("Mount volume %d\n", volno); while (getchar() != '\n') ; if ((mt = open(magtape, 0)) == -1) { printf("Cannot open tape!\n"); } if (readhdr(&tmpbuf) == 0) { printf("Not a dump tape.Try again\n"); goto loop; } if (checkvol(&tmpbuf, volno) == 0) { printf("Wrong tape. Try again\n"); goto loop; } readtape(b); return; } } bcopy(&tbf[(bct++*DEV_BSIZE)], b, DEV_BSIZE); } putdir(b) char *b; { register struct direct *dp; struct direct cvtbuf; struct odirect *odp, *eodp; u_int loc; register int i; if (cvtflag) { eodp = (struct odirect *)&b[DEV_BSIZE]; for (odp = (struct odirect *)b; odp < eodp; odp++) { if (odp->d_ino) { dcvt(odp, &cvtbuf); putent(&cvtbuf); } } return; } for (loc = 0; loc < DEV_BSIZE; ) { dp = (struct direct *)(b + loc); i = DIRBLKSIZ - (loc & (DIRBLKSIZ - 1)); if (dp->d_reclen == 0 || dp->d_reclen > i) { loc += i; continue; } loc += dp->d_reclen; if (dp->d_ino) putent(dp); } } putent(dp) register struct direct *dp; { dp->d_reclen = DIRSIZ(dp); if (drblock.dd_loc + dp->d_reclen > DIRBLKSIZ) { ((struct direct *)(drblock.dd_buf + prev))->d_reclen = DIRBLKSIZ - prev; fwrite(drblock.dd_buf, DIRBLKSIZ, 1, df); drblock.dd_loc = 0; } bcopy(dp, drblock.dd_buf + drblock.dd_loc, dp->d_reclen); prev = drblock.dd_loc; drblock.dd_loc += dp->d_reclen; } flushent() { ((struct direct *)(drblock.dd_buf + prev))->d_reclen =DIRBLKSIZ - prev; fwrite(drblock.dd_buf, DIRBLKSIZ, 1, df); prev = drblock.dd_loc = 0; seekpt = ftell(df); } struct direct * rddir() { register struct direct *dp; for (;;) { if (drblock.dd_loc == 0) { drblock.dd_size = fread(drblock.dd_buf, 1,DIRBLKSIZ,df); if (drblock.dd_size <= 0) { printf("error reading directory\n"); return(NULL); } } if (drblock.dd_loc >= drblock.dd_size) { drblock.dd_loc = 0; continue; } dp = (struct direct *)(drblock.dd_buf + drblock.dd_loc); if (dp->d_reclen == 0 || dp->d_reclen > DIRBLKSIZ + 1 - drblock.dd_loc) { printf("corrupted directory: bad reclen %d\n", dp->d_reclen); return(NULL); } drblock.dd_loc += dp->d_reclen; if (dp->d_ino == 0 && strcmp(dp->d_name, "/")) continue; return(dp); } } /* * search the directory inode ino * looking for entry cp */ search(inum) ino_t inum; { register low, high, probe; low = 0; high = ipos-1; while (low != high) { probe = (high - low + 1)/2 + low; /* printf("low = %d, high = %d, probe = %d, ino = %d, inum = %d\n", low, high, probe, inum, inotab[probe].t_ino); */ if (inum >= inotab[probe].t_ino) low = probe; else high = probe - 1; } return(inum == inotab[low].t_ino); } /* * read the tape into buf, then return whether or * or not it is a header block. */ gethead(buf) struct spcl *buf; { readtape((char *)buf); return(ishead(buf)); } ishead(buf) register struct spcl *buf; { register int ret = 0; if (buf->c_magic == OFS_MAGIC) { if (cvtflag == 0) printf("Convert old direct format to new\n"); ret = cvtflag = 1; } else if (buf->c_magic == NFS_MAGIC) { if (cvtflag) printf("Was converting old direct format, not now\n"); cvtflag = 0; ret = 1; } if (ret == 0) return(ret); return(checksum((int *) buf)); } /* * return whether or not the buffer contains a header block */ checktype(b, t) struct spcl *b; int t; { return(b->c_type == t); } checksum(b) int *b; { register i, j; j = DEV_BSIZE/sizeof(int); i = 0; do i += *b++; while (--j); if (i != CHECKSUM) { printf("Checksum error %o\n", i); return(0); } return(1); } checkvol(b, t) struct spcl *b; int t; { if (b->c_volume == t) return(1); return(0); } readhdr(b) struct spcl *b; { if (gethead(b) == 0) return(0); if (checktype(b, TS_TAPE) == 0) return(0); return(1); } /* * read a bit mask from the tape into m. */ readbits(m) short *m; { register i; i = spcl.c_count; while (i--) { readtape((char *) m); m += (DEV_BSIZE/(MLEN/BITS)); } while (gethead(&spcl) == 0) ; } null() { ; } m Suk Lee ..!{decvax,linus,allegra,ihnp4}!utcsrgv!spoo zn|trs100|Radio Shack Model 100:\ :am:bs:le=^H:li#8:co#40:ku=^^:kd=^_:kl=^]:kr=^\:up=\EA:\ :nd=\EC:ho=\EH:ce=\EK:cd=\EJ:cl=\EE:xt:cm=\EY%+ %+ :\ :so=\Ep:se=\Eq:al=\EL:dl=\EM: zt|mac|macintosh|Macintosh with MacTerminal:\ :al=20\E[L:dl=20\E[M:ip=7:dc=7\E[P:ic=9\E[@:xn:dN#30:tc=vt100: zs|zen50|z50:zephyr:\ :cm=\E=%+ %+ :cd=\EY:co#80:li#24:\ :am:al=\EE:ce=\ET:dc=\EW:dl=\ER:ic=\EQ:im=:ei=:\ :cl=\E+:bs:ma=^Hhetc/dump/dumpitime.c 644 0 0 7347 5674204544 7713 #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)dumpitime.c 1.2 (2.11BSD GTE) 12/6/94"; #endif #include "dump.h" char *prdate(d) time_t d; { register char *p; if(d == 0) return("the epoch"); p = ctime(&d); p[24] = 0; return(p); } inititimes() { FILE *df; register int i; register struct itime *itwalk; if (idates_in) return; if ( (df = fopen(increm, "r")) == NULL){ nidates = 0; ithead = 0; } else { do{ itwalk=(struct itime *)calloc(1,sizeof (struct itime)); if (getrecord(df, &(itwalk->it_value)) < 0) break; nidates++; itwalk->it_next = ithead; ithead = itwalk; } while (1); fclose(df); } idates_in = 1; /* * arrayify the list, leaving enough room for the additional * record that we may have to add to the idate structure */ idatev = (struct idates **)calloc((unsigned)(nidates + 1), sizeof (struct idates *)); for (i = nidates-1, itwalk = ithead; i >= 0; i--, itwalk = itwalk->it_next) idatev[i] = &itwalk->it_value; } getitime() { register struct idates *ip; register int i; char *fname; fname = disk; #ifdef FDEBUG msg("Looking for name %s in increm = %s for delta = %c\n", fname, increm, incno); #endif spcl.c_ddate = 0; lastlevel = '0'; inititimes(); /* * Go find the entry with the same name for a lower increment * and older date */ ITITERATE(i, ip){ if(strncmp(fname, ip->id_name, sizeof (ip->id_name)) != 0) continue; if (ip->id_incno >= incno) continue; if (ip->id_ddate <= spcl.c_ddate) continue; spcl.c_ddate = ip->id_ddate; lastlevel = ip->id_incno; } } putitime() { FILE *df; register struct idates *itwalk; register int i; char *fname; if(uflag == 0) return; fname = disk; spcl.c_ddate = 0; ITITERATE(i, itwalk){ if (strncmp(fname, itwalk->id_name, sizeof (itwalk->id_name)) != 0) continue; if (itwalk->id_incno != incno) continue; goto found; } /* * construct the new upper bound; * Enough room has been allocated. */ itwalk = idatev[nidates] = (struct idates *)calloc(1, sizeof(struct idates)); nidates += 1; found: strncpy(itwalk->id_name, fname, sizeof (itwalk->id_name)); itwalk->id_incno = incno; itwalk->id_ddate = spcl.c_date; if ( (df = fopen(increm, "w")) == NULL){ msg("Cannot open %s\n", increm); dumpabort(); } ITITERATE(i, itwalk){ recout(df, itwalk); } fclose(df); msg("level %c dump on %s\n", incno, prdate(spcl.c_date)); } recout(file, what) FILE *file; struct idates *what; { fprintf(file, DUMPOUTFMT, what->id_name, what->id_incno, ctime(&(what->id_ddate)) ); } int recno; int getrecord(df, idatep) FILE *df; struct idates *idatep; { char buf[BUFSIZ]; recno = 0; if ( (fgets(buf, BUFSIZ, df)) != buf) return(-1); recno++; if (makeidate(idatep, buf) < 0) msg("Unknown intermediate format in %s, line %d\n", NINCREM, recno); #ifdef FDEBUG msg("getrecord: %s %c %s\n", idatep->id_name, idatep->id_incno, prdate(idatep->id_ddate)); #endif return(0); } time_t unctime(); int makeidate(ip, buf) struct idates *ip; char *buf; { char un_buf[128]; sscanf(buf, DUMPINFMT, ip->id_name, &ip->id_incno, un_buf); ip->id_ddate = unctime(un_buf); if (ip->id_ddate < 0) return(-1); return(0); } est(ip) struct dinode *ip; { long s; esize++; s = (ip->di_size + DEV_BSIZE-1) / DEV_BSIZE; esize += s; if(s > NADDR-3) { /* * This code is only appproximate. * it totally estimates low on doubly and triply indirect * files. */ s -= NADDR-3; s = ((s + DEV_BSIZE/sizeof(daddr_t))-1) / (DEV_BSIZE/sizeof(daddr_t)); esize += s; } } bmapest(map) short *map; { register i, n; n = -1; for(i=0; ic_type == t); } checksum(b) int *b; { register i, j; j = DEV_BSIZE/sizeof(int); i = 0; do i +=etc/dump/dumpmain.c 644 0 0 22311 5671243574 7537 #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)dumpmain.c 1.3 (2.11BSD GTE) 12/6/94"; #endif #include "dump.h" long blocksperfile; int cartridge = 0; static long numarg(); static void missingarg(); char *host = NULL; main(argc, argv) int argc; char *argv[]; { register char *cp; int i, Tflag = 0, honorlevel = 1, mapsize; register struct fstab *dt; density = 160; /* density in 0.1" units */ time(&(spcl.c_date)); tsize = 0; /* Default later, based on 'c' option for cart tapes */ tape = TAPE; increm = NINCREM; incno = '0'; if (argc == 1) { (void) fprintf(stderr, "Must specify a key.\n"); Exit(X_ABORT); } argv++; argc -= 2; for (cp = *argv++; *cp; cp++) { switch (*cp) { case '-': break; case 'w': lastdump('w'); /* tell us only what has to be done */ exit(0); break; case 'W': /* what to do */ lastdump('W'); /* tell us state of what is done */ exit(0); /* do nothing else */ case 'f': /* output file */ if (argc < 1) missingarg('f', "output file"); tape = *argv++; argc--; break; case 'd': /* density, in bits per inch */ density = numarg('d', "density", 10L, 327670L, &argc, &argv) / 10; break; case 's': /* tape size, feet */ tsize = numarg('s', "size", 1L, 0L, &argc, &argv) * 12 * 10; break; case 'T': /* time of last dump */ if (argc < 1) missingarg('T', "time of last dump"); spcl.c_ddate = unctime(*argv); if (spcl.c_ddate < 0) { (void)fprintf(stderr, "bad time \"%s\"\n", *argv); exit(X_ABORT); } Tflag = 1; lastlevel = '?'; argc--; argv++; break; #ifdef notnow case 'b': /* blocks per tape write */ ntrec = numarg('b', "number of blocks per write", 1L, 1000L, &argc, &argv); break; #endif case 'B': /* blocks per output file */ blocksperfile = numarg('B', "number of blocks per file", 1L, 0L, &argc, &argv); break; case 'c': /* Tape is cart. not 9-track */ cartridge = 1; break; /* dump level */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': incno = *cp; break; case 'u': /* update /etc/dumpdates */ uflag++; break; case 'n': /* notify operators */ notify++; break; case 'h': honorlevel = numarg('h', "honor level", 0L, 10L, &argc, &argv); break; default: fprintf(stderr, "bad key '%c%'\n", *cp); exit(X_ABORT); } } if (argc < 1) { (void)fprintf(stderr, "Must specify disk or filesystem\n"); exit(X_ABORT); } disk = *argv++; argc--; if (argc >= 1) { (void)fprintf(stderr, "Unknown arguments to dump:"); while (argc--) (void)fprintf(stderr, " %s", *argv++); (void)fprintf(stderr, "\n"); exit(X_ABORT); } if (Tflag && uflag) { (void)fprintf(stderr, "You cannot use the T and u flags together.\n"); exit(X_ABORT); } if (strcmp(tape, "-") == 0) { pipeout++; tape = "standard output"; } if (blocksperfile) blocksperfile = blocksperfile / NTREC * NTREC; /* round down */ else { /* * Determine how to default tape size and density * * density tape size * 9-track 1600 bpi (160 bytes/.1") 2300 ft. * 9-track 6250 bpi (625 bytes/.1") 2300 ft. * cartridge 8000 bpi (100 bytes/.1") 1700 ft. * (450*4 - slop) */ if (density == 0) density = cartridge ? 100 : 160; if (tsize == 0) tsize = cartridge ? 1700L*120L : 2300L*120L; } if (index(tape, ':')) { host = tape; tape = index(host, ':'); *tape++ = '\0'; #ifdef RDUMP if (rmthost(host) == 0) exit(X_ABORT); #else (void)fprintf(stderr, "remote dump not enabled\n"); exit(X_ABORT); #endif } (void)setuid(getuid()); /* rmthost() is the only reason to be setuid */ if (signal(SIGHUP, sighup) == SIG_IGN) signal(SIGHUP, SIG_IGN); if (signal(SIGTRAP, sigtrap) == SIG_IGN) signal(SIGTRAP, SIG_IGN); if (signal(SIGFPE, sigfpe) == SIG_IGN) signal(SIGFPE, SIG_IGN); if (signal(SIGBUS, sigbus) == SIG_IGN) signal(SIGBUS, SIG_IGN); if (signal(SIGSEGV, sigsegv) == SIG_IGN) signal(SIGSEGV, SIG_IGN); if (signal(SIGTERM, sigterm) == SIG_IGN) signal(SIGTERM, SIG_IGN); if (signal(SIGINT, interrupt) == SIG_IGN) signal(SIGINT, SIG_IGN); set_operators(); /* /etc/group snarfed */ /* * disk can be either the character or block special file name, * or the full file system path name. */ if (dt = getfsfile(disk)) disk = rawname(dt->fs_spec); else if (dt = getfsspec(disk)) disk = rawname(disk); else dt = getfsspec(deraw(disk)); if (!Tflag) getitime(); /* /etc/dumpdates snarfed */ msg("Date of this level %c dump: %s\n", incno, prdate(spcl.c_date)); msg("Date of last level %c dump: %s\n", lastlevel, prdate(spcl.c_ddate)); msg("Dumping %s ", disk); if (dt != 0) msgtail("(%s) ", dt->fs_file); if (host) msgtail("to %s on host %s\n", tape, host); else msgtail("to %s\n", tape); fi = open(disk, 0); if (fi < 0) { msg("Cannot open %s\n", disk); Exit(X_ABORT); } bzero(clrmap, sizeof (clrmap)); bzero(dirmap, sizeof (dirmap)); bzero(nodmap, sizeof (nodmap)); mapsize = roundup(howmany(sizeof(dirmap),NBBY), DEV_BSIZE); esize = 0; nonodump = (incno - '0') < honorlevel; msg("mapping (Pass I) [regular files]\n"); pass(mark, (short *)NULL); /* mark updates esize */ do { msg("mapping (Pass II) [directories]\n"); nadded = 0; pass(add, dirmap); } while(nadded); bmapest(clrmap); bmapest(nodmap); if (pipeout) { esize += 10; /* 10 trailer blocks */ msg("estimated %ld tape blocks.\n", esize); } else { double fetapes; if (blocksperfile) fetapes = (double) esize / blocksperfile; else if (cartridge) { /* Estimate number of tapes, assuming streaming stops at the end of each block written, and not in mid-block. Assume no erroneous blocks; this can be compensated for with an artificially low tape size. */ fetapes = ( esize /* blocks */ * DEV_BSIZE /* bytes/block */ * (1.0/density) /* 0.1" / byte */ + esize /* blocks */ * (1.0/NTREC) /* streaming-stops per block */ * 15.48 /* 0.1" / streaming-stop */ ) * (1.0 / tsize ); /* tape / 0.1" */ } else { /* Estimate number of tapes, for old fashioned 9-track tape */ int tenthsperirg = (density == 625) ? 3 : 7; fetapes = ( esize /* blocks */ * DEV_BSIZE /* bytes / block */ * (1.0/density) /* 0.1" / byte */ + esize /* blocks */ * (1.0/NTREC) /* IRG's / block */ * tenthsperirg /* 0.1" / IRG */ ) * (1.0 / tsize ); /* tape / 0.1" */ } etapes = fetapes; /* truncating assignment */ etapes++; /* count the dumped inodes map on each additional tape */ esize += (etapes - 1) * (howmany(mapsize * sizeof(char), DEV_BSIZE) + 1); esize += etapes + 10; /* headers + 10 trailer blks */ msg("estimated %ld tape blocks on %3.2f tape(s).\n", esize, fetapes); } alloctape(); /* Allocate tape buffer */ otape(); /* bitmap is the first to tape write */ time(&(tstart_writing)); bitmap(clrmap, TS_CLRI); msg("dumping (Pass III) [directories]\n"); pass(dump, dirmap); msg("dumping (Pass IV) [regular files]\n"); pass(dump, nodmap); spcl.c_type = TS_END; for(i=0; i vmax)) goto bad; return (val); bad: (void)fprintf(stderr, "bad '%c' (%s) value \"%s\"\n", letter, meaning, str); exit(X_ABORT); /* NOTREACHED */ } static void missingarg(letter, meaning) int letter; char *meaning; { (void)fprintf(stderr, "The '%c' flag (%s) requires an argument\n", letter, meaning); exit(X_ABORT); } int sighup(){ msg("SIGHUP() try rewriting\n"); sigAbort();} int sigtrap(){ msg("SIGTRAP() try rewriting\n"); sigAbort();} int sigfpe(){ msg("SIGFPE() try rewriting\n"); sigAbort();} int sigbus(){ msg("SIGBUS() try rewriting\n"); sigAbort();} int sigsegv(){ msg("SIGSEGV() ABORTING!\n"); abort();} int sigalrm(){ msg("SIGALRM() try rewriting\n"); sigAbort();} int sigterm(){ msg("SIGTERM() try rewriting\n"); sigAbort();} sigAbort() { if (pipeout) { msg("Unknown signal, cannot recover\n"); dumpabort(); } msg("Rewriting attempted as response to unknown signal.\n"); fflush(stderr); fflush(stdout); close_rewind(); exit(X_REWRITE); } char *rawname(cp) char *cp; { static char rawbuf[32]; char *dp = rindex(cp, '/'); if (dp == 0) return ((char *) 0); *dp = '\0'; strcpy(rawbuf, cp); *dp++ = '/'; strcat(rawbuf, "/r"); strcat(rawbuf, dp); return (rawbuf); } char *deraw(cp) char *cp; { static char rawbuf[32]; register char *dp; register char *tp; strcpy(rawbuf, cp); dp = rindex(rawbuf, '/'); if (dp++ == 0) return((char *) 0); tp = dp++; while (*tp++ = *dp++); return(rawbuf); } ot use am: because autowrap mode lost when kermit dropped and restarted. # Reverse video for standout like H19. K4|msk227|mskermit227|MS-DOS Kermit 2.27 for the IBMPC:\ :al=\EL:am@:bs:cd=\EJ:ce=\EK:cl=\EE:cm=\EY%+ %+ :co#80:\ :dc=\EN:dl=\EM:do=\EB:ei=\EO:im=\E@:\ :ho=\EH:li#24:nd=\EC:up=\EA:pt:rc=\Ek:sc=\Ejetc/dump/dumpoptr.c 644 0 0 15262 5674205720 7600 #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)dumpoptr.c 1.5 (2.11BSD GTE) 12/6/94"; #endif #include "dump.h" struct group *getgrnam(); /* * Query the operator; This fascist piece of code requires * an exact response. * It is intended to protect dump aborting by inquisitive * people banging on the console terminal to see what is * happening which might cause dump to croak, destroying * a large number of hours of work. * * Every 2 minutes we reprint the message, alerting others * that dump needs attention. */ int timeout; char *attnmessage; /* attemtion message */ query(question) char *question; { char replybuffer[64]; int back; FILE *mytty; if ( (mytty = fopen("/dev/tty", "r")) == NULL){ msg("fopen on /dev/tty fails\n"); abort(); } attnmessage = question; timeout = 0; alarmcatch(); for(;;){ if ( fgets(replybuffer, 63, mytty) == NULL){ if (ferror(mytty)){ clearerr(mytty); continue; } } else if ( (strcmp(replybuffer, "yes\n") == 0) || (strcmp(replybuffer, "Yes\n") == 0)){ back = 1; goto done; } else if ( (strcmp(replybuffer, "no\n") == 0) || (strcmp(replybuffer, "No\n") == 0)){ back = 0; goto done; } else { msg("\"Yes\" or \"No\"?\n"); alarmcatch(); } } done: /* * Turn off the alarm, and reset the signal to trap out.. */ alarm(0); if (signal(SIGALRM, sigalrm) == SIG_IGN) signal(SIGALRM, SIG_IGN); fclose(mytty); return(back); } /* * Alert the console operator, and enable the alarm clock to * sleep for 2 minutes in case nobody comes to satisfy dump */ alarmcatch() { if (timeout) msgtail("\n"); msg("NEEDS ATTENTION: %s: (\"yes\" or \"no\") ", attnmessage); signal(SIGALRM, alarmcatch); alarm(120); timeout = 1; } /* * Here if an inquisitive operator interrupts the dump program */ interrupt() { msg("Interrupt received.\n"); if (query("Do you want to abort dump?")) dumpabort(); signal(SIGINT, interrupt); } /* * The following variables and routines manage alerting * operators to the status of dump. * This works much like wall(1) does. */ struct group *gp; /* * Get the names from the group entry "operator" to notify. */ set_operators() { if (!notify) /*not going to notify*/ return; gp = getgrnam(OPGRENT); endgrent(); if (gp == (struct group *)0){ msg("No entry in /etc/group for %s.\n", OPGRENT); notify = 0; return; } } struct tm *localtime(); struct tm *localclock; /* * We fork a child to do the actual broadcasting, so * that the process control groups are not messed up */ broadcast(message) char *message; { time_t clock; FILE *f_utmp; struct utmp utmp; char **np; int pid, s; switch (pid = fork()) { case -1: return; case 0: break; default: while (wait(&s) != pid) continue; return; } if (!notify || gp == 0) exit(0); clock = time((time_t *)0); localclock = localtime(&clock); if((f_utmp = fopen("/etc/utmp", "r")) == NULL) { msg("Cannot open /etc/utmp\n"); return; } while (!feof(f_utmp)){ if (fread((char *)&utmp, sizeof (struct utmp), 1, f_utmp) != 1) break; if (utmp.ut_name[0] == 0) continue; for (np = gp->gr_mem; *np; np++){ if (strncmp(*np, utmp.ut_name, sizeof(utmp.ut_name)) != 0) continue; /* * Do not send messages to operators on dialups */ if (strncmp(utmp.ut_line, DIALUP, strlen(DIALUP)) == 0) continue; #ifdef DEBUG msg("Message to %s at %s\n", utmp.ut_name, utmp.ut_line); #endif DEBUG sendmes(utmp.ut_line, message); } } fclose(f_utmp); Exit(0); /* the wait in this same routine will catch this */ /* NOTREACHED */ } sendmes(tty, message) char *tty, *message; { char t[50], buf[BUFSIZ]; register char *cp; register int c; int ch, msize; register FILE *f_tty; msize = strlen(message); strcpy(t, "/dev/"); strcat(t, tty); if((f_tty = fopen(t, "w")) != NULL) { setbuf(f_tty, buf); fprintf(f_tty, "\n\007\007\007Message from the dump program to all operators at %d:%02d ...\r\n\n" ,localclock->tm_hour ,localclock->tm_min); for (cp = message, c = msize; c-- > 0; cp++) { ch = *cp; if (ch == '\n') putc('\r', f_tty); putc(ch, f_tty); } fclose(f_tty); } } /* * print out an estimate of the amount of time left to do the dump */ time_t tschedule = 0; timeest() { time_t tnow, deltat; long pleft; char buf[BUFSIZ]; time (&tnow); if (tnow >= tschedule){ tschedule = tnow + 300; if (blockswritten < 500L) return; /* / \ |/ estimated blocks \ | delta time = ||---------------- | X time so far | - time so far |\ blocks thus far / | \ / */ pleft = ((100 * esize)/blockswritten) - 100; deltat = (time_t) (tnow - tstart_writing) * pleft; deltat = deltat/100; /* scale back down */ sprintf(buf,"%3.2f%%%% done, finished in %d:%02d\n", (float) (blockswritten*100.0)/esize, (int)(deltat/3600L), (int)((deltat%3600L)/60L)); msg(buf); } } /* VARARGS1 */ /* ARGSUSED */ msg(fmt, a1, a2, a3, a4, a5) char *fmt; { fprintf(stderr," DUMP: "); #ifdef TDEBUG fprintf(stderr,"pid=%d ", getpid()); #endif fprintf(stderr, fmt, a1, a2, a3, a4, a5); fflush(stdout); fflush(stderr); } /* VARARGS1 */ /* ARGSUSED */ msgtail(fmt, a1, a2, a3, a4, a5) char *fmt; { fprintf(stderr, fmt, a1, a2, a3, a4, a5); } /* * Tell the operator what has to be done. */ lastdump(arg) char arg; /* w ==> just what to do; W ==> most recent dumps */ { char *lastname; char *date; register int i; time_t tnow; register struct fstab *dt; int dumpme; register struct idates *itwalk; int idatesort(); time(&tnow); inititimes(); /* /etc/dumpdates input */ qsort(idatev, nidates, sizeof(struct idates *), idatesort); if (arg == 'w') fprintf(stdout, "Dump these file systems:\n"); else fprintf(stdout, "Last dump(s) done (Dump '>' file systems):\n"); lastname = "??"; ITITERATE(i, itwalk){ if (strncmp(lastname, itwalk->id_name, sizeof(itwalk->id_name)) == 0) continue; date = (char *)ctime(&itwalk->id_ddate); date[16] = '\0'; /* blast away seconds and year */ lastname = itwalk->id_name; dt = getfsspec(deraw(itwalk->id_name)); dumpme = ( (dt != 0) && (dt->fs_freq != 0) && (itwalk->id_ddate < tnow - (dt->fs_freq*DAY))); if ( (arg != 'w') || dumpme) fprintf(stdout,"%c %8s\t(%6s) Last dump: Level %c, Date %s\n", dumpme && (arg != 'w') ? '>' : ' ', itwalk->id_name, dt ? dt->fs_file : 0, itwalk->id_incno, date ); } } int idatesort(p1, p2) struct idates **p1, **p2; { int diff; diff = strncmp((*p1)->id_name, (*p2)->id_name, sizeof((*p1)->id_name)); if (diff == 0) if ((*p2)->id_ddate > (*p1)->id_ddate) return (1); else if ((*p2)->id_ddate == (*p1)->id_ddate) return (0); else return (-1); else return (diff); } + 10 trailer blks */ msg("estimated %ld tape blocks on %3.2f tape(s).\n", esize, fetapes); } alloctape(); /* Allocate tape buffer */ otape(); /* bitmap is the first to tape write */ time(&(tstart_writing)); bitmap(clrmap, TS_CLRI); msg("dumping (Pass III) [directories]\n"); pass(dump, dirmap); msg("dumping (Petc/dump/dumptape.c 644 0 0 26341 5344265462 7550 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)dumptape.c 5.5 (Berkeley) 5/23/86"; #endif #include #include "dump.h" char (*tblock)[DEV_BSIZE]; /* Pointer to malloc()ed buffer for tape */ #define writesize (NTREC * DEV_BSIZE) /* Size of malloc()ed buffer for tape */ int trecno = 0; #ifdef RDUMP extern char *host; int rmtopen(), rmtwrite(); void rmtclose(); #endif RDUMP extern int read(), write(); /* * Concurrent dump mods (Caltech) - disk block reading and tape writing * are exported to several slave processes. While one slave writes the * tape, the others read disk blocks; they pass control of the tape in * a ring via flock(). The parent process traverses the filesystem and * sends spclrec()'s and lists of daddr's to the slaves via pipes. */ struct req { /* instruction packets sent to slaves */ daddr_t dblk; int count; } *req; #define reqsiz (NTREC * sizeof (struct req)) /* * this is allocated here becaue malloc can all too easily fail later on. * IF anymore functionality is added to 'dump' then the bitmaps will have * to be moved to a file and paged. */ char ___xxx[reqsiz + writesize]; #define SLAVES 3 /* 1 slave writing, 1 reading, 1 for slack */ int slavefd[SLAVES]; /* pipes from master to each slave */ int slavepid[SLAVES]; /* used by killall() */ int rotor; /* next slave to be instructed */ int master; /* pid of master, for sending error signals */ u_int tenths; /* length of tape used per block written */ alloctape() { /* * CDC 92181's and 92185's make 0.8" gaps in 1600-bpi start/stop mode * (see DEC TU80 User's Guide). The shorter gaps of 6250-bpi require * repositioning after stopping, i.e, streaming mode, where the gap is * variable, 0.30" to 0.45". The gap is maximal when the tape stops. */ tenths = writesize/density + (density == 625 ? 5 : 8); /* * Allocate tape buffer contiguous with the array of instruction * packets, so flusht() can write them together with one write(). */ req = (struct req *)___xxx; if (req == NULL) return(0); tblock = (char (*)[DEV_BSIZE]) &req[NTREC]; req = (struct req *)tblock - NTREC; return(1); } taprec(dp) char *dp; { req[trecno].dblk = (daddr_t)0; req[trecno].count = 1; bcopy(dp, tblock, DEV_BSIZE); tblock++; /* *(union u_spcl *)(*tblock++) = *(union u_spcl *)dp; /* movc3 */ trecno++; spcl.c_tapea++; if(trecno >= NTREC) flusht(); } tapsrec(blkno) daddr_t blkno; { if (blkno == 0) return; req[trecno].dblk = blkno; req[trecno].count = 1; trecno++; spcl.c_tapea++; if (trecno >= NTREC) flusht(); } int nogripe = 0; tperror() { if (pipeout) { msg("Tape write error on %s\n", tape); msg("Cannot recover\n"); dumpabort(); /* NOTREACHED */ } msg("Tape write error %ld feet into tape %d\n", asize/120L, tapeno); broadcast("TAPE ERROR!\n"); if (!query("Do you want to restart?")) dumpabort(); msg("This tape will rewind. After it is rewound,\n"); msg("replace the faulty tape with a new one;\n"); msg("this dump volume will be rewritten.\n"); killall(); nogripe = 1; close_rewind(); Exit(X_REWRITE); } sigpipe() { msg("Broken pipe\n"); dumpabort(); } flusht() { int siz = (char *)tblock - (char *)req; if (atomic(write, slavefd[rotor], req, siz) != siz) { perror(" DUMP: error writing command pipe"); dumpabort(); } if (++rotor >= SLAVES) rotor = 0; tblock = (char (*)[DEV_BSIZE]) &req[NTREC]; trecno = 0; asize += tenths; blockswritten += NTREC; if (!pipeout && asize > tsize) { close_rewind(); otape(); } timeest(); } rewind() { int f; if (pipeout) return; for (f = 0; f < SLAVES; f++) close(slavefd[f]); while (wait(NULL) >= 0) ; /* wait for any signals from slaves */ msg("Closing %s\n", tape); #ifdef RDUMP if (host) { rmtclose(); while (rmtopen(tape, 0) < 0) sleep(10); rmtclose(); return; } #endif RDUMP close(to); while ((f = open(tape, 0)) < 0) sleep (10); close(f); } close_rewind() { rewind(); if (!nogripe) { msg("Change Tapes: Mount tape #%d\n", tapeno+1); broadcast("CHANGE TAPES!\7\7\n"); } while (!query("Is the new tape mounted and ready to go?")) if (query("Do you want to abort?")) { dumpabort(); /*NOTREACHED*/ } } /* * We implement taking and restoring checkpoints on the tape level. * When each tape is opened, a new process is created by forking; this * saves all of the necessary context in the parent. The child * continues the dump; the parent waits around, saving the context. * If the child returns X_REWRITE, then it had problems writing that tape; * this causes the parent to fork again, duplicating the context, and * everything continues as if nothing had happened. */ otape() { int parentpid; int childpid; int status; int waitpid; int (*interrupt)() = signal(SIGINT, SIG_IGN); parentpid = getpid(); restore_check_point: signal(SIGINT, interrupt); /* * All signals are inherited... */ childpid = fork(); if (childpid < 0) { msg("Context save fork fails in parent %d\n", parentpid); Exit(X_ABORT); } if (childpid != 0) { /* * PARENT: * save the context by waiting * until the child doing all of the work returns. * don't catch the interrupt */ signal(SIGINT, SIG_IGN); #ifdef TDEBUG msg("Tape: %d; parent process: %d child process %d\n", tapeno+1, parentpid, childpid); #endif TDEBUG while ((waitpid = wait(&status)) != childpid) msg("Parent %d waiting for child %d has another child %d return\n", parentpid, childpid, waitpid); if (status & 0xFF) { msg("Child %d returns LOB status %o\n", childpid, status&0xFF); } status = (status >> 8) & 0xFF; #ifdef TDEBUG switch(status) { case X_FINOK: msg("Child %d finishes X_FINOK\n", childpid); break; case X_ABORT: msg("Child %d finishes X_ABORT\n", childpid); break; case X_REWRITE: msg("Child %d finishes X_REWRITE\n", childpid); break; default: msg("Child %d finishes unknown %d\n", childpid, status); break; } #endif TDEBUG switch(status) { case X_FINOK: Exit(X_FINOK); case X_ABORT: Exit(X_ABORT); case X_REWRITE: goto restore_check_point; default: msg("Bad return code from dump: %d\n", status); Exit(X_ABORT); } /*NOTREACHED*/ } else { /* we are the child; just continue */ #ifdef TDEBUG sleep(4); /* allow time for parent's message to get out */ msg("Child on Tape %d has parent %d, my pid = %d\n", tapeno+1, parentpid, getpid()); #endif TDEBUG #ifdef RDUMP while ((to = (host ? rmtopen(tape, 2) : pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666))) < 0) #else RDUMP while ((to = pipeout ? 1 : open(tape, O_WRONLY|O_CREAT, 0666)) < 0) #endif RDUMP { msg("Cannot open output \"%s\".\n", tape); if (!query("Do you want to retry the open?")) dumpabort(); } enslave(); /* Share open tape file descriptor with slaves */ asize = 0; tapeno++; /* current tape sequence */ newtape++; /* new tape signal */ spcl.c_volume++; spcl.c_type = TS_TAPE; spclrec(); if (tapeno > 1) msg("Tape %d begins with blocks from ino %d\n", tapeno, ino); } } dumpabort() { if (master != 0 && master != getpid()) kill(master, SIGTERM); /* Signals master to call dumpabort */ else { killall(); msg("The ENTIRE dump is aborted.\n"); } Exit(X_ABORT); } Exit(status) { #ifdef TDEBUG msg("pid = %d exits with status %d\n", getpid(), status); #endif TDEBUG exit(status); } /* * could use pipe() for this if flock() worked on pipes */ lockfile(fd) int fd[2]; { char tmpname[20]; strcpy(tmpname, "/tmp/dumplockXXXXXX"); mktemp(tmpname); if ((fd[1] = creat(tmpname, 0400)) < 0) { msg("Could not create lockfile "); perror(tmpname); dumpabort(); } if ((fd[0] = open(tmpname, 0)) < 0) { msg("Could not reopen lockfile "); perror(tmpname); dumpabort(); } unlink(tmpname); } enslave() { int first[2], prev[2], next[2], cmd[2]; /* file descriptors */ register int i, j; master = getpid(); signal(SIGTERM, dumpabort); /* Slave sends SIGTERM on dumpabort() */ signal(SIGPIPE, sigpipe); signal(SIGUSR1, tperror); /* Slave sends SIGUSR1 on tape errors */ lockfile(first); for (i = 0; i < SLAVES; i++) { if (i == 0) { prev[0] = first[1]; prev[1] = first[0]; } else { prev[0] = next[0]; prev[1] = next[1]; flock(prev[1], LOCK_EX); } if (i < SLAVES - 1) { lockfile(next); } else { next[0] = first[0]; next[1] = first[1]; /* Last slave loops back */ } if (pipe(cmd) < 0 || (slavepid[i] = fork()) < 0) { msg("too many slaves, %d (recompile smaller) ", i); perror(""); dumpabort(); } slavefd[i] = cmd[1]; if (slavepid[i] == 0) { /* Slave starts up here */ for (j = 0; j <= i; j++) close(slavefd[j]); signal(SIGINT, SIG_IGN); /* Master handles this */ doslave(cmd[0], prev, next); Exit(X_FINOK); } close(cmd[0]); if (i > 0) { close(prev[0]); close(prev[1]); } } close(first[0]); close(first[1]); master = 0; rotor = 0; } killall() { register int i; for (i = 0; i < SLAVES; i++) if (slavepid[i] > 0) kill(slavepid[i], SIGKILL); } /* * Synchronization - each process has a lockfile, and shares file * descriptors to the following process's lockfile. When our write * completes, we release our lock on the following process's lock- * file, allowing the following process to lock it and proceed. We * get the lock back for the next cycle by swapping descriptors. */ doslave(cmd, prev, next) register int cmd, prev[2], next[2]; { register int nread, toggle = 0; int nwrite; close(fi); if ((fi = open(disk, 0)) < 0) { /* Need our own seek pointer */ perror(" DUMP: slave couldn't reopen disk"); dumpabort(); } /* * Get list of blocks to dump, read the blocks into tape buffer */ while ((nread = atomic(read, cmd, req, reqsiz)) == reqsiz) { register struct req *p = req; for (trecno = 0; trecno < NTREC; trecno += p->count, p += p->count) { if (p->dblk) { bread(p->dblk, tblock[trecno], p->count * DEV_BSIZE); } else { if (p->count != 1 || atomic(read, cmd, tblock[trecno], DEV_BSIZE) != DEV_BSIZE) { msg("Master/slave protocol botched.\n"); dumpabort(); } } } flock(prev[toggle], LOCK_EX); /* Wait our turn */ #ifdef RDUMP if ((nwrite = (host ? rmtwrite(tblock[0], writesize) : write(to, tblock[0], writesize))) != writesize) { #else RDUMP if ((nwrite = write(to, tblock[0], writesize)) != writesize) { #endif RDUMP if (nwrite == -1) perror("write"); else msg("short write: got %d instead of %d\n", nwrite, writesize); kill(master, SIGUSR1); for (;;) sigpause(0L); } toggle ^= 1; flock(next[toggle], LOCK_UN); /* Next slave's turn */ } /* Also jolts him awake */ if (nread != 0) { perror(" DUMP: error reading command pipe"); dumpabort(); } } /* * Since a read from a pipe may not return all we asked for, * or a write may not write all we ask if we get a signal, * loop until the count is satisfied (or error). */ atomic(func, fd, buf, count) int (*func)(), fd, count; char *buf; { int got, need = count; while ((got = (*func)(fd, buf, need)) > 0 && (need -= got) > 0) buf += got; return (got < 0 ? got : count - need); } _REWRITE); } char *rawname(cp) char *cp; { static char rawbuf[32]; char *dp = rindex(cp, '/'); if (dp == 0) return ((char *) 0); *dp = '\0'; strcpy(rawbuf, cp); *dp++ = '/'; strcat(rawbuf, "/r"); strcat(rawbuf, dp); return (rawbuf); } char *deraw(cp) char *cp; { static etc/dump/dumptraverse.c 644 0 0 11342 5671232710 10436 #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)dumptraverse.c 1.2 (2.11BSD GTE) 12/6/94"; #endif #include "dump.h" struct fs sblock; /* disk block */ struct dinode itab[INOPB * NI]; pass(fn, map) int (*fn)(); short *map; { register i, j; int bits; ino_t mino; daddr_t d; sync(); bread((daddr_t)1, (char *)&sblock, sizeof(sblock)); mino = (sblock.fs_isize-2) * INOPB; ino = 0; for(i=2;; i+=NI) { if(ino >= mino) break; d = (unsigned)i; for(j=0; j= mino) break; if((ino % MLEN) == 0) { bits = ~0; if(map != NULL) bits = *map++; } ino++; if(bits & 1) { if(d != 0) { bread(d, (char *)itab, sizeof(itab)); d = 0; } (*fn)(&itab[j]); } bits >>= 1; } } } icat(ip, fn1, fn2) struct dinode *ip; int (*fn1)(), (*fn2)(); { register i; (*fn2)(ip->di_addr, NADDR-3); for(i=0; idi_addr[i] != 0) { if(i < NADDR-3) (*fn1)(ip->di_addr[i]); else indir(ip->di_addr[i], fn1, fn2, i-(NADDR-3)); } } } indir(d, fn1, fn2, n) daddr_t d; int (*fn1)(), (*fn2)(); { register i; daddr_t idblk[NINDIR]; bread(d, (char *)idblk, sizeof(idblk)); if(n <= 0) { spcl.c_type = TS_ADDR; (*fn2)(idblk, NINDIR); for(i=0; idi_mtime >= (t) || (dp)->di_ctime >= (t)) #define WANTTODUMP(dp) (CHANGEDSINCE(dp,spcl.c_ddate) && \ (nonodump || (dp->di_flags & UF_NODUMP) != UF_NODUMP)) mark(ip) register struct dinode *ip; { register f; f = ip->di_mode & IFMT; if(f == 0) return; BIS(ino, clrmap); if(f == IFDIR) BIS(ino, dirmap); if (WANTTODUMP(ip)) { BIS(ino, nodmap); if (f != IFREG && f != IFDIR && f != IFLNK){ esize++; return; } est(ip); } } add(ip) struct dinode *ip; { if(BIT(ino, nodmap)) return; nsubdir = 0; dadded = 0; icat(ip, dsrch, nullf); if(dadded) { BIS(ino, nodmap); est(ip); nadded++; } if(nsubdir == 0) if(!BIT(ino, nodmap)) BIC(ino, dirmap); } dump(ip) struct dinode *ip; { register i; if(newtape) { newtape = 0; bitmap(nodmap, TS_BITS); } BIC(ino, nodmap); spcl.c_dinode = *ip; spcl.c_type = TS_INODE; spcl.c_count = 0; i = ip->di_mode & IFMT; if(i != IFDIR && i != IFREG && i != IFLNK) { spclrec(); return; } icat(ip, tapsrec, dmpspc); } dmpspc(dp, n) daddr_t *dp; { register i, t; spcl.c_count = n; for(i=0; id_reclen == 0) { /* * following hack is for directories which, although occupying a full fs block * do not have the second DIRBLKSIZ section initialized to an empty dir blk. */ if (i != DIRBLKSIZ) /* XXX */ fprintf(stderr,"corrupted directory, inumber %u\n",ino); break; } i += dp->d_reclen; if (dp->d_ino == 0) continue; if (dp->d_name[0] == '.') { if (dp->d_name[1] == '\0') continue; if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') continue; } if(BIT(dp->d_ino, nodmap)) { dadded++; return; } if(BIT(dp->d_ino, dirmap)) nsubdir++; } } nullf() { } int breaderrors = 0; #define BREADEMAX 32 bread(da, ba, c) daddr_t da; char *ba; unsigned c; { register n; register unsigned regc; if (lseek(fi, (off_t)da * DEV_BSIZE, 0) < 0) msg("bread: lseek fails\n"); regc = c; /* put c someplace safe; it gets clobbered */ n = read(fi, ba, c); if (n == -1 || ((unsigned)n) != c || regc != c){ msg("(This should not happen)bread from %s [block %ld]: c=0x%x, regc=0x%x, &c=0x%x, n=0x%x\n", disk, da, c, regc, &c, n); if (++breaderrors > BREADEMAX){ msg("More than %d block read errors from %d\n", BREADEMAX, disk); broadcast("DUMP IS AILING!\n"); msg("This is an unrecoverable error.\n"); if (!query("Do you want to attempt to continue?")){ dumpabort(); /*NOTREACHED*/ } else breaderrors = 0; } } } 0666)) < 0) #endif RDUMP { msg("Cannot open output \"%s\".\n", tape); if (!query("Do you want to retry the open?")) dumpabort(); } enslave(); /* Share open tape file descriptor with slaves */ asize = 0; tapeno++; /* current tape sequence */ newtape++; /* etc/dump/unctime.c 644 0 0 3625 4701641457 7353 #include #include #include /* * Convert a ctime(3) format string into a system format date. * Return the date thus calculated. * * Return -1 if the string is not in ctime format. */ /* * Offsets into the ctime string to various parts. */ #define E_MONTH 4 #define E_DAY 8 #define E_HOUR 11 #define E_MINUTE 14 #define E_SECOND 17 #define E_YEAR 20 time_t unctime(str) char *str; { struct tm then; char dbuf[30]; time_t emitl(); if (strlen(str) != 25) str[25] = 0; strcpy(dbuf, str); dbuf[E_MONTH+3] = 0; if ( (then.tm_mon = lookup(&dbuf[E_MONTH])) < 0) { return(-1);; } then.tm_mday = atoi(&dbuf[E_DAY]); then.tm_hour = atoi(&dbuf[E_HOUR]); then.tm_min = atoi(&dbuf[E_MINUTE]); then.tm_sec = atoi(&dbuf[E_SECOND]); then.tm_year = atoi(&dbuf[E_YEAR]) - 1900; return(emitl(&then)); } static char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; static lookup(str) char *str; { register char *cp, *cp2; for (cp = months, cp2 = str; *cp != 0; cp += 3) if (strncmp(cp, cp2, 3) == 0) return((cp-months) / 3); return(-1); } /* * Routine to convert a localtime(3) format date back into * a system format date. * * Use a binary search. */ struct tm *localtime(); time_t emitl(dp) struct tm *dp; { time_t conv, bit; register int i; struct tm dcopy; dcopy = *dp; dp = &dcopy; conv = 0; for (i = 30; i >= 0; i--) { bit = 1L << i; conv |= bit; if (dcmp(localtime(&conv), dp) > 0) conv &= ~bit; } return(conv); } /* * Compare two localtime dates, return result. */ #define DECIDE(a) \ if (dp->a > dp2->a) \ return(1); \ if (dp->a < dp2->a) \ return(-1) static dcmp(dp, dp2) register struct tm *dp, *dp2; { DECIDE(tm_year); DECIDE(tm_mon); DECIDE(tm_mday); DECIDE(tm_hour); DECIDE(tm_min); DECIDE(tm_sec); return(0); } #if !defined(lint) && defined(DOSCCS) static char *sccsid = "@(#)unctime.c 1.3 (Berkeley) 81/04/18"; #endif ; } icat(ip, tapsrec, dmpspc); } dmpspc(dp, n) daddr_t *dp; { register i, t; spcl.c_count = n; for(ietc/dump/dumprmt.c 644 0 0 11003 5674205472 7407 /*- * Copyright (c) 1980 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)dumprmt.c 1.2 (2.11BSD GTE) 12/7/94"; #endif #include #include #include #include #include #include #include #include #include #include #include #define TS_CLOSED 0 #define TS_OPEN 1 #define rmtstate rstate static int rmtstate = TS_CLOSED; int rmtape; void rmtgetconn(); void rmtconnaborted(); int rmtreply(); int rmtgetb(); void rmtgets(); int rmtcall(); char *rmtpeer; extern void msg(); int rmthost(host) char *host; { rmtpeer = host; signal(SIGPIPE, rmtconnaborted); rmtgetconn(); if (rmtape < 0) return (0); return (1); } void rmtconnaborted() { fprintf(stderr, "rdump: Lost connection to remote host.\n"); exit(1); } void rmtgetconn() { static struct servent *sp = 0; struct passwd *pw; char *name = "root"; int size; if (sp == 0) { sp = getservbyname("shell", "tcp"); if (sp == 0) { fprintf(stderr, "rdump: shell/tcp: unknown service\n"); exit(1); } } pw = getpwuid(getuid()); if (pw && pw->pw_name) name = pw->pw_name; rmtape = rcmd(&rmtpeer, sp->s_port, name, name, "rmt", 0); size = NTREC * DEV_BSIZE; while (size > DEV_BSIZE && setsockopt(rmtape, SOL_SOCKET, SO_SNDBUF, &size, sizeof (size)) < 0) size -= DEV_BSIZE; } int rmtopen(tape, mode) char *tape; int mode; { char buf[256]; (void)sprintf(buf, "O%s\n%d\n", tape, mode); rmtstate = TS_OPEN; return (rmtcall(tape, buf)); } void rmtclose() { if (rmtstate != TS_OPEN) return; rmtcall("close", "C\n"); rmtstate = TS_CLOSED; } int rmtwrite(buf, count) char *buf; int count; { char line[30]; (void)sprintf(line, "W%d\n", count); write(rmtape, line, strlen(line)); write(rmtape, buf, count); return (rmtreply("write")); } int rmtcall(cmd, buf) char *cmd, *buf; { if (write(rmtape, buf, strlen(buf)) != strlen(buf)) rmtconnaborted(); return (rmtreply(cmd)); } int rmtreply(cmd) char *cmd; { char code[30], emsg[BUFSIZ]; rmtgets(code, sizeof (code)); if (*code == 'E' || *code == 'F') { rmtgets(emsg, sizeof (emsg)); msg("%s: %s\n", cmd, emsg, code + 1); if (*code == 'F') { rmtstate = TS_CLOSED; return (-1); } return (-1); } if (*code != 'A') { msg("Protocol to remote tape server botched (code %s?).\n", code); rmtconnaborted(); } return (atoi(code + 1)); } int rmtgetb() { char c; if (read(rmtape, &c, 1) != 1) rmtconnaborted(); return (c); } void rmtgets(cp, len) char *cp; int len; { while (len > 1) { *cp = rmtgetb(); if (*cp == '\n') { cp[1] = 0; return; } cp++; len--; } msg("Protocol to remote tape server botched (in rmtgets).\n"); rmtconnaborted(); } > #include #include #include #include #include #include #define TS_CLOSED 0 #define TS_OPEN 1 #define rmtstate rstate static int rmtstate = TS_CLOSED; int rmtape; void rmtgetconn(); void rmtconnaborted(); int rmtreply(); int rmtgetb(); void rmtgets(); int rmtcall(); char *rmtpeer; extern void msg(); int rmthost(host) char *host; { rmtpeer = host; signal(SIGPIPE, rmtconnaborted); rmtgetconn(); if (rmtape < 0) returetc/config/ 750 0 12 0 6024536020 5753 etc/config/config.c 440 0 12 116 5012665274 7440 main() { puts("config hasn't been implemented under 2.11BSD."); exit(-1); } etc/config/Makefile 440 0 12 2115 5326557353 7516 # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.3 (Berkeley) 2/18/86 # # CFILES= config.c OBJS= config.o SEPFLAG= -i CFLAGS=-O LDFLAGS=-ll config: ${OBJS} ${CC} ${OBJS} ${SEPFLAG} -o config ${LDFLAGS} clean: rm -f ${OBJS} lex.yy.c y.tab.c y.tab.h config install: config install -s config ${DESTDIR}/etc/config lint: ${CFILES} lint ${CFILES} depend: grep '^#include' ${CFILES} | grep -v '<' | \ sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' \ -e 's/\.c/.o/' \ -e 's,../[a-zA-Z]*/,,' | \ awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ else rec = rec " " $$2 } } \ END { print rec } ' > makedep echo '$$r makedep' >>eddep echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep echo '$$r makedep' >>eddep echo 'w' >>eddep cp Makefile Makefile.bak ed - Makefile < eddep rm eddep makedep # DO NOT DELETE THIS LINE -- make depend uses it unt); return (rmtreply("write")); } int rmtcall(cmd, buf) char *cmd, *buf; { if (write(rmtape, buf, strlen(buf)) != strlen(buf)) rmtconnaborted(); return (rmtreply(cmd)); } int rmtreply(cmd) char *cmd; { char code[30], emsg[BUFSIZ]; rmtgets(code, sizeof (code)); if (*code == 'E' || *code == 'F') { rmtgets(emsg, sizeof (emsg)); msg("%s: %s\n", cmd, emsg, code + 1); if (*code == 'F') { rmtstate = TS_CLOSED; etc/getty/ 750 0 12 0 6024536036 5651 etc/getty/gettytab 440 0 12 5371 5672246253 7520 # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)gettytab 5.7.1 (2.11BSD GTE) 12/9/94 # # # Most of the table entries here are just copies of the # old getty table, it is by no means certain, or even likely, # then any of them are optimal for any purpose whatever. # Nor is it likely that more than a couple are even correct # # # The default gettytab entry, used to set defaults for all other # entries, and in cases where getty is called with no table name # default:\ :ap:fd#1000:im=\r\n\r\n2.11 BSD UNIX (%h) (%t)\r\n\r\r\n\r:sp#1200: # # Fixed speed entries # # The "std.NNN" names are known to the special case # portselector code in getty, however they can # be assigned to any table desired. # The "NNN-baud" names are known to the special case # autobaud code in getty, and likewise can # be assigned to any table desired (hopefully the same speed). # a|std.110|110-baud:\ :nd#1:cd#1:sp#110: b|std.134|134.5-baud:\ :ep:nd#1:cd#2:ff#1:td#1:sp#134:ht:nl: 1|std.150|150-baud:\ :ep:nd#1:cd#2:td#1:fd#1:sp#150:ht:nl:lm=\E\72\6\6\17login\72 : c|std.300|300-baud:\ :nd#1:cd#1:sp#300: d|std.600|600-baud:\ :nd#1:cd#1:sp#600: f|std.1200|1200-baud:\ :fd#1:sp#1200: 6|std.2400|2400-baud:\ :sp#2400:ht: 7|std.4800|4800-baud:\ :sp#4800:ht: 2|std.9600|9600-baud:\ :sp#9600: g|std.19200|19200-baud:\ :sp#19200: # # Dial in rotary tables, speed selection via 'break' # 0|d300|Dial-300:\ :nx=d1200:cd#2:sp#300: d1200|Dial-1200:\ :nx=d150:fd#1:sp#1200: d150|Dial-150:\ :nx=d110:lm@:tc=150-baud: d110|Dial-110:\ :nx=d300:tc=300-baud: # # Odd special case terminals # -|tty33|asr33|Pity the poor user of this beast:\ :tc=110-baud: 4|Console|Console Decwriter II:\ :nd@:cd@:rw:tc=300-baud: e|Console-1200|Console Decwriter III:\ :fd@:nd@:cd@:rw:tc=1200-baud: l|lsi chess terminal:\ :sp#300: X|Xwindow|X window system:\ :fd@:nd@:cd@:rw:sp#9600: # # Fast dialup terminals, 2400/1200/300 rotary (can start either way) # D2400|Fast-Dial-2400:\ :nx=D1200:tc=2400-baud: 3|D1200|Fast-Dial-1200:\ :nx=D300:tc=1200-baud: 5|D300|Fast-Dial-300:\ :nx=D2400:tc=300-baud: # # Wierdo special case for fast crt's with hardcopy devices # 8|T9600|CRT with hardcopy:\ :nx=T300:tc=9600-baud: 9|T300|CRT with hardcopy (300):\ :nx=T9600:tc=300-baud: # # Plugboard, and misc other terminals # p|P9600|Plugboard-9600:\ :nx=P300:tc=9600-baud: q|P300|Plugboard-300:\ :nx=P1200:tc=300-baud: r|P1200|Plugboard-1200:\ :nx=P9600:tc=1200-baud: # # XXXX Port selector # s|DSW|Port Selector:\ :ps:sp#2400: # # Auto-baud speed detect entry for Micom 600. # Special code in getty will switch this out # to one of the NNN-baud entries. # A|Auto-baud:\ :ab:sp#2400:f0#040: eturn; bread(d, dbuf, DEV_BSIZE); for (i = 0; i < DEV_BSIZE; ) { dp = (struct direct *)(dbuf + i); if (dp->d_reclen == 0) { /* * following hack is for directories which, although occupying a full fs block * do not have the second DIRBLKSIZ section initialetc/getty/gettytab.h 440 0 12 6021 5672245565 7744 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)gettytab.h 5.2.2 (2.11BSD GTE) 12/9/94 */ /* * Getty description definitions. */ struct gettystrs { char *field; /* name to lookup in gettytab */ char *defalt; /* value we find by looking in defaults */ char *value; /* value that we find there */ }; struct gettynums { char *field; /* name to lookup */ long defalt; /* number we find in defaults */ long value; /* number we find there */ int set; /* we actually got this one */ }; struct gettyflags { char *field; /* name to lookup */ char invrt; /* name existing in gettytab --> false */ char defalt; /* true/false in defaults */ char value; /* true/false flag */ char set; /* we found it */ }; /* * String values. */ #define NX gettystrs[0].value #define CL gettystrs[1].value #define IM gettystrs[2].value #define LM gettystrs[3].value #define ER gettystrs[4].value #define KL gettystrs[5].value #define ET gettystrs[6].value #define PC gettystrs[7].value #define TT gettystrs[8].value #define EV gettystrs[9].value #define LO gettystrs[10].value #define HN gettystrs[11].value #define HE gettystrs[12].value #define IN gettystrs[13].value #define QU gettystrs[14].value #define XN gettystrs[15].value #define XF gettystrs[16].value #define BK gettystrs[17].value #define SU gettystrs[18].value #define DS gettystrs[19].value #define RP gettystrs[20].value #define FL gettystrs[21].value #define WE gettystrs[22].value #define LN gettystrs[23].value /* * Numeric definitions. */ #define IS gettynums[0].value #define OS gettynums[1].value #define SP gettynums[2].value #define ND gettynums[3].value #define CD gettynums[4].value #define TD gettynums[5].value #define FD gettynums[6].value #define BD gettynums[7].value #define TO gettynums[8].value #define F0 gettynums[9].value #define F0set gettynums[9].set #define F1 gettynums[10].value #define F1set gettynums[10].set #define F2 gettynums[11].value #define F2set gettynums[11].set #define PF gettynums[12].value /* * Boolean values. */ #define HT gettyflags[0].value #define NL gettyflags[1].value #define EP gettyflags[2].value #define EPset gettyflags[2].set #define OP gettyflags[3].value #define OPset gettyflags[2].set #define AP gettyflags[4].value #define APset gettyflags[2].set #define EC gettyflags[5].value #define CO gettyflags[6].value #define CB gettyflags[7].value #define CK gettyflags[8].value #define CE gettyflags[9].value #define PE gettyflags[10].value #define RW gettyflags[11].value #define XC gettyflags[12].value #define IG gettyflags[13].value #define PS gettyflags[14].value #define HC gettyflags[15].value #define UB gettyflags[16].value #define AB gettyflags[17].value #define DX gettyflags[18].value int getent(); long getnum(); int getflag(); char *getstr(); long setflags(); extern struct gettyflags gettyflags[]; extern struct gettynums gettynums[]; extern struct gettystrs gettystrs[]; extern int hopcount; dir blk. */ if (i != DIRBLKSIZ) /* XXX */ fprintf(stderr,"corrupted directory, inumber %u\n",ino); break; } i += dp->d_reclen; if (dp->d_ino == 0) continue; if (dp->d_name[0] == '.') { if (dp->d_name[1] == '\0') continue; if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') continue; } if(BIT(dp->d_ino, nodmap)) { dadded++; return; } if(BIT(dp->d_ino, dirmap)) nsubdir++; } } nullf() { } int breaderrors = 0; #define BREADEMAX 32 bread(da,etc/getty/init.c 440 0 12 5405 5672245533 7057 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)init.c 5.2.1 (2.11BSD GTE) 12/9/94"; #endif /* * Getty table initializations. * * Melbourne getty. */ #include #include "gettytab.h" extern struct sgttyb tmode; extern struct tchars tc; extern struct ltchars ltc; extern char hostname[]; struct gettystrs gettystrs[] = { { "nx" }, /* next table */ { "cl" }, /* screen clear characters */ { "im" }, /* initial message */ { "lm", "login: " }, /* login message */ { "er", &tmode.sg_erase }, /* erase character */ { "kl", &tmode.sg_kill }, /* kill character */ { "et", &tc.t_eofc }, /* eof chatacter (eot) */ { "pc", "" }, /* pad character */ { "tt" }, /* terminal type */ { "ev" }, /* enviroment */ { "lo", "/bin/login" }, /* login program */ { "hn", hostname }, /* host name */ { "he" }, /* host name edit */ { "in", &tc.t_intrc }, /* interrupt char */ { "qu", &tc.t_quitc }, /* quit char */ { "xn", &tc.t_startc }, /* XON (start) char */ { "xf", &tc.t_stopc }, /* XOFF (stop) char */ { "bk", &tc.t_brkc }, /* brk char (alt \n) */ { "su", <c.t_suspc }, /* suspend char */ { "ds", <c.t_dsuspc }, /* delayed suspend */ { "rp", <c.t_rprntc }, /* reprint char */ { "fl", <c.t_flushc }, /* flush output */ { "we", <c.t_werasc }, /* word erase */ { "ln", <c.t_lnextc }, /* literal next */ { 0 } }; struct gettynums gettynums[] = { { "is" }, /* input speed */ { "os" }, /* output speed */ { "sp" }, /* both speeds */ { "nd" }, /* newline delay */ { "cd" }, /* carriage-return delay */ { "td" }, /* tab delay */ { "fd" }, /* form-feed delay */ { "bd" }, /* backspace delay */ { "to" }, /* timeout */ { "f0" }, /* output flags */ { "f1" }, /* input flags */ { "f2" }, /* user mode flags */ { "pf" }, /* delay before flush at 1st prompt */ { 0 } }; struct gettyflags gettyflags[] = { { "ht", 0 }, /* has tabs */ { "nl", 1 }, /* has newline char */ { "ep", 0 }, /* even parity */ { "op", 0 }, /* odd parity */ { "ap", 0 }, /* any parity */ { "ec", 1 }, /* no echo */ { "co", 0 }, /* console special */ { "cb", 0 }, /* crt backspace */ { "ck", 0 }, /* crt kill */ { "ce", 0 }, /* crt erase */ { "pe", 0 }, /* printer erase */ { "rw", 1 }, /* don't use raw */ { "xc", 1 }, /* don't ^X ctl chars */ { "ig", 0 }, /* ignore garbage */ { "ps", 0 }, /* do port selector speed select */ { "hc", 1 }, /* don't set hangup on close */ { "ub", 0 }, /* unbuffered output */ { "ab", 0 }, /* auto-baud detect with '\r' */ { "dx", 0 }, /* set decctlq */ { 0 } }; gettyflags[17].value #define DX gettyflags[18].value int getent(); long getnum(); int getflag(); char *getstr(); long setflags(); extern struct gettyflags gettyflags[]; extern struct gettynums gettynums[]; extern struct gettystrs gettystrs[]; exteetc/getty/subr.c 440 0 12 17024 5672247024 7104 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)subr.c 5.4.1 (2.11BSD GTE) 12/9/94"; #endif /* * Melbourne getty. */ #include #include "gettytab.h" extern struct sgttyb tmode; extern struct tchars tc; extern struct ltchars ltc; /* * Get a table entry. */ gettable(name, buf, area) char *name, *buf, *area; { register struct gettystrs *sp; register struct gettynums *np; register struct gettyflags *fp; register n; hopcount = 0; /* new lookup, start fresh */ if (getent(buf, name) != 1) return; for (sp = gettystrs; sp->field; sp++) sp->value = getstr(sp->field, &area); for (np = gettynums; np->field; np++) { n = getnum(np->field); if (n == -1) np->set = 0; else { np->set = 1; np->value = n; } } for (fp = gettyflags; fp->field; fp++) { n = getflag(fp->field); if (n == -1) fp->set = 0; else { fp->set = 1; fp->value = n ^ fp->invrt; } } } gendefaults() { register struct gettystrs *sp; register struct gettynums *np; register struct gettyflags *fp; for (sp = gettystrs; sp->field; sp++) if (sp->value) sp->defalt = sp->value; for (np = gettynums; np->field; np++) if (np->set) np->defalt = np->value; for (fp = gettyflags; fp->field; fp++) if (fp->set) fp->defalt = fp->value; else fp->defalt = fp->invrt; } setdefaults() { register struct gettystrs *sp; register struct gettynums *np; register struct gettyflags *fp; for (sp = gettystrs; sp->field; sp++) if (!sp->value) sp->value = sp->defalt; for (np = gettynums; np->field; np++) if (!np->set) np->value = np->defalt; for (fp = gettyflags; fp->field; fp++) if (!fp->set) fp->value = fp->defalt; } static char ** charnames[] = { &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK, &SU, &DS, &RP, &FL, &WE, &LN, 0 }; static char * charvars[] = { &tmode.sg_erase, &tmode.sg_kill, &tc.t_intrc, &tc.t_quitc, &tc.t_startc, &tc.t_stopc, &tc.t_eofc, &tc.t_brkc, <c.t_suspc, <c.t_dsuspc, <c.t_rprntc, <c.t_flushc, <c.t_werasc, <c.t_lnextc, 0 }; setchars() { register int i; register char *p; for (i = 0; charnames[i]; i++) { p = *charnames[i]; if (p && *p) *charvars[i] = *p; else *charvars[i] = '\377'; } } long setflags(n) { register long f; switch (n) { case 0: if (F0set) return(F0); break; case 1: if (F1set) return(F1); break; default: if (F2set) return(F2); break; } f = 0; if (AP) f |= ANYP; else if (OP) f |= ODDP; else if (EP) f |= EVENP; if (NL) f |= CRMOD; f |= delaybits(); if (n == 1) { /* read mode flags */ if (RW) f |= RAW; else f |= CBREAK; return (f); } if (!HT) f |= XTABS; if (n == 0) return (f); if (CB) f |= CRTBS; if (CE) f |= CRTERA; if (CK) f |= CRTKIL; if (PE) f |= PRTERA; if (EC) f |= ECHO; if (XC) f |= CTLECH; if (DX) f |= DECCTQ; return (f); } struct delayval { unsigned delay; /* delay in ms */ int bits; }; /* * below are random guesses, I can't be bothered checking */ struct delayval crdelay[] = { 1, CR1, 2, CR2, 3, CR3, 83, CR1, 166, CR2, 0, CR3, }; struct delayval nldelay[] = { 1, NL1, /* special, calculated */ 2, NL2, 3, NL3, 100, NL2, 0, NL3, }; struct delayval bsdelay[] = { 1, BS1, 0, 0, }; struct delayval ffdelay[] = { 1, FF1, 1750, FF1, 0, FF1, }; struct delayval tbdelay[] = { 1, TAB1, 2, TAB2, 3, XTABS, /* this is expand tabs */ 100, TAB1, 0, TAB2, }; delaybits() { register f; f = adelay(CD, crdelay); f |= adelay(ND, nldelay); f |= adelay(FD, ffdelay); f |= adelay(TD, tbdelay); f |= adelay(BD, bsdelay); return (f); } adelay(ms, dp) register long ms; register struct delayval *dp; { if (ms == 0) return (0); while (dp->delay && ms > dp->delay) dp++; return (dp->bits); } char editedhost[32]; edithost(pat) register char *pat; { register char *host = HN; register char *res = editedhost; if (!pat) pat = ""; while (*pat) { switch (*pat) { case '#': if (*host) host++; break; case '@': if (*host) *res++ = *host++; break; default: *res++ = *pat; break; } if (res == &editedhost[sizeof editedhost - 1]) { *res = '\0'; return; } pat++; } if (*host) strncpy(res, host, sizeof editedhost - (res - editedhost) - 1); else *res = '\0'; editedhost[sizeof editedhost - 1] = '\0'; } struct speedtab { int speed; int uxname; } speedtab[] = { 50, B50, 75, B75, 110, B110, 134, B134, 150, B150, 200, B200, 300, B300, 600, B600, 1200, B1200, 1800, B1800, 2400, B2400, 4800, B4800, 9600, B9600, 19200, EXTA, 19, EXTA, /* for people who say 19.2K */ 38400, EXTB, 38, EXTB, 7200, EXTB, /* alternative */ 0 }; speed(val) long val; { register struct speedtab *sp; if (val <= 15) return (val); for (sp = speedtab; sp->speed; sp++) if (sp->speed == val) return (sp->uxname); return (B300); /* default in impossible cases */ } makeenv(env) char *env[]; { static char termbuf[128] = "TERM="; register char *p, *q; register char **ep; char *index(); ep = env; if (TT && *TT) { strcat(termbuf, TT); *ep++ = termbuf; } if (p = EV) { q = p; while (q = index(q, ',')) { *q++ = '\0'; *ep++ = p; p = q; } if (*p) *ep++ = p; } *ep = (char *)0; } /* * This speed select mechanism is written for the Develcon DATASWITCH. * The Develcon sends a string of the form "B{speed}\n" at a predefined * baud rate. This string indicates the user's actual speed. * The routine below returns the terminal type mapped from derived speed. */ struct portselect { char *ps_baud; char *ps_type; } portspeeds[] = { { "B110", "std.110" }, { "B134", "std.134" }, { "B150", "std.150" }, { "B300", "std.300" }, { "B600", "std.600" }, { "B1200", "std.1200" }, { "B2400", "std.2400" }, { "B4800", "std.4800" }, { "B9600", "std.9600" }, { "B19200", "std.19200" }, { 0 } }; char * portselector() { char c, baud[20], *type = "default"; register struct portselect *ps; int len; alarm(5*60); for (len = 0; len < sizeof (baud) - 1; len++) { if (read(0, &c, 1) <= 0) break; c &= 0177; if (c == '\n' || c == '\r') break; if (c == 'B') len = 0; /* in case of leading garbage */ baud[len] = c; } baud[len] = '\0'; for (ps = portspeeds; ps->ps_baud; ps++) if (strcmp(ps->ps_baud, baud) == 0) { type = ps->ps_type; break; } sleep(2); /* wait for connection to complete */ return (type); } /* * This auto-baud speed select mechanism is written for the Micom 600 * portselector. Selection is done by looking at how the character '\r' * is garbled at the different speeds. */ #include char * autobaud() { long rfds; struct timeval timeout; char c, *type = "1200-baud"; int null = 0; ioctl(0, TIOCFLUSH, &null); rfds = 1 << 0; timeout.tv_sec = 30; timeout.tv_usec = 0; if (select(32, &rfds, (int *)0, (int *)0, &timeout) <= 0) return (type); if (read(0, &c, sizeof(char)) != sizeof(char)) return (type); timeout.tv_sec = 0; timeout.tv_usec = 20; (void) select(32, (int *)0, (int *)0, (int *)0, &timeout); ioctl(0, TIOCFLUSH, &null); switch (c & 0377) { case 0200: /* 300-baud */ type = "300-baud"; break; case 0346: /* 1200-baud */ type = "1200-baud"; break; case 015: /* 2400-baud */ case 0215: type = "2400-baud"; break; default: /* 4800-baud */ type = "4800-baud"; break; case 0377: /* 9600-baud */ type = "9600-baud"; break; } return (type); } RM, dumpabort); /* Slave sends SIGTERM on dumpabort() */ signal(SIGPIPE, sigpipe); signal(SIGUSR1, tperror); /* Slave sends SIGUSR1 on tape errors */ lockfile(first); for (i = 0; i < SLAVES; i++) { if (i == 0) { prev[0] = first[1]; prev[1] = first[0]; } else { prev[0] = next[0]; prev[1] = next[1]; flock(prev[1], LOCK_EX); } if (i < SLAVES - 1) { lockfile(next); } else { next[0] = first[0]; next[1] = first[1]; /* Last slave loops back */ } etc/getty/main.c 640 0 12 20366 5672246741 7067 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1980 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)main.c 5.5.1 (2.11BSD GTE) 12/9/94"; #endif /* * getty -- adapt to terminal speed on dialup, and call login * * Melbourne getty, June 83, kre. */ #include #include #include #include #include #include #include "gettytab.h" extern char **environ; struct sgttyb tmode = { 0, 0, CERASE, CKILL, 0 }; struct tchars tc = { CINTR, CQUIT, CSTART, CSTOP, CEOF, CBRK, }; struct ltchars ltc = { CSUSP, CDSUSP, CRPRNT, CFLUSH, CWERASE, CLNEXT }; int crmod; int upper; int lower; int digit; char hostname[32]; char name[16]; char dev[] = "/dev/"; char ctty[] = "/dev/console"; char ttyn[32]; char *portselector(); char *ttyname(); #define OBUFSIZ 128 #define TABBUFSIZ 512 char defent[TABBUFSIZ]; char defstrs[TABBUFSIZ]; char tabent[TABBUFSIZ]; char tabstrs[TABBUFSIZ]; char *env[128]; char partab[] = { 0001,0201,0201,0001,0201,0001,0001,0201, 0202,0004,0003,0205,0005,0206,0201,0001, 0201,0001,0001,0201,0001,0201,0201,0001, 0001,0201,0201,0001,0201,0001,0001,0201, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0200, 0200,0000,0000,0200,0000,0200,0200,0000, 0200,0000,0000,0200,0000,0200,0200,0000, 0000,0200,0200,0000,0200,0000,0000,0201 }; #define ERASE tmode.sg_erase #define KILL tmode.sg_kill #define EOT tc.t_eofc jmp_buf timeout; dingdong() { alarm(0); signal(SIGALRM, SIG_DFL); longjmp(timeout, 1); } jmp_buf intrupt; interrupt() { signal(SIGINT, interrupt); longjmp(intrupt, 1); } main(argc, argv) char *argv[]; { register char *tname; long allflags; int repcnt = 0; int someflags; signal(SIGINT, SIG_IGN); /* signal(SIGQUIT, SIG_DFL); */ openlog("getty", LOG_ODELAY|LOG_CONS, LOG_AUTH); gethostname(hostname, sizeof(hostname)); if (hostname[0] == '\0') strcpy(hostname, "Amnesiac"); /* * The following is a work around for vhangup interactions * which cause great problems getting window systems started. * If the tty line is "-", we do the old style getty presuming * that the file descriptors are already set up for us. * J. Gettys - MIT Project Athena. */ if (argc <= 2 || strcmp(argv[2], "-") == 0) strcpy(ttyn, ttyname(0)); else { strcpy(ttyn, dev); strncat(ttyn, argv[2], sizeof(ttyn)-sizeof(dev)); if (strcmp(argv[0], "+") != 0) { chown(ttyn, 0, 0); chmod(ttyn, 0622); /* * Delay the open so DTR stays down long enough to be detected. */ sleep(2); while (open(ttyn, O_RDWR) != 0) { if (repcnt % 10 == 0) { syslog(LOG_ERR, "%s: %m", ttyn); closelog(); } repcnt++; sleep(60); } signal(SIGHUP, SIG_IGN); vhangup(); (void) open(ttyn, O_RDWR); close(0); dup(1); dup(0); signal(SIGHUP, SIG_DFL); } } gettable("default", defent, defstrs); gendefaults(); tname = "default"; if (argc > 1) tname = argv[1]; for (;;) { int ldisp = OTTYDISC; gettable(tname, tabent, tabstrs); if (OPset || EPset || APset) APset++, OPset++, EPset++; setdefaults(); ioctl(0, TIOCFLUSH, 0); /* clear out the crap */ if (IS) tmode.sg_ispeed = speed(IS); else if (SP) tmode.sg_ispeed = speed(SP); if (OS) tmode.sg_ospeed = speed(OS); else if (SP) tmode.sg_ospeed = speed(SP); tmode.sg_flags = setflags(0); ioctl(0, TIOCSETP, &tmode); setchars(); ioctl(0, TIOCSETC, &tc); ioctl(0, TIOCSETD, &ldisp); if (HC) ioctl(0, TIOCHPCL, 0); if (AB) { extern char *autobaud(); tname = autobaud(); continue; } if (PS) { tname = portselector(); continue; } if (CL && *CL) putpad(CL); edithost(HE); if (IM && *IM) putf(IM); if (setjmp(timeout)) { tmode.sg_ispeed = tmode.sg_ospeed = 0; ioctl(0, TIOCSETP, &tmode); exit(1); } if (TO) { signal(SIGALRM, dingdong); alarm((int)TO); } if (getname()) { register int i; oflush(); alarm(0); signal(SIGALRM, SIG_DFL); if (!(upper || lower || digit)) continue; allflags = setflags(2); tmode.sg_flags = allflags & 0xffff; someflags = allflags >> 16; if (crmod || NL) tmode.sg_flags |= CRMOD; ioctl(0, TIOCSETP, &tmode); ioctl(0, TIOCSLTC, <c); ioctl(0, TIOCLSET, &someflags); signal(SIGINT, SIG_DFL); for (i = 0; environ[i] != (char *)0; i++) env[i] = environ[i]; makeenv(&env[i]); execle(LO, "login", "-p", name, (char *) 0, env); exit(1); } alarm(0); signal(SIGALRM, SIG_DFL); signal(SIGINT, SIG_IGN); if (NX && *NX) tname = NX; } } getname() { register char *np; register c; char cs; /* * Interrupt may happen if we use CBREAK mode */ if (setjmp(intrupt)) { signal(SIGINT, SIG_IGN); return (0); } signal(SIGINT, interrupt); tmode.sg_flags = setflags(0); ioctl(0, TIOCSETP, &tmode); tmode.sg_flags = setflags(1); prompt(); if (PF > 0) { oflush(); sleep((int)PF); PF = 0; } ioctl(0, TIOCSETP, &tmode); crmod = 0; upper = 0; lower = 0; digit = 0; np = name; for (;;) { oflush(); if (read(0, &cs, 1) <= 0) exit(0); if ((c = cs&0177) == 0) return (0); if (c == EOT) exit(1); if (c == '\r' || c == '\n' || np >= &name[sizeof name]) { putf("\r\n"); break; } if (islower(c)) lower++; else if (isupper(c)) upper++; else if (c == ERASE || c == '#' || c == '\b') { if (np > name) { np--; if (tmode.sg_ospeed >= B1200) puts("\b \b"); else putchr(cs); } continue; } else if (c == KILL || c == '@') { putchr(cs); putchr('\r'); if (tmode.sg_ospeed < B1200) putchr('\n'); /* this is the way they do it down under ... */ else if (np > name) puts(" \r"); prompt(); np = name; continue; } else if (isdigit(c)) digit++; if (IG && (c <= ' ' || c > 0176)) continue; *np++ = c; putchr(cs); } signal(SIGINT, SIG_IGN); *np = 0; if (c == '\r') crmod++; return (1); } static short tmspc10[] = { 0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5, 15 }; putpad(s) register char *s; { register pad = 0; register mspc10; if (isdigit(*s)) { while (isdigit(*s)) { pad *= 10; pad += *s++ - '0'; } pad *= 10; if (*s == '.' && isdigit(s[1])) { pad += s[1] - '0'; s += 2; } } puts(s); /* * If no delay needed, or output speed is * not comprehensible, then don't try to delay. */ if (pad == 0) return; if (tmode.sg_ospeed <= 0 || tmode.sg_ospeed >= (sizeof tmspc10 / sizeof tmspc10[0])) return; /* * Round up by a half a character frame, * and then do the delay. * Too bad there are no user program accessible programmed delays. * Transmitting pad characters slows many * terminals down and also loads the system. */ mspc10 = tmspc10[tmode.sg_ospeed]; pad += mspc10 / 2; for (pad /= mspc10; pad > 0; pad--) putchr(*PC); } puts(s) register char *s; { while (*s) putchr(*s++); } char outbuf[OBUFSIZ]; int obufcnt = 0; putchr(cc) { char c; c = cc; c |= partab[c&0177] & 0200; if (OP) c ^= 0200; if (!UB) { outbuf[obufcnt++] = c; if (obufcnt >= OBUFSIZ) oflush(); } else write(1, &c, 1); } oflush() { if (obufcnt) write(1, outbuf, obufcnt); obufcnt = 0; } prompt() { putf(LM); if (CO) putchr('\n'); } putf(cp) register char *cp; { char *ttyn, *slash; char datebuffer[60]; extern char editedhost[]; extern char *ttyname(), *rindex(); while (*cp) { if (*cp != '%') { putchr(*cp++); continue; } switch (*++cp) { case 't': ttyn = ttyname(0); slash = rindex(ttyn, '/'); if (slash == (char *) 0) puts(ttyn); else puts(&slash[1]); break; case 'h': puts(editedhost); break; case 'd': get_date(datebuffer); puts(datebuffer); break; case '%': putchr('%'); break; } cp++; } } ng rfds; struct timeval timeout; char c, *type = "1200-baud"; int null = 0; ioctl(0, TIOCFLUSH, &null); rfds = 1 << 0; timeout.tv_sec = 30; timeout.tv_usec = 0; if (select(32, &rfds, (int *)0, (int *)0, &timeout) <= 0) return (type); if (read(0, &c, sizeetc/getty/Makefile 440 0 12 1115 4622364677 7407 # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.1 (Berkeley) 4/29/85 # DESTDIR= CFLAGS= -O SEPFLAG=-i OBJS= main.o init.o subr.o gettytab.o get_date.o all: getty getty: ${OBJS} ${CC} ${SEPFLAG} -o getty ${OBJS} install: all gettytab install -s getty ${DESTDIR}/etc/getty -install -c -m 444 gettytab ${DESTDIR}/etc/gettytab clean: rm -f getty ${OBJS} a.out core errs main.o: gettytab.h init.o: gettytab.h subr.o: gettytab.h ameþƒ portselector(); continue; } if (CL && *CL) putpad(CL); edithost(HE); if (IM && *IM) putf(IM); if (setjmp(timeout)) { tmode.sg_ispeed = tmode.sg_ospeed = 0; ioctl(0, TIOCSETP, &tmode); exit(1); } if (TO) { signal(SIGALRM, dingdong); alarm((int)TO); } if (getname()) { register int i; oflush(); alarm(0); signal(SIGALRM, SIG_DFL); if (!(upper || lower || digit)) continetc/getty/get_date.c 440 0 12 2376 5672247552 7677 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)get_date.c 5.1.1 (2.11BSD GTE) 12/9/94"; #endif #include #include static char *days[] = { "Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat" }; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec" }; #define AM "am" #define PM "pm" get_date(datebuffer) char *datebuffer; { register struct tm *tmp; struct timeval tv; int realhour; register char *zone; gettimeofday(&tv, 0); tmp = localtime(&tv.tv_sec); realhour = tmp->tm_hour; zone = AM; /* default to morning */ if (tmp->tm_hour == 0) realhour = 12; /* midnight */ else if (tmp->tm_hour == 12) zone = PM; /* noon */ else if (tmp->tm_hour >= 13 && tmp->tm_hour <= 23) { /* afternoon */ realhour = realhour - 12; zone = PM; } /* format is '8:10pm on Sunday, 16 Sept 1973' */ sprintf(datebuffer, "%d:%02d%s on %s, %d %s %d", realhour, tmp->tm_min, zone, days[tmp->tm_wday], tmp->tm_mday, months[tmp->tm_mon], 1900 + tmp->tm_year); } (SIGINT, SIG_DFL); for (i = 0; environ[i] != (char *)0; i++) env[i] = environ[i]; makeenv(&env[i]); execle(LO, "login", "-p", name, (char *) 0, env); exit(1); } alarm(0); signal(SIGALRM, SIG_DFL); signal(SIGINT, SIG_IGN); if (NX && etc/getty/gettytab.c 440 0 12 13222 4405327327 7746 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)gettytab.c 5.1 (Berkeley) 4/29/85"; #endif not lint #include #define TABBUFSIZ 512 static char *tbuf; int hopcount; /* detect infinite loops in termcap, init 0 */ char *skip(); char *getstr(); char *decode(); /* * Get an entry for terminal name in buffer bp, * from the termcap file. Parse is very rudimentary; * we just notice escaped newlines. */ getent(bp, name) char *bp, *name; { register char *cp; register int c; register int i = 0, cnt = 0; char ibuf[TABBUFSIZ]; char *cp2; int tf; tbuf = bp; tf = open("/etc/gettytab", 0); if (tf < 0) return (-1); for (;;) { cp = bp; for (;;) { if (i == cnt) { cnt = read(tf, ibuf, TABBUFSIZ); if (cnt <= 0) { close(tf); return (0); } i = 0; } c = ibuf[i++]; if (c == '\n') { if (cp > bp && cp[-1] == '\\'){ cp--; continue; } break; } if (cp >= bp+TABBUFSIZ) { write(2,"Gettytab entry too long\n", 24); break; } else *cp++ = c; } *cp = 0; /* * The real work for the match. */ if (namatch(name)) { close(tf); return(nchktc()); } } } /* * tnchktc: check the last entry, see if it's tc=xxx. If so, * recursively find xxx and append that entry (minus the names) * to take the place of the tc=xxx entry. This allows termcap * entries to say "like an HP2621 but doesn't turn on the labels". * Note that this works because of the left to right scan. */ #define MAXHOP 32 nchktc() { register char *p, *q; char tcname[16]; /* name of similar terminal */ char tcbuf[TABBUFSIZ]; char *holdtbuf = tbuf; int l; p = tbuf + strlen(tbuf) - 2; /* before the last colon */ while (*--p != ':') if (p MAXHOP) { write(2, "Getty: infinite tc= loop\n", 25); return (0); } if (getent(tcbuf, tcname) != 1) return(0); for (q=tcbuf; *q != ':'; q++) ; l = p - holdtbuf + strlen(q); if (l > TABBUFSIZ) { write(2, "Gettytab entry too long\n", 24); q[TABBUFSIZ - (p-tbuf)] = 0; } strcpy(p, q+1); tbuf = holdtbuf; return(1); } /* * Tnamatch deals with name matching. The first field of the termcap * entry is a sequence of names separated by |'s, so we compare * against each such name. The normal : terminator after the last * name (before the first field) stops us. */ namatch(np) char *np; { register char *Np, *Bp; Bp = tbuf; if (*Bp == '#') return(0); for (;;) { for (Np = np; *Np && *Bp == *Np; Bp++, Np++) continue; if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) return (1); while (*Bp && *Bp != ':' && *Bp != '|') Bp++; if (*Bp == 0 || *Bp == ':') return (0); Bp++; } } /* * Skip to the next field. Notice that this is very dumb, not * knowing about \: escapes or any such. If necessary, :'s can be put * into the termcap file in octal. */ static char * skip(bp) register char *bp; { while (*bp && *bp != ':') bp++; while (*bp == ':') bp++; return (bp); } /* * Return the (numeric) option id. * Numeric options look like * li#80 * i.e. the option string is separated from the numeric value by * a # character. If the option is not found we return -1. * Note that we handle octal numbers beginning with 0. */ long getnum(id) char *id; { register long i, base; register char *bp = tbuf; for (;;) { bp = skip(bp); if (*bp == 0) return (-1); if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) continue; if (*bp == '@') return(-1); if (*bp != '#') continue; bp++; base = 10; if (*bp == '0') base = 8; i = 0; while (isdigit(*bp)) i *= base, i += *bp++ - '0'; return (i); } } /* * Handle a flag option. * Flag options are given "naked", i.e. followed by a : or the end * of the buffer. Return 1 if we find the option, or 0 if it is * not given. */ getflag(id) char *id; { register char *bp = tbuf; for (;;) { bp = skip(bp); if (!*bp) return (-1); if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { if (!*bp || *bp == ':') return (1); else if (*bp == '!') return (0); else if (*bp == '@') return(-1); } } } /* * Get a string valued option. * These are given as * cl=^Z * Much decoding is done on the strings, and the strings are * placed in area, which is a ref parameter which is updated. * No checking on area overflow. */ char * getstr(id, area) char *id, **area; { register char *bp = tbuf; for (;;) { bp = skip(bp); if (!*bp) return (0); if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) continue; if (*bp == '@') return(0); if (*bp != '=') continue; bp++; return (decode(bp, area)); } } /* * Tdecode does the grung work to decode the * string capability escapes. */ static char * decode(str, area) register char *str; char **area; { register char *cp; register int c; register char *dp; int i; cp = *area; while ((c = *str++) && c != ':') { switch (c) { case '^': c = *str++ & 037; break; case '\\': dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; c = *str++; nextc: if (*dp++ == c) { c = *dp++; break; } dp++; if (*dp) goto nextc; if (isdigit(c)) { c -= '0', i = 2; do c <<= 3, c |= *str++ - '0'; while (--i && isdigit(*str)); } break; } *cp++ = c; } *cp++ = 0; str = *area; *area = cp; return (str); } datebuffer); puts(datebuffer); break; case '%': putchr('%'); break; } cp++; } } ng rfds; struct timeval timeout; char c, *type = "1200-baud"; int null = 0; ioctl(0, TIOCFLUSH, &null); rfds = 1 << 0; timeout.tv_sec = 30; timeout.tv_usec = 0; if (select(32, &rfds, (int *)0, (int *)0, &timeout) <= 0) return (type); if (read(0, &c, sizeetc/ftpd/ 755 0 12 0 6024536033 5454 etc/ftpd/CHANGES 444 0 3 2461 4366734330 6524 This version of ftpd has been fixed to conform to RFC959. Unfortunately, this conformance introduces a user visible change. While technically, this is the fault of the client (ftp) instead of the server (ftpd), the change will be seen whenever an old ftp client calls a new ftpd server. The problem is that the old ftpd implemented the NLST command by execing /bin/ls. This produced non-conformant output in some cases. The new ftpd no longer executes /bin/ls for the NLST command as it has it's own built-in code. The user visible change in the ftp behavior is caused by the ftp client "knowing" that the daemon will exec /bin/ls. This assumption should not have been made. When the old ftp client is used, one of the options is the "ls" command which sends the command NLST to the ftpd server. The client should really be sending the LIST command. The new ftp client has been corrected to do this. NLST should not normally be used directly by humans. It is intended to interface with commands like mget or mput. Users who are not able to upgrade their ftp client may obtain the previous behavior, by using the command "dir" instead of "ls". These changes only apply to those sites using code derived from the Berkeley software releases (which means almost every UNIX based implementation will see this problem). rlen(q); if (l > TABBUFSIZ) { write(2, "Gettytab entry too long\n", 24); q[TABBUFSIZ - (p-tbuf)] = 0; } strcpy(p, q+1); tbuf = holdtbuf; return(1); } /* * Tnamatch deals with name matching. The fetc/ftpd/Makefile 444 0 12 3274 5331145606 7207 # # Copyright (c) 1988 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that the above copyright notice and this paragraph are # duplicated in all such forms and that any documentation, # advertising materials, and other materials related to such # distribution and use acknowledge that the software was developed # by the University of California, Berkeley. The name of the # University may not be used to endorse or promote products derived # from this software without specific prior written permission. # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # @(#)Makefile based on 5.10 (Berkeley) 4/20/89 # CFLAGS= -O -I../ftp -I. -DSETPROCTITLE -I/usr/local/include SEPFLAG= -i LIBC= /lib/libc.a SRCS= ftpd.c ftpcmd.c glob.c logwtmp.c popen.c vers.c OBJS= ftpd.o ftpcmd.o glob.o logwtmp.o popen.o vers.o MAN= ftpd.0 MANSRC= ftpd.8 all: ftpd ftpd: ${OBJS} ${LIBC} ${CC} ${SEPFLAG} -o $@ ${OBJS} vers.o: ftpd.c ftpcmd.y sh newvers.sh ${CC} ${CFLAGS} -c vers.c clean: rm -f ${OBJS} ${MAN} ${GUSMAN} ftpd core ftpcmd.c cleandir: clean rm -f tags .depend depend: ${SRCS} mkdep ${CFLAGS} ${SRCS} install: ${MAN} ${GUSMAN} ftpd install -s -o bin -g bin -m 751 ftpd ${DESTDIR}/etc install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat8 ftpd.0: ${MANSRC} /usr/man/manroff ${MANSRC} > ${MAN} lint: ${SRCS} lint ${CFLAGS} ${SRCS} tags: ${SRCS} ctags ${SRCS} # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. ) stops us. */ namatch(np) char *np; { register char *Np, *Bp; Bp = tbuf; if (*Bp == '#') return(0); for (;;) { for (Np = np; *Np && *Bp == *Np; Bp++, Np++) continue; if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0)) return (1); while (*Bp && *Bp != ':' && *Bp != '|') Bp++; if (*Bp == 0 || *etc/ftpd/ftpcmd.y 444 0 12 55436 4570467656 7265 /* * Copyright (c) 1985, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)ftpcmd.y 5.20 (Berkeley) 2/28/89 */ /* * Grammar for FTP commands. * See RFC 959. */ %{ #ifndef lint static char sccsid[] = "@(#)ftpcmd.y 5.20 (Berkeley) 2/28/89"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include extern struct sockaddr_in data_dest; extern int logged_in; extern struct passwd *pw; extern int guest; extern int logging; extern int type; extern int form; extern int debug; extern int timeout; extern int maxtimeout; extern int pdata; extern char hostname[], remotehost[]; extern char proctitle[]; extern char *globerr; extern int usedefault; extern int transflag; extern char tmpline[]; char **glob(); off_t restart_point; static int cmd_type; static int cmd_form; static int cmd_bytesz; char cbuf[512]; char *fromname; char *index(); %} %token A B C E F I L N P R S T SP CRLF COMMA STRING NUMBER USER PASS ACCT REIN QUIT PORT PASV TYPE STRU MODE RETR STOR APPE MLFL MAIL MSND MSOM MSAM MRSQ MRCP ALLO REST RNFR RNTO ABOR DELE CWD LIST NLST SITE STAT HELP NOOP MKD RMD PWD CDUP STOU SMNT SYST SIZE MDTM UMASK IDLE CHMOD LEXERR %start cmd_list %% cmd_list: /* empty */ | cmd_list cmd = { fromname = (char *) 0; restart_point = (off_t) 0; } | cmd_list rcmd ; cmd: USER SP username CRLF = { user((char *) $3); free((char *) $3); } | PASS SP password CRLF = { pass((char *) $3); free((char *) $3); } | PORT SP host_port CRLF = { usedefault = 0; if (pdata >= 0) { (void) close(pdata); pdata = -1; } reply(200, "PORT command successful."); } | PASV CRLF = { passive(); } | TYPE SP type_code CRLF = { switch (cmd_type) { case TYPE_A: if (cmd_form == FORM_N) { reply(200, "Type set to A."); type = cmd_type; form = cmd_form; } else reply(504, "Form must be N."); break; case TYPE_E: reply(504, "Type E not implemented."); break; case TYPE_I: reply(200, "Type set to I."); type = cmd_type; break; case TYPE_L: #if NBBY == 8 if (cmd_bytesz == 8) { reply(200, "Type set to L (byte size 8)."); type = cmd_type; } else reply(504, "Byte size must be 8."); #else /* NBBY == 8 */ UNIMPLEMENTED for NBBY != 8 #endif /* NBBY == 8 */ } } | STRU SP struct_code CRLF = { switch ($3) { case STRU_F: reply(200, "STRU F ok."); break; default: reply(504, "Unimplemented STRU type."); } } | MODE SP mode_code CRLF = { switch ($3) { case MODE_S: reply(200, "MODE S ok."); break; default: reply(502, "Unimplemented MODE type."); } } | ALLO SP NUMBER CRLF = { reply(202, "ALLO command ignored."); } | ALLO SP NUMBER SP R SP NUMBER CRLF = { reply(202, "ALLO command ignored."); } | RETR check_login SP pathname CRLF = { if ($2 && $4 != NULL) retrieve((char *) 0, (char *) $4); if ($4 != NULL) free((char *) $4); } | STOR check_login SP pathname CRLF = { if ($2 && $4 != NULL) store((char *) $4, "w", 0); if ($4 != NULL) free((char *) $4); } | APPE check_login SP pathname CRLF = { if ($2 && $4 != NULL) store((char *) $4, "a", 0); if ($4 != NULL) free((char *) $4); } | NLST check_login CRLF = { if ($2) send_file_list("."); } | NLST check_login SP STRING CRLF = { if ($2 && $4 != NULL) send_file_list((char *) $4); if ($4 != NULL) free((char *) $4); } | LIST check_login CRLF = { if ($2) retrieve("/bin/ls -lgA", ""); } | LIST check_login SP pathname CRLF = { if ($2 && $4 != NULL) retrieve("/bin/ls -lgA %s", (char *) $4); if ($4 != NULL) free((char *) $4); } | STAT check_login SP pathname CRLF = { if ($2 && $4 != NULL) statfilecmd((char *) $4); if ($4 != NULL) free((char *) $4); } | STAT CRLF = { statcmd(); } | DELE check_login SP pathname CRLF = { if ($2 && $4 != NULL) delete((char *) $4); if ($4 != NULL) free((char *) $4); } | RNTO SP pathname CRLF = { if (fromname) { renamecmd(fromname, (char *) $3); free(fromname); fromname = (char *) 0; } else { reply(503, "Bad sequence of commands."); } free((char *) $3); } | ABOR CRLF = { reply(225, "ABOR command successful."); } | CWD check_login CRLF = { if ($2) cwd(pw->pw_dir); } | CWD check_login SP pathname CRLF = { if ($2 && $4 != NULL) cwd((char *) $4); if ($4 != NULL) free((char *) $4); } | HELP CRLF = { help(cmdtab, (char *) 0); } | HELP SP STRING CRLF = { register char *cp = (char *)$3; if (strncasecmp(cp, "SITE", 4) == 0) { cp = (char *)$3 + 4; if (*cp == ' ') cp++; if (*cp) help(sitetab, cp); else help(sitetab, (char *) 0); } else help(cmdtab, (char *) $3); } | NOOP CRLF = { reply(200, "NOOP command successful."); } | MKD check_login SP pathname CRLF = { if ($2 && $4 != NULL) makedir((char *) $4); if ($4 != NULL) free((char *) $4); } | RMD check_login SP pathname CRLF = { if ($2 && $4 != NULL) removedir((char *) $4); if ($4 != NULL) free((char *) $4); } | PWD check_login CRLF = { if ($2) pwd(); } | CDUP check_login CRLF = { if ($2) cwd(".."); } | SITE SP HELP CRLF = { help(sitetab, (char *) 0); } | SITE SP HELP SP STRING CRLF = { help(sitetab, (char *) $5); } | SITE SP UMASK check_login CRLF = { int oldmask; if ($4) { oldmask = umask(0); (void) umask(oldmask); reply(200, "Current UMASK is %03o", oldmask); } } | SITE SP UMASK check_login SP octal_number CRLF = { int oldmask; if ($4) { if (($6 == -1) || ($6 > 0777)) { reply(501, "Bad UMASK value"); } else { oldmask = umask($6); reply(200, "UMASK set to %03o (was %03o)", $6, oldmask); } } } | SITE SP CHMOD check_login SP octal_number SP pathname CRLF = { if ($4 && ($8 != NULL)) { if ($6 > 0777) reply(501, "CHMOD: Mode value must be between 0 and 0777"); else if (chmod((char *) $8, $6) < 0) perror_reply(550, (char *) $8); else reply(200, "CHMOD command successful."); } if ($8 != NULL) free((char *) $8); } | SITE SP IDLE CRLF = { reply(200, "Current IDLE time limit is %d seconds; max %d", timeout, maxtimeout); } | SITE SP IDLE SP NUMBER CRLF = { if ($5 < 30 || $5 > maxtimeout) { reply(501, "Maximum IDLE time must be between 30 and %d seconds", maxtimeout); } else { timeout = $5; (void) alarm((unsigned) timeout); reply(200, "Maximum IDLE time set to %d seconds", timeout); } } | STOU check_login SP pathname CRLF = { if ($2 && $4 != NULL) store((char *) $4, "w", 1); if ($4 != NULL) free((char *) $4); } | SYST CRLF = { #ifdef unix #ifdef BSD reply(215, "UNIX Type: L%d Version: BSD-%d", NBBY, BSD); #else /* BSD */ reply(215, "UNIX Type: L%d", NBBY); #endif /* BSD */ #else /* unix */ reply(215, "UNKNOWN Type: L%d", NBBY); #endif /* unix */ } /* * SIZE is not in RFC959, but Postel has blessed it and * it will be in the updated RFC. * * Return size of file in a format suitable for * using with RESTART (we just count bytes). */ | SIZE check_login SP pathname CRLF = { if ($2 && $4 != NULL) sizecmd((char *) $4); if ($4 != NULL) free((char *) $4); } /* * MDTM is not in RFC959, but Postel has blessed it and * it will be in the updated RFC. * * Return modification time of file as an ISO 3307 * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx * where xxx is the fractional second (of any precision, * not necessarily 3 digits) */ | MDTM check_login SP pathname CRLF = { if ($2 && $4 != NULL) { struct stat stbuf; if (stat((char *) $4, &stbuf) < 0) perror_reply(550, "%s", (char *) $4); else if ((stbuf.st_mode&S_IFMT) != S_IFREG) { reply(550, "%s: not a plain file.", (char *) $4); } else { register struct tm *t; struct tm *gmtime(); t = gmtime(&stbuf.st_mtime); reply(213, "19%02d%02d%02d%02d%02d%02d", t->tm_year, t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); } } if ($4 != NULL) free((char *) $4); } | QUIT CRLF = { reply(221, "Goodbye."); dologout(0); } | error CRLF = { yyerrok; } ; rcmd: RNFR check_login SP pathname CRLF = { char *renamefrom(); restart_point = (off_t) 0; if ($2 && $4) { fromname = renamefrom((char *) $4); if (fromname == (char *) 0 && $4) { free((char *) $4); } } } | REST SP STRING CRLF = { long atol(); fromname = (char *) 0; restart_point = atol($3); reply(350, "Restarting at %ld. %s", restart_point, "Send STORE or RETRIEVE to initiate transfer."); } ; username: STRING ; password: /* empty */ = { *(char **)&($$) = (char *)calloc(1, sizeof (char)); } | STRING ; byte_size: NUMBER ; host_port: NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER = { register char *a, *p; a = (char *)&data_dest.sin_addr; a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7; p = (char *)&data_dest.sin_port; p[0] = $9; p[1] = $11; data_dest.sin_family = AF_INET; } ; form_code: N = { $$ = FORM_N; } | T = { $$ = FORM_T; } | C = { $$ = FORM_C; } ; type_code: A = { cmd_type = TYPE_A; cmd_form = FORM_N; } | A SP form_code = { cmd_type = TYPE_A; cmd_form = $3; } | E = { cmd_type = TYPE_E; cmd_form = FORM_N; } | E SP form_code = { cmd_type = TYPE_E; cmd_form = $3; } | I = { cmd_type = TYPE_I; } | L = { cmd_type = TYPE_L; cmd_bytesz = NBBY; } | L SP byte_size = { cmd_type = TYPE_L; cmd_bytesz = $3; } /* this is for a bug in the BBN ftp */ | L byte_size = { cmd_type = TYPE_L; cmd_bytesz = $2; } ; struct_code: F = { $$ = STRU_F; } | R = { $$ = STRU_R; } | P = { $$ = STRU_P; } ; mode_code: S = { $$ = MODE_S; } | B = { $$ = MODE_B; } | C = { $$ = MODE_C; } ; pathname: pathstring = { /* * Problem: this production is used for all pathname * processing, but only gives a 550 error reply. * This is a valid reply in some cases but not in others. */ if (logged_in && $1 && strncmp((char *) $1, "~", 1) == 0) { *(char **)&($$) = *glob((char *) $1); if (globerr != NULL) { reply(550, globerr); $$ = NULL; } free((char *) $1); } else $$ = $1; } ; pathstring: STRING ; octal_number: NUMBER = { register int ret, dec, multby, digit; /* * Convert a number that was read as decimal number * to what it would be if it had been read as octal. */ dec = $1; multby = 1; ret = 0; while (dec) { digit = dec%10; if (digit > 7) { ret = -1; break; } ret += digit * multby; multby *= 8; dec /= 10; } $$ = ret; } ; check_login: /* empty */ = { if (logged_in) $$ = 1; else { reply(530, "Please login with USER and PASS."); $$ = 0; } } ; %% extern jmp_buf errcatch; #define CMD 0 /* beginning of command */ #define ARGS 1 /* expect miscellaneous arguments */ #define STR1 2 /* expect SP followed by STRING */ #define STR2 3 /* expect STRING */ #define OSTR 4 /* optional SP then STRING */ #define ZSTR1 5 /* SP then optional STRING */ #define ZSTR2 6 /* optional STRING after SP */ #define SITECMD 7 /* SITE command */ #define NSTR 8 /* Number followed by a string */ struct tab { char *name; short token; short state; short implemented; /* 1 if command is implemented */ char *help; }; struct tab cmdtab[] = { /* In order defined in RFC 765 */ { "USER", USER, STR1, 1, " username" }, { "PASS", PASS, ZSTR1, 1, " password" }, { "ACCT", ACCT, STR1, 0, "(specify account)" }, { "SMNT", SMNT, ARGS, 0, "(structure mount)" }, { "REIN", REIN, ARGS, 0, "(reinitialize server state)" }, { "QUIT", QUIT, ARGS, 1, "(terminate service)", }, { "PORT", PORT, ARGS, 1, " b0, b1, b2, b3, b4" }, { "PASV", PASV, ARGS, 1, "(set server in passive mode)" }, { "TYPE", TYPE, ARGS, 1, " [ A | E | I | L ]" }, { "STRU", STRU, ARGS, 1, "(specify file structure)" }, { "MODE", MODE, ARGS, 1, "(specify transfer mode)" }, { "RETR", RETR, STR1, 1, " file-name" }, { "STOR", STOR, STR1, 1, " file-name" }, { "APPE", APPE, STR1, 1, " file-name" }, { "MLFL", MLFL, OSTR, 0, "(mail file)" }, { "MAIL", MAIL, OSTR, 0, "(mail to user)" }, { "MSND", MSND, OSTR, 0, "(mail send to terminal)" }, { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" }, { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" }, { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" }, { "MRCP", MRCP, STR1, 0, "(mail recipient)" }, { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" }, { "REST", REST, STR1, 1, "(restart command)" }, { "RNFR", RNFR, STR1, 1, " file-name" }, { "RNTO", RNTO, STR1, 1, " file-name" }, { "ABOR", ABOR, ARGS, 1, "(abort operation)" }, { "DELE", DELE, STR1, 1, " file-name" }, { "CWD", CWD, OSTR, 1, "[ directory-name ]" }, { "XCWD", CWD, OSTR, 1, "[ directory-name ]" }, { "LIST", LIST, OSTR, 1, "[ path-name ]" }, { "NLST", NLST, OSTR, 1, "[ path-name ]" }, { "SITE", SITE, SITECMD, 1, "site-cmd [ arguments ]" }, { "SYST", SYST, ARGS, 1, "(get type of operating system)" }, { "STAT", STAT, OSTR, 1, "[ path-name ]" }, { "HELP", HELP, OSTR, 1, "[ ]" }, { "NOOP", NOOP, ARGS, 1, "" }, { "MKD", MKD, STR1, 1, " path-name" }, { "XMKD", MKD, STR1, 1, " path-name" }, { "RMD", RMD, STR1, 1, " path-name" }, { "XRMD", RMD, STR1, 1, " path-name" }, { "PWD", PWD, ARGS, 1, "(return current directory)" }, { "XPWD", PWD, ARGS, 1, "(return current directory)" }, { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" }, { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" }, { "STOU", STOU, STR1, 1, " file-name" }, { "SIZE", SIZE, OSTR, 1, " path-name" }, { "MDTM", MDTM, OSTR, 1, " path-name" }, { NULL, 0, 0, 0, 0 } }; struct tab sitetab[] = { { "UMASK", UMASK, ARGS, 1, "[ umask ]" }, { "IDLE", IDLE, ARGS, 1, "[ maximum-idle-time ]" }, { "CHMOD", CHMOD, NSTR, 1, " mode file-name" }, { "HELP", HELP, OSTR, 1, "[ ]" }, { NULL, 0, 0, 0, 0 } }; struct tab * lookup(p, cmd) register struct tab *p; char *cmd; { for (; p->name != NULL; p++) if (strcmp(cmd, p->name) == 0) return (p); return (0); } #include /* * getline - a hacked up version of fgets to ignore TELNET escape codes. */ char * getline(s, n, iop) char *s; register FILE *iop; { register c; register char *cs; cs = s; /* tmpline may contain saved command from urgent mode interruption */ for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) { *cs++ = tmpline[c]; if (tmpline[c] == '\n') { *cs++ = '\0'; if (debug) syslog(LOG_DEBUG, "command: %s", s); tmpline[0] = '\0'; return(s); } if (c == 0) tmpline[0] = '\0'; } while ((c = getc(iop)) != EOF) { c &= 0377; if (c == IAC) { if ((c = getc(iop)) != EOF) { c &= 0377; switch (c) { case WILL: case WONT: c = getc(iop); printf("%c%c%c", IAC, DONT, 0377&c); (void) fflush(stdout); continue; case DO: case DONT: c = getc(iop); printf("%c%c%c", IAC, WONT, 0377&c); (void) fflush(stdout); continue; case IAC: break; default: continue; /* ignore command */ } } } *cs++ = c; if (--n <= 0 || c == '\n') break; } if (c == EOF && cs == s) return (NULL); *cs++ = '\0'; if (debug) syslog(LOG_DEBUG, "command: %s", s); return (s); } static int toolong() { time_t now; extern char *ctime(); extern time_t time(); reply(421, "Timeout (%d seconds): closing control connection.", timeout); (void) time(&now); if (logging) { syslog(LOG_INFO, "User %s timed out after %d seconds at %s", (pw ? pw -> pw_name : "unknown"), timeout, ctime(&now)); } dologout(1); } yylex() { static int cpos, state; register char *cp, *cp2; register struct tab *p; int n; char c, *strpbrk(); char *copy(); for (;;) { switch (state) { case CMD: (void) signal(SIGALRM, toolong); (void) alarm((unsigned) timeout); if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) { reply(221, "You could at least say goodbye."); dologout(0); } (void) alarm(0); #ifdef SETPROCTITLE if (strncasecmp(cbuf, "PASS", 4) != NULL) setproctitle("%s: %s", proctitle, cbuf); #endif /* SETPROCTITLE */ if ((cp = index(cbuf, '\r'))) { *cp++ = '\n'; *cp = '\0'; } if ((cp = strpbrk(cbuf, " \n"))) cpos = cp - cbuf; if (cpos == 0) cpos = 4; c = cbuf[cpos]; cbuf[cpos] = '\0'; upper(cbuf); p = lookup(cmdtab, cbuf); cbuf[cpos] = c; if (p != 0) { if (p->implemented == 0) { nack(p->name); longjmp(errcatch,0); /* NOTREACHED */ } state = p->state; *(char **)&yylval = p->name; return (p->token); } break; case SITECMD: if (cbuf[cpos] == ' ') { cpos++; return (SP); } cp = &cbuf[cpos]; if ((cp2 = strpbrk(cp, " \n"))) cpos = cp2 - cbuf; c = cbuf[cpos]; cbuf[cpos] = '\0'; upper(cp); p = lookup(sitetab, cp); cbuf[cpos] = c; if (p != 0) { if (p->implemented == 0) { state = CMD; nack(p->name); longjmp(errcatch,0); /* NOTREACHED */ } state = p->state; *(char **)&yylval = p->name; return (p->token); } state = CMD; break; case OSTR: if (cbuf[cpos] == '\n') { state = CMD; return (CRLF); } /* FALLTHROUGH */ case STR1: case ZSTR1: dostr1: if (cbuf[cpos] == ' ') { cpos++; state = state == OSTR ? STR2 : ++state; return (SP); } break; case ZSTR2: if (cbuf[cpos] == '\n') { state = CMD; return (CRLF); } /* FALLTHROUGH */ case STR2: cp = &cbuf[cpos]; n = strlen(cp); cpos += n - 1; /* * Make sure the string is nonempty and \n terminated. */ if (n > 1 && cbuf[cpos] == '\n') { cbuf[cpos] = '\0'; *(char **)&yylval = copy(cp); cbuf[cpos] = '\n'; state = ARGS; return (STRING); } break; case NSTR: if (cbuf[cpos] == ' ') { cpos++; return (SP); } if (isdigit(cbuf[cpos])) { cp = &cbuf[cpos]; while (isdigit(cbuf[++cpos])) ; c = cbuf[cpos]; cbuf[cpos] = '\0'; yylval = atoi(cp); cbuf[cpos] = c; state = STR1; return (NUMBER); } state = STR1; goto dostr1; case ARGS: if (isdigit(cbuf[cpos])) { cp = &cbuf[cpos]; while (isdigit(cbuf[++cpos])) ; c = cbuf[cpos]; cbuf[cpos] = '\0'; yylval = atoi(cp); cbuf[cpos] = c; return (NUMBER); } switch (cbuf[cpos++]) { case '\n': state = CMD; return (CRLF); case ' ': return (SP); case ',': return (COMMA); case 'A': case 'a': return (A); case 'B': case 'b': return (B); case 'C': case 'c': return (C); case 'E': case 'e': return (E); case 'F': case 'f': return (F); case 'I': case 'i': return (I); case 'L': case 'l': return (L); case 'N': case 'n': return (N); case 'P': case 'p': return (P); case 'R': case 'r': return (R); case 'S': case 's': return (S); case 'T': case 't': return (T); } break; default: fatal("Unknown state in scanner."); } yyerror((char *) 0); state = CMD; longjmp(errcatch,0); } } upper(s) register char *s; { while (*s != '\0') { if (islower(*s)) *s = toupper(*s); s++; } } char * copy(s) char *s; { char *p; extern char *malloc(), *strcpy(); p = malloc((unsigned) strlen(s) + 1); if (p == NULL) fatal("Ran out of memory."); (void) strcpy(p, s); return (p); } help(ctab, s) struct tab *ctab; char *s; { register struct tab *c; register int width, NCMDS; char *type; if (ctab == sitetab) type = "SITE "; else type = ""; width = 0, NCMDS = 0; for (c = ctab; c->name != NULL; c++) { int len = strlen(c->name); if (len > width) width = len; NCMDS++; } width = (width + 8) &~ 7; if (s == 0) { register int i, j, w; int columns, lines; lreply(214, "The following %scommands are recognized %s.", type, "(* =>'s unimplemented)"); columns = 76 / width; if (columns == 0) columns = 1; lines = (NCMDS + columns - 1) / columns; for (i = 0; i < lines; i++) { printf(" "); for (j = 0; j < columns; j++) { c = ctab + j * lines + i; printf("%s%c", c->name, c->implemented ? ' ' : '*'); if (c + lines >= &ctab[NCMDS]) break; w = strlen(c->name) + 1; while (w < width) { putchar(' '); w++; } } printf("\r\n"); } (void) fflush(stdout); reply(214, "Direct comments to ftp-bugs@%s.", hostname); return; } upper(s); c = lookup(ctab, s); if (c == (struct tab *)0) { reply(502, "Unknown command %s.", s); return; } if (c->implemented) reply(214, "Syntax: %s%s %s", type, c->name, c->help); else reply(214, "%s%-*s\t%s; unimplemented.", type, width, c->name, c->help); } sizecmd(filename) char *filename; { switch (type) { case TYPE_L: case TYPE_I: { struct stat stbuf; if (stat(filename, &stbuf) < 0 || (stbuf.st_mode&S_IFMT) != S_IFREG) reply(550, "%s: not a plain file.", filename); else reply(213, "%lu", stbuf.st_size); break;} case TYPE_A: { FILE *fin; register int c; long count; struct stat stbuf; fin = fopen(filename, "r"); if (fin == NULL) { perror_reply(550, filename); return; } if (fstat(fileno(fin), &stbuf) < 0 || (stbuf.st_mode&S_IFMT) != S_IFREG) { reply(550, "%s: not a plain file.", filename); (void) fclose(fin); return; } count = 0; while((c=getc(fin)) != EOF) { if (c == '\n') /* will get expanded to \r\n */ count++; count++; } (void) fclose(fin); reply(213, "%ld", count); break;} default: reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); } } ARGS, 1, "(terminate service)", }, { "PORT", PORT, ARGS, 1, " b0, b1, b2, b3, b4" }, { "PASV", PASV, ARGS, 1, "(set server in passive mode)" }, { "TYPE", TYPE, ARGS, 1, " [ A | E | I | L ]" }, { "STRU", STRU, ARGSetc/ftpd/ftpd.8 444 0 3 14622 4403276106 6573 .\" Copyright (c) 1985, 1988 The Regents of the University of California. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms are permitted .\" provided that the above copyright notice and this paragraph are .\" duplicated in all such forms and that any documentation, .\" advertising materials, and other materials related to such .\" distribution and use acknowledge that the software was developed .\" by the University of California, Berkeley. The name of the .\" University may not be used to endorse or promote products derived .\" from this software without specific prior written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED .\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .\" @(#)ftpd.8 6.7 (Berkeley) 2/28/89 .\" .TH FTPD 8 "February 23, 1989" .UC 5 .SH NAME ftpd \- DARPA Internet File Transfer Protocol server .SH SYNOPSIS .B /etc/ftpd [ .B \-d ] [ .B \-l ] [ .BR \-t timeout ] [ .BR \-T maxtimeout ] .SH DESCRIPTION .I Ftpd is the DARPA Internet File Transfer Protocol server process. The server uses the TCP protocol and listens at the port specified in the ``ftp'' service specification; see .IR services (5). .PP If the .B \-d option is specified, debugging information is written to the syslog. .PP If the .B \-l option is specified, each ftp session is logged in the syslog. .PP The ftp server will timeout an inactive session after 15 minutes. If the .B \-t option is specified, the inactivity timeout period will be set to .I timeout seconds. A client may also request a different timeout period; the maximum period allowed may be set to .I timeout seconds with the .B \-T option. The default limit is 2 hours. .PP The ftp server currently supports the following ftp requests; case is not distinguished. .PP .nf .ta \w'Request 'u \fBRequest Description\fP ABOR abort previous command ACCT specify account (ignored) ALLO allocate storage (vacuously) APPE append to a file CDUP change to parent of current working directory CWD change working directory DELE delete a file HELP give help information LIST give list files in a directory (``ls -lgA'') MKD make a directory MDTM show last modification time of file MODE specify data transfer \fImode\fP NLST give name list of files in directory NOOP do nothing PASS specify password PASV prepare for server-to-server transfer PORT specify data connection port PWD print the current working directory QUIT terminate session REST restart incomplete transfer RETR retrieve a file RMD remove a directory RNFR specify rename-from file name RNTO specify rename-to file name SITE non-standard commands (see next section) SIZE return size of file STAT return status of server STOR store a file STOU store a file with a unique name STRU specify data transfer \fIstructure\fP SYST show operating system type of server system TYPE specify data transfer \fItype\fP USER specify user name XCUP change to parent of current working directory (deprecated) XCWD change working directory (deprecated) XMKD make a directory (deprecated) XPWD print the current working directory (deprecated) XRMD remove a directory (deprecated) .fi .PP The following non-standard or UNIX specific commands are supported by the SITE request. .PP .nf .ta \w'Request 'u \fBRequest Description\fP UMASK change umask. \fIE.g.\fP SITE UMASK 002 IDLE set idle-timer. \fIE.g.\fP SITE IDLE 60 CHMOD change mode of a file. \fIE.g.\fP SITE CHMOD 755 filename HELP give help information. \fIE.g.\fP SITE HELP .fi .PP The remaining ftp requests specified in Internet RFC 959 are recognized, but not implemented. MDTM and SIZE are not specified in RFC 959, but will appear in the next updated FTP RFC. .PP The ftp server will abort an active file transfer only when the ABOR command is preceded by a Telnet "Interrupt Process" (IP) signal and a Telnet "Synch" signal in the command Telnet stream, as described in Internet RFC 959. If a STAT command is received during a data transfer, preceded by a Telnet IP and Synch, transfer status will be returned. .PP .I Ftpd interprets file names according to the ``globbing'' conventions used by .IR csh (1). This allows users to utilize the metacharacters ``*?[]{}~''. .PP .I Ftpd authenticates users according to three rules. .IP 1) The user name must be in the password data base, .IR /etc/passwd , and not have a null password. In this case a password must be provided by the client before any file operations may be performed. .IP 2) The user name must not appear in the file .IR /etc/ftpusers . .IP 3) The user must have a standard shell returned by .IR getusershell (3). .IP 4) If the user name is ``anonymous'' or ``ftp'', an anonymous ftp account must be present in the password file (user ``ftp''). In this case the user is allowed to log in by specifying any password (by convention this is given as the client host's name). .PP In the last case, .I ftpd takes special measures to restrict the client's access privileges. The server performs a .IR chroot (2) command to the home directory of the ``ftp'' user. In order that system security is not breached, it is recommended that the ``ftp'' subtree be constructed with care; the following rules are recommended. .IP ~ftp) Make the home directory owned by ``ftp'' and unwritable by anyone. .IP ~ftp/bin) Make this directory owned by the super-user and unwritable by anyone. The program .IR ls (1) must be present to support the list command. This program should have mode 111. .IP ~ftp/etc) Make this directory owned by the super-user and unwritable by anyone. The files .IR passwd (5) and .IR group (5) must be present for the .I ls command to be able to produce owner names rather than numbers. The password field in .I passwd is not used, and should not contain real encrypted passwords. These files should be mode 444. .IP ~ftp/pub) Make this directory mode 777 and owned by ``ftp''. Users should then place files which are to be accessible via the anonymous account in this directory. .SH "SEE ALSO" ftp(1), getusershell(3), syslogd(8) .SH BUGS The anonymous account is inherently dangerous and should avoided when possible. .PP The server must run as the super-user to create sockets with privileged port numbers. It maintains an effective user id of the logged in user, reverting to the super-user only when binding addresses to sockets. The possible security holes have been extensively scrutinized, but are possibly incomplete. at the software was developed .\" by the University of California, Berkeley. The name of the .\" University metc/ftpd/ftpd.c 444 0 12 74676 5472566073 6721 /* * Copyright (c) 1985, 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1985, 1988 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)ftpd.c 5.28.1 (2.11BSD) 11/17/93"; #endif /* * FTP server. */ #include #include #include #include #include #include #include #include #define FTP_NAMES #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 64 #endif #if defined(sun) && !defined(FD_SET) /* FD_SET being defined is a cheap way of determining if we are on 4.0 or not */ typedef int uid_t; typedef int gid_t; #endif /* * File containing login names * NOT to be used on this machine. * Commonly used to disallow uucp. */ extern int errno; extern char *sys_errlist[]; extern int sys_nerr; extern char *crypt(); extern char version[]; extern char *home; /* pointer to home directory for glob */ extern FILE *ftpd_popen(), *fopen(), *freopen(); extern int ftpd_pclose(), fclose(); extern char *getline(); extern char cbuf[]; extern off_t restart_point; struct sockaddr_in ctrl_addr; struct sockaddr_in data_source; struct sockaddr_in data_dest; struct sockaddr_in his_addr; struct sockaddr_in pasv_addr; int data; jmp_buf errcatch, urgcatch; int logged_in; struct passwd *pw; int debug; int timeout = 900; /* timeout after 15 minutes of inactivity */ int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ int logging; int guest; int type; int form; int stru; /* avoid C keyword */ int mode; int usedefault = 1; /* for data transfers */ int pdata = -1; /* for passive mode */ int transflag; off_t file_size; off_t byte_count; #if !defined(CMASK) || CMASK == 0 #undef CMASK #define CMASK 027 #endif int defumask = CMASK; /* default umask value */ char tmpline[7]; char hostname[MAXHOSTNAMELEN]; char remotehost[MAXHOSTNAMELEN]; /* * Timeout intervals for retrying connections * to hosts that don't accept PORT cmds. This * is a kludge, but given the problems with TCP... */ #define SWAITMAX 90 /* wait at most 90 seconds */ #define SWAITINT 5 /* interval between retries */ int swaitmax = SWAITMAX; int swaitint = SWAITINT; int lostconn(); int myoob(); FILE *getdatasock(), *dataconn(); #ifdef SETPROCTITLE char **Argv = NULL; /* pointer to argument vector */ char *LastArgv = NULL; /* end of argv */ char proctitle[BUFSIZ]; /* initial part of title */ #endif /* SETPROCTITLE */ main(argc, argv, envp) int argc; char *argv[]; char **envp; { int addrlen, on = 1; char *cp; /* * LOG_NDELAY sets up the logging connection immediately, * necessary for anonymous ftp's that chroot and can't do it later. */ openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_DAEMON); addrlen = sizeof (his_addr); if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); exit(1); } addrlen = sizeof (ctrl_addr); if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); exit(1); } data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); debug = 0; #ifdef SETPROCTITLE /* * Save start and extent of argv for setproctitle. */ Argv = argv; while (*envp) envp++; LastArgv = envp[-1] + strlen(envp[-1]); #endif /* SETPROCTITLE */ argc--, argv++; while (argc > 0 && *argv[0] == '-') { for (cp = &argv[0][1]; *cp; cp++) switch (*cp) { case 'v': debug = 1; break; case 'd': debug = 1; break; case 'l': logging = 1; break; case 't': timeout = atoi(++cp); if (maxtimeout < timeout) maxtimeout = timeout; goto nextopt; case 'T': maxtimeout = atoi(++cp); if (timeout > maxtimeout) timeout = maxtimeout; goto nextopt; case 'u': { int val = 0; while (*++cp && *cp >= '0' && *cp <= '9') val = val*8 + *cp - '0'; if (*cp) fprintf(stderr, "ftpd: Bad value for -u\n"); else defumask = val; goto nextopt; } default: fprintf(stderr, "ftpd: Unknown flag -%c ignored.\n", *cp); break; } nextopt: argc--, argv++; } (void) freopen(_PATH_DEVNULL, "w", stderr); (void) signal(SIGPIPE, lostconn); (void) signal(SIGCHLD, SIG_IGN); if ((int)signal(SIGURG, myoob) < 0) syslog(LOG_ERR, "signal: %m"); /* handle urgent data inline */ /* Sequent defines this, but it doesn't work */ #ifdef SO_OOBINLINE if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0) syslog(LOG_ERR, "setsockopt: %m"); #endif #ifdef F_SETOWN if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) syslog(LOG_ERR, "fcntl F_SETOWN: %m"); #endif dolog(&his_addr); /* * Set up default state */ data = -1; type = TYPE_A; form = FORM_N; stru = STRU_F; mode = MODE_S; tmpline[0] = '\0'; (void) gethostname(hostname, sizeof (hostname)); reply(220, "%s FTP server (%s) ready.", hostname, version); (void) setjmp(errcatch); for (;;) (void) yyparse(); /* NOTREACHED */ } lostconn() { if (debug) syslog(LOG_DEBUG, "lost connection"); dologout(-1); } static char ttyline[20]; /* * Helper function for sgetpwnam(). */ char * sgetsave(s) char *s; { char *malloc(); char *new = malloc((unsigned) strlen(s) + 1); if (new == NULL) { perror_reply(421, "Local resource failure: malloc"); dologout(1); /* NOTREACHED */ } (void) strcpy(new, s); return (new); } /* * Save the result of a getpwnam. Used for USER command, since * the data returned must not be clobbered by any other command * (e.g., globbing). */ struct passwd * sgetpwnam(name) char *name; { static struct passwd save; register struct passwd *p; char *sgetsave(); if ((p = getpwnam(name)) == NULL) return (p); if (save.pw_name) { free(save.pw_name); free(save.pw_passwd); free(save.pw_gecos); free(save.pw_dir); free(save.pw_shell); } save = *p; save.pw_name = sgetsave(p->pw_name); save.pw_passwd = sgetsave(p->pw_passwd); save.pw_gecos = sgetsave(p->pw_gecos); save.pw_dir = sgetsave(p->pw_dir); save.pw_shell = sgetsave(p->pw_shell); return (&save); } int login_attempts; /* number of failed login attempts */ int askpasswd; /* had user command, ask for passwd */ /* * USER command. * Sets global passwd pointer pw if named account exists * and is acceptable; sets askpasswd if a PASS command is * expected. If logged in previously, need to reset state. * If name is "ftp" or "anonymous" and ftp account exists, * set guest and pw, then just return. * If account doesn't exist, ask for passwd anyway. * Otherwise, check user requesting login privileges. * Disallow anyone who does not have a standard * shell as returned by getusershell(). * Disallow anyone mentioned in the file _PATH_FTPUSERS * to allow people such as root and uucp to be avoided. */ user(name) char *name; { register char *cp; FILE *fd; char *shell; char line[BUFSIZ], *getusershell(); if (logged_in) { if (guest) { reply(530, "Can't change user from guest login."); return; } end_login(); } guest = 0; if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { if ((pw = sgetpwnam("ftp")) != NULL) { guest = 1; askpasswd = 1; reply(331, "Guest login ok, send ident as password."); } else reply(530, "User %s unknown.", name); return; } if (pw = sgetpwnam(name)) { if ((shell = pw->pw_shell) == NULL || *shell == 0) shell = _PATH_BSHELL; while ((cp = getusershell()) != NULL) if (strcmp(cp, shell) == 0) break; endusershell(); if (cp == NULL) { reply(530, "User %s access denied.", name); if (logging) syslog(LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s", remotehost, name); pw = (struct passwd *) NULL; return; } if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) { while (fgets(line, sizeof (line), fd) != NULL) { if ((cp = index(line, '\n')) != NULL) *cp = '\0'; if (strcmp(line, name) == 0) { reply(530, "User %s access denied.", name); if (logging) syslog(LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s", remotehost, name); pw = (struct passwd *) NULL; return; } } } (void) fclose(fd); } reply(331, "Password required for %s.", name); askpasswd = 1; /* * Delay before reading passwd after first failed * attempt to slow down passwd-guessing programs. */ if (login_attempts) sleep((unsigned) login_attempts); } /* * Terminate login as previous user, if any, resetting state; * used when USER command is given or login fails. */ end_login() { (void) seteuid((uid_t)0); if (logged_in) logwtmp(ttyline, "", ""); pw = NULL; logged_in = 0; guest = 0; } pass(passwd) char *passwd; { char *xpasswd, *salt; if (logged_in || askpasswd == 0) { reply(503, "Login with USER first."); return; } askpasswd = 0; if (!guest) { /* "ftp" is only account allowed no password */ if (pw == NULL) salt = "xx"; else salt = pw->pw_passwd; xpasswd = crypt(passwd, salt); /* The strcmp does not catch null passwords! */ if (pw == NULL || *pw->pw_passwd == '\0' || strcmp(xpasswd, pw->pw_passwd)) { reply(530, "Login incorrect."); pw = NULL; if (login_attempts++ >= 5) { syslog(LOG_NOTICE, "repeated login failures from %s", remotehost); exit(0); } return; } } login_attempts = 0; /* this time successful */ (void) setegid((gid_t)pw->pw_gid); (void) initgroups(pw->pw_name, pw->pw_gid); /* open wtmp before chroot */ (void)sprintf(ttyline, "ftp%d", getpid()); logwtmp(ttyline, pw->pw_name, remotehost); logged_in = 1; if (guest) { /* * We MUST do a chdir() after the chroot. Otherwise * the old current directory will be accessible as "." * outside the new root! */ if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { reply(550, "Can't set guest privileges."); goto bad; } } else if (chdir(pw->pw_dir) < 0) { if (chdir("/") < 0) { reply(530, "User %s: can't change directory to %s.", pw->pw_name, pw->pw_dir); goto bad; } else lreply(230, "No directory! Logging in with home=/"); } if (seteuid((uid_t)pw->pw_uid) < 0) { reply(550, "Can't set uid."); goto bad; } if (guest) { reply(230, "Guest login ok, access restrictions apply."); #ifdef SETPROCTITLE sprintf(proctitle, "%s: anonymous/%.*s", remotehost, sizeof(proctitle) - sizeof(remotehost) - sizeof(": anonymous/"), passwd); setproctitle(proctitle); #endif /* SETPROCTITLE */ if (logging) syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", remotehost, passwd); } else { reply(230, "User %s logged in.", pw->pw_name); #ifdef SETPROCTITLE sprintf(proctitle, "%s: %s", remotehost, pw->pw_name); setproctitle(proctitle); #endif /* SETPROCTITLE */ if (logging) syslog(LOG_INFO, "FTP LOGIN FROM %s, %s", remotehost, pw->pw_name); } home = pw->pw_dir; /* home dir for globbing */ (void) umask(defumask); return; bad: /* Forget all about it... */ end_login(); } retrieve(cmd, name) char *cmd, *name; { FILE *fin, *dout; struct stat st; int (*closefunc)(); if (cmd == 0) { fin = fopen(name, "r"), closefunc = fclose; st.st_size = 0; } else { char line[BUFSIZ]; (void) sprintf(line, cmd, name), name = line; fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; st.st_size = -1; st.st_blksize = BUFSIZ; } if (fin == NULL) { if (errno != 0) perror_reply(550, name); return; } if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || (st.st_mode&S_IFMT) != S_IFREG)) { reply(550, "%s: not a plain file.", name); goto done; } if (restart_point) { if (type == TYPE_A) { register int i, n, c; n = restart_point; i = 0; while (i++ < n) { if ((c=getc(fin)) == EOF) { perror_reply(550, name); goto done; } if (c == '\n') i++; } } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { perror_reply(550, name); goto done; } } dout = dataconn(name, st.st_size, "w"); if (dout == NULL) goto done; send_data(fin, dout, st.st_blksize); (void) fclose(dout); data = -1; pdata = -1; done: (*closefunc)(fin); } store(name, mode, unique) char *name, *mode; int unique; { FILE *fout, *din; struct stat st; int (*closefunc)(); char *gunique(); if (unique && stat(name, &st) == 0 && (name = gunique(name)) == NULL) return; if (restart_point) mode = "r+w"; fout = fopen(name, mode); closefunc = fclose; if (fout == NULL) { perror_reply(553, name); return; } if (restart_point) { if (type == TYPE_A) { register int i, n, c; n = restart_point; i = 0; while (i++ < n) { if ((c=getc(fout)) == EOF) { perror_reply(550, name); goto done; } if (c == '\n') i++; } /* * We must do this seek to "current" position * because we are changing from reading to * writing. */ if (fseek(fout, 0L, L_INCR) < 0) { perror_reply(550, name); goto done; } } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { perror_reply(550, name); goto done; } } din = dataconn(name, (off_t)-1, "r"); if (din == NULL) goto done; if (receive_data(din, fout) == 0) { if (unique) reply(226, "Transfer complete (unique file name:%s).", name); else reply(226, "Transfer complete."); } (void) fclose(din); data = -1; pdata = -1; done: (*closefunc)(fout); } FILE * getdatasock(mode) char *mode; { int s, on = 1, tries; if (data >= 0) return (fdopen(data, mode)); s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) return (NULL); (void) seteuid((uid_t)0); if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) goto bad; /* anchor socket to avoid multi-homing problems */ data_source.sin_family = AF_INET; data_source.sin_addr = ctrl_addr.sin_addr; for (tries = 1; ; tries++) { if (bind(s, (struct sockaddr *)&data_source, sizeof (data_source)) >= 0) break; if (errno != EADDRINUSE || tries > 10) goto bad; sleep(tries); } (void) seteuid((uid_t)pw->pw_uid); return (fdopen(s, mode)); bad: (void) seteuid((uid_t)pw->pw_uid); (void) close(s); return (NULL); } FILE * dataconn(name, size, mode) char *name; off_t size; char *mode; { char sizebuf[32]; FILE *file; int retry = 0; file_size = size; byte_count = 0; if (size != (off_t) -1) (void) sprintf (sizebuf, " (%ld bytes)", size); else (void) strcpy(sizebuf, ""); if (pdata >= 0) { struct sockaddr_in from; int s, fromlen = sizeof(from); s = accept(pdata, (struct sockaddr *)&from, &fromlen); if (s < 0) { reply(425, "Can't open data connection."); (void) close(pdata); pdata = -1; return(NULL); } (void) close(pdata); pdata = s; reply(150, "Opening %s mode data connection for %s%s.", type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); return(fdopen(pdata, mode)); } if (data >= 0) { reply(125, "Using existing data connection for %s%s.", name, sizebuf); usedefault = 1; return (fdopen(data, mode)); } if (usedefault) data_dest = his_addr; usedefault = 1; file = getdatasock(mode); if (file == NULL) { reply(425, "Can't create data socket (%s,%d): %s.", inet_ntoa(data_source.sin_addr), ntohs(data_source.sin_port), errno < sys_nerr ? sys_errlist[errno] : "unknown error"); return (NULL); } data = fileno(file); while (connect(data, (struct sockaddr *)&data_dest, sizeof (data_dest)) < 0) { if (errno == EADDRINUSE && retry < swaitmax) { sleep((unsigned) swaitint); retry += swaitint; continue; } perror_reply(425, "Can't build data connection"); (void) fclose(file); data = -1; return (NULL); } reply(150, "Opening %s mode data connection for %s%s.", type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); return (file); } /* * Tranfer the contents of "instr" to * "outstr" peer using the appropriate * encapsulation of the data subject * to Mode, Structure, and Type. * * NB: Form isn't handled. */ send_data(instr, outstr, blksize) FILE *instr, *outstr; off_t blksize; { register int c, cnt; register char *buf; int netfd, filefd; transflag++; if (setjmp(urgcatch)) { transflag = 0; return; } switch (type) { case TYPE_A: while ((c = getc(instr)) != EOF) { byte_count++; if (c == '\n') { if (ferror(outstr)) goto data_err; (void) putc('\r', outstr); } (void) putc(c, outstr); } fflush(outstr); transflag = 0; if (ferror(instr)) goto file_err; if (ferror(outstr)) goto data_err; reply(226, "Transfer complete."); return; case TYPE_I: case TYPE_L: if ((buf = (char *) malloc((u_int)blksize)) == NULL) { transflag = 0; perror_reply(451, "Local resource failure: malloc"); return; } netfd = fileno(outstr); filefd = fileno(instr); while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && write(netfd, buf, cnt) == cnt) byte_count += cnt; transflag = 0; (void)free(buf); if (cnt != 0) { if (cnt < 0) goto file_err; goto data_err; } reply(226, "Transfer complete."); return; default: transflag = 0; reply(550, "Unimplemented TYPE %d in send_data", type); return; } data_err: transflag = 0; perror_reply(426, "Data connection"); return; file_err: transflag = 0; perror_reply(551, "Error on input file"); } /* * Transfer data from peer to * "outstr" using the appropriate * encapulation of the data subject * to Mode, Structure, and Type. * * N.B.: Form isn't handled. */ receive_data(instr, outstr) FILE *instr, *outstr; { register int c; int cnt, bare_lfs = 0; char buf[BUFSIZ]; transflag++; if (setjmp(urgcatch)) { transflag = 0; return (-1); } switch (type) { case TYPE_I: case TYPE_L: while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) { if (write(fileno(outstr), buf, cnt) != cnt) goto file_err; byte_count += cnt; } if (cnt < 0) goto data_err; transflag = 0; return (0); case TYPE_E: reply(553, "TYPE E not implemented."); transflag = 0; return (-1); case TYPE_A: while ((c = getc(instr)) != EOF) { byte_count++; if (c == '\n') bare_lfs++; while (c == '\r') { if (ferror(outstr)) goto data_err; if ((c = getc(instr)) != '\n') { (void) putc ('\r', outstr); if (c == '\0' || c == EOF) goto contin2; } } (void) putc(c, outstr); contin2: ; } fflush(outstr); if (ferror(instr)) goto data_err; if (ferror(outstr)) goto file_err; transflag = 0; if (bare_lfs) { lreply(226, "WARNING! %d bare linefeeds received in ASCII mode", bare_lfs); printf(" File may not have transferred correctly.\r\n"); } return (0); default: reply(550, "Unimplemented TYPE %d in receive_data", type); transflag = 0; return (-1); } data_err: transflag = 0; perror_reply(426, "Data Connection"); return (-1); file_err: transflag = 0; perror_reply(452, "Error writing file"); return (-1); } statfilecmd(filename) char *filename; { char line[BUFSIZ]; FILE *fin; int c; (void) sprintf(line, "/bin/ls -lgA %s", filename); fin = ftpd_popen(line, "r"); lreply(211, "status of %s:", filename); while ((c = getc(fin)) != EOF) { if (c == '\n') { if (ferror(stdout)){ perror_reply(421, "control connection"); (void) ftpd_pclose(fin); dologout(1); /* NOTREACHED */ } if (ferror(fin)) { perror_reply(551, filename); (void) ftpd_pclose(fin); return; } (void) putc('\r', stdout); } (void) putc(c, stdout); } (void) ftpd_pclose(fin); reply(211, "End of Status"); } statcmd() { struct sockaddr_in *sin; u_char *a, *p; lreply(211, "%s FTP server status:", hostname, version); printf(" %s\r\n", version); printf(" Connected to %s", remotehost); if (!isdigit(remotehost[0])) printf(" (%s)", inet_ntoa(his_addr.sin_addr)); printf("\r\n"); if (logged_in) { if (guest) printf(" Logged in anonymously\r\n"); else printf(" Logged in as %s\r\n", pw->pw_name); } else if (askpasswd) printf(" Waiting for password\r\n"); else printf(" Waiting for user name\r\n"); printf(" TYPE: %s", typenames[type]); if (type == TYPE_A || type == TYPE_E) printf(", FORM: %s", formnames[form]); if (type == TYPE_L) #if NBBY == 8 printf(" %d", NBBY); #else printf(" %d", bytesize); /* need definition! */ #endif printf("; STRUcture: %s; transfer MODE: %s\r\n", strunames[stru], modenames[mode]); if (data != -1) printf(" Data connection open\r\n"); else if (pdata != -1) { printf(" in Passive mode"); sin = &pasv_addr; goto printaddr; } else if (usedefault == 0) { printf(" PORT"); sin = &data_dest; printaddr: a = (u_char *) &sin->sin_addr; p = (u_char *) &sin->sin_port; #define UC(b) (((int) b) & 0xff) printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); #undef UC } else printf(" No data connection\r\n"); reply(211, "End of status"); } fatal(s) char *s; { reply(451, "Error in server: %s\n", s); reply(221, "Closing connection due to server error."); dologout(0); /* NOTREACHED */ } /* VARARGS2 */ reply(n, fmt, p0, p1, p2, p3, p4, p5) int n; char *fmt; { printf("%d ", n); printf(fmt, p0, p1, p2, p3, p4, p5); printf("\r\n"); (void)fflush(stdout); if (debug) { syslog(LOG_DEBUG, "<--- %d ", n); syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5); } } /* VARARGS2 */ lreply(n, fmt, p0, p1, p2, p3, p4, p5) int n; char *fmt; { printf("%d- ", n); printf(fmt, p0, p1, p2, p3, p4, p5); printf("\r\n"); (void)fflush(stdout); if (debug) { syslog(LOG_DEBUG, "<--- %d- ", n); syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5); } } ack(s) char *s; { reply(250, "%s command successful.", s); } nack(s) char *s; { reply(502, "%s command not implemented.", s); } /* ARGSUSED */ yyerror(s) char *s; { char *cp; if (cp = index(cbuf,'\n')) *cp = '\0'; reply(500, "'%s': command not understood.", cbuf); } delete(name) char *name; { struct stat st; if (stat(name, &st) < 0) { perror_reply(550, name); return; } if ((st.st_mode&S_IFMT) == S_IFDIR) { if (rmdir(name) < 0) { perror_reply(550, name); return; } goto done; } if (unlink(name) < 0) { perror_reply(550, name); return; } done: ack("DELE"); } cwd(path) char *path; { if (chdir(path) < 0) perror_reply(550, path); else ack("CWD"); } makedir(name) char *name; { if (mkdir(name, 0777) < 0) perror_reply(550, name); else reply(257, "MKD command successful."); } removedir(name) char *name; { if (rmdir(name) < 0) perror_reply(550, name); else ack("RMD"); } pwd() { char path[MAXPATHLEN + 1]; extern char *getwd(); if (getwd(path) == (char *)NULL) reply(550, "%s.", path); else reply(257, "\"%s\" is current directory.", path); } char * renamefrom(name) char *name; { struct stat st; if (stat(name, &st) < 0) { perror_reply(550, name); return ((char *)0); } reply(350, "File exists, ready for destination name"); return (name); } renamecmd(from, to) char *from, *to; { if (rename(from, to) < 0) perror_reply(550, "rename"); else ack("RNTO"); } dolog(sin) struct sockaddr_in *sin; { struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr, sizeof (struct in_addr), AF_INET); time_t t, time(); extern char *ctime(); if (hp) (void) strncpy(remotehost, hp->h_name, sizeof (remotehost)); else (void) strncpy(remotehost, inet_ntoa(sin->sin_addr), sizeof (remotehost)); #ifdef SETPROCTITLE sprintf(proctitle, "%s: connected", remotehost); setproctitle(proctitle); #endif /* SETPROCTITLE */ if (logging) { t = time((time_t *) 0); syslog(LOG_INFO, "connection from %s at %s", remotehost, ctime(&t)); } } /* * Record logout in wtmp file * and exit with supplied status. */ dologout(status) int status; { if (logged_in) { (void) seteuid((uid_t)0); logwtmp(ttyline, "", ""); } /* beware of flushing buffers after a SIGPIPE */ _exit(status); } myoob() { char *cp; /* only process if transfer occurring */ if (!transflag) return; cp = tmpline; if (getline(cp, 7, stdin) == NULL) { reply(221, "You could at least say goodbye."); dologout(0); } upper(cp); if (strcmp(cp, "ABOR\r\n") == 0) { tmpline[0] = '\0'; reply(426, "Transfer aborted. Data connection closed."); reply(226, "Abort successful"); longjmp(urgcatch, 1); } if (strcmp(cp, "STAT\r\n") == 0) { if (file_size != (off_t) -1) reply(213, "Status: %lu of %lu bytes transferred", byte_count, file_size); else reply(213, "Status: %lu bytes transferred", byte_count); } } /* * Note: a response of 425 is not mentioned as a possible response to * the PASV command in RFC959. However, it has been blessed as * a legitimate response by Jon Postel in a telephone conversation * with Rick Adams on 25 Jan 89. */ passive() { int len; register char *p, *a; pdata = socket(AF_INET, SOCK_STREAM, 0); if (pdata < 0) { perror_reply(425, "Can't open passive connection"); return; } pasv_addr = ctrl_addr; pasv_addr.sin_port = 0; (void) seteuid((uid_t)0); if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) { (void) seteuid((uid_t)pw->pw_uid); goto pasv_error; } (void) seteuid((uid_t)pw->pw_uid); len = sizeof(pasv_addr); if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) goto pasv_error; if (listen(pdata, 1) < 0) goto pasv_error; a = (char *) &pasv_addr.sin_addr; p = (char *) &pasv_addr.sin_port; #define UC(b) (((int) b) & 0xff) reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); return; pasv_error: (void) close(pdata); pdata = -1; perror_reply(425, "Can't open passive connection"); return; } /* * Generate unique name for file with basename "local". * The file named "local" is already known to exist. * Generates failure reply on error. */ char * gunique(local) char *local; { static char new[MAXPATHLEN]; struct stat st; char *cp = rindex(local, '/'); int count = 0; if (cp) *cp = '\0'; if (stat(cp ? local : ".", &st) < 0) { perror_reply(553, cp ? local : "."); return((char *) 0); } if (cp) *cp = '/'; (void) strcpy(new, local); cp = new + strlen(new); *cp++ = '.'; for (count = 1; count < 100; count++) { (void) sprintf(cp, "%d", count); if (stat(new, &st) < 0) return(new); } reply(452, "Unique file name cannot be created."); return((char *) 0); } /* * Format and send reply containing system error number. */ perror_reply(code, string) int code; char *string; { if (errno < sys_nerr) reply(code, "%s: %s.", string, sys_errlist[errno]); else reply(code, "%s: unknown error %d.", string, errno); } static char *onefile[] = { "", 0 }; send_file_list(whichfiles) char *whichfiles; { struct stat st; DIR *dirp = NULL; struct direct *dir; FILE *dout = NULL; register char **dirlist, *dirname; int simple = 0; char *strpbrk(); if (strpbrk(whichfiles, "~{[*?") != NULL) { extern char **glob(), *globerr; globerr = NULL; dirlist = glob(whichfiles); if (globerr != NULL) { reply(550, globerr); return; } else if (dirlist == NULL) { errno = ENOENT; perror_reply(550, whichfiles); return; } } else { onefile[0] = whichfiles; dirlist = onefile; simple = 1; } if (setjmp(urgcatch)) { transflag = 0; return; } while (dirname = *dirlist++) { if (stat(dirname, &st) < 0) { /* * If user typed "ls -l", etc, and the client * used NLST, do what the user meant. */ if (dirname[0] == '-' && *dirlist == NULL && transflag == 0) { retrieve("/bin/ls %s", dirname); return; } perror_reply(550, whichfiles); if (dout != NULL) { (void) fclose(dout); transflag = 0; data = -1; pdata = -1; } return; } if ((st.st_mode&S_IFMT) == S_IFREG) { if (dout == NULL) { dout = dataconn("file list", (off_t)-1, "w"); if (dout == NULL) return; transflag++; } fprintf(dout, "%s%s\n", dirname, type == TYPE_A ? "\r" : ""); byte_count += strlen(dirname) + 1; continue; } else if ((st.st_mode&S_IFMT) != S_IFDIR) continue; if ((dirp = opendir(dirname)) == NULL) continue; while ((dir = readdir(dirp)) != NULL) { char nbuf[MAXPATHLEN]; if (dir->d_name[0] == '.' && dir->d_namlen == 1) continue; if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && dir->d_namlen == 2) continue; sprintf(nbuf, "%s/%s", dirname, dir->d_name); /* * We have to do a stat to insure it's * not a directory or special file. */ if (simple || (stat(nbuf, &st) == 0 && (st.st_mode&S_IFMT) == S_IFREG)) { if (dout == NULL) { dout = dataconn("file list", (off_t)-1, "w"); if (dout == NULL) return; transflag++; } if (nbuf[0] == '.' && nbuf[1] == '/') fprintf(dout, "%s%s\n", &nbuf[2], type == TYPE_A ? "\r" : ""); else fprintf(dout, "%s%s\n", nbuf, type == TYPE_A ? "\r" : ""); byte_count += strlen(nbuf) + 1; } } (void) closedir(dirp); } if (dout == NULL) reply(550, "No files found."); else if (ferror(dout) != 0) perror_reply(550, "Data connection"); else reply(226, "Transfer complete."); transflag = 0; if (dout != NULL) (void) fclose(dout); data = -1; pdata = -1; } #ifdef SETPROCTITLE /* * clobber argv so ps will show what we're doing. * (stolen from sendmail) * warning, since this is usually started from inetd.conf, it * often doesn't have much of an environment or arglist to overwrite. */ /*VARARGS1*/ setproctitle(fmt, a, b, c) char *fmt; { register char *p, *bp, ch; register int i; char buf[BUFSIZ]; (void) sprintf(buf, fmt, a, b, c); /* make ps print our process name */ p = Argv[0]; *p++ = '-'; i = strlen(buf); if (i > LastArgv - p - 2) { i = LastArgv - p - 2; buf[i] = '\0'; } bp = buf; while (ch = *bp++) if (ch != '\n' && ch != '\r') *p++ = ch; while (p < LastArgv) *p++ = ' '; } #endif /* SETPROCTITLE */ inet_ntoa(his_addr.sin_addr)); printf("\r\n"); if (logged_in) {etc/ftpd/glob.c 751 0 12 0 6045326243 12670 2/usr/src/ucb/ftp/glob.cetc/ftpd/logwtmp.c 444 0 3 3443 4423444562 7366 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * */ #ifndef lint static char sccsid[] = "@(#)logwtmp.c based on 5.5 (Berkeley) 4/2/89"; #endif /* not lint */ #include #include #include #include #include #ifndef _PATH_WTMP #define _PATH_WTMP "/usr/adm/wtmp" #endif static int fd = -1; /* * Modified version of logwtmp that holds wtmp file open * after first call, for use with ftp (which may chroot * after login, but before logout). */ logwtmp(line, name, host) char *line, *name, *host; { struct utmp ut; struct stat buf; time_t time(); char *strncpy(); if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) return; if (fstat(fd, &buf) == 0) { (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line)); (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name)); (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host)); (void)time(&ut.ut_time); if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp)) (void)ftruncate(fd, buf.st_size); } } YPE_A || type == TYPE_E) printf(", FORM: %s", formnames[form]); if (type == TYPE_L) #if NBBY == 8 printf(" %d", NBBY); #else printf(" %d", bytesize); /* need definition! */ #endif printf("; STRUcture: %s; transferetc/ftpd/newvers.sh 444 0 3 2113 4347411511 7540 #!/bin/sh - # # Copyright (c) 1983 The Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that the above copyright notice and this paragraph are # duplicated in all such forms and that any documentation, # advertising materials, and other materials related to such # distribution and use acknowledge that the software was developed # by the University of California, Berkeley. The name of the # University may not be used to endorse or promote products derived # from this software without specific prior written permission. # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # @(#)newvers.sh 5.4 (Berkeley) 12/7/88 # if [ ! -r version ]; then echo 0 > version; fi touch version awk ' { version = $1 + 1; }\ END { printf "char version[] = \"Version 5.%d ", version > "vers.c";\ printf "%d\n", version > "version"; }' < version echo `date`'";' >> vers.c endif static int fd = -1; /* * Modified version of logwtmp that holds wtmp file open * after first call, for use with ftp (which may chroot * after login, but before logout). */ logwtmp(line, name, host) char *line, *name, *host; { struct utmp ut; struct stat buf; time_t time(); char *strncpy(); if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) return; if (fstat(fd, &buf) == 0) { (void)strncpy(ut.ut_letc/ftpd/pathnames.h 444 0 3 1673 4422222012 7644 /* * Copyright (c) 1989 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * %W% (Berkeley) %G% */ #define _PATH_BSHELL "/bin/sh" #define _PATH_DEVNULL "/dev/null" #define _PATH_FTPUSERS "/etc/ftpusers" { printf "char version[] = \"Version 5.%d ", version > "vers.c";\ etc/ftpd/popen.c 444 0 12 7543 4530647011 7034 /* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * This code is derived from software written by Ken Arnold and * published in UNIX Review, Vol. 6, No. 8. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * */ #ifndef lint static char sccsid[] = "@(#)popen.c 5.7 (Berkeley) 2/14/89"; #endif /* not lint */ #include #include #include #include /* * Special version of popen which avoids call to shell. This insures noone * may create a pipe to a hidden program as a side effect of a list or dir * command. */ static int *pids; static int fds; FILE * ftpd_popen(program, type) char *program, *type; { register char *cp; FILE *iop; int argc, gargc, pdes[2], pid; char **pop, *argv[100], *gargv[1000], *vv[2], **ppop, *endprogram; extern char **glob(), **copyblk(), *strtok(), *malloc(); if (*type != 'r' && *type != 'w' || type[1]) return(NULL); if (!pids) { if ((fds = getdtablesize()) <= 0) return(NULL); if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL) return(NULL); bzero((char *)pids, fds * sizeof(int)); } if (pipe(pdes) < 0) return(NULL); endprogram = program + strlen(program); /* break up string into pieces */ for (argc = 0, cp = program;; cp = NULL) if (!(argv[argc++] = strtok(cp, " \t\n"))) break; /* glob each piece */ gargv[0] = argv[0]; for (gargc = argc = 1; argv[argc]; argc++) { if (!(pop = glob(argv[argc]))) { /* globbing failed */ vv[0] = argv[argc]; vv[1] = NULL; pop = copyblk(vv); } for (ppop = pop; *ppop != NULL; ppop++) { if (*ppop >= program && *ppop <= endprogram) { cp = (char *) malloc(strlen(*ppop) + 1); strcpy(cp, *ppop); *ppop = cp; } } argv[argc] = (char *)pop; /* save to free later */ while (*pop && gargc < 1000) gargv[gargc++] = *pop++; } gargv[gargc] = NULL; iop = NULL; switch(pid = vfork()) { case -1: /* error */ (void)close(pdes[0]); (void)close(pdes[1]); goto pfree; /* NOTREACHED */ case 0: /* child */ if (*type == 'r') { if (pdes[1] != 1) { dup2(pdes[1], 1); dup2(pdes[1], 2); /* stderr, too! */ (void)close(pdes[1]); } (void)close(pdes[0]); } else { if (pdes[0] != 0) { dup2(pdes[0], 0); (void)close(pdes[0]); } (void)close(pdes[1]); } execv(gargv[0], gargv); _exit(1); } /* parent; assume fdopen can't fail... */ if (*type == 'r') { iop = fdopen(pdes[0], type); (void)close(pdes[1]); } else { iop = fdopen(pdes[1], type); (void)close(pdes[0]); } pids[fileno(iop)] = pid; pfree: for (argc = 1; argv[argc] != NULL; argc++) { blkfree((char **)argv[argc]); free((char *)argv[argc]); } return(iop); } ftpd_pclose(iop) FILE *iop; { register int fdes; long omask; union wait stat_loc; int pid; /* * pclose returns -1 if stream is not associated with a * `popened' command, or, if already `pclosed'. */ if (pids == 0 || pids[fdes = fileno(iop)] == 0) return(-1); (void)fclose(iop); omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1); (void)sigsetmask(omask); pids[fdes] = 0; return(pid == -1 ? -1 : stat_loc.w_status); } in_port; #define UC(b) (((int) b) & 0xff) printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); #undef UC } eetc/ftpd/strpbrk.c 644 0 12 2524 4423447414 7404 /* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)strpbrk.c based on 5.5 (Berkeley) 7/14/88"; #endif /* LIBC_SCCS and not lint */ #include #ifndef UCHAR_MAX #define UCHAR_MAX 0xff #endif char * strpbrk(str, chars) register char *str, *chars; { static u_char charmap[UCHAR_MAX]; register int ch; register char *p; for (p = chars; ch = *p++;) charmap[ch] = 1; p = NULL; for (; ch = *str; ++str) if (charmap[ch]) { p = str; break; } while (ch = *chars++) charmap[ch] = 0; return(p); } oid)close(pdes[0]); } else { if (pdes[0] != 0) { dup2(pdes[0], 0); (void)close(pdes[0]); } (void)close(pdes[1]); } execv(gargv[0], gargv); _exit(1)etc/ftpd/vers.c 444 0 3 75 6024263154 6605 char version[] = "Version 5.79 Sat Sep 9 03:03:24 PDT 1995"; cøftpcmd.yc÷ftpd.8ycöftpd.cycõglob.cycô logwtmp.có newvers.she.cò pathnames.h.cñpopen.cs.ð strpbrk.cïvers.c.cî$versioncetc/ftpd/version 444 0 3 3 6024263153 7040 79 û.q ..úCHANGES.cùMakefilecøftpcmd.yc÷ftpd.8ycöftpd.cycõglob.cycô logwtmp.có newvers.she.cò pathnames.h.cñpopen.cs.ð strpbrk.cïvers.c.cî$versioncetc/fstat.c 440 0 12 36024 5514437121 6111 /* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1987 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)fstat.c 5.11.1 (2.11BSD GTE) 12/31/93"; #endif /* * fstat */ #include #include #include #include #include #include #include #include #include #include #include #include #define KERNEL #include #undef KERNEL #include #include #include #include #include #include #include #ifdef ULTRIX /* UFS -> GFS */ # define inode gnode # define x_iptr x_gptr # define i_dev g_dev # define i_number g_number # define i_mode g_mode # define i_size g_size #endif #define N_KMEM "/dev/kmem" #define N_MEM "/dev/mem" #define N_SWAP "/dev/drum" #define N_UNIX "/vmunix" #define TEXT -2 #define WD -1 typedef struct devs { struct devs *next; dev_t dev; int inum; char *name; } DEVS; DEVS *devs; #ifdef pdp11 static struct nlist nl[] = { { "_proc" }, #define X_PROC 0 { "_nproc" }, #define X_NPROC 1 { "_netdata" }, #define X_NETDATA 2 { "" }, }; #else static struct nlist nl[] = { { "_proc" }, #define X_PROC 0 { "_Usrptmap" }, #define X_USRPTMA 1 { "_nproc" }, #define X_NPROC 2 { "_usrpt" }, #define X_USRPT 3 { "" }, }; #endif struct proc *mproc; #ifndef pdp11 struct pte *Usrptma, *usrpt; #endif union { struct user user; #ifdef pdp11 char upages[ctob(USIZE)]; #else char upages[UPAGES][NBPG]; #endif } user; extern int errno; static int fflg, vflg; static int kmem, mem, nproc, swap; static char *uname; #ifdef pdp11 static off_t netdata; long lgetw(); #endif off_t lseek(); main(argc, argv) int argc; char **argv; { extern char *optarg; extern int optind; register struct passwd *passwd; register int pflg, pid, uflg, uid; int ch, size; struct passwd *getpwnam(), *getpwuid(); long lgetw(); char *malloc(); pflg = uflg = 0; while ((ch = getopt(argc, argv, "p:u:v")) != EOF) switch((char)ch) { case 'p': if (pflg++) usage(); if (!isdigit(*optarg)) { fputs("fstat: -p option requires a process id.\n", stderr); usage(); } pid = atoi(optarg); break; case 'u': if (uflg++) usage(); if (!(passwd = getpwnam(optarg))) { fprintf(stderr, "%s: unknown uid\n", optarg); exit(1); } uid = passwd->pw_uid; uname = passwd->pw_name; break; case 'v': /* undocumented: print read error messages */ vflg++; break; case '?': default: usage(); } if (*(argv += optind)) { for (; *argv; ++argv) { if (getfname(*argv)) fflg = 1; } if (!fflg) /* file(s) specified, but none accessable */ exit(1); } openfiles(); if (nlist(N_UNIX, nl) == -1 || !nl[0].n_type) { fprintf(stderr, "%s: No namelist\n", N_UNIX); exit(1); } #ifdef pdp11 if (nl[X_NETDATA].n_type) { netdata = lgetw((off_t)nl[X_NETDATA].n_value); netdata = ctob(netdata); } #else Usrptma = (struct pte *)nl[X_USRPTMA].n_value; usrpt = (struct pte *) nl[X_USRPT].n_value; #endif nproc = (int)lgetw((off_t)nl[X_NPROC].n_value); #ifdef pdp11 (void)lseek(kmem, (off_t)nl[X_PROC].n_value, L_SET); #else (void)lseek(kmem, lgetw((off_t)nl[X_PROC].n_value), L_SET); #endif size = nproc * sizeof(struct proc); if ((mproc = (struct proc *)malloc((u_int)size)) == NULL) { fprintf(stderr, "fstat: out of space.\n"); exit(1); } if (read(kmem, (char *)mproc, size) != size) rerr1("proc table", N_KMEM); printf("USER\t CMD\t PID FD\tDEVICE\tINODE\t SIZE TYPE%s\n", fflg ? " NAME" : ""); for (; nproc--; ++mproc) { if (mproc->p_stat == 0) continue; if (pflg && mproc->p_pid != pid) continue; if (uflg) { if (mproc->p_uid != uid) continue; } else uname = (passwd = getpwuid(mproc->p_uid)) ? passwd->pw_name : "unknown"; if (mproc->p_stat != SZOMB && getu() == 0) continue; dotext(); readf(); } exit(0); } #ifndef pdp11 static getu() { struct pte *pteaddr, apte; struct pte arguutl[UPAGES+CLSIZE]; register int i; int ncl; if ((mproc->p_flag & SLOAD) == 0) { if (swap < 0) return(0); (void)lseek(swap, (off_t)dtob(mproc->p_swaddr), L_SET); if (read(swap, (char *)&user.user, sizeof(struct user)) != sizeof(struct user)) { fprintf(stderr, "fstat: can't read u for pid %d from %s\n", mproc->p_pid, N_SWAP); return(0); } return(1); } pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; (void)lseek(kmem, (off_t)pteaddr, L_SET); if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { printf("fstat: can't read indir pte to get u for pid %d from %s\n", mproc->p_pid, N_SWAP); return(0); } (void)lseek(mem, (off_t)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof(struct pte), L_SET); if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { printf("fstat: can't read page table for u of pid %d from %s\n", mproc->p_pid, N_KMEM); return(0); } ncl = (sizeof(struct user) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE); while (--ncl >= 0) { i = ncl * CLSIZE; (void)lseek(mem, (off_t)ctob(arguutl[CLSIZE+i].pg_pfnum), L_SET); if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) { printf("fstat: can't read page %u of u of pid %d from %s\n", arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, N_MEM); return(0); } } return(1); } #else static getu() { if ((mproc->p_flag & SLOAD) == 0) { if (swap < 0) return(0); (void)lseek(swap, (off_t)(mproc->p_addr)<<9, L_SET); if (read(swap, (char *)&user.user, sizeof(struct user)) != sizeof(struct user)) { fprintf(stderr, "fstat: can't read u for pid %d from %s\n", mproc->p_pid, N_SWAP); return(0); } return(1); } (void)lseek(mem, (off_t)ctob((off_t)mproc->p_addr), L_SET); if (read(mem, &user.user, sizeof(user.user))!=sizeof(user.user)) { printf("fstat: can't read page table for u of pid %d from %s\n", mproc->p_pid, N_MEM); return(0); } return(1); } #endif static dotext() { struct text text; #ifdef pdp11 if (!mproc->p_textp) return; #endif (void)lseek(kmem, (off_t)mproc->p_textp, L_SET); if (read(kmem, (char *) &text, sizeof(text)) != sizeof(text)) { rerr1("text table", N_KMEM); return; } if (text.x_flag) itrans(DTYPE_INODE, text.x_iptr, TEXT); } static itrans(ftype, g, fno) int ftype, fno; struct inode *g; /* if ftype is inode */ { struct inode inode; dev_t idev; char *comm, *itype(); char *name = (char *)NULL; /* set by devmatch() on a match */ if (g || fflg) { (void)lseek(kmem, (off_t)g, L_SET); if (read(kmem, (char *)&inode, sizeof(inode)) != sizeof(inode)) { rerr2(errno, (int)g, "inode"); return; } idev = inode.i_dev; if (fflg && !devmatch(idev, inode.i_number, &name)) return; } if (mproc->p_pid == 0) comm = "swapper"; #ifndef pdp11 else if (mproc->p_pid == 2) comm = "pagedaemon"; #endif else comm = user.user.u_comm; printf("%-8.8s %-10.10s %5d ", uname, comm, mproc->p_pid); switch(fno) { case WD: printf(" wd"); break; case TEXT: printf("text"); break; default: printf("%4d", fno); } if (g == 0) { printf("* (deallocated)\n"); return; } switch(ftype) { case DTYPE_INODE: #ifdef pdp11 case DTYPE_PIPE: #endif printf("\t%2d, %2d\t%5lu\t%6ld\t%3s %s\n", major(inode.i_dev), minor(inode.i_dev), (long)inode.i_number, inode.i_mode == IFSOCK ? 0L : inode.i_size, #ifdef pdp11 ftype == DTYPE_PIPE ? "pip" : #endif itype(inode.i_mode), name ? name : ""); break; case DTYPE_SOCKET: socktrans((struct socket *)g); break; #ifdef DTYPE_PORT case DTYPE_PORT: printf("* (fifo / named pipe)\n"); break; #endif default: printf("* (unknown file type)\n"); } } static char * itype(mode) u_short mode; { switch(mode & IFMT) { case IFCHR: return("chr"); case IFDIR: return("dir"); case IFBLK: return("blk"); case IFREG: return("reg"); case IFLNK: return("lnk"); case IFSOCK: return("soc"); default: return("unk"); } /*NOTREACHED*/ } static socktrans(sock) struct socket *sock; { static char *stypename[] = { "unused", /* 0 */ "stream", /* 1 */ "dgram", /* 2 */ "raw", /* 3 */ "rdm", /* 4 */ "seqpak" /* 5 */ }; #define STYPEMAX 5 struct socket so; struct protosw proto; struct domain dom; struct inpcb inpcb; struct unpcb unpcb; int len; char dname[32], *strcpy(); /* fill in socket */ #ifdef pdp11 (void)lseek(mem, (off_t)sock + netdata, L_SET); if (read(mem, (char *)&so, sizeof(struct socket)) #else (void)lseek(kmem, (off_t)sock, L_SET); if (read(kmem, (char *)&so, sizeof(struct socket)) #endif != sizeof(struct socket)) { rerr2(errno, (int)sock, "socket"); return; } /* fill in protosw entry */ #ifdef pdp11 (void)lseek(mem, (off_t)so.so_proto + netdata, L_SET); if (read(mem, (char *)&proto, sizeof(struct protosw)) #else (void)lseek(kmem, (off_t)so.so_proto, L_SET); if (read(kmem, (char *)&proto, sizeof(struct protosw)) #endif != sizeof(struct protosw)) { rerr2(errno, (int)so.so_proto, "protosw"); return; } /* fill in domain */ #ifdef pdp11 (void)lseek(mem, (off_t)proto.pr_domain + netdata, L_SET); if (read(mem, (char *)&dom, sizeof(struct domain)) #else (void)lseek(kmem, (off_t)proto.pr_domain, L_SET); if (read(kmem, (char *)&dom, sizeof(struct domain)) #endif != sizeof(struct domain)) { rerr2(errno, (int)proto.pr_domain, "domain"); return; } /* * grab domain name * kludge "internet" --> "inet" for brevity */ if (dom.dom_family == AF_INET) (void)strcpy(dname, "inet"); else { #ifdef pdp11 (void)lseek(mem, (off_t)dom.dom_name + netdata, L_SET); if ((len = read(mem, dname, sizeof(dname) - 1)) < 0) { #else (void)lseek(kmem, (off_t)dom.dom_name, L_SET); if ((len = read(kmem, dname, sizeof(dname) - 1)) < 0) { #endif rerr2(errno, (int)dom.dom_name, "char"); dname[0] = '\0'; } else dname[len] = '\0'; } if ((u_short)so.so_type > STYPEMAX) printf("* (%s unk%d %x", dname, so.so_type, so.so_state); else printf("* (%s %s %x", dname, stypename[so.so_type], so.so_state); /* * protocol specific formatting * * Try to find interesting things to print. For tcp, the interesting * thing is the address of the tcpcb, for udp and others, just the * inpcb (socket pcb). For unix domain, its the address of the socket * pcb and the address of the connected pcb (if connected). Otherwise * just print the protocol number and address of the socket itself. * The idea is not to duplicate netstat, but to make available enough * information for further analysis. */ switch(dom.dom_family) { case AF_INET: getinetproto(proto.pr_protocol); if (proto.pr_protocol == IPPROTO_TCP ) { if (so.so_pcb) { #ifdef pdp11 (void)lseek(mem,(off_t)so.so_pcb+netdata,L_SET); if (read(mem, &inpcb, sizeof(struct inpcb)) #else (void)lseek(kmem, (off_t)so.so_pcb, L_SET); if (read(kmem, (char *)&inpcb, sizeof(struct inpcb)) #endif != sizeof(struct inpcb)){ rerr2(errno, (int)so.so_pcb, "inpcb"); return; } printf(" %x", (int)inpcb.inp_ppcb); } } else if (so.so_pcb) printf(" %x", (int)so.so_pcb); break; case AF_UNIX: /* print address of pcb and connected pcb */ if (so.so_pcb) { printf(" %x", (int)so.so_pcb); #ifdef pdp11 (void)lseek(mem, (off_t)so.so_pcb + netdata, L_SET); if (read(mem, (char *)&unpcb, sizeof(struct unpcb)) #else (void)lseek(kmem, (off_t)so.so_pcb, L_SET); if (read(kmem, (char *)&unpcb, sizeof(struct unpcb)) #endif != sizeof(struct unpcb)){ rerr2(errno, (int)so.so_pcb, "unpcb"); return; } if (unpcb.unp_conn) { char shoconn[4], *cp; cp = shoconn; if (!(so.so_state & SS_CANTRCVMORE)) *cp++ = '<'; *cp++ = '-'; if (!(so.so_state & SS_CANTSENDMORE)) *cp++ = '>'; *cp = '\0'; printf(" %s %x", shoconn, (int)unpcb.unp_conn); } } break; default: /* print protocol number and socket address */ printf(" %d %x", proto.pr_protocol, (int)sock); } printf(")\n"); } /* * getinetproto -- * print name of protocol number */ static getinetproto(number) int number; { char *cp; switch(number) { case IPPROTO_IP: cp = "ip"; break; case IPPROTO_ICMP: cp ="icmp"; break; case IPPROTO_GGP: cp ="ggp"; break; case IPPROTO_TCP: cp ="tcp"; break; case IPPROTO_EGP: cp ="egp"; break; case IPPROTO_PUP: cp ="pup"; break; case IPPROTO_UDP: cp ="udp"; break; case IPPROTO_IDP: cp ="idp"; break; case IPPROTO_RAW: cp ="raw"; break; default: printf(" %d", number); return; } printf(" %s", cp); } static readf() { struct file lfile; int i; itrans(DTYPE_INODE, user.user.u_cdir, WD); for (i = 0; i < NOFILE; i++) { if (user.user.u_ofile[i] == 0) continue; (void)lseek(kmem, (off_t)user.user.u_ofile[i], L_SET); if (read(kmem, (char *)&lfile, sizeof(lfile)) != sizeof(lfile)) { rerr1("file", N_KMEM); continue; } itrans(lfile.f_type, (struct inode *)lfile.f_data, i); } } static devmatch(idev, inum, name) dev_t idev; ino_t inum; char **name; { register DEVS *d; for (d = devs; d; d = d->next) if (d->dev == idev && (d->inum == 0 || d->inum == inum)) { *name = d->name; return(1); } return(0); } static getfname(filename) char *filename; { struct stat statbuf; DEVS *cur; char *malloc(); if (stat(filename, &statbuf)) { perror(filename); return(0); } if ((cur = (DEVS *)malloc(sizeof(DEVS))) == NULL) { fprintf(stderr, "fstat: out of space.\n"); exit(1); } cur->next = devs; devs = cur; /* if file is block special, look for open files on it */ if ((statbuf.st_mode & S_IFMT) != S_IFBLK) { cur->inum = statbuf.st_ino; cur->dev = statbuf.st_dev; } else { cur->inum = 0; cur->dev = statbuf.st_rdev; } cur->name = filename; return(1); } static openfiles() { if ((kmem = open(N_KMEM, O_RDONLY, 0)) < 0) { perror(N_KMEM); exit(1); } if ((mem = open(N_MEM, O_RDONLY, 0)) < 0) { perror(N_MEM); exit(1); } if ((swap = open(N_SWAP, O_RDONLY, 0)) < 0) { perror(N_SWAP); exit(1); } } static rerr1(what, fromwhat) char *what, *fromwhat; { if (vflg) printf("fstat: error reading %s from %s", what, fromwhat); } static rerr2(err, address, what) int err, address; char *what; { if (vflg) printf("error %d reading %s at %x from kmem\n", errno, what, address); } static long lgetw(loc) off_t loc; { #ifdef pdp11 u_short word; #else long word; #endif (void)lseek(kmem, (off_t)loc, L_SET); if (read(kmem, (char *)&word, sizeof(word)) != sizeof(word)) rerr2(errno, (int)loc, "word"); return((long)word); } static usage() { fputs("usage: fstat [-v] [-u user] [-p pid] [filename ...]\n", stderr); exit(1); } _szpt - 1]; (void)lseek(kmem, (off_t)pteaddr, L_SET); if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { printf("fstat: can't read indir pte to get u for pid %d from %s\n", mproc->p_pid, N_SWAP); return(0); } (void)lseek(mem, (off_t)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) * sizeof(struct pte), L_SET); if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { printf("fstat: can't read page table for u of pid %d from %s\n", mproc->p_pid, N_KMEM); retc/routed/ 750 0 12 0 6024536061 6015 etc/routed/Makefile 440 0 12 1563 4306712601 7543 # # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.2 (Berkeley) 2/7/86 # ALL= routed OBJS= af.o if.o input.o main.o output.o startup.o tables.o timer.o \ trace.o inet.o CFLAGS= -O SEPFLAG=-i C2= /lib/c2 INLINE= /sys/machine/inline/inline DESTDIR= LDFLAGS= all: ${ALL} routed: ${OBJS} ${CC} ${SEPFLAG} -o routed ${LDFLAGS} ${OBJS} install: routed install -s routed ${DESTDIR}/etc # The following can be deleted where not appropriate to use the kernel's # inline code expansions. #.c.o: # ${CC} -S ${CFLAGS} $*.c # ${C2} $*.s | ${INLINE} | ${AS} -o $*.o # rm -f $*.s clean: rm -f routed *.o core a.out t.c linterrs typescript errs ${OBJS}: defs.h af.h defs.h interface.h table.h trace.h \ /usr/include/protocols/routed.h >next = devs; devs = cur; /* if file is block special, look for open files on it */ if ((statbuf.st_mode & S_IFMT) != S_IFBLK) { cur->ietc/routed/af.c 440 0 12 5363 5514436327 6651 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)af.c 5.4.1 (2.11BSD GTE) 1/1/94"; #endif #include "defs.h" /* * Address family support routines */ int inet_hash(), inet_netmatch(), inet_output(), inet_portmatch(), inet_portcheck(), inet_checkhost(), inet_rtflags(), inet_sendsubnet(), inet_canon(); char *inet_format(); #define NIL { 0 } #define INET \ { inet_hash, inet_netmatch, inet_output, \ inet_portmatch, inet_portcheck, inet_checkhost, \ inet_rtflags, inet_sendsubnet, inet_canon, \ inet_format \ } struct afswitch afswitch[AF_MAX] = { NIL, /* 0- unused */ NIL, /* 1- Unix domain, unused */ INET, /* Internet */ }; int af_max = sizeof(afswitch) / sizeof(afswitch[0]); struct sockaddr_in inet_default = { AF_INET, INADDR_ANY }; inet_hash(sin, hp) register struct sockaddr_in *sin; struct afhash *hp; { u_long n; n = inet_netof(sin->sin_addr); if (n) while ((n & 0xff) == 0) { n >>= 8; } hp->afh_nethash = n; hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); #ifdef pdp11 hp->afh_hosthash &= 0x7fff; #else hp->afh_hosthash &= 0x7fffffff; #endif } inet_netmatch(sin1, sin2) struct sockaddr_in *sin1, *sin2; { return (inet_netof(sin1->sin_addr) == inet_netof(sin2->sin_addr)); } /* * Verify the message is from the right port. */ inet_portmatch(sin) register struct sockaddr_in *sin; { return (sin->sin_port == sp->s_port); } /* * Verify the message is from a "trusted" port. */ inet_portcheck(sin) struct sockaddr_in *sin; { return (ntohs(sin->sin_port) <= IPPORT_RESERVED); } /* * Internet output routine. */ inet_output(s, flags, sin, size) int s, flags; struct sockaddr_in *sin; int size; { struct sockaddr_in dst; dst = *sin; sin = &dst; if (sin->sin_port == 0) sin->sin_port = sp->s_port; if (sendto(s, packet, size, flags, sin, sizeof (*sin)) < 0) perror("sendto"); } /* * Return 1 if the address is believed * for an Internet host -- THIS IS A KLUDGE. */ inet_checkhost(sin) struct sockaddr_in *sin; { u_long n = ntohl(sin->sin_addr.s_addr); int i; #ifdef IN_BADCLASS #undef IN_BADCLASS #endif IN_BADCLASS #define IN_BADCLASS(n) (((long) (n) & 0xe0000000) == 0xe0000000) if (IN_BADCLASS(n) || sin->sin_port != 0) return (0); if (n != 0 && (n & 0xff000000) == 0) return (0); for (i = 0; i < sizeof(sin->sin_zero)/sizeof(sin->sin_zero[0]); i++) if (sin->sin_zero[i]) return (0); return (1); } inet_canon(sin) struct sockaddr_in *sin; { sin->sin_port = 0; } char * inet_format(sin) struct sockaddr_in *sin; { char *inet_ntoa(); return (inet_ntoa(sin->sin_addr)); } BPG) { printf("fstat: can't read page %u of u of pid %d from %s\n", arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, N_MEM); return(0); } } return(1); } #else static getu() { if ((mproc->p_flag & SLOAD) == 0) { if (swap < 0) return(0); (void)lseek(swap, (ofetc/routed/af.h 440 0 12 2233 4100744421 6632 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)af.h 5.3 (Berkeley) 4/20/86 */ /* * Routing table management daemon. */ /* * Per address family routines. */ struct afswitch { int (*af_hash)(); /* returns keys based on address */ int (*af_netmatch)(); /* verifies net # matching */ int (*af_output)(); /* interprets address for sending */ int (*af_portmatch)(); /* packet from some other router? */ int (*af_portcheck)(); /* packet from privileged peer? */ int (*af_checkhost)(); /* tells if address is valid */ int (*af_rtflags)(); /* get flags for route (host or net) */ int (*af_sendsubnet)(); /* check bounds of subnet broadcast */ int (*af_canon)(); /* canonicalize address for compares */ char *(*af_format)(); /* convert address to string */ }; /* * Structure returned by af_hash routines. */ struct afhash { u_int afh_hosthash; /* host based hash */ u_int afh_nethash; /* network based hash */ }; struct afswitch afswitch[]; /* table proper */ int af_max; /* number of entries in table */ hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); #ifdef pdp11 hp->afh_hosthash &= 0x7fff; #else hp->afh_hosthash &= 0x7fffffff; #endif } inet_netmatch(sin1, sin2) struct sockaddr_in *sin1, *sin2; { return (inet_netof(sin1->sin_addr) == inet_netof(sin2->sin_addr)); } /* * Verify the message is from the right port. */ inet_portmatch(sin) register setc/routed/defs.h 440 0 12 3134 5514436346 7204 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)defs.h 5.3.1 (2.11BSD GTE) 1/1/94 */ /* * Internal data structure definitions for * user routing process. Based on Xerox NS * protocol specs with mods relevant to more * general addressing scheme. */ #include #include #include #include #include #include #include #include #include "trace.h" #include "interface.h" #include "table.h" #include "af.h" /* * When we find any interfaces marked down we rescan the * kernel every CHECK_INTERVAL seconds to see if they've * come up. */ #define CHECK_INTERVAL (1*60) #define equal(a1, a2) \ (bcmp((caddr_t)(a1), (caddr_t)(a2), sizeof (struct sockaddr)) == 0) #define min(a,b) ((a)>(b)?(b):(a)) struct sockaddr_in addr; /* address of daemon's socket */ int s; /* source and sink of all data */ int kmem; int supplier; /* process should supply updates */ int install; /* if 1 call kernel */ int lookforinterfaces; /* if 1 probe kernel for new up interfaces */ int performnlist; /* if 1 check if /vmunix has changed */ int externalinterfaces; /* # of remote and local interfaces */ long timeval; /* local idea of time */ char packet[MAXPACKETSIZE+1]; struct rip *msg; char **argv0; struct servent *sp; extern char *sys_errlist[]; extern int errno; char *malloc(); int exit(); int sendmsg(); int supply(); int timer(); int cleanup(); time_t time(); ge is from a "trusted" port. */ inet_portcheck(sin) struct sockaddr_in *sin; { return (ntohs(sin->sin_port) <= IPPORT_RESERVED); } /* * Internet output routine. */ inet_output(s, flags, sin, size) int s, flags; struct sockaddr_in *sin; int size; { struct sockaddr_in dst; dst = *sin; sin = &dst; if (sin->sin_port == 0) sin->sin_port = sp->s_port; if (sendto(s, packet, size, flags, sin, sizeof (*sin))etc/routed/if.c 440 0 12 5165 4100744422 6645 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)if.c 5.3 (Berkeley) 4/20/86"; #endif not lint /* * Routing Table Management Daemon */ #include "defs.h" extern struct interface *ifnet; /* * Find the interface with address addr. */ struct interface * if_ifwithaddr(addr) struct sockaddr *addr; { register struct interface *ifp; #define same(a1, a2) \ (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) for (ifp = ifnet; ifp; ifp = ifp->int_next) { if (ifp->int_flags & IFF_REMOTE) continue; if (ifp->int_addr.sa_family != addr->sa_family) continue; if (same(&ifp->int_addr, addr)) break; if ((ifp->int_flags & IFF_BROADCAST) && same(&ifp->int_broadaddr, addr)) break; } return (ifp); } /* * Find the point-to-point interface with destination address addr. */ struct interface * if_ifwithdstaddr(addr) struct sockaddr *addr; { register struct interface *ifp; for (ifp = ifnet; ifp; ifp = ifp->int_next) { if ((ifp->int_flags & IFF_POINTOPOINT) == 0) continue; if (same(&ifp->int_dstaddr, addr)) break; } return (ifp); } /* * Find the interface on the network * of the specified address. */ struct interface * if_ifwithnet(addr) register struct sockaddr *addr; { register struct interface *ifp; register int af = addr->sa_family; register int (*netmatch)(); if (af >= af_max) return (0); netmatch = afswitch[af].af_netmatch; for (ifp = ifnet; ifp; ifp = ifp->int_next) { if (ifp->int_flags & IFF_REMOTE) continue; if (af != ifp->int_addr.sa_family) continue; if ((*netmatch)(addr, &ifp->int_addr)) break; } return (ifp); } /* * Find an interface from which the specified address * should have come from. Used for figuring out which * interface a packet came in on -- for tracing. */ struct interface * if_iflookup(addr) struct sockaddr *addr; { register struct interface *ifp, *maybe; register int af = addr->sa_family; register int (*netmatch)(); if (af >= af_max) return (0); maybe = 0; netmatch = afswitch[af].af_netmatch; for (ifp = ifnet; ifp; ifp = ifp->int_next) { if (ifp->int_addr.sa_family != af) continue; if (same(&ifp->int_addr, addr)) break; if ((ifp->int_flags & IFF_BROADCAST) && same(&ifp->int_broadaddr, addr)) break; if ((ifp->int_flags & IFF_POINTOPOINT) && same(&ifp->int_dstaddr, addr)) break; if (maybe == 0 && (*netmatch)(addr, &ifp->int_addr)) maybe = ifp; } if (ifp == 0) ifp = maybe; return (ifp); } n_port = 0; } char * inet_format(sin) struct sockaddr_in *sin; { char *inet_ntoa(); return (inet_ntoa(sin->sin_addr)); } BPG) { printf("fstat: can't read page %u of u of pid %d from %s\n", arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, N_MEM); return(0); } } return(1); } #else static getu() { if ((mproc->p_flag & SLOAD) == 0) { if (swap < 0) return(0); (void)lseek(swap, (ofetc/routed/inet.c 440 0 12 10410 4100747036 7217 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)inet.c 5.4 (Berkeley) 6/3/86"; #endif not lint /* * Temporarily, copy these routines from the kernel, * as we need to know about subnets. */ #include "defs.h" extern struct interface *ifnet; /* * Formulate an Internet address from network + host. */ struct in_addr inet_makeaddr(net, host) u_long net, host; { register struct interface *ifp; register u_long mask; u_long addr; if (IN_CLASSA(net)) mask = IN_CLASSA_HOST; else if (IN_CLASSB(net)) mask = IN_CLASSB_HOST; else mask = IN_CLASSC_HOST; for (ifp = ifnet; ifp; ifp = ifp->int_next) if ((ifp->int_netmask & net) == ifp->int_net) { mask = ~ifp->int_subnetmask; break; } addr = net | (host & mask); addr = htonl(addr); return (*(struct in_addr *)&addr); } /* * Return the network number from an internet address. */ u_long inet_netof(in) struct in_addr in; { register u_long i = ntohl(in.s_addr); register u_long net; register struct interface *ifp; if (IN_CLASSA(i)) net = i & IN_CLASSA_NET; else if (IN_CLASSB(i)) net = i & IN_CLASSB_NET; else net = i & IN_CLASSC_NET; /* * Check whether network is a subnet; * if so, return subnet number. */ for (ifp = ifnet; ifp; ifp = ifp->int_next) if ((ifp->int_netmask & net) == ifp->int_net) return (i & ifp->int_subnetmask); return (net); } /* * Return the host portion of an internet address. */ u_long inet_lnaof(in) struct in_addr in; { register u_long i = ntohl(in.s_addr); register u_long net, host; register struct interface *ifp; if (IN_CLASSA(i)) { net = i & IN_CLASSA_NET; host = i & IN_CLASSA_HOST; } else if (IN_CLASSB(i)) { net = i & IN_CLASSB_NET; host = i & IN_CLASSB_HOST; } else { net = i & IN_CLASSC_NET; host = i & IN_CLASSC_HOST; } /* * Check whether network is a subnet; * if so, use the modified interpretation of `host'. */ for (ifp = ifnet; ifp; ifp = ifp->int_next) if ((ifp->int_netmask & net) == ifp->int_net) return (host &~ ifp->int_subnetmask); return (host); } /* * Return RTF_HOST if the address is * for an Internet host, RTF_SUBNET for a subnet, * 0 for a network. */ inet_rtflags(sin) struct sockaddr_in *sin; { register u_long i = ntohl(sin->sin_addr.s_addr); register u_long net, host; register struct interface *ifp; if (IN_CLASSA(i)) { net = i & IN_CLASSA_NET; host = i & IN_CLASSA_HOST; } else if (IN_CLASSB(i)) { net = i & IN_CLASSB_NET; host = i & IN_CLASSB_HOST; } else { net = i & IN_CLASSC_NET; host = i & IN_CLASSC_HOST; } /* * Check whether this network is subnetted; * if so, check whether this is a subnet or a host. */ for (ifp = ifnet; ifp; ifp = ifp->int_next) if (net == ifp->int_net) { if (host &~ ifp->int_subnetmask) return (RTF_HOST); else if (ifp->int_subnetmask != ifp->int_netmask) return (RTF_SUBNET); else return (0); /* network */ } if (host == 0) return (0); /* network */ else return (RTF_HOST); } /* * Return true if a route to subnet of route rt should be sent to dst. * Send it only if dst is on the same logical network, * or the route is the "internal" route for the net. */ inet_sendsubnet(rt, dst) struct rt_entry *rt; struct sockaddr_in *dst; { register u_long r = ntohl(((struct sockaddr_in *)&rt->rt_dst)->sin_addr.s_addr); register u_long d = ntohl(dst->sin_addr.s_addr); if (IN_CLASSA(r)) { if ((r & IN_CLASSA_NET) == (d & IN_CLASSA_NET)) { if ((r & IN_CLASSA_HOST) == 0) return ((rt->rt_state & RTS_INTERNAL) == 0); return (1); } if (r & IN_CLASSA_HOST) return (0); return ((rt->rt_state & RTS_INTERNAL) != 0); } else if (IN_CLASSB(r)) { if ((r & IN_CLASSB_NET) == (d & IN_CLASSB_NET)) { if ((r & IN_CLASSB_HOST) == 0) return ((rt->rt_state & RTS_INTERNAL) == 0); return (1); } if (r & IN_CLASSB_HOST) return (0); return ((rt->rt_state & RTS_INTERNAL) != 0); } else { if ((r & IN_CLASSC_NET) == (d & IN_CLASSC_NET)) { if ((r & IN_CLASSC_HOST) == 0) return ((rt->rt_state & RTS_INTERNAL) == 0); return (1); } if (r & IN_CLASSC_HOST) return (0); return ((rt->rt_state & RTS_INTERNAL) != 0); } } ifp = ifp->int_next) if ((ifp->int_netmask & net) == ifp->int_net) { mask = ~ifp->int_subnetmask; break; } addr = net | (host & mask); addr = htonl(addr); return (*(struct in_addr *)&addr); } /* * Return the network number from an ietc/routed/input.c 440 0 12 12530 4101140130 7403 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)input.c 5.6 (Berkeley) 6/3/86"; #endif not lint /* * Routing Table Management Daemon */ #include "defs.h" #include /* * Process a newly received packet. */ rip_input(from, size) struct sockaddr *from; int size; { register struct rt_entry *rt; register struct netinfo *n; register struct interface *ifp; struct interface *if_ifwithdstaddr(); int newsize; register struct afswitch *afp; ifp = 0; TRACE_INPUT(ifp, from, size); if (from->sa_family >= af_max || (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) { syslog(LOG_INFO, "\"from\" address in unsupported address family (%d), cmd %d\n", from->sa_family, msg->rip_cmd); return; } switch (msg->rip_cmd) { case RIPCMD_REQUEST: newsize = 0; size -= 4 * sizeof (char); n = msg->rip_nets; while (size > 0) { if (size < sizeof (struct netinfo)) break; size -= sizeof (struct netinfo); if (msg->rip_vers > 0) { n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); n->rip_metric = ntohl(n->rip_metric); } /* * A single entry with sa_family == AF_UNSPEC and * metric ``infinity'' means ``all routes''. * We respond to routers only if we are acting * as a supplier, or to anyone other than a router * (eg, query). */ if (n->rip_dst.sa_family == AF_UNSPEC && n->rip_metric == HOPCNT_INFINITY && size == 0) { if (supplier || (*afp->af_portmatch)(from) == 0) supply(from, 0, 0); return; } if (n->rip_dst.sa_family < af_max && afswitch[n->rip_dst.sa_family].af_hash) rt = rtlookup(&n->rip_dst); else rt = 0; n->rip_metric = rt == 0 ? HOPCNT_INFINITY : min(rt->rt_metric+1L, HOPCNT_INFINITY); if (msg->rip_vers > 0) { n->rip_dst.sa_family = htons(n->rip_dst.sa_family); n->rip_metric = htonl(n->rip_metric); } n++, newsize += sizeof (struct netinfo); } if (newsize > 0) { msg->rip_cmd = RIPCMD_RESPONSE; newsize += sizeof (int); (*afp->af_output)(s, 0, from, newsize); } return; case RIPCMD_TRACEON: case RIPCMD_TRACEOFF: /* verify message came from a privileged port */ if ((*afp->af_portcheck)(from) == 0) return; if (if_iflookup(from) == 0) { syslog(LOG_ERR, "trace command from unknown router, %s", (*afswitch[from->sa_family].af_format)(from)); return; } packet[size] = '\0'; if (msg->rip_cmd == RIPCMD_TRACEON) traceon(msg->rip_tracefile); else traceoff(); return; case RIPCMD_RESPONSE: /* verify message came from a router */ if ((*afp->af_portmatch)(from) == 0) return; (*afp->af_canon)(from); /* are we talking to ourselves? */ ifp = if_ifwithaddr(from); if (ifp) { rt = rtfind(from); if (rt == 0 || (rt->rt_state & RTS_INTERFACE) == 0) addrouteforif(ifp); else rt->rt_timer = 0; return; } /* * Update timer for interface on which the packet arrived. * If from other end of a point-to-point link that isn't * in the routing tables, (re-)add the route. */ if ((rt = rtfind(from)) && (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE))) rt->rt_timer = 0; else if (ifp = if_ifwithdstaddr(from)) addrouteforif(ifp); else if (if_iflookup(from) == 0) { syslog(LOG_ERR, "packet from unknown router, %s", (*afswitch[from->sa_family].af_format)(from)); return; } size -= 4 * sizeof (char); n = msg->rip_nets; for (; size > 0; size -= sizeof (struct netinfo), n++) { if (size < sizeof (struct netinfo)) break; if (msg->rip_vers > 0) { n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); n->rip_metric = ntohl(n->rip_metric); } if ((unsigned) n->rip_metric > HOPCNT_INFINITY) continue; if (n->rip_dst.sa_family >= af_max || (afp = &afswitch[n->rip_dst.sa_family])->af_hash == (int (*)())0) { syslog(LOG_INFO, "route in unsupported address family (%d), from %s (af %d)\n", n->rip_dst.sa_family, (*afswitch[from->sa_family].af_format)(from), from->sa_family); continue; } if (((*afp->af_checkhost)(&n->rip_dst)) == 0) { syslog(LOG_DEBUG, "bad host in route from %s (af %d)\n", (*afswitch[from->sa_family].af_format)(from), from->sa_family); continue; } rt = rtlookup(&n->rip_dst); if (rt == 0 || (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == (RTS_INTERNAL|RTS_INTERFACE)) { rt = rtfind(&n->rip_dst); if (rt && equal(from, &rt->rt_router) && rt->rt_metric == n->rip_metric) continue; if (n->rip_metric < HOPCNT_INFINITY) rtadd(&n->rip_dst, from, (int)n->rip_metric, 0); continue; } /* * Update if from gateway and different, * shorter, or getting stale and equivalent. */ if (equal(from, &rt->rt_router)) { if (n->rip_metric == HOPCNT_INFINITY) { rtdelete(rt); continue; } if (n->rip_metric != rt->rt_metric) rtchange(rt,from, (short)n->rip_metric); rt->rt_timer = 0; } else if ((unsigned) (n->rip_metric) < rt->rt_metric || (rt->rt_timer > (EXPIRE_TIME/2) && rt->rt_metric == (short)n->rip_metric)) { rtchange(rt, from, (short)n->rip_metric); rt->rt_timer = 0; } } return; } } e IFREG: return("reg"); case IFLNK: return("lnk"); case IFSOCK: return("soc"); default: return("unk"); } /*NOTREACHED*/ } static socktrans(sock) struct setc/routed/interface.h 440 0 12 4401 4100744424 10206 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)interface.h 5.3 (Berkeley) 4/20/86 */ /* * Routing table management daemon. */ /* * An ``interface'' is similar to an ifnet structure, * except it doesn't contain q'ing info, and it also * handles ``logical'' interfaces (remote gateways * that we want to keep polling even if they go down). * The list of interfaces which we maintain is used * in supplying the gratuitous routing table updates. */ struct interface { struct interface *int_next; struct sockaddr int_addr; /* address on this host */ union { struct sockaddr intu_broadaddr; struct sockaddr intu_dstaddr; } int_intu; #define int_broadaddr int_intu.intu_broadaddr /* broadcast address */ #define int_dstaddr int_intu.intu_dstaddr /* other end of p-to-p link */ int int_metric; /* init's routing entry */ int int_flags; /* see below */ /* START INTERNET SPECIFIC */ u_long int_net; /* network # */ u_long int_netmask; /* net mask for addr */ u_long int_subnet; /* subnet # */ u_long int_subnetmask; /* subnet mask for addr */ /* END INTERNET SPECIFIC */ struct ifdebug int_input, int_output; /* packet tracing stuff */ int int_ipackets; /* input packets received */ int int_opackets; /* output packets sent */ char *int_name; /* from kernel if structure */ u_short int_transitions; /* times gone up-down */ }; /* * 0x1 to 0x10 are reused from the kernel's ifnet definitions, * the others agree with the RTS_ flags defined elsewhere. */ #define IFF_UP 0x1 /* interface is up */ #define IFF_BROADCAST 0x2 /* broadcast address valid */ #define IFF_DEBUG 0x4 /* turn on debugging */ #define IFF_LOOPBACK 0x8 /* software loopback net */ #define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */ #define IFF_SUBNET 0x1000 /* interface on subnetted network */ #define IFF_PASSIVE 0x2000 /* can't tell if up/down */ #define IFF_INTERFACE 0x4000 /* hardware interface */ #define IFF_REMOTE 0x8000 /* interface isn't on this machine */ struct interface *if_ifwithaddr(); struct interface *if_ifwithdstaddr(); struct interface *if_ifwithnet(); struct interface *if_iflookup(); se RIPCMD_TRACEOFF: /* verify message came from a privileged port */ if ((*afp->af_portcheck)(from) == 0) return; if (if_iflookup(from) == 0) { syslog(LOG_ERR, "trace command from unknown router, %s", (*afswitch[from->sa_family].af_formaetc/routed/main.c 440 0 12 7601 4101127522 7165 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)main.c 5.7 (Berkeley) 4/20/86"; #endif not lint /* * Routing Table Management Daemon */ #include "defs.h" #include #include #include #include #include #include int supplier = -1; /* process should supply updates */ int gateway = 0; /* 1 if we are a gateway to parts beyond */ struct rip *msg = (struct rip *)packet; int hup(); main(argc, argv) int argc; char *argv[]; { int cc; struct sockaddr from; u_char retry; argv0 = argv; openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); setlogmask(LOG_UPTO(LOG_WARNING)); sp = getservbyname("router", "udp"); if (sp == NULL) { fprintf(stderr, "routed: router/udp: unknown service\n"); exit(1); } addr.sin_family = AF_INET; addr.sin_port = sp->s_port; s = getsocket(AF_INET, SOCK_DGRAM, &addr); if (s < 0) exit(1); argv++, argc--; while (argc > 0 && **argv == '-') { if (strcmp(*argv, "-s") == 0) { supplier = 1; argv++, argc--; continue; } if (strcmp(*argv, "-q") == 0) { supplier = 0; argv++, argc--; continue; } if (strcmp(*argv, "-t") == 0) { tracepackets++; setlogmask(LOG_UPTO(LOG_DEBUG)); argv++, argc--; continue; } if (strcmp(*argv, "-d") == 0) { setlogmask(LOG_UPTO(LOG_DEBUG)); argv++, argc--; continue; } if (strcmp(*argv, "-g") == 0) { gateway = 1; argv++, argc--; continue; } fprintf(stderr, "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); exit(1); } #ifndef DEBUG if (!tracepackets) { int t; if (fork()) exit(0); for (t = 0; t < 20; t++) if (t != s) (void) close(t); (void) open("/", 0); (void) dup2(0, 1); (void) dup2(0, 2); t = open("/dev/tty", 2); if (t >= 0) { ioctl(t, TIOCNOTTY, (char *)0); (void) close(t); } } #endif /* * Any extra argument is considered * a tracing log file. */ if (argc > 0) traceon(*argv); /* * Collect an initial view of the world by * checking the interface configuration and the gateway kludge * file. Then, send a request packet on all * directly connected networks to find out what * everyone else thinks. */ rtinit(); gwkludge(); ifinit(); if (gateway > 0) rtdefault(); if (supplier < 0) supplier = 0; msg->rip_cmd = RIPCMD_REQUEST; msg->rip_vers = RIPVERSION; msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); toall(sendmsg); signal(SIGALRM, timer); signal(SIGHUP, hup); signal(SIGTERM, hup); timer(); for (;;) { long ibits; register int n; ibits = 1L << s; n = select(20, &ibits, 0, 0, 0); if (n < 0) continue; if (ibits & (1L << s)) process(s); /* handle ICMP redirects */ } } process(fd) int fd; { struct sockaddr from; int fromlen = sizeof (from), cc; long omask; cc = recvfrom(fd, packet, sizeof (packet), 0, &from, &fromlen); if (cc <= 0) { if (cc < 0 && errno != EINTR) perror("recvfrom"); return; } if (fromlen != sizeof (struct sockaddr_in)) return; omask = sigblock(sigmask(SIGALRM)); rip_input(&from, cc); sigsetmask(omask); } getsocket(domain, type, sin) int domain, type; struct sockaddr_in *sin; { int s, on = 1; if ((s = socket(domain, type, 0)) < 0) { perror("socket"); syslog(LOG_ERR, "socket: %m"); return (-1); } if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); close(s); return (-1); } if (bind(s, sin, sizeof (*sin), 0) < 0) { perror("bind"); syslog(LOG_ERR, "bind: %m"); close(s); return (-1); } return (s); } >= af_max || (afp = &afswitch[n->rip_dst.sa_family])->af_hash == (int (*)())0) { syslog(LOG_INFO, "route ietc/routed/output.c 440 0 12 5656 4101140172 7605 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)output.c 5.3 (Berkeley) 5/30/86"; #endif not lint /* * Routing Table Management Daemon */ #include "defs.h" /* * Apply the function "f" to all non-passive * interfaces. If the interface supports the * use of broadcasting use it, otherwise address * the output to the known router. */ toall(f) int (*f)(); { register struct interface *ifp; register struct sockaddr *dst; register int flags; extern struct interface *ifnet; for (ifp = ifnet; ifp; ifp = ifp->int_next) { if (ifp->int_flags & IFF_PASSIVE) continue; dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : &ifp->int_addr; flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; (*f)(dst, flags, ifp); } } /* * Output a preformed packet. */ /*ARGSUSED*/ sendmsg(dst, flags, ifp) struct sockaddr *dst; int flags; struct interface *ifp; { (*afswitch[dst->sa_family].af_output)(s, flags, dst, sizeof (struct rip)); TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); } /* * Supply dst with the contents of the routing tables. * If this won't fit in one packet, chop it up into several. */ supply(dst, flags, ifp) struct sockaddr *dst; int flags; struct interface *ifp; { register struct rt_entry *rt; struct netinfo *n = msg->rip_nets; register struct rthash *rh; struct rthash *base = hosthash; int doinghost = 1, size; int (*output)() = afswitch[dst->sa_family].af_output; int (*sendsubnet)() = afswitch[dst->sa_family].af_sendsubnet; msg->rip_cmd = RIPCMD_RESPONSE; msg->rip_vers = RIPVERSION; again: for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { /* * Don't resend the information * on the network from which it was received. */ if (ifp && rt->rt_ifp == ifp) continue; if (rt->rt_state & RTS_EXTERNAL) continue; /* * Limit the spread of subnet information * to those who are interested. */ if (doinghost == 0 && rt->rt_state & RTS_SUBNET) { if (ifp && (ifp->int_flags & IFF_SUBNET) == 0) continue; if (rt->rt_dst.sa_family != dst->sa_family) continue; if ((*sendsubnet)(rt, dst) == 0) continue; } size = (char *)n - packet; if (size > MAXPACKETSIZE - sizeof (struct netinfo)) { (*output)(s, flags, dst, size); TRACE_OUTPUT(ifp, dst, size); n = msg->rip_nets; } n->rip_dst = rt->rt_dst; n->rip_dst.sa_family = htons(n->rip_dst.sa_family); n->rip_metric = htonl(min(rt->rt_metric + 1L, HOPCNT_INFINITY)); n++; } if (doinghost) { doinghost = 0; base = nethash; goto again; } if (n != msg->rip_nets) { size = (char *)n - packet; (*output)(s, flags, dst, size); TRACE_OUTPUT(ifp, dst, size); } } ); if (n < 0) continue; if (ibits & (1L << s)) process(s); /* handle Ietc/routed/startup.c 440 0 12 24016 4306712601 7767 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)startup.c 5.7 (Berkeley) 6/3/86"; #endif not lint /* * Routing Table Management Daemon */ #include "defs.h" #include #include #include struct interface *ifnet; int lookforinterfaces = 1; int externalinterfaces = 0; /* # of remote and local interfaces */ /* * Find the network interfaces which have configured themselves. * If the interface is present but not yet up (for example an * ARPANET IMP), set the lookforinterfaces flag so we'll * come back later and look again. */ ifinit() { struct interface ifs, *ifp; int s, n; char buf[BUFSIZ]; struct ifconf ifc; struct ifreq ifreq, *ifr; struct sockaddr_in *sin; u_long i; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } ifc.ifc_len = sizeof (buf); ifc.ifc_buf = buf; if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { syslog(LOG_ERR, "ioctl (get interface configuration)"); close(s); return (0); } ifr = ifc.ifc_req; lookforinterfaces = 0; for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) { bzero((char *)&ifs, sizeof(ifs)); ifs.int_addr = ifr->ifr_addr; ifreq = *ifr; if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { syslog(LOG_ERR, "ioctl (get interface flags)"); continue; } ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; /* no one cares about software loopback interfaces */ if (ifs.int_flags & IFF_LOOPBACK) continue; if ((ifs.int_flags & IFF_UP) == 0 || ifr->ifr_addr.sa_family == AF_UNSPEC) { lookforinterfaces = 1; continue; } /* already known to us? */ if (if_ifwithaddr(&ifs.int_addr)) continue; /* argh, this'll have to change sometime */ if (ifs.int_addr.sa_family != AF_INET) continue; if (ifs.int_flags & IFF_POINTOPOINT) { if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "ioctl (get dstaddr)"); continue; } ifs.int_dstaddr = ifreq.ifr_dstaddr; } if (ifs.int_flags & IFF_BROADCAST) { if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "ioctl (get broadaddr)"); continue; } ifs.int_broadaddr = ifreq.ifr_broadaddr; } if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) syslog(LOG_ERR, "ioctl (get metric)"); else ifs.int_metric = ifreq.ifr_metric; if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) { syslog(LOG_ERR, "ioctl (get netmask)"); continue; } sin = (struct sockaddr_in *)&ifreq.ifr_addr; ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr); sin = (struct sockaddr_in *)&ifs.int_addr; i = ntohl(sin->sin_addr.s_addr); if (IN_CLASSA(i)) ifs.int_netmask = IN_CLASSA_NET; else if (IN_CLASSB(i)) ifs.int_netmask = IN_CLASSB_NET; else ifs.int_netmask = IN_CLASSC_NET; ifs.int_net = i & ifs.int_netmask; ifs.int_subnet = i & ifs.int_subnetmask; if (ifs.int_subnetmask != ifs.int_netmask) ifs.int_flags |= IFF_SUBNET; ifp = (struct interface *)malloc(sizeof (struct interface)); if (ifp == 0) { printf("routed: out of memory\n"); break; } *ifp = ifs; /* * Count the # of directly connected networks * and point to point links which aren't looped * back to ourself. This is used below to * decide if we should be a routing ``supplier''. */ if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || if_ifwithaddr(&ifs.int_dstaddr) == 0) externalinterfaces++; /* * If we have a point-to-point link, we want to act * as a supplier even if it's our only interface, * as that's the only way our peer on the other end * can tell that the link is up. */ if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) supplier = 1; ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); if (ifp->int_name == 0) { fprintf(stderr, "routed: ifinit: out of memory\n"); goto bad; /* ??? */ } strcpy(ifp->int_name, ifr->ifr_name); ifp->int_next = ifnet; ifnet = ifp; traceinit(ifp); addrouteforif(ifp); } if (externalinterfaces > 1 && supplier < 0) supplier = 1; close(s); return; bad: sleep(60); close(kmem), close(s); execv("/etc/routed", argv0); _exit(0177); } /* * Add route for interface if not currently installed. * Create route to other end if a point-to-point link, * otherwise a route to this (sub)network. * INTERNET SPECIFIC. */ addrouteforif(ifp) struct interface *ifp; { struct sockaddr_in net; struct sockaddr *dst; struct rt_entry *rt; if (ifp->int_flags & IFF_POINTOPOINT) dst = &ifp->int_dstaddr; else { bzero((char *)&net, sizeof (net)); net.sin_family = AF_INET; net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY); dst = (struct sockaddr *)&net; } rt = rtfind(dst); if (rt && (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE) return; if (rt) rtdelete(rt); /* * If interface on subnetted network, * install route to network as well. * This is meant for external viewers. */ if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) { net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); rt = rtfind(dst); if (rt == 0) rtadd(dst, &ifp->int_addr, ifp->int_metric, ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) | RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET)); net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY); } if (ifp->int_transitions++ > 0) syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); rtadd(dst, &ifp->int_addr, ifp->int_metric, ifp->int_flags & (IFF_INTERFACE|IFF_PASSIVE|IFF_REMOTE|IFF_SUBNET)); } /* * As a concession to the ARPANET we read a list of gateways * from /etc/gateways and add them to our tables. This file * exists at each ARPANET gateway and indicates a set of ``remote'' * gateways (i.e. a gateway which we can't immediately determine * if it's present or not as we can do for those directly connected * at the hardware level). If a gateway is marked ``passive'' * in the file, then we assume it doesn't have a routing process * of our design and simply assume it's always present. Those * not marked passive are treated as if they were directly * connected -- they're added into the interface list so we'll * send them routing updates. */ gwkludge() { struct sockaddr_in dst, gate; FILE *fp; char *type, *dname, *gname, *qual, buf[BUFSIZ]; struct interface *ifp; int metric, n; struct rt_entry route; fp = fopen("/etc/gateways", "r"); if (fp == NULL) return; qual = buf; dname = buf + 64; gname = buf + ((BUFSIZ - 64) / 3); type = buf + (((BUFSIZ - 64) * 2) / 3); bzero((char *)&dst, sizeof (dst)); bzero((char *)&gate, sizeof (gate)); bzero((char *)&route, sizeof(route)); /* format: {net | host} XX gateway XX metric DD [passive]\n */ #define readentry(fp) \ fscanf((fp), "%s %s gateway %s metric %d %s\n", \ type, dname, gname, &metric, qual) for (;;) { if ((n = readentry(fp)) == EOF) break; if (!getnetorhostname(type, dname, &dst)) continue; if (!gethostnameornumber(gname, &gate)) continue; if (strcmp(qual, "passive") == 0) { /* * Passive entries aren't placed in our tables, * only the kernel's, so we don't copy all of the * external routing information within a net. * Internal machines should use the default * route to a suitable gateway (like us). */ route.rt_dst = *(struct sockaddr *) &dst; route.rt_router = *(struct sockaddr *) &gate; route.rt_flags = RTF_UP; if (strcmp(type, "host") == 0) route.rt_flags |= RTF_HOST; if (metric) route.rt_flags |= RTF_GATEWAY; (void) ioctl(s, SIOCADDRT, (char *)&route.rt_rt); continue; } if (strcmp(qual, "external") == 0) { /* * Entries marked external are handled * by other means, e.g. EGP, * and are placed in our tables only * to prevent overriding them * with something else. */ rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE); continue; } /* assume no duplicate entries */ externalinterfaces++; ifp = (struct interface *)malloc(sizeof (*ifp)); bzero((char *)ifp, sizeof (*ifp)); ifp->int_flags = IFF_REMOTE; /* can't identify broadcast capability */ ifp->int_net = inet_netof(dst.sin_addr); if (strcmp(type, "host") == 0) { ifp->int_flags |= IFF_POINTOPOINT; ifp->int_dstaddr = *((struct sockaddr *)&dst); } ifp->int_addr = *((struct sockaddr *)&gate); ifp->int_metric = metric; ifp->int_next = ifnet; ifnet = ifp; addrouteforif(ifp); } fclose(fp); } getnetorhostname(type, name, sin) char *type, *name; struct sockaddr_in *sin; { if (strcmp(type, "net") == 0) { struct netent *np = getnetbyname(name); u_long n; if (np == 0) n = inet_network(name); else { if (np->n_addrtype != AF_INET) return (0); n = np->n_net; /* * getnetbyname returns right-adjusted value. */ if (n < 128) n <<= IN_CLASSA_NSHIFT; else if (n < 65536) n <<= IN_CLASSB_NSHIFT; else n <<= IN_CLASSC_NSHIFT; } sin->sin_family = AF_INET; sin->sin_addr = inet_makeaddr(n, INADDR_ANY); return (1); } if (strcmp(type, "host") == 0) { struct hostent *hp = gethostbyname(name); if (hp == 0) sin->sin_addr.s_addr = inet_addr(name); else { if (hp->h_addrtype != AF_INET) return (0); bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); } sin->sin_family = AF_INET; return (1); } return (0); } gethostnameornumber(name, sin) char *name; struct sockaddr_in *sin; { struct hostent *hp; hp = gethostbyname(name); if (hp) { bcopy(hp->h_addr, &sin->sin_addr, hp->h_length); sin->sin_family = hp->h_addrtype; return (1); } sin->sin_addr.s_addr = inet_addr(name); sin->sin_family = AF_INET; return (sin->sin_addr.s_addr != -1); } pcb) printf(" %x", (int)so.so_pcb); break; case AF_UNIX: /* print address of pcb and connected pcb */ if (so.so_pcb) { printf(" %x", (int)so.so_pcb); #ifdef pdp11 (void)lseek(mem, (off_t)so.so_pcb + netdata, L_SET); if (read(mem, (char *)&unpcb, sizeof(struct unpcb)) #else (void)lseek(kmem, (off_t)so.so_pcb, L_SET); if (read(kmem, (char *)&unpcb, sizeof(struct unpcb)) #endif != sizeof(struct unpcb)){ rerr2(errno, (int)so.so_pcb, "unpcb"); return; } etc/routed/table.h 440 0 12 4330 4306712601 7336 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)table.h 5.2 (Berkeley) 4/20/86 */ /* * Routing table management daemon. */ /* * Routing table structure; differs a bit from kernel tables. * * Note: the union below must agree in the first 4 members * so the ioctl's will work. */ struct rthash { struct rt_entry *rt_forw; struct rt_entry *rt_back; }; struct rt_entry { struct rt_entry *rt_forw; struct rt_entry *rt_back; union { struct rtentry rtu_rt; struct { u_int rtu_hash; struct sockaddr rtu_dst; struct sockaddr rtu_router; short rtu_flags; short rtu_state; int rtu_timer; int rtu_metric; struct interface *rtu_ifp; } rtu_entry; } rt_rtu; }; #define rt_rt rt_rtu.rtu_rt /* pass to ioctl */ #define rt_hash rt_rtu.rtu_entry.rtu_hash /* for net or host */ #define rt_dst rt_rtu.rtu_entry.rtu_dst /* match value */ #define rt_router rt_rtu.rtu_entry.rtu_router /* who to forward to */ #define rt_flags rt_rtu.rtu_entry.rtu_flags /* kernel flags */ #define rt_timer rt_rtu.rtu_entry.rtu_timer /* for invalidation */ #define rt_state rt_rtu.rtu_entry.rtu_state /* see below */ #define rt_metric rt_rtu.rtu_entry.rtu_metric /* cost of route */ #define rt_ifp rt_rtu.rtu_entry.rtu_ifp /* interface to take */ #define ROUTEHASHSIZ 32 /* must be a power of 2 */ #define ROUTEHASHMASK (ROUTEHASHSIZ - 1) /* * "State" of routing table entry. */ #define RTS_CHANGED 0x1 /* route has been altered recently */ #define RTS_EXTERNAL 0x2 /* extern info, not installed or sent */ #define RTS_INTERNAL 0x4 /* internal route, not installed */ #define RTS_PASSIVE IFF_PASSIVE /* don't time out route */ #define RTS_INTERFACE IFF_INTERFACE /* route is for network interface */ #define RTS_REMOTE IFF_REMOTE /* route is for ``remote'' entity */ #define RTS_SUBNET IFF_SUBNET /* route is for network subnet */ /* * Flags are same as kernel, with this addition for af_rtflags: */ #define RTF_SUBNET 0x8000 /* pseudo: route to subnet */ struct rthash nethash[ROUTEHASHSIZ]; struct rthash hosthash[ROUTEHASHSIZ]; struct rt_entry *rtlookup(); struct rt_entry *rtfind(); ET; else ifs.int_netmask = IN_CLASSC_NET; ifs.int_net = i & ifs.int_netmask; ifs.int_subnet = i & ifs.int_subnetmask; if (ifs.int_subnetmask != ifs.int_netmask) ifs.int_flags |= IFF_SUBNET; ifp = (struct interface *)malloc(sizeof (struct interface)); if (ifp == 0) { printf("etc/routed/tables.c 440 0 12 13230 4101134444 7527 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)tables.c 5.5 (Berkeley) 5/28/86"; #endif not lint /* * Routing Table Management Daemon */ #include "defs.h" #include #include #include #ifndef DEBUG #define DEBUG 0 #endif #if DEBUG int install = 0; /* if 1 call kernel */ #else int install = 1; /* if 1 call kernel */ #endif /* * Lookup dst in the tables for an exact match. */ struct rt_entry * rtlookup(dst) struct sockaddr *dst; { register struct rt_entry *rt; register struct rthash *rh; register u_int hash; struct afhash h; int doinghost = 1; if (dst->sa_family >= af_max) return (0); (*afswitch[dst->sa_family].af_hash)(dst, &h); hash = h.afh_hosthash; rh = &hosthash[hash & ROUTEHASHMASK]; again: for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { if (rt->rt_hash != hash) continue; if (equal(&rt->rt_dst, dst)) return (rt); } if (doinghost) { doinghost = 0; hash = h.afh_nethash; rh = &nethash[hash & ROUTEHASHMASK]; goto again; } return (0); } /* * Find a route to dst as the kernel would. */ struct rt_entry * rtfind(dst) struct sockaddr *dst; { register struct rt_entry *rt; register struct rthash *rh; register u_int hash; struct afhash h; int af = dst->sa_family; int doinghost = 1, (*match)(); if (af >= af_max) return (0); (*afswitch[af].af_hash)(dst, &h); hash = h.afh_hosthash; rh = &hosthash[hash & ROUTEHASHMASK]; again: for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { if (rt->rt_hash != hash) continue; if (doinghost) { if (equal(&rt->rt_dst, dst)) return (rt); } else { if (rt->rt_dst.sa_family == af && (*match)(&rt->rt_dst, dst)) return (rt); } } if (doinghost) { doinghost = 0; hash = h.afh_nethash; rh = &nethash[hash & ROUTEHASHMASK]; match = afswitch[af].af_netmatch; goto again; } return (0); } rtadd(dst, gate, metric, state) struct sockaddr *dst, *gate; int metric, state; { struct afhash h; register struct rt_entry *rt; struct rthash *rh; int af = dst->sa_family, flags; u_int hash; if (af >= af_max) return; (*afswitch[af].af_hash)(dst, &h); flags = (*afswitch[af].af_rtflags)(dst); /* * Subnet flag isn't visible to kernel, move to state. XXX */ if (flags & RTF_SUBNET) { state |= RTS_SUBNET; flags &= ~RTF_SUBNET; } if (flags & RTF_HOST) { hash = h.afh_hosthash; rh = &hosthash[hash & ROUTEHASHMASK]; } else { hash = h.afh_nethash; rh = &nethash[hash & ROUTEHASHMASK]; } rt = (struct rt_entry *)malloc(sizeof (*rt)); if (rt == 0) return; rt->rt_hash = hash; rt->rt_dst = *dst; rt->rt_router = *gate; rt->rt_metric = metric; rt->rt_timer = 0; rt->rt_flags = RTF_UP | flags; rt->rt_state = state | RTS_CHANGED; rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router); if (rt->rt_ifp == 0) rt->rt_ifp = if_ifwithnet(&rt->rt_router); if (metric) rt->rt_flags |= RTF_GATEWAY; insque(rt, rh); TRACE_ACTION(ADD, rt); /* * If the ioctl fails because the gateway is unreachable * from this host, discard the entry. This should only * occur because of an incorrect entry in /etc/gateways. */ if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 && ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) { perror("SIOCADDRT"); if (errno == ENETUNREACH) { TRACE_ACTION(DELETE, rt); remque(rt); free((char *)rt); } } } rtchange(rt, gate, metric) struct rt_entry *rt; struct sockaddr *gate; short metric; { int doioctl = 0, metricchanged = 0; struct rtentry oldroute; if (!equal(&rt->rt_router, gate) && (rt->rt_state & RTS_INTERNAL) == 0) doioctl++; if (metric != rt->rt_metric) metricchanged++; if (doioctl || metricchanged) { TRACE_ACTION(CHANGE FROM, rt); if ((rt->rt_state & RTS_INTERFACE) && metric) { rt->rt_state &= ~RTS_INTERFACE; syslog(LOG_ERR, "changing route from interface %s (timed out)", rt->rt_ifp->int_name); } if (doioctl) { oldroute = rt->rt_rt; rt->rt_router = *gate; rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router); if (rt->rt_ifp == 0) rt->rt_ifp = if_ifwithnet(&rt->rt_router); } rt->rt_metric = metric; if (metric) rt->rt_flags |= RTF_GATEWAY; else rt->rt_flags &= ~RTF_GATEWAY; rt->rt_state |= RTS_CHANGED; TRACE_ACTION(CHANGE TO, rt); } if (doioctl && install) { if (ioctl(s, SIOCADDRT, (char *)&rt->rt_rt) < 0) perror("SIOCADDRT"); if (ioctl(s, SIOCDELRT, (char *)&oldroute) < 0) perror("SIOCDELRT"); } } rtdelete(rt) struct rt_entry *rt; { if (rt->rt_state & RTS_INTERFACE) syslog(LOG_ERR, "deleting route to interface %s (timed out)", rt->rt_ifp->int_name); TRACE_ACTION(DELETE, rt); if (install && (rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 && ioctl(s, SIOCDELRT, (char *)&rt->rt_rt)) perror("SIOCDELRT"); remque(rt); free((char *)rt); } /* * If we have an interface to the wide, wide world, * add an entry for an Internet default route (wildcard) to the internal * tables and advertise it. This route is not added to the kernel routes, * but this entry prevents us from listening to other people's defaults * and installing them in the kernel here. */ rtdefault() { extern struct sockaddr inet_default; rtadd(&inet_default, &inet_default, 0, RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL); } rtinit() { register struct rthash *rh; for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; } %s %s gateway %s metric %d %s\n", \ type, dname, gname, &metric, qual) for (;;) { if ((n = readentry(fp)) == EOF) break; if (!getnetorhostname(type, dname, &dst)) continue; if (!gethostnameornumber(gname, &gate)) continue; if (strcmp(qual, "passive") == 0) { /* * Passive entries aren't placed in our tables, * only the kernel's,etc/routed/timer.c 440 0 12 4717 4310611004 7361 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)timer.c 5.3 (Berkeley) 11/20/85"; #endif not lint /* * Routing Table Management Daemon */ #include "defs.h" long timeval = -TIMER_RATE; /* * Timer routine. Performs routing information supply * duties and manages timers on routing table entries. */ timer() { register struct rthash *rh; register struct rt_entry *rt; struct rthash *base = hosthash; int doinghost = 1, timetobroadcast; extern int externalinterfaces; timeval += TIMER_RATE; if (lookforinterfaces && (timeval % CHECK_INTERVAL) == 0) ifinit(); timetobroadcast = supplier && (timeval % SUPPLY_INTERVAL) == 0; again: for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) { rt = rh->rt_forw; for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { /* * We don't advance time on a routing entry for * a passive gateway, or any interface if we're * not acting as supplier. */ if (!(rt->rt_state & RTS_PASSIVE) && (supplier || !(rt->rt_state & RTS_INTERFACE))) rt->rt_timer += TIMER_RATE; if (rt->rt_timer >= EXPIRE_TIME) rt->rt_metric = HOPCNT_INFINITY; if (rt->rt_timer >= GARBAGE_TIME) { rt = rt->rt_back; rtdelete(rt->rt_forw); continue; } if (rt->rt_state & RTS_CHANGED) { rt->rt_state &= ~RTS_CHANGED; /* don't send extraneous packets */ if (!supplier || timetobroadcast) continue; msg->rip_cmd = RIPCMD_RESPONSE; msg->rip_vers = RIPVERSION; msg->rip_nets[0].rip_dst = rt->rt_dst; msg->rip_nets[0].rip_dst.sa_family = htons(msg->rip_nets[0].rip_dst.sa_family); msg->rip_nets[0].rip_metric = htonl(min(rt->rt_metric+1L,HOPCNT_INFINITY)); toall(sendmsg); } } } if (doinghost) { doinghost = 0; base = nethash; goto again; } if (timetobroadcast) toall(supply); alarm(TIMER_RATE); } /* * On hangup, let everyone know we're going away. */ hup() { register struct rthash *rh; register struct rt_entry *rt; struct rthash *base = hosthash; int doinghost = 1; if (supplier) { again: for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) { rt = rh->rt_forw; for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) rt->rt_metric = HOPCNT_INFINITY; } if (doinghost) { doinghost = 0; base = nethash; goto again; } toall(supply); } exit(1); } t = 1, (*match)(); if (af >= af_max) return (etc/routed/trace.c 440 0 12 13475 4307647135 7404 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)trace.c 5.3 (Berkeley) 5/30/86"; #endif not lint /* * Routing Table Management Daemon */ #define RIPCMDS #include "defs.h" #include #define NRECORDS 50 /* size of circular trace buffer */ #ifdef DEBUG FILE *ftrace = stdout; int tracing = 1; #endif traceinit(ifp) register struct interface *ifp; { if (iftraceinit(ifp, &ifp->int_input) && iftraceinit(ifp, &ifp->int_output)) return; tracing = 0; fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); } static iftraceinit(ifp, ifd) struct interface *ifp; register struct ifdebug *ifd; { register struct iftrace *t; ifd->ifd_records = (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); if (ifd->ifd_records == 0) return (0); ifd->ifd_front = ifd->ifd_records; ifd->ifd_count = 0; for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { t->ift_size = 0; t->ift_packet = 0; } ifd->ifd_if = ifp; return (1); } traceon(file) char *file; { struct stat stbuf; if (ftrace != NULL) return; if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) return; ftrace = fopen(file, "a"); if (ftrace == NULL) return; dup2(fileno(ftrace), 1); dup2(fileno(ftrace), 2); tracing = 1; } traceoff() { if (!tracing) return; if (ftrace != NULL) fclose(ftrace); ftrace = NULL; tracing = 0; } trace(ifd, who, p, len, m) register struct ifdebug *ifd; struct sockaddr *who; char *p; int len, m; { register struct iftrace *t; if (ifd->ifd_records == 0) return; t = ifd->ifd_front++; if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) ifd->ifd_front = ifd->ifd_records; if (ifd->ifd_count < NRECORDS) ifd->ifd_count++; if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { free(t->ift_packet); t->ift_packet = 0; } t->ift_stamp = time((time_t *)0); t->ift_who = *who; if (len > 0 && t->ift_packet == 0) { t->ift_packet = malloc(len); if (t->ift_packet == 0) len = 0; } if (len > 0) bcopy(p, t->ift_packet, len); t->ift_size = len; t->ift_metric = m; } traceaction(fd, action, rt) FILE *fd; char *action; struct rt_entry *rt; { struct sockaddr_in *dst, *gate; static struct bits { int t_bits; char *t_name; } flagbits[] = { { RTF_UP, "UP" }, { RTF_GATEWAY, "GATEWAY" }, { RTF_HOST, "HOST" }, { 0 } }, statebits[] = { { RTS_PASSIVE, "PASSIVE" }, { RTS_REMOTE, "REMOTE" }, { RTS_INTERFACE,"INTERFACE" }, { RTS_CHANGED, "CHANGED" }, { RTS_INTERNAL, "INTERNAL" }, { RTS_EXTERNAL, "EXTERNAL" }, { RTS_SUBNET, "SUBNET" }, { 0 } }; register struct bits *p; register int first; char *cp; struct interface *ifp; if (fd == NULL) return; fprintf(fd, "%s ", action); dst = (struct sockaddr_in *)&rt->rt_dst; gate = (struct sockaddr_in *)&rt->rt_router; fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); fprintf(fd, "router %s, metric %d, flags", inet_ntoa(gate->sin_addr), rt->rt_metric); cp = " %s"; for (first = 1, p = flagbits; p->t_bits > 0; p++) { if ((rt->rt_flags & p->t_bits) == 0) continue; fprintf(fd, cp, p->t_name); if (first) { cp = "|%s"; first = 0; } } fprintf(fd, " state"); cp = " %s"; for (first = 1, p = statebits; p->t_bits > 0; p++) { if ((rt->rt_state & p->t_bits) == 0) continue; fprintf(fd, cp, p->t_name); if (first) { cp = "|%s"; first = 0; } } putc('\n', fd); if (!tracepackets && (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) dumpif(fd, rt->rt_ifp); fflush(fd); } dumpif(fd, ifp) register struct interface *ifp; { if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { fprintf(fd, "*** Packet history for interface %s ***\n", ifp->int_name); dumptrace(fd, "to", &ifp->int_output); dumptrace(fd, "from", &ifp->int_input); fprintf(fd, "*** end packet history ***\n"); } fflush(fd); } dumptrace(fd, dir, ifd) FILE *fd; char *dir; register struct ifdebug *ifd; { register struct iftrace *t; char *cp = !strcmp(dir, "to") ? "Output" : "Input"; if (ifd->ifd_front == ifd->ifd_records && ifd->ifd_front->ift_size == 0) { fprintf(fd, "%s: no packets.\n", cp); fflush(fd); return; } fprintf(fd, "%s trace:\n", cp); t = ifd->ifd_front - ifd->ifd_count; if (t < ifd->ifd_records) t += NRECORDS; for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { if (t >= ifd->ifd_records + NRECORDS) t = ifd->ifd_records; if (t->ift_size == 0) continue; fprintf(fd, "%.24s: metric=%D\n", ctime(&t->ift_stamp), t->ift_metric); dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size); } } dumppacket(fd, dir, who, cp, size) FILE *fd; struct sockaddr_in *who; /* should be sockaddr */ char *dir, *cp; register int size; { register struct rip *msg = (struct rip *)cp; register struct netinfo *n; if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) fprintf(fd, "%s %s %s.%d", ripcmds[msg->rip_cmd], dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); else { fprintf(fd, "Bad cmd 0x%x %s %x.%d\n", msg->rip_cmd, dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet); fflush(fd); return; } switch (msg->rip_cmd) { case RIPCMD_REQUEST: case RIPCMD_RESPONSE: fprintf(fd, ":\n"); size -= 4 * sizeof (char); n = msg->rip_nets; for (; size > 0; n++, size -= sizeof (struct netinfo)) { if (size < sizeof (struct netinfo)) break; fprintf(fd, "\tdst %s metric %D\n", #define satosin(sa) ((struct sockaddr_in *)&sa) inet_ntoa(satosin(n->rip_dst)->sin_addr), ntohl(n->rip_metric)); } break; case RIPCMD_TRACEON: fprintf(fd, ", file=%*s\n", size, msg->rip_tracefile); break; case RIPCMD_TRACEOFF: fprintf(fd, "\n"); break; } fflush(fd); } &dst)) continue; if (!gethostnameornumber(gname, &gate)) continue; if (strcmp(qual, "passive") == 0) { /* * Passive entries aren't placed in our tables, * only the kernel's,etc/routed/trace.h 440 0 12 3273 4100744430 7347 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)trace.h 5.2 (Berkeley) 4/20/86 */ /* * Routing table management daemon. */ /* * Trace record format. */ struct iftrace { time_t ift_stamp; /* time stamp */ struct sockaddr ift_who; /* from/to */ char *ift_packet; /* pointer to packet */ short ift_size; /* size of packet */ short ift_metric; /* metric on associated metric */ }; /* * Per interface packet tracing buffers. An incoming and * outgoing circular buffer of packets is maintained, per * interface, for debugging. Buffers are dumped whenever * an interface is marked down. */ struct ifdebug { struct iftrace *ifd_records; /* array of trace records */ struct iftrace *ifd_front; /* next empty trace record */ int ifd_count; /* number of unprinted records */ struct interface *ifd_if; /* for locating stuff */ }; /* * Packet tracing stuff. */ int tracepackets; /* watch packets as they go by */ int tracing; /* on/off */ FILE *ftrace; /* output trace file */ #define TRACE_ACTION(action, route) { \ if (tracing) \ traceaction(ftrace, "action", route); \ } #define TRACE_INPUT(ifp, src, size) { \ if (tracing) { \ ifp = if_iflookup(src); \ if (ifp) \ trace(&ifp->int_input, src, packet, size, \ ntohl(ifp->int_metric)); \ } \ if (tracepackets) \ dumppacket(stdout, "from", src, packet, size); \ } #define TRACE_OUTPUT(ifp, dst, size) { \ if (tracing && ifp) \ trace(&ifp->int_output, dst, packet, size, ifp->int_metric); \ if (tracepackets) \ dumppacket(stdout, "to", dst, packet, size); \ } . * * @(#)trace.h 5.2 (Berkeley) 4/20/86 */ /* * Routing table management daemon. */ /* * Trace record format. */ struct iftrace { time_t ift_stamp; /* time stamp */ struct sockaddr ift_who; /* from/to */ char *ift_packet; /* pointer to packet */ short ift_size; /* size of packet */ short ift_metric; /* meetc/routed/tools/ 770 0 12 0 4101142074 7146 etc/routed/tools/Makefile 440 0 12 1043 4100744476 10703 # # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.1 (Berkeley) 6/4/85 # ALL= ../protocol.h query.c trace.c CFLAGS= -O DESTDIR= LDFLAGS= all: query trace # test programs and utilities query: query.o ${CC} -o query ${LDFLAGS} query.o trace: trace.o ${CC} -o trace ${LDFLAGS} trace.o install: @echo Nothing to install clean: rm -f *.o core a.out t.c query linterrs trace typescript errs * Per interface packet tracing buffers. Anþƒncoming and * outgoing circular buffer of packets is maintained, per * interface, for debugging. Buffers are dumped whenever * an interface is marked down. */ struct ifdebug { struct iftrace *ifd_records; /* array of trace records */ struct iftrace *ifd_front; /* next empty trace record */ int ifd_count; /* number of unprinted records */ struct interface *ifd_if; /* for locating stuff */ }; /* * Packet tracing stufetc/routed/tools/query.c 440 0 12 12613 4101131603 10560 /* * Copyright (c) 1980 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)query.c 5.7 (Berkeley) 5/15/86"; #endif not lint #include #include #include #include #include #include #include #include #include #include #define WTIME 5 /* Time to wait for all responses */ #define STIME 500000L /* usec to wait for another response */ int s; int timedout, timeout(); char packet[MAXPACKETSIZE]; extern int errno; int nflag; main(argc, argv) int argc; char *argv[]; { int cc, count; long bits; struct sockaddr from; int fromlen = sizeof(from); struct timeval shorttime; if (argc < 2) { usage: printf("usage: query [ -n ] hosts...\n"); exit(1); } s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); exit(2); } argv++, argc--; if (*argv[0] == '-') { switch (argv[0][1]) { case 'n': nflag++; break; default: goto usage; } argc--, argv++; } while (argc > 0) { query(*argv); count++; argv++, argc--; } /* * Listen for returning packets; * may be more than one packet per host. */ bits = 1L << s; bzero(&shorttime, sizeof(shorttime)); shorttime.tv_usec = STIME; signal(SIGALRM, timeout); alarm(WTIME); while ((count > 0 && !timedout) || select(20, &bits, 0, 0, &shorttime) > 0) { cc = recvfrom(s, packet, sizeof (packet), 0, &from, &fromlen); if (cc <= 0) { if (cc < 0) { if (errno == EINTR) continue; perror("recvfrom"); (void) close(s); exit(1); } continue; } rip_input(&from, cc); count--; } } query(host) char *host; { struct sockaddr_in router; register struct rip *msg = (struct rip *)packet; struct hostent *hp; struct servent *sp; bzero((char *)&router, sizeof (router)); router.sin_family = AF_INET; router.sin_addr.s_addr = inet_addr(host); if (router.sin_addr.s_addr == -1) { hp = gethostbyname(host); if (hp == 0) { printf("%s: unknown\n", host); exit(1); } bcopy(hp->h_addr, &router.sin_addr, hp->h_length); } sp = getservbyname("router", "udp"); if (sp == 0) { printf("udp/router: service unknown\n"); exit(1); } router.sin_port = sp->s_port; msg->rip_cmd = RIPCMD_REQUEST; msg->rip_vers = RIPVERSION; msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); msg->rip_nets[0].rip_metric = htonl(HOPCNT_INFINITY); if (sendto(s, packet, sizeof (struct rip), 0, &router, sizeof(router)) < 0) perror(host); } /* * Handle an incoming routing packet. */ rip_input(from, size) struct sockaddr_in *from; int size; { register struct rip *msg = (struct rip *)packet; register struct netinfo *n; char *name; u_long lna, net, subnet; struct hostent *hp; struct netent *np; if (msg->rip_cmd != RIPCMD_RESPONSE) return; printf("%d bytes from ", size); if (nflag) printf("%s:\n", inet_ntoa(from->sin_addr)); else { hp = gethostbyaddr(&from->sin_addr, sizeof (struct in_addr), AF_INET); name = hp == 0 ? "???" : hp->h_name; printf("%s(%s):\n", name, inet_ntoa(from->sin_addr)); } size -= sizeof (int); n = msg->rip_nets; while (size > 0) { if (size < sizeof (struct netinfo)) break; if (msg->rip_vers > 0) { n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); n->rip_metric = ntohl(n->rip_metric); } switch (n->rip_dst.sa_family) { case AF_INET: { register struct sockaddr_in *sin; sin = (struct sockaddr_in *)&n->rip_dst; net = inet_netof(sin->sin_addr); subnet = inet_subnetof(sin->sin_addr); lna = inet_lnaof(sin->sin_addr); name = "???"; if (!nflag) { if (sin->sin_addr.s_addr == 0) name = "default"; else if (lna == INADDR_ANY) { np = getnetbyaddr(net, AF_INET); if (np) name = np->n_name; else if (net == 0) name = "default"; } else if ((lna & 0xff) == 0 && (np = getnetbyaddr(subnet, AF_INET))) { struct in_addr subnaddr, inet_makeaddr(); subnaddr = inet_makeaddr(subnet, INADDR_ANY); if (bcmp(&sin->sin_addr, &subnaddr, sizeof(subnaddr)) == 0) name = np->n_name; else goto host; } else { host: hp = gethostbyaddr(&sin->sin_addr, sizeof (struct in_addr), AF_INET); if (hp) name = hp->h_name; } printf("\t%s(%s), metric %D\n", name, inet_ntoa(sin->sin_addr), n->rip_metric); } else printf("\t%s, metric %D\n", inet_ntoa(sin->sin_addr), n->rip_metric); break; } default: { u_short *p = (u_short *)n->rip_dst.sa_data; printf("\t(af %d) %x %x %x %x %x %x %x, metric %D\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], n->rip_dst.sa_family, n->rip_metric); break; } } size -= sizeof (struct netinfo), n++; } } timeout() { timedout = 1; } /* * Return the possible subnetwork number from an internet address. * SHOULD FIND OUT WHETHER THIS IS A LOCAL NETWORK BEFORE LOOKING * INSIDE OF THE HOST PART. We can only believe this if we have other * information (e.g., we can find a name for this number). */ inet_subnetof(in) struct in_addr in; { register u_long i = ntohl(in.s_addr); if (IN_CLASSA(i)) return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); else if (IN_CLASSB(i)) return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); else return ((i & 0xffffffc0) >> 28); } ; n++, size -= sizeof (struct netinfo)) { if (size < sizeof (struct netinfo)) break; fprintf(fd, "\tdst %s etc/routed/tools/trace.c 440 0 12 4260 4277714232 10513 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)trace.c 5.3 (Berkeley) 2/12/86"; #endif not lint #include #include #include #include #include #include #include #include #include struct sockaddr_in myaddr = { AF_INET, IPPORT_RESERVED-1 }; char packet[MAXPACKETSIZE]; main(argc, argv) int argc; char *argv[]; { int size, s; struct sockaddr from; struct sockaddr_in router; register struct rip *msg = (struct rip *)packet; struct hostent *hp; struct servent *sp; if (argc < 3) { usage: printf("usage: trace cmd machines,\n"); printf("cmd either \"on filename\", or \"off\"\n"); exit(1); } s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { perror("socket"); exit(2); } #ifdef vax || pdp11 myaddr.sin_port = htons(myaddr.sin_port); #endif if (bind(s, &myaddr, sizeof(myaddr)) < 0) { perror("bind"); exit(2); } argv++, argc--; msg->rip_cmd = strcmp(*argv, "on") == 0 ? RIPCMD_TRACEON : RIPCMD_TRACEOFF; msg->rip_vers = RIPVERSION; argv++, argc--; size = sizeof (int); if (msg->rip_cmd == RIPCMD_TRACEON) { strcpy(msg->rip_tracefile, *argv); size += strlen(*argv); argv++, argc--; } if (argc == 0) goto usage; bzero((char *)&router, sizeof (router)); router.sin_family = AF_INET; sp = getservbyname("router", "udp"); if (sp == 0) { printf("udp/router: service unknown\n"); exit(1); } router.sin_port = sp->s_port; while (argc > 0) { router.sin_family = AF_INET; router.sin_addr.s_addr = inet_addr(*argv); if (router.sin_addr.s_addr == -1) { hp = gethostbyname(*argv); if (hp == 0) { printf("%s: unknown\n", *argv); exit(1); } bcopy(hp->h_addr, &router.sin_addr, hp->h_length); } if (sendto(s, packet, size, 0, &router, sizeof(router)) < 0) perror(*argv); argv++, argc--; } } (argc > 0) { query(*argv); count++; argv++, argc--; } /* * Listen for returning packets; * may be more than one packet per host. */ bits = 1L << s; bzero(&shorttime, sizeof(shorttime)); shorttime.tv_usec = STIME; signal(SIGALRM, timeout); alarm(WTIME); while ((count > 0 && !timedout) || select(20, &bits, 0, etc/routed/make.out 440 0 12 3427 4100746073 7554 cc -c af.c af.c:47: warning: sign extension in bitwise logical operation cc -c if.c cc -c input.c cc -c main.c main.c:103: warning: sign extension in bitwise logical operation main.c:103: warning: sign extension in bitwise logical operation cc -c output.c cc -c startup.c startup.c:45: warning: sign extension in bitwise logical operation startup.c:45: warning: sign extension in bitwise logical operation startup.c:56: warning: sign extension in bitwise logical operation startup.c:56: warning: sign extension in bitwise logical operation startup.c:76: warning: sign extension in bitwise logical operation startup.c:76: warning: sign extension in bitwise logical operation startup.c:83: warning: sign extension in bitwise logical operation startup.c:83: warning: sign extension in bitwise logical operation startup.c:89: warning: sign extension in bitwise logical operation startup.c:89: warning: sign extension in bitwise logical operation startup.c:93: warning: sign extension in bitwise logical operation startup.c:93: warning: sign extension in bitwise logical operation startup.c:263: warning: sign extension in bitwise logical operation startup.c:263: warning: sign extension in bitwise logical operation cc -c tables.c tables.c:153: warning: sign extension in bitwise logical operation tables.c:153: warning: sign extension in bitwise logical operation tables.c:199: warning: sign extension in bitwise logical operation tables.c:199: warning: sign extension in bitwise logical operation tables.c:201: warning: sign extension in bitwise logical operation tables.c:201: warning: sign extension in bitwise logical operation tables.c:215: warning: sign extension in bitwise logical operation tables.c:215: warning: sign extension in bitwise logical operation 23: Illegal initialization *** Exit 1 Stop. } } query(host) char *host; { struct sockaddr_in router; register struct rip *msg = (struct rip *)packet; struct hostent *hp; struct servent *sp; bzero((char *)&router, sizeof (router)); router.sin_family = AF_INET; routeretc/implog/ 750 0 12 0 6024536043 6002 etc/implog/implog.c 440 0 12 116 5133425560 7500 main() { puts("implog hasn't been implemented under 2.11BSD."); exit(-1); } etc/implog/Makefile 440 0 12 1032 4015525326 7522 # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.3 (Berkeley) 9/7/85 # ALL= implog implogd DESTDIR= CFLAGS=-O SEPFLAG= -i all: ${ALL} implog: implog.o ${CC} ${SEPFLAG} implog.o -o implog implogd: implogd.o ${CC} ${SEPFLAG} implogd.o -o implogd clean: rm -f ${ALL} *.o *.s errs core a.out t.? install: ${ALL} install -s implog ${DESTDIR}/etc install -s implogd ${DESTDIR}/etc eration startup.c:76: warning: sign extension in bitwiþƒ logical operation startup.c:76: warning: sign extension in bitwise logical operation startup.c:83: warning: sign extension in bitwise logical operation startup.c:83: warning: sign extension in bitwise logical operation startup.c:89: warning: sign extension in bitwise logical operation startup.c:89: warning: sign extension in bitwise logical operation startup.c:93: warning: sign extension in bitwise logical operation startup.cetc/implog/implogd.c 440 0 12 117 5133425561 7646 main() { puts("implogd hasn't been implemented under 2.11BSD."); exit(-1); } etc/Makefile 440 0 12 7204 5741404104 6237 # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.14.3 (2.11BSD GTE) 4/7/95 # DESTDIR= CFLAGS= -O SEPFLAG= -i # Programs that live in subdirectories, and have makefiles of their own. # SUBDIR= chroot config dev_mkdb dump fingerd fsck ftpd getty htable implog \ named restor routed talkd termcap tftpd timed tzone XNSrouted \ mkpasswd vipw rlogind rshd tcpd # Shell scripts that need only be installed and are never removed. # SCRIPT= mklost+found # C programs that live in the current directory and do not need # explicit make lines. # STD= ac accton arff bad144 badsect catman chown clri comsat \ cron dcheck diskpart dumpfs edquota flcopy \ gettable ifconfig icheck inetd init newfs mkfs mknod \ mkproto mount ncheck quotaon quotacheck reboot renice \ repquota rexecd rmt route rwhod rxformat sa savecore \ shutdown slattach swapon syslogd telnetd tunefs umount update # C programs that live in the current directory and need explicit make lines. # NSTD= # Programs that must run setuid to root # SETUID= ping # C programs that must run set-group-id kmem. # KMEM= fstat pstat arp dmesg kgmon trpt # C programs that must run set-group-id operator. # OPERATOR= quot # optional: not always made OPTIONAL= mkhosts all: ${SUBDIR} ${STD} ${NSTD} ${OPTIONAL} ${KMEM} ${SETUID} ${OPERATOR} ${SUBDIR}: FRC cd $@; make ${MFLAGS} SEPFLAG=${SEPFLAG} ${STD} ${KMEM} ${SETUID} ${OPERATOR}: cc ${CFLAGS} ${SEPFLAG} -o $@ $@.c install: ${STD} ${NSTD} ${SETUID} ${KMEM} ${OPERATOR} -for i in ${SUBDIR}; do \ (cd $$i; make ${MFLAGS} DESTDIR=${DESTDIR} install); done -for i in ${SCRIPT}; do (install -c $$i.sh ${DESTDIR}/etc/$$i); done install -s ${STD} ${NSTD} ${DESTDIR}/etc -for i in ${OPTIONAL}; do \ (if [ -f $$i ]; then install -s $$i ${DESTDIR}/etc; fi); done -for i in ${SETUID}; do \ (install -o root -m 4755 -s $$i ${DESTDIR}/etc/$$i); done -for i in ${KMEM}; do \ (install -g kmem -m 2755 -s $$i ${DESTDIR}/etc/$$i); done -for i in ${OPERATOR}; do \ (install -g operator -m 2755 -s $$i ${DESTDIR}/etc/$$i); done -chown root.operator ${DESTDIR}/etc/shutdown -chmod 4750 ${DESTDIR}/etc/shutdown -rm -f ${DESTDIR}/etc/quotaoff -ln ${DESTDIR}/etc/quotaon ${DESTDIR}/etc/quotaoff -rm -f ${DESTDIR}/etc/fastboot ${DESTDIR}/etc/halt -ln ${DESTDIR}/etc/reboot ${DESTDIR}/etc/fastboot -ln ${DESTDIR}/etc/reboot ${DESTDIR}/etc/halt -mkdir ${DESTDIR}/usr/spool/rwho -chmod 755 ${DESTDIR}/etc/init clean: -rm -f a.out core *.s *.o -for i in ${SUBDIR}; do (cd $$i; make ${MFLAGS} clean); done -rm -f ${STD} ${NSTD} ${KMEM} ${SETUID} ${OPERATOR} ${OPTIONAL} FRC: depend: for i in ${STD} ${NSTD} ${KMEM} ${SETUID}; do \ cc -M ${INCPATH} $$i.c | sed 's/\.o//' | \ awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ else rec = rec " " $$2 } } \ END { print rec } ' >> makedep; done echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep echo '$$r makedep' >>eddep echo 'w' >>eddep cp Makefile Makefile.bak ed - Makefile < eddep rm eddep makedep echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile echo '# see make depend above' >> Makefile # Files listed in ${NSTD} and ${OPTIONAL} have explicit make lines given below. mkhosts: @echo "Mkhosts only works with the dbm version of the hostent routines." @echo "If gethosts() is not in libc, mkhosts isn't installed." -cc ${CFLAGS} -o mkhosts mkhosts.c || rm mkhosts # DO NOT DELETE THIS LINE -- make depend uses it unknown\n", host); exit(1); } bcopy(hp->h_addr, &router.sin_addr, hp->h_length); } sp = getservbyname("router", "udp"); if (sp == 0) { printf("udp/router: service unknown\n"); exit(1); } router.sin_port = sp->s_port; msg->rip_cmd = RIPCMD_REQUEST; msg->rip_vers = RIPVERSION; msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); msg->rip_nets[0].rip_metric etc/htable/ 750 0 12 0 6024536041 5750 etc/htable/parse.y 440 0 12 4002 4015515255 7336 %{ /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)parse.y 5.2 (Berkeley) 6/21/85"; #endif not lint #include "htable.h" %} %union { int number; struct addr *addrlist; struct name *namelist; } %start Table %token END %token NUMBER KEYWORD %token NAME %type Names Cputype Opsys Protos Proto %type Addresses Address %% Table : Entry | Table Entry ; Entry : KEYWORD ':' Addresses ':' Names ':' END = { do_entry($1, $3, $5, NONAME, NONAME, NONAME); } | KEYWORD ':' Addresses ':' Names ':' Cputype ':' END = { do_entry($1, $3, $5, $7, NONAME, NONAME); } | KEYWORD ':' Addresses ':' Names ':' Cputype ':' Opsys ':' END = { do_entry($1, $3, $5, $7, $9, NONAME); } | KEYWORD ':' Addresses ':' Names ':' Cputype ':' Opsys ':' ':' END = { do_entry($1, $3, $5, $7, $9, NONAME); } | KEYWORD ':' Addresses ':' Names ':' Cputype ':' Opsys ':' Protos ':' END = { do_entry($1, $3, $5, $7, $9, $11); } | error END | END /* blank line */ ; Addresses: Address = { $$ = $1; } | Address ',' Addresses = { $1->addr_link = $3; $$ = $1; } ; Address : NUMBER '.' NUMBER '.' NUMBER '.' NUMBER = { char *a; $$ = (struct addr *)malloc(sizeof (struct addr)); a = (char *)&($$->addr_val); a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7; $$->addr_link = NOADDR; } ; Names : NAME = { $$ = $1; } | NAME ',' Names = { $1->name_link = $3; $$ = $1; } ; Cputype : /* empty */ = { $$ = NONAME; } | NAME = { $$ = $1; } ; Opsys : /* empty */ = { $$ = NONAME; } | NAME = { $$ = $1; } ; Protos : Proto = { $$ = $1; } | Proto ',' Protos = { $1->name_link = $3; $$ = $1; } ; Proto : NAME = { $$ = $1; } ; %% #include extern int yylineno; yyerror(msg) char *msg; { fprintf(stderr, "\"%s\", line %d: %s\n", infile, yylineno, msg); } c, mkhosts isn't installed." -cc ${CFLAGS} -o mkhosts mkhosts.c || rm mkhosts # DO NOT DELETE THIS LINE -- make depend uses it unknown\n", host); exit(1); } bcopy(hp->h_addr, &router.sin_addr, hp->h_length); } sp = getservbyname("router", "udp"); if (sp == 0) { printf("udp/router: service unknown\n"); exit(1); } router.sin_port = sp->s_port; msg->rip_cmd = RIPCMD_REQUEST; msg->rip_vers = RIPVERSION; msg->rip_nets[0].rip_dst.sa_family = htons(AF_UNSPEC); msg->rip_nets[0].rip_metric etc/htable/Makefile 440 0 12 1247 5326557362 7515 # # Copyright (c) 1980 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.2 (Berkeley) 9/18/85 # CFLAGS= -O SEPFLAG= -i DESTDIR= ALL= htable all: ${ALL} htable: htable.o parse.o scan.o ${CC} ${SEPFLAG} htable.o parse.o scan.o -o htable htable.o: htable.c htable.h ${CC} ${CFLAGS} -c htable.c scan.o: scan.c htable.h y.tab.h parse.o: parse.c htable.h scan.c: scan.l parse.c: parse.y y.tab.h: ${YACC} -d parse.y rm y.tab.c clean: rm -f ${ALL} *.o *.s parse.c scan.c y.tab.h errs install: htable install -s htable ${DESTDIR}/etc/htable , NONAME); } | KEYWORD ':' Addresses ':' Names ':' Cputype ':' END = { do_entry($1, $3, $5, $7, NONAME, NONAME); } | KEYWORD ':' Addresses ':' Names ':' Cputype ':' Opsys ':' END = { do_entry($1, $3, $5, $7, $9, NONAME); } | KEYWORD ':' Addresses ':' Names ':' Cputype ':' Opsys ':' ':' END = { do_entry($1, $3, $5, $7, $9, NONAMEetc/htable/htable.h 440 0 12 1630 4015515256 7447 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. * * @(#)htable.h 5.1 (Berkeley) 5/28/85 */ #include /* * common definitions for htable */ struct addr { u_long addr_val; struct addr *addr_link; }; struct name { char *name_val; struct name *name_link; }; struct gateway { struct gateway *g_link; struct gateway *g_dst; /* connected gateway if metric > 0 */ struct gateway *g_firstent; /* first entry for this gateway */ struct name *g_name; int g_net; u_long g_addr; /* address on g_net */ int g_metric; /* hops to this net */ }; #define NOADDR ((struct addr *)0) #define NONAME ((struct name *)0) #define KW_NET 1 #define KW_GATEWAY 2 #define KW_HOST 3 struct name *newname(); char *malloc(); char *infile; /* Input file name */ ORD ':' Addresses ':' Names ':' Cputype ':' Opsys ':' ':' END = { do_entry($1, $3, $5, $7, $9, NONAMEetc/htable/scan.l 440 0 12 2271 4015515256 7142 %{ /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)scan.l 5.4 (Berkeley) 4/19/86"; #endif not lint #include "y.tab.h" #include "htable.h" %} BLANK [ \t] DIGIT [0-9] ALPHA [A-Za-z] ANUM [0-9A-Za-z] NAMECHR [0-9A-Za-z./-] %% "NET" { yylval.number = KW_NET; return (KEYWORD); } "GATEWAY" { yylval.number = KW_GATEWAY; return (KEYWORD); } "HOST" { yylval.number = KW_HOST; return (KEYWORD); } {ALPHA}{NAMECHR}*{ANUM} { yylval.namelist = newname(yytext); return (NAME); } {ALPHA} { yylval.namelist = newname(yytext); return (NAME); } {DIGIT}+{ALPHA}{NAMECHR}* { fprintf(stderr, "Warning: nonstandard name \"%s\"\n", yytext); yylval.namelist = newname(yytext); return (NAME); } {DIGIT}+ { yylval.number = atoi(yytext); return (NUMBER); } "." return ('.'); ":" return (':'); "," return (','); "/" return ('/'); ";".* ; "\n"{BLANK}+ ; {BLANK}+ ; "\n" return (END); . fprintf(stderr, "Illegal char: '%s'\n", yytext); %% yywrap() { return (1); } net */ }; #define NOADDR ((struct addr *)0) #define NONAME ((struct name *)0) #define KW_NET 1 #define KW_GATEWAY 2 #define KW_HOST 3 struct name *newname(); char *malloc(); char *infile; /* Input file name */ ORD ':' Addresses ':' Names ':' Cputype ':' Opsys ':' ':' END = { do_entry($1, $3, $5, $7, $9, NONAMEetc/htable/htable.c 440 0 12 26712 5514436375 7503 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)htable.c 5.5.1 (2.11BSD GTE) 1/1/94"; #endif /* * htable - convert NIC host table into a UNIX format. * NIC format is described in RFC 810, 1 March 1982. */ #include #include #include #include #include "htable.h" /* includes */ #include #include #include #define DATELINES 3 /* these lines usually contain the date */ #define MAXNETS 30 /* array size for local, connected nets */ FILE *hf; /* hosts file */ FILE *gf; /* gateways file */ FILE *nf; /* networks file */ struct gateway *savegateway(), *gatewayto(); u_long connected_nets[MAXNETS]; int nconnected; u_long local_nets[MAXNETS]; int nlocal; char *myname; main(argc, argv) int argc; char *argv[]; { int errs; infile = "(stdin)"; myname = argv[0]; argc--; argv++; while (argc--) { if (*argv[0] == '-') { switch (argv[0][1]) { case 'c': nconnected = addlocal(argv[1], connected_nets); argv++; argc--; break; case 'l': nlocal = addlocal(argv[1], local_nets); argv++; argc--; break; default: usage(); /*NOTREACHED*/ } } else { infile = argv[0]; if (freopen(infile, "r", stdin) == NULL) { perror(infile); exit(1); } } argv++; } hf = fopen("hosts", "w"); if (hf == NULL) { perror("hosts"); exit(1); } copylocal(hf, "localhosts"); gf = fopen("gateways", "w"); if (gf == NULL) { perror("gateways"); exit(1); } copygateways(gf, "localgateways"); nf = fopen("networks", "w"); if (nf == NULL) { perror("networks"); exit(1); } copylocal(nf, "localnetworks"); copycomments(stdin, hf, DATELINES); errs = yyparse(); dogateways(); exit(errs); } usage() { fprintf(stderr, "usage: %s [ -c connected-nets ] [-l local-nets ] [ input-file ]\n", myname); exit(1); } /* * Turn a comma-separated list of network names or numbers in dot notation * (e.g. "arpanet, 128.32") into an array of net numbers. */ addlocal(arg, nets) char *arg; int *nets; { register char *p, c; register int nfound = 0; do { p = arg; while (*p && *p != ',' && !isspace(*p)) p++; c = *p; *p = 0; while (*arg && isspace(*arg)) arg++; if (*arg == 0) continue; if (nfound == MAXNETS) { fprintf(stderr, "%s: Too many networks in list\n", myname); return (nfound); } if (getnetaddr(arg, &nets[nfound])) nfound++; else { fprintf(stderr, "%s: %s: unknown network\n", myname, arg); exit(1); } arg = p + 1; } while (c); return (nfound); } struct name * newname(str) char *str; { char *p; struct name *nm; p = malloc(strlen(str) + 1); strcpy(p, str); nm = (struct name *)malloc(sizeof (struct name)); nm->name_val = p; nm->name_link = NONAME; return (nm); } char * lower(str) char *str; { register char *cp = str; while (*cp) { if (isupper(*cp)) *cp = tolower(*cp); cp++; } return (str); } do_entry(keyword, addrlist, namelist, cputype, opsys, protos) int keyword; struct addr *addrlist; struct name *namelist, *cputype, *opsys, *protos; { register struct addr *al, *al2; register struct name *nl; struct addr *connect_addr; char *cp; switch (keyword) { case KW_NET: nl = namelist; if (nl == NONAME) { fprintf(stderr, "htable: net"); putnet(stderr, inet_netof(addrlist->addr_val)); fprintf(stderr, " missing names.\n"); break; } fprintf(nf, "%-16.16s", lower(nl->name_val)); al2 = addrlist; while (al = al2) { char *cp; putnet(nf, inet_netof(al->addr_val)); cp = "\t%s"; while (nl = nl->name_link) { fprintf(nf, cp, lower(nl->name_val)); cp = " %s"; } putc('\n', nf); al2 = al->addr_link; free((char *)al); } break; case KW_GATEWAY: /* locate locally connected address, if one */ for (al = addrlist; al; al = al->addr_link) if (connectedto(inet_netof(al->addr_val))) break; if (al == NULL) { /* * Not connected to known networks. Save for later. */ struct gateway *gw, *firstgw = (struct gateway *) NULL; for (al = addrlist; al; al = al->addr_link) { register u_long net; net = inet_netof(al->addr_val); gw = savegateway(namelist, net, al->addr_val, 0); if (firstgw == (struct gateway *) NULL) firstgw = gw; gw->g_firstent = firstgw; } freeaddrs(addrlist); goto dontfree; } /* * Connected to a known network. * Mark this as the gateway to all other networks * that are on the addrlist (unless we already have * gateways to them). */ connect_addr = al; for (al = addrlist; al; al = al->addr_link) { register u_long net; /* suppress duplicates -- not optimal */ net = inet_netof(al->addr_val); if (connectedto(net) || gatewayto(net)) continue; printgateway(net, namelist->name_val, 1); (void) savegateway(namelist, net, al->addr_val, 1); } /* * Put the gateway in the hosts file. */ putaddr(hf, connect_addr->addr_val); cp = "%s"; for (nl = namelist; nl; nl = nl->name_link) { fprintf(hf, cp, lower(nl->name_val)); cp = " %s"; } fprintf(hf, "\t# gateway\n"); freeaddrs(addrlist); goto dontfree; case KW_HOST: al2 = addrlist; while (al = al2) { if (!local(inet_netof(al->addr_val))) { char *cp; putaddr(hf, al->addr_val); cp = "%s"; for (nl = namelist; nl; nl = nl->name_link) { fprintf(hf, cp, lower(nl->name_val)); cp = " %s"; } putc('\n', hf); } al2 = al->addr_link; free((char *)al); } break; default: fprintf(stderr, "Unknown keyword: %d.\n", keyword); } freenames(namelist); dontfree: freenames(cputype); freenames(opsys); freenames(protos); } printgateway(net, name, metric) u_long net; char *name; int metric; { struct netent *np; fprintf(gf, "net "); np = getnetbyaddr(net, AF_INET); if (np) fprintf(gf, "%s", np->n_name); else putnet(gf, net); fprintf(gf, " gateway %s metric %d passive\n", lower(name), metric); } copylocal(f, filename) FILE *f; char *filename; { register FILE *lhf; register cc; char buf[BUFSIZ]; extern int errno; lhf = fopen(filename, "r"); if (lhf == NULL) { if (errno != ENOENT) { perror(filename); exit(1); } fprintf(stderr, "Warning, no %s file.\n", filename); return; } while (cc = fread(buf, 1, sizeof(buf), lhf)) fwrite(buf, 1, cc, f); fclose(lhf); } copygateways(f, filename) FILE *f; char *filename; { register FILE *lhf; struct name *nl; char type[80]; char dname[80]; char gname[80]; char junk[80]; char buf[500]; u_long addr, net; int metric; extern int errno; lhf = fopen(filename, "r"); if (lhf == NULL) { if (errno != ENOENT) { perror(filename); exit(1); } fprintf(stderr, "Warning, no %s file.\n", filename); return; } /* format: {net | host} XX gateway XX metric DD [passive]\n */ for (;;) { junk[0] = 0; if (fgets(buf, sizeof(buf), lhf) == (char *)NULL) break; fputs(buf, gf); if (buf[0] == '#' || sscanf(buf, "%s %s gateway %s metric %d %s", type, dname, gname, &metric, junk) < 5) continue; if (strcmp(type, "net")) continue; if (!getnetaddr(dname, &net)) continue; if (!gethostaddr(gname, &addr)) continue; nl = newname(gname); (void) savegateway(nl, net, addr, metric); } fclose(lhf); } getnetaddr(name, addr) char *name; u_long *addr; { struct netent *np = getnetbyname(name); int n; if (np == 0) { *addr = inet_network(name); return (*addr != -1); } else { if (np->n_addrtype != AF_INET) return (0); *addr = np->n_net; return (1); } } gethostaddr(name, addr) char *name; u_long *addr; { struct hostent *hp; hp = gethostbyname(name); if (hp) { *addr = *(u_long *)(hp->h_addr); return (1); } *addr = inet_addr(name); return (*addr != -1); } copycomments(in, out, ccount) FILE *in, *out; int ccount; { char buf[BUFSIZ]; int length; int count; char *fgets(); for (count=0; count < ccount; count++) { if ((fgets(buf, sizeof(buf), in) == NULL) || (buf[0] != ';')) return; buf[0] = '#'; fputs(buf, out); } return; } #define UC(b) (((int)(b))&0xff) /* * Print network number in internet-standard dot notation; * v is in host byte order. */ putnet(f, v) FILE *f; register u_long v; { if (v < 128) fprintf(f, "%d", (int)v); else if (v < 65536) fprintf(f, "%d.%d", UC(v >> 8), UC(v)); else fprintf(f, "%d.%d.%d", UC(v >> 16), UC(v >> 8), UC(v)); } putaddr(f, v) FILE *f; u_long v; { register char *a = (char *)&v; char buf[32]; sprintf(buf,"%d.%d.%d.%d", UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3])); fprintf(f, "%-16.16s", buf); } freenames(list) struct name *list; { register struct name *nl, *nl2; nl2 = list; while (nl = nl2) { nl2 = nl->name_link; free(nl->name_val); free((char *)nl); } } freeaddrs(list) struct addr *list; { register struct addr *al, *al2; al2 = list; while (al = al2) al2 = al->addr_link, free((char *)al); } struct gateway *gateways = 0; struct gateway *lastgateway = 0; struct gateway * gatewayto(net) register u_long net; { register struct gateway *gp; for (gp = gateways; gp; gp = gp->g_link) if ((gp->g_net == net) && (gp->g_metric > 0)) return (gp); return ((struct gateway *) NULL); } struct gateway * savegateway(namelist, net, addr, metric) struct name *namelist; u_long addr, net; int metric; { register struct gateway *gp; gp = (struct gateway *)malloc(sizeof (struct gateway)); if (gp == 0) { fprintf(stderr, "htable: out of memory\n"); exit(1); } gp->g_link = (struct gateway *) NULL; if (lastgateway) lastgateway->g_link = gp; else gateways = gp; lastgateway = gp; gp->g_name = namelist; gp->g_net = net; gp->g_addr = addr; gp->g_metric = metric; if (metric == 1) gp->g_dst = gp; return (gp); } connectedto(net) u_long net; { register i; for (i = 0; i < nconnected; i++) if (connected_nets[i] == net) return(1); return(0); } local(net) u_long net; { register i; for (i = 0; i < nlocal; i++) if (local_nets[i] == net) return(1); return(0); } #define MAXHOPS 10 /* * Go through list of gateways, finding connections for gateways * that are not yet connected. */ dogateways() { register struct gateway *gp, *gw, *ggp; register int hops, changed = 1; struct name *nl; char *cp; for (hops = 0; hops < MAXHOPS && changed; hops++, changed = 0) { for (gp = gateways; gp; gp = gp->g_link) if ((gp->g_metric == 0) && (gw = gatewayto(gp->g_net))) { /* * Found a new connection. * For each other network that this gateway is on, * add a new gateway to that network. */ changed = 1; gp->g_dst = gw->g_dst; gp->g_metric = gw->g_metric + 1; for (ggp = gp->g_firstent; ggp->g_name == gp->g_name; ggp = ggp->g_link) { if (ggp == gp) continue; if (gatewayto(ggp->g_net)) continue; ggp->g_dst = gp->g_dst; ggp->g_metric = gp->g_metric; printgateway(ggp->g_net, gw->g_dst->g_name->name_val, gp->g_metric); } /* * Put the gateway in the hosts file, * using the address for the connected net. */ putaddr(hf, gp->g_addr); cp = "%s"; for (nl = gp->g_name; nl; nl = nl->name_link) { fprintf(hf, cp, lower(nl->name_val)); cp = " %s"; } fprintf(hf, "\t# gateway\n"); } } } ) + 1); strcpy(p, str); nm = (struct name *)malloc(setc/htable/hosts 440 0 12 60600 4015515257 7145 # # Berkeley Host Database # @(#)localhosts 1.31 5/13/86 # 127.1 localhost loghost localhost.berkeley.edu # These are needed for arpa and ucbvax to ifconfig imp's. 10.2.0.78 ucb-vax 10.0.0.78 ucb-arpa # # Berkeley Subnet 128.32.0 -- 3Mb/s Ethernet # 128.32.4 ucbarpa arpa ucbarpa.berkeley.edu 128.32.7 monet ucbmonet monet.berkeley.edu 128.32.10 ucbvax vax ucbvax.berkeley.edu 128.32.11 kim ucbkim kim.berkeley.edu 128.32.12 calder ucbcalder calder.berkeley.edu 128.32.13 dali ucbdali dali.berkeley.edu 128.32.14 matisse ucbmatisse matisse.berkeley.edu 128.32.19 ingres ucbingres ingres.berkeley.edu 128.32.22 degas ucbdegas degas.berkeley.edu 128.32.24 miro ucbmiro miro.berkeley.edu 128.32.25 lapis-en ucblapis-en lapis-en.berkeley.edu 128.32.31 renoir ucbrenoir renoir.berkeley.edu # # Berkeley Subnet 129 -- Experimental 10Mb/s Ethernet # 128.32.129.1 matisse-10 ucbmatisse-10 matisse-10.berkeley.edu 128.32.129.2 monet-10 ucbmonet-10 monet-10.berkeley.edu 128.32.129.3 calder-10 ucbcalder-10 calder-10.berkeley.edu # # Berkeley Subnet 130 -- CS Division 10 Mb/s Ethernet # 128.32.130.1 calder-cs calder-cs.berkeley.edu 128.32.130.2 vangogh ucbvangogh vangogh.berkeley.edu 128.32.130.3 okeeffe ucbokeeffe okeeffe.berkeley.edu 128.32.130.4 matisse-cs matisse-cs.berkeley.edu 128.32.130.5 cogsci ucbcogsci cogsci.berkeley.edu 128.32.130.6 monet-cs monet-cs.berkeley.edu 128.32.130.7 kim-cs kim-cg kim-cs.berkeley.edu 128.32.130.8 gardenia ucbgardenia gardenia.berkeley.edu 128.32.130.9 magnolia ucbmagnolia magnolia.berkeley.edu 128.32.130.10 azalea ucbazalea azalea.berkeley.edu 128.32.130.11 ucbarpa-cs arpa-cs ucbarpa-cs.berkeley.edu 128.32.130.12 ucbvax-cs vax-cs ucbvax-cs.berkeley.edu # # Berkeley Subnet 131 -- Evans Sun + Dandelion net # 128.32.131.1 xcssun ucbxcssun xcssun.berkeley.edu 128.32.131.2 xearth ucbxearth xearth.berkeley.edu 128.32.131.3 pluto ucbpluto pluto.berkeley.edu 128.32.131.4 uranus ucburanus uranus.berkeley.edu 128.32.131.5 neptune ucbneptune neptune.berkeley.edu 128.32.131.6 saturn ucbsaturn saturn.berkeley.edu 128.32.131.7 jupiter ucbjupiter jupiter.berkeley.edu 128.32.131.8 mars ucbmars mars.berkeley.edu 128.32.131.9 venus ucbvenus venus.berkeley.edu 128.32.131.10 mercury ucbmercury mercury.berkeley.edu 128.32.131.11 dali-xcs net124 ucbnet124 dali-xcs.berkeley.edu 128.32.131.12 disney ucbdisney disney.berkeley.edu 128.32.131.13 snow ucbsnow snow.berkeley.edu 128.32.131.14 bashful ucbbashful bashful.berkeley.edu 128.32.131.15 grumpy ucbgrumpy grumpy.berkeley.edu 128.32.131.16 sleepy ucbsleepy sleepy.berkeley.edu 128.32.131.17 doc ucbdoc doc.berkeley.edu 128.32.131.18 dopey ucbdopey dopey.berkeley.edu 128.32.131.19 happy ucbhappy happy.berkeley.edu 128.32.131.20 sneezy ucbsneezy sneezy.berkeley.edu 128.32.131.21 charming ucbcharming ucbprince prince charming.berkeley.edu 128.32.131.22 rip ucbrip rip.berkeley.edu 128.32.131.23 phoenix ucbphoenix phoenix.berkeley.edu 128.32.131.24 spur-gw ucbspur-gw spur-gw.berkeley.edu 128.32.131.25 birch ucbbirch birch.berkeley.edu 128.32.131.26 ash ucbash ash.berkeley.edu 128.32.131.27 teak ucbteak teak.berkeley.edu 128.32.131.28 palm ucbpalm palm.berkeley.edu 128.32.131.29 fir ucbfir fir.berkeley.edu 128.32.131.30 yew ucbyew yew.berkeley.edu 128.32.131.31 geppetto ucbgeppetto geppetto.berkeley.edu 128.32.131.32 pinocchio ucbpinocchio pinocchio.berkeley.edu 128.32.131.33 mike ucbmike mike.berkeley.edu 128.32.131.34 rob ucbrob rob.berkeley.edu 128.32.131.35 chip ucbchip chip.berkeley.edu 128.32.131.36 dim ucbdim dim.berkeley.edu 128.32.131.37 stun ucbstun stun.berkeley.edu 128.32.131.38 monet-xcs ucbmonet-xcs monet-xcs.berkeley.edu 128.32.131.39 harry ucbharry harry.berkeley.edu 128.32.131.40 craig ucbcraig craig.berkeley.edu 128.32.131.41 tigger ucbtigger tigger.berkeley.edu 128.32.131.42 fritz ucbfritz fritz.berkeley.edu 128.32.131.43 gerry ucbgerry gerry.berkeley.edu 128.32.131.44 pine ucbpine pine.berkeley.edu 128.32.131.45 fleur-de-lis ucbfleur-de-lis fleur-de-lis.berkeley.edu 128.32.131.46 piglet ucbpiglet piglet.berkeley.edu 128.32.131.47 achilles ucbachilles achilles.berkeley.edu 128.32.131.48 hector ucbhector hector.berkeley.edu 128.32.131.49 ji ucbji ji.berkeley.edu 128.32.131.50 madrone ucbmadrone madrone.berkeley.edu 128.32.131.51 tanoak ucbtanoak tanoak.berkeley.edu 128.32.131.52 cypress ucbcypress cypress.berkeley.edu 128.32.131.53 manzanita ucbmanzanita manzanita.berkeley.edu 128.32.131.54 dougfir ucbdougfir dougfir.berkeley.edu 128.32.131.55 bansai ucbbansai bansai.berkeley.edu 128.32.131.56 euca eucalyptus ucbeucalyptus eucalyptus.berkeley.edu 128.32.131.64 viking ucbviking viking.berkeley.edu 128.32.131.65 apollo ucbapollo apollo.berkeley.edu 128.32.131.66 mariner ucbmariner mariner.berkeley.edu 128.32.131.67 voyager ucbvoyager voyager.berkeley.edu 128.32.131.68 pioneer ucbpioneer pioneer.berkeley.edu 128.32.131.69 calder-xcs ucbcalder-xcs calder-xcs.berkeley.edu 128.32.131.70 challenger ucbchallenger challenger.berkeley.edu 128.32.131.71 discovery ucbdiscovery discovery.berkeley.edu 128.32.131.72 columbia ucbcolumbia columbia.berkeley.edu 128.32.131.73 enterprise ucbenterprise enterprise.berkeley.edu 128.32.131.74 atlantis ucbatlantis atlantis.berkeley.edu 128.32.131.75 explorer ucbexplorer explorer.berkeley.edu 128.32.131.76 ranger ucbranger ranger.berkeley.edu 128.32.131.78 mahogany ucbmahogany mahogany.berkeley.edu 128.32.131.79 elm ucbelm elm.berkeley.edu 128.32.131.80 oak ucboak oak.berkeley.edu 128.32.131.81 walnut ucbwalnut walnut.berkeley.edu 128.32.131.82 redwood ucbredwood redwood.berkeley.edu 128.32.131.83 liveoak ucbliveoak liveoak.berkeley.edu 128.32.131.84 larch ucblarch larch.berkeley.edu 128.32.131.85 maple ucbmaple maple.berkeley.edu 128.32.131.86 baobab ucbbaobab baobab.berkeley.edu 128.32.131.87 primrose ucbprimrose primrose.berkeley.edu 128.32.131.88 poppy ucbpoppy poppy.berkeley.edu 128.32.131.89 lupine ucblupine lupine.berkeley.edu 128.32.131.90 fuchsia ucbfuchsia fuchsia.berkeley.edu 128.32.131.91 freesia ucbfreesia freesia.berkeley.edu 128.32.131.92 lilly ucblilly lilly.berkeley.edu 128.32.131.93 orchid ucborchid orchid.berkeley.edu 128.32.131.94 bromeliad ucbbromeliad bromeliad.berkeley.edu 128.32.131.95 snapdragon ucbsnapdragon snapdragon.berkeley.edu 128.32.131.99 wisteria ucbwisteria wisteria.berkeley.edu 128.32.131.100 fezzik ucbfezzik fezzik.berkeley.edu 128.32.131.101 marigold ucbmarigold marigold.berkeley.edu 128.32.131.102 sunflower ucbsunflower sunflower.berkeley.edu 128.32.131.103 columbine ucbcolumbine columbine.berkeley.edu 128.32.131.104 ginko ucbginko ginko.berkeley.edu 128.32.131.105 geranium ucbgeranium geranium.berkeley.edu 128.32.131.106 copihue ucbcopihue copihue.berkeley.edu 128.32.131.107 daisy ucbdaisy daisy.berkeley.edu 128.32.131.108 dandelion ucbdandelion dandelion.berkeley.edu 128.32.131.109 lotus ucblotus lotus.berkeley.edu 128.32.131.110 mimosa ucbmimosa mimosa.berkeley.edu 128.32.131.111 genziana ucbgenziana genziana.berkeley.edu 128.32.131.114 mum ucbmum ucbchrysanthemum chrysanthemum mum.berkeley.edu 128.32.131.115 pawlonia ucbpawlonia pawlonia.berkeley.edu 128.32.131.116 sequoia ucbsequoia sequoia.berkeley.edu 128.32.131.117 lassen ucblassen lassen.berkeley.edu 128.32.131.118 ibmpc ibmpc.berkeley.edu 128.32.131.119 leeb leeb.berkeley.edu 128.32.131.120 shangri-la ucbshangri-la shangri-la.berkeley.edu 128.32.131.121 lewis ucblewis lewis.berkeley.edu 128.32.131.122 clark ucbclark clark.berkeley.edu 128.32.131.123 yaakov ucbyaakov yaakov.berkeley.edu 128.32.131.124 julia ucbjulia julia.berkeley.edu 128.32.131.125 plato ucbplato plato.berkeley.edu 128.32.131.126 mustapha ucbmustapha mustapha.berkeley.edu 128.32.131.127 warthog ucbwarthog warthog.berkeley.edu 128.32.131.128 bison ucbbison bison.berkeley.edu 128.32.131.129 dikdik ucbdikdik dikdik.berkeley.edu 128.32.131.130 aristotle ucbaristotle aristotle.berkeley.edu # # Berkeley Subnet 132 -- CAD 10Mb/s Ethernet # 128.32.132.1 ic ucbic ic.berkeley.edu 128.32.132.2 icw ucbicw icw.berkeley.edu 128.32.132.3 cad-ec ucbcad-ec cad-ec.berkeley.edu 128.32.132.4 sim ucbsim sim.berkeley.edu 128.32.132.5 eros ucberos eros.berkeley.edu 128.32.132.6 hyper ucbhyper hyper.berkeley.edu 128.32.132.8 dent ucbdent arthur dent.berkeley.edu 128.32.132.9 prefect ucbprefect ford prefect.berkeley.edu 128.32.132.10 decadence ucbdecadence decadence.berkeley.edu 128.32.132.11 samantha ucbsamantha fox samantha.berkeley.edu 128.32.132.12 veronica ucbveronica hart veronica.berkeley.edu 128.32.132.13 kelly ucbkelly nichols kelly.berkeley.edu 128.32.132.14 beeblebrox ucbbeeblebrox zaphod zap beeblebrox.berkeley.edu 128.32.132.15 bfly ucbfly bfly.berkeley.edu 128.32.132.16 squish ucbsquish squish.berkeley.edu 128.32.132.17 twolf ucbtwolf twolf.berkeley.edu 128.32.132.18 washoe ucbwashoe washoe.berkeley.edu 128.32.132.19 rich ucbrich rich.berkeley.edu 128.32.132.20 scruff scruff.berkeley.edu scruffy 128.32.132.21 alberto ucbalberto alberto.berkeley.edu 128.32.132.22 trillian ucbtrillian trillian.berkeley.edu 128.32.132.23 genie ucbgenie genie.berkeley.edu 128.32.132.24 zero ucbzero zero.berkeley.edu 128.32.132.25 bunny ucbunny bunny.berkeley.edu 128.32.132.26 athos ucbathos athos.berkeley.edu 128.32.132.27 porthos ucbporthos porthos.berkeley.edu 128.32.132.28 aramis ucbaramis aramis.berkeley.edu 128.32.132.29 dartagnan ucbdartagnan dart ucbdart dartagnan.berkeley.edu 128.32.132.30 nat ucbnat nat.berkeley.edu 128.32.132.31 dont_panic panic dont dont_panic.berkeley.edu 128.32.132.32 hopper hopper.berkeley.edu 128.32.132.33 fourier ucbfourier fourier.berkeley.edu 128.32.132.34 marilyn chambers marilyn.berkeley.edu 128.32.132.35 deep thought the-ultimate-machine deep.berkeley.edu 128.32.132.36 canova canova.berkeley.edu 128.32.132.37 fjord ucbfjord slarti slartibartfast fjord.berkeley.edu 128.32.132.38 baloss baloss.berkeley.edu 128.32.132.39 logos logos.berkeley.edu 128.32.132.40 hogan hogan.berkeley.edu 128.32.132.41 pavepaws pavepaws.berkeley.edu 128.32.132.42 sequent sequent.berkeley.edu 128.32.132.43 woozle wooz woozle.berkeley.edu 128.32.132.44 moose moose.berkeley.edu 128.32.132.45 elk elk.berkeley.edu 128.32.132.46 vectra vectra.berkeley.edu 128.32.132.47 squirrel squirrel.berkeley.edu 128.32.132.49 caliban caliban.berkeley.edu 128.32.132.54 shambhala shambhala.berkeley.edu 128.32.132.55 susie susie.berkeley.edu 128.32.132.56 pacific pacific.berkeley.edu 128.32.132.57 curry curry.berkeley.edu 128.32.132.58 dankoon dankoon.berkeley.edu 128.32.132.59 peking peking.berkeley.edu 128.32.132.60 surf surf.berkeley.edu 128.32.132.61 v572 v572.berkeley.edu 128.32.132.122 sonja ucbsonja sonja.berkeley.edu 128.32.132.123 vogon ucbvogon vogon.berkeley.edu 128.32.132.131 mv1 ucbmv1 mv1.berkeley.edu 128.32.132.132 mv2 ucbmv2 mv2.berkeley.edu # # Berkeley Subnet 133 -- 484 Cory # 128.32.133.2 esvax-133 ucbesvax-133 esvax-133.berkeley.edu 128.32.133.3 medea-ec ucbmedea-ec medea-ec.berkeley.edu 128.32.133.4 merlin ucbmerlin merlin.berkeley.edu 128.32.133.5 oz ucboz oz.berkeley.edu 128.32.133.6 davinci ucbdavinci davinci.berkeley.edu 128.32.133.7 zeus ucbzeus ucbzeus-133 zeus-133 zeus.berkeley.edu 128.32.133.8 jason ucbjason jason.berkeley.edu 128.32.133.9 zworykin ucbzworykin zworykin.berkeley.edu 128.32.133.25 ingres-ec ucbingres-ec ingres-ec.berkeley.edu 128.32.133.26 iiris ucbiiris iiris.berkeley.edu # # Berkeley Subnet 134 -- EECS Administration # 128.32.134.1 shadow ucbshadow shadowvax shadow.berkeley.edu 128.32.134.2 ear ucbear ear.berkeley.edu 128.32.134.3 east ucbeast east.berkeley.edu 128.32.134.4 silvia ucbsilvia sylvia silvia.berkeley.edu 128.32.134.5 dean ucbdean dean.berkeley.edu 128.32.134.6 cory-il ucbcory-il cory-il.berkeley.edu 128.32.134.7 zooey ucbzooey zooey.berkeley.edu 128.32.134.8 seymour ucbseymour seymour.berkeley.edu 128.32.134.9 holden ucbholden holden.berkeley.edu 128.32.134.10 buddy ucbbuddy buddy.berkeley.edu 128.32.134.11 franny ucbfranny franny.berkeley.edu 128.32.134.12 morgan ucbmorgan morgan.berkeley.edu 128.32.134.13 fern ucbfern fern.berkeley.edu 128.32.134.14 carol ucbcarol carol.berkeley.edu 128.32.134.15 dorothy ucbdorothy dorothy.berkeley.edu 128.32.134.16 ernie-il1 ucbernie-il1 ernie-il1.berkeley.edu 128.32.134.17 caliban caliban.berkeley.edu # # Berkeley Subnet 135 -- Math/Stat # 128.32.135.1 bach ucbbach ucbstatvax statvax bach.berkeley.edu 128.32.135.3 bizet ucbbizet bizet.berkeley.edu 128.32.135.4 brahms ucbbrahms ucbmathstat mathstat brahms.berkeley.edu 128.32.135.5 cartan-ec ucbcartan-ec cartan-ec.berkeley.edu 128.32.135.6 weyl ucbweyl weyl.berkeley.edu 128.32.135.7 setosa ucbsetosa setosa.berkeley.edu 128.32.135.9 dvorak ucbdvorak dv dvorak.berkeley.edu 128.32.135.10 crow ucbcrow crow.berkeley.edu 128.32.135.11 glinda ucbglinda glinda.berkeley.edu 128.32.135.12 lion ucblion lion.berkeley.edu 128.32.135.13 tinman ucbtinman tinman.berkeley.edu 128.32.135.14 toto ucbtoto toto.berkeley.edu 128.32.135.15 witch ucbwitch witch.berkeley.edu 128.32.135.16 wizard ucbwizard wizard.berkeley.edu 128.32.135.17 badger ucbbadger badger.berkeley.edu 128.32.135.18 mole ucbmole mole.berkeley.edu 128.32.135.19 toad ucbtoad toad.berkeley.edu # # Berkeley Subnet 136 -- Computer Center 10Mb/s Ethernet # 128.32.136.01 agate ucbagate Agate agate.berkeley.edu 128.32.136.02 amber ucbamber Amber amber.berkeley.edu 128.32.136.03 beryl ucbberyl Beryl beryl.berkeley.edu 128.32.136.04 cmsa ucbcmsa Cmsa cmsa.berkeley.edu 128.32.136.05 coral ucbcoral Coral coral.berkeley.edu 128.32.136.06 garnet ucbgarnet Garnet garnet.berkeley.edu 128.32.136.07 iris ucbiris Iris iris.berkeley.edu 128.32.136.08 ivory ucbivory Ivory ivory.berkeley.edu 128.32.136.09 jade ucbjade Jade jade.berkeley.edu 128.32.136.10 jasper ucbjasper Jasper jasper.berkeley.edu 128.32.136.11 lapis ucblapis Lapis lapis.berkeley.edu 128.32.136.12 lilac ucblilac Lilac lilac.berkeley.edu 128.32.136.13 opal ucbopal Opal opal.berkeley.edu 128.32.136.14 pearl ucbpearl Pearl pearl.berkeley.edu 128.32.136.15 populi ucbpopuli Populi populi.berkeley.edu 128.32.136.16 rose ucbrose Rose rose.berkeley.edu 128.32.136.17 ruby ucbruby Ruby ruby.berkeley.edu 128.32.136.18 topaz ucbtopaz Topaz topaz.berkeley.edu 128.32.136.19 tulip ucbtulip Tulip tulip.berkeley.edu 128.32.136.20 zircon ucbzircon Zircon zircon.berkeley.edu 128.32.136.22 violet ucbviolet Violet violet.berkeley.edu # # Berkeley Subnet 137 -- 10MB ucb-spine # 128.32.137.1 cory ucbcory cory.berkeley.edu 128.32.137.2 esvax ucbesvax esvax.berkeley.edu 128.32.137.3 ucbvax-spine ucbvax-il ucbvax-spine.berkeley.edu 128.32.137.4 cartan ucbcartan cartan.berkeley.edu 128.32.137.5 eros-de1 ucberos-de1 eros-de1.berkeley.edu 128.32.137.6 medea ucbmedea medea.berkeley.edu 128.32.137.7 cad ucbcad cad.berkeley.edu 128.32.137.8 ucbarpa-spine arpa-spine ucbarpa-spine.berkeley.edu 128.32.137.11 jade-il1 ucbjade-il1 jade-il1.berkeley.edu 128.32.137.13 ernie ucbernie ernie.berkeley.edu # # Berkeley Subnet 138 -- Ucf-net # 128.32.138.1 bugs ucbugs ucbbugs ugs bugs.berkeley.edu 128.32.138.2 miro-itt ucbmiro-itt miro-itt.berkeley.edu # # Berkeley Subnet 139 -- Suns on 3rd/4th floors Cory # 128.32.139.2 zeus ucbzeus ucbzeus-139 zeus-139 zeus.berkeley.edu 128.32.139.3 image ucbimage image.berkeley.edu 128.32.139.4 robert ucbrobert robert.berkeley.edu 128.32.139.5 bass ucbbass bass.berkeley.edu 128.32.139.6 bob ucbbob bob.berkeley.edu 128.32.139.7 jan ucbjan jan.berkeley.edu 128.32.139.8 bud ucbbud bud.berkeley.edu 128.32.139.9 heine ucbheine heine.berkeley.edu 128.32.139.10 corona ucbcorona corona.berkeley.edu 128.32.139.11 molson ucbmolson molson.berkeley.edu 128.32.139.12 dab ucbdab dab.berkeley.edu 128.32.139.13 tuborg ucbtuborg tuborg.berkeley.edu 128.32.139.14 asahi ucbasahi asahi.berkeley.edu 128.32.139.15 suntory ucbsuntory suntory.berkeley.edu 128.32.139.50 coors ucbcoors coors.berkeley.edu # # Point-Point links - Subnet 140 # 128.32.140.1 cgl-dmc ucsf-dmc cgl-dmc.berkeley.edu 128.32.140.2 ucbarpa-dmc arpa-dmc ucb-dmc ucbarpa-dmc.berkeley.edu 128.32.140.3 ucbvax-dmc ucbvax-dmc.berkeley.edu 128.32.140.4 cartan-dmc ucbcartan-dmc cartan-dmc.berkeley.edu # # Berkeley Subnet 141 -- Engineering building interconnect 10Mb/s Ethernet # 128.32.141.1 jade-eng ucbjade-eng jade-eng.berkeley.edu # cevax is not yet on its own net (manager dls@cevax David L. Steere) 128.32.141.2 cevax ucbcevax cevax.berkeley.edu 128.32.141.3 etch-gw ucbetch-gw etch-gw.berkeley.edu 128.32.141.4 etch-gw2 ucbetch-gw2 etch-gw2.berkeley.edu # # Berkeley Subnet 142 -- Etcheverry Hall 10Mb/s Ethernet # 128.32.142.1 euler ucbeuler euler.berkeley.edu 128.32.142.2 newton ucbnewton newton.berkeley.edu 128.32.142.3 kepler ucbkepler kepler.berkeley.edu 128.32.142.5 maxwell ucbmaxwell maxwell.berkeley.edu 128.32.142.6 joule ucbjoule joule.berkeley.edu 128.32.142.7 mistletoe ucbmistletoe mistletoe.berkeley.edu 128.32.142.25 mote ucbmote mote.berkeley.edu # # # Berkeley Subnet 143 -- Davis Hall 10Mb/s Ethernet # #128.32.143.1 cevax ucbcevax (not yet) # # Berkeley Subnet 144 (128.32.144.0) -- Latimer Hall Ethernet # Berkeley Subnet 145 (128.32.145.0) -- Richmond Field Station Ethernet # Berkeley Subnet 146 (128.32.146.0) -- Earth Sciences Bldg. Ethernet # Berkeley Subnet 147 (128.32.147.0) -- Internal Development, IBM VM subnet # # Berkeley Subnet 148 (128.32.148.0) -- Etcheverry Hall Subnet Ethernet 128.32.148.1 element-gw ucbelement-gw element-gw.berkeley.edu 128.32.148.2 hydrogen ucbhydrogen hydrogen.berkeley.edu 128.32.148.3 helium ucbhelium helium.berkeley.edu 128.32.148.4 lithium ucblithium lithium.berkeley.edu 128.32.148.5 beryllium ucbberyllium beryllium.berkeley.edu 128.32.148.6 boron ucbboron boron.berkeley.edu 128.32.148.7 carbon ucbcarbon carbon.berkeley.edu 128.32.148.8 nitrogen ucbnitrogen nitrogen.berkeley.edu 128.32.148.9 oxygen ucboxygen oxygen.berkeley.edu 128.32.148.10 fluorine ucbfluorine fluorine.berkeley.edu 128.32.148.11 neon ucbneon neon.berkeley.edu 128.32.148.12 sodium ucbsodium sodium.berkeley.edu 128.32.148.13 magnesium ucbmagnesium magnesium.berkeley.edu 128.32.148.14 aluminum ucbaluminum aluminum.berkeley.edu 128.32.148.15 silicon ucbsilicon silicon.berkeley.edu 128.32.148.16 phosphorus ucbphosphorus phosphorus.berkeley.edu 128.32.148.17 sulfur ucbsulfur sulfur.berkeley.edu # # Berkeley Subnet 150 -- 10MB/s spur's sun-network # 128.32.150.1 envy-150 envy ucbenvy-150 envy.berkeley.edu envy-150.berkeley.edu 128.32.150.2 clove ucbclove clove.berkeley.edu 128.32.150.3 salt ucbsalt salt.berkeley.edu 128.32.150.4 saffron ucbsaffron saffron.berkeley.edu 128.32.150.5 garlic ucbgarlic garlic.berkeley.edu 128.32.150.6 sage ucbsage sage.berkeley.edu 128.32.150.7 nutmeg ucbnutmeg nutmeg.berkeley.edu 128.32.150.8 paprika ucbpaprika paprika.berkeley.edu 128.32.150.9 murder ucbmurder murder.berkeley.edu 128.32.150.10 earth ucbearth earth.berkeley.edu 128.32.150.11 lust ucblust lust.berkeley.edu 128.32.150.12 lust20 ucblust20 lust20.berkeley.edu 128.32.150.13 pride ucbpride pride.berkeley.edu 128.32.150.14 sloth ucbsloth sloth.berkeley.edu 128.32.150.15 dill ucbdill dill.berkeley.edu 128.32.150.16 basil ucbbasil basil.berkeley.edu 128.32.150.17 thyme ucbthyme thyme.berkeley.edu 128.32.150.18 bay ucbbay bay.berkeley.edu 128.32.150.19 parsley ucbparsley parsley.berkeley.edu 128.32.150.20 pepper ucbpepper pepper.berkeley.edu 128.32.150.21 anger ucbanger anger.berkeley.edu 128.32.150.22 greed ucbgreed greed.berkeley.edu 128.32.150.25 cayenne ucbcayenne cayenne.berkeley.edu 128.32.150.26 chilli ucbchilli chilli.berkeley.edu 128.32.150.27 allspice ucballspice allspice.berkeley.edu 128.32.150.28 ginger ucbginger ginger.berkeley.edu 128.32.150.29 oregano ucboregano oregano.berkeley.edu 128.32.150.30 rosemary ucbrosemary rosemary.berkeley.edu 128.32.150.31 fennel ucbfennel fennel.berkeley.edu 128.32.150.32 cinnamon ucbcinnamon cinnamon.berkeley.edu 128.32.150.33 tarragon ucbtarragon tarragon.berkeley.edu 128.32.150.34 anise ucbanise anise.berkeley.edu 128.32.150.35 coriander ucbcoriander coriander.berkeley.edu 128.32.150.37 tumeric ucbtumeric tumeric.berkeley.edu 128.32.150.38 mustard ucbmustard mustard.berkeley.edu 128.32.150.39 cardamom ucbcardamom cardamom.berkeley.edu 128.32.150.40 sarsaparilla ucbsarsaparilla sarsaparilla.berkeley.edu 128.32.150.41 sassafrass ucbsassafrass sassafrass.berkeley.edu 128.32.150.42 hecuba ucbhecuba hecuba.berkeley.edu 128.32.150.43 priam ucbpriam priam.berkeley.edu 128.32.150.44 tully ucbtully tully.berkeley.edu 128.32.150.45 helen ucbhelen helen.berkeley.edu 128.32.150.46 paris ucbparis paris.berkeley.edu 128.32.150.47 menelaus ucbmenelaus menelaus.berkeley.edu 128.32.150.48 odysseus ucbodysseus odysseus.berkeley.edu 128.32.150.49 agamemnon ucbagamemnon agamemnon.berkeley.edu 128.32.150.50 homer ucbhomer homer.berkeley.edu 128.32.150.51 cumin ucbcumin cumin.berkeley.edu 128.32.150.52 mint ucbmint mint.berkeley.edu 128.32.150.53 marjoram ucbmarjoram marjoram.berkeley.edu 128.32.150.54 mace ucbmace mace.berkeley.edu 128.32.150.55 fenugreek ucbfenugreek fenugreek.berkeley.edu 128.32.150.56 savory ucbsavory savory.berkeley.edu 128.32.150.57 caraway ucbcaraway caraway.berkeley.edu 128.32.150.58 shallot ucbshallot shallot.berkeley.edu 128.32.150.59 borage ucbborage borage.berkeley.edu # # Subnet 151 Evans Hall public workstations # # Subnet 152 Computer center staff workstations 128.32.152.10 jade-il3 ucbjade-il3 128.32.152.01 heart ucbheart heart.berkeley.edu # Jane Wolff 128.32.152.02 biko ucbiko biko.berkeley.edu # Steve Jacobson 128.32.152.03 quark ucbquark quark.berkeley.edu # Ed Moy 128.32.152.04 rkneff1 ucbrkneff1 rkneff1.berkeley.edu # Ray Neff 128.32.152.05 rkneff2 ucbrkneff2 rkneff2.berkeley.edu # Ray Neff 128.32.152.06 misc ucbmisc misc.berkeley.edu # Greg Minshall 128.32.152.07 grendel ucbgrendel grendel.berkeley.edu # Ken Lindahl 128.32.152.08 temp ucbtemp temp.berkeley.edu # place holder for test 128.32.152.09 tern ucbtern tern.berkeley.edu # Bob Campbell 128.32.152.11 eris ucberis eris.berkeley.edu # Mike Meyer 128.32.152.42 io ucbio io.berkeley.edu # David Wasley 128.32.152.58 ripple ucbripple ripple.berkeley.edu # Jordan Hubbard # # Subnet 153 DLA interconnect link # # Subnet 154 DLA network # # Subnet 155 Suns in Bechtel library # # Berkeley Subnet 156 -- Cory "others" catchall net # 128.32.156.02 zworykin-156 ucbzworykin-156 zworykin-156.berkeley.edu 128.32.156.03 nyquist ucbnyquist nyquist.berkeley.edu 128.32.156.04 marconi ucbmarconi marconi.berkeley.edu 128.32.156.05 edison ucbedison edison.berkeley.edu 128.32.156.06 deforest ucbdeforest deforest.berkeley.edu 128.32.156.07 armstrong ucbarmstrong armstrong.berkeley.edu 128.32.156.08 bell ucbbell bell.berkeley.edu 128.32.156.09 shannon ucbshannon shannon.berkeley.edu 128.32.156.10 franklin ucbfranklin franklin.berkeley.edu 128.32.156.12 tesla ucbtesla tesla.berkeley.edu 128.32.156.13 hodges ucbhodges hodges.berkeley.edu 128.32.156.14 light ucblight light.berkeley.edu 128.32.156.23 kuhimagen ucbkuhimagen kuhimagen.berkeley.edu 128.32.156.40 kuhn ucbkuhn kuhn.berkeley.edu 128.32.156.41 tucker ucbtucker tucker.berkeley.edu 128.32.156.50 huffman ucbhuffman huffman.berkeley.edu 128.32.156.51 sesame ucbsesame sesame.berkeley.edu 128.32.156.52 booze ucbbooze booze.berkeley.edu 128.32.156.53 gin ucbgin gin.berkeley.edu 128.32.156.54 tequila ucbtequila tequila.berkeley.edu 128.32.156.55 layout ucblayout layout.berkeley.edu 128.32.156.56 lagrange ucblagrange lagrange.berkeley.edu 128.32.156.57 mouton ucbmouton mouton.berkeley.edu 128.32.156.58 latour ucblatour latour.berkeley.edu 128.32.156.59 lambert ucblambert lambert.berkeley.edu 128.32.156.60 em em.berkeley.edu # # Subnet 157 Cory Others-Net? # # Berkeley Class A Private Net -- 3Mb/s Ethernet # 126.1 matisse-a ucbmatisse-a 126.2 calder-a ucbcalder-a 126.3 monet-a ucbmonet-a # # Berkeley Class C Private Net -- 3Mb/s Ethernet # 192.0.46.1 matisse-c ucbmatisse-c 192.0.46.2 calder-c ucbcalder-c 192.0.46.3 monet-c ucbmonet-c 192.0.46.4 okeeffe-c ucbokeeffe-c 192.0.46.5 vangogh-c ucbvangogh-c # # UCSF Class C net # 192.5.49.1 ucsfcgl cgl ucsf-cgl 192.5.49.2 ucsfigv igv 192.5.49.3 ucsfmeta meta ucsf-meta fuzzy 192.5.49.4 cgliris 192.5.49.10 ucsfmis mis 192.5.49.11 ucsfbcl bcl 192.5.49.12 ucsfcca cca ucsfvaxa vaxa 192.5.49.13 ucsfccb ccb 192.5.49.14 ucsfmsg msg 192.5.49.15 bcliris 192.5.49.16 ucsfnmr nmr 192.5.49.17 ucsfvivo vivo nmrvivo # # DECWRL # 128.45.0.241 decwrl-dmc # Off Campus Hosts and Networks (from SRI-NIC hostname server) # 36.10.0.171 su-playfair.arpa su-playfair playfair 128.39.1.2 tor nta-vax # ucbesvax esvax.berkeley.edu 128.32.137.3 ucbvax-spine ucbvax-il ucbvax-spine.berkeley.edu 128.32.137.4 cartan ucbcartan cartaetc/htable/localgateways 440 0 12 470 4015515257 10603 # # Local gateways, not known in hosts.txt # (or reordered to force one of multiple choices) # net sons-net gateway ucbkim metric 1 passive net xcs-net gateway ucbdali metric 1 passive net milnet gateway milsac metric 1 passive net ipto-net gateway ipto-gw metric 1 passive # # Gateways from NIC hosts file # etc/htable/localhosts 440 0 12 7257 4015515257 10151 # # Berkeley Host Database # 127.1 localhost # # Berkeley Local Net 128.32 -- 3Mb/s Ethernet # 128.32.4 ucbarpa arpa 128.32.5 ucbcad cad 128.32.6 ucbernie ernie 128.32.7 ucbmonet monet 128.32.9 ucbesvax esvax 128.32.10 ucbvax ucbvax vax 128.32.11 ucbkim kim 128.32.12 ucbcalder calder 128.32.13 ucbdali dali 128.32.14 ucbmatisse matisse 128.32.15 ucbmedea medea 128.32.19 ucbingres ingres 128.32.20 ucboz-en oz-en #128.32.21 ucbear ear 128.32.22 ucbdegas degas #128.32.23 ucbturner turner 128.32.24 ucbmiro miro 128.32.25 ucbjade jade #128.32.26 ucbbach bach ucbstatvax statvax #128.32.27 ucbic ic 128.32.28 ucbcory cory 128.32.29 ucbcartan cartan #128.32.30 ucbbrahms brahms ucbmathstat mathstat 128.32.31 ucbrenoir renoir 128.32.32 ucbshadow shadow shadowvax # # Berkeley Local Net 99 -- Ungermann-Bass # 99.2.0.93 ucbmatisse-un matisse-un 99.2.0.86 ucbdali-un dali-un # # Berkeley Local Net 98 -- 3Com 10Mb/s Ethernet # 98.0.2.80 ucbmatisse-ec matisse-ec 98.0.2.67 ucbmonet-ec monet-ec 98.0.0.3 ucbcalder-ec calder-ec # # Berkeley Local Net 97 -- Interlan 10Mb/s Ethernet # 97.128.1.69 ucbmonet-il monet-il 97.128.1.65 ucbmatisse-il matisse-il 97.0.0.3 ucbcalder-il calder-il # # Berkeley Local Net 96 -- CAD 10Mb/s Ethernet # 96.0.5.128 ucbic ic 96.0.5.129 ucbicw icw 96.0.5.130 ucbcad-ec cad-ec 96.128.9.25 ucbunny bunny 96.128.10.122 ucbsonja sonja # # Berkeley Local Net 95 -- 484 Cory # 95.0.83.0 ucbbob bob 95.0.98.116 ucbjan jan 95.0.7.71 ucbmedea-ec medea-ec 95.0.7.70 ucbmerlin merlin 95.0.22.41 ucboz oz 95.0.71.152 ucbzeus zeus # # Berkeley Local Net 94 -- EECS Administration # 94.0.0.1 ucbshadow-de shadow-de shadowvax-de 94.0.0.2 ucbear ear 94.0.0.3 ucbeast east # # Berkeley Local Net 90 (Math/Stat) 90.0.87.148 ucbbach bach ucbstatvax statvax 128.32.26 ucbbizet bizet #90.0.39.117 ucbbizet bizet 90.0.87.153 ucbbrahms brahms ucbmathstat mathstat 90.1.35.5 ucbcartan-ec cartan-ec 90.1.35.9 ucbweyl weyl # # Berkeley Class C Local Net 1 -- 3Mb/s Ethernet # 192.0.46.1 ucbmatisse-en2 matisse-en2 192.0.46.2 ucbcalder-en2 calder-en2 192.0.46.3 ucbmonet-en2 monet-en2 # # Berkeley Local Net 125 -- SUN 10Mb/s Ethernet # 125.0.20.137 ucbmike mike 125.0.17.146 ucbrob rob 125.0.20.71 ucbchip chip 125.0.71.3 ucbdim dim 125.16688 ucbstun stun 125.0.2.67 ucbkim-ec kim-ec 125.0.120.50 ucblust lust # XCS file server cluster 124.0.17.102 ucbxcssun xcssun 124.0.52.83 ucbearth earth 124.0.65.39 ucbpluto pluto 124.0.54.48 ucburanus uranus 124.0.20.40 ucbneptune neptune 124.0.24.113 ucbsaturn saturn 124.0.65.65 ucbjupiter jupiter 124.0.65.34 ucbmars mars 124.0.65.35 ucbvenus venus 124.0.41.64 ucbmercury mercury 124.0.39.130 ucbnet124 net124 124.0.65.10 ucbdisney disney 124.0.71.16 ucbsnow snow 124.0.82.65 ucbbashful bashful 124.0.82.149 ucbgrumpy grumpy 124.0.82.57 ucbsleepy sleepy 124.0.65.136 ucbdoc doc 124.0.65.150 ucbdopey dopey 124.0.65.129 ucbhappy happy 124.0.82.150 ucbsneezy sneezy 124.1.1.24 ucbphoenix phoenix 124.0.129.56 ucbenvy envy 124.0.118.132 ucbpride pride 124.0.96.80 ucbsloth sloth 124.0.120.50 ucbdesire desire # # Berkeley Local Net 89 -- Computer Center 10Mb/s Ethernet # 89.0.4.153 ucbruby ruby Ruby 89.0.4.21 ucbamber amber Amber 89.0.6.38 ucbcoral coral Coral 89.0.6.35 ucbtopaz topaz Topaz 89.0.6.36 ucbopal opal Opal 89.0.6.37 ucbivory ivory Ivory 89.0.4.119 ucblapis lapis Lapis 89.0.6.33 ucbjade-ec jade-ec 89.0.4.85 ucbpopuli populi Populi 89.1.3.160 ucbagate agate Agate 89.1.3.204 ucbberyl beryl Beryl 89.1.11.82 ucbgarnet garnet Garnet 89.1.14.83 ucbjasper jasper Jasper 89.1.15.2 ucbpearl pearl Pearl 89.1.9.134 ucbzircon zircon Zircon # # Miscellaneous # 26.1.1.34 lbl-g 26.1.2.34 lbl-h 26.1.3.34 lbl-ws # # Off Campus Hosts and Networks (from SRI-NIC hostname server) # innamon ucbcinnamon cinnamon.berkeley.edu 128.32.150.33 tarragon ucbtarragon tarragon.berkeley.edu 128.32.150.34 anise ucbanise anise.berkeley.edu 128.32.150.35 coriander ucbcoriander coriander.berkeley.edu 128.32.150.37 tumeric ucbtumeric tumeric.berkeley.edu 128.32.150.38 mustard ucbmustard mustard.berkeley.edu 128.32.150.39 caetc/htable/localnetworks 440 0 12 767 4015515257 10644 # # Internet networks (reordered for local efficiency) # ucb-ether 128.32 berkeley ucb ucb-localnet old-ucb-ether 46 ub-net 99 ungermann-bass-network 3com-net 98 3com-network interlan-net 97 interlan-network cad-net 96 cad-network cory-net 95 cory-network eecs-net 94 eecs-admin-network ucb-ether2 192.0.46 ucbether2 ether2 ms-net 90 ms-network math-stat-net cc-net 89 cc-network comp-center-net sons-net 125 three-suns-network xcs-net 124 xcsnet loopback-net 127 software-loopback-net etc/timed/ 750 0 12 0 6024536074 5621 etc/timed/vax/ 770 0 12 0 3543615003 6412 etc/timed/vax/cksum.c 440 0 12 2440 3543603425 7767 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)cksum.c 1.2 (Berkeley) 9/18/85"; #endif not lint #include #define ADD asm("adwc (r9)+,r8;"); /* computes the checksum for ip packets for the VAX */ in_cksum(addr, len) u_short *addr; int len; { register int nleft = len; /* on vax, (user mode), r11 */ #ifndef lint register int xxx; /* on vax, (user mode), r10 */ #endif not lint register u_short *w = addr; /* on vax, known to be r9 */ register int sum = 0; /* on vax, known to be r8 */ if (((int)w&0x2) && nleft >= 2) { sum += *w++; nleft -= 2; } while ((nleft -= 32) >= 0) { asm("clrl r0"); /* clears carry */ ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD; asm("adwc $0,r8"); } nleft += 32; while ((nleft -= 8) >= 0) { asm("clrl r0"); ADD; ADD; asm("adwc $0,r8"); } nleft += 8; { asm("ashl $-16,r8,r0; addw2 r0,r8"); asm("adwc $0,r8; movzwl r8,r8"); } while ((nleft -= 2) >= 0) { asm("movzwl (r9)+,r0; addl2 r0,r8"); } if (nleft == -1) { sum += *(u_char *)w; } { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8"); asm("mcoml r8,r8; movzwl r8,r8"); } return (sum); } 117 ucbbizet bizet 90.0.87.153 ucbbrahms brahms ucbmathstat mathstat 90.1.35.5 ucbcartan-ec cartan-ec 90.1.35.9 ucbweyl weyl # # Berkeley Class C Local Net 1 -- 3Mb/s Ethernet # 192.0.46.1 ucbmatisse-en2 matisse-en2 192.0etc/timed/m68000/ 770 0 12 0 3503621343 6446 etc/timed/m68000/ocsum.s 440 0 12 2241 3503621330 10035 .data .asciz "@(#)ocsum.s 4.4 83/08/16 Copyr 1983 Sun Micro" .even .text | Copyright (c) 1983 by Sun Microsystems, Inc. | Do a 16 bit one's complement sum of a given number of words | The word pointer may not be odd .globl _ocsum _ocsum: movl sp@(4),a0 | get ptr movl sp@(8),d0 | get word count movl d2,sp@- | save a reg movl d0,d2 | save the count lsrl #1,d0 | make d0 longs movl #0,d1 | zero accumulator jra 1$ | into loop | Here we run in 68010 loop mode until we get a carry 2$: addl a0@+,d1 | add in long 1$: dbcs d0,2$ | continue until carry or done jcc 3$ | if no carry, we're done addql #1,d1 | add in carry jra 1$ | and go back to test for carry again 3$: btst #0,d2 | another short? jeq ret | no, go away movl #0,d0 | must do unsigned add movw a0@,d0 | get the short addl d0,d1 | add it in jcc ret addql #1,d1 | Now add in high word to low word as above ret: movl d1,d0 lsrl #8,d0 | get high word in d0 lsrl #8,d0 | and clear high do as well andl #0xFFFF,d1 | clear high d1 addw d1,d0 | add in just the low word movl #0,d1 | doesn't clear x bit addxw d1,d0 | add in final carry movl sp@+,d2 | restore reg rts | all done *(u_char *)w; } { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8"); asm("mcoml r8,r8; movzwl r8,r8"); } return (sum); } 117 ucbbizet bizet 90.0.87.153 ucbbrahms brahms ucbmathstat mathstat 90.1.35.5 ucbcartan-ec cartan-ec 90.1.35.9 ucbweyl weyl # # Berkeley Class C Local Net 1 -- 3Mb/s Ethernet # 192.0.46.1 ucbmatisse-en2 matisse-en2 192.0etc/timed/m68000/cksum.c 440 0 12 2025 3671724037 10027 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)cksum.c 2.1 (Berkeley) 6/6/86"; #endif not lint #include "../globals.h" #include /* computes the checksum for ip packets for a Motorola 68000 base computer */ in_cksum(w, mlen) register u_short *w; register int mlen; { register int sum = 0; if (mlen > 0) { if (((int)w & 1) == 0) { sum = ocsum(w, mlen>>1); w += mlen>>1; if (mlen & 1) { sum += *(u_char *)w << 8; mlen = -1; } } else { u_short swsum; sum = *(u_char *)w << 8; mlen--; w = (u_short *)(1 + (int)w); swsum = ocsum(w, mlen>>1); swab((char *)&swsum, (char *)&swsum, sizeof swsum); sum += swsum; w += mlen>>1; if (mlen & 1) sum += *(u_char *)w; } } sum = (sum & 0xFFFF) + (sum >> 16); sum = (sum & 0xFFFF) + (sum >> 16); sum = (~sum) & 0xFFFF; return (sum); } d in just the low word movl #0,d1 | doesn't clear x bit addxw d1,d0 | add in final carry movl sp@+,d2 | restore reg rts | all done *(u_char *)w; } { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8"); asm("mcoml r8,r8; movzwl r8,r8"); } return (sum); } 117 ucbbizet bizet 90.0.87.153 ucbbrahms brahms ucbmathstat mathstat 90.1.35.5 ucbcartan-ec cartan-ec 90.1.35.9 ucbweyl weyl # # Berkeley Class C Local Net 1 -- 3Mb/s Ethernet # 192.0.46.1 ucbmatisse-en2 matisse-en2 192.0etc/timed/Makefile 440 0 12 20053 4115662104 7356 # # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 2.1 (Berkeley) 12/10/85 # # optional flags are: MEASURE TESTING DEBUG CFLAGS= -O -DMEASURE SEPFLAG= -i DESTDIR= MACHINE= pdp LIBS= PROGRS= timed timedc SRCDS= acksend.c candidate.c correct.c \ master.c networkdelta.c readmsg.c slave.c timed.c OBJDS= acksend.o candidate.o correct.o \ master.o networkdelta.o readmsg.o slave.o timed.o SRCCS= cmds.c cmdtab.c timedc.c OBJCS= cmds.o cmdtab.o timedc.o COMMS= byteorder.c measure.c ${MACHINE}/cksum.c COMMO= byteorder.o measure.o cksum.o all: ${PROGRS} #cksum.o: # cc ${CFLAGS} -c ${MACHINE}/$*.c cksum.o: cc ${CFLAGS} -S ${MACHINE}/cksum.c ed - < ${MACHINE}/cksum-fix > /dev/null cksum.s as - -o $@ cksum.s rm -f cksum.s timed: ${OBJDS} ${COMMO} cc ${SEPFLAG} ${CFLAGS} ${OBJDS} ${COMMO} ${LIBS} -o timed timedc: ${OBJCS} ${COMMO} cc ${SEPFLAG} ${CFLAGS} ${OBJCS} ${COMMO} ${LIBS} -o timedc install: ${PROGRS} install -s timed ${DESTDIR}/etc install -s -o root -m 4511 timedc ${DESTDIR}/etc clean: rm -f a.out core *.o Makefile.bak errs ${PROGRS} lint: lint ${SRCDS} ${COMMS} lint ${SRCCS} ${COMMS} depend: for i in ${SRCCS} ${SRCDS} ${COMMS}; do \ cc -M ${CFLAGS} $$i | awk ' { if ($$1 != prev) \ { if (rec != "") print rec; rec = $$0; prev = $$1; } \ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ else rec = rec " " $$2 } } \ END { print rec } ' >> makedep; done echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep echo '$$r makedep' >>eddep echo 'w' >>eddep cp Makefile Makefile.bak ed - Makefile < eddep rm eddep makedep echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile echo '# see make depend above' >> Makefile # DO NOT DELETE THIS LINE -- make depend uses it cmds.o: cmds.c ./timedc.h /usr/include/sys/param.h cmds.o: /usr/include/machine/machparam.h /usr/include/signal.h cmds.o: /usr/include/sys/types.h /usr/include/stdio.h /usr/include/sys/time.h cmds.o: /usr/include/time.h /usr/include/errno.h /usr/include/sys/socket.h cmds.o: /usr/include/netinet/in.h /usr/include/netdb.h /usr/include/arpa/inet.h cmds.o: /usr/include/netinet/in_systm.h /usr/include/netinet/ip.h cmds.o: /usr/include/netinet/ip_icmp.h /usr/include/protocols/timed.h cmds.o: /usr/include/sys/file.h cmdtab.o: cmdtab.c ./timedc.h /usr/include/sys/param.h cmdtab.o: /usr/include/machine/machparam.h /usr/include/signal.h cmdtab.o: /usr/include/sys/types.h /usr/include/stdio.h /usr/include/sys/time.h cmdtab.o: /usr/include/time.h /usr/include/errno.h /usr/include/sys/socket.h cmdtab.o: /usr/include/netinet/in.h /usr/include/netdb.h cmdtab.o: /usr/include/arpa/inet.h timedc.o: timedc.c ./timedc.h /usr/include/sys/param.h timedc.o: /usr/include/machine/machparam.h /usr/include/signal.h timedc.o: /usr/include/sys/types.h /usr/include/stdio.h /usr/include/sys/time.h timedc.o: /usr/include/time.h /usr/include/errno.h /usr/include/sys/socket.h timedc.o: /usr/include/netinet/in.h /usr/include/netdb.h timedc.o: /usr/include/arpa/inet.h /usr/include/signal.h /usr/include/ctype.h timedc.o: /usr/include/setjmp.h /usr/include/syslog.h acksend.o: acksend.c ./globals.h /usr/include/sys/param.h acksend.o: /usr/include/machine/machparam.h /usr/include/signal.h acksend.o: /usr/include/sys/types.h /usr/include/stdio.h acksend.o: /usr/include/sys/time.h /usr/include/time.h /usr/include/errno.h acksend.o: /usr/include/syslog.h /usr/include/sys/socket.h acksend.o: /usr/include/netinet/in.h /usr/include/netdb.h acksend.o: /usr/include/arpa/inet.h /usr/include/protocols/timed.h candidate.o: candidate.c ./globals.h /usr/include/sys/param.h candidate.o: /usr/include/machine/machparam.h /usr/include/signal.h candidate.o: /usr/include/sys/types.h /usr/include/stdio.h candidate.o: /usr/include/sys/time.h /usr/include/time.h /usr/include/errno.h candidate.o: /usr/include/syslog.h /usr/include/sys/socket.h candidate.o: /usr/include/netinet/in.h /usr/include/netdb.h candidate.o: /usr/include/arpa/inet.h /usr/include/protocols/timed.h correct.o: correct.c ./globals.h /usr/include/sys/param.h correct.o: /usr/include/machine/machparam.h /usr/include/signal.h correct.o: /usr/include/sys/types.h /usr/include/stdio.h correct.o: /usr/include/sys/time.h /usr/include/time.h /usr/include/errno.h correct.o: /usr/include/syslog.h /usr/include/sys/socket.h correct.o: /usr/include/netinet/in.h /usr/include/netdb.h correct.o: /usr/include/arpa/inet.h /usr/include/protocols/timed.h master.o: master.c ./globals.h /usr/include/sys/param.h master.o: /usr/include/machine/machparam.h /usr/include/signal.h master.o: /usr/include/sys/types.h /usr/include/stdio.h /usr/include/sys/time.h master.o: /usr/include/time.h /usr/include/errno.h /usr/include/syslog.h master.o: /usr/include/sys/socket.h /usr/include/netinet/in.h master.o: /usr/include/netdb.h /usr/include/arpa/inet.h master.o: /usr/include/protocols/timed.h /usr/include/setjmp.h networkdelta.o: networkdelta.c ./globals.h /usr/include/sys/param.h networkdelta.o: /usr/include/machine/machparam.h /usr/include/signal.h networkdelta.o: /usr/include/sys/types.h /usr/include/stdio.h networkdelta.o: /usr/include/sys/time.h /usr/include/time.h networkdelta.o: /usr/include/errno.h /usr/include/syslog.h networkdelta.o: /usr/include/sys/socket.h /usr/include/netinet/in.h networkdelta.o: /usr/include/netdb.h /usr/include/arpa/inet.h networkdelta.o: /usr/include/protocols/timed.h readmsg.o: readmsg.c ./globals.h /usr/include/sys/param.h readmsg.o: /usr/include/machine/machparam.h /usr/include/signal.h readmsg.o: /usr/include/sys/types.h /usr/include/stdio.h readmsg.o: /usr/include/sys/time.h /usr/include/time.h /usr/include/errno.h readmsg.o: /usr/include/syslog.h /usr/include/sys/socket.h readmsg.o: /usr/include/netinet/in.h /usr/include/netdb.h readmsg.o: /usr/include/arpa/inet.h /usr/include/protocols/timed.h slave.o: slave.c ./globals.h /usr/include/sys/param.h slave.o: /usr/include/machine/machparam.h /usr/include/signal.h slave.o: /usr/include/sys/types.h /usr/include/stdio.h /usr/include/sys/time.h slave.o: /usr/include/time.h /usr/include/errno.h /usr/include/syslog.h slave.o: /usr/include/sys/socket.h /usr/include/netinet/in.h slave.o: /usr/include/netdb.h /usr/include/arpa/inet.h slave.o: /usr/include/protocols/timed.h /usr/include/setjmp.h timed.o: timed.c ./globals.h /usr/include/sys/param.h timed.o: /usr/include/machine/machparam.h /usr/include/signal.h timed.o: /usr/include/sys/types.h /usr/include/stdio.h /usr/include/sys/time.h timed.o: /usr/include/time.h /usr/include/errno.h /usr/include/syslog.h timed.o: /usr/include/sys/socket.h /usr/include/netinet/in.h timed.o: /usr/include/netdb.h /usr/include/arpa/inet.h timed.o: /usr/include/protocols/timed.h /usr/include/net/if.h timed.o: /usr/include/sys/file.h /usr/include/sys/ioctl.h timed.o: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h timed.o: /usr/include/setjmp.h byteorder.o: byteorder.c ./globals.h /usr/include/sys/param.h byteorder.o: /usr/include/machine/machparam.h /usr/include/signal.h byteorder.o: /usr/include/sys/types.h /usr/include/stdio.h byteorder.o: /usr/include/sys/time.h /usr/include/time.h /usr/include/errno.h byteorder.o: /usr/include/syslog.h /usr/include/sys/socket.h byteorder.o: /usr/include/netinet/in.h /usr/include/netdb.h byteorder.o: /usr/include/arpa/inet.h /usr/include/protocols/timed.h measure.o: measure.c ./globals.h /usr/include/sys/param.h measure.o: /usr/include/machine/machparam.h /usr/include/signal.h measure.o: /usr/include/sys/types.h /usr/include/stdio.h measure.o: /usr/include/sys/time.h /usr/include/time.h /usr/include/errno.h measure.o: /usr/include/syslog.h /usr/include/sys/socket.h measure.o: /usr/include/netinet/in.h /usr/include/netdb.h measure.o: /usr/include/arpa/inet.h /usr/include/protocols/timed.h measure.o: /usr/include/netinet/in_systm.h /usr/include/netinet/ip.h measure.o: /usr/include/netinet/ip_icmp.h cksum.o: vax/cksum.c /usr/include/sys/types.h # DEPENDENCIES MUST END AT END OF FILE # IF YOU PUT STUFF HERE IT WILL GO AWAY # see make depend above cmdtab.c timedc.c OBJCS= cmds.o cmdtab.o timedc.o COMMS= byteorder.c measure.c ${MACHINE}/cksum.c COMMO= byteorder.o measure.o cksum.o all: ${PROGRS} #cksum.o: # cc ${CFLAGS} -c ${MACHINE}/$*.c cksum.o: cc ${CFLAGS} -S ${MACHINE}/cksum.c ed - < ${MACHINE}/cksum-fix > /dev/null cksum.s as - -o $@ cksum.s rm -f cksum.s timed: ${OBJDS} ${COMMO} cc ${SEPFLAG} ${CFLAGS} ${OBJDS} ${COMMO} ${LIBS} -o timed timedc: ${OBJCS} ${COMMO} cc ${SEPFLAG} ${CFLAGS} etc/timed/acksend.c 440 0 12 3513 3666436034 7467 /* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)acksend.c 2.4 (Berkeley) 5/27/86"; #endif not lint #include "globals.h" #include #define RECEIVED 0 #define LOST 1 #define SECFORACK 1 /* seconds */ #define USECFORACK 0 /* microseconds */ #define MAXCOUNT 5 struct tsp *answer; /* * Acksend implements reliable datagram transmission by using sequence * numbers and retransmission when necessary. * `name' is the name of the destination * `addr' is the address to send to * If `name' is ANYADDR, this routine implements reliable broadcast. */ struct tsp *acksend(message, addr, name, ack, net) struct tsp *message; struct sockaddr_in *addr; char *name; int ack; struct netinfo *net; { int count; int flag; extern u_short sequence; struct timeval tout; struct tsp *readmsg(); count = 0; message->tsp_vers = TSPVERSION; message->tsp_seq = sequence; if (trace) { fprintf(fd, "acksend: "); if (name == ANYADDR) fprintf(fd, "broadcast: "); else fprintf(fd, "%s: ", name); print(message, addr); } bytenetorder(message); do { if (sendto(sock, (char *)message, sizeof(struct tsp), 0, addr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "acksend: sendto: %m"); exit(1); } tout.tv_sec = SECFORACK; tout.tv_usec = USECFORACK; answer = readmsg(ack, name, &tout, net); if (answer != NULL) { if (answer->tsp_seq != sequence) { if (trace) fprintf(fd, "acksend: seq # %d != %d\n", answer->tsp_seq, sequence); continue; } flag = RECEIVED; } else { flag = LOST; if (++count == MAXCOUNT) { break; } } } while (flag != RECEIVED); sequence++; return(answer); } make depend above' >> Makefile # DO NOT DELETE THIS LINE -- make depend uses it cmds.o: cmds.c ./timedc.h /usr/include/sys/param.h cmds.o: /usr/include/machine/machparam.h /usr/inetc/timed/byteorder.c 440 0 12 2330 3664145740 10051 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)byteorder.c 2.4 (Berkeley) 5/20/86"; #endif not lint #include "globals.h" #include /* * Two routines to do the necessary byte swapping for timed protocol * messages. Protocol is defined in /usr/include/protocols/timed.h */ bytenetorder(ptr) struct tsp *ptr; { ptr->tsp_seq = htons((u_short)ptr->tsp_seq); switch (ptr->tsp_type) { case TSP_SETTIME: case TSP_ADJTIME: case TSP_SETDATE: case TSP_SETDATEREQ: ptr->tsp_time.tv_sec = htonl((u_long)ptr->tsp_time.tv_sec); ptr->tsp_time.tv_usec = htonl((u_long)ptr->tsp_time.tv_usec); break; default: break; /* nothing more needed */ } } bytehostorder(ptr) struct tsp *ptr; { ptr->tsp_seq = ntohs((u_short)ptr->tsp_seq); switch (ptr->tsp_type) { case TSP_SETTIME: case TSP_ADJTIME: case TSP_SETDATE: case TSP_SETDATEREQ: ptr->tsp_time.tv_sec = ntohl((u_long)ptr->tsp_time.tv_sec); ptr->tsp_time.tv_usec = ntohl((u_long)ptr->tsp_time.tv_usec); break; default: break; /* nothing more needed */ } } netorder(message); do { if (sendto(sock, (char *)message, sizeof(struct tsp), 0, addr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "acksend: sendto: %m"); exit(1); } tout.tv_sec = SECFORACK; tout.tv_usec = USECFORACK; answer = readmsg(ack, name, &tout, net); if (etc/timed/candidate.c 440 0 12 5376 3652551253 10000 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)candidate.c 2.3 (Berkeley) 4/21/86"; #endif not lint #include "globals.h" #include #define ELECTIONWAIT 3 /* seconds */ /* * `election' candidates a host as master: it is called by a slave * which runs with the -M option set when its election timeout expires. * Note the conservative approach: if a new timed comes up, or another * candidate sends an election request, the candidature is withdrawn. */ election(net) struct netinfo *net; { int ret; struct tsp *resp, msg, *readmsg(); struct timeval wait; struct tsp *answer, *acksend(); long casual(); struct sockaddr_in server; syslog(LOG_INFO, "THIS MACHINE IS A CANDIDATE"); if (trace) { fprintf(fd, "THIS MACHINE IS A CANDIDATE\n"); } ret = MASTER; slvcount = 1; msg.tsp_type = TSP_ELECTION; msg.tsp_vers = TSPVERSION; (void)strcpy(msg.tsp_name, hostname); bytenetorder(&msg); if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, &net->dest_addr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } do { wait.tv_sec = ELECTIONWAIT; wait.tv_usec = 0; resp = readmsg(TSP_ANY, (char *)ANYADDR, &wait, net); if (resp != NULL) { switch (resp->tsp_type) { case TSP_ACCEPT: (void) addmach(resp->tsp_name, &from); break; case TSP_MASTERUP: case TSP_MASTERREQ: /* * If a timedaemon is coming up at the same time, * give up the candidature: it will be the master. */ ret = SLAVE; break; case TSP_QUIT: case TSP_REFUSE: /* * Collision: change value of election timer * using exponential backoff. * The value of timer will be recomputed (in slave.c) * using the original interval when election will * be successfully completed. */ backoff *= 2; delay2 = casual((long)MINTOUT, (long)(MAXTOUT * backoff)); ret = SLAVE; break; case TSP_ELECTION: /* no master for another round */ msg.tsp_type = TSP_REFUSE; (void)strcpy(msg.tsp_name, hostname); server = from; answer = acksend(&msg, &server, resp->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_ERR, "error in election"); } else { (void) addmach(resp->tsp_name, &from); } break; case TSP_SLAVEUP: (void) addmach(resp->tsp_name, &from); break; case TSP_SETDATE: case TSP_SETDATEREQ: break; default: if (trace) { fprintf(fd, "candidate: "); print(resp, &from); } break; } } else { break; } } while (ret == MASTER); return(ret); } nclude/arpa/inet.h timedc.o: timedc.c ./timedc.h /usr/include/sys/param.h timedc.o: /usr/include/machine/machparam.h /usr/include/signal.h timedc.o: /usr/include/sys/types.h /usr/include/stdio.h /usr/include/sys/time.h timedc.o: /usr/include/time.h /usr/incletc/timed/cmds.c 440 0 12 20530 5514436441 7017 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)cmds.c 2.2.1 (2.11BSD GTE) 1/1/94"; #endif #include "timedc.h" #include #include #include #define TSPTYPES #include #include int id; int sock; int sock_raw; char hostname[MAXHOSTNAMELEN]; struct hostent *hp, *gethostbyname(); struct sockaddr_in server; extern long measure_delta; int bytenetorder(), bytehostorder(); char *strcpy(); /* * Clockdiff computes the difference between the time of the machine on * which it is called and the time of the machines given as argument. * The time differences measured by clockdiff are obtained using a sequence * of ICMP TSTAMP messages which are returned to the sender by the IP module * in the remote machine. * In order to compare clocks of machines in different time zones, the time * is transmitted (as a 32-bit value) in milliseconds since midnight UT. * If a hosts uses a different time format, it should set the high order * bit of the 32-bit quantity it transmits. * However, VMS apparently transmits the time in milliseconds since midnight * local time (rather than GMT) without setting the high order bit. * Furthermore, it does not understand daylight-saving time. This makes * clockdiff behaving inconsistently with hosts running VMS. * * In order to reduce the sensitivity to the variance of message transmission * time, clockdiff sends a sequence of messages. Yet, measures between * two `distant' hosts can be affected by a small error. The error can, however, * be reduced by increasing the number of messages sent in each measurement. */ clockdiff(argc, argv) int argc; char *argv[]; { int measure_status; struct timeval ack; int measure(); if(argc < 2) { printf("Usage: clockdiff host ... \n"); return; } id = getpid(); (void)gethostname(hostname,sizeof(hostname)); while (argc > 1) { argc--; argv++; hp = gethostbyname(*argv); if (hp == NULL) { printf("%s: unknown host\n", *argv); continue; } server.sin_family = hp->h_addrtype; bcopy(hp->h_addr, &(server.sin_addr.s_addr), hp->h_length); ack.tv_sec = 10; ack.tv_usec = 0; if ((measure_status = measure(&ack, &server)) < 0) { perror("measure"); return; } switch (measure_status) { case HOSTDOWN: printf("%s is down\n", hp->h_name); continue; break; case NONSTDTIME: printf("%s time transmitted in a non-standard format\n", hp->h_name); continue; break; case UNREACHABLE: printf("%s is unreachable\n", hp->h_name); continue; break; default: break; } if (measure_delta > 0) printf("time on %s is %D ms. ahead of time on %s\n", hp->h_name, measure_delta, hostname); else if (measure_delta == 0) printf("%s and %s have the same time\n", hp->h_name, hostname); else printf("time on %s is %D ms. behind time on %s\n", hp->h_name, -measure_delta, hostname); } return; } /* * finds location of master timedaemon */ msite(argc) int argc; { int length; int cc; fd_set ready; struct sockaddr_in dest; struct timeval tout; struct sockaddr_in from; struct tsp msg; struct servent *srvp; if (argc != 1) { printf("Usage: msite\n"); return; } srvp = getservbyname("timed", "udp"); if (srvp == 0) { fprintf(stderr, "udp/timed: unknown service\n"); return; } dest.sin_port = srvp->s_port; dest.sin_family = AF_INET; (void)gethostname(hostname,sizeof(hostname)); hp = gethostbyname(hostname); if (hp == NULL) { perror("gethostbyname"); return; } bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); (void)strcpy(msg.tsp_name, hostname); msg.tsp_type = TSP_MSITE; msg.tsp_vers = TSPVERSION; bytenetorder(&msg); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, &dest, length) < 0) { perror("sendto"); return; } tout.tv_sec = 15; tout.tv_usec = 0; FD_ZERO(&ready); FD_SET(sock, &ready); if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { length = sizeof(struct sockaddr_in); cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0, &from, &length); if (cc < 0) { perror("recvfrom"); return; } bytehostorder(&msg); if (msg.tsp_type == TSP_ACK) printf("master timedaemon runs on %s\n", msg.tsp_name); else printf("received wrong ack: %s\n", tsptype[msg.tsp_type]); } else printf("communication error\n"); } /* * quits timedc */ quit() { exit(0); } #define MAXH 4 /* max no. of hosts where election can occur */ /* * Causes the election timer to expire on the selected hosts * It sends just one udp message per machine, relying on * reliability of communication channel. */ testing(argc, argv) int argc; char *argv[]; { int length; int nhosts; struct servent *srvp; struct sockaddr_in sin[MAXH]; struct tsp msg; if(argc < 2) { printf("Usage: testing host ...\n"); return; } srvp = getservbyname("timed", "udp"); if (srvp == 0) { fprintf(stderr, "udp/timed: unknown service\n"); return; } nhosts = 0; while (argc > 1) { argc--; argv++; hp = gethostbyname(*argv); if (hp == NULL) { printf("%s: unknown host\n", *argv); argc--; argv++; continue; } sin[nhosts].sin_port = srvp->s_port; sin[nhosts].sin_family = hp->h_addrtype; bcopy(hp->h_addr, &(sin[nhosts].sin_addr.s_addr), hp->h_length); if (++nhosts == MAXH) break; } msg.tsp_type = TSP_TEST; msg.tsp_vers = TSPVERSION; (void)gethostname(hostname, sizeof(hostname)); (void)strcpy(msg.tsp_name, hostname); bytenetorder(&msg); /* it is not really necessary here */ while (nhosts-- > 0) { length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, &sin[nhosts], length) < 0) { perror("sendto"); return; } } } /* * Enables or disables tracing on local timedaemon */ tracing(argc, argv) int argc; char *argv[]; { int onflag; int length; int cc; fd_set ready; struct sockaddr_in dest; struct timeval tout; struct sockaddr_in from; struct tsp msg; struct servent *srvp; if (argc != 2) { printf("Usage: tracing { on | off }\n"); return; } srvp = getservbyname("timed", "udp"); if (srvp == 0) { fprintf(stderr, "udp/timed: unknown service\n"); return; } dest.sin_port = srvp->s_port; dest.sin_family = AF_INET; (void)gethostname(hostname,sizeof(hostname)); hp = gethostbyname(hostname); bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); if (strcmp(argv[1], "on") == 0) { msg.tsp_type = TSP_TRACEON; onflag = ON; } else { msg.tsp_type = TSP_TRACEOFF; onflag = OFF; } (void)strcpy(msg.tsp_name, hostname); msg.tsp_vers = TSPVERSION; bytenetorder(&msg); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, &dest, length) < 0) { perror("sendto"); return; } tout.tv_sec = 5; tout.tv_usec = 0; FD_ZERO(&ready); FD_SET(sock, &ready); if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { length = sizeof(struct sockaddr_in); cc = recvfrom(sock, (char *)&msg, sizeof(struct tsp), 0, &from, &length); if (cc < 0) { perror("recvfrom"); return; } bytehostorder(&msg); if (msg.tsp_type == TSP_ACK) if (onflag) printf("timed tracing enabled\n"); else printf("timed tracing disabled\n"); else printf("wrong ack received: %s\n", tsptype[msg.tsp_type]); } else printf("communication error\n"); } priv_resources() { int port; struct sockaddr_in sin; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { perror("opening socket"); return(-1); } sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0; for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { sin.sin_port = htons((u_short)port); if (bind(sock, (struct sockaddr *)&sin, sizeof (sin)) >= 0) break; if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { perror("bind"); (void) close(sock); return(-1); } } if (port == IPPORT_RESERVED / 2) { fprintf(stderr, "all reserved ports in use\n"); (void) close(sock); return(-1); } sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sock_raw < 0) { perror("opening raw socket"); (void) close(sock_raw); return(-1); } return(1); } fair playfair 128.39.1.2 tor nta-vax # ucbesvax esvax.berkeley.edu 128.32.137.3 ucbvax-spine ucbvax-il ucbvax-spine.berkeley.edu 128.32.137.4 cartan ucbcartan cartaetc/timed/cmdtab.c 440 0 12 2014 5514436462 7303 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) static char sccsid[] = "@(#)cmdtab.c 2.3.1 (2.11BSD GTE) 1/1/94"; #endif #include "timedc.h" int clockdiff(), help(), msite(), quit(), testing(), tracing(); char clockdiffhelp[] = "measures clock differences between machines"; char helphelp[] = "gets help on commands"; char msitehelp[] = "finds location of master"; char quithelp[] = "exits timedc"; char testinghelp[] = "causes election timers to expire"; char tracinghelp[] = "turns tracing on or off"; struct cmd cmdtab[] = { { "clockdiff", clockdiffhelp, clockdiff, 0 }, { "election", testinghelp, testing, 1 }, { "help", helphelp, help, 0 }, { "msite", msitehelp, msite, 0 }, { "quit", quithelp, quit, 0 }, { "trace", tracinghelp, tracing, 1 }, { "?", helphelp, help, 0 }, }; int NCMDS = sizeof (cmdtab) / sizeof (cmdtab[0]); nning VMS. * * In order to reduce the sensitivity to the variance of message transmission * time, clockdiff sends a sequence of messages. Yet, measures between * two `distant' hosts can be affected by a small error. The error can, however, * be reduced by increasing the number of messages sent in each measurement. */ clockdiff(argc, argv) int argc; char *argv[]; { int measure_status; struct timeval ack; int measure(); if(argc < 2) { printf("Usage: clockdiff host ... \n"); retetc/timed/correct.c 440 0 12 5316 4355112706 7514 /* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)correct.c 2.3 (Berkeley) 5/28/86"; #endif not lint #include "globals.h" #include #ifdef MEASURE extern FILE *fp; #endif /* * `correct' sends to the slaves the corrections for their clocks */ correct(avdelta) long avdelta; { int i; long corr; struct timeval adjlocal; struct tsp msgs; struct timeval mstotvround(); struct tsp *answer, *acksend(); #ifdef MEASURE for(i=0; i= 3) *x = *x-temp+5; else { if (temp <= -3) *x = *x - temp -5; else *x = *x-temp; } adj.tv_sec = *x/1000; adj.tv_usec = (*x-adj.tv_sec*1000)*1000; if (adj.tv_usec < 0) { adj.tv_usec += 1000000; adj.tv_sec--; } return(adj); } adjclock(corr) struct timeval *corr; { struct timeval now; if (timerisset(corr)) { if (corr->tv_sec < MAXADJ && corr->tv_sec > - MAXADJ) { (void)adjtime(corr, (struct timeval *)0); } else { syslog(LOG_WARNING, "clock correction too large to adjust (%ld sec)", corr->tv_sec); (void) gettimeofday(&now, (struct timezone *)0); timevaladd(&now, corr); if (settimeofday(&now, (struct timezone *)0) < 0) syslog(LOG_ERR, "can't set time"); } } } timevaladd(tv1, tv2) register struct timeval *tv1, *tv2; { tv1->tv_sec += tv2->tv_sec; tv1->tv_usec += tv2->tv_usec; if (tv1->tv_usec >= 1000000) { tv1->tv_sec++; tv1->tv_usec -= 1000000; } if (tv1->tv_usec < 0) { tv1->tv_sec--; tv1->tv_usec += 1000000; } } nt argc; { int length; int cc; fd_set ready; struct sockaddr_in dest; struct timeval tout; struct sockaddr_in from; struct tsp msg; struct servent *srvp; if (argc != 1) { printf("Usage: msite\n"); return; } srvp = getservbyname("timed", "udp"); if (srvp == 0) { fprintf(stderr, "udp/timetc/timed/globals.h 440 0 12 4251 5514436500 7477 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ /* @(#)globals.h 2.4.1 (2.11BSD GTE) 1/1/94 */ #include #include #include #include #include #include #include #include #include extern int errno; extern int sock; #define SAMPLEINTVL 240 /* synch() freq for master, sec */ #define MAXADJ 20 /* max correction (sec) for adjtime */ /* * Parameters for network time measurement * of each host using ICMP timestamp requests. */ #define RANGE 20 /* best expected round-trip time, ms */ #define MSGS 5 /* # of timestamp replies to average */ #define TRIALS 10 /* max # of timestamp echos sent */ #define MINTOUT 360 #define MAXTOUT 900 #define GOOD 1 #define UNREACHABLE 2 #define NONSTDTIME 3 #ifdef pdp11 #define HOSTDOWN 0x7fff #else #define HOSTDOWN 0x7fffffff #endif #define OFF 0 #define ON 1 /* * Global and per-network states. */ #define NOMASTER 0 /* no master on any network */ #define SLAVE 1 #define MASTER 2 #define IGNORE 4 #define ALL (SLAVE|MASTER|IGNORE) #define SUBMASTER (SLAVE|MASTER) #define NHOSTS 100 /* max number of hosts controlled by timed */ struct host { char *name; struct sockaddr_in addr; long delta; u_short seq; }; struct netinfo { struct netinfo *next; u_long net; u_long mask; struct in_addr my_addr; struct sockaddr_in dest_addr; /* broadcast addr or point-point */ long status; }; extern struct netinfo *nettab; extern int status; extern int trace; extern int sock; extern struct sockaddr_in from; extern struct netinfo *fromnet, *slavenet; extern FILE *fd; extern char hostname[]; extern char tracefile[]; extern struct host hp[]; extern int backoff; extern long delay1, delay2; extern int slvcount; extern int nslavenets; /* Number of nets were I could be a slave */ extern int nmasternets; /* Number of nets were I could be a master */ extern int nignorednets; /* Number of ignored nets */ extern int nnets; /* Number of nets I am connected to */ char *strcpy(), *malloc(); (LOG_WARNING, "clock correction too large to adjust (%ld sec)", corr->tv_sec); (void) gettimeofday(&now, (struct timezone *)0); timevaladd(&now, corr); if (settimeofday(&now, (struct timezone *)0) < 0) syslog(LOG_ERR, "can't set time"); } } } timevaladd(tv1, tv2) register struct timeval *tv1, *tv2; { tv1->tetc/timed/master.c 440 0 12 27500 4355112706 7365 /* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)master.c 2.14 (Berkeley) 6/5/86"; #endif not lint #include "globals.h" #include #include #include #include extern int machup; extern long measure_delta; extern jmp_buf jmpenv; extern u_short sequence; #ifdef MEASURE int header; FILE *fp = NULL; #endif /* * The main function of `master' is to periodically compute the differences * (deltas) between its clock and the clocks of the slaves, to compute the * network average delta, and to send to the slaves the differences between * their individual deltas and the network delta. * While waiting, it receives messages from the slaves (i.e. requests for * master's name, remote requests to set the network time, ...), and * takes the appropriate action. */ master() { int ind; long pollingtime; struct timeval wait; struct timeval time; struct timeval otime; struct timezone tzone; struct tsp *msg, to; struct sockaddr_in saveaddr; int findhost(); char *date(); struct tsp *readmsg(); struct tsp *answer, *acksend(); char olddate[32]; struct sockaddr_in server; register struct netinfo *ntp; #ifdef MEASURE if (fp == NULL) { fp = fopen("/usr/adm/timed.masterlog", "w"); setlinebuf(fp); } #endif syslog(LOG_INFO, "This machine is master"); if (trace) fprintf(fd, "THIS MACHINE IS MASTER\n"); for (ntp = nettab; ntp != NULL; ntp = ntp->next) if (ntp->status == MASTER) masterup(ntp); pollingtime = 0; loop: (void)gettimeofday(&time, (struct timezone *)0); if (time.tv_sec >= pollingtime) { pollingtime = time.tv_sec + SAMPLEINTVL; synch(0L); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { to.tsp_type = TSP_LOOP; to.tsp_vers = TSPVERSION; to.tsp_seq = sequence++; to.tsp_hopcnt = 10; (void)strcpy(to.tsp_name, hostname); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, &ntp->dest_addr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } } wait.tv_sec = pollingtime - time.tv_sec; wait.tv_usec = 0; msg = readmsg(TSP_ANY, (char *)ANYADDR, &wait, (struct netinfo *)NULL); if (msg != NULL) { switch (msg->tsp_type) { case TSP_MASTERREQ: break; case TSP_SLAVEUP: ind = addmach(msg->tsp_name, &from); newslave(ind, msg->tsp_seq); break; case TSP_SETDATE: saveaddr = from; /* * the following line is necessary due to syslog * calling ctime() which clobbers the static buffer */ (void)strcpy(olddate, date()); (void)gettimeofday(&time, &tzone); otime = time; time.tv_sec = msg->tsp_time.tv_sec; time.tv_usec = msg->tsp_time.tv_usec; (void)settimeofday(&time, &tzone); syslog(LOG_NOTICE, "date changed from: %s", olddate); logwtmp(otime, time); msg->tsp_type = TSP_DATEACK; msg->tsp_vers = TSPVERSION; (void)strcpy(msg->tsp_name, hostname); bytenetorder(msg); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &saveaddr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } spreadtime(); pollingtime = 0; break; case TSP_SETDATEREQ: ind = findhost(msg->tsp_name); if (ind < 0) { syslog(LOG_WARNING, "DATEREQ from uncontrolled machine"); break; } if (hp[ind].seq != msg->tsp_seq) { hp[ind].seq = msg->tsp_seq; /* * the following line is necessary due to syslog * calling ctime() which clobbers the static buffer */ (void)strcpy(olddate, date()); (void)gettimeofday(&time, &tzone); otime = time; time.tv_sec = msg->tsp_time.tv_sec; time.tv_usec = msg->tsp_time.tv_usec; (void)settimeofday(&time, &tzone); syslog(LOG_NOTICE, "date changed by %s from: %s", msg->tsp_name, olddate); logwtmp(otime, time); spreadtime(); pollingtime = 0; } break; case TSP_MSITE: case TSP_MSITEREQ: break; case TSP_TRACEON: if (!(trace)) { fd = fopen(tracefile, "w"); setlinebuf(fd); fprintf(fd, "Tracing started on: %s\n\n", date()); } trace = ON; break; case TSP_TRACEOFF: if (trace) { fprintf(fd, "Tracing ended on: %s\n", date()); (void)fclose(fd); } #ifdef GPROF moncontrol(0); _mcleanup(); moncontrol(1); #endif trace = OFF; break; case TSP_ELECTION: to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); server = from; answer = acksend(&to, &server, msg->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_ERR, "election error"); } else { (void) addmach(msg->tsp_name, &from); } pollingtime = 0; break; case TSP_CONFLICT: /* * After a network partition, there can be * more than one master: the first slave to * come up will notify here the situation. */ (void)strcpy(to.tsp_name, hostname); if (fromnet == NULL) break; for(;;) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &fromnet->dest_addr, (char *)ANYADDR, TSP_MASTERACK, fromnet); if (answer == NULL) break; to.tsp_type = TSP_QUIT; server = from; msg = acksend(&to, &server, answer->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (msg == NULL) { syslog(LOG_ERR, "error on sending QUIT"); } else { (void) addmach(answer->tsp_name, &from); } } masterup(fromnet); pollingtime = 0; break; case TSP_RESOLVE: /* * do not want to call synch() while waiting * to be killed! */ (void)gettimeofday(&time, (struct timezone *)0); pollingtime = time.tv_sec + SAMPLEINTVL; break; case TSP_QUIT: /* become slave */ #ifdef MEASURE if (fp != NULL) { (void)fclose(fp); fp = NULL; } #endif longjmp(jmpenv, 2); break; case TSP_LOOP: /* * We should not have received this from a net * we are master on. There must be two masters * in this case. */ to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); server = from; answer = acksend(&to, &server, msg->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_WARNING, "loop breakage: no reply to QUIT"); } else { (void)addmach(msg->tsp_name, &from); } default: if (trace) { fprintf(fd, "garbage: "); print(msg, &from); } break; } } goto loop; } /* * `synch' synchronizes all the slaves by calling measure, * networkdelta and correct */ synch(mydelta) long mydelta; { int i; int measure_status; long netdelta; struct timeval tack; #ifdef MEASURE #define MAXLINES 8 static int lines = 1; struct timeval start, end; #endif int measure(); int correct(); long networkdelta(); char *date(); if (slvcount > 1) { #ifdef MEASURE (void)gettimeofday(&start, (struct timezone *)0); if (header == ON || --lines == 0) { fprintf(fp, "%s\n", date()); for (i=0; i 1) { netdelta = networkdelta(); if (trace) fprintf(fd, "master correct: %ld ms.\n", mydelta); correct(netdelta); } } #ifdef MEASURE gettimeofday(&end, 0); end.tv_sec -= start.tv_sec; end.tv_usec -= start.tv_usec; if (end.tv_usec < 0) { end.tv_sec -= 1; end.tv_usec += 1000000; } fprintf(fp, "%D ms.\n", (end.tv_sec*1000+end.tv_usec/1000)); #endif for(i=1; imask) == ntp->net) rmmach(i--); if (trace) prthp(); } /* * remove the machine with the given index in the host table. */ rmmach(ind) int ind; { if (trace) fprintf(fd, "rmmach: %s\n", hp[ind].name); free(hp[ind].name); hp[ind] = hp[--slvcount]; } prthp() { int i; fprintf(fd, "host table:"); for (i=1; idest_addr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } for (;;) { wait.tv_sec = 1; wait.tv_usec = 0; msg = readmsg(TSP_SLAVEUP, (char *)ANYADDR, &wait, net); if (msg != NULL) { (void) addmach(msg->tsp_name, &from); } else break; } } newslave(ind, seq) u_short seq; { struct tsp to; struct tsp *answer, *acksend(); if (trace) prthp(); if (seq == 0 || hp[ind].seq != seq) { hp[ind].seq = seq; to.tsp_type = TSP_SETTIME; (void)strcpy(to.tsp_name, hostname); /* * give the upcoming slave the time * to check its input queue before * setting the time */ sleep(1); (void) gettimeofday(&to.tsp_time, (struct timezone *)0); answer = acksend(&to, &hp[ind].addr, hp[ind].name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_WARNING, "no reply to initial SETTIME from: %s", hp[ind].name); rmmach(ind); } } } char *wtmpfile = "/usr/adm/wtmp"; struct utmp wtmp[2] = { { "|", "", "", 0 }, { "{", "", "", 0 } }; logwtmp(otime, ntime) struct timeval otime, ntime; { int f; wtmp[0].ut_time = otime.tv_sec + (otime.tv_usec + 500000) / 1000000; wtmp[1].ut_time = ntime.tv_sec + (ntime.tv_usec + 500000) / 1000000; if (wtmp[0].ut_time == wtmp[1].ut_time) return; if ((f = open(wtmpfile, O_WRONLY|O_APPEND)) >= 0) { (void) write(f, (char *)wtmp, sizeof(wtmp)); (void) close(f); } } edu 128.32.139.8 bud ucbbud bud.berkeley.edu 128.32.139.9 heine ucbheine heine.berkeley.edu 128.32.139.10 corona ucbcorona corona.berkeley.edu 128.32.139.11 molson ucbmolson molson.berkeleetc/timed/measure.c 440 0 12 11114 4115662104 7521 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)measure.c 2.4 (Berkeley) 5/28/86"; #endif not lint #include "globals.h" #include #include #include #include #define BIASP 43199999 #define BIASN -43200000 #define MODULO 86400000 #define PROCESSING_TIME 5 /* ms. to reduce error in measurement */ #define PACKET_IN 1024 extern int id; long measure_delta; extern int sock_raw; static n_short seqno = 0; /* * Measures the differences between machines' clocks using * ICMP timestamp messages. */ measure(wait, addr) struct timeval *wait; struct sockaddr_in *addr; { int length; int status; int msgcount, trials; int cc, count; fd_set ready; long sendtime, recvtime, histime; long min1, min2, diff; register long delta1, delta2; struct timeval tv1, tout; u_char packet[PACKET_IN], opacket[64]; register struct icmp *icp = (struct icmp *) packet; register struct icmp *oicp = (struct icmp *) opacket; struct ip *ip = (struct ip *) packet; min1 = min2 = 0x7fffffff; status = HOSTDOWN; measure_delta = HOSTDOWN; /* empties the icmp input queue */ FD_ZERO(&ready); empty: tout.tv_sec = tout.tv_usec = 0; FD_SET(sock_raw, &ready); if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { length = sizeof(struct sockaddr_in); cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, (struct sockaddr_in *)NULL, &length); if (cc < 0) return(-1); goto empty; } /* * To measure the difference, select MSGS messages whose round-trip * time is smaller than RANGE if ckrange is 1, otherwise simply * select MSGS messages regardless of round-trip transmission time. * Choose the smallest transmission time in each of the two directions. * Use these two latter quantities to compute the delta between * the two clocks. */ length = sizeof(struct sockaddr_in); oicp->icmp_type = ICMP_TSTAMP; oicp->icmp_code = 0; oicp->icmp_cksum = 0; oicp->icmp_id = id; oicp->icmp_rtime = 0; oicp->icmp_ttime = 0; FD_ZERO(&ready); msgcount = 0; for (trials = 0; msgcount < MSGS && trials < TRIALS; ++trials) { oicp->icmp_seq = ++seqno; oicp->icmp_cksum = 0; tout.tv_sec = wait->tv_sec; tout.tv_usec = wait->tv_usec; (void)gettimeofday (&tv1, (struct timezone *)0); sendtime = oicp->icmp_otime = (tv1.tv_sec%(24L*60L*60L)) * 1000 + tv1.tv_usec / 1000; oicp->icmp_cksum = in_cksum((u_short *)oicp, sizeof(*oicp)); count = sendto(sock_raw, (char *)opacket, sizeof(*oicp), 0, addr, sizeof(struct sockaddr_in)); if (count < 0) { status = UNREACHABLE; return(-1); } for (;;) { FD_SET(sock_raw, &ready); if ((count = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) <= 0) break; cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, (struct sockaddr_in *)NULL, &length); (void)gettimeofday(&tv1, (struct timezone *)0); if (cc < 0) return(-1); icp = (struct icmp *)(packet + (ip->ip_hl << 2)); if((icp->icmp_type == ICMP_TSTAMPREPLY) && icp->icmp_id == id && icp->icmp_seq == seqno) break; } if (count <= 0) continue; /* resend */ recvtime = (tv1.tv_sec % (24L*60L*60L)) * 1000 + tv1.tv_usec / 1000; diff = recvtime - sendtime; /* * diff can be less than 0 aroud midnight */ if (diff < 0) continue; msgcount++; histime = ntohl((u_long)icp->icmp_rtime); /* * a hosts using a time format different from * ms. since midnight UT (as per RFC792) should * set the high order bit of the 32-bit time * value it transmits. */ if ((histime & 0x80000000) != 0) { status = NONSTDTIME; break; } status = GOOD; delta1 = histime - sendtime; /* * Handles wrap-around to avoid that around * midnight small time differences appear * enormous. However, the two machine's clocks * must be within 12 hours from each other. */ if (delta1 < BIASN) delta1 += MODULO; else if (delta1 > BIASP) delta1 -= MODULO; delta2 = recvtime - histime; if (delta2 < BIASN) delta2 += MODULO; else if (delta2 > BIASP) delta2 -= MODULO; if (delta1 < min1) min1 = delta1; if (delta2 < min2) min2 = delta2; if (diff < RANGE) { min1 = delta1; min2 = delta2; break; } } /* * If no answer is received for TRIALS consecutive times, * the machine is assumed to be down */ if (status == GOOD) { measure_delta = (min1 - min2)/2 + PROCESSING_TIME; } return(status); } f machup = 1; hp[0].delta = 0; for(i=1; i extern char *tsptype[]; /* * LOOKAT checks if the message is of the requested type and comes from * the right machine, returning 1 in case of affirmative answer */ #define LOOKAT(msg, mtype, mfrom, netp, froms) \ (((((mtype) == TSP_ANY) || ((mtype) == (msg).tsp_type)) && \ (((mfrom) == NULL) || (strcmp((mfrom), (msg).tsp_name) == 0)) && \ (((netp) == NULL) || \ (((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net))) \ ? 1 : 0) #define MORETIME(rtime, rtout) \ (((rtime).tv_sec > (rtout).tv_sec || \ ((rtime).tv_sec == (rtout).tv_sec && \ (rtime).tv_usec >= (rtout).tv_usec)) \ ? 0 : 1) struct timeval rtime, rwait, rtout; struct tsp msgin; static struct tsplist { struct tsp info; struct sockaddr_in addr; struct tsplist *p; } msgslist; struct sockaddr_in from; struct netinfo *fromnet; /* * `readmsg' returns message `type' sent by `machfrom' if it finds it * either in the receive queue, or in a linked list of previously received * messages that it maintains. * Otherwise it waits to see if the appropriate message arrives within * `intvl' seconds. If not, it returns NULL. */ struct tsp * readmsg(type, machfrom, intvl, netfrom) int type; char *machfrom; struct timeval *intvl; struct netinfo *netfrom; { int length; fd_set ready; static struct tsplist *head = &msgslist; static struct tsplist *tail = &msgslist; struct tsplist *prev; register struct netinfo *ntp; register struct tsplist *ptr; if (trace) { fprintf(fd, "looking for %s from %s\n", tsptype[type], machfrom == NULL ? "ANY" : machfrom); ptr = head->p; fprintf(fd, "msgqueue:\n"); while (ptr != NULL) { fprintf(fd, "\t"); print(&ptr->info, &ptr->addr); ptr = ptr->p; } } ptr = head->p; prev = head; /* * Look for the requested message scanning through the * linked list. If found, return it and free the space */ while (ptr != NULL) { if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) { msgin = ptr->info; from = ptr->addr; prev->p = ptr->p; if (ptr == tail) tail = prev; free((char *)ptr); fromnet = NULL; if (netfrom == NULL) for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if ((ntp->mask & from.sin_addr.s_addr) == ntp->net) { fromnet = ntp; break; } } else fromnet = netfrom; if (trace) { fprintf(fd, "readmsg: "); print(&msgin, &from); } return(&msgin); } else { prev = ptr; ptr = ptr->p; } } /* * If the message was not in the linked list, it may still be * coming from the network. Set the timer and wait * on a select to read the next incoming message: if it is the * right one, return it, otherwise insert it in the linked list. */ (void)gettimeofday(&rtime, (struct timezone *)0); rtout.tv_sec = rtime.tv_sec + intvl->tv_sec; rtout.tv_usec = rtime.tv_usec + intvl->tv_usec; if (rtout.tv_usec > 1000000) { rtout.tv_usec -= 1000000; rtout.tv_sec++; } FD_ZERO(&ready); for (; MORETIME(rtime, rtout); (void)gettimeofday(&rtime, (struct timezone *)0)) { rwait.tv_sec = rtout.tv_sec - rtime.tv_sec; rwait.tv_usec = rtout.tv_usec - rtime.tv_usec; if (rwait.tv_usec < 0) { rwait.tv_usec += 1000000; rwait.tv_sec--; } if (rwait.tv_sec < 0) rwait.tv_sec = rwait.tv_usec = 0; if (trace) { fprintf(fd, "readmsg: wait: (%D %D)\n", rwait.tv_sec, rwait.tv_usec); } FD_SET(sock, &ready); if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &rwait)) { length = sizeof(struct sockaddr_in); if (recvfrom(sock, (char *)&msgin, sizeof(struct tsp), 0, &from, &length) < 0) { syslog(LOG_ERR, "receiving datagram packet: %m"); exit(1); } bytehostorder(&msgin); if (msgin.tsp_vers > TSPVERSION) { if (trace) { fprintf(fd, "readmsg: version mismatch\n"); /* should do a dump of the packet, but... */ } continue; } fromnet = NULL; for (ntp = nettab; ntp != NULL; ntp = ntp->next) if ((ntp->mask & from.sin_addr.s_addr) == ntp->net) { fromnet = ntp; break; } /* * drop packets from nets we are ignoring permanently */ if (fromnet == NULL) { /* * The following messages may originate on * this host with an ignored network address */ if (msgin.tsp_type != TSP_TRACEON && msgin.tsp_type != TSP_SETDATE && msgin.tsp_type != TSP_MSITE && #ifdef TESTING msgin.tsp_type != TSP_TEST && #endif msgin.tsp_type != TSP_TRACEOFF) { if (trace) { fprintf(fd, "readmsg: discarded: "); print(&msgin, &from); } continue; } } /* * Throw away messages coming from this machine, unless * they are of some particular type. * This gets rid of broadcast messages and reduces * master processing time. */ if ( !(strcmp(msgin.tsp_name, hostname) != 0 || msgin.tsp_type == TSP_SETDATE || #ifdef TESTING msgin.tsp_type == TSP_TEST || #endif msgin.tsp_type == TSP_MSITE || (msgin.tsp_type == TSP_LOOP && msgin.tsp_hopcnt != 10) || msgin.tsp_type == TSP_TRACEON || msgin.tsp_type == TSP_TRACEOFF)) { if (trace) { fprintf(fd, "readmsg: discarded: "); print(&msgin, &from); } continue; } /* * Send acknowledgements here; this is faster and avoids * deadlocks that would occur if acks were sent from a * higher level routine. Different acknowledgements are * necessary, depending on status. */ if (fromnet->status == MASTER) masterack(); else if (fromnet->status == SLAVE) slaveack(); else ignoreack(); if (LOOKAT(msgin, type, machfrom, netfrom, from)) { if (trace) { fprintf(fd, "readmsg: "); print(&msgin, &from); } return(&msgin); } else { tail->p = (struct tsplist *) malloc(sizeof(struct tsplist)); tail = tail->p; tail->p = NULL; tail->info = msgin; tail->addr = from; } } else { break; } } return((struct tsp *)NULL); } /* * `slaveack' sends the necessary acknowledgements: * only the type ACK is to be sent by a slave */ slaveack() { int length; struct tsp resp; length = sizeof(struct sockaddr_in); switch(msgin.tsp_type) { case TSP_ADJTIME: case TSP_SETTIME: case TSP_ACCEPT: case TSP_REFUSE: case TSP_TRACEON: case TSP_TRACEOFF: case TSP_QUIT: resp = msgin; resp.tsp_type = TSP_ACK; resp.tsp_vers = TSPVERSION; (void)strcpy(resp.tsp_name, hostname); if (trace) { fprintf(fd, "Slaveack: "); print(&resp, &from); } bytenetorder(&resp); /* this is not really necessary here */ if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, &from, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } break; default: break; } } /* * Certain packets may arrive from this machine on ignored networks. * These packets should be acknowledged. */ ignoreack() { int length; struct tsp resp; length = sizeof(struct sockaddr_in); switch(msgin.tsp_type) { case TSP_TRACEON: case TSP_TRACEOFF: resp = msgin; resp.tsp_type = TSP_ACK; resp.tsp_vers = TSPVERSION; (void)strcpy(resp.tsp_name, hostname); if (trace) { fprintf(fd, "Ignoreack: "); print(&resp, &from); } bytenetorder(&resp); /* this is not really necessary here */ if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, &from, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } break; default: break; } } /* * `masterack' sends the necessary acknowledgments * to the messages received by a master */ masterack() { int length; struct tsp resp; length = sizeof(struct sockaddr_in); resp = msgin; resp.tsp_vers = TSPVERSION; (void)strcpy(resp.tsp_name, hostname); switch(msgin.tsp_type) { case TSP_QUIT: case TSP_TRACEON: case TSP_TRACEOFF: case TSP_MSITE: case TSP_MSITEREQ: resp.tsp_type = TSP_ACK; bytenetorder(&resp); if (trace) { fprintf(fd, "Masterack: "); print(&resp, &from); } if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, &from, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } break; case TSP_RESOLVE: case TSP_MASTERREQ: resp.tsp_type = TSP_MASTERACK; bytenetorder(&resp); if (trace) { fprintf(fd, "Masterack: "); print(&resp, &from); } if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, &from, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } break; case TSP_SETDATEREQ: resp.tsp_type = TSP_DATEACK; bytenetorder(&resp); if (trace) { fprintf(fd, "Masterack: "); print(&resp, &from); } if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, &from, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } break; default: break; } } /* * Print a TSP message */ print(msg, addr) struct tsp *msg; struct sockaddr_in *addr; { switch (msg->tsp_type) { case TSP_LOOP: fprintf(fd, "%s %d %u (#%d) %s %s\n", tsptype[msg->tsp_type], msg->tsp_vers, msg->tsp_seq, msg->tsp_hopcnt, msg->tsp_name, inet_ntoa(addr->sin_addr)); break; case TSP_SETTIME: case TSP_ADJTIME: case TSP_SETDATE: case TSP_SETDATEREQ: fprintf(fd, "%s %d %u (%ld, %ld) %s %s\n", tsptype[msg->tsp_type], msg->tsp_vers, msg->tsp_seq, msg->tsp_time.tv_sec, msg->tsp_time.tv_usec, msg->tsp_name, inet_ntoa(addr->sin_addr)); break; default: fprintf(fd, "%s %d %u %s %s\n", tsptype[msg->tsp_type], msg->tsp_vers, msg->tsp_seq, msg->tsp_name, inet_ntoa(addr->sin_addr)); break; } } EST && #endif msgin.tsp_type != TSP_TRACEOFF) { if (trace) { fprintf(fd, "readmsg: discarded: "); print(&msgin, &from); } continue; } } /* * Throw away messages coming from this machine, unless * they are of some particular type. * Thisetc/timed/networkdelta.c 440 0 12 2742 3577123074 10563 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)networkdelta.c 2.1 (Berkeley) 12/10/85"; #endif not lint #include "globals.h" #include extern int machup; /* * `networkdelta' selects the largest set of deltas that fall within the * interval RANGE, and uses them to compute the network average delta */ long networkdelta() { int i, j, maxind, minind; int ext; int tempind; long tempdata; long x[NHOSTS]; long average; for (i=0; i i+1) j--; if ((x[j]-x[i] <= RANGE) && (j-i >= maxind-minind)) { minind=i; maxind=j; } i++; if(i = j) j++; } } while (j < machup); if ((x[machup-1] - x[i] <= RANGE) && (machup-i-1 >= maxind-minind)) { minind=i; maxind=machup-1; } /****/ compute: ext = maxind - minind + 1; average = 0; for (i=minind; i<=maxind; i++) average += x[i]; average /= ext; return(average); } ADJTIME: case TSP_SETTIME: cetc/timed/slave.c 440 0 12 33150 4115662453 7205 /* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)slave.c 2.16 (Berkeley) 6/5/86"; #endif not lint #include "globals.h" #include #include extern jmp_buf jmpenv; extern u_short sequence; slave() { int length; int senddateack; long electiontime, refusetime, looktime; u_short seq; char candidate[MAXHOSTNAMELEN]; struct tsp *msg, to, *readmsg(); struct sockaddr_in saveaddr, msaveaddr; struct timeval wait; struct timeval time, otime; struct tsp *answer, *acksend(); int timeout(); char *date(); long casual(); int bytenetorder(); char olddate[32]; struct sockaddr_in server; register struct netinfo *ntp; int ind; struct tsp resp; extern int Mflag; extern int justquit; #ifdef MEASURE extern FILE *fp; #endif if (slavenet) { resp.tsp_type = TSP_SLAVEUP; resp.tsp_vers = TSPVERSION; (void)strcpy(resp.tsp_name, hostname); bytenetorder(&resp); if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, &slavenet->dest_addr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } if (status & MASTER) { #ifdef MEASURE if (fp == NULL) { fp = fopen("/usr/adm/timed.masterlog", "w"); setlinebuf(fp); } #endif syslog(LOG_INFO, "THIS MACHINE IS A SUBMASTER"); if (trace) { fprintf(fd, "THIS MACHINE IS A SUBMASTER\n"); } for (ntp = nettab; ntp != NULL; ntp = ntp->next) if (ntp->status == MASTER) masterup(ntp); } else { syslog(LOG_INFO, "THIS MACHINE IS A SLAVE"); if (trace) { fprintf(fd, "THIS MACHINE IS A SLAVE\n"); } } seq = 0; senddateack = OFF; refusetime = 0; (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; if (Mflag) if (justquit) looktime = time.tv_sec + delay2; else looktime = 1; else looktime = 0; loop: length = sizeof(struct sockaddr_in); (void)gettimeofday(&time, (struct timezone *)0); if (time.tv_sec > electiontime) { if (trace) fprintf(fd, "election timer expired\n"); longjmp(jmpenv, 1); } if (looktime && time.tv_sec > looktime) { if (trace) fprintf(fd, "Looking for nets to master and loops\n"); if (nignorednets > 0) { for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == IGNORE) { lookformaster(ntp); if (ntp->status == MASTER) masterup(ntp); else ntp->status = IGNORE; } } setstatus(); #ifdef MEASURE /* * Check to see if we just became master * (file not open) */ if (fp == NULL) { fp = fopen("/usr/adm/timed.masterlog", "w"); setlinebuf(fp); } #endif } for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == MASTER) { to.tsp_type = TSP_LOOP; to.tsp_vers = TSPVERSION; to.tsp_seq = sequence++; to.tsp_hopcnt = 10; (void)strcpy(to.tsp_name, hostname); bytenetorder(&to); if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, &ntp->dest_addr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } } (void)gettimeofday(&time, (struct timezone *)0); looktime = time.tv_sec + delay2; } wait.tv_sec = electiontime - time.tv_sec + 10; wait.tv_usec = 0; msg = readmsg(TSP_ANY, (char *)ANYADDR, &wait, (struct netinfo *)NULL); if (msg != NULL) { switch (msg->tsp_type) { case TSP_SETDATE: #ifdef TESTING case TSP_TEST: #endif case TSP_MSITE: case TSP_TRACEOFF: case TSP_TRACEON: break; case TSP_MASTERUP: if (fromnet == NULL) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; default: if (fromnet == NULL || fromnet->status == IGNORE) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; } switch (msg->tsp_type) { case TSP_ADJTIME: if (fromnet->status != SLAVE) break; (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; if (seq != msg->tsp_seq) { seq = msg->tsp_seq; if ((status & SUBMASTER) == SUBMASTER) { synch((msg->tsp_time.tv_sec * 1000) + (msg->tsp_time.tv_usec / 1000)); } else { adjclock(&(msg->tsp_time)); } } break; case TSP_SETTIME: if (fromnet->status != SLAVE) break; if (seq == msg->tsp_seq) break; seq = msg->tsp_seq; (void)strcpy(olddate, date()); (void)gettimeofday(&otime, (struct timezone *)0); (void)settimeofday(&msg->tsp_time, (struct timezone *)0); syslog(LOG_NOTICE, "date changed by %s from: %s", msg->tsp_name, olddate); logwtmp(otime, msg->tsp_time); if ((status & SUBMASTER) == SUBMASTER) spreadtime(); (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; if (senddateack == ON) { senddateack = OFF; msg->tsp_type = TSP_DATEACK; (void)strcpy(msg->tsp_name, hostname); bytenetorder(msg); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &saveaddr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } break; case TSP_MASTERUP: if (slavenet && fromnet != slavenet) break; makeslave(fromnet); setstatus(); msg->tsp_type = TSP_SLAVEUP; msg->tsp_vers = TSPVERSION; (void)strcpy(msg->tsp_name, hostname); bytenetorder(msg); answerdelay(); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &from, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } backoff = 1; delay2 = casual((long)MINTOUT, (long)MAXTOUT); (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; refusetime = 0; break; case TSP_MASTERREQ: if (fromnet->status != SLAVE) break; (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; break; case TSP_SETDATE: saveaddr = from; msg->tsp_type = TSP_SETDATEREQ; msg->tsp_vers = TSPVERSION; (void)strcpy(msg->tsp_name, hostname); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == SLAVE) break; } if (ntp == NULL) break; answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR, TSP_DATEACK, ntp); if (answer != NULL) { msg->tsp_type = TSP_ACK; bytenetorder(msg); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &saveaddr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } senddateack = ON; } break; case TSP_SETDATEREQ: saveaddr = from; if (status != SUBMASTER || fromnet->status != MASTER) break; for (ntp = nettab; ntp != NULL; ntp = ntp->next) { if (ntp->status == SLAVE) break; } ind = findhost(msg->tsp_name); if (ind < 0) { syslog(LOG_WARNING, "DATEREQ from uncontrolled machine"); break; } syslog(LOG_DEBUG, "forwarding date change request for %s", msg->tsp_name); (void)strcpy(msg->tsp_name, hostname); answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR, TSP_DATEACK, ntp); if (answer != NULL) { msg->tsp_type = TSP_DATEACK; bytenetorder(msg); length = sizeof(struct sockaddr_in); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &saveaddr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } break; case TSP_TRACEON: if (!(trace)) { fd = fopen(tracefile, "w"); setlinebuf(fd); fprintf(fd, "Tracing started on: %s\n\n", date()); } trace = ON; break; case TSP_TRACEOFF: if (trace) { fprintf(fd, "Tracing ended on: %s\n", date()); (void)fclose(fd); } #ifdef GPROF moncontrol(0); _mcleanup(); moncontrol(1); #endif trace = OFF; break; case TSP_SLAVEUP: if ((status & MASTER) && fromnet->status == MASTER) { ind = addmach(msg->tsp_name, &from); newslave(ind, msg->tsp_seq); } break; case TSP_ELECTION: if (fromnet->status == SLAVE) { (void)gettimeofday(&time, (struct timezone *)0); electiontime = time.tv_sec + delay2; seq = 0; /* reset sequence number */ if (time.tv_sec < refusetime) msg->tsp_type = TSP_REFUSE; else { msg->tsp_type = TSP_ACCEPT; refusetime = time.tv_sec + 30; } (void)strcpy(candidate, msg->tsp_name); (void)strcpy(msg->tsp_name, hostname); answerdelay(); server = from; answer = acksend(msg, &server, candidate, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) syslog(LOG_WARNING, "no answer from master candidate\n"); } else { /* fromnet->status == MASTER */ to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); server = from; answer = acksend(&to, &server, msg->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_WARNING, "election error: no reply to QUIT"); } else { (void) addmach(msg->tsp_name, &from); } } break; case TSP_CONFLICT: if (fromnet->status != MASTER) break; /* * After a network partition, there can be * more than one master: the first slave to * come up will notify here the situation. */ (void)strcpy(to.tsp_name, hostname); if (fromnet == NULL) break; for(;;) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &fromnet->dest_addr, (char *)ANYADDR, TSP_MASTERACK, fromnet); if (answer == NULL) break; to.tsp_type = TSP_QUIT; server = from; msg = acksend(&to, &server, answer->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (msg == NULL) { syslog(LOG_WARNING, "conflict error: no reply to QUIT"); } else { (void) addmach(answer->tsp_name, &from); } } masterup(fromnet); break; case TSP_MSITE: if (!slavenet) break; msaveaddr = from; msg->tsp_type = TSP_MSITEREQ; msg->tsp_vers = TSPVERSION; (void)strcpy(msg->tsp_name, hostname); answer = acksend(msg, &slavenet->dest_addr, (char *)ANYADDR, TSP_ACK, slavenet); if (answer != NULL) { msg->tsp_type = TSP_ACK; length = sizeof(struct sockaddr_in); bytenetorder(msg); if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &msaveaddr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } break; case TSP_ACCEPT: case TSP_REFUSE: break; case TSP_RESOLVE: break; case TSP_QUIT: /* become slave */ #ifdef MEASURE if (fp != NULL) { (void)fclose(fp); fp = NULL; } #endif longjmp(jmpenv, 2); break; #ifdef TESTING case TSP_TEST: electiontime = 0; break; #endif case TSP_MSITEREQ: if (status & MASTER) break; if (trace) { fprintf(fd, "garbage: "); print(msg, &from); } break; case TSP_LOOP: /* looking for loops of masters */ if ( !(status & MASTER)) break; if (fromnet->status == SLAVE) { if ( !strcmp(msg->tsp_name, hostname)) { for(;;) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &fromnet->dest_addr, (char *)ANYADDR, TSP_MASTERACK, fromnet); if (answer == NULL) break; to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); server = from; answer = acksend(&to, &server, answer->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_ERR, "loop kill error"); } else { electiontime = 0; } } } else { if (msg->tsp_hopcnt-- <= 0) break; bytenetorder(msg); ntp = nettab; for (; ntp != NULL; ntp = ntp->next) if (ntp->status == MASTER) if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, &ntp->dest_addr, length) < 0) { syslog(LOG_ERR, "sendto: %m"); exit(1); } } } else { /* * We should not have received this from a net * we are master on. There must be two masters * in this case. */ if (fromnet->my_addr.s_addr == from.sin_addr.s_addr) break; for (;;) { to.tsp_type = TSP_RESOLVE; answer = acksend(&to, &fromnet->dest_addr, (char *)ANYADDR, TSP_MASTERACK, fromnet); if (answer == NULL) break; to.tsp_type = TSP_QUIT; (void)strcpy(to.tsp_name, hostname); server = from; answer = acksend(&to, &server, answer->tsp_name, TSP_ACK, (struct netinfo *)NULL); if (answer == NULL) { syslog(LOG_ERR, "loop kill error2"); } else { (void)addmach(msg->tsp_name, &from); } } } break; default: if (trace) { fprintf(fd, "garbage: "); print(msg, &from); } break; } } goto loop; } /* * Used before answering a broadcast message to avoid network * contention and likely collisions. */ answerdelay() { struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = delay1; (void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, &timeout); return; } fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; default: if (fromnet == NULL || fromnet->status == IGNORE) { if (trace) { fprintf(fd, "slave ignored: "); print(msg, &from); } goto loop; } break; } switch (msg->tsp_type) { case TSP_ADJTIME: if (fromnet->status != SLAVE) break; (void)gettimeofday(&time, (struetc/timed/timed.c 440 0 12 32505 5514436517 7204 /* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #if defined(DOSCCS) && !defined(lint) char copyright[] = "@(#) Copyright (c) 1985 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)timed.c 2.10.1 (2.11BSD GTE) 1/1/94"; #endif #include "globals.h" #define TSPTYPES #include #include #include #include #include int id; int trace; int sock, sock_raw; int status = 0; int backoff; int slvcount; /* no. of slaves controlled by master */ int machup; u_short sequence; /* sequence number */ long delay1; long delay2; long random(); char hostname[MAXHOSTNAMELEN]; struct host hp[NHOSTS]; char tracefile[] = "/usr/adm/timed.log"; FILE *fd; jmp_buf jmpenv; struct netinfo *nettab = NULL; int nslavenets; /* Number of networks were I could be a slave */ int nmasternets; /* Number of networks were I could be a master */ int nignorednets; /* Number of ignored networks */ int nnets; /* Number of networks I am connected to */ struct netinfo *slavenet; struct netinfo *firstslavenet(); int Mflag; int justquit = 0; struct nets { char *name; long net; struct nets *next; } *nets = (struct nets *)0; /* * The timedaemons synchronize the clocks of hosts in a local area network. * One daemon runs as master, all the others as slaves. The master * performs the task of computing clock differences and sends correction * values to the slaves. * Slaves start an election to choose a new master when the latter disappears * because of a machine crash, network partition, or when killed. * A resolution protocol is used to kill all but one of the masters * that happen to exist in segments of a partitioned network when the * network partition is fixed. * * Authors: Riccardo Gusella & Stefano Zatti */ main(argc, argv) int argc; char **argv; { int on; int ret; long seed; int nflag, iflag; struct timeval time; struct servent *srvp; long casual(); char *date(); int n; int flag; char buf[BUFSIZ]; struct ifconf ifc; struct ifreq ifreq, *ifr; register struct netinfo *ntp; struct netinfo *ntip; struct netinfo *savefromnet; struct sockaddr_in server; u_short port; uid_t getuid(); #ifdef lint ntip = NULL; #endif Mflag = 0; on = 1; backoff = 1; trace = OFF; nflag = OFF; iflag = OFF; openlog("timed", LOG_CONS|LOG_PID, LOG_DAEMON); if (getuid() != 0) { fprintf(stderr, "Timed: not superuser\n"); exit(1); } while (--argc > 0 && **++argv == '-') { (*argv)++; do { switch (**argv) { case 'M': Mflag = 1; break; case 't': trace = ON; break; case 'n': argc--, argv++; if (iflag) { fprintf(stderr, "timed: -i and -n make no sense together\n"); } else { nflag = ON; addnetname(*argv); } while (*(++(*argv)+1)) ; break; case 'i': argc--, argv++; if (nflag) { fprintf(stderr, "timed: -i and -n make no sense together\n"); } else { iflag = ON; addnetname(*argv); } while (*(++(*argv)+1)) ; break; default: fprintf(stderr, "timed: -%c: unknown option\n", **argv); break; } } while (*++(*argv)); } #ifndef DEBUG if (fork()) exit(0); { int s; for (s = getdtablesize(); s >= 0; --s) (void) close(s); (void) open("/dev/null", 0); (void) dup2(0, 1); (void) dup2(0, 2); s = open("/dev/tty", 2); if (s >= 0) { (void) ioctl(s, TIOCNOTTY, (char *)0); (void) close(s); } } #endif if (trace == ON) { fd = fopen(tracefile, "w"); setlinebuf(fd); fprintf(fd, "Tracing started on: %s\n\n", date()); } srvp = getservbyname("timed", "udp"); if (srvp == 0) { syslog(LOG_CRIT, "unknown service 'timed/udp'"); exit(1); } port = srvp->s_port; server.sin_port = srvp->s_port; server.sin_family = AF_INET; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) < 0) { syslog(LOG_ERR, "setsockopt: %m"); exit(1); } if (bind(sock, &server, sizeof(server))) { if (errno == EADDRINUSE) syslog(LOG_ERR, "server already running"); else syslog(LOG_ERR, "bind: %m"); exit(1); } /* choose a unique seed for random number generation */ (void)gettimeofday(&time, (struct timezone *)0); seed = time.tv_sec + time.tv_usec; srandom(seed); sequence = random(); /* initial seq number */ /* rounds kernel variable time to multiple of 5 ms. */ time.tv_sec = 0; time.tv_usec = -((time.tv_usec/1000) % 5) * 1000; (void)adjtime(&time, (struct timeval *)0); id = getpid(); if (gethostname(hostname, sizeof(hostname) - 1) < 0) { syslog(LOG_ERR, "gethostname: %m"); exit(1); } hp[0].name = hostname; if (nflag || iflag) { struct netent *getnetent(); struct netent *n; struct nets *np; for ( np = nets ; np ; np = np->next) { n = getnetbyname(np->name); if (n == NULL) { syslog(LOG_ERR, "getnetbyname: unknown net %s", np->name); exit(1); } np->net = n->n_net; } } ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { syslog(LOG_ERR, "get interface configuration: %m"); exit(1); } n = ifc.ifc_len/sizeof(struct ifreq); ntp = NULL; for (ifr = ifc.ifc_req; n > 0; n--, ifr++) { if (ifr->ifr_addr.sa_family != AF_INET) continue; ifreq = *ifr; if (ntp == NULL) ntp = (struct netinfo *)malloc(sizeof(struct netinfo)); ntp->my_addr = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get interface flags: %m"); continue; } if ((ifreq.ifr_flags & IFF_UP) == 0 || ((ifreq.ifr_flags & IFF_BROADCAST) == 0 && (ifreq.ifr_flags & IFF_POINTOPOINT) == 0)) { continue; } if (ifreq.ifr_flags & IFF_BROADCAST) flag = 1; else flag = 0; if (ioctl(sock, SIOCGIFNETMASK, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get netmask: %m"); continue; } ntp->mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; if (flag) { if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get broadaddr: %m"); continue; } ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_broadaddr; } else { if (ioctl(sock, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "get destaddr: %m"); continue; } ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_dstaddr; } ntp->dest_addr.sin_port = port; if (nflag || iflag) { u_long addr, mask; struct nets *n; addr = ntohl(ntp->dest_addr.sin_addr.s_addr); mask = ntohl(ntp->mask); while ((mask & 1) == 0) { addr >>= 1; mask >>= 1; } for (n = nets ; n ; n = n->next) if (addr == n->net) break; if (nflag && !n || iflag && n) continue; } ntp->net = ntp->mask & ntp->dest_addr.sin_addr.s_addr; ntp->next = NULL; if (nettab == NULL) { nettab = ntp; } else { ntip->next = ntp; } ntip = ntp; ntp = NULL; } if (ntp) (void) free((char *)ntp); if (nettab == NULL) { syslog(LOG_ERR, "No network usable"); exit(1); } for (ntp = nettab; ntp != NULL; ntp = ntp->next) lookformaster(ntp); setstatus(); /* * Take care of some basic initialization. */ /* us. delay to be used in response to broadcast */ delay1 = casual((long)10000, (long)200000); /* election timer delay in secs. */ delay2 = casual((long)MINTOUT, (long)MAXTOUT); if (Mflag) { /* open raw socket used to measure time differences */ sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sock_raw < 0) { syslog(LOG_ERR, "opening raw socket: %m"); exit (1); } /* * number (increased by 1) of slaves controlled by master: * used in master.c, candidate.c, networkdelta.c, and * correct.c */ slvcount = 1; ret = setjmp(jmpenv); switch (ret) { case 0: makeslave(firstslavenet()); setstatus(); break; case 1: /* Just lost our master */ setstatus(); slavenet->status = election(slavenet); checkignorednets(); setstatus(); if (slavenet->status == MASTER) makeslave(firstslavenet()); else makeslave(slavenet); setstatus(); break; case 2: /* Just been told to quit */ fromnet->status = SLAVE; setstatus(); savefromnet = fromnet; rmnetmachs(fromnet); checkignorednets(); if (slavenet) makeslave(slavenet); else makeslave(savefromnet); setstatus(); justquit = 1; break; default: /* this should not happen */ syslog(LOG_ERR, "Attempt to enter invalid state"); break; } if (status == MASTER) master(); else slave(); } else { /* if Mflag is not set timedaemon is forced to act as a slave */ status = SLAVE; if (setjmp(jmpenv)) { setstatus(); checkignorednets(); } makeslave(firstslavenet()); for (ntp = nettab; ntp != NULL; ntp = ntp->next) if (ntp->status == MASTER) ntp->status = IGNORE; setstatus(); slave(); } } /* * Try to become master over ignored nets.. */ checkignorednets() { register struct netinfo *ntp; for (ntp = nettab; ntp != NULL; ntp = ntp->next) if (ntp->status == IGNORE) lookformaster(ntp); } lookformaster(ntp) register struct netinfo *ntp; { struct tsp resp, conflict, *answer, *readmsg(), *acksend(); struct timeval time; char mastername[MAXHOSTNAMELEN]; struct sockaddr_in masteraddr; ntp->status = SLAVE; /* look for master */ resp.tsp_type = TSP_MASTERREQ; (void)strcpy(resp.tsp_name, hostname); answer = acksend(&resp, &ntp->dest_addr, (char *)ANYADDR, TSP_MASTERACK, ntp); if (answer == NULL) { /* * Various conditions can cause conflict: race between * two just started timedaemons when no master is * present, or timedaemon started during an election. * Conservative approach is taken: give up and became a * slave postponing election of a master until first * timer expires. */ time.tv_sec = time.tv_usec = 0; answer = readmsg(TSP_MASTERREQ, (char *)ANYADDR, &time, ntp); if (answer != NULL) { ntp->status = SLAVE; return; } time.tv_sec = time.tv_usec = 0; answer = readmsg(TSP_MASTERUP, (char *)ANYADDR, &time, ntp); if (answer != NULL) { ntp->status = SLAVE; return; } time.tv_sec = time.tv_usec = 0; answer = readmsg(TSP_ELECTION, (char *)ANYADDR, &time, ntp); if (answer != NULL) { ntp->status = SLAVE; return; } ntp->status = MASTER; } else { (void)strcpy(mastername, answer->tsp_name); masteraddr = from; /* * If network has been partitioned, there might be other * masters; tell the one we have just acknowledged that * it has to gain control over the others. */ time.tv_sec = 0; time.tv_usec = 300000; answer = readmsg(TSP_MASTERACK, (char *)ANYADDR, &time, ntp); /* * checking also not to send CONFLICT to ack'ed master * due to duplicated MASTERACKs */ if (answer != NULL && strcmp(answer->tsp_name, mastername) != 0) { conflict.tsp_type = TSP_CONFLICT; (void)strcpy(conflict.tsp_name, hostname); if (acksend(&conflict, &masteraddr, mastername, TSP_ACK, (struct netinfo *)NULL) == NULL) { syslog(LOG_ERR, "error on sending TSP_CONFLICT"); exit(1); } } } } /* * based on the current network configuration, set the status, and count * networks; */ setstatus() { register struct netinfo *ntp; status = 0; nmasternets = nslavenets = nnets = nignorednets = 0; if (trace) fprintf(fd, "Net status:\n"); for (ntp = nettab; ntp != NULL; ntp = ntp->next) { switch ((int)ntp->status) { case MASTER: nmasternets++; break; case SLAVE: nslavenets++; break; case IGNORE: nignorednets++; break; } if (trace) { fprintf(fd, "\t%-16s", inet_ntoa(ntp->net)); switch ((int)ntp->status) { case MASTER: fprintf(fd, "MASTER\n"); break; case SLAVE: fprintf(fd, "SLAVE\n"); break; case IGNORE: fprintf(fd, "IGNORE\n"); break; default: fprintf(fd, "invalid state %d\n"); break; } } nnets++; status |= ntp->status; } status &= ~IGNORE; if (trace) fprintf(fd, "\tnets = %d, masters = %d, slaves = %d, ignored = %d\n", nnets, nmasternets, nslavenets, nignorednets); } makeslave(net) struct netinfo *net; { register struct netinfo *ntp; for (ntp = nettab; ntp != NULL; ntp = ntp->next) if (ntp->status == SLAVE && ntp != net) ntp->status = IGNORE; slavenet = net; } struct netinfo * firstslavenet() { register struct netinfo *ntp; for (ntp = nettab; ntp != NULL; ntp = ntp->next) if (ntp->status == SLAVE) return (ntp); return ((struct netinfo *)0); } /* * `casual' returns a random number in the range [inf, sup] */ long casual(inf, sup) long inf; long sup; { float value; value = (float)(random() & 0x7fffffff) / 0x7fffffff; return(inf + (sup - inf) * value); } char * date() { char *ctime(); struct timeval tv; (void)gettimeofday(&tv, (struct timezone *)0); return (ctime(&tv.tv_sec)); } addnetname(name) char *name; { register struct nets **netlist = &nets; while (*netlist) netlist = &((*netlist)->next); *netlist = (struct nets *)malloc(sizeof **netlist); if (*netlist == (struct nets *)0) { syslog(LOG_ERR, "malloc failed"); exit(1); } bzero((char *)*netlist, sizeof(**netlist)); (*netlist)->name = name; } sizeof(struct ifreq); ntp = NULL; for (ifr = ifc.ifc_req; n > 0; n--, ifr++) { if (ifr->ifr_addr.sa_family != AF_INET) continue; ifreq = *ifr; if (ntp == NULL) ntp = (structetc/timed/timedc.c 440 0 12 10232 4103636610 7325 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)timedc.c 2.3 (Berkeley) 6/5/86"; #endif not lint #include "timedc.h" #include #include #include #include int top; int margc; int fromatty; char *margv[20]; char cmdline[200]; jmp_buf toplevel; int intr(); int priv_resources(); struct cmd *getcmd(); main(argc, argv) char *argv[]; { register struct cmd *c; openlog("timedc", LOG_ODELAY, LOG_AUTH); /* * security dictates! */ if (priv_resources() < 0) { fprintf(stderr, "Could not get priviledged resources\n"); exit(1); } (void) setuid(getuid()); if (--argc > 0) { c = getcmd(*++argv); if (c == (struct cmd *)-1) { printf("?Ambiguous command\n"); exit(1); } if (c == 0) { printf("?Invalid command\n"); exit(1); } if (c->c_priv && getuid()) { printf("?Privileged command\n"); exit(1); } (*c->c_handler)(argc, argv); exit(0); } fromatty = isatty(fileno(stdin)); top = setjmp(toplevel) == 0; if (top) (void) signal(SIGINT, intr); for (;;) { cmdscanner(top); top = 1; } } intr() { if (!fromatty) exit(0); longjmp(toplevel, 1); } extern struct cmd cmdtab[]; extern int help(); /* * Command parser. */ cmdscanner(top) int top; { register struct cmd *c; if (!top) putchar('\n'); for (;;) { if (fromatty) { printf("timedc> "); (void) fflush(stdout); } if (gets(cmdline) == 0) quit(); if (cmdline[0] == 0) break; makeargv(); c = getcmd(margv[0]); if (c == (struct cmd *)-1) { printf("?Ambiguous command\n"); continue; } if (c == 0) { printf("?Invalid command\n"); continue; } if (c->c_priv && getuid()) { printf("?Privileged command\n"); continue; } (*c->c_handler)(margc, margv); } longjmp(toplevel, 0); } struct cmd * getcmd(name) register char *name; { register char *p, *q; register struct cmd *c, *found; register int nmatches, longest; extern int NCMDS; longest = 0; nmatches = 0; found = 0; for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { p = c->c_name; for (q = name; *q == *p++; q++) if (*q == 0) /* exact match? */ return(c); if (!*q) { /* the name was a prefix */ if (q - name > longest) { longest = q - name; nmatches = 1; found = c; } else if (q - name == longest) nmatches++; } } if (nmatches > 1) return((struct cmd *)-1); return(found); } /* * Slice a string up into argc/argv. */ makeargv() { register char *cp; register char **argp = margv; margc = 0; for (cp = cmdline; *cp;) { while (isspace(*cp)) cp++; if (*cp == '\0') break; *argp++ = cp; margc += 1; while (*cp != '\0' && !isspace(*cp)) cp++; if (*cp == '\0') break; *cp++ = '\0'; } *argp++ = 0; } #define HELPINDENT (sizeof ("directory")) /* * Help command. */ help(argc, argv) int argc; char *argv[]; { register struct cmd *c; if (argc == 1) { register int i, j, w; int columns, width = 0, lines; extern int NCMDS; printf("Commands may be abbreviated. Commands are:\n\n"); for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { int len = strlen(c->c_name); if (len > width) width = len; } width = (width + 8) &~ 7; columns = 80 / width; if (columns == 0) columns = 1; lines = (NCMDS + columns - 1) / columns; for (i = 0; i < lines; i++) { for (j = 0; j < columns; j++) { c = cmdtab + j * lines + i; printf("%s", c->c_name); if (c + lines >= &cmdtab[NCMDS]) { printf("\n"); break; } w = strlen(c->c_name); while (w < width) { w = (w + 8) &~ 7; putchar('\t'); } } } return; } while (--argc > 0) { register char *arg; arg = *++argv; c = getcmd(arg); if (c == (struct cmd *)-1) printf("?Ambiguous help command %s\n", arg); else if (c == (struct cmd *)0) printf("?Invalid help command %s\n", arg); else printf("%-*s\t%s\n", HELPINDENT, c->c_name, c->c_help); } } and conditions for redistribution. */ #ifndef lint char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; #endif not lint #ifndef lint static char sccsid[] = "@(#)timedc.c 2.3 (Berkeley) 6/5/86"; #endif not lint #include "timedc.h" #include #include #include #incetc/timed/timedc.h 440 0 12 1461 5514436535 7331 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ /* @(#)timedc.h 2.1.1 (2.11BSD GTE) 1/1/94 */ #include #include #include #include #include #include #include #include extern int errno; #define ON 1 #define OFF 0 #define MSGS 6 #define TRIALS 5 #define GOOD 1 #define UNREACHABLE 2 #define NONSTDTIME 3 #ifdef pdp11 #define HOSTDOWN 0x7fff #else #define HOSTDOWN 0x7fffffff #endif struct cmd { char *c_name; /* command name */ char *c_help; /* help message */ int (*c_handler)(); /* routine to do the work */ int c_priv; /* privileged command */ }; iv_resources() < 0) { fprintf(stderr, "Could not get priviledged resources\n"); exit(1); } (void) setuid(getuid()); if (--argc > 0) { c = getcmd(*++argv); if (c == (struct cmd *)-1) { printf("etc/timed/pdp/ 770 0 12 0 4103633174 6401 etc/timed/pdp/cksum-fix 440 0 12 2475 4103626542 10325 /in_ckad/ .,.+1c / 1's comp add. sum = in_ckadd(a,b); mov (sp)+,r0 add (sp),r0 adc r0 . /in_ckbu/ .c / 1's complement checksum routine. assumes sum on entry is on logical even / byte boundary, even though entry address may be odd. / / r2 - 1's complement sum / r3 - number of bytes / r4 - byte address clr -(sp) /assume even start address bit $1,r4 beq 1f /if even starting address inc (sp) clr r0 bisb (r4)+,r0 /get byte at odd address add r0,r2 adc r2 swab r2 dec r3 /and adjust byte count 1: clr r1 /assume even byte count asr r3 /convert byte to word count adc r1 /set r1 if extra trailing odd byte tst r3 beq 4f /if no words left 2: add (r4)+,r2 /add into checksum adc r2 sob r3,2b /and process all of them 4: tst r1 /extra trailing byte? beq 3f /if not, exit clr r0 bisb (r4)+,r0 /get that extra byte add r0,r2 /and include in the checksum adc r2 3: tst (sp)+ beq 5f /if starting address not odd swab r2 5: . w q signal(SIGINT, intr); for (;;) { cmdscanner(top); top = 1; } } intr() { if (!fromatty) exit(0); longjmp(toplevel, 1); } extern struct cmd cmdtab[]; extern int help(); /* * Command paetc/timed/pdp/cksum.c 440 0 12 1522 4103634735 7755 /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)cksum.c 2.1 (Berkeley) 6/6/86"; #endif not lint #include "../globals.h" #include /* computes the checksum for ip packets for a pdp-11 base computer */ in_cksum(w, mlen) register u_char *w; /* known to be r4 */ register u_int mlen; /* known to be r3 */ { register u_int sum = 0; /* known to be r2 */ if (mlen > 0) { if (mlen & 01) { /* * The segment is an odd length, add the high * order byte into the checksum. */ sum = in_ckadd(sum,(*w++ << 8)); mlen--; } if (mlen > 0) in_ckbuf(); /* arguments already in registers */ } return (~sum); } /if no words left 2: add (r4)+,r2 /add into checksum adc r2 sob r3,2b /and process all of them 4: tst r1 etc/timed/tags 440 0 12 4034 4104070123 6550 C readmsg.c /^#define C(x) ((x)&0xff)$/ LOOKAT readmsg.c /^#define LOOKAT(msg, mtype, mfrom, netp, froms) \\$/ MORETIME readmsg.c /^#define MORETIME(rtime, rtout) \\$/ Mtimed timed.c /^main(argc, argv)$/ Mtimedc timedc.c /^main(argc, argv)$/ acksend acksend.c /^struct tsp *acksend(message, addr, name, ack, net)/ addmach master.c /^addmach(name, addr)$/ addnetname timed.c /^addnetname(name)$/ adjclock correct.c /^adjclock(corr)$/ answerdelay slave.c /^answerdelay()$/ bytehostorder byteorder.c /^bytehostorder(ptr)$/ bytenetorder byteorder.c /^bytenetorder(ptr)$/ casual timed.c /^casual(inf, sup)$/ checkignorednets timed.c /^checkignorednets()$/ clockdiff cmds.c /^clockdiff(argc, argv)$/ cmdscanner timedc.c /^cmdscanner(top)$/ correct correct.c /^correct(avdelta)$/ date timed.c /^date()$/ election candidate.c /^election(net)$/ findhost master.c /^findhost(name)$/ firstslavenet timed.c /^firstslavenet()$/ getcmd timedc.c /^getcmd(name)$/ help timedc.c /^help(argc, argv)$/ ignoreack readmsg.c /^ignoreack()$/ intr timedc.c /^intr()$/ logwtmp master.c /^logwtmp(otime, ntime)$/ lookformaster timed.c /^lookformaster(ntp)$/ makeargv timedc.c /^makeargv()$/ makeslave timed.c /^makeslave(net)$/ master master.c /^master()$/ masterack readmsg.c /^masterack()$/ masterup master.c /^masterup(net)$/ measure measure.c /^measure(wait, addr)$/ msite cmds.c /^msite(argc)$/ mstotvround correct.c /^struct timeval mstotvround(x)$/ networkdelta networkdelta.c /^long networkdelta()$/ newslave master.c /^newslave(ind, seq)$/ print readmsg.c /^print(msg, addr)$/ priv_resources cmds.c /^priv_resources()$/ prthp master.c /^prthp()$/ quit cmds.c /^quit()$/ readmsg readmsg.c /^readmsg(type, machfrom, intvl, netfrom)$/ rmmach master.c /^rmmach(ind)$/ rmnetmachs master.c /^rmnetmachs(ntp)$/ setstatus timed.c /^setstatus()$/ slave slave.c /^slave()$/ slaveack readmsg.c /^slaveack()$/ spreadtime master.c /^spreadtime()$/ synch master.c /^synch(mydelta)$/ testing cmds.c /^testing(argc, argv)$/ timevaladd correct.c /^timevaladd(tv1, tv2)$/ tracing cmds.c /^tracing(argc, argv)$/ margv); } longjmp(toplevel, 0); } struct cmd * getcmd(name) register char *name; { register char *p, *q; register struct cmd *c, *found; register int nmatches, longest; extern int NCMDS; longest = 0; nmatches = 0; found = 0; for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { p = c->c_name; for (q = name; *q == *p++; q++) if (*q == 0) /* exact match? */ return(c); if (!*q) { /* the name was a prefix */ if (q - name > longest) { longest = q - name; etc/XNSrouted/ 750 0 12 0 6024536100 6400 etc/XNSrouted/Makefile 440 0 12 1041 4020215176 10121 # # Copyright (c) 1983 Regents of the University of California. # All rights reserved. The Berkeley software License Agreement # specifies the terms and conditions for redistribution. # # @(#)Makefile 5.5 (Berkeley) 9/17/85"; # # Makefile for Xerox Routing Information Protocol # Daemon # ALL= XNSrouted OBJS= XNSrouted.o CFLAGS= -O SEPFLAG= -i all: ${ALL} XNSrouted: ${OBJS} ${CC} ${SEPFLAG} -o XNSrouted ${OBJS} install: XNSrouted install -s XNSrouted ${DESTDIR}/etc clean: rm -f XNSrouted *.o core a.out t.c linterrs typescript errs /^bytenetorder(ptr)$/ casual timed.c /^casual(iþƒ, sup)$/ checkignorednets timed.c /^checkignorednets()$/ clockdiff cmds.c /^clockdiff(argc, argv)$/ cmdscanner timedc.c /^cmdscanner(top)$/ correct correct.c /^correct(avdelta)$/ date timed.c /^date()$/ election candidate.c /^election(net)$/ findhost master.c /^findhost(name)$/ firstslavenet timed.c /^firstslavenet()$/ getcmd timedc.c /^getcmd(name)$/ help timedc.c /^help(argc, argv)$/ ignoreack readmsg.c /^ignoreack()$/ intr etc/XNSrouted/XNSrouted.c 440 0 12 121 5133425562 10506 main() { puts("XNSrouted hasn't been implemented under 2.11BSD."); exit(-1); } etc/named/ 755 0 12 0 5367120236 5606 etc/named/tools/ 755 0 0 0 6024523034 6715 etc/named/tools/nslookup/ 755 0 0 0 6024536050 10571 etc/named/tools/nslookup/commands.l 644 0 0 12036 5367001751 12662 %{ /*- * Copyright (c) 1985 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)commands.l 5.13 (Berkeley) 7/24/90"; #endif /* ******************************************************************************* * * commands.l * * Andrew Cherenson CS298-26 Fall 1985 * * Lex input file for the nslookup program command interpreter. * When a sequence is recognized, the associated action * routine is called. The action routine may need to * parse the string for additional information. * * Recognized commands: (identifiers are shown in uppercase) * * server NAME - set default server to NAME, using default server * lserver NAME - set default server to NAME, using initial server * finger [NAME] - finger the optional NAME * exit - exit the program * root - set default server to the root * ls NAME - list the domain NAME * view FILE - sorts and view the file with more * set OPTION - set an option * help - print help information * ? - print help information * NAME - print info about the host/domain NAME * using default server. * NAME1 NAME2 - as above, but use NAME2 as server * * * yylex Results: * 0 upon end-of-file. * 1 after each command. * ******************************************************************************* */ #include "res.h" extern char rootServerName[]; %} WS [ \t] FLET [A-Za-z0-9.*\\] LET [A-Za-z0-9.*] NAME [A-Za-z0-9.*=_/-] %% ^{WS}*server{WS}+{LET}{NAME}*{WS}*$ { /* * 0 == use current server to find * the new one. * 1 == use original server to find * the new one. */ SetDefaultServer(yytext, 0); return(1); } ^{WS}*lserver{WS}+{LET}{NAME}*{WS}*$ { SetDefaultServer(yytext, 1); return(1); } ^{WS}*exit{WS}*$ { return(0); } ^{WS}*root{WS}*$ { SetDefaultServer(rootServerName, 1); return(1); } ^{WS}*finger({WS}+{LET}{NAME}*)?{WS}+>>?{WS}*{NAME}+{WS}*$ { /* * 2nd arg. * 0 == output to stdout * 1 == output to file */ Finger(yytext, 1); return(1); } ^{WS}*finger({WS}+{LET}{NAME}*)?{WS}*$ { Finger(yytext, 0); return(1); } ^{WS}*view{WS}+{NAME}+{WS}*$ { ViewList(yytext); return(1); } ^{WS}*ls{WS}+(("-a"|"-d"|"-h"|"-m"|"-s"){WS}+)?{LET}{NAME}*{WS}+>>?{WS}+{NAME}+{WS}*$ { /* * 2nd arg. * 0 == output to stdout * 1 == output to file */ ListHosts(yytext, 1); return(1); } ^{WS}*ls{WS}+(("-a"|"-d"|"-h"|"-m"|"-s"){WS}+)?{LET}{NAME}*{WS}*$ { ListHosts(yytext, 0); return(1); } ^{WS}*ls{WS}+-t{WS}+({LET}{NAME}*{WS}+)?{LET}{NAME}*{WS}+>>?{WS}+{NAME}+{WS}*$ { /* * 2nd arg. * 0 == output to stdout * 1 == output to file */ ListHostsByType(yytext, 1); return(1); } ^{WS}*ls{WS}+-t{WS}+({LET}{NAME}*{WS}+)?{LET}{NAME}*{WS}*$ { ListHostsByType(yytext, 0); return(1); } ^{WS}*set{WS}+{NAME}+{WS}*$ { SetOption(yytext); return(1); } ^{WS}*help{WS}*$ { extern void PrintHelp(); PrintHelp(); return(1); } ^{WS}*"?"{WS}*$ { PrintHelp(); return(1); } ^{WS}*{FLET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ { /* * 0 == output to stdout * 1 == output to file */ LookupHost(yytext, 1); return(1); } ^{WS}*{FLET}{NAME}*{WS}*$ { LookupHost(yytext, 0); return(1); } ^{WS}*{FLET}{NAME}*{WS}+{LET}{NAME}*{WS}+>>?{WS}*{NAME}+{WS}*$ { /* * 0 == output to stdout * 1 == output to file */ LookupHostWithServer(yytext, 1); return(1); } ^{WS}*{FLET}{NAME}*{WS}+{LET}{NAME}*{WS}*$ { LookupHostWithServer(yytext, 0); return(1); } ^{WS}*\n { return(1); } ^.*\n { printf("Unrecognized command: %s", yytext); return(1); } \n { ; } %% truct nets **netlist = &nets; while (*netlist) netlist = &((*netlist)->next); *netlist = (struct nets *)malloc(sizeof **netlist); if (*netlist == (struct nets *)0) { syslog(LOG_ERR, "malloc failed"); exit(1); } bzero((char *)*netlist, sizeof(**netlist)); (*netlist)->name = name; } sizeof(struct ifreq); ntp = NULL; for (ifr = ifc.ifc_req; n > 0; n--, ifr++) { if (ifr->ifr_addr.sa_family != AF_INET) continue; ifreq = *ifr; if (ntp == NULL) ntp = (structetc/named/tools/nslookup/Makefile 644 0 0 3256 5367006423 12331 # # Copyright (c) 1987 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that the above copyright notice and this paragraph are # duplicated in all such forms and that any documentation, # advertising materials, and other materials related to such # distribution and use acknowledge that the software was developed # by the University of California, Berkeley. The name of the # University may not be used to endorse or promote products derived # from this software without specific prior written permission. # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # @(#)Makefile 5.20 (Berkeley) 10/2/89 # CFLAGS= -O RES= LIBC= /lib/libc.a LIBS= -ll ${RES} CSRCS= main.c getinfo.c debug.c send.c skip.c list.c subr.c res_debug.c SRCS= ${CSRCS} commands.c OBJS= main.o getinfo.o debug.o send.o skip.o list.o subr.o commands.o \ res_debug.o all: nslookup nslookup.0 nslookup: ${OBJS} ${LIBC} ${CC} -i -o $@ ${OBJS} ${LIBS} clean: rm -f ${OBJS} core nslookup nslookup.0 commands.c lex.yy.c lex.yy.o cleandir: clean rm -f tags .depend depend: ${SRCS} mkdep ${CFLAGS} ${SRCS} install: nslookup nslookup.0 install -s -o bin -g bin -m 755 nslookup ${DESTDIR}/usr/bin/nslookup install -c -o bin -g bin -m 444 nslookup.help ${DESTDIR}/usr/lib/nslookup.help install -c -o bin -g bin -m 444 nslookup.0 ${DESTDIR}/usr/man/cat1/nslookup.0 nslookup.0: nslookup.8 /usr/man/manroff nslookup.8 > nslookup.0 lint: ${SRCS} lint -ax ${SRCS} tags: ${CSRCS} ctags ${CSRCS} - finger the optional NAME * exit - exit the program * root - set default server to the root * ls NAME - list the domain NAME * view FILE - sorts and view the file with more * set OPTION - set an option * help - print help information * ? - print help information * NAME - print info about the host/domain NAME * usingetc/named/tools/nslookup/subr.c 644 0 0 27251 5367011145 12026 /* * Copyright (c) 1985,1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)subr.c 5.22 (Berkeley) 8/3/90"; #endif /* ******************************************************************************* * * subr.c -- * * Miscellaneous subroutines for the name server * lookup program. * * Copyright (c) 1985 * Andrew Cherenson * U.C. Berkeley * CS298-26 Fall 1985 * ******************************************************************************* */ #include #include #include #include #include #include #include #include #include #include #include "res.h" /* ******************************************************************************* * * IntrHandler -- * * This routine is called whenever a control-C is typed. * It performs three main functions: * - closes an open socket connection, * - closes an open output file (used by LookupHost, et al.), * - jumps back to the main read-eval loop. * * If a user types a ^C in the middle of a routine that uses a socket, * the routine would not be able to close the socket. To prevent an * overflow of the process's open file table, the socket and output * file descriptors are closed by the interrupt handler. * * Side effects: * Open file descriptors are closed. * If filePtr is valid, it is closed. * Flow of control returns to the main() routine. * ******************************************************************************* */ #ifdef SVR3 void #else int #endif IntrHandler() { extern jmp_buf env; #if defined(BSD) && BSD >= 199006 extern FILE *yyin; /* scanner input file */ extern void yyrestart(); /* routine to restart scanner after interrupt */ #endif SendRequest_close(); ListHost_close(); if (filePtr != NULL && filePtr != stdout) { fclose(filePtr); filePtr = NULL; } printf("\n"); #if defined(BSD) && BSD >= 199006 yyrestart(yyin); #endif longjmp(env, 1); } /* ******************************************************************************* * * Malloc -- * Calloc -- * * Calls the malloc library routine with SIGINT blocked to prevent * corruption of malloc's data structures. We need to do this because * a control-C doesn't kill the program -- it causes a return to the * main command loop. * * NOTE: This method doesn't prevent the pointer returned by malloc * from getting lost, so it is possible to get "core leaks". * * If malloc fails, the program exits. * * Results: * (address) - address of new buffer. * ******************************************************************************* */ char * Malloc(size) int size; { char *ptr; #ifdef SYSV #ifdef SVR3 sighold(SIGINT); ptr = malloc((unsigned) size); sigrelse(SIGINT); #else { int (*old)(); old = signal(SIGINT, SIG_IGN); ptr = malloc((unsigned) size); signal(SIGINT, old); } #endif #else { long saveMask; saveMask = sigblock(sigmask(SIGINT)); ptr = (char *)malloc((unsigned) size); (void) sigsetmask(saveMask); } #endif if (ptr == NULL) { fflush(stdout); fprintf(stderr, "*** Can't allocate memory\n"); fflush(stderr); abort(); /*NOTREACHED*/ } else { return(ptr); } } char * Calloc(num, size) register int num, size; { char *ptr = Malloc(num*size); bzero(ptr, num*size); return(ptr); } /* ******************************************************************************* * * PrintHostInfo -- * * Prints out the HostInfo structure for a host. * ******************************************************************************* */ void PrintHostInfo(file, title, hp) FILE *file; char *title; register HostInfo *hp; { register char **cp; register ServerInfo **sp; char comma; int i; fprintf(file, "%-7s %s", title, hp->name); if (hp->addrList != NULL) { if (hp->addrList[1] != NULL) { fprintf(file, "\nAddresses:"); } else { fprintf(file, "\nAddress:"); } comma = ' '; i = 0; for (cp = hp->addrList; cp && *cp; cp++) { i++; if (i > 4) { fprintf(file, "\n\t"); comma = ' '; i = 0; } fprintf(file,"%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); comma = ','; } } if (hp->aliases != NULL) { fprintf(file, "\nAliases:"); comma = ' '; i = 10; for (cp = hp->aliases; cp && *cp && **cp; cp++) { i += strlen(*cp) + 2; if (i > 75) { fprintf(file, "\n\t"); comma = ' '; i = 10; } fprintf(file, "%c %s", comma, *cp); comma = ','; } } if (hp->servers != NULL) { fprintf(file, "\nServed by:\n"); for (sp = hp->servers; *sp != NULL ; sp++) { fprintf(file, "- %s\n\t", (*sp)->name); comma = ' '; i = 0; for (cp = (*sp)->addrList; cp && *cp && **cp; cp++) { i++; if (i > 4) { fprintf(file, "\n\t"); comma = ' '; i = 0; } fprintf(file, "%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); comma = ','; } fprintf(file, "\n\t"); comma = ' '; i = 10; for (cp = (*sp)->domains; cp && *cp && **cp; cp++) { i += strlen(*cp) + 2; if (i > 75) { fprintf(file, "\n\t"); comma = ' '; i = 10; } fprintf(file, "%c %s", comma, *cp); comma = ','; } fprintf(file, "\n"); } } fprintf(file, "\n\n"); } /* ******************************************************************************* * * OpenFile -- * * Parses a command string for a file name and opens * the file. * * Results: * file pointer - the open was successful. * NULL - there was an error opening the file or * the input string was invalid. * ******************************************************************************* */ FILE * OpenFile(string, file) char *string; char *file; { char *redirect; FILE *tmpPtr; /* * Open an output file if we see '>' or >>'. * Check for overwrite (">") or concatenation (">>"). */ redirect = strchr(string, '>'); if (redirect == NULL) { return(NULL); } if (redirect[1] == '>') { sscanf(redirect, ">> %s", file); tmpPtr = fopen(file, "a+"); } else { sscanf(redirect, "> %s", file); tmpPtr = fopen(file, "w"); } if (tmpPtr != NULL) { redirect[0] = '\0'; } return(tmpPtr); } /* ******************************************************************************* * * DecodeError -- * * Converts an error code into a character string. * ******************************************************************************* */ char * DecodeError(result) int result; { switch (result) { case NOERROR: return("Success"); break; case FORMERR: return("Format error"); break; case SERVFAIL: return("Server failed"); break; case NXDOMAIN: return("Non-existent domain"); break; case NOTIMP: return("Not implemented"); break; case REFUSED: return("Query refused"); break; case NOCHANGE: return("No change"); break; case TIME_OUT: return("Timed out"); break; case NO_INFO: return("No information"); break; case ERROR: return("Unspecified error"); break; case NONAUTH: return("Non-authoritative answer"); break; case NO_RESPONSE: return("No response from server"); break; default: break; } return("BAD ERROR VALUE"); } int StringToClass(class, dflt) char *class; int dflt; { if (strcasecmp(class, "IN") == 0) return(C_IN); if (strcasecmp(class, "HESIOD") == 0 || strcasecmp(class, "HS") == 0) return(C_HS); if (strcasecmp(class, "CHAOS") == 0) return(C_CHAOS); if (strcasecmp(class, "ANY") == 0) return(C_ANY); fprintf(stderr, "unknown query class: %s\n", class); return(dflt); } /* ******************************************************************************* * * StringToType -- * * Converts a string form of a query type name to its * corresponding integer value. * ******************************************************************************* */ int StringToType(type, dflt) char *type; int dflt; { if (strcasecmp(type, "A") == 0) return(T_A); if (strcasecmp(type, "NS") == 0) return(T_NS); /* authoritative server */ if (strcasecmp(type, "MX") == 0) return(T_MX); /* mail exchanger */ if (strcasecmp(type, "CNAME") == 0) return(T_CNAME); /* canonical name */ if (strcasecmp(type, "SOA") == 0) return(T_SOA); /* start of authority zone */ if (strcasecmp(type, "MB") == 0) return(T_MB); /* mailbox domain name */ if (strcasecmp(type, "MG") == 0) return(T_MG); /* mail group member */ if (strcasecmp(type, "MR") == 0) return(T_MR); /* mail rename name */ if (strcasecmp(type, "WKS") == 0) return(T_WKS); /* well known service */ if (strcasecmp(type, "PTR") == 0) return(T_PTR); /* domain name pointer */ if (strcasecmp(type, "HINFO") == 0) return(T_HINFO); /* host information */ if (strcasecmp(type, "MINFO") == 0) return(T_MINFO); /* mailbox information */ if (strcasecmp(type, "AXFR") == 0) return(T_AXFR); /* zone transfer */ if (strcasecmp(type, "MAILA") == 0) return(T_MAILA); /* mail agent */ if (strcasecmp(type, "MAILB") == 0) return(T_MAILB); /* mail box */ if (strcasecmp(type, "ANY") == 0) return(T_ANY); /* matches any type */ if (strcasecmp(type, "UINFO") == 0) return(T_UINFO); /* user info */ if (strcasecmp(type, "UID") == 0) return(T_UID); /* user id */ if (strcasecmp(type, "GID") == 0) return(T_GID); /* group id */ if (strcasecmp(type, "TXT") == 0) return(T_TXT); /* text */ fprintf(stderr, "unknown query type: %s\n", type); return(dflt); } /* ******************************************************************************* * * DecodeType -- * * Converts a query type to a descriptive name. * (A more verbose form of p_type.) * * ******************************************************************************* */ static char nbuf[20]; char * DecodeType(type) int type; { switch (type) { case T_A: return("address"); case T_NS: return("name server"); case T_CNAME: return("canonical name"); case T_SOA: return("start of authority"); case T_MB: return("mailbox"); case T_MG: return("mail group member"); case T_MR: return("mail rename"); case T_NULL: return("null"); case T_WKS: return("well-known service"); case T_PTR: return("domain name pointer"); case T_HINFO: return("host information"); case T_MINFO: return("mailbox information"); case T_MX: return("mail exchanger"); case T_TXT: return("text"); case T_UINFO: return("user information"); case T_UID: return("user ID"); case T_GID: return("group ID"); case T_AXFR: return("zone transfer"); case T_MAILB: return("mailbox-related data"); case T_MAILA: return("mail agent"); case T_ANY: return("\"any\""); default: (void) sprintf(nbuf, "%d", type); return (nbuf); } } rr); abort(); /*NOTREACHED*/ } else { return(ptr); } } char * Calloc(num, size) register int num, size; { char *ptr = Malloc(num*size); bzero(ptr, num*size); return(ptr); } /* ******************************************************************************* * * PrintHostInfo -- * * Prints out the HostInfo setc/named/tools/nslookup/debug.c 644 0 0 24162 5367011736 12145 /* * Copyright (c) 1985,1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)debug.c 5.22 (Berkeley) 6/29/90"; #endif /* ******************************************************************************* * * debug.c -- * * Routines to print out packets received from a name server query. * * Modified version of 4.3BSD BIND res_debug.c 5.30 6/27/90 * ******************************************************************************* */ #include #include #include #include #include #include #include #include "res.h" extern char ctime(); /* * Imported from res_debug.c */ extern char *_res_resultcodes[]; extern char *_res_opcodes[]; /* * Used to highlight the start of a record when printing it. */ #define INDENT " -> " /* * Print the contents of a query. * This is intended to be primarily a debugging routine. */ Print_query(msg, eom, printHeader) char *msg, *eom; int printHeader; { Fprint_query(msg, eom, printHeader,stdout); } Fprint_query(msg, eom, printHeader,file) char *msg, *eom; int printHeader; FILE *file; { register char *cp; register HEADER *hp; register int n; short class; short type; /* * Print header fields. */ hp = (HEADER *)msg; cp = msg + sizeof(HEADER); if (printHeader || (_res.options & RES_DEBUG2)) { fprintf(file," HEADER:\n"); fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]); fprintf(file,", id = %d", ntohs(hp->id)); fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]); fprintf(file,"\theader flags: "); if (hp->qr) { fprintf(file," response"); } else { fprintf(file," query"); } if (hp->aa) fprintf(file,", auth. answer"); if (hp->tc) fprintf(file,", truncation"); if (hp->rd) fprintf(file,", want recursion"); if (hp->ra) fprintf(file,", recursion avail."); if (hp->pr) fprintf(file,", primary"); fprintf(file,"\n\tquestions = %d", ntohs(hp->qdcount)); fprintf(file,", answers = %d", ntohs(hp->ancount)); fprintf(file,", authority records = %d", ntohs(hp->nscount)); fprintf(file,", additional = %d\n\n", ntohs(hp->arcount)); } /* * Print question records. */ if (n = ntohs(hp->qdcount)) { fprintf(file," QUESTIONS:\n"); while (--n >= 0) { fprintf(file,"\t"); cp = Print_cdname(cp, msg, eom, file); if (cp == NULL) return; type = _getshort(cp); cp += sizeof(u_short); class = _getshort(cp); cp += sizeof(u_short); fprintf(file,", type = %s", p_type(type)); fprintf(file,", class = %s\n", p_class(class)); } } /* * Print authoritative answer records */ if (n = ntohs(hp->ancount)) { fprintf(file," ANSWERS:\n"); while (--n >= 0) { fprintf(file, INDENT); cp = Print_rr(cp, msg, eom, file); if (cp == NULL) return; } } /* * print name server records */ if (n = ntohs(hp->nscount)) { fprintf(file," AUTHORITY RECORDS:\n"); while (--n >= 0) { fprintf(file, INDENT); cp = Print_rr(cp, msg, eom, file); if (cp == NULL) return; } } /* * print additional records */ if (n = ntohs(hp->arcount)) { fprintf(file," ADDITIONAL RECORDS:\n"); while (--n >= 0) { fprintf(file, INDENT); cp = Print_rr(cp, msg, eom, file); if (cp == NULL) return; } } fprintf(file,"\n------------\n"); } char * Print_cdname_sub(cp, msg, eom, file, format) char *cp, *msg, *eom; FILE *file; int format; { int n; char name[MAXDNAME]; extern char *strcpy(); if ((n = dn_expand(msg, eom, cp, name, sizeof(name))) < 0) return (NULL); if (name[0] == '\0') { (void) strcpy(name, "(root)"); } if (format) { fprintf(file, "%-30s", name); } else { fputs(name, file); } return (cp + n); } char * Print_cdname(cp, msg, eom, file) char *cp, *msg, *eom; FILE *file; { return(Print_cdname_sub(cp, msg, eom, file, 0)); } char * Print_cdname2(cp, msg, eom, file) char *cp, *msg, *eom; FILE *file; { return(Print_cdname_sub(cp, msg, eom, file, 1)); } /* * Print resource record fields in human readable form. */ char * Print_rr(cp, msg, eom, file) char *cp, *msg, *eom; FILE *file; { int type, class, dlen, n, c; u_long rrttl, ttl; struct in_addr inaddr; char *cp1, *cp2; long debug; if ((cp = Print_cdname(cp, msg, eom, file)) == NULL) { fprintf(file, "(name truncated?)\n"); return (NULL); /* compression error */ } type = _getshort(cp); cp += sizeof(u_short); class = _getshort(cp); cp += sizeof(u_short); rrttl = _getlong(cp); cp += sizeof(u_long); dlen = _getshort(cp); cp += sizeof(u_short); debug = _res.options & (RES_DEBUG|RES_DEBUG2); if (debug) { if (_res.options & RES_DEBUG2) { fprintf(file,"\n\ttype = %s, class = %s, dlen = %d", p_type(type), p_class(class), dlen); } if (type == T_SOA) { fprintf(file,"\n\tttl = %ld (%s)", rrttl, p_time(rrttl)); } (void) putc('\n', file); } cp1 = cp; /* * Print type specific data, if appropriate */ switch (type) { case T_A: switch (class) { case C_IN: case C_HS: bcopy(cp, (char *)&inaddr, sizeof(inaddr)); if (dlen == 4) { fprintf(file,"\tinternet address = %s\n", inet_ntoa(inaddr)); cp += dlen; } else if (dlen == 7) { fprintf(file,"\tinternet address = %s", inet_ntoa(inaddr)); fprintf(file,", protocol = %d", cp[4]); fprintf(file,", port = %d\n", (cp[5] << 8) + cp[6]); cp += dlen; } break; default: fprintf(file,"\taddress, class = %d, len = %d\n", class, dlen); cp += dlen; } break; case T_CNAME: fprintf(file,"\tcanonical name = "); goto doname; case T_MG: fprintf(file,"\tmail group member = "); goto doname; case T_MB: fprintf(file,"\tmail box = "); goto doname; case T_MR: fprintf(file,"\tmailbox rename = "); goto doname; case T_MX: fprintf(file,"\tpreference = %u",_getshort(cp)); cp += sizeof(u_short); fprintf(file,", mail exchanger = "); goto doname; case T_NS: fprintf(file,"\tnameserver = "); goto doname; case T_PTR: fprintf(file,"\tname = "); doname: cp = Print_cdname(cp, msg, eom, file); (void) putc('\n', file); break; case T_HINFO: if (n = *cp++) { fprintf(file,"\tCPU = %.*s", n, cp); cp += n; } if (n = *cp++) { fprintf(file,"\tOS = %.*s\n", n, cp); cp += n; } break; case T_SOA: if (!debug) (void) putc('\n', file); fprintf(file,"\torigin = "); cp = Print_cdname(cp, msg, eom, file); fprintf(file,"\n\tmail addr = "); cp = Print_cdname(cp, msg, eom, file); fprintf(file,"\n\tserial = %ld", _getlong(cp)); cp += sizeof(u_long); ttl = _getlong(cp); fprintf(file,"\n\trefresh = %ld (%s)", ttl, p_time(ttl)); cp += sizeof(u_long); ttl = _getlong(cp); fprintf(file,"\n\tretry = %ld (%s)", ttl, p_time(ttl)); cp += sizeof(u_long); ttl = _getlong(cp); fprintf(file,"\n\texpire = %ld (%s)", ttl, p_time(ttl)); cp += sizeof(u_long); ttl = _getlong(cp); fprintf(file,"\n\tminimum ttl = %ld (%s)\n", ttl, p_time(ttl)); cp += sizeof(u_long); break; case T_MINFO: if (!debug) (void) putc('\n', file); fprintf(file,"\trequests = "); cp = Print_cdname(cp, msg, eom, file); fprintf(file,"\n\terrors = "); cp = Print_cdname(cp, msg, eom, file); (void) putc('\n', file); break; case T_TXT: (void) fputs("\ttext = \"", file); cp2 = cp1 + dlen; while (cp < cp2) { if (n = (unsigned char) *cp++) { for (c = n; c > 0 && cp < cp2; c--) if (*cp == '\n') { (void) putc('\\', file); (void) putc(*cp++, file); } else (void) putc(*cp++, file); } } (void) fputs("\"\n", file); break; case T_UINFO: fprintf(file,"\tuser info = %s\n", cp); cp += dlen; break; case T_UID: case T_GID: if (dlen == 4) { fprintf(file,"\t%cid = %ld\n",type == T_UID ? 'u' : 'g', _getlong(cp)); cp += sizeof(int); } else { fprintf(file,"\t%cid of length %d?\n", type == T_UID ? 'u' : 'g', dlen); cp += dlen; } break; case T_WKS: { struct protoent *protoPtr; if (dlen < sizeof(u_long) + 1) break; if (!debug) (void) putc('\n', file); bcopy(cp, (char *)&inaddr, sizeof(inaddr)); cp += sizeof(u_long); if ((protoPtr = getprotobynumber(*cp)) != NULL) { fprintf(file,"\tinet address = %s, protocol = %s\n\t", inet_ntoa(inaddr), protoPtr->p_name); } else { fprintf(file,"\tinet address = %s, protocol = %d\n\t", inet_ntoa(inaddr), *cp); } cp++; n = 0; while (cp < cp1 + dlen) { c = *cp++; do { struct servent *s; if (c & 0200) { s = getservbyport(n, (char *)NULL); if (s != NULL) { fprintf(file," %s", s->s_name); } else { fprintf(file," #%d", n); } } c <<= 1; } while (++n & 07); } putc('\n',file); } break; case T_NULL: fprintf(file, "\tNULL (dlen %d)\n", dlen); cp += dlen; break; default: fprintf(file,"\t??? unknown type %d ???\n", type); cp += dlen; } if (_res.options & RES_DEBUG && type != T_SOA) { fprintf(file,"\tttl = %ld (%s)\n", rrttl, p_time(rrttl)); } if (cp != cp1 + dlen) { fprintf(file, "\n*** Error: record size incorrect (%d != %d)\n\n", cp - cp1, dlen); cp = NULL; } return (cp); } = 0; } fprintf(file,"%c %s", comma, inet_ntoa(*(struct in_addr *)*cp)); comma = ','; } } if (hp->aliases != NULL) { fprintf(file, "\nAliases:"); comma = ' '; i = 10; for (cp = hp->aliases; cp && *cp && **cp; cp++) { i += strlen(*cp) + 2; if (i > 75) { fprintf(file, "\n\t"); comma = ' '; i = 10; } fprintf(file, "%c %s", comma, *cp); coetc/named/tools/nslookup/res.h 644 0 0 7467 5521655417 11650 /* * Copyright (c) 1985,1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)res.h 5.10.1 (2.11BSD GTE) 1/26/94 */ /* ******************************************************************************* * * res.h -- * * Definitions used by modules of the name server lookup program. * * Copyright (c) 1985 * Andrew Cherenson * U.C. Berkeley * CS298-26 Fall 1985 * ******************************************************************************* */ /* * This really doesn't belong here and can go away when newer resolver routines * and include files are ported over. */ #define MAXDFLSRCH 3 #define TRUE 1 #define FALSE 0 typedef int Boolean; /* * Define return statuses in addtion to the ones defined in namserv.h * let SUCCESS be a synonym for NOERROR * * TIME_OUT - a socket connection timed out. * NO_INFO - the server didn't find any info about the host. * ERROR - one of the following types of errors: * dn_expand, res_mkquery failed * bad command line, socket operation failed, etc. * NONAUTH - the server didn't have the desired info but * returned the name(s) of some servers who should. * NO_RESPONSE - the server didn't respond. * */ #define SUCCESS 0 #define TIME_OUT -1 #define NO_INFO -2 #define ERROR -3 #define NONAUTH -4 #define NO_RESPONSE -5 /* * Define additional options for the resolver state structure. * * RES_DEBUG2 more verbose debug level */ #define RES_DEBUG2 0x80000000 /* * Maximum length of server, host and file names. */ #define NAME_LEN 256 /* * Modified struct hostent from * * "Structures returned by network data base library. All addresses * are supplied in host order, and returned in network order (suitable * for use in system calls)." */ typedef struct { char *name; /* official name of host */ char **domains; /* domains it serves */ char **addrList; /* list of addresses from name server */ } ServerInfo; typedef struct { char *name; /* official name of host */ char **aliases; /* alias list */ char **addrList; /* list of addresses from name server */ int addrType; /* host address type */ int addrLen; /* length of address */ ServerInfo **servers; } HostInfo; /* * FilePtr is used for directing listings to a file. * It is global so the Control-C handler can close it. */ extern FILE *filePtr; /* * TCP/UDP port of server. */ extern unsigned short nsport; /* * External routines: */ extern Boolean IsAddr(); extern int Print_query(); extern char *Print_cdname(); extern char *Print_cdname2(); /* fixed width */ extern char *Print_rr(); extern char *DecodeType(); /* descriptive version of p_type */ extern char *DecodeError(); extern char *Calloc(); extern char *Malloc(); extern void NsError(); extern void PrintServer(); extern void PrintHostInfo(); extern void ShowOptions(); extern void FreeHostInfoPtr(); extern FILE *OpenFile(); extern char *res_skip(); extern char *getenv(); cid of length %d?\n", type == T_UID ? 'u' : 'g', dlen); cp += dlen; } break; case T_WKS: { struct protoent *protoPtr; if (dlen < sizeof(u_long) + 1) break; if (!debug) (etc/named/tools/nslookup/nslookup.8 644 0 0 27551 5367000103 12645 .\" Copyright (c) 1986,1990 Regents of the University of California. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms are permitted provided .\" that: (1) source distributions retain this entire copyright notice and .\" comment, and (2) distributions including binaries display the following .\" acknowledgement: ``This product includes software developed by the .\" University of California, Berkeley and its contributors'' in the .\" documentation or other materials provided with the distribution and in .\" all advertising materials mentioning features or use of this software. .\" Neither the name of the University nor the names of its contributors may .\" be used to endorse or promote products derived from this software without .\" specific prior written permission. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED .\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" .\" @(#)nslookup.8 5.3 (Berkeley) 6/24/90 .\" .TH NSLOOKUP 8 "June 24, 1990" .UC 6 .SH NAME nslookup \- query Internet name servers interactively .SH SYNOPSIS .B nslookup [ .I \-option ... ] [ .I host-to-find | \- [ .I server ]] .SH DESCRIPTION .I Nslookup is a program to query Internet domain name servers. Nslookup has two modes: interactive and non-interactive. Interactive mode allows the user to query name servers for information about various hosts and domains or to print a list of hosts in a domain. Non-interactive mode is used to print just the name and requested information for a host or domain. .sp 1 .SH ARGUMENTS Interactive mode is entered in the following cases: .IP a) 4 when no arguments are given (the default name server will be used), .IP b) 4 when the first argument is a hyphen (\-) and the second argument is the host name or Internet address of a name server. .LP Non-interactive mode is used when the name or Internet address of the host to be looked up is given as the first argument. The optional second argument specifies the host name or address of a name server. .LP The options listed under the ``set'' command below can be specified in the .nslookuprc file in the user's home directory if they are listed one per line. Options can also be specified on the command line if they precede the arguments and are prefixed with a hyphen. For example, to change the default query type to host information, and the initial timeout to 10 seconds, type: .sp .5v nslookup \-query=hinfo \-timeout=10 .sp .5v .SH "INTERACTIVE COMMANDS" Commands may be interrupted at any time by typing a control-C. To exit, type a control-D (EOF) or type exit. The command line length must be less than 256 characters. To treat a built-in command as a host name, precede it with an escape character (\e). \fBN.B.\fP an unrecognized command will be interpreted as a host name. .sp .5v .IP "\fIhost\fP [\fIserver\fP]" Look up information for \fIhost\fP using the current default server or using \fIserver\fP if specified. If \fIhost\fP is an Internet address and the query type is A or PTR, the name of the host is returned. If \fIhost\fP is a name and does not have a trailing period, the default domain name is appended to the name. (This behavior depends on the state of the \fBset\fP options \fBdomain\fP, \fBsrchlist\fP, \fBdefname\fP, and \fBsearch\fP). To look up a host not in the current domain, append a period to the name. .sp 1 .IP "\fBserver\fP \fIdomain\fP" .ns .IP "\fBlserver\fP \fIdomain\fP" Change the default server to \fIdomain\fP. \fBLserver\fP uses the initial server to look up information about \fIdomain\fP while \fBserver\fP uses the current default server. If an authoritative answer can't be found, the names of servers that might have the answer are returned. .sp 1 .IP \fBroot\fP Changes the default server to the server for the root of the domain name space. Currently, the host ns.internic.net is used. (This command is a synonym for \fBlserver ns.internic.net.\fP) The name of the root server can be changed with the \fBset root\fP command. .sp 1 .IP "\fBfinger\fP [\fIname\fP] [\fB>\fP \fIfilename\fP]" .ns .IP "\fBfinger\fP [\fIname\fP] [\fB>>\fP \fIfilename\fP]" Connects with the finger server on the current host. The current host is defined when a previous lookup for a host was successful and returned address information (see the \fBset querytype=A\fP command). \fIName\fP is optional. \fB>\fP and \fB>>\fP can be used to redirect output in the usual manner. .sp 1 .IP "\fBls\fR [\fIoption\fR] \fIdomain\fR [\fB>\fR \fIfilename\fR]" .ns .IP "\fBls\fR [\fIoption\fR] \fIdomain\fR [\fB>>\fR \fIfilename\fR]" List the information available for \fIdomain\fP, optionally creating or appending to \fIfilename\fP. The default output contains host names and their Internet addresses. .I Option can be one of the following: .RS .IP "\fB\-t \fIquerytype\fP" 4 lists all records of the specified type (see \fIquerytype\fP below). .IP \fB\-a\fP 4 lists aliases of hosts in the domain. synonym for \fB\-t\ \ CNAME\fP. .IP \fB\-d\fP 4 lists all records for the domain. synonym for \fB\-t\ \ ANY\fP. .IP \fB\-h\fP 4 lists CPU and operating system information for the domain. synonym for \fB\-t\ \ HINFO\fP. .IP \fB\-s\fP 4 lists well-known services of hosts in the domain. synonym for \fB\-t\ \ WKS\fP. .P When output is directed to a file, hash marks are printed for every 50 records received from the server. .RE .sp 1 .IP "\fBview\fP \fIfilename\fP" Sorts and lists the output of previous \fBls\fP command(s) with \fImore\fP(1). .sp 1 .ne 4 .IP "\fBhelp\fP" .ns .IP "\fB?\fP" Prints a brief summary of commands. .sp 1 .IP "\fBexit\fP" Exits the program. .sp 1 .IP "\fBset\fP \fIkeyword\fP[=\fIvalue\fP]" This command is used to change state information that affects the lookups. Valid keywords are: .RS .IP "\fBall\fP" Prints the current values of the frequently-used options to \fBset\fP. Information about the current default server and host is also printed. .IP "\fBclass=\fIvalue\fR" Change the query class to one of: .RS .IP IN 10 the Internet class. .IP CHAOS 10 the Chaos class. .IP HESIOD 10 the MIT Athena Hesiod class. .IP ANY 10 wildcard (any of the above). .P The class specifies the protocol group of the information. .br (Default = IN, abbreviation = cl) .RE .IP "\fB[no]debug\fP" Turn debugging mode on. A lot more information is printed about the packet sent to the server and the resulting answer. .br (Default = nodebug, abbreviation = [no]deb) .IP "\fB[no]d2\fP" Turn exhaustive debugging mode on. Essentially all fields of every packet are printed. .br (Default = nod2) .IP "\fBdomain=\fIname\fR" Change the default domain name to \fIname\fP. The default domain name is appended to a lookup request depending on the state of the \fBdefname\fP and \fBsearch\fP options. The domain search list contains the parents of the default domain if it has at least two components in its name. For example, if the default domain is CC.Berkeley.EDU, the search list is CC.Berkeley.EDU and Berkeley.EDU. Use the \fBset srchlist\fP command to specify a different list. Use the \fBset all\fP command to display the list. .br (Default = value from hostname, /etc/resolv.conf or LOCALDOMAIN, abbreviation = do) .IP "\fBsrchlist=\fIname1/name2/...\fR" Change the default domain name to \fIname1\fP and the domain search list to \fIname1\fP, \fIname2\fP, etc. A maximum of 6 names separated by slashes (/) can be specified. For example, .sp .5v set\ srchlist=lcs.MIT.EDU/ai.MIT.EDU/MIT.EDU .sp .5v sets the domain to lcs.MIT.EDU and the search list to the three names. This command overrides the default domain name and search list of the \fBset domain\fP command. Use the \fBset all\fP command to display the list. .br (Default = value based on hostname, /etc/resolv.conf or LOCALDOMAIN, abbreviation = srchl) .IP "\fB[no]defname\fP" If set, append the default domain name to a single-component lookup request (i.e., one that does not contain a period). .br (Default = defname, abbreviation = [no]def) .IP "\fB[no]search\fP" If the lookup request contains at least one period but doesn't end with a trailing period, append the domain names in the domain search list to the request until an answer is received. .br (Default = search, abbreviation = [no]sea) .IP "\fBport=\fIvalue\fR" Change the default TCP/UDP name server port to \fIvalue\fP. .br (Default = 53, abbreviation = po) .IP "\fBquerytype=\fIvalue\fR" .ns .IP "\fBtype=\fIvalue\fR" .ns Change the type of information query to one of: .RS .IP A 10 the host's Internet address. .IP CNAME 10 the canonical name for an alias. .IP HINFO 10 the host CPU and operating system type. .IP MINFO 10 the mailbox or mail list information. .IP MX 10 the mail exchanger. .IP NS 10 the name server for the named zone. .IP PTR 10 the host name if the query is an Internet address, otherwise the pointer to other information. .IP SOA 10 the domain's ``start-of-authority'' information. .IP TXT 10 the text information. .IP UINFO 10 the user information. .IP WKS 10 the supported well-known services. .P Other types (ANY, AXFR, MB, MD, MF, NULL) are described in the RFC-1035 document. .br (Default = A, abbreviations = q, ty) .RE .IP "\fB[no]recurse\fP" Tell the name server to query other servers if it does not have the information. .br (Default = recurse, abbreviation = [no]rec) .IP \fBretry=\fInumber\fR Set the number of retries to \fInumber\fP. When a reply to a request is not received within a certain amount of time (changed with \fBset timeout\fP), the timeout period is doubled and the request is resent. The retry value controls how many times a request is resent before giving up. .br (Default = 4, abbreviation = ret) .IP \fBroot=\fIhost\fR Change the name of the root server to \fIhost\fP. This affects the \fBroot\fP command. .br (Default = ns.internic.net., abbreviation = ro) .IP \fBtimeout=\fInumber\fR Change the initial timeout interval for waiting for a reply to \fInumber\fP seconds. Each retry doubles the timeout period. .br (Default = 5 seconds, abbreviation = ti) .IP "\fB[no]vc\fP" Always use a virtual circuit when sending requests to the server. .br (Default = novc, abbreviation = [no]v) .IP "\fB[no]ignoretc\fP" Ignore packet truncation errors. .br (Default = noignoretc, abbreviation = [no]ig) .RE .SH DIAGNOSTICS If the lookup request was not successful, an error message is printed. Possible errors are: .IP "Timed out" 5 The server did not respond to a request after a certain amount of time (changed with \fBset timeout=\fIvalue\fR) and a certain number of retries (changed with \fBset retry=\fIvalue\fR). .IP "No response from server" 5 No name server is running on the server machine. .IP "No records" 5 The server does not have resource records of the current query type for the host, although the host name is valid. The query type is specified with the \fBset querytype\fP command. .IP "Non-existent domain" 5 The host or domain name does not exist. .IP "Connection refused" 5 .ns .IP "Network is unreachable" 5 The connection to the name or finger server could not be made at the current time. This error commonly occurs with \fBls\fP and \fBfinger\fP requests. .IP "Server failure" 5 The name server found an internal inconsistency in its database and could not return a valid answer. .IP "Refused" 5 The name server refused to service the request. .IP "Format error" 5 The name server found that the request packet was not in the proper format. It may indicate an error in \fInslookup\fP. .sp 1 .SH FILES .ta \w'/usr/share/misc/nslookup.helpXXX'u /etc/resolv.conf initial domain name and name server addresses. .br $HOME/.nslookuprc user's initial options. .br /usr/share/misc/nslookup.help summary of commands. .SH ENVIRONMENT .ta \w'HOSTALIASESXXXX'u HOSTALIASES file containing host aliases. .br LOCALDOMAIN overrides default domain. .SH SEE ALSO resolver(3), resolver(5), named(8), .br RFC-1034 ``Domain Names \- Concepts and Facilities'' .br RFC-1035 ``Domain Names \- Implementation and Specification'' .SH AUTHOR Andrew Cherenson o change the default query type to host information, and the initial timeout to 10 seconds, type: .sp .5v nslookup \-query=hinfo \-timeout=10 .sp .5vetc/named/tools/nslookup/list.c 644 0 0 51202 5367001600 12012 /* * Copyright (c) 1985,1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)list.c 5.20 (Berkeley) 6/1/90"; #endif /* ******************************************************************************* * * list.c -- * * Routines to obtain info from name and finger servers. * * Adapted from 4.3BSD BIND ns_init.c and from finger.c. * ******************************************************************************* */ #include #include #include #include #include #include #include #include #include #include #include #include "res.h" /* * Imported from res_debug.c */ extern char *_res_resultcodes[]; extern int errno; typedef union { HEADER qb1; char qb2[PACKETSZ]; } querybuf; extern HostInfo *defaultPtr; extern HostInfo curHostInfo; extern int curHostValid; extern int queryType; extern int queryClass; static int sockFD = -1; static int ListSubr(); /* * During a listing to a file, hash marks are printed * every HASH_SIZE records. */ #define HASH_SIZE 50 /* ******************************************************************************* * * ListHosts -- * ListHostsByType -- * * Requests the name server to do a zone transfer so we * find out what hosts it knows about. * * For ListHosts, there are five types of output: * - Internet addresses (default) * - cpu type and operating system (-h option) * - canonical and alias names (-a option) * - well-known service names (-s option) * - ALL records (-d option) * ListHostsByType prints records of the default type or of a speicific * type. * * To see all types of information sorted by name, do the following: * ls -d domain.edu > file * view file * * Results: * SUCCESS the listing was successful. * ERROR the server could not be contacted because * a socket could not be obtained or an error * occured while receiving, or the output file * could not be opened. * ******************************************************************************* */ void ListHostsByType(string, putToFile) char *string; int putToFile; { int i, qtype, result; char *namePtr; char name[NAME_LEN]; char option[NAME_LEN]; /* * Parse the command line. It maybe of the form "ls -t domain" * or "ls -t type domain". */ i = sscanf(string, " ls -t %s %s", option, name); if (putToFile && i == 2 && name[0] == '>') { i--; } if (i == 2) { qtype = StringToType(option, -1); if (qtype == -1) return; namePtr = name; } else if (i == 1) { namePtr = option; qtype = queryType; } else { fprintf(stderr, "*** ls: invalid request %s\n",string); return; } result = ListSubr(qtype, namePtr, putToFile ? string : NULL); if (result != SUCCESS) fprintf(stderr, "*** Can't list domain %s: %s\n", namePtr, DecodeError(result)); } void ListHosts(string, putToFile) char *string; int putToFile; { int i, qtype, result; char *namePtr; char name[NAME_LEN]; char option[NAME_LEN]; /* * Parse the command line. It maybe of the form "ls domain", * "ls -X domain". */ i = sscanf(string, " ls %s %s", option, name); if (putToFile && i == 2 && name[0] == '>') { i--; } if (i == 2) { if (strcmp("-a", option) == 0) { qtype = T_CNAME; } else if (strcmp("-h", option) == 0) { qtype = T_HINFO; } else if (strcmp("-m", option) == 0) { qtype = T_MX; } else if (strcmp("-s", option) == 0) { qtype = T_WKS; } else if (strcmp("-d", option) == 0) { qtype = T_ANY; } else { qtype = T_A; } namePtr = name; } else if (i == 1) { namePtr = option; qtype = T_A; } else { fprintf(stderr, "*** ls: invalid request %s\n",string); return; } result = ListSubr(qtype, namePtr, putToFile ? string : NULL); if (result != SUCCESS) fprintf(stderr, "*** Can't list domain %s: %s\n", namePtr, DecodeError(result)); } static int ListSubr(qtype, domain, cmd) int qtype; char *domain; char *cmd; { querybuf buf; struct sockaddr_in sin; HEADER *headerPtr; int msglen; int amtToRead; int numRead; int numAnswers = 0; int result; int soacnt = 0; u_short len; char *cp, *nmp; char dname[2][NAME_LEN]; char file[NAME_LEN]; static char *answer = NULL; static int answerLen = 0; enum { NO_ERRORS, ERR_READING_LEN, ERR_READING_MSG, ERR_PRINTING, } error = NO_ERRORS; /* * Create a query packet for the requested domain name. */ msglen = res_mkquery(QUERY, domain, queryClass, T_AXFR, (char *)0, 0, (char *)0, (char *) &buf, sizeof(buf)); if (msglen < 0) { if (_res.options & RES_DEBUG) { fprintf(stderr, "*** ls: res_mkquery failed\n"); } return (ERROR); } bzero((char *)&sin, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(nsport); /* * Check to see if we have the address of the server or the * address of a server who knows about this domain. * * For now, just use the first address in the list. */ if (defaultPtr->addrList != NULL) { sin.sin_addr = *(struct in_addr *) defaultPtr->addrList[0]; } else { sin.sin_addr = *(struct in_addr *)defaultPtr->servers[0]->addrList[0]; } /* * Set up a virtual circuit to the server. */ if ((sockFD = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("ls: socket"); return(ERROR); } if (connect(sockFD, &sin, sizeof(sin)) < 0) { int e; if (errno == ECONNREFUSED) { e = NO_RESPONSE; } else { perror("ls: connect"); e = ERROR; } (void) close(sockFD); sockFD = -1; return e; } /* * Send length & message for zone transfer */ len = htons(msglen); if (write(sockFD, (char *)&len, sizeof(len)) != sizeof(len) || write(sockFD, (char *) &buf, msglen) != msglen) { perror("ls: write"); (void) close(sockFD); sockFD = -1; return(ERROR); } fprintf(stdout,"[%s]\n", (defaultPtr->addrList != NULL) ? defaultPtr->name : defaultPtr->servers[0]->name); if (cmd == NULL) { filePtr = stdout; } else { filePtr = OpenFile(cmd, file); if (filePtr == NULL) { fprintf(stderr, "*** Can't open %s for writing\n", file); (void) close(sockFD); sockFD = -1; return(ERROR); } fprintf(filePtr, "> %s\n", cmd); fprintf(filePtr,"[%s]\n", (defaultPtr->addrList != NULL) ? defaultPtr->name : defaultPtr->servers[0]->name); } #if 0 if (qtype == T_CNAME) { fprintf(filePtr, "%-30s", "Alias"); } else if (qtype == T_TXT) { fprintf(filePtr, "%-30s", "Key"); } else { fprintf(filePtr, "%-30s", "Host or domain name"); } switch (qtype) { case T_A: fprintf(filePtr, " %-30s\n", "Internet Address"); break; case T_HINFO: fprintf(filePtr, " %-30s\n", "CPU & OS"); break; case T_CNAME: fprintf(filePtr, " %-30s\n", "Canonical Name"); break; case T_MX: fprintf(filePtr, " %-30s\n", "Metric & Host"); break; case T_WKS: fprintf(filePtr, " %-4s %s\n", "Protocol", "Services"); break; case T_MB: fprintf(filePtr, " %-30s\n", "Mailbox"); break; case T_MG: fprintf(filePtr, " %-30s\n", "Mail Group"); break; case T_MR: fprintf(filePtr, " %-30s\n", "Mail Rename"); break; case T_MINFO: fprintf(filePtr, " %-30s\n", "Mail List Requests & Errors"); break; case T_UINFO: fprintf(filePtr, " %-30s\n", "User Information"); break; case T_UID: fprintf(filePtr, " %-30s\n", "User ID"); break; case T_GID: fprintf(filePtr, " %-30s\n", "Group ID"); break; case T_TXT: fprintf(filePtr, " %-30s\n", "Text"); break; case T_NS: fprintf(filePtr, " %-30s\n", "Name Servers"); break; case T_PTR: fprintf(filePtr, " %-30s\n", "Pointers"); break; case T_SOA: fprintf(filePtr, " %-30s\n", "Start of Authority"); break; case T_ANY: fprintf(filePtr, " %-30s\n", "Resource Record Info."); break; } #endif dname[0][0] = '\0'; while (1) { unsigned short tmp; /* * Read the length of the response. */ cp = (char *) &tmp; amtToRead = sizeof(u_short); while (amtToRead > 0 && (numRead=read(sockFD, cp, amtToRead)) > 0) { cp += numRead; amtToRead -= numRead; } if (numRead <= 0) { error = ERR_READING_LEN; break; } if ((len = htons(tmp)) == 0) { break; /* nothing left to read */ } /* * The server sent too much data to fit the existing buffer -- * allocate a new one. */ if (len > answerLen) { if (answerLen != 0) { free(answer); } answerLen = len; answer = Malloc(answerLen); } /* * Read the response. */ amtToRead = len; cp = answer; while (amtToRead > 0 && (numRead=read(sockFD, cp, amtToRead)) > 0) { cp += numRead; amtToRead -= numRead; } if (numRead <= 0) { error = ERR_READING_MSG; break; } result = PrintListInfo(filePtr, answer, cp, qtype, dname[0]); if (result != SUCCESS) { error = ERR_PRINTING; break; } numAnswers++; if (cmd != NULL && ((numAnswers % HASH_SIZE) == 0)) { fprintf(stdout, "#"); fflush(stdout); } cp = answer + sizeof(HEADER); if (ntohs(((HEADER* )answer)->qdcount) > 0) cp += dn_skipname(cp, answer + len) + QFIXEDSZ; nmp = cp; cp += dn_skipname(cp, (u_char *)answer + len); if ((_getshort(cp) == T_SOA)) { dn_expand(answer, answer + len, nmp, dname[soacnt], sizeof(dname[0])); if (soacnt) { if (strcmp(dname[0], dname[1]) == 0) break; } else soacnt++; } } if (cmd != NULL) { fprintf(stdout, "%sReceived %d record%s.\n", (numAnswers >= HASH_SIZE) ? "\n" : "", numAnswers, (numAnswers != 1) ? "s" : ""); } (void) close(sockFD); sockFD = -1; if (cmd != NULL && filePtr != NULL) { fclose(filePtr); filePtr = NULL; } switch (error) { case NO_ERRORS: return (SUCCESS); case ERR_READING_LEN: return(ERROR); case ERR_PRINTING: return(result); case ERR_READING_MSG: headerPtr = (HEADER *) answer; fprintf(stderr,"*** ls: error receiving zone transfer:\n"); fprintf(stderr, " result: %s, answers = %d, authority = %d, additional = %d\n", _res_resultcodes[headerPtr->rcode], ntohs(headerPtr->ancount), ntohs(headerPtr->nscount), ntohs(headerPtr->arcount)); return(ERROR); default: return(ERROR); } } /* ******************************************************************************* * * PrintListInfo -- * * Used by the ListInfo routine to print the answer * received from the name server. Only the desired * information is printed. * * Results: * SUCCESS the answer was printed without a problem. * NO_INFO the answer packet did not contain an answer. * ERROR the answer was malformed. * Misc. errors returned in the packet header. * ******************************************************************************* */ #define NAME_FORMAT " %-30s" static Boolean strip_domain(string, domain) char *string, *domain; { register char *dot; if (*domain != '\0') { dot = string; while ((dot = strchr(dot, '.')) != NULL && strcasecmp(domain, ++dot)) ; if (dot != NULL) { dot[-1] = '\0'; return TRUE; } } return FALSE; } PrintListInfo(file, msg, eom, qtype, domain) FILE *file; char *msg, *eom; int qtype; char *domain; { register char *cp; HEADER *headerPtr; int type, class, dlen, nameLen; u_long ttl; int n, pref; struct in_addr inaddr; char name[NAME_LEN]; char name2[NAME_LEN]; Boolean stripped; /* * Read the header fields. */ headerPtr = (HEADER *)msg; cp = msg + sizeof(HEADER); if (headerPtr->rcode != NOERROR) { return(headerPtr->rcode); } /* * We are looking for info from answer resource records. * If there aren't any, return with an error. We assume * there aren't any question records. */ if (ntohs(headerPtr->ancount) == 0) { return(NO_INFO); } else { if (ntohs(headerPtr->qdcount) > 0) { nameLen = dn_skipname(cp, eom); if (nameLen < 0) return (ERROR); cp += nameLen + QFIXEDSZ; } if ((nameLen = dn_expand(msg, eom, cp, name, sizeof(name))) < 0) return (ERROR); cp += nameLen; type = _getshort(cp); cp += sizeof(u_short); if (!(type == qtype || qtype == T_ANY) && !((type == T_NS || type == T_PTR) && qtype == T_A)) return(SUCCESS); class = _getshort(cp); cp += sizeof(u_short); ttl = _getlong(cp); cp += sizeof(u_long); dlen = _getshort(cp); cp += sizeof(u_short); if (name[0] == 0) strcpy(name, "(root)"); /* Strip the domain name from the data, if desired. */ stripped = FALSE; if ((_res.options & RES_DEBUG) == 0) { if (type != T_SOA) { stripped = strip_domain(name, domain); } } if (!stripped && nameLen < sizeof(name)-1) { strcat(name, "."); } fprintf(file, NAME_FORMAT, name); if (qtype == T_ANY) { if (_res.options & RES_DEBUG) { fprintf(file,"\t%lu %-5s", ttl, p_class(queryClass)); } fprintf(file," %-5s", p_type(type)); } /* XXX merge this into debug.c's print routines */ switch (type) { case T_A: if (class == C_IN) { bcopy(cp, (char *)&inaddr, sizeof(inaddr)); if (dlen == 4) { fprintf(file," %s", inet_ntoa(inaddr)); } else if (dlen == 7) { fprintf(file," %s", inet_ntoa(inaddr)); fprintf(file," (%d, %d)", cp[4],(cp[5] << 8) + cp[6]); } else fprintf(file, " (dlen = %d?)", dlen); } break; case T_CNAME: case T_MB: case T_MG: case T_MR: if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) { fprintf(file, " ***\n"); return (ERROR); } fprintf(file, " %s", name2); break; case T_NS: case T_PTR: putc(' ', file); if (qtype != T_ANY) fprintf(file,"%s = ", type == T_PTR ? "host" : "server"); cp = Print_cdname2(cp, msg, eom, file); break; case T_HINFO: if (n = *cp++) { (void)sprintf(name,"%.*s", n, cp); fprintf(file," %-10s", name); cp += n; } else { fprintf(file," %-10s", " "); } if (n = *cp++) { fprintf(file," %.*s", n, cp); cp += n; } break; case T_SOA: if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) { fprintf(file, " ***\n"); return (ERROR); } cp += nameLen; fprintf(file, " %s", name2); if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) { fprintf(file, " ***\n"); return (ERROR); } cp += nameLen; fprintf(file, " %s. (", name2); for (n = 0; n < 5; n++) { u_long u; u = _getlong(cp); cp += sizeof(u_long); fprintf(file,"%s%lu", n? " " : "", u); } fprintf(file, ")"); break; case T_MX: pref = _getshort(cp); cp += sizeof(u_short); fprintf(file," %-3d ",pref); if ((nameLen = dn_expand(msg, eom, cp, name2, sizeof(name2))) < 0) { fprintf(file, " ***\n"); return (ERROR); } fprintf(file, " %s", name2); break; case T_TXT: { char *cp2 = cp + dlen; int c; (void) fputs(" \"", file); while (cp < cp2) { if (n = (unsigned char) *cp++) { for (c = n; c > 0 && cp < cp2; c--) if (*cp == '\n') { (void) putc('\\', file); (void) putc(*cp++, file); } else (void) putc(*cp++, file); } } (void) putc('"', file); } break; case T_MINFO: (void) putc(' ', file); cp = Print_cdname(cp, msg, eom, file); fprintf(file, " "); cp = Print_cdname(cp, msg, eom, file); break; case T_UINFO: fprintf(file, " %s", cp); break; case T_UID: case T_GID: fprintf(file, " %lu", _getlong(cp)); break; case T_WKS: if (class == C_IN) { struct protoent *pp; struct servent *ss; u_short port; cp += 4; /* skip inet address */ dlen -= 4; setprotoent(1); setservent(1); n = *cp & 0377; pp = getprotobynumber(n); if (pp == 0) fprintf(file," %-3d ", n); else fprintf(file," %-3s ", pp->p_name); cp++; dlen--; port = 0; while (dlen-- > 0) { n = *cp++; do { if (n & 0200) { ss = getservbyport((int)htons(port), pp->p_name); if (ss == 0) fprintf(file," %u", port); else fprintf(file," %s", ss->s_name); } n <<= 1; } while (++port & 07); } endprotoent(); endservent(); } break; } fprintf(file,"\n"); } return(SUCCESS); } /* ******************************************************************************* * * ViewList -- * * A hack to view the output of the ls command in sorted * order using more. * ******************************************************************************* */ ViewList(string) char *string; { char file[NAME_LEN]; char command[NAME_LEN]; sscanf(string, " view %s", file); (void)sprintf(command, "grep \"^ \" %s | sort | more", file); system(command); } /* ******************************************************************************* * * Finger -- * * Connects with the finger server for the current host * to request info on the specified person (long form) * who is on the system (short form). * * Results: * SUCCESS the finger server was contacted. * ERROR the server could not be contacted because * a socket could not be obtained or connected * to or the service could not be found. * ******************************************************************************* */ Finger(string, putToFile) char *string; int putToFile; { struct servent *sp; struct sockaddr_in sin; register FILE *f; register int c; register int lastc; char name[NAME_LEN]; char file[NAME_LEN]; /* * We need a valid current host info to get an inet address. */ if (!curHostValid) { fprintf(stderr, "Finger: no current host defined.\n"); return (ERROR); } if (sscanf(string, " finger %s", name) == 1) { if (putToFile && (name[0] == '>')) { name[0] = '\0'; } } else { name[0] = '\0'; } sp = getservbyname("finger", "tcp"); if (sp == 0) { fprintf(stderr, "Finger: unknown service\n"); return (ERROR); } bzero((char *)&sin, sizeof(sin)); sin.sin_family = curHostInfo.addrType; sin.sin_port = sp->s_port; bcopy(curHostInfo.addrList[0], (char *)&sin.sin_addr, curHostInfo.addrLen); /* * Set up a virtual circuit to the host. */ sockFD = socket(curHostInfo.addrType, SOCK_STREAM, 0); if (sockFD < 0) { fflush(stdout); perror("finger: socket"); return (ERROR); } if (connect(sockFD, (char *)&sin, sizeof (sin)) < 0) { fflush(stdout); perror("finger: connect"); close(sockFD); sockFD = -1; return (ERROR); } if (!putToFile) { filePtr = stdout; } else { filePtr = OpenFile(string, file); if (filePtr == NULL) { fprintf(stderr, "*** Can't open %s for writing\n", file); close(sockFD); sockFD = -1; return(ERROR); } fprintf(filePtr,"> %s\n", string); } fprintf(filePtr, "[%s]\n", curHostInfo.name); if (name[0] != '\0') { write(sockFD, "/W ", 3); } write(sockFD, name, strlen(name)); write(sockFD, "\r\n", 2); f = fdopen(sockFD, "r"); while ((c = getc(f)) != EOF) { switch (c) { case 0210: case 0211: case 0212: case 0214: c -= 0200; break; case 0215: c = '\n'; break; } putc(lastc = c, filePtr); } if (lastc != '\n') { putc('\n', filePtr); } putc('\n', filePtr); close(sockFD); sockFD = -1; if (putToFile) { fclose(filePtr); filePtr = NULL; } return (SUCCESS); } ListHost_close() { if (sockFD != -1) { (void) close(sockFD); sockFD = -1; } } { fprintf(stdout, "%sReceived %d record%s.\n", (numAnswers >= HASH_SIZE) ? "\n" : "", numAnswers, (numAnswers != 1) ? "s" : ""); } (void) close(sockFD); sockFD = -1; if (cmd != NULL && filePtr != NULL) { fclose(filePtr); filePtr = NULL; } switch (error) { case NO_ERRORS: return (SUCCESS); case ERR_READING_LEN: return(ERROR); caseetc/named/tools/nslookup/getinfo.c 644 0 0 47325 5367011514 12512 /* * Copyright (c) 1985,1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)getinfo.c 5.22 (Berkeley) 6/1/90"; #endif /* ******************************************************************************* * * getinfo.c -- * * Routines to create requests to name servers * and interpret the answers. * * Adapted from 4.3BSD BIND gethostnamadr.c * ******************************************************************************* */ #include #include #include #include #include #include #include #include #include "res.h" extern char *_res_resultcodes[]; extern char *res_skip(); #define MAXALIASES 35 #define MAXADDRS 35 #define MAXDOMAINS 35 #define MAXSERVERS 10 static char *addr_list[MAXADDRS + 1]; static char *host_aliases[MAXALIASES]; static int host_aliases_len[MAXALIASES]; static char hostbuf[BUFSIZ+1]; typedef struct { char *name; char *domain[MAXDOMAINS]; int numDomains; char *address[MAXADDRS]; int numAddresses; } ServerTable; ServerTable server[MAXSERVERS]; typedef union { HEADER qb1; char qb2[PACKETSZ]; } querybuf; typedef union { long al; char ac; } align; #define GetShort(cp) _getshort(cp); cp += sizeof(unsigned short); /* ******************************************************************************* * * GetAnswer -- * * Interprets an answer packet and retrieves the following * information: * * Results: * SUCCESS the info was retrieved. * NO_INFO the packet did not contain an answer. * NONAUTH non-authoritative information was found. * ERROR the answer was malformed. * Other errors returned in the packet header. * ******************************************************************************* */ static int GetAnswer(nsAddrPtr, queryType, msg, msglen, iquery, hostPtr, isServer) struct in_addr *nsAddrPtr; char *msg; int queryType; int msglen; Boolean iquery; register HostInfo *hostPtr; Boolean isServer; { register HEADER *headerPtr; register char *cp; querybuf answer; char *eom, *bp, **aliasPtr; char **addrPtr; char *namePtr; char *dnamePtr; int type, class; int qdcount, ancount, arcount, nscount, buflen; int origClass; int numAliases = 0; int numAddresses = 0; int n, i, j; int len; int dlen; int status; int numServers; Boolean haveAnswer; Boolean printedAnswers = FALSE; /* * If the hostPtr was used before, free up the calloc'd areas. */ FreeHostInfoPtr(hostPtr); status = SendRequest(nsAddrPtr, msg, msglen, (char *) &answer, sizeof(answer), &n); if (status != SUCCESS) { if (_res.options & RES_DEBUG2) printf("SendRequest failed\n"); return (status); } eom = (char *) &answer + n; headerPtr = (HEADER *) &answer; if (headerPtr->rcode != NOERROR) { return (headerPtr->rcode); } qdcount = ntohs(headerPtr->qdcount); ancount = ntohs(headerPtr->ancount); arcount = ntohs(headerPtr->arcount); nscount = ntohs(headerPtr->nscount); /* * If there are no answer, n.s. or additional records * then return with an error. */ if (ancount == 0 && nscount == 0 && arcount == 0) { return (NO_INFO); } bp = hostbuf; buflen = sizeof(hostbuf); cp = (char *) &answer + sizeof(HEADER); /* Skip over question section. */ while (qdcount-- > 0) { cp += dn_skipname(cp, eom) + QFIXEDSZ; } aliasPtr = host_aliases; addrPtr = addr_list; haveAnswer = FALSE; /* * Scan through the answer resource records. * Answers for address query types are saved. * Other query type answers are just printed. */ if (ancount != 0) { if (!isServer && !headerPtr->aa) { printf("Non-authoritative answer:\n"); } if (queryType != T_A && !(iquery && queryType == T_PTR)) { while (--ancount >= 0 && cp < eom) { if ((cp = Print_rr(cp, (char *)&answer, eom, stdout)) == NULL) { return(ERROR); } } printedAnswers = TRUE; } else { while (--ancount >= 0 && cp < eom) { if ((n = dn_expand((char *)&answer, eom, cp, bp, buflen)) < 0) { return(ERROR); } cp += n; type = GetShort(cp); class = GetShort(cp); cp += sizeof(u_long); /* skip TTL */ dlen = GetShort(cp); if (type == T_CNAME) { /* * Found an alias. */ cp += dlen; if (aliasPtr >= &host_aliases[MAXALIASES-1]) { continue; } *aliasPtr++ = bp; n = strlen(bp) + 1; host_aliases_len[numAliases] = n; numAliases++; bp += n; buflen -= n; continue; } else if (type == T_PTR) { /* * Found a "pointer" to the real name. */ if((n=dn_expand((char *)&answer, eom, cp, bp,buflen)) < 0) { cp += n; continue; } cp += n; len = strlen(bp) + 1; hostPtr->name = Calloc(1, len); bcopy(bp, hostPtr->name, len); haveAnswer = TRUE; break; } else if (type != T_A) { cp += dlen; continue; } if (haveAnswer) { /* * If we've already got 1 address, we aren't interested * in addresses with a different length or class. */ if (dlen != hostPtr->addrLen) { cp += dlen; continue; } if (class != origClass) { cp += dlen; continue; } } else { /* * First address: record its length and class so we * only save additonal ones with the same attributes. */ hostPtr->addrLen = dlen; origClass = class; hostPtr->addrType = (class == C_IN) ? AF_INET : AF_UNSPEC; len = strlen(bp) + 1; hostPtr->name = Calloc(1, len); bcopy(bp, hostPtr->name, len); } bp += (((u_long)bp) % sizeof(align)); if (bp + dlen >= &hostbuf[sizeof(hostbuf)]) { if (_res.options & RES_DEBUG) { printf("Size (%d) too big\n", dlen); } break; } bcopy(cp, *addrPtr++ = bp, dlen); bp +=dlen; cp += dlen; numAddresses++; haveAnswer = TRUE; } } } if ((queryType == T_A || queryType == T_PTR) && haveAnswer) { /* * Go through the alias and address lists and return them * in the hostPtr variable. */ if (numAliases > 0) { hostPtr->aliases = (char **) Calloc(1 + numAliases, sizeof(char *)); for (i = 0; i < numAliases; i++) { hostPtr->aliases[i] = Calloc(1, host_aliases_len[i]); bcopy(host_aliases[i], hostPtr->aliases[i],host_aliases_len[i]); } hostPtr->aliases[i] = NULL; } if (numAddresses > 0) { hostPtr->addrList = (char **)Calloc(1+numAddresses, sizeof(char *)); for (i = 0; i < numAddresses; i++) { hostPtr->addrList[i] = Calloc(1, hostPtr->addrLen); bcopy(addr_list[i], hostPtr->addrList[i], hostPtr->addrLen); } hostPtr->addrList[i] = NULL; } #ifdef verbose if (headerPtr->aa || nscount == 0) { hostPtr->servers = NULL; return (SUCCESS); } #else hostPtr->servers = NULL; return (SUCCESS); #endif } /* * At this point, for the T_A query type, only empty answers remain. * For other query types, additional information might be found * in the additional resource records part. */ if (!headerPtr->aa && (queryType != T_A) && (nscount > 0 || arcount > 0)) { if (printedAnswers) { putchar('\n'); } printf("Authoritative answers can be found from:\n"); } cp = res_skip((char *) &answer, 2, eom); numServers = 0; if (queryType != T_A) { /* * If we don't need to save the record, just print it. */ while (--nscount >= 0 && cp < eom) { if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) { return(ERROR); } } } else { while (--nscount >= 0 && cp < eom) { /* * Go through the NS records and retrieve the names of hosts * that serve the requested domain. */ if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) { return(ERROR); } cp += n; len = strlen(bp) + 1; dnamePtr = Calloc(1, len); /* domain name */ bcopy(bp, dnamePtr, len); type = GetShort(cp); class = GetShort(cp); cp += sizeof(u_long); /* skip TTL */ dlen = GetShort(cp); if (type != T_NS) { cp += dlen; } else { Boolean found; if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0){ return(ERROR); } cp += n; len = strlen(bp) + 1; namePtr = Calloc(1, len); /* server host name */ bcopy(bp, namePtr, len); /* * Store the information keyed by the server host name. */ found = FALSE; for (j = 0; j < numServers; j++) { if (strcmp(namePtr, server[j].name) == 0) { found = TRUE; free(namePtr); break; } } if (found) { server[j].numDomains++; if (server[j].numDomains <= MAXDOMAINS) { server[j].domain[server[j].numDomains-1] = dnamePtr; } } else { if (numServers >= MAXSERVERS) { break; } server[numServers].name = namePtr; server[numServers].domain[0] = dnamePtr; server[numServers].numDomains = 1; server[numServers].numAddresses = 0; numServers++; } } } } /* * Additional resource records contain addresses of servers. */ cp = res_skip((char *) &answer, 3, eom); if (queryType != T_A) { /* * If we don't need to save the record, just print it. */ while (--arcount >= 0 && cp < eom) { if ((cp = Print_rr(cp, (char *) &answer, eom, stdout)) == NULL) { return(ERROR); } } } else { while (--arcount >= 0 && cp < eom) { if ((n = dn_expand((char *) &answer, eom, cp, bp, buflen)) < 0) { break; } cp += n; type = GetShort(cp); class = GetShort(cp); cp += sizeof(u_long); /* skip TTL */ dlen = GetShort(cp); if (type != T_A) { cp += dlen; continue; } else { for (j = 0; j < numServers; j++) { if (strcmp(bp, server[j].name) == 0) { server[j].numAddresses++; if (server[j].numAddresses <= MAXADDRS) { server[j].address[server[j].numAddresses-1] = Calloc(1,dlen); bcopy(cp, server[j].address[server[j].numAddresses-1],dlen); break; } } } cp += dlen; } } } /* * If we are returning name server info, transfer it to the hostPtr. */ if (numServers > 0) { hostPtr->servers = (ServerInfo **) Calloc(numServers+1, sizeof(ServerInfo *)); for (i = 0; i < numServers; i++) { hostPtr->servers[i] = (ServerInfo *) Calloc(1, sizeof(ServerInfo)); hostPtr->servers[i]->name = server[i].name; hostPtr->servers[i]->domains = (char **) Calloc(server[i].numDomains+1,sizeof(char *)); for (j = 0; j < server[i].numDomains; j++) { hostPtr->servers[i]->domains[j] = server[i].domain[j]; } hostPtr->servers[i]->domains[j] = NULL; hostPtr->servers[i]->addrList = (char **) Calloc(server[i].numAddresses+1,sizeof(char *)); for (j = 0; j < server[i].numAddresses; j++) { hostPtr->servers[i]->addrList[j] = server[i].address[j]; } hostPtr->servers[i]->addrList[j] = NULL; } hostPtr->servers[i] = NULL; } switch (queryType) { case T_A: return NONAUTH; case T_PTR: if (iquery) return NO_INFO; /* fall through */ default: return SUCCESS; } } /* ******************************************************************************* * * GetHostInfo -- * * Retrieves host name, address and alias information * for a domain. * * Algorithm from res_search(). * * Results: * ERROR - res_mkquery failed. * + return values from GetAnswer() * ******************************************************************************* */ int GetHostInfoByName(nsAddrPtr, queryClass, queryType, name, hostPtr, isServer) struct in_addr *nsAddrPtr; int queryClass; int queryType; char *name; HostInfo *hostPtr; Boolean isServer; { int n; register int result; register char *cp, **domain; extern char *hostalias(); Boolean got_nodata = FALSE; u_long ina; /* Catch explicit addresses */ if ((queryType == T_A) && IsAddr(name, &ina)) { hostPtr->name = Calloc(strlen(name)+3, 1); (void)sprintf(hostPtr->name,"[%s]",name); hostPtr->aliases = NULL; hostPtr->servers = NULL; hostPtr->addrType = AF_INET; hostPtr->addrLen = sizeof(struct in_addr); hostPtr->addrList = (char **)Calloc(2, sizeof(char *)); hostPtr->addrList[0] = Calloc(sizeof(long), sizeof(char)); bcopy((char *)&ina, hostPtr->addrList[0], sizeof(ina)); hostPtr->addrList[1] = NULL; return(SUCCESS); } result = NXDOMAIN; for (cp = name, n = 0; *cp; cp++) if (*cp == '.') n++; if (n == 0 && (cp = hostalias(name))) { printf("Aliased to \"%s\"\n\n", cp); return (GetHostDomain(nsAddrPtr, queryClass, queryType, cp, (char *)NULL, hostPtr, isServer)); } /* * We do at least one level of search if * - there is no dot and RES_DEFNAME is set, or * - there is at least one dot, there is no trailing dot, * and RES_DNSRCH is set. */ if ((n == 0 && _res.options & RES_DEFNAMES) || (n != 0 && *--cp != '.' && _res.options & RES_DNSRCH)) for (domain = _res.dnsrch; *domain; domain++) { result = GetHostDomain(nsAddrPtr, queryClass, queryType, name, *domain, hostPtr, isServer); /* * If no server present, give up. * If name isn't found in this domain, * keep trying higher domains in the search list * (if that's enabled). * On a NO_INFO error, keep trying, otherwise * a wildcard entry of another type could keep us * from finding this entry higher in the domain. * If we get some other error (negative answer or * server failure), then stop searching up, * but try the input name below in case it's fully-qualified. */ if (result == SUCCESS || result == NO_RESPONSE) return result; if (result == NO_INFO) got_nodata++; if ((result != NXDOMAIN && result != NO_INFO) || (_res.options & RES_DNSRCH) == 0) break; } /* * If the search/default failed, try the name as fully-qualified, * but only if it contained at least one dot (even trailing). * This is purely a heuristic; we assume that any reasonable query * about a top-level domain (for servers, SOA, etc) will not use * res_search. */ if (n && (result = GetHostDomain(nsAddrPtr, queryClass, queryType, name, (char *)NULL, hostPtr, isServer)) == SUCCESS) return result; if (got_nodata) result = NO_INFO; return (result); } /* * Perform a query on the concatenation of name and domain, * removing a trailing dot from name if domain is NULL. */ GetHostDomain(nsAddrPtr, queryClass, queryType, name, domain, hostPtr, isServer) struct in_addr *nsAddrPtr; int queryClass; int queryType; char *name, *domain; HostInfo *hostPtr; Boolean isServer; { querybuf buf; char nbuf[2*MAXDNAME+2]; char *longname = nbuf; int n; if (domain == NULL) { /* * Check for trailing '.'; * copy without '.' if present. */ n = strlen(name) - 1; if (name[n] == '.' && n < sizeof(nbuf) - 1) { bcopy(name, nbuf, n); nbuf[n] = '\0'; } else longname = name; } else { (void)sprintf(nbuf, "%.*s.%.*s", MAXDNAME, name, MAXDNAME, domain); longname = nbuf; } n = res_mkquery(QUERY, longname, queryClass, queryType, (char *)0, 0, (struct rrec *)0, (char *) &buf, sizeof(buf)); if (n < 0) { if (_res.options & RES_DEBUG) { printf("Res_mkquery failed\n"); } return (ERROR); } n = GetAnswer(nsAddrPtr, queryType, (char *)&buf, n, 0, hostPtr, isServer); /* * GetAnswer didn't find a name, so set it to the specified one. */ if (n == NONAUTH) { if (hostPtr->name == NULL) { int len = strlen(longname) + 1; hostPtr->name = Calloc(len, sizeof(char)); bcopy(longname, hostPtr->name, len); } } return(n); } /* ******************************************************************************* * * GetHostInfoByAddr -- * * Performs an inverse query to find the host name * that corresponds to the given address. * * Results: * ERROR - res_mkquery failed. * + return values from GetAnswer() * ******************************************************************************* */ int GetHostInfoByAddr(nsAddrPtr, address, hostPtr) struct in_addr *nsAddrPtr; struct in_addr *address; HostInfo *hostPtr; { int n; querybuf buf; char qbuf[MAXDNAME]; char *p = (char *) &address->s_addr; (void)sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", ((unsigned)p[3] & 0xff), ((unsigned)p[2] & 0xff), ((unsigned)p[1] & 0xff), ((unsigned)p[0] & 0xff)); n = res_mkquery(QUERY, qbuf, C_IN, T_PTR, (char *)NULL, 0, (struct rrec *)NULL, (char *) &buf, sizeof(buf)); if (n < 0) { if (_res.options & RES_DEBUG) { printf("res_mkquery() failed\n"); } return (ERROR); } n = GetAnswer(nsAddrPtr, T_PTR, (char *) &buf, n, 1, hostPtr, 1); if (n == SUCCESS) { hostPtr->addrType = AF_INET; hostPtr->addrLen = 4; hostPtr->addrList = (char **)Calloc(2, sizeof(char *)); hostPtr->addrList[0] = Calloc(sizeof(long), sizeof(char)); bcopy((char *)p, hostPtr->addrList[0], sizeof(struct in_addr)); hostPtr->addrList[1] = NULL; } return n; } /* ******************************************************************************* * * FreeHostInfoPtr -- * * Deallocates all the calloc'd areas for a HostInfo variable. * ******************************************************************************* */ void FreeHostInfoPtr(hostPtr) register HostInfo *hostPtr; { int i, j; if (hostPtr->name != NULL) { free(hostPtr->name); hostPtr->name = NULL; } if (hostPtr->aliases != NULL) { i = 0; while (hostPtr->aliases[i] != NULL) { free(hostPtr->aliases[i]); i++; } free((char *)hostPtr->aliases); hostPtr->aliases = NULL; } if (hostPtr->addrList != NULL) { i = 0; while (hostPtr->addrList[i] != NULL) { free(hostPtr->addrList[i]); i++; } free((char *)hostPtr->addrList); hostPtr->addrList = NULL; } if (hostPtr->servers != NULL) { i = 0; while (hostPtr->servers[i] != NULL) { if (hostPtr->servers[i]->name != NULL) { free(hostPtr->servers[i]->name); } if (hostPtr->servers[i]->domains != NULL) { j = 0; while (hostPtr->servers[i]->domains[j] != NULL) { free(hostPtr->servers[i]->domains[j]); j++; } free((char *)hostPtr->servers[i]->domains); } if (hostPtr->servers[i]->addrList != NULL) { j = 0; while (hostPtr->servers[i]->addrList[j] != NULL) { free(hostPtr->servers[i]->addrList[j]); j++; } free((char *)hostPtr->servers[i]->addrList); } free((char *)hostPtr->servers[i]); i++; } free((char *)hostPtr->servers); hostPtr->servers = NULL; } } er[j].numDomains <= MAXDOMAINS) { server[j].domain[server[j].numDomains-1] = dnamePtr; } } else { if (numServers >= MAXSERVERS) { break; } server[numServers].name = namePtr; server[numServers].domain[0] = dnamePtr; server[numServers].numDomains = 1; etc/named/tools/nslookup/send.c 644 0 0 30164 5367012217 12002 /* * Copyright (c) 1985, 1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)send.c 5.17 (Berkeley) 6/29/90"; #endif /* ******************************************************************************* * * send.c -- * * Routine to send request packets to a name server. * * Based on "@(#)res_send.c 6.25 (Berkeley) 6/1/90". * ******************************************************************************* */ /* * Send query to name server and wait for reply. */ #include #include #include #include #include #include #include #include #include #include #include "res.h" extern int errno; static int s = -1; /* socket used for communications */ #define SR 1 /* SendRequest style */ #ifndef DEBUG #define DEBUG #endif unsigned short nsport = NAMESERVER_PORT; /* ******************************************************************************* * * SendRequest -- * * Sends a request packet to a name server whose address * is specified by the first argument and returns with * the answer packet. * * Results: * SUCCESS - the request was sent and an answer * was received. * TIME_OUT - the virtual circuit connection timed-out * or a reply to a datagram wasn't received. * * ******************************************************************************* */ int SendRequest(nsAddrPtr, buf, buflen, answer, anslen, trueLenPtr) struct in_addr *nsAddrPtr; char *buf; int buflen; char *answer; u_int anslen; int *trueLenPtr; { register int n; int try, v_circuit, resplen, ns; int gotsomewhere = 0, connected = 0; int connreset = 0; u_short id, len; char *cp; fd_set dsmask; struct timeval timeout; HEADER *hp = (HEADER *) buf; HEADER *anhp = (HEADER *) answer; struct iovec iov[2]; int terrno = ETIMEDOUT; char junk[512]; #if SR struct sockaddr_in sin; if (_res.options & RES_DEBUG2) { printf("------------\nSendRequest(), len %d\n", buflen); Print_query(buf, buf+buflen, 1); } sin.sin_family = AF_INET; sin.sin_port = htons(nsport); sin.sin_addr = *nsAddrPtr; #else #ifdef DEBUG if (_res.options & RES_DEBUG) { printf("res_send()\n"); p_query(buf); } #endif DEBUG if (!(_res.options & RES_INIT)) if (res_init() == -1) { return(-1); } #endif /* SR */ v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ; id = hp->id; /* * Send request, RETRY times, or until successful */ for (try = 0; try < _res.retry; try++) { #if !SR for (ns = 0; ns < _res.nscount; ns++) { #ifdef DEBUG if (_res.options & RES_DEBUG) printf("Querying server (# %d) address = %s\n", ns+1, inet_ntoa(_res.nsaddr_list[ns].sin_addr)); #endif DEBUG #endif /* !SR */ usevc: if (v_circuit) { int truncated = 0; /* * Use virtual circuit; * at most one attempt per server. */ try = _res.retry; if (s < 0) { s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { terrno = errno; #ifdef DEBUG if (_res.options & RES_DEBUG) perror("socket (vc) failed"); #endif DEBUG continue; } #if SR if (connect(s, &sin, #else if (connect(s, &(_res.nsaddr_list[ns]), #endif sizeof(struct sockaddr)) < 0) { terrno = errno; #ifdef DEBUG if (_res.options & RES_DEBUG) perror("connect failed"); #endif DEBUG (void) close(s); s = -1; continue; } } /* * Send length & message */ len = htons((u_short)buflen); iov[0].iov_base = (caddr_t)&len; iov[0].iov_len = sizeof(len); iov[1].iov_base = buf; iov[1].iov_len = buflen; if (writev(s, iov, 2) != sizeof(len) + buflen) { terrno = errno; #ifdef DEBUG if (_res.options & RES_DEBUG) perror("write failed"); #endif DEBUG (void) close(s); s = -1; continue; } /* * Receive length & response */ cp = answer; len = sizeof(short); while (len != 0 && (n = read(s, (char *)cp, (int)len)) > 0) { cp += n; len -= n; } if (n <= 0) { terrno = errno; #ifdef DEBUG if (_res.options & RES_DEBUG) perror("read failed"); #endif DEBUG (void) close(s); s = -1; /* * A long running process might get its TCP * connection reset if the remote server was * restarted. Requery the server instead of * trying a new one. When there is only one * server, this means that a query might work * instead of failing. We only allow one reset * per query to prevent looping. */ if (terrno == ECONNRESET && !connreset) { connreset = 1; ns--; } continue; } cp = answer; if ((resplen = ntohs(*(u_short *)cp)) > anslen) { #ifdef DEBUG if (_res.options & RES_DEBUG) fprintf(stderr, "response truncated\n"); #endif DEBUG len = anslen; truncated = 1; } else len = resplen; while (len != 0 && (n = read(s, (char *)cp, (int)len)) > 0) { cp += n; len -= n; } if (n <= 0) { terrno = errno; #ifdef DEBUG if (_res.options & RES_DEBUG) perror("read failed"); #endif DEBUG (void) close(s); s = -1; continue; } if (truncated) { /* * Flush rest of answer * so connection stays in synch. */ anhp->tc = 1; len = resplen - anslen; while (len != 0) { n = (len > sizeof(junk) ? sizeof(junk) : len); if ((n = read(s, junk, n)) > 0) len -= n; else break; } } } else { /* * Use datagrams. */ if (s < 0) { s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) { terrno = errno; #ifdef DEBUG if (_res.options & RES_DEBUG) perror("socket (dg) failed"); #endif DEBUG continue; } } #if SR /* * Special case the send code below * since we have just 1 server. */ #if BSD >= 43 if (connected == 0) { if (connect(s, &sin, sizeof(struct sockaddr)) < 0) { if (_res.options & RES_DEBUG) perror("connect"); continue; } connected = 1; } if (send(s, buf, buflen, 0) != buflen) { if (_res.options & RES_DEBUG) perror("send"); continue; } #else /* BSD */ if (sendto(s, buf, buflen, 0, &sin, sizeof(struct sockaddr)) != buflen) { if (_res.options & RES_DEBUG) perror("sendto"); continue; } #endif #else /* SR */ #if BSD >= 43 /* * I'm tired of answering this question, so: * On a 4.3BSD+ machine (client and server, * actually), sending to a nameserver datagram * port with no nameserver will cause an * ICMP port unreachable message to be returned. * If our datagram socket is "connected" to the * server, we get an ECONNREFUSED error on the next * socket operation, and select returns if the * error message is received. We can thus detect * the absence of a nameserver without timing out. * If we have sent queries to at least two servers, * however, we don't want to remain connected, * as we wish to receive answers from the first * server to respond. */ if (_res.nscount == 1 || (try == 0 && ns == 0)) { /* * Don't use connect if we might * still receive a response * from another server. */ if (connected == 0) { if (connect(s, &_res.nsaddr_list[ns], sizeof(struct sockaddr)) < 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) perror("connect"); #endif DEBUG continue; } connected = 1; } if (send(s, buf, buflen, 0) != buflen) { #ifdef DEBUG if (_res.options & RES_DEBUG) perror("send"); #endif DEBUG continue; } } else { /* * Disconnect if we want to listen * for responses from more than one server. */ if (connected) { (void) connect(s, &no_addr, sizeof(no_addr)); connected = 0; } #endif BSD if (sendto(s, buf, buflen, 0, &_res.nsaddr_list[ns], sizeof(struct sockaddr)) != buflen) { #ifdef DEBUG if (_res.options & RES_DEBUG) perror("sendto"); #endif DEBUG continue; } #if BSD >= 43 } #endif #endif /* SR */ /* * Wait for reply */ timeout.tv_sec = (_res.retrans << try); #if !SR if (try > 0) timeout.tv_sec /= _res.nscount; #endif /* SR */ if (timeout.tv_sec <= 0) timeout.tv_sec = 1; timeout.tv_usec = 0; wait: FD_ZERO(&dsmask); FD_SET(s, &dsmask); n = select(s+1, &dsmask, (fd_set *)NULL, (fd_set *)NULL, &timeout); if (n < 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) perror("select"); #endif DEBUG continue; } if (n == 0) { /* * timeout */ #ifdef DEBUG if (_res.options & RES_DEBUG) printf("timeout (%d secs)\n", timeout.tv_sec); #endif DEBUG #if BSD >= 43 gotsomewhere = 1; #endif continue; } if ((resplen = recv(s, answer, anslen, 0)) <= 0) { #ifdef DEBUG if (_res.options & RES_DEBUG) perror("recvfrom"); #endif DEBUG continue; } gotsomewhere = 1; if (id != anhp->id) { /* * response from old query, ignore it */ #if SR if (_res.options & RES_DEBUG2) { printf("------------\nOld answer:\n"); Print_query(answer, answer+resplen, 1); } #else #ifdef DEBUG if (_res.options & RES_DEBUG) { printf("old answer:\n"); p_query(answer); } #endif DEBUG #endif goto wait; } if (!(_res.options & RES_IGNTC) && anhp->tc) { /* * get rest of answer; * use TCP with same server. */ #ifdef DEBUG if (_res.options & RES_DEBUG) printf("truncated answer\n"); #endif DEBUG (void) close(s); s = -1; v_circuit = 1; goto usevc; } } #if SR if (_res.options & RES_DEBUG) { if (_res.options & RES_DEBUG2) printf("------------\nGot answer (%d bytes):\n", resplen); else printf("------------\nGot answer:\n"); Print_query(answer, answer+resplen, 1); } (void) close(s); s = -1; *trueLenPtr = resplen; return (SUCCESS); #else #ifdef DEBUG if (_res.options & RES_DEBUG) { printf("got answer:\n"); p_query(answer); } #endif DEBUG /* * If using virtual circuits, we assume that the first server * is preferred * over the rest (i.e. it is on the local * machine) and only keep that one open. * If we have temporarily opened a virtual circuit, * or if we haven't been asked to keep a socket open, * close the socket. */ if ((v_circuit && ((_res.options & RES_USEVC) == 0 || ns != 0)) || (_res.options & RES_STAYOPEN) == 0) { (void) close(s); s = -1; } return (resplen); } #endif /* SR */ } if (s >= 0) { (void) close(s); s = -1; } #if SR if (v_circuit == 0) if (gotsomewhere == 0) return NO_RESPONSE; /* no nameservers found */ else return TIME_OUT; /* no answer obtained */ else if (errno == ECONNREFUSED) return NO_RESPONSE; else return ERROR; #else if (v_circuit == 0) if (gotsomewhere == 0) errno = ECONNREFUSED; /* no nameservers found */ else errno = ETIMEDOUT; /* no answer obtained */ else errno = terrno; return (-1); #endif } /* * This routine is for closing the socket if a virtual circuit is used and * the program wants to close it. * * Called from the interrupt handler. */ SendRequest_close() { if (s != -1) { (void) close(s); s = -1; } } tr, isServer) struct in_addr *nsAddrPtr; int queryClass; int queryType; char *name; HostInfo *hostPtr; Boolean isServer; { int n; register int result; register char *cp, **domain; extern char *hostalias(); Boolean got_nodata = FALSE; u_long ina; /* Catch explicit addresses */ if ((queryType == T_A) && IsAddr(name, &ina)) { hoetc/named/tools/nslookup/main.c 644 0 0 70300 5367002474 11775 /* * Copyright (c) 1985,1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1985,1989 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)main.c 5.39 (Berkeley) 6/24/90"; #endif /* ******************************************************************************* * * main.c -- * * Main routine and some action routines for the name server * lookup program. * * Andrew Cherenson * U.C. Berkeley Computer Science Div. * CS298-26, Fall 1985 * ******************************************************************************* */ #include #include #include #include #include #include #include #include #include #include #include #include #include "res.h" #include "pathnames.h" /* * Default Internet address of the current host. */ #if BSD < 43 #define LOCALHOST "127.0.0.1" #endif /* * Name of a top-level name server. Can be changed with * the "set root" command. */ #ifndef ROOT_SERVER #define ROOT_SERVER "ns.internic.net." #endif char rootServerName[NAME_LEN] = ROOT_SERVER; /* * Import the state information from the resolver library. */ extern struct state _res; /* * Info about the most recently queried host. */ HostInfo curHostInfo; int curHostValid = FALSE; /* * Info about the default name server. */ HostInfo *defaultPtr = NULL; char defaultServer[NAME_LEN]; struct in_addr defaultAddr; /* * Initial name server query type is Address. */ int queryType = T_A; int queryClass = C_IN; /* * Stuff for Interrupt (control-C) signal handler. */ #ifdef SVR3 extern void IntrHandler(); #else extern int IntrHandler(); #endif FILE *filePtr; jmp_buf env; static void CvtAddrToPtr(); static void ReadRC(); /* ******************************************************************************* * * main -- * * Initializes the resolver library and determines the address * of the initial name server. The yylex routine is used to * read and perform commands. * ******************************************************************************* */ main(argc, argv) int argc; char **argv; { char *wantedHost = NULL; Boolean useLocalServer; int result; int i; struct hostent *hp; extern int h_errno; /* * Initialize the resolver library routines. */ if (res_init() == -1) { fprintf(stderr,"*** Can't initialize resolver.\n"); exit(1); } /* * Allocate space for the default server's host info and * find the server's address and name. If the resolver library * already has some addresses for a potential name server, * then use them. Otherwise, see if the current host has a server. * Command line arguments may override the choice of initial server. */ defaultPtr = (HostInfo *) Calloc(1, sizeof(HostInfo)); /* * Parse the arguments: * no args = go into interactive mode, use default host as server * 1 arg = use as host name to be looked up, default host will be server * non-interactive mode * 2 args = 1st arg: * if it is '-', then * ignore but go into interactive mode * else * use as host name to be looked up, * go into non-interactive mode * 2nd arg: name or inet address of server * * "Set" options are specified with a leading - and must come before * any arguments. For example, to find the well-known services for * a host, type "nslookup -query=wks host" */ ReadRC(); /* look for options file */ ++argv; --argc; /* skip prog name */ while (argc && *argv[0] == '-' && argv[0][1]) { (void) SetOption (&(argv[0][1])); ++argv; --argc; } if (argc > 2) { Usage(); } if (argc && *argv[0] != '-') { wantedHost = *argv; /* name of host to be looked up */ } useLocalServer = FALSE; if (argc == 2) { struct in_addr addr; /* * Use an explicit name server. If the hostname lookup fails, * default to the server(s) in resolv.conf. */ addr.s_addr = inet_addr(*++argv); if (addr.s_addr != (u_long)-1) { _res.nscount = 1; _res.nsaddr.sin_addr = addr; } else { hp = gethostbyname(*argv); if (hp == NULL) { fprintf(stderr, "*** Can't find server address for '%s': ", *argv); herror((char *)NULL); fputc('\n', stderr); } else { #if BSD < 43 bcopy(hp->h_addr, (char *)&_res.nsaddr.sin_addr, hp->h_length); _res.nscount = 1; #else for (i = 0; i < MAXNS && hp->h_addr_list[i] != NULL; i++) { bcopy(hp->h_addr_list[i], (char *)&_res.nsaddr_list[i].sin_addr, hp->h_length); } _res.nscount = i; #endif } } } if (_res.nscount == 0 || useLocalServer) { LocalServer(defaultPtr); } else { for (i = 0; i < _res.nscount; i++) { if (_res.nsaddr_list[i].sin_addr.s_addr == INADDR_ANY) { LocalServer(defaultPtr); break; } else { result = GetHostInfoByAddr(&(_res.nsaddr_list[i].sin_addr), &(_res.nsaddr_list[i].sin_addr), defaultPtr); if (result != SUCCESS) { fprintf(stderr, "*** Can't find server name for address %s: %s\n", inet_ntoa(_res.nsaddr_list[i].sin_addr), DecodeError(result)); } else { defaultAddr = _res.nsaddr_list[i].sin_addr; break; } } } /* * If we have exhausted the list, tell the user about the * command line argument to specify an address. */ if (i == _res.nscount) { fprintf(stderr, "*** Default servers are not available\n"); exit(1); } } strcpy(defaultServer, defaultPtr->name); #ifdef DEBUG #ifdef DEBUG2 _res.options |= RES_DEBUG2; #endif _res.options |= RES_DEBUG; _res.retry = 2; #endif DEBUG /* * If we're in non-interactive mode, look up the wanted host and quit. * Otherwise, print the initial server's name and continue with * the initialization. */ if (wantedHost != (char *) NULL) { LookupHost(wantedHost, 0); } else { PrintHostInfo(stdout, "Default Server:", defaultPtr); /* * Setup the environment to allow the interrupt handler to return here. */ (void) setjmp(env); /* * Return here after a longjmp. */ signal(SIGINT, IntrHandler); signal(SIGPIPE, SIG_IGN); /* * Read and evaluate commands. The commands are described in commands.l * Yylex returns 0 when ^D or 'exit' is typed. */ printf("> "); fflush(stdout); while(yylex()) { printf("> "); fflush(stdout); } } exit(0); } LocalServer(defaultPtr) HostInfo *defaultPtr; { char hostName[NAME_LEN]; #if BSD < 43 int result; #endif gethostname(hostName, sizeof(hostName)); #if BSD < 43 defaultAddr.s_addr = inet_addr(LOCALHOST); result = GetHostInfoByName(&defaultAddr, C_IN, T_A, hostName, defaultPtr, 1); if (result != SUCCESS) { fprintf(stderr, "*** Can't find initialize address for server %s: %s\n", defaultServer, DecodeError(result)); exit(1); } #else defaultAddr.s_addr = htonl(INADDR_ANY); (void) GetHostInfoByName(&defaultAddr, C_IN, T_A, "0.0.0.0", defaultPtr, 1); free(defaultPtr->name); defaultPtr->name = Calloc(1, sizeof(hostName)+1); strcpy(defaultPtr->name, hostName); #endif } /* ******************************************************************************* * * Usage -- * * Lists the proper methods to run the program and exits. * ******************************************************************************* */ Usage() { fprintf(stderr, "Usage:\n"); fprintf(stderr, " nslookup [-opt ...] # interactive mode using default server\n"); fprintf(stderr, " nslookup [-opt ...] - server # interactive mode using 'server'\n"); fprintf(stderr, " nslookup [-opt ...] host # just look up 'host' using default server\n"); fprintf(stderr, " nslookup [-opt ...] host server # just look up 'host' using 'server'\n"); exit(1); } /* ******************************************************************************* * * IsAddr -- * * Returns TRUE if the string looks like an Internet address. * A string with a trailing dot is not an address, even if it looks * like one. * * XXX doesn't treat 255.255.255.255 as an address. * ******************************************************************************* */ Boolean IsAddr(host, addrPtr) char *host; u_long *addrPtr; /* If return TRUE, contains IP address */ { register char *cp; u_long addr; if (isdigit(host[0])) { /* Make sure it has only digits and dots. */ for (cp = host; *cp; ++cp) { if (!isdigit(*cp) && *cp != '.') return FALSE; } /* If it has a trailing dot, don't treat it as an address. */ if (*--cp != '.') { if ((addr = inet_addr(host)) != (u_long) -1) { *addrPtr = addr; return TRUE; #if 0 } else { /* XXX Check for 255.255.255.255 case */ #endif } } } return FALSE; } /* ******************************************************************************* * * SetDefaultServer -- * * Changes the default name server to the one specified by * the first argument. The command "server name" uses the current * default server to lookup the info for "name". The command * "lserver name" uses the original server to lookup "name". * * Side effects: * This routine will cause a core dump if the allocation requests fail. * * Results: * SUCCESS The default server was changed successfully. * NONAUTH The server was changed but addresses of * other servers who know about the requested server * were returned. * Errors No info about the new server was found or * requests to the current server timed-out. * ******************************************************************************* */ int SetDefaultServer(string, local) char *string; Boolean local; { register HostInfo *newDefPtr; struct in_addr *servAddrPtr; struct in_addr addr; char newServer[NAME_LEN]; int result; int i; /* * Parse the command line. It maybe of the form "server name", * "lserver name" or just "name". */ if (local) { i = sscanf(string, " lserver %s", newServer); } else { i = sscanf(string, " server %s", newServer); } if (i != 1) { i = sscanf(string, " %s", newServer); if (i != 1) { fprintf(stderr,"SetDefaultServer: invalid name: %s\n", string); return(ERROR); } } /* * Allocate space for a HostInfo variable for the new server. Don't * overwrite the old HostInfo struct because info about the new server * might not be found and we need to have valid default server info. */ newDefPtr = (HostInfo *) Calloc(1, sizeof(HostInfo)); /* * A 'local' lookup uses the original server that the program was * initialized with. * * Check to see if we have the address of the server or the * address of a server who knows about this domain. * XXX For now, just use the first address in the list. */ if (local) { servAddrPtr = &defaultAddr; } else if (defaultPtr->addrList != NULL) { servAddrPtr = (struct in_addr *) defaultPtr->addrList[0]; } else { servAddrPtr = (struct in_addr *) defaultPtr->servers[0]->addrList[0]; } result = ERROR; if (IsAddr(newServer, &addr.s_addr)) { result = GetHostInfoByAddr(servAddrPtr, &addr, newDefPtr); /* If we can't get the name, fall through... */ } if (result != SUCCESS && result != NONAUTH) { result = GetHostInfoByName(servAddrPtr, C_IN, T_A, newServer, newDefPtr, 1); } if (result == SUCCESS || result == NONAUTH) { /* * Found info about the new server. Free the resources for * the old server. */ FreeHostInfoPtr(defaultPtr); free((char *)defaultPtr); defaultPtr = newDefPtr; strcpy(defaultServer, defaultPtr->name); PrintHostInfo(stdout, "Default Server:", defaultPtr); return(SUCCESS); } else { fprintf(stderr, "*** Can't find address for server %s: %s\n", newServer, DecodeError(result)); free((char *)newDefPtr); return(result); } } /* ******************************************************************************* * * DoLoookup -- * * Common subroutine for LookupHost and LookupHostWithServer. * * Results: * SUCCESS - the lookup was successful. * Misc. Errors - an error message is printed if the lookup failed. * ******************************************************************************* */ static int DoLookup(host, servPtr, serverName) char *host; HostInfo *servPtr; char *serverName; { int result; struct in_addr *servAddrPtr; struct in_addr addr; /* Skip escape character */ if (host[0] == '\\') host++; /* * If the user gives us an address for an address query, * silently treat it as a PTR query. If the query type is already * PTR, then convert the address into the in-addr.arpa format. * * Use the address of the server if it exists, otherwise use the * address of a server who knows about this domain. * XXX For now, just use the first address in the list. */ if (servPtr->addrList != NULL) { servAddrPtr = (struct in_addr *) servPtr->addrList[0]; } else { servAddrPtr = (struct in_addr *) servPtr->servers[0]->addrList[0]; } /* * RFC1123 says we "SHOULD check the string syntactically for a * dotted-decimal number before looking it up [...]" (p. 13). */ if (queryType == T_A && IsAddr(host, &addr.s_addr)) { result = GetHostInfoByAddr(servAddrPtr, &addr, &curHostInfo); } else { if (queryType == T_PTR) { CvtAddrToPtr(host); } result = GetHostInfoByName(servAddrPtr, queryClass, queryType, host, &curHostInfo, 0); } switch (result) { case SUCCESS: /* * If the query was for an address, then the &curHostInfo * variable can be used by Finger. * There's no need to print anything for other query types * because the info has already been printed. */ if (queryType == T_A) { curHostValid = TRUE; PrintHostInfo(filePtr, "Name:", &curHostInfo); } break; /* * No Authoritative answer was available but we got names * of servers who know about the host. */ case NONAUTH: PrintHostInfo(filePtr, "Name:", &curHostInfo); break; case NO_INFO: fprintf(stderr, "*** No %s (%s) records available for %s\n", DecodeType(queryType), p_type(queryType), host); break; case TIME_OUT: fprintf(stderr, "*** Request to %s timed-out\n", serverName); break; default: fprintf(stderr, "*** %s can't find %s: %s\n", serverName, host, DecodeError(result)); } return result; } /* ******************************************************************************* * * LookupHost -- * * Asks the default name server for information about the * specified host or domain. The information is printed * if the lookup was successful. * * Results: * ERROR - the output file could not be opened. * + results of DoLookup * ******************************************************************************* */ int LookupHost(string, putToFile) char *string; Boolean putToFile; { char host[NAME_LEN]; char file[NAME_LEN]; int result; /* * Invalidate the current host information to prevent Finger * from using bogus info. */ curHostValid = FALSE; /* * Parse the command string into the host and * optional output file name. * */ sscanf(string, " %s", host); /* removes white space */ if (!putToFile) { filePtr = stdout; } else { filePtr = OpenFile(string, file); if (filePtr == NULL) { fprintf(stderr, "*** Can't open %s for writing\n", file); return(ERROR); } fprintf(filePtr,"> %s\n", string); } PrintHostInfo(filePtr, "Server:", defaultPtr); result = DoLookup(host, defaultPtr, defaultServer); if (putToFile) { fclose(filePtr); filePtr = NULL; } return(result); } /* ******************************************************************************* * * LookupHostWithServer -- * * Asks the name server specified in the second argument for * information about the host or domain specified in the first * argument. The information is printed if the lookup was successful. * * Address info about the requested name server is obtained * from the default name server. This routine will return an * error if the default server doesn't have info about the * requested server. Thus an error return status might not * mean the requested name server doesn't have info about the * requested host. * * Comments from LookupHost apply here, too. * * Results: * ERROR - the output file could not be opened. * + results of DoLookup * ******************************************************************************* */ int LookupHostWithServer(string, putToFile) char *string; Boolean putToFile; { char file[NAME_LEN]; char host[NAME_LEN]; char server[NAME_LEN]; int result; static HostInfo serverInfo; curHostValid = FALSE; sscanf(string, " %s %s", host, server); if (!putToFile) { filePtr = stdout; } else { filePtr = OpenFile(string, file); if (filePtr == NULL) { fprintf(stderr, "*** Can't open %s for writing\n", file); return(ERROR); } fprintf(filePtr,"> %s\n", string); } result = GetHostInfoByName( defaultPtr->addrList ? (struct in_addr *) defaultPtr->addrList[0] : (struct in_addr *) defaultPtr->servers[0]->addrList[0], C_IN, T_A, server, &serverInfo, 1); if (result != SUCCESS) { fprintf(stderr,"*** Can't find address for server %s: %s\n", server, DecodeError(result)); } else { PrintHostInfo(filePtr, "Server:", &serverInfo); result = DoLookup(host, &serverInfo, server); } if (putToFile) { fclose(filePtr); filePtr = NULL; } return(result); } /* ******************************************************************************* * * SetOption -- * * This routine is used to change the state information * that affect the lookups. The command format is * set keyword[=value] * Most keywords can be abbreviated. Parsing is very simplistic-- * A value must not be separated from its keyword by white space. * * Valid keywords: Meaning: * all lists current values of options. * ALL lists current values of options, including * hidden options. * [no]d2 turn on/off extra debugging mode. * [no]debug turn on/off debugging mode. * [no]defname use/don't use default domain name. * [no]search use/don't use domain search list. * domain=NAME set default domain name to NAME. * [no]ignore ignore/don't ignore trunc. errors. * query=value set default query type to value, * value is one of the query types in RFC883 * without the leading T_. (e.g., A, HINFO) * [no]recurse use/don't use recursive lookup. * retry=# set number of retries to #. * root=NAME change root server to NAME. * time=# set timeout length to #. * [no]vc use/don't use virtual circuit. * port TCP/UDP port to server. * * Deprecated: * [no]primary use/don't use primary server. * * Results: * SUCCESS the command was parsed correctly. * ERROR the command was not parsed correctly. * ******************************************************************************* */ int SetOption(option) register char *option; { char type[NAME_LEN]; char *ptr; int tmp; while (isspace(*option)) ++option; if (strncmp (option, "set ", 4) == 0) option += 4; while (isspace(*option)) ++option; if (*option == 0) { fprintf(stderr, "*** Invalid set command\n"); return(ERROR); } else { if (strncmp(option, "all", 3) == 0) { ShowOptions(); } else if (strncmp(option, "ALL", 3) == 0) { ShowOptions(); } else if (strncmp(option, "d2", 2) == 0) { /* d2 (more debug) */ _res.options |= (RES_DEBUG | RES_DEBUG2); } else if (strncmp(option, "nod2", 4) == 0) { _res.options &= ~RES_DEBUG2; printf("d2 mode disabled; still in debug mode\n"); } else if (strncmp(option, "def", 3) == 0) { /* defname */ _res.options |= RES_DEFNAMES; } else if (strncmp(option, "nodef", 5) == 0) { _res.options &= ~RES_DEFNAMES; } else if (strncmp(option, "do", 2) == 0) { /* domain */ ptr = strchr(option, '='); if (ptr != NULL) { sscanf(++ptr, "%s", _res.defdname); res_re_init(); } } else if (strncmp(option, "deb", 1) == 0) { /* debug */ _res.options |= RES_DEBUG; } else if (strncmp(option, "nodeb", 5) == 0) { _res.options &= ~(RES_DEBUG | RES_DEBUG2); } else if (strncmp(option, "ig", 2) == 0) { /* ignore */ _res.options |= RES_IGNTC; } else if (strncmp(option, "noig", 4) == 0) { _res.options &= ~RES_IGNTC; } else if (strncmp(option, "po", 2) == 0) { /* port */ ptr = strchr(option, '='); if (ptr != NULL) { sscanf(++ptr, "%hu", &nsport); } #ifdef deprecated } else if (strncmp(option, "pri", 3) == 0) { /* primary */ _res.options |= RES_PRIMARY; } else if (strncmp(option, "nopri", 5) == 0) { _res.options &= ~RES_PRIMARY; #endif } else if (strncmp(option, "q", 1) == 0 || /* querytype */ strncmp(option, "ty", 2) == 0) { /* type */ ptr = strchr(option, '='); if (ptr != NULL) { sscanf(++ptr, "%s", type); queryType = StringToType(type, queryType); } } else if (strncmp(option, "cl", 2) == 0) { /* query class */ ptr = strchr(option, '='); if (ptr != NULL) { sscanf(++ptr, "%s", type); queryClass = StringToClass(type, queryClass); } } else if (strncmp(option, "rec", 3) == 0) { /* recurse */ _res.options |= RES_RECURSE; } else if (strncmp(option, "norec", 5) == 0) { _res.options &= ~RES_RECURSE; } else if (strncmp(option, "ret", 3) == 0) { /* retry */ ptr = strchr(option, '='); if (ptr != NULL) { sscanf(++ptr, "%d", &tmp); if (tmp >= 0) { _res.retry = tmp; } } } else if (strncmp(option, "ro", 2) == 0) { /* root */ ptr = strchr(option, '='); if (ptr != NULL) { sscanf(++ptr, "%s", rootServerName); } } else if (strncmp(option, "sea", 3) == 0) { /* search list */ _res.options |= RES_DNSRCH; } else if (strncmp(option, "nosea", 5) == 0) { _res.options &= ~RES_DNSRCH; } else if (strncmp(option, "srchl", 5) == 0) { /* domain search list */ ptr = strchr(option, '='); if (ptr != NULL) { res_dnsrch(++ptr); } } else if (strncmp(option, "ti", 2) == 0) { /* timeout */ ptr = strchr(option, '='); if (ptr != NULL) { sscanf(++ptr, "%d", &tmp); if (tmp >= 0) { _res.retrans = tmp; } } } else if (strncmp(option, "v", 1) == 0) { /* vc */ _res.options |= RES_USEVC; } else if (strncmp(option, "nov", 3) == 0) { _res.options &= ~RES_USEVC; } else { fprintf(stderr, "*** Invalid option: %s\n", option); return(ERROR); } } return(SUCCESS); } /* * Fake a reinitialization when the domain is changed. */ res_re_init() { register char *cp, **pp; int n; /* find components of local domain that might be searched */ pp = _res.dnsrch; *pp++ = _res.defdname; for (cp = _res.defdname, n = 0; *cp; cp++) if (*cp == '.') n++; cp = _res.defdname; for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH; n--) { cp = strchr(cp, '.'); *pp++ = ++cp; } *pp = 0; _res.options |= RES_INIT; } #define SRCHLIST_SEP '/' res_dnsrch(cp) register char *cp; { register char **pp; int n; (void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1); if ((cp = strchr(_res.defdname, '\n')) != NULL) *cp = '\0'; /* * Set search list to be blank-separated strings * on rest of line. */ cp = _res.defdname; pp = _res.dnsrch; *pp++ = cp; for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) { if (*cp == SRCHLIST_SEP) { *cp = '\0'; n = 1; } else if (n) { *pp++ = cp; n = 0; } } if ((cp = strchr(pp[-1], SRCHLIST_SEP)) != NULL) { *cp = '\0'; } *pp = NULL; } /* ******************************************************************************* * * ShowOptions -- * * Prints out the state information used by the resolver * library and other options set by the user. * ******************************************************************************* */ void ShowOptions() { register char **cp; PrintHostInfo(stdout, "Default Server:", defaultPtr); if (curHostValid) { PrintHostInfo(stdout, "Host:", &curHostInfo); } printf("Set options:\n"); printf(" %sdebug \t", (_res.options & RES_DEBUG) ? "" : "no"); printf(" %sdefname\t", (_res.options & RES_DEFNAMES) ? "" : "no"); printf(" %ssearch\t", (_res.options & RES_DNSRCH) ? "" : "no"); printf(" %srecurse\n", (_res.options & RES_RECURSE) ? "" : "no"); printf(" %sd2\t\t", (_res.options & RES_DEBUG2) ? "" : "no"); printf(" %svc\t\t", (_res.options & RES_USEVC) ? "" : "no"); printf(" %signoretc\t", (_res.options & RES_IGNTC) ? "" : "no"); printf(" port=%u\n", nsport); printf(" querytype=%s\t", p_type(queryType)); printf(" class=%s\t", p_class(queryClass)); printf(" timeout=%d\t", _res.retrans); printf(" retry=%d\n", _res.retry); printf(" root=%s\n", rootServerName); printf(" domain=%s\n", _res.defdname); if (cp = _res.dnsrch) { printf(" srchlist=%s", *cp); for (cp++; *cp; cp++) { printf("%c%s", SRCHLIST_SEP, *cp); } putchar('\n'); } putchar('\n'); } #undef SRCHLIST_SEP /* ******************************************************************************* * * PrintHelp -- * * Prints out the help file. * (Code taken from Mail.) * ******************************************************************************* */ void PrintHelp() { register int c; register FILE *helpFilePtr; if ((helpFilePtr = fopen(_PATH_HELPFILE, "r")) == NULL) { perror(_PATH_HELPFILE); return; } while ((c = getc(helpFilePtr)) != EOF) { putchar((char) c); } fclose(helpFilePtr); } /* ******************************************************************************* * * CvtAddrToPtr -- * * Convert a dotted-decimal Internet address into the standard * PTR format (reversed address with .in-arpa. suffix). * * Assumes the argument buffer is large enougth to hold the result. * ******************************************************************************* */ static void CvtAddrToPtr(name) char *name; { char *p; int ip[4]; struct in_addr addr; if (IsAddr(name, &addr.s_addr)) { p = inet_ntoa(addr); if (sscanf(p, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]) == 4) { sprintf(name, "%d.%d.%d.%d.in-addr.arpa.", ip[3], ip[2], ip[1], ip[0]); } } } /* ******************************************************************************* * * ReadRC -- * * Use the contents of ~/.nslookuprc as options. * ******************************************************************************* */ static void ReadRC() { register FILE *fp; register char *cp; char buf[NAME_LEN]; if ((cp = getenv("HOME")) != NULL) { (void) strcpy(buf, cp); (void) strcat(buf, "/.nslookuprc"); if ((fp = fopen(buf, "r")) != NULL) { while (fgets(buf, sizeof(buf), fp) != NULL) { if ((cp = strchr(buf, '\n')) != NULL) { *cp = '\0'; } (void) SetOption(buf); } (void) fclose(fp); } } } %s for writing\n", file); return(ERROR); } fprintf(filePtr,"> %s\n", string); } result = GetHostInfoByName( defaultPtr->addrList ? (struct in_addr *) defaultPtr->addrList[0] : (struct in_addr *) defaultPtr->servers[0]->addrList[0], C_IN, T_A, server, &serverInfo, 1); if (resultetc/named/tools/nslookup/skip.c 644 0 0 10342 5367003451 12013 /* * Copyright (c) 1985 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) static char sccsid[] = "@(#)skip.c 5.9 (Berkeley) 8/3/90"; #endif /* ******************************************************************************* * * skip.c -- * * Routines to skip over portions of a query buffer. * * Note: this file has been submitted for inclusion in * BIND resolver library. When this has been done, this file * is no longer necessary (assuming there haven't been any * changes). * * Adapted from 4.3BSD BIND res_debug.c * ******************************************************************************* */ #include #include #include #include #include "res.h" char *res_skip_rr(); /* ******************************************************************************* * * res_skip -- * * Skip the contents of a query. * * Interpretation of numFieldsToSkip argument: * res_skip returns pointer to: * 1 -> start of question records. * 2 -> start of authoritative answer records. * 3 -> start of additional records. * 4 -> first byte after end of additional records. * * Results: * (address) - success operation. * NULL - a resource record had an incorrect format. * ******************************************************************************* */ char * res_skip(msg, numFieldsToSkip, eom) char *msg; int numFieldsToSkip; char *eom; { register char *cp; register HEADER *hp; register int tmp; register int n; /* * Skip the header fields. */ hp = (HEADER *)msg; cp = msg + sizeof(HEADER); /* * skip question records. */ if (n = ntohs(hp->qdcount) ) { while (--n >= 0 && cp < eom) { tmp = dn_skipname(cp, eom); if (tmp == -1) return(NULL); cp += tmp; cp += sizeof(u_short); /* type */ cp += sizeof(u_short); /* class */ } } if (--numFieldsToSkip <= 0) return(cp); /* * skip authoritative answer records */ if (n = ntohs(hp->ancount)) { while (--n >= 0 && cp < eom) { cp = res_skip_rr(cp, eom); if (cp == NULL) return(NULL); } } if (--numFieldsToSkip == 0) return(cp); /* * skip name server records */ if (n = ntohs(hp->nscount)) { while (--n >= 0 && cp < eom) { cp = res_skip_rr(cp, eom); if (cp == NULL) return(NULL); } } if (--numFieldsToSkip == 0) return(cp); /* * skip additional records */ if (n = ntohs(hp->arcount)) { while (--n >= 0 && cp < eom) { cp = res_skip_rr(cp, eom); if (cp == NULL) return(NULL); } } return(cp); } /* ******************************************************************************* * * res_skip_rr -- * * Skip over resource record fields. * * Results: * (address) - success operation. * NULL - a resource record had an incorrect format. ******************************************************************************* */ char * res_skip_rr(cp, eom) char *cp; char *eom; { int tmp; int dlen; if ((tmp = dn_skipname(cp, eom)) == -1) return (NULL); /* compression error */ cp += tmp; if ((cp + RRFIXEDSZ) > eom) return (NULL); cp += sizeof(u_short); /* type */ cp += sizeof(u_short); /* class */ cp += sizeof(u_long); /* ttl */ dlen = _getshort(cp); cp += sizeof(u_short); /* dlen */ cp += dlen; if (cp > eom) return (NULL); return (cp); } a query buffer. * * Note: this file has been submitted for inclusion in * BIND resolver library. When this has been done, this file * is no longer necessary (assuming there haven't been any * changes). * * Adapted from 4.3BSD BIND res_debug.c * ********************************etc/named/tools/nslookup/nslookup.help 644 0 0 3236 4630137542 13412 Commands: (identifiers are shown in uppercase, [] means optional) NAME - print info about the host/domain NAME using default server NAME1 NAME2 - as above, but use NAME2 as server help or ? - print info on common commands; see nslookup(1) for details set OPTION - set an option all - print options, current server and host [no]debug - print debugging information [no]d2 - print exhaustive debugging information [no]defname - append domain name to each query [no]recurse - ask for recursive answer to query [no]vc - always use a virtual circuit domain=NAME - set default domain name to NAME srchlist=N1[/N2/.../N6] - set domain to N1 and search list to N1,N2, etc. root=NAME - set root server to NAME retry=X - set number of retries to X timeout=X - set initial time-out interval to X seconds querytype=X - set query type, e.g., A,ANY,CNAME,HINFO,MX,NS,PTR,SOA,WKS type=X - synonym for querytype class=X - set query class to one of IN (Internet), CHAOS, HESIOD or ANY server NAME - set default server to NAME, using current default server lserver NAME - set default server to NAME, using initial server finger [USER] - finger the optional NAME at the current default host root - set current default server to the root ls [opt] DOMAIN [> FILE] - list addresses in DOMAIN (optional: output to FILE) -a - list canonical names and aliases -h - list HINFO (CPU type and operating system) -s - list well-known services -d - list all records -t TYPE - list records of the given type (e.g., A,CNAME,MX, etc.) view FILE - sort an 'ls' output file and view it with more exit - exit the program, ^D also exits .h" char *res_skip_rr(); /* ******************************************************************************* * * res_skip -- * * Skip the contents of a query. * * Interpretation of numFieldsToSkip argument: * res_skip returns pointer to: * 1 -> start of question records. * 2 -> start of authoritative answer records.etc/named/tools/nslookup/pathnames.h 644 0 0 2116 5367000771 13014 /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)pathnames.h 5.1 (Berkeley) 5/28/90 */ #define _PATH_HELPFILE "/usr/lib/nslookup.help" ver NAME - set default server to NAME, using initial server finger [USER] - finger the optional NAME at the current default host root - set current default server to the root ls [opt] DOMAIN [> FILE] - list addresses in DOMAIN (optional: output to FILE) -a - list canonical names and aliases -h - list HINFO (CPU type and operating system) -s - list well-known services -d - list all records -t TYPE etc/named/tools/nslookup/res_debug.c 644 0 0 24321 5367005477 13020 /*- * Copyright (c) 1985, 1990 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * @(#)res_debug.c 5.30 (Berkeley) 6/27/90 */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)res_debug.c 5.30 (Berkeley) 6/27/90"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include "res.h" extern char *p_cdname(), *p_rr(), *p_type(), *p_class(), *p_time(); extern char *inet_ntoa(); char *_res_opcodes[] = { "QUERY", "IQUERY", "CQUERYM", "CQUERYU", "4", "5", "6", "7", "8", "UPDATEA", "UPDATED", "UPDATEDA", "UPDATEM", "UPDATEMA", "ZONEINIT", "ZONEREF", }; char *_res_resultcodes[] = { "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP", "REFUSED", "6", "7", "8", "9", "10", "11", "12", "13", "14", "NOCHANGE", }; p_query(msg) char *msg; { fp_query(msg,stdout); } /* * Print the contents of a query. * This is intended to be primarily a debugging routine. */ fp_query(msg,file) char *msg; FILE *file; { register char *cp; register HEADER *hp; register int n; /* * Print header fields. */ hp = (HEADER *)msg; cp = msg + sizeof(HEADER); fprintf(file,"HEADER:\n"); fprintf(file,"\topcode = %s", _res_opcodes[hp->opcode]); fprintf(file,", id = %d", ntohs(hp->id)); fprintf(file,", rcode = %s\n", _res_resultcodes[hp->rcode]); fprintf(file,"\theader flags: "); if (hp->qr) fprintf(file," qr"); if (hp->aa) fprintf(file," aa"); if (hp->tc) fprintf(file," tc"); if (hp->rd) fprintf(file," rd"); if (hp->ra) fprintf(file," ra"); if (hp->pr) fprintf(file," pr"); fprintf(file,"\n\tqdcount = %d", ntohs(hp->qdcount)); fprintf(file,", ancount = %d", ntohs(hp->ancount)); fprintf(file,", nscount = %d", ntohs(hp->nscount)); fprintf(file,", arcount = %d\n\n", ntohs(hp->arcount)); /* * Print question records. */ if (n = ntohs(hp->qdcount)) { fprintf(file,"QUESTIONS:\n"); while (--n >= 0) { fprintf(file,"\t"); cp = p_cdname(cp, msg, file); if (cp == NULL) return; fprintf(file,", type = %s", p_type(_getshort(cp))); cp += sizeof(u_short); fprintf(file,", class = %s\n\n", p_class(_getshort(cp))); cp += sizeof(u_short); } } /* * Print authoritative answer records */ if (n = ntohs(hp->ancount)) { fprintf(file,"ANSWERS:\n"); while (--n >= 0) { fprintf(file,"\t"); cp = p_rr(cp, msg, file); if (cp == NULL) return; } } /* * print name server records */ if (n = ntohs(hp->nscount)) { fprintf(file,"NAME SERVERS:\n"); while (--n >= 0) { fprintf(file,"\t"); cp = p_rr(cp, msg, file); if (cp == NULL) return; } } /* * print additional records */ if (n = ntohs(hp->arcount)) { fprintf(file,"ADDITIONAL RECORDS:\n"); while (--n >= 0) { fprintf(file,"\t"); cp = p_rr(cp, msg, file); if (cp == NULL) return; } } } char * p_cdname(cp, msg, file) char *cp, *msg; FILE *file; { char name[MAXDNAME]; int n; if ((n = dn_expand(msg, msg + 512, cp, name, sizeof(name))) < 0) return (NULL); if (name[0] == '\0') { name[0] = '.'; name[1] = '\0'; } fputs(name, file); return (cp + n); } /* * Print resource record fields in human readable form. */ char * p_rr(cp, msg, file) char *cp, *msg; FILE *file; { int type, class, dlen, n, c; struct in_addr inaddr; char *cp1, *cp2; if ((cp = p_cdname(cp, msg, file)) == NULL) return (NULL); /* compression error */ fprintf(file,"\n\ttype = %s", p_type(type = _getshort(cp))); cp += sizeof(u_short); fprintf(file,", class = %s", p_class(class = _getshort(cp))); cp += sizeof(u_short); fprintf(file,", ttl = %s", p_time(_getlong(cp))); cp += sizeof(u_long); fprintf(file,", dlen = %d\n", dlen = _getshort(cp)); cp += sizeof(u_short); cp1 = cp; /* * Print type specific data, if appropriate */ switch (type) { case T_A: switch (class) { case C_IN: case C_HS: bcopy(cp, (char *)&inaddr, sizeof(inaddr)); if (dlen == 4) { fprintf(file,"\tinternet address = %s\n", inet_ntoa(inaddr)); cp += dlen; } else if (dlen == 7) { fprintf(file,"\tinternet address = %s", inet_ntoa(inaddr)); fprintf(file,", protocol = %d", cp[4]); fprintf(file,", port = %d\n", (cp[5] << 8) + cp[6]); cp += dlen; } break; default: cp += dlen; } break; case T_CNAME: case T_MB: case T_MG: case T_MR: case T_NS: case T_PTR: fprintf(file,"\tdomain name = "); cp = p_cdname(cp, msg, file); fprintf(file,"\n"); break; case T_HINFO: if (n = *cp++) { fprintf(file,"\tCPU=%.*s\n", n, cp); cp += n; } if (n = *cp++) { fprintf(file,"\tOS=%.*s\n", n, cp); cp += n; } break; case T_SOA: fprintf(file,"\torigin = "); cp = p_cdname(cp, msg, file); fprintf(file,"\n\tmail addr = "); cp = p_cdname(cp, msg, file); fprintf(file,"\n\tserial = %ld", _getlong(cp)); cp += sizeof(u_long); fprintf(file,"\n\trefresh = %s", p_time(_getlong(cp))); cp += sizeof(u_long); fprintf(file,"\n\tretry = %s", p_time(_getlong(cp))); cp += sizeof(u_long); fprintf(file,"\n\texpire = %s", p_time(_getlong(cp))); cp += sizeof(u_long); fprintf(file,"\n\tmin = %s\n", p_time(_getlong(cp))); cp += sizeof(u_long); break; case T_MX: fprintf(file,"\tpreference = %ld,",_getshort(cp)); cp += sizeof(u_short); fprintf(file," name = "); cp = p_cdname(cp, msg, file); break; case T_TXT: (void) fputs("\t\"", file); cp2 = cp1 + dlen; while (cp < cp2) { if (n = (unsigned char) *cp++) { for (c = n; c > 0 && cp < cp2; c--) if (*cp == '\n') { (void) putc('\\', file); (void) putc(*cp++, file); } else (void) putc(*cp++, file); } } (void) fputs("\"\n", file); break; case T_MINFO: fprintf(file,"\trequests = "); cp = p_cdname(cp, msg, file); fprintf(file,"\n\terrors = "); cp = p_cdname(cp, msg, file); break; case T_UINFO: fprintf(file,"\t%s\n", cp); cp += dlen; break; case T_UID: case T_GID: if (dlen == 4) { fprintf(file,"\t%ld\n", _getlong(cp)); cp += sizeof(int); } break; case T_WKS: if (dlen < sizeof(u_long) + 1) break; bcopy(cp, (char *)&inaddr, sizeof(inaddr)); cp += sizeof(u_long); fprintf(file,"\tinternet address = %s, protocol = %d\n\t", inet_ntoa(inaddr), *cp++); n = 0; while (cp < cp1 + dlen) { c = *cp++; do { if (c & 0200) fprintf(file," %d", n); c <<= 1; } while (++n & 07); } putc('\n',file); break; #ifdef ALLOW_T_UNSPEC case T_UNSPEC: { int NumBytes = 8; char *DataPtr; int i; if (dlen < NumBytes) NumBytes = dlen; fprintf(file, "\tFirst %d bytes of hex data:", NumBytes); for (i = 0, DataPtr = cp; i < NumBytes; i++, DataPtr++) fprintf(file, " %x", *DataPtr); fputs("\n", file); cp += dlen; } break; #endif /* ALLOW_T_UNSPEC */ default: fprintf(file,"\t???\n"); cp += dlen; } if (cp != cp1 + dlen) { fprintf(file,"packet size error (%#x != %#x)\n", cp, cp1+dlen); cp = NULL; } fprintf(file,"\n"); return (cp); } static char nbuf[40]; /* * Return a string for the type */ char * p_type(type) int type; { switch (type) { case T_A: return("A"); case T_NS: /* authoritative server */ return("NS"); case T_CNAME: /* canonical name */ return("CNAME"); case T_SOA: /* start of authority zone */ return("SOA"); case T_MB: /* mailbox domain name */ return("MB"); case T_MG: /* mail group member */ return("MG"); case T_MR: /* mail rename name */ return("MR"); case T_NULL: /* null resource record */ return("NULL"); case T_WKS: /* well known service */ return("WKS"); case T_PTR: /* domain name pointer */ return("PTR"); case T_HINFO: /* host information */ return("HINFO"); case T_MINFO: /* mailbox information */ return("MINFO"); case T_MX: /* mail routing info */ return("MX"); case T_TXT: /* text */ return("TXT"); case T_AXFR: /* zone transfer */ return("AXFR"); case T_MAILB: /* mail box */ return("MAILB"); case T_MAILA: /* mail address */ return("MAILA"); case T_ANY: /* matches any type */ return("ANY"); case T_UINFO: return("UINFO"); case T_UID: return("UID"); case T_GID: return("GID"); #ifdef ALLOW_T_UNSPEC case T_UNSPEC: return("UNSPEC"); #endif /* ALLOW_T_UNSPEC */ default: (void)sprintf(nbuf, "%d", type); return(nbuf); } } /* * Return a mnemonic for class */ char * p_class(class) int class; { switch (class) { case C_IN: /* internet class */ return("IN"); case C_HS: /* hesiod class */ return("HS"); case C_ANY: /* matches any class */ return("ANY"); default: (void)sprintf(nbuf, "%d", class); return(nbuf); } } /* * Return a mnemonic for a time to live */ char * p_time(value) u_long value; { int secs, mins, hours; register char *p; if (value == 0) { strcpy(nbuf, "0 secs"); return(nbuf); } secs = value % 60; value /= 60; mins = value % 60; value /= 60; hours = value % 24; value /= 24; #define PLURALIZE(x) x, (x == 1) ? "" : "s" p = nbuf; if (value) { (void)sprintf(p, "%d day%s", PLURALIZE(value)); while (*++p); } if (hours) { if (value) *p++ = ' '; (void)sprintf(p, "%d hour%s", PLURALIZE(hours)); while (*++p); } if (mins) { if (value || hours) *p++ = ' '; (void)sprintf(p, "%d min%s", PLURALIZE(mins)); while (*++p); } if (secs || ! (value || hours || mins)) { if (value || hours || mins) *p++ = ' '; (void)sprintf(p, "%d sec%s", PLURALIZE(secs)); } return(nbuf); } , server); } if (putToFile) { fclose(filePtr); filePtr = NULL; } return(result); } /* ******************************************************************************* * * SetOption -- * * This routine is used to change the state information * that affect the lookups. The commetc/named/tools/Makefile 644 0 0 3307 5367014326 10455 # # Copyright (c) 1987 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that the above copyright notice and this paragraph are # duplicated in all such forms and that any documentation, # advertising materials, and other materials related to such # distribution and use acknowledge that the software was developed # by the University of California, Berkeley. The name of the # University may not be used to endorse or promote products derived # from this software without specific prior written permission. # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # @(#)Makefile 4.9 (Berkeley) 10/10/88 # CFLAGS= -O RES= LIBC= /lib/libc.a SRCS= nsquery.c nstest.c OBJS= all: nsquery nstest nslookup nsquery: ${LIBC} ${CC} ${CFLAGS} -i -o $@ nsquery.c ${RES} # test programs and utilities nstest: ${LIBC} @echo "The resolver routines in libc must be compiled with the -DDEBUG" @echo "option or nstest will not have any output." ${CC} ${CFLAGS} -i -o $@ nstest.c ${RES} nslookup: FRC cd nslookup; make ${MFLAGS} RES=${RES} clean: FRC cd nslookup; make ${MFLAGS} clean rm -f ${OBJS} core nsquery nstest depend: ${SRCS} cd nslookup; make ${MFLAGS} depend mkdep -p ${CFLAGS} ${SRCS} install: ${MAN} cd nslookup; make ${MFLAGS} DESTDIR=${DESTDIR} install install -s -m 555 nsquery ${DESTDIR}/usr/bin install -s -m 555 nstest ${DESTDIR}/usr/bin lint: ${SRCS} cd nslookup; make ${MFLAGS} lint lint -axc ${SRCS} tags: ${SRCS} cd nslookup; make ${MFLAGS} tags ctags ${SRCS} FRC: : case T_NS: case T_PTR: fprintf(file,"\tdomain name = "); cp = p_cdname(cp, msg, file); fprintf(file,"\n"); break; case T_HINFO: if (n = *cp++) { fprintf(file,"\tCPU=%.*s\n", n, cp); cp += n; } if (n = *cp++) { fprintf(file,"\tOS=%.*s\n", n, cp); cp += n; } break; case T_SOA:etc/named/tools/nsquery.c 644 0 0 5016 5367013454 10667 /* * Copyright (c) 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1986 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)nsquery.c 4.8 (Berkeley) 6/1/90"; #endif #include #include #include #include #include #include #include main(argc, argv) int argc; char **argv; { extern struct state _res; register struct hostent *hp; if (argc >= 2 && strcmp(argv[1], "-d") == 0) { _res.options |= RES_DEBUG; argc--; argv++; } if (argc < 2) { fprintf(stderr, "usage: nsquery [-d] host [server]\n"); exit(1); } if (argc == 3) { hp = gethostbyname(argv[2]); if (hp == NULL) { fprintf(stderr, "nsquery:"); herror(argv[2]); exit(1); } printf("\nServer:\n"); printanswer(hp); _res.nsaddr.sin_addr = *(struct in_addr *)hp->h_addr; } hp = gethostbyname(argv[1]); if (hp == NULL) { fprintf(stderr, "nsquery: %s: ", argv[1]); herror((char *)NULL); exit(1); } printanswer(hp); exit(0); } printanswer(hp) register struct hostent *hp; { register char **cp; extern char *inet_ntoa(); printf("Name: %s\n", hp->h_name); #if BSD >= 43 || defined(h_addr) printf("Addresses:"); for (cp = hp->h_addr_list; cp && *cp; cp++) printf(" %s", inet_ntoa(*(struct in_addr *)(*cp))); printf("\n"); #else printf("Address: %s\n", inet_ntoa(*(struct in_addr *)hp->h_addr)); #endif printf("Aliases:"); for (cp = hp->h_aliases; cp && *cp && **cp; cp++) printf(" %s", *cp); printf("\n\n"); } ); break; case T_MX: fprintf(file,"\tpreference = %ld,",_getshort(cp)); cp += sizeof(u_short); fprintf(file," name = "); cp = p_cdname(cp, msg, file); break; case T_TXT: (void) fputs("\t\"", file); cp2 = cp1 + dlen; while (cp < cp2) { if (n = (unsigned char) *cp++) { for (c = n; c > 0 && cp < cp2; c--) if (*cp == '\n') { (void) putc('\\', file); (void) putc(*cp++, file); } else (void) putc(*cp++, file); } } (void) fputsetc/named/tools/nstest.c 644 0 0 22403 5367014611 10514 /* * Copyright (c) 1986, 1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted provided * that: (1) source distributions retain this entire copyright notice and * comment, and (2) distributions including binaries display the following * acknowledgement: ``This product includes software developed by the * University of California, Berkeley and its contributors'' in the * documentation or other materials provided with the distribution and in * all advertising materials mentioning features or use of this software. * Neither the name of the University nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #if !defined(lint) && defined(DOSCCS) char copyright[] = "@(#) Copyright (c) 1986 Regents of the University of California.\n\ All rights reserved.\n"; static char sccsid[] = "@(#)nstest.c 4.12 (Berkeley) 6/1/90"; #endif #include #include #include #include #include #include extern char *inet_ntoa(); char *progname; FILE *log; #define MAXDATA 256 /* really should get definition from named/db.h */ main(argc, argv) char **argv; { register char *cp; u_short port = htons(NAMESERVER_PORT); char buf[BUFSIZ]; char packet[PACKETSZ]; char answer[PACKETSZ]; struct rrec NewRR; int n, dump_packet; NewRR.r_data = (char *) malloc(MAXDATA); NewRR.r_data = (char *) malloc(MAXDATA); progname = argv[0]; dump_packet = 0; _res.options |= RES_DEBUG|RES_RECURSE; (void) res_init(); while (argc > 1 && argv[1][0] == '-') { argc--; cp = *++argv; while (*++cp) switch (*cp) { case 'p': if (--argc <= 0) usage(); port = htons(atoi(*++argv)); break; case 'i': _res.options |= RES_IGNTC; break; case 'v': _res.options |= RES_USEVC|RES_STAYOPEN; break; case 'r': _res.options &= ~RES_RECURSE; break; case 'd': dump_packet++; break; default: usage(); } } _res.nsaddr.sin_family = AF_INET; _res.nsaddr.sin_addr.s_addr = INADDR_ANY; _res.nsaddr.sin_port = port; if (argc > 1) { _res.nsaddr.sin_addr.s_addr = inet_addr(argv[1]); if (_res.nsaddr.sin_addr.s_addr == (u_long) -1) usage(); } if (argc > 2) { log = fopen(argv[2],"w"); if (log == NULL) perror(argv[2]); } for (;;) { printf("> "); fflush(stdout); if ((cp = (char *)gets(buf)) == NULL) break; switch (*cp++) { case 'a': n = res_mkquery(QUERY, cp, C_IN, T_A, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'A': n = ntohl(inet_addr(cp)); putlong(n, cp); n = res_mkquery(IQUERY, "", C_IN, T_A, cp, sizeof(long), NULL, packet, sizeof(packet)); break; case 'f': n = res_mkquery(QUERY, cp, C_ANY, T_UINFO, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'g': n = res_mkquery(QUERY, cp, C_ANY, T_GID, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'G': *(int *)cp = htonl(atoi(cp)); n = res_mkquery(IQUERY, "", C_ANY, T_GID, cp, sizeof(int), NULL, packet, sizeof(packet)); break; case 'c': n = res_mkquery(QUERY, cp, C_IN, T_CNAME, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'h': n = res_mkquery(QUERY, cp, C_IN, T_HINFO, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'm': n = res_mkquery(QUERY, cp, C_IN, T_MX, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'M': n = res_mkquery(QUERY, cp, C_IN, T_MAILB, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'n': n = res_mkquery(QUERY, cp, C_IN, T_NS, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'p': n = res_mkquery(QUERY, cp, C_IN, T_PTR, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 's': n = res_mkquery(QUERY, cp, C_IN, T_SOA, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'T': n = res_mkquery(QUERY, cp, C_IN, T_TXT, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'u': n = res_mkquery(QUERY, cp, C_ANY, T_UID, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'U': *(int *)cp = htonl(atoi(cp)); n = res_mkquery(IQUERY, "", C_ANY, T_UID, cp, sizeof(int), NULL, packet, sizeof(packet)); break; case 'x': n = res_mkquery(QUERY, cp, C_IN, T_AXFR, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'w': n = res_mkquery(QUERY, cp, C_IN, T_WKS, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'b': n = res_mkquery(QUERY, cp, C_IN, T_MB, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'B': n = res_mkquery(QUERY, cp, C_IN, T_MG, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'i': n = res_mkquery(QUERY, cp, C_IN, T_MINFO, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'r': n = res_mkquery(QUERY, cp, C_IN, T_MR, (char *)0, 0, NULL, packet, sizeof(packet)); break; case '*': n = res_mkquery(QUERY, cp, C_IN, T_ANY, (char *)0, 0, NULL, packet, sizeof(packet)); break; #ifdef ALLOW_UPDATES case '^': { char IType[10], TempStr[50]; int Type, oldnbytes, nbytes, i; #ifdef ALLOW_T_UNSPEC printf("Data type (a = T_A, u = T_UNSPEC): "); gets(IType); if (IType[0] == 'u') { Type = T_UNSPEC; printf("How many data bytes? "); gets(TempStr); /* Throw away CR */ sscanf(TempStr, "%d", &nbytes); for (i = 0; i < nbytes; i++) { (NewRR.r_data)[i] = (char) i; } } else { #endif ALLOW_T_UNSPEC Type = T_A; nbytes = sizeof(u_long); printf("Inet addr for new dname (e.g., 192.4.3.2): "); gets(TempStr); putlong(ntohl(inet_addr(TempStr)), NewRR.r_data); #ifdef ALLOW_T_UNSPEC } #endif ALLOW_T_UNSPEC NewRR.r_class = C_IN; NewRR.r_type = Type; NewRR.r_size = nbytes; NewRR.r_ttl = 99999999; printf("Add, modify, or modify all (a/m/M)? "); gets(TempStr); if (TempStr[0] == 'a') { n = res_mkquery(UPDATEA, cp, C_IN, Type, OldRRData, nbytes, &NewRR, packet, sizeof(packet)); } else { if (TempStr[0] == 'm') { printf("How many data bytes in old RR? "); gets(TempStr); /* Throw away CR */ sscanf(TempStr, "%d", &oldnbytes); for (i = 0; i < oldnbytes; i++) { OldRRData[i] = (char) i; } n = res_mkquery(UPDATEM, cp, C_IN, Type, OldRRData, oldnbytes, &NewRR, packet, sizeof(packet)); } else { /* Modify all */ n = res_mkquery(UPDATEMA, cp, C_IN, Type, NULL, 0, &NewRR, packet, sizeof(packet)); } } } break; #ifdef ALLOW_T_UNSPEC case 'D': n = res_mkquery(UPDATEDA, cp, C_IN, T_UNSPEC, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'd': { char TempStr[100]; int nbytes, i; printf("How many data bytes in oldrr data? "); gets(TempStr); /* Throw away CR */ sscanf(TempStr, "%d", &nbytes); for (i = 0; i < nbytes; i++) { OldRRData[i] = (char) i; } n = res_mkquery(UPDATED, cp, C_IN, T_UNSPEC, OldRRData, nbytes, NULL, packet, sizeof(packet)); } break; #endif ALLOW_T_UNSPEC #endif ALLOW_UPDATES default: printf("a{host} - query T_A\n"); printf("A{addr} - iquery T_A\n"); printf("b{user} - query T_MB\n"); printf("B{user} - query T_MG\n"); printf("f{host} - query T_UINFO\n"); printf("g{host} - query T_GID\n"); printf("G{gid} - iquery T_GID\n"); printf("h{host} - query T_HINFO\n"); printf("i{host} - query T_MINFO\n"); printf("p{host} - query T_PTR\n"); printf("m{host} - query T_MX\n"); printf("M{host} - query T_MAILB\n"); printf("n{host} - query T_NS\n"); printf("r{host} - query T_MR\n"); printf("s{host} - query T_SOA\n"); printf("T{host} - query T_TXT\n"); printf("u{host} - query T_UID\n"); printf("U{uid} - iquery T_UID\n"); printf("x{host} - query T_AXFR\n"); printf("w{host} - query T_WKS\n"); printf("c{host} - query T_CNAME\n"); printf("*{host} - query T_ANY\n"); #ifdef ALLOW_UPDATES printf("^{host} - add/mod/moda (T_A/T_UNSPEC)\n"); #ifdef ALLOW_T_UNSPEC printf("D{host} - deletea T_UNSPEC\n"); printf("d{host} - delete T_UNSPEC\n"); #endif ALLOW_T_UNSPEC #endif ALLOW_UPDATES continue; } if (n < 0) { printf("res_mkquery: buffer too small\n"); continue; } if (log) { fprintf(log,"SEND QUERY\n"); fp_query(packet, log); } n = res_send(packet, n, answer, sizeof(answer)); if (n < 0) { printf("res_send: send error\n"); if (log) fprintf(log, "res_send: send error\n"); } else { if (dump_packet) { int f; f = creat("ns_packet.dump", 0644); write(f, answer, n); (void) close(f); } if (log) { fprintf(log, "GOT ANSWER\n"); fp_query(answer, log); } } } } usage() { fprintf(stderr, "Usage: %s [-v] [-i] [-r] [-d] [-p port] hostaddr\n", progname); exit(1); } RY, cp, C_IN, T_A, (char *)0, 0, NULL, packet, sizeof(packet)); break; case 'A': n = ntohl(inet_addr(cp)); putlong(n, cp); n = res_mkquery(IQUERY, "", C_IN, T_A, cp, sizeof(long), NULL, packet, sizeof(packet)); break; case 'etc/named/Makefile 640 0 12 1507 5327167717 7345 # # Copyright (c) 1987 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that this notice is preserved and that due credit is given # to the University of California at Berkeley. The name of the University # may not be used to endorse or promote products derived from this # software without specific prior written permission. This software # is provided ``as is'' without express or implied warranty. # # @(#)Makefile 4.14 (Berkeley) 2/28/88 # SUBDIR= tools named all: named tools tools: FRC (cd tools; make ${MFLAGS} ); named: FRC (cd named; make ${MFLAGS} named); clean: FRC for i in ${SUBDIR}; do \ (cd $$i; make ${MFLAGS} clean); \ done install: all (cd named; make ${MFLAGS} install); (cd tools; make ${MFLAGS} install); FRC: < nbytes; i++) { OldRRData[i] = (char) i; } n = res_mkquery(UPDATED, cp, C_IN, T_UNSPEC, OldRRData, nbytes, NULL, packet, sizeof(packet)); } break; #endietc/named/doc/ 755 0 12 0 4310163574 6352 etc/named/doc/rfc1034.lpr 640 0 12 366227 4212204763 10311 Network Working Group P. Mockapetris Request for Comments: 1034 ISI Obsoletes: RFCs 882, 883, 973 November 1987 DOMAIN NAMES - CONCEPTS AND FACILITIES 1. STATUS OF THIS MEMO This RFC is an introduction to the Domain Name System (DNS), and omits many details which can be found in a companion RFC, "Domain Names - Implementation and Specification" [RFC-1035]. That RFC assumes that the reader is familiar with the concepts discussed in this memo. A subset of DNS functions and data types constitute an official protocol. The official protocol includes standard queries and their responses and most of the Internet class data formats (e.g., host addresses). However, the domain system is intentionally extensible. Researchers are continuously proposing, implementing and experimenting with new data types, query types, classes, functions, etc. Thus while the components of the official protocol are expected to stay essentially unchanged and operate as a production service, experimental behavior should always be expected in extensions beyond the official protocol. Experimental or obsolete features are clearly marked in these RFCs, and such information should be used with caution. The reader is especially cautioned not to depend on the values which appear in examples to be current or complete, since their purpose is primarily pedagogical. Distribution of this memo is unlimited. 2. INTRODUCTION This RFC introduces domain style names, their use for Internet mail and host address support, and the protocols and servers used to implement domain name facilities. 2.1. The history of domain names The impetus for the development of the domain system was growth in the Internet: - Host name to address mappings were maintained by the Network Information Center (NIC) in a single file (HOSTS.TXT) which was FTPed by all hosts [RFC-952, RFC-953]. The total network Mockapetris [Page 1] RFC 1034 Domain Concepts and Facilities November 1987 bandwidth consumed in distributing a new version by this scheme is proportional to the square of the number of hosts in the network, and even when multiple levels of FTP are used, the outgoing FTP load on the NIC host is considerable. Explosive growth in the number of hosts didn't bode well for the future. - The network population was also changing in character. The timeshared hosts that made up the original ARPANET were being replaced with local networks of workstations. Local organizations were administering their own names and addresses, but had to wait for the NIC to change HOSTS.TXT to make changes visible to the Internet at large. Organizations also wanted some local structure on the name space. - The applications on the Internet were getting more sophisticated and creating a need for general purpose name service. The result was several ideas about name spaces and their management [IEN-116, RFC-799, RFC-819, RFC-830]. The proposals varied, but a common thread was the idea of a hierarchical name space, with the hierarchy roughly corresponding to organizational structure, and names using "." as the character to mark the boundary between hierarchy levels. A design using a distributed database and generalized resources was described in [RFC-882, RFC-883]. Based on experience with several implementations, the system evolved into the scheme described in this memo. The terms "domain" or "domain name" are used in many contexts beyond the DNS described here. Very often, the term domain name is used to refer to a name with structure indicated by dots, but no relation to the DNS. This is particularly true in mail addressing [Quarterman 86]. 2.2. DNS design goals The design goals of the DNS influence its structure. They are: - The primary goal is a consistent name space which will be used for referring to resources. In order to avoid the problems caused by ad hoc encodings, names should not be required to contain network identifiers, addresses, routes, or similar information as part of the name. - The sheer size of the database and frequency of updates suggest that it must be maintained in a distributed manner, with local caching to improve performance. Approaches that Mockapetris [Page 2] RFC 1034 Domain Concepts and Facilities November 1987 attempt to collect a consistent copy of the entire database will become more and more expensive and difficult, and hence should be avoided. The same principle holds for the structure of the name space, and in particular mechanisms for creating and deleting names; these should also be distributed. - Where there tradeoffs between the cost of acquiring data, the speed of updates, and the accuracy of caches, the source of the data should control the tradeoff. - The costs of implementing such a facility dictate that it be generally useful, and not restricted to a single application. We should be able to use names to retrieve host addresses, mailbox data, and other as yet undetermined information. All data associated with a name is tagged with a type, and queries can be limited to a single type. - Because we want the name space to be useful in dissimilar networks and applications, we provide the ability to use the same name space with different protocol families or management. For example, host address formats differ between protocols, though all protocols have the notion of address. The DNS tags all data with a class as well as the type, so that we can allow parallel use of different formats for data of type address. - We want name server transactions to be independent of the communications system that carries them. Some systems may wish to use datagrams for queries and responses, and only establish virtual circuits for transactions that need the reliability (e.g., database updates, long transactions); other systems will use virtual circuits exclusively. - The system should be useful across a wide spectrum of host capabilities. Both personal computers and large timeshared hosts should be able to use the system, though perhaps in different ways. 2.3. Assumptions about usage The organization of the domain system derives from some assumptions about the needs and usage patterns of its user community and is designed to avoid many of the the complicated problems found in general purpose database systems. The assumptions are: - The size of the total database will initially be proportional Mockapetris [Page 3] RFC 1034 Domain Concepts and Facilities November 1987 to the number of hosts using the system, but will eventually grow to be proportional to the number of users on those hosts as mailboxes and other information are added to the domain system. - Most of the data in the system will change very slowly (e.g., mailbox bindings, host addresses), but that the system should be able to deal with subsets that change more rapidly (on the order of seconds or minutes). - The administrative boundaries used to distribute responsibility for the database will usually correspond to organizations that have one or more hosts. Each organization that has responsibility for a particular set of domains will provide redundant name servers, either on the organization's own hosts or other hosts that the organization arranges to use. - Clients of the domain system should be able to identify trusted name servers they prefer to use before accepting referrals to name servers outside of this "trusted" set. - Access to information is more critical than instantaneous updates or guarantees of consistency. Hence the update process allows updates to percolate out through the users of the domain system rather than guaranteeing that all copies are simultaneously updated. When updates are unavailable due to network or host failure, the usual course is to believe old information while continuing efforts to update it. The general model is that copies are distributed with timeouts for refreshing. The distributor sets the timeout value and the recipient of the distribution is responsible for performing the refresh. In special situations, very short intervals can be specified, or the owner can prohibit copies. - In any system that has a distributed database, a particular name server may be presented with a query that can only be answered by some other server. The two general approaches to dealing with this problem are "recursive", in which the first server pursues the query for the client at another server, and "iterative", in which the server refers the client to another server and lets the client pursue the query. Both approaches have advantages and disadvantages, but the iterative approach is preferred for the datagram style of access. The domain system requires implementation of the iterative approach, but allows the recursive approach as an option. Mockapetris [Page 4] RFC 1034 Domain Concepts and Facilities November 1987 The domain system assumes that all data originates in master files scattered through the hosts that use the domain system. These master files are updated by local system administrators. Master files are text files that are read by a local name server, and hence become available through the name servers to users of the domain system. The user programs access name servers through standard programs called resolvers. The standard format of master files allows them to be exchanged between hosts (via FTP, mail, or some other mechanism); this facility is useful when an organization wants a domain, but doesn't want to support a name server. The organization can maintain the master files locally using a text editor, transfer them to a foreign host which runs a name server, and then arrange with the system administrator of the name server to get the files loaded. Each host's name servers and resolvers are configured by a local system administrator [RFC-1033]. For a name server, this configuration data includes the identity of local master files and instructions on which non-local master files are to be loaded from foreign servers. The name server uses the master files or copies to load its zones. For resolvers, the configuration data identifies the name servers which should be the primary sources of information. The domain system defines procedures for accessing the data and for referrals to other name servers. The domain system also defines procedures for caching retrieved data and for periodic refreshing of data defined by the system administrator. The system administrators provide: - The definition of zone boundaries. - Master files of data. - Updates to master files. - Statements of the refresh policies desired. The domain system provides: - Standard formats for resource data. - Standard methods for querying the database. - Standard methods for name servers to refresh local data from foreign name servers. Mockapetris [Page 5] RFC 1034 Domain Concepts and Facilities November 1987 2.4. Elements of the DNS The DNS has three major components: - The DOMAIN NAME SPACE and RESOURCE RECORDS, which are specifications for a tree structured name space and data associated with the names. Conceptually, each node and leaf of the domain name space tree names a set of information, and query operations are attempts to extract specific types of information from a particular set. A query names the domain name of interest and describes the type of resource information that is desired. For example, the Internet uses some of its domain names to identify hosts; queries for address resources return Internet host addresses. - NAME SERVERS are server programs which hold information about the domain tree's structure and set information. A name server may cache structure or set information about any part of the domain tree, but in general a particular name server has complete information about a subset of the domain space, and pointers to other name servers that can be used to lead to information from any part of the domain tree. Name servers know the parts of the domain tree for which they have complete information; a name server is said to be an AUTHORITY for these parts of the name space. Authoritative information is organized into units called ZONEs, and these zones can be automatically distributed to the name servers which provide redundant service for the data in a zone. - RESOLVERS are programs that extract information from name servers in response to client requests. Resolvers must be able to access at least one name server and use that name server's information to answer a query directly, or pursue the query using referrals to other name servers. A resolver will typically be a system routine that is directly accessible to user programs; hence no protocol is necessary between the resolver and the user program. These three components roughly correspond to the three layers or views of the domain system: - From the user's point of view, the domain system is accessed through a simple procedure or OS call to a local resolver. The domain space consists of a single tree and the user can request information from any section of the tree. - From the resolver's point of view, the domain system is composed of an unknown number of name servers. Each name Mockapetris [Page 6] RFC 1034 Domain Concepts and Facilities November 1987 server has one or more pieces of the whole domain tree's data, but the resolver views each of these databases as essentially static. - From a name server's point of view, the domain system consists of separate sets of local information called zones. The name server has local copies of some of the zones. The name server must periodically refresh its zones from master copies in local files or foreign name servers. The name server must concurrently process queries that arrive from resolvers. In the interests of performance, implementations may couple these functions. For example, a resolver on the same machine as a name server might share a database consisting of the the zones managed by the name server and the cache managed by the resolver. 3. DOMAIN NAME SPACE and RESOURCE RECORDS 3.1. Name space specifications and terminology The domain name space is a tree structure. Each node and leaf on the tree corresponds to a resource set (which may be empty). The domain system makes no distinctions between the uses of the interior nodes and leaves, and this memo uses the term "node" to refer to both. Each node has a label, which is zero to 63 octets in length. Brother nodes may not have the same label, although the same label can be used for nodes which are not brothers. One label is reserved, and that is the null (i.e., zero length) label used for the root. The domain name of a node is the list of the labels on the path from the node to the root of the tree. By convention, the labels that compose a domain name are printed or read left to right, from the most specific (lowest, farthest from the root) to the least specific (highest, closest to the root). Internally, programs that manipulate domain names should represent them as sequences of labels, where each label is a length octet followed by an octet string. Because all domain names end at the root, which has a null string for a label, these internal representations can use a length byte of zero to terminate a domain name. By convention, domain names can be stored with arbitrary case, but domain name comparisons for all present domain functions are done in a case-insensitive manner, assuming an ASCII character set, and a high order zero bit. This means that you are free to create a node with label "A" or a node with label "a", but not both as brothers; you could refer to either using "a" or "A". When you receive a domain name or Mockapetris [Page 7] RFC 1034 Domain Concepts and Facilities November 1987 label, you should preserve its case. The rationale for this choice is that we may someday need to add full binary domain names for new services; existing services would not be changed. When a user needs to type a domain name, the length of each label is omitted and the labels are separated by dots ("."). Since a complete domain name ends with the root label, this leads to a printed form which ends in a dot. We use this property to distinguish between: - a character string which represents a complete domain name (often called "absolute"). For example, "poneria.ISI.EDU." - a character string that represents the starting labels of a domain name which is incomplete, and should be completed by local software using knowledge of the local domain (often called "relative"). For example, "poneria" used in the ISI.EDU domain. Relative names are either taken relative to a well known origin, or to a list of domains used as a search list. Relative names appear mostly at the user interface, where their interpretation varies from implementation to implementation, and in master files, where they are relative to a single origin domain name. The most common interpretation uses the root "." as either the single origin or as one of the members of the search list, so a multi-label relative name is often one where the trailing dot has been omitted to save typing. To simplify implementations, the total number of octets that represent a domain name (i.e., the sum of all label octets and label lengths) is limited to 255. A domain is identified by a domain name, and consists of that part of the domain name space that is at or below the domain name which specifies the domain. A domain is a subdomain of another domain if it is contained within that domain. This relationship can be tested by seeing if the subdomain's name ends with the containing domain's name. For example, A.B.C.D is a subdomain of B.C.D, C.D, D, and " ". 3.2. Administrative guidelines on use As a matter of policy, the DNS technical specifications do not mandate a particular tree structure or rules for selecting labels; its goal is to be as general as possible, so that it can be used to build arbitrary applications. In particular, the system was designed so that the name space did not have to be organized along the lines of network boundaries, name servers, etc. The rationale for this is not that the name space should have no implied semantics, but rather that the choice of implied semantics should be left open to be used for the problem at Mockapetris [Page 8] RFC 1034 Domain Concepts and Facilities November 1987 hand, and that different parts of the tree can have different implied semantics. For example, the IN-ADDR.ARPA domain is organized and distributed by network and host address because its role is to translate from network or host numbers to names; NetBIOS domains [RFC-1001, RFC- 1002] are flat because that is appropriate for that application. However, there are some guidelines that apply to the "normal" parts of the name space used for hosts, mailboxes, etc., that will make the name space more uniform, provide for growth, and minimize problems as software is converted from the older host table. The political decisions about the top levels of the tree originated in RFC-920. Current policy for the top levels is discussed in [RFC-1032]. MILNET conversion issues are covered in [RFC-1031]. Lower domains which will eventually be broken into multiple zones should provide branching at the top of the domain so that the eventual decomposition can be done without renaming. Node labels which use special characters, leading digits, etc., are likely to break older software which depends on more restrictive choices. 3.3. Technical guidelines on use Before the DNS can be used to hold naming information for some kind of object, two needs must be met: - A convention for mapping between object names and domain names. This describes how information about an object is accessed. - RR types and data formats for describing the object. These rules can be quite simple or fairly complex. Very often, the designer must take into account existing formats and plan for upward compatibility for existing usage. Multiple mappings or levels of mapping may be required. For hosts, the mapping depends on the existing syntax for host names which is a subset of the usual text representation for domain names, together with RR formats for describing host addresses, etc. Because we need a reliable inverse mapping from address to host name, a special mapping for addresses into the IN-ADDR.ARPA domain is also defined. For mailboxes, the mapping is slightly more complex. The usual mail address @ is mapped into a domain name by converting into a single label (regardles of dots it contains), converting into a domain name using the usual text format for domain names (dots denote label breaks), and concatenating the two to form a single domain name. Thus the mailbox Mockapetris [Page 9] RFC 1034 Domain Concepts and Facilities November 1987 HOSTMASTER@SRI-NIC.ARPA is represented as a domain name by HOSTMASTER.SRI-NIC.ARPA. An appreciation for the reasons behind this design also must take into account the scheme for mail exchanges [RFC- 974]. The typical user is not concerned with defining these rules, but should understand that they usually are the result of numerous compromises between desires for upward compatibility with old usage, interactions between different object definitions, and the inevitable urge to add new features when defining the rules. The way the DNS is used to support some object is often more crucial than the restrictions inherent in the DNS. 3.4. Example name space The following figure shows a part of the current domain name space, and is used in many examples in this RFC. Note that the tree is a very small subset of the actual name space. | | +---------------------+------------------+ | | | MIL EDU ARPA | | | | | | +-----+-----+ | +------+-----+-----+ | | | | | | | BRL NOSC DARPA | IN-ADDR SRI-NIC ACC | +--------+------------------+---------------+--------+ | | | | | UCI MIT | UDEL YALE | ISI | | +---+---+ | | | | LCS ACHILLES +--+-----+-----+--------+ | | | | | | XX A C VAXA VENERA Mockapetris In this example, the root domain has three immediate subdomains: MIL, EDU, and ARPA. The LCS.MIT.EDU domain has one immediate subdomain named XX.LCS.MIT.EDU. All of the leaves are also domains. 3.5. Preferred name syntax The DNS specifications attempt to be as general as possible in the rules Mockapetris [Page 10] RFC 1034 Domain Concepts and Facilities November 1987 for constructing domain names. The idea is that the name of any existing object can be expressed as a domain name with minimal changes. However, when assigning a domain name for an object, the prudent user will select a name which satisfies both the rules of the domain system and any existing rules for the object, whether these rules are published or implied by existing programs. For example, when naming a mail domain, the user should satisfy both the rules of this memo and those in RFC-822. When creating a new host name, the old rules for HOSTS.TXT should be followed. This avoids problems when old software is converted to use domain names. The following syntax will result in fewer problems with many applications that use domain names (e.g., mail, TELNET). ::= | " " ::=