{ Permission to copy or distribute this software or documen- } { tation in hard or soft copy granted only by written license } { obtained from the Institute for Information Systems. } PROCEDURE PREFIXER; BEGIN { PREFIXER } IF CHECKFILE('Prefix titles by','',1,FALSE,FALSE,[NOVOL,BADDIR,OKDIR, UNBLKDVOL],86,0) THEN BEGIN DKVID := GVID; WRITE(OUTPUT,'Prefix is ',DKVID,':'); CLEARLINE END END {PREFIXER} ; PROCEDURE LISTDIR(DETAIL: BOOLEAN); VAR OUT : TEXT; SAVEVID : VID; LINE,LARGEST,FREEBLKS,USEDAREA,USEDBLKS: INTEGER; PROCEDURE WRITELINE(FIRSTCALL: BOOLEAN); BEGIN IF FIRSTCALL OR (LINE = SYSCOM^.CRTINFO.HEIGHT) THEN BEGIN { May need to wait or write out heading } IF OK THEN BEGIN { Listing to console } IF NOT (FIRSTCALL OR QUESTION) THEN BEGIN { Must wait before continuing } HOMECURSOR; CLEARLINE; IF SPACEWAIT(FALSE) THEN EXIT(LISTDIR); END; CLEARSCREEN; LINE := 2; WRITELN(OUT); WRITE(OUT,SAVEVID,':') END ELSE IF FIRSTCALL THEN BEGIN { Not listing to console } IF NOT DONE THEN { Listing to unblocked device } CLEARSCREEN; HOMECURSOR; WRITELN(OUT); WRITE(OUT,SAVEVID,':') END; IF FIRSTCALL AND DONE THEN { Corrects cursor positioning } BEGIN HOMECURSOR; IF NOT WILDCARD THEN CLWRITELN('') END END; IF NOT (OK AND FIRSTCALL AND WILDCARD) THEN { For cursor positioning } WRITELN(OUT); LINE := LINE+1 END {WRITELINE} ; PROCEDURE FREECHECK(FIRSTOPEN,NEXTUSED: INTEGER); VAR FREEAREA: INTEGER; BEGIN FREEAREA := NEXTUSED-FIRSTOPEN; { Finds space bet. last & next file } IF FREEAREA > LARGEST THEN LARGEST := FREEAREA; { Is this the biggest } IF FREEAREA > 0 THEN { There is a space between these files } BEGIN FREEBLKS := FREEBLKS+FREEAREA; { Running totla of free blocks } IF DETAIL THEN { Extended listing } BEGIN WRITE(OUT,'< UNUSED > ', FREEAREA:4,' ':11,FIRSTOPEN:6); WRITELINE(FALSE) END END; END {FREECHECK} ; PROCEDURE SHOWDIR; BEGIN IF DONE AND (NOT QUESTION) THEN { Listing to a file } BEGIN IF X = 0 THEN { First call to procedure } BEGIN WRITE(OUTPUT,'Writing'); CLEARLINE END ELSE WRITE(OUTPUT,'.') { Show progress of listing } END; X := X + 1; WITH GDIR^[I] DO BEGIN FREECHECK(GDIR^[I-1].DLASTBLK,DFIRSTBLK); { Check for free blocks } USEDAREA := DLASTBLK-DFIRSTBLK; { Area used } USEDBLKS := USEDBLKS+USEDAREA; { Running total of used blocks } WRITE(OUT,DTID,' ':TIDLENG-LENGTH(DTID)+1,USEDAREA:4); IF DACCESS.MONTH > 0 THEN WRITE(OUT,' ':2,DACCESS.DAY:2,'-', MONTHS[DACCESS.MONTH],'-',DACCESS.YEAR:2); IF DETAIL THEN { Extended listing } BEGIN IF DACCESS.MONTH = 0 THEN WRITE(OUT,' ':11); WRITE(OUT,DFIRSTBLK:6,DLASTBYTE:6); GS := 'ILLEGAL'; CASE DFKIND OF XDSKFILE: GS := 'Bad disk'; CODEFILE: GS := 'Codefile'; TEXTFILE: GS := 'Textfile'; INFOFILE: GS := 'Infofile'; DATAFILE: GS := 'Datafile'; GRAFFILE: GS := 'Graffile'; FOTOFILE: GS := 'Fotofile' END; WRITE(OUT,' ':2,GS) END; WRITELINE(FALSE) END; END; BEGIN {LISTDIR} DONE := FALSE; X := 0; OK := TRUE; IF CHECKFILE('Dir listing of','',-1,TRUE,FALSE,[OKDIR,OKFILE],84,84) THEN BEGIN FOUND := TRUE; SAVEVID := GVID; IF TOWHERE = '' THEN { Default destination is console } GS := 'CONSOLE:' ELSE IF SCANINPUT(TOWHERE,[BADFILE,OKFILE,UNBLKDVOL],83,1) THEN BEGIN { Not listing to default volume } DONE := UNITABLE [GUNIT].UISBLKD; OK := FALSE; GS := TOWHERE END ELSE GS := ''; { Bad destination name, abort LISTDIR } IF GS <> '' THEN BEGIN REWRITE(OUT,GS); { Change output to appropriate device } IF NOT CHECKRSLT(IORESULT) THEN { Bad I/O result } GS := '' END; IF GS = '' THEN EXIT(LISTDIR); FREEBLKS := 0; USEDBLKS := 0; LARGEST := 0; LINE := 0; IF FILENAM1 = '' THEN WRITELINE(TRUE); I := 0; IF SCANINPUT(FROMWHERE,[OKDIR,OKFILE],84,-1) THEN IF WILDCARD THEN WHILE SEARCHDIR('List ',I,TRUE,FALSE) DO { Get file to be listed } SHOWDIR ELSE FOR I := 1 TO GDIR^[0].DNUMFILES DO BEGIN IF FILENAM1 = '' THEN { List all the files } SHOWDIR ELSE IF GDIR^[I].DTID = FILENAM1 THEN { List only this file } SHOWDIR END; OK := FALSE; IF FOUND THEN BEGIN IF (FILENAM1 = '') OR WILDCARD THEN BEGIN FREECHECK(GDIR^[I-1].DLASTBLK,GDIR^[0].DEOVBLK); WRITE(OUT,X,'/',GDIR^[0].DNUMFILES,' files'); IF NOT SYSCOM^.MISCINFO.SLOWTERM THEN WRITE(OUT,''); WRITE(OUT,', ',USEDBLKS); IF NOT SYSCOM^.MISCINFO.SLOWTERM THEN WRITE(OUT,' blocks'); WRITE(OUT,' used, ',FREEBLKS,' unused'); IF DETAIL THEN WRITE(OUT,', ',LARGEST,' in largest area'); IF DONE THEN BEGIN WRITELN(OUTPUT); WRITELN(OUT) END END; IF CHECKRSLT(IORESULT) THEN BEGIN OK := TRUE; CLOSE(OUT,LOCK) END END; IF NOT OK THEN CLOSE(OUT,NORMAL) END END {LISTDIR} ; PROCEDURE LISTVOLS; BEGIN { LISTVOLS } GUNIT := VOLSEARCH(GVID,TRUE,GDIR); { Update unitable } CLEARSCREEN; WRITELN(OUTPUT); WRITELN(OUTPUT,'Volumes on-line:'); FOR GUNIT := 1 TO MAXUNIT DO WITH UNITABLE[GUNIT] DO IF UVID <> '' THEN { Volume is on-line } BEGIN WRITE(OUTPUT,GUNIT:3); IF UVID = SYVID THEN WRITE(OUTPUT,' * ') { This volume is the booted device } ELSE IF UISBLKD THEN WRITE(OUTPUT,' # ') { Blocked unit } ELSE WRITE(OUTPUT,' '); { Unblocked unit } WRITELN(OUTPUT,UVID,':') END; WRITELN(OUTPUT,'Prefix is - ',DKVID,':') { Prefix } END {LISTVOLS} ; PROCEDURE BADBLOCKS; VAR A: PACKED ARRAY [0..FBLKSIZE] OF CHAR; BEGIN { BADBLOCKS } CLEARSCREEN; IF CHECKFILE('Bad blocks scan of','',1,FALSE,FALSE, [OKDIR,BADDIR],80,0) THEN BEGIN UNITCLEAR(GUNIT); IF CHECKRSLT(IORESULT) THEN { Unit is on-line } BEGIN X := 0; FOR I := 0 TO UNITABLE[GUNIT].UEOVBLK-1 DO BEGIN UNITREAD(GUNIT,A,FBLKSIZE,I); IF SYSCOM^.IORSLT <> INOERROR THEN BEGIN X := X+1; WRITELN(OUTPUT,'Block ',I,' is bad') END END; WRITE(OUTPUT,X,' bad blocks') END END END {BADBLOCKS} ; PROCEDURE ZEROVOLUME; LABEL 1; VAR NBLOCKS,LASTBLK: INTEGER; LDE: DIRENTRY; BEGIN { ZEROVOLUME } CLEARSCREEN; LASTBLK := 6; { Leave room for directory and bootstrap } IF CHECKFILE('Zero dir of','',1,FALSE,FALSE,[OKDIR,BADDIR],80,0) THEN BEGIN UNITCLEAR(GUNIT); IF CHECKRSLT(IORESULT) THEN { Unit is on-line } BEGIN IF GDIR <> NIL THEN { There's a directory on this volume } BEGIN WRITE(OUTPUT,'Destroy ',GVID,': ? '); IF NGETCHAR(TRUE) <> 'Y' THEN GOTO 1 END; WRITE(OUTPUT,'Duplicate dir ? '); CH := NGETCHAR(TRUE); IF CH = 'Y' THEN { Leave room for a duplicate directory } LASTBLK := 10 ELSE IF CH = SYSCOM^.CRTINFO.ALTMODE THEN { Abort ZEROVOLUME } GOTO 1; CH := 'N'; IF GDIR <> NIL THEN { There's a directory on this volume } IF (GDIR^[0].DEOVBLK >=LASTBLK) AND (GDIR^[0].DEOVBLK <= 10000) THEN BEGIN { The number of blocks present may be valid } WRITE(OUTPUT,GDIR^[0].DEOVBLK,' blocks ? '); CH := NGETCHAR(TRUE); IF CH = SYSCOM^.CRTINFO.ALTMODE THEN GOTO 1 { Abort ZEROVOLUME } ELSE IF CH = 'Y' THEN NBLOCKS := GDIR^[0].DEOVBLK { Keep the present number } END; IF CH <> 'Y' THEN BEGIN { Need to get a new number of blocks on disk } WRITE(OUTPUT,'# of blocks ? '); NBLOCKS := 0; READLN(INPUT,NBLOCKS); IF NBLOCKS < LASTBLK THEN BEGIN { Not a valid number of blocks, abort ZEROVOLUME } WRITE(OUTPUT,'Bad # blocks'); GOTO 1 END END; WRITE(OUTPUT,'New vol name ? '); READLN(INPUT,GS); EATSPACES(GS); IF GS = '' THEN GOTO 1; IF GS[LENGTH(GS)] = ':' THEN DELETE(GS,LENGTH(GS),1); IF (GS = '') OR (LENGTH(GS) > VIDLENG) THEN BEGIN MESSAGES(54); GOTO 1 END; TOUPPER(GS,1,LENGTH(GS)); { Change to upper-case } WITH LDE DO BEGIN DFIRSTBLK := 0; DLASTBLK := LASTBLK; DFKIND := UNTYPEDFILE; DVID := GS; DEOVBLK := NBLOCKS; DLOADTIME := 0; DLASTBOOT := THEDATE; DNUMFILES := 0; WRITE(OUTPUT,DVID,': correct ? '); IF NGETCHAR(TRUE) = 'Y' THEN BEGIN UNITWRITE(GUNIT,LDE,SIZEOF(LDE),DIRBLK); IF CHECKRSLT(IORESULT) THEN { I/O result is good } WRITE(OUTPUT,DVID,': zeroed') END END END END; 1: END {ZEROVOLUME} ; PROCEDURE DATESET; VAR DELIMS: SET OF '-'..'/'; FUNCTION FINDDELIM : BOOLEAN; BEGIN { FINDDELIM } OK := TRUE; WHILE OK AND (GS <> '') DO BEGIN IF GS[1] IN DELIMS THEN OK := FALSE; DELETE(GS,1,1) END; FINDDELIM := GS <> '' END { FINDDELIM }; BEGIN {DATESET} CLEARSCREEN; DELIMS := ['-','/']; PL := 'Date set: <1..31>--<00..99> OR '; PROMPT; WRITELN(OUTPUT); WITH THEDATE DO IF MONTH = 0 THEN WRITELN(OUTPUT,'No current date') ELSE WRITELN(OUTPUT,'Today is ',DAY:2,'-',MONTHS[MONTH],'-',YEAR:2); WRITE(OUTPUT,'New date ? '); READLN(INPUT,GS); EATSPACES(GS); { Remove spaces and non-printable characters } IF GS <> '' THEN BEGIN I := 0; REPEAT IF GS[1] IN DIGITS THEN I := I*10+ORD(GS[1])-ORD('0'); IF NOT(GS[1] IN DELIMS) THEN DELETE(GS,1,1) UNTIL (GS = '') OR (GS[1] IN DELIMS) OR (I > 31); IF (I > 0) AND (I < 32) THEN THEDATE.DAY := I END; IF FINDDELIM AND (LENGTH(GS) > 2) THEN BEGIN GVID := ' '; TOUPPER(GS,1,1); { Change to upper-case } FOR I := 2 TO 3 DO IF ( GS[I] >= 'A' ) AND ( GS[I] <= 'Z' ) THEN GS[I] := CHR( ORD( GS[I] )-ORD( 'A' )+ORD( 'a' )); MOVELEFT(GS[1],GVID[1],3); FOR I := 1 TO 12 DO IF MONTHS[I] = GVID THEN THEDATE.MONTH := I END; IF FINDDELIM THEN BEGIN OK := FALSE; I := 0; REPEAT IF GS[1] IN DIGITS THEN BEGIN I := I*10+ORD(GS[1])-ORD('0'); OK := I <= 99 END; DELETE(GS,1,1) UNTIL (GS = ''); IF OK THEN THEDATE.YEAR := I END; GUNIT := VOLSEARCH(SYVID,FALSE,GDIR); IF GUNIT = SYSCOM^.SYSUNIT THEN BEGIN GDIR^[0].DLASTBOOT := THEDATE; WRITEDIR(GUNIT,GDIR) END; WITH THEDATE DO WRITE(OUTPUT,'New date is ',DAY:2,'-',MONTHS[MONTH],'-',YEAR:2) END { DATESET } ; PROCEDURE XBLOCKS; LABEL 1; VAR CONFLICT : BOOLEAN; FIRSTBLK,LASTBLK,MAXBLK,MINBLK : INTEGER; LDE : DIRENTRY; A,B : ARRAY [0..255] OF INTEGER; BEGIN { XBLOCKS } CLEARSCREEN; IF CHECKFILE('Examine blocks on','',1,FALSE,FALSE,[OKDIR],80,0) THEN BEGIN CONFLICT := FALSE; MINBLK := 32767; MAXBLK := -1; FIRSTBLK := 0; LASTBLK := 0; WRITE(OUTPUT,'Block number-range ? '); READ(INPUT,FIRSTBLK); IF EOLN(INPUT) THEN LASTBLK := FIRSTBLK ELSE BEGIN READ(INPUT,LASTBLK); IF NOT EOLN(INPUT) THEN WRITELN(OUTPUT); IF LASTBLK < 0 THEN LASTBLK := ABS(LASTBLK); IF LASTBLK < FIRSTBLK THEN BEGIN I := FIRSTBLK; FIRSTBLK := LASTBLK; LASTBLK := I END END; IF FIRSTBLK < GDIR^[0].DLASTBLK THEN BEGIN { Directory is endangered } WRITE(OUTPUT,'Risk the dir ? '); IF NGETCHAR(TRUE) <> 'Y' THEN GOTO 1 END; FOR X := 1 TO GDIR^[0].DNUMFILES DO WITH GDIR^[X] DO IF (FIRSTBLK < DLASTBLK) AND (LASTBLK >= DFIRSTBLK) THEN BEGIN { The block is located in a file } IF NOT CONFLICT THEN BEGIN CONFLICT := TRUE; WRITELN(OUTPUT,'File(s) endangered:') END; WRITELN(OUTPUT,DTID,' ':TIDLENG-LENGTH(DTID)+1, DFIRSTBLK:6,DLASTBLK:6) END; IF CONFLICT THEN BEGIN { Files are endangered } WRITE(OUTPUT,'Try to fix them ? '); IF NGETCHAR(TRUE) <> 'Y' THEN GOTO 1 END; FOR X := FIRSTBLK TO LASTBLK DO BEGIN WRITE(OUTPUT,'Block ',X); UNITREAD(GUNIT,A,FBLKSIZE,X); B := A; UNITWRITE(GUNIT,A,FBLKSIZE,X); IF IORESULT = 0 THEN UNITREAD(GUNIT,B,FBLKSIZE,X); IF (IORESULT = 0) AND (A = B) THEN WRITELN(OUTPUT,' may be ok') ELSE BEGIN WRITELN(OUTPUT,' is bad'); IF X < MINBLK THEN MINBLK := X; IF X > MAXBLK THEN MAXBLK := X END END; IF MAXBLK < 0 THEN GOTO 1; IF MINBLK = MAXBLK THEN WRITELN(OUTPUT,'Block ',MINBLK,' is still bad') ELSE WRITELN(OUTPUT,'Blocks ',MINBLK,' thru ',MAXBLK, ' are still bad'); WRITE(OUTPUT,'Mark them'); IF CONFLICT THEN WRITE(OUTPUT,' (may remove files!)'); WRITE(OUTPUT,' ? '); IF NGETCHAR(TRUE) <> 'Y' THEN GOTO 1; IF CONFLICT THEN BEGIN X := 1; {ZAP CONFLICTS} WHILE X <= GDIR^[0].DNUMFILES DO WITH GDIR^[X] DO IF (MINBLK < DLASTBLK) AND (MAXBLK >= DFIRSTBLK) THEN DELENTRY(X,GDIR) ELSE X := X+1 END; IF GDIR^[0].DNUMFILES = MAXDIR THEN BEGIN IF CHECKRSLT(ORD(INOROOM)) THEN; GOTO 1 END; WITH LDE DO BEGIN DFIRSTBLK := MINBLK; DLASTBLK := MAXBLK+1; DFKIND := XDSKFILE; DLASTBYTE := FBLKSIZE; DACCESS := THEDATE; DTID := 'BAD.xxxxx.BAD'; FIRSTBLK := MINBLK; FOR I := 4 DOWNTO 0 DO BEGIN DTID[9-I] := CHR(FIRSTBLK DIV IPOT[I] + ORD('0')); FIRSTBLK := FIRSTBLK MOD IPOT[I] END END; X := GDIR^[0].DNUMFILES; WHILE MINBLK < GDIR^[X].DLASTBLK DO X := X - 1; INSENTRY(LDE,X+1,GDIR); WRITEDIR(GUNIT,GDIR); WRITE(OUTPUT,LDE.DTID,' marked') END; 1: END {XBLOCKS} ; PROCEDURE KRUNCH; LABEL 1; VAR LINX: DIRRANGE; NBLOCKS,DESTBLK,RELBLOCK,CHUNKSIZE,AINX,LBLOCK: INTEGER; REBOOT: BOOLEAN; BEGIN { KRUNCH } CLEARSCREEN; IF CHECKFILE('Crunch','',1,FALSE,FALSE,[OKDIR],80,0) THEN BEGIN WRITE(OUTPUT,'Are you sure'); IF NOT SYSCOM^.MISCINFO.SLOWTERM THEN WRITE(OUTPUT,' you want to crunch ',GVID,':'); WRITE(OUTPUT,' ? '); IF NGETCHAR(TRUE) <> 'Y' THEN GOTO 1; { Abort CRUNCH } REBOOT := FALSE; { Will be set to true if *SYSTEM.PASCAL is moved } SYSCOM^.MISCINFO.NOBREAK := TRUE; FOR LINX := 1 TO GDIR^[0].DNUMFILES DO WITH GDIR^[LINX] DO IF (DFKIND <> XDSKFILE) AND (DFIRSTBLK > GDIR^[LINX-1].DLASTBLK) THEN BEGIN WRITELN(OUTPUT,'Moving ',DTID); REBOOT := REBOOT OR ((DTID = 'SYSTEM.PASCAL') AND (GVID=SYVID)); NBLOCKS := DLASTBLK-DFIRSTBLK; { Number of blocks in file } DESTBLK := GDIR^[LINX-1].DLASTBLK; { Were is this file going } RELBLOCK := 0; REPEAT CHUNKSIZE := NBLOCKS-RELBLOCK; IF CHUNKSIZE > GBUFBLKS THEN CHUNKSIZE := GBUFBLKS; IF CHUNKSIZE > 0 THEN BEGIN AINX := 0; FOR LBLOCK := DFIRSTBLK+RELBLOCK TO DFIRSTBLK+RELBLOCK+CHUNKSIZE-1 DO BEGIN UNITREAD(GUNIT,GBUF^[AINX],FBLKSIZE,LBLOCK); IF IORESULT <> 0 THEN BEGIN WRITELN(OUTPUT,'Read error, rel ', LBLOCK-DFIRSTBLK,', abs ',LBLOCK); EXIT(KRUNCH) END; AINX := AINX+FBLKSIZE END; AINX := 0; FOR LBLOCK := DESTBLK+RELBLOCK TO DESTBLK+RELBLOCK+CHUNKSIZE-1 DO BEGIN UNITWRITE(GUNIT,GBUF^[AINX],FBLKSIZE,LBLOCK); IF IORESULT <> 0 THEN BEGIN WRITELN(OUTPUT,'Write error, rel ', LBLOCK-DESTBLK,', abs ',LBLOCK); EXIT(KRUNCH) END; AINX := AINX+FBLKSIZE END; RELBLOCK := RELBLOCK+CHUNKSIZE END UNTIL CHUNKSIZE = 0; DFIRSTBLK := DESTBLK; DLASTBLK := DESTBLK+NBLOCKS; WRITEDIR(GUNIT,GDIR) END; WRITELN(OUTPUT,GVID,': crunched'); IF REBOOT THEN BEGIN { *SYSTEM.PASCAL was moved } WRITELN(OUTPUT,'Please re-boot'); REPEAT UNTIL FALSE END; SYSCOM^.MISCINFO.NOBREAK := FALSE END; 1: END {KRUNCH} ; PROCEDURE CALLPROMPT; BEGIN PROMPT; CH := GETCHAR(BADCOMMAND); IF CH = ' ' THEN CLEARSCREEN ELSE BEGIN HOMECURSOR; CLEARLINE; IF CH = 'Q' THEN EXIT(FILEHANDLER) END END; BEGIN {FILEHANDLER} FILERINIT; REPEAT BADCOMMAND := FALSE; INSTRING := ''; CLEAR; REPEAT PL := 'Filer: G(et, S(ave, W(hat, N(ew, L(dir, R(em, C(hng, T(rans, D(ate, Q(uit [F.5]'; CALLPROMPT; IF CH = '?' THEN BEGIN PL := 'Filer: B(ad-blks, E(xt-dir, K(rnch, M(ake, P(refix, V(ols, X(amine, Z(ero [F.5]'; CALLPROMPT END; BADCOMMAND := NOT (CH IN ['B','C','D','E','G','K','L','M','N', 'P','R','S','T','V','W','X','Z']); UNTIL NOT BADCOMMAND; PL := ''; CASE CH OF 'L': LISTDIR(FALSE); 'E': LISTDIR(TRUE); 'G': GETWORK; 'N': NEWWORK(TRUE); 'C': CHANGER; 'R': REMOVER; 'T': TRANSFER; 'S': IF SAVEWORK(BADCOMMAND) THEN BEGIN { Saving workfile on a different disk } TRANSFER; IF NOT BADCOMMAND THEN BEGIN { The code file may need to be saved } BADCOMMAND := TRUE; IF SAVEWORK(BADCOMMAND) THEN TRANSFER END END; 'P': PREFIXER; 'W': WHATWORK; 'M': MAKEFILE; 'V': LISTVOLS; 'B': BADBLOCKS; 'Z': ZEROVOLUME; 'X': XBLOCKS; 'K': KRUNCH; 'D': DATESET END UNTIL FALSE END {FILEHANDLER} ; BEGIN END.