PROGRAM UNIX; /* Copyright (c) 1979 David A. Butterfield and Daniel Weise */ CONST QUIT = 'q'; DIR = 'd'; LIST = 'l'; HUH = '?'; CHDIR = 'c'; TYPEIT = 't'; MOVE = 'm'; DIRBIT = 40000B; SPBIT = 20000B; LARGE = 10000B; TYPE CHAR13ARRAY = ARRAY[0..13] OF CHAR; INODE = RECORD FLAGS: INTEGER; NLINKS: CHAR; UID: CHAR; GID: CHAR; SIZEHI: CHAR; SIZELO: INTEGER; BLKNOS: ARRAY[0..7] OF INTEGER; ACTIME: ARRAY[0..1] OF INTEGER; MODTIME: ARRAY[0..1] OF INTEGER END; DIRENTRY = RECORD INODENO: INTEGER; FILENAME: ARRAY[0..13] OF CHAR END; FUNNY = RECORD CASE INTEGER OF 1: (INODEREC: ARRAY[0..15] OF INODE); 2: (DIRBLOCKREC: ARRAY[0..31] OF DIRENTRY); 3: (CHARREC: ARRAY[0..511] OF CHAR); 4: (INTS: ARRAY[0..255] OF INTEGER) END; VAR DEV: TEXT; CIHAVE: INTEGER; /* INODE NUMBER OF CURRENT DIRECTORY */ ICURD: INODE; /* CONTAINS THE INODE OF THE CURRENT DIRECTORY */ DECNT: INTEGER; /* NUMBER OF ENTRIES IN THE CURRENT DIRECTORY */ DATABLOCK: FUNNY; INODEBLOCK: ARRAY[0..15] OF INODE; INHAVE: INTEGER; /* PHYSICAL BLOCK IN INODEBLOCK */ DIRBLOCK: ARRAY[0..31] OF DIRENTRY; DIHAVE: INTEGER; /* PHYSICAL BLOCK IN DIRBLOCK */ INDBLOCK: ARRAY[0..255] OF INTEGER; IBHAVE: INTEGER; /* PHYSICAL BLOCK IN INDBLOCK */ DINDBLOCK: ARRAY[0..255] OF INTEGER; DIBHAVE: INTEGER; /* PHYSICAL BLOCK IN DINDBLOCK */ INBUFF: ARRAY[1..80] OF CHAR; /* THIS IS THE INPUT LINE */ Logname: ARRAY[1..8] OF CHAR; LOGPASS: ARRAY[1..8] OF CHAR; LOGGEDIN: BOOLEAN; NOTDONE: BOOLEAN; OPTION: CHAR; ARG: INTEGER; FOO: CHAR; NL : ARRAY [0..1] OF CHAR; PROCEDURE SEEK(VAR F:TEXT; VAR X: FUNNY; BLOCKNO: INTEGER); EXTERNAL; FUNCTION GETBLKNO(RBLOCK:INTEGER; SOURCEINODE:INODE): INTEGER; VAR LINDBLOCKNO, LDINDBLOCKNO, PHYSBLOCK: INTEGER; BEGIN IF (SOURCEINODE.FLAGS & LARGE) = 0 THEN IF RBLOCK < 8 THEN PHYSBLOCK := SOURCEINODE.BLKNOS[RBLOCK] ELSE BEGIN WRITELN('ATTEMPT TO REFERENCE #',RBLOCK,'OF A SMALL FILE.'); RBLOCK := RBLOCK DIV 0 END ELSE BEGIN /* LARGE OR HUGE FILE */ LINDBLOCKNO := RBLOCK DIV 256; IF LINDBLOCKNO < 7 THEN BEGIN IF SOURCEINODE.BLKNOS[LINDBLOCKNO] <> IBHAVE THEN BEGIN SEEK(DEV,DATABLOCK,SOURCEINODE.BLKNOS[LINDBLOCKNO]); INDBLOCK := DATABLOCK.INTS; IBHAVE := SOURCEINODE.BLKNOS[LINDBLOCKNO] END; PHYSBLOCK := INDBLOCK[RBLOCK MOD 256] END ELSE BEGIN /* HUGE FILE WERE HERE IFF LINDBLOCKNO >= 7 */ IF SOURCEINODE.BLKNOS[7] <> IBHAVE THEN BEGIN SEEK(DEV,DATABLOCK,SOURCEINODE.BLKNOS[7]); INDBLOCK := DATABLOCK.INTS; IBHAVE := SOURCEINODE.BLKNOS[7] END; LINDBLOCKNO := LINDBLOCKNO - 7; IF INDBLOCK[LINDBLOCKNO] <> DIBHAVE THEN BEGIN SEEK(DEV,DATABLOCK,INDBLOCK[LINDBLOCKNO]); DINDBLOCK := DATABLOCK.INTS; DIBHAVE := INDBLOCK[LINDBLOCKNO] END; PHYSBLOCK := DINDBLOCK[RBLOCK MOD 256] END END; GETBLKNO := PHYSBLOCK END; FUNCTION GETI(INODENO: INTEGER):INTEGER; VAR BLOCK: INTEGER; BEGIN INODENO := INODENO - 1; GETI := 17B & INODENO; BLOCK := INODENO DIV 16 + 2; IF BLOCK <> INHAVE THEN BEGIN SEEK(DEV,DATABLOCK,BLOCK); INODEBLOCK := DATABLOCK.INODEREC; INHAVE := BLOCK END END; FUNCTION GETD(DIRNUMBER: INTEGER):INTEGER; VAR BLOCK: INTEGER; BEGIN GETD := 37B & DIRNUMBER; BLOCK := GETBLKNO(DIRNUMBER DIV 32, ICURD); IF BLOCK <> DIHAVE THEN BEGIN SEEK(DEV, DATABLOCK, BLOCK); DIHAVE := BLOCK; DIRBLOCK := DATABLOCK.DIRBLOCKREC END END; PROCEDURE GETFILE(INODENO:INTEGER); VAR HI: CHAR; FINPTR, LO, SIZE, BLOCK, I, J: INTEGER; ANSWER: ARRAY[1..14] OF CHAR; INSERTCRS: BOOLEAN; BEGIN WRITE('Should I add carriage returns? '); READLN(ANSWER); INSERTCRS := (ANSWER[1] = 'y') OR (ANSWER[1] = 'Y'); FINPTR := GETI(INODENO); HI := INODEBLOCK[FINPTR].SIZEHI; LO := INODEBLOCK[FINPTR].SIZELO; /*$C MOVB HI(6),%0 BIC #^O177400,%0 MOV LO(6),%1 SUB #1,%1 SBC %0 ASHC #-9.,%0 MOV %1,SIZE(6) */ FOR I := 0 TO SIZE DO BEGIN BLOCK := GETBLKNO(I,INODEBLOCK[FINPTR]); IF BLOCK <> 0 THEN BEGIN SEEK(DEV,DATABLOCK,BLOCK); IF INSERTCRS THEN FOR J:= 0 TO 511 DO IF DATABLOCK.CHARREC[J] = CHR(12B) THEN WRITE(CHR(15B),CHR(12B)) ELSE WRITE(DATABLOCK.CHARREC[J]) ELSE WRITE(DATABLOCK.CHARREC) END ELSE WRITELN(NL,'BLOCK ',I,' IS EMPTY') END END; PROCEDURE MOVEFILE(INODENO:INTEGER); VAR OUTPUT: TEXT; FILENAME: ARRAY[1..14] OF CHAR; HI: CHAR; FINPTR, LO, SIZE, BLOCK, I, J: INTEGER; INSERTCRS: BOOLEAN; BEGIN WRITE('Write to file: '); READLN(FILENAME); REWRITE(OUTPUT,FILENAME); WRITE('Should I add carriage returns? '); READLN(FILENAME); INSERTCRS := (filename[1] = 'y') OR (filename[1] = 'Y'); FINPTR := GETI(INODENO); HI := INODEBLOCK[FINPTR].SIZEHI; LO := INODEBLOCK[FINPTR].SIZELO; /*$C MOVB HI(6),%0 BIC #^O177400,%0 MOV LO(6),%1 SUB #1,%1 SBC %0 ASHC #-9.,%0 MOV %1,SIZE(6) */ FOR I:= 0 TO SIZE DO BEGIN BLOCK := GETBLKNO(I,INODEBLOCK[FINPTR]); SEEK(DEV,DATABLOCK,BLOCK); IF INSERTCRS THEN FOR J:= 0 TO 511 DO IF DATABLOCK.CHARREC[J] = CHR(12B) THEN WRITE(OUTPUT,CHR(15B),CHR(12B)) ELSE WRITE(OUTPUT,DATABLOCK.CHARREC[J]) ELSE WRITE(OUTPUT,DATABLOCK.CHARREC) END; CLOSE(OUTPUT) END; PROCEDURE WRITEF(VAR NAME: CHAR13ARRAY); VAR I: INTEGER; BEGIN FOR I := 0 TO 13 DO BEGIN IF ORD(NAME[I]) = 0 THEN WRITE(' ') ELSE WRITE(NAME[I]) END END; PROCEDURE GETCURD(CIWANT: INTEGER); VAR HI: CHAR; FINPTR, LO: INTEGER; BEGIN IF CIWANT <> CIHAVE THEN BEGIN FINPTR := GETI(CIWANT); IF (INODEBLOCK[FINPTR].FLAGS & DIRBIT) = 0 THEN WRITELN('Not a directory') ELSE BEGIN CIHAVE := CIWANT; ICURD := INODEBLOCK[FINPTR] END END; HI := ICURD.SIZEHI; LO := ICURD.SIZELO; /*$C MOVB HI(6),%0 MOV LO(6),%1 ASHC #-4,%0 MOV %1,DECNT(5) ; ASSUME NO MORE THAN 32767 ENTRIES */ END; PROCEDURE DIRLIST; VAR HI: CHAR; LO, FINODE, FINPTR, DIRPTR, DIRCNT, SIZE: INTEGER; BEGIN FOR DIRCNT := 0 TO DECNT-1 DO BEGIN DIRPTR := GETD(DIRCNT); FINODE := DIRBLOCK[DIRPTR].INODENO; IF FINODE <> 0 THEN BEGIN WRITE(FINODE:6,' '); WRITEF(DIRBLOCK[DIRPTR].FILENAME); WRITE(' '); FINPTR := GETI(FINODE); IF (INODEBLOCK[FINPTR].FLAGS AND DIRBIT) <> 0 THEN WRITE('d') ELSE WRITE(' '); IF (INODEBLOCK[FINPTR].FLAGS AND SPBIT) <> 0 THEN WRITE('s') ELSE WRITE(' '); HI := INODEBLOCK[FINPTR].SIZEHI; LO := INODEBLOCK[FINPTR].SIZELO; /*$C MOVB HI(6),%0 BIC #^O177400,%0 MOV LO(6),%1 SUB #1,%1 SBC %0 ASHC #-9.,%0 MOV %1,SIZE(6) */ WRITELN(SIZE+1:4) END END END; BEGIN /*$C BIS #^O40000,@#^O44 */ NL[0] := CHR(15B); NL[1]:= CHR(12B); WRITELN(CHR(14B),'Program to read Unix disks.'); WRITE('Unix disk drive: '); READLN(Logname); If Ord(Logname[1]) > 96 then Logname[1] := Chr(Ord(Logname[1]) - 32); If Ord(Logname[2]) > 96 then Logname[2] := Chr(Ord(Logname[2]) - 32); NOTDONE := TRUE; CIHAVE := 0; INHAVE := 0; DIHAVE := 0; IBHAVE := 0; DIBHAVE := 0; /* RESET(DEV,'DX1:'); */ reset(dev,Logname); GETCURD(1); WHILE NOTDONE DO BEGIN WRITE('% '); READ(OPTION); CASE OPTION OF HUH: BEGIN READLN(FOO); WRITELN('q = quit',NL,'d = l = directory listing',NL, 'c = change directory',NL,'t = type file',NL, 'm = move to rt11 file') END; QUIT,'Q': Begin Readln(Foo); /* Get rid of trailing CR */ NOTDONE := FALSE; End; DIR,'D',LIST,'L': BEGIN READLN(FOO); DIRLIST END; CHDIR,'C': BEGIN READLN(ARG); GETCURD(ARG) END; TYPEIT,'T': BEGIN READLN(ARG); GETFILE(ARG) END; MOVE,'M': BEGIN READLN(ARG); MOVEFILE(ARG) END; ELSE BEGIN READLN(FOO); WRITELN('Illegal command -- type ? for help') END END END; CLOSE(DEV) END.