! CLEAN for VAX, GDMR ! Utility to manage files on VMS ! ! Revision History, in reverse order ! ! 2.1.0 18-Jul-1986 JGH changed to use the Latice Logic command line ! parsing library and added /IDENT to print version ! ! This must be compiled with checks off, (gets integer overflow otherwise) external string (31) Product Code = "CLEAN", Version = "2", Release = "1", Revision = "0" recordformat dfidf(shortinteger a, b, c) recordformat namf(byteinteger bid {16_2}, bln {16_38}, rss, rsl, c integer rsa, shortinteger spare1, c byteinteger ess, esl, integer esa, c record (namf)name rfl, c integer dvi1, dvi2, dvi3, dvi4, c record (dfidf) fid, did, integer wcc, fnb) recordformat fabf(byteinteger bid {16_3}, bln {16_50}, c shortinteger ifi, integer fop, sts, stv, c integer alq, shortinteger deq, byteinteger fac, shr, c integer ctx, byteinteger rtv, org, rat, rfm, c integer jnl, record (*)name xab, c record (namf)name nam, integer fna, dna, c byteinteger fns, dns, shortinteger mrs, integer mrn, c shortinteger bls, byteinteger bks, fsz, c integer dev, sdc, integer spare1, spare2) recordformat fibf(string (2) acctl, byteinteger wsize, c record (dfidf) fid, did, integer wcc, c shortinteger nmctl, exctl, integer exsz, exvbn, c byteinteger alopts, alalign, string (9) alloc) recordformat rabf(byteinteger bid {16_1}, bln {16_44}, c shortinteger isi, integer rop, sts, stv, c shortinteger rfa1, rfa2, rfa3, spare1, c integer ctx, shortinteger spare2, c byteinteger rac, tmo, c shortinteger usz, rsz, integer ubf, rbf, rhb, kbf, c byteinteger ksz, spare3, mbf, mbc, integer bkt, c record (fabf)name fab, integer spare4) systemintegerfnspec get(record (rabf)name r, integer i, j) systemintegerfnspec put(record (rabf)name r, integer i, j) systemintegerfnspec readblock alias "SYS$READ" {block IO input} c (record (rabf)name r, integer i, j) systemintegerfnspec writeblock alias "SYS$WRITE" {block IO output} c (record (rabf)name r, integer i, j) systemintegerfnspec connect(record (rabf)name r, integer i, j) systemintegerfnspec open(record (fabf)name f, integer i, j) systemintegerfnspec close(record (fabf)name f, integer i, j) systemintegerfnspec create(record (fabf)name f, integer x, y) systemintegerfnspec erase(record (fabf)name f, integer i, j) systemintegerfnspec parse(record (fabf)name f, integer i, j) systemintegerfnspec search(record (fabf)name f, integer i, j) systemintegerfnspec rename(record (fabf)name old, integer i, j, c record (fabf)name new) recordformat iosbf(shortinteger status, count, integer divdep) recordformat acbf(shortinteger size, type, integer addr) systemintegerfnspec qiow(integer efn, chan, func, c record (iosbf)name iosb, c integer astadr, astprm, p1, p2, p3, p4, p5, p6) recordformat desc(integer length, addr) systemintegerfnspec assign(record (desc)name d, integername chan, c integer acmode, mbxnam) systemintegerfnspec dassgn(integer chan) recordformat recattrf(byteinteger rfo, atr, shortinteger lrl, c spare1, hbk, spare2, ebk, ffb, c byteinteger bkz, hsz, shortinteger mrz, dxq) systemroutinespec exit(integer i) from Imp include CLI Parse routine report(integer e1, e2) recordformat errf(short count, flags, integer e1, e2) systemroutinespec putmsg(record (errf)name msgvec, integer actrtn, facnam) record (desc) fac record (errf) mess ownstring (5) name = "CLEAN" if e1&16_fffff000 = 0 then mess_count = 1 else mess_count = 2 mess_flags = 1; mess_e1 = e1; mess_e2 = e2 fac_length = 5; fac_addr = addr(name)+1 putmsg(mess, 0, 0); !addr(fac)) end owninteger safe = 0; ! = 1 for deletion confirmation routine wait(integer i) systemintegerfnspec schdwk(integer pir, prcnam, integername daytim, c integer reptim) systemroutinespec hiber integer status, t2 = -1, t1 t1 = -10000*i status = schdwk(0, 0, t1, 0) signal 15, status if status&1 = 0 hiber end routine readline(string (*)name s) byteinteger ch string (255) t t="" cycle readsymbol(ch) s = t and return if ch = nl ch = ch-32 if 'a' <= ch <= 'z'; ! to upper case t = t.tostring(ch) repeat end constinteger abort = 16_2c, fnf = 16_18292, nmf = 16_182ca routine poct(integer i) integer j, k, flag = 0 for j = 30, -3, 0 cycle k = (i>>j)&7+'0' printsymbol(k) unless k = '0' and flag = 0 and j # 0 flag = flag+1 unless k = '0' repeat end recordformat timef(integer t1, t2) string (24)fn time(record (timef)name x) ! ! convert time in system format into an ascii string ! systemintegerfnspec asctim(integer a, record (desc)name d, c record (timef)name x, integer c) record (desc) d string (24) s integer status d_length = 23; d_addr = addr(s)+1; ! set up descriptor status = asctim(0, d, x, 0) ; ! convert x to ascii signal 15, status if status&1 = 0 length(s) = 23 result = s end integerfn getchan(string (255) file) ! ! get an IO channel to the disk file is on (for qiow later) ! string (255) junk integer status, chan = 0 record (desc) d file -> file.(":").junk; ! only want device name file = file.":"; ! put back colon (unnecessary?) d_length = length(file); ! set up descriptor length field d_addr = addr(file)+1; ! and address status = assign(d,chan,3,0) signal 15, status if status&1 = 0 result = chan end routine dropchan(integer chan) ! ! finished with channel, so deassign it ! integer status status = dassgn(chan) signal 15, status if status&1 = 0 end routine acp(record (dfidf)name fid, record (acbf)name a, c integer chan, func) ! ! queue an IO request to the ACP ! fid is file id (6 bytes) ! a is start of attribute control block list ! chan is IO channel ! func is the function required (IO$_....) ! record (fibf) f = 0; ! file information block record (iosbf) iosb; ! io status block record (desc) d integer status f_fid = fid; ! only fid field is set d_length = 44; ! descriptor length field for fib d_addr = addr(f); ! and address status = qiow(0,chan,func,iosb,0,0,addr(d),0,0,0,addr(a),0) signal 15, status if status&1 = 0 signal 15, iosb_status if iosb_status&1 = 0 end predicate privileged ! ! %true %if SYSPRV ! %false %otherwise ! recordformat if(short len, code, integer addr, retlen) recordformat pf(integer p1, p2) systemintegerfnspec getjpi(integer s1, pidadr, prcnam, itmlst, s2, s3, s4) record (if) end = 0, item = 0 record (pf) p integer status item_len = 8; item_code = 16_204; item_addr = addr(p) status = getjpi(0, 0, 0, addr(item), 0, 0, 0) signal 15, status if status&1 = 0 false if p_p1&(1<<16_1c) = 0 true end routine showowner(integer x) ! ! write out uic in octal ! routine woct(shortinteger i) printsymbol(i>>6&7+'0') printsymbol(i>>3&7+'0') printsymbol(i&7+'0') end printsymbol('[') woct(x>>16) printsymbol(',') woct(x&16_ffff) printsymbol(']') end routine setowner(integername x) ! ! put a new uic into the appropriate file attribute field ! shortinteger g, m routine readoct(shortintegername k) string (255) line integer ptr = 1 readline(line) cycle return if ptr > length(line) exit if byteinteger(addr(line)+ptr) > ' ' ptr = ptr+1 repeat signal 3, 1, byteinteger(addr(line)+ptr) c unless '0' <= byteinteger(addr(line)+ptr) <= '7' k = 0 while ptr <= length(line) and c '0' <= byteinteger(addr(line)+ptr) <= '7' cycle k = k<<3+(byteinteger(addr(line)+ptr)-'0') signal 1 unless k <= 8_377 ptr = ptr+1 repeat end routine getgroup ! ! read in group number ! on 1, 3 start if event_event = 1 start printstring("group number out of range") else printstring("non-octal character """.tostring(event_extra)."""") finish newline finish prompt("group: ") readoct(g) end routine getmember ! ! read in member number ! on 1, 3 start if event_event = 1 start printstring("member number out of range") newline else printstring("non-octal character """.tostring(event_extra)."""") newline finish finish prompt("member: ") readoct(m) end g = x>>16; m = x&16_ffff; ! unpack old uic getgroup getmember x = g<<16+m; ! pack into longword end routine o(record (dfidf)name fid, string (255) file) ! ! change owner of file (privileged) ! fid is file id (6 bytes) ! file is only to give device name ! record (acbf) term = 0, a = 0; ! attribute control block list integer owner, chan signal 6 unless privileged chan = getchan(file); ! need an IO channel to the disk a_size = 4; a_type = 16_15; a_addr = addr(owner) acp(fid,a,chan,16_32); ! access file printstring("current owner is "); showowner(owner); newline setowner(owner); ! change owner field acp(fid,a,chan,16_36); ! modify attribute printstring("new owner is "); showowner(owner); newline dropchan(chan); ! finished with IO channel end routine showprot(integer x) ! ! unpack and print file protection ! routine putprot(integer i) ! ! print protection for one class ! i = i&15 printstring("none") and return if i = 15 printsymbol('r') if i&1 = 0 printsymbol('w') if i&2 = 0 printsymbol('e') if i&4 = 0 printsymbol('d') if i&8 = 0 end printstring("system:"); putprot(x) printstring(" owner:"); putprot(x>>4) printstring(" group:"); putprot(x>>8) printstring(" world:"); putprot(x>>12) end routine setprot(shortintegername prot) ! ! set protection field of file attribute ! routine getprot(shortintegername i) ! ! read in, decode and pack file protection ! string (255) line integer j, ptr cycle readline(line); ptr = 0 i = -1 cycle ptr = ptr+1 return if ptr > length(line); ! no more j = byteinteger(addr(line)+ptr) if j = 'R' start i = i&10; ! read and execute continue else if j = 'W' i = i&8; ! write, read, execute continue else if j = 'E' i = i&11; ! execute continue else if j = 'D' i = 0; ! all continue else if j = 'N' i = i&15; ! none continue else printstring("spurious character """.tostring(j)."""") newline exit ; ! throw away the last line finish repeat repeat end shortinteger sys, own, gro, wor prompt("system: "); getprot(sys) prompt("owner: "); getprot(own) prompt("group: "); getprot(gro) prompt("world: "); getprot(wor) prot = (prot&16_fff0)+sys unless sys = -1; ! set system prot = (prot&16_ff0f)+own<<4 unless own = -1; ! set owner prot = (prot&16_f0ff)+gro<<8 unless gro = -1; ! set group prot = (prot&16_0fff)+wor<<12 unless wor = -1; ! set world prot = (prot&16_f0ff)+(prot&(prot>>4)&16_0f00); ! group >= world prot = (prot&16_ff0f)+(prot&(prot>>4)&16_00f0); ! owner >= group !! prot = (prot&16_fff0)+(prot&(prot>>8)&16_000f); ! system >= group end routine p(record (dfidf)name fid, string (255) file) ! ! change file protection ! fid is file id (6 bytes) ! file is for device name only ! record (acbf) term = 0, a = 0; ! attribute list integer chan shortinteger x; ! for protection code chan = getchan(file); ! get IO channel to disk a_size = 2; a_type = 16_16; a_addr = addr(x) acp(fid,a,chan,16_32); ! access file printstring("current protection - "); showprot(x); newline setprot(x); ! set up new protection acp(fid,a,chan,16_36); ! modify file attribute printstring("new protection - "); showprot(x); newline dropchan(chan); ! finished with IO channel end routine d(record (fabf)name f) ! ! delete file in NAM block ! integer status status = erase(f, 0, 0) signal 15, status, f_stv if status&1 = 0 end routinespec locate(record (fabf)name f) routine l(record (fabf)name f, string (255)name rs) ! ! list remaining files in directory ! integer i = 0, xtl string (255) oldfile = "#", ext, dir, file on 15 start newline unless i = 0 signal 15, event_sub, f_stv finish cycle locate(f); ! get next file length(rs) = f_nam_rsl; ! set resultant string length rs -> dir.("]").file; ! strip off directory file -> file.(".").ext; ! separate off extension unless file = oldfile start ; ! a new file name oldfile = file; ! remember it newline unless i = 0; ! not the first time through printstring(file) spaces(9-length(file)) i = 1 printsymbol('.') printstring(ext) xtl = length(ext); ! remember length of extension else ; ! same name, new ext/version i = i+1 if i = 8 start ; ! no more room on line newline spaces(9) i = 1 else spaces(8-xtl) finish printsymbol('.') printstring(ext) xtl = length(ext) finish repeat end conststring (10)array org(0:1) = "sequential", "relative" conststring (27)array rfm(0:5) = "undefined", "fixed-length", "variable-length", "variable with fixed control", "stream-CR?", "stream-LF" routine i(record (dfidf)name fid, string (255) file) ! ! info on file ! fid is file id (6 bytes) ! file is for device name only ! record (acbf) term = 0, revdate, credate, uic, fpro, revcnt, bakdate, c recattr, uchar; ! attributes list record (recattrf) a record (timef) rev, cre, bak integer u, chan, uch shortinteger prot, revns string (255) s = "" ! first set up attribute control blocks bakdate_size = 8; bakdate_type = 16_14; bakdate_addr = addr(bak) revdate_size = 8; revdate_type = 16_12; revdate_addr = addr(rev) credate_size = 8; credate_type = 16_11; credate_addr = addr(cre) revcnt_size = 2; revcnt_type = 16_d; revcnt_addr = addr(revns) uic_size = 4; uic_type = 16_15; uic_addr = addr(u) fpro_size = 2; fpro_type = 16_16; fpro_addr = addr(prot) recattr_size = 20; recattr_type = 4; recattr_addr = addr(a) uchar_size = 4; uchar_type = 3; uchar_addr = addr(uch) ! all done, we can now get the info chan = getchan(file) acp(fid,uchar,chan,16_32) dropchan(chan) ! and print it out printstring("owner: "); showowner(u) printstring("; file id: "); write(fid_a,0) printstring(", sequence no: "); write(fid_b,0) unless fid_c = 0 start printstring(", rel vol no: "); write(fid_c,0) finish newline printstring("created ".time(cre)) unless revns = 1 start printstring("; revised ".time(rev)." (") write(revns,1) printsymbol(')') finish newline unless bak_t1 = 0 and bak_t2 = 0 start printstring("last backed up ".time(bak)) newline finish printstring("protection - "); showprot(prot); newline printstring("blocks allocated:"); write(a_hbk,1) a_ebk = a_ebk-1 and a_ffb = 512 if a_ffb = 0 printstring("; blocks used:"); write(a_ebk,1) printstring(" (bytes used in last:"); write(a_ffb,1) printsymbol(')'); newline printstring("organisation: ".org(a_rfo>>4&1)) a_rfo = a_rfo&15; ! clear out organisation printstring("; format: ".rfm(a_rfo)); newline if a_rfo >= 2 start printstring("maximum allowed record length:") if a_mrz = 0 then printstring(" undefined") else c write(a_mrz,1) and printstring(" bytes") newline printstring("longest actual record:") write(a_lrl,1); printstring(" bytes") newline else if a_rfo = 1 printstring("record length:"); write(a_lrl,1) printstring(" bytes"); newline finish if a_atr > 7 start ; ! nospan s = "nospan, " a_atr = a_atr&7; ! clear nospan - the others are mutually exclusive finish if a_atr = 1 start s = s."FORTRAN CC, " else if a_atr = 2 s = s."implied CC, " else if a_atr = 4 s = s."print-file CC, " finish else s = s."no CC, " s = s."marked for deletion, " unless uch&16_8000 = 0 s = s."bad block, " unless uch&16_4000 = 0 s = s."directory, " unless uch&16_2000 = 0 s = s."spool, " unless uch&16_1000 = 0 s = s."contiguous, " unless uch&16_80 = 0 s = s."locked, " unless uch&16_40 = 0 s = s."contig-best-try, " unless uch&16_20 = 0 s = s."write-check, " unless uch&16_10 = 0 byteinteger(addr(s)) = byteinteger(addr(s))-2; ! remove last ", " printstring("characteristics: ".s) newline end record (timef)fn systime(string (255) t) ! ! convert time in ascii to system-format quadword ! systemintegerfnspec bintim(record (desc)name d, record (timef)name t) record (desc) d record (timef) b integer status d_length = length(t); d_addr = addr(t)+1 status = bintim(d,b) signal 15, status if status&1 = 0 result = b end integerfn stoi(string (255) s) ! ! convert string containing an integer to its value ! integer i = 0, ch, j for j = 1, 1, length(s) cycle ch = charno(s,j) signal 15, 16_12 unless '0' <= ch <= '9' i = i*10+(ch-'0') signal 15, 16_11ea unless i < 16_0fffffff; ! too big repeat result = i end routine dates(record (dfidf)name f, string (255) file) ! ! modify time attributes of file ! integer chan record (acbf) term = 0, credate, revdate, bakdate, revcnt record (timef) cre, rev, bak shortinteger cnt string (255) line signal 6 unless privileged chan = getchan(file) revcnt_size = 2; revcnt_type = 16_d; revcnt_addr = addr(cnt) bakdate_size = 8; bakdate_type = 16_14; bakdate_addr = addr(bak) revdate_size = 8; revdate_type = 16_12; revdate_addr = addr(rev) credate_size = 8; credate_type = 16_11; credate_addr = addr(cre) acp(f,revcnt,chan,16_32) printstring("created ".time(cre)) if cnt > 1 start printstring(", revised ".time(rev)." (") write(cnt,1) printsymbol(')') finish newline printstring("backed up ".time(bak)) and newline c unless bak_t1 = 0 and bak_t2 = 0 prompt("creation date/time "); readline(line) cre = systime(line) unless line = "" prompt("revision date/time "); readline(line) rev = systime(line) unless line = "" prompt("revision number "); readline(line) cnt = stoi(line)&16_7fff unless line = "" prompt("backup date/time "); readline(line) bak = systime(line) unless line = "" acp(f,revcnt,chan,16_36) dropchan(chan) end predicate directory(record (dfidf)name fid, string (255) d) ! ! %true if file is a directory ! %false otherwise ! don't believe file extension, look at file characteristics ! record (acbf) temp = 0, uchar; ! attributes list integer uch, chan uchar_size = 4; uchar_type = 3; uchar_addr = addr(uch) chan = getchan(d) acp(fid,uchar,chan,16_32); ! access file dropchan(chan) true unless uch&16_2000 = 0; ! a directory false end ownstring (5) defnam = "*.*;*" routine setup(string (*)name file, def, string (255)name es, rs, c record (fabf)name f, record (namf)name n) ! ! set up FAB, NAM blocks ! f_bid = 3; f_bln = 16_50 n_bid = 2; n_bln = 16_38 f_fna = addr(file)+1; f_fns = length(file) f_dna = addr(def)+1; f_dns = length(def) n_esa = addr(es)+1; n_ess = 127 n_rsa = addr(rs)+1; n_rss = 127 f_nam == n f_fop = 16_01000040; ! nam, sqo end routine checkname(record (fabf)name f) ! ! check and parse file name ! integer status status = parse(f, 0, 0) signal 15, status, f_stv if status&1 = 0 end routine locate(record (fabf)name f) ! ! look for a file and get its fid ! integer status status = search(f, 0, 0) signal 15, status, f_stv if status&1 = 0 end routine name(string (255) oldname, newname, string (*)name newrs) ! ! rename file to newname ! return it in newrs ! record (fabf) f1 = 0, f = 0 record (namf) n1 = 0, n = 0 string (255) es1, rs1, es, rs, def integer status oldname -> def.(";").es; ! lose version number def = def.";0"; ! want new one to be highest version setup(oldname, def, es, rs, f, n) setup(newname, def, es1, rs1, f1, n1) checkname(f) checkname(f1) locate(f) signal 15, abort if n_fid_a = n1_did_a; ! MT trap status = rename(f, 0, 0, f1) signal 15, status, f_stv if status&1 = 0 length(rs1) = n1_rsl newrs = rs1 end predicate dirempty(string (255) dir) ! ! %true if directory is empty ! %false otherwise ! record (fabf) f = 0 record (namf) n = 0 string (255) es, rs on 15 start true if event_sub = fnf; ! file not found => empty false ; ! some other error - assume it isn't empty finish setup(dir, defnam, es, rs, f, n) checkname(f) locate(f) false ; ! we suceeded in finding a file - not empty end routine nlines(record (fabf) f) record (rabf) r = 0 integer status, count = 0 systemintegerfnspec find(record (rabf)name r, integer i, J) r_bid = 1; r_bln = 16_44 r_fab == f r_rop = 16_10000; ! loc f_fac = 2; ! put status = open(f, 0, 0) signal 15, status, f_stv if status&1 = 0 status = connect(r, 0, 0) signal 15, status, r_stv if status&1 = 0 count = count+1 and status = find(r, 0, 0) until status&1 = 0 signal 15, status, r_stv unless status = 16_1827a printstring("file contains") write(count-1, 1) printstring(" record") printsymbol('s') unless count = 2 newline status = close(f, 0, 0) signal 15, status, f_stv if status&1 = 0 end routine t(record (fabf)name f, integer n) ! ! type out first n lines of file ! record (rabf) r = 0 record (fabf) f1 = f; ! copy the FAB - we want to change it string (255) s integer status, i, j, k if Interrupted start ; finish ; ! no ^C pending n = 16_7fffffff if n = 0; ! whole file (a large no. of lines) f1_fac = 2; ! get r_bid = 1; r_bln = 16_44 r_fab == f1 r_ubf = addr(s)+1 r_usz = 255 status = open(f1, 0, 0) signal 15, status, f1_stv if status&1 = 0 unless f1_org = 0 start printstring("file is not sequential") newline -> e finish status = connect(r, 0, 0) signal 15, status, r_stv if status&1 = 0 for i = 1, 1, n cycle exit if Interrupted; ! ^C - stop printing status = get(r, 0, 0) exit if status = 16_1827a; ! end of file signal 15, status, r_stv if status&1 = 0 unless r_rsz = 0 start for j = r_ubf,1,r_rsz+r_ubf-1 cycle ; ! down record k = byteinteger(j)&16_7f; ! lose parity printsymbol(k) if k >= ' ' or k = 9 or k = 13 repeat finish newline repeat e: status = close(f1, 0, 0) signal 15, status, f1_stv if status&1 = 0 end routine help newline printstring( c "? to print the current filespec") newline printstring( c "A <file> to append the file to another file") newline printstring( c "C <file> to copy the file into another file") newline printstring( c "D to delete the file (note that directories must be empty)") newline printstring( c "E to exit from the directory currently being scanned") newline printstring( c "F <filespec> to change temporarily to a new filespec") newline printstring( c "H to type this information") newline printstring( c "I to display details of the file characteristics") newline printstring( c "K to count the number of lines in the file") newline printstring( c "L to list the remaining files in the current directory") newline printstring( c "N <newfile> to rename the file to newfile") newline ! ! O to change file owner ! printstring( c "P to change the file protection - reply with r, w, e, d or n (for none)") newline printstring( c "Q to quit the program (^Z has the same effect)") newline printstring( c "R to restart the scan of the current directory from the top") newline printstring( c "S to enter and examine a subdirectory") newline printstring( c "T <n> to type out the first n lines of the file (default whole file)") newline ! ! U to allow alteration of end of file block ! ! ! W to alter time attributes ! printstring( c "X to exit from the directory currently being scanned") newline printstring( c "Z to clear the screen of a Tektronix and reprompt") newline printstring( c "<cr> to go on to the next file") newline printstring( c "^C to abort T") newlines(2) end routine u(record (dfidf)name fid, string (255) file) record (acbf) term = 0, recattr record (recattrf) a integer chan recattr_size = 20; recattr_type = 4; recattr_addr = addr(a) chan = getchan(file) acp(fid, recattr, chan, 16_32) printstring("size = "); write(a_hbk, 0) printstring(", block with ffb = "); write(a_ebk, 0); newline l: prompt("last block "); read(a_ebk) unless 0 <= a_ebk <= a_hbk start printstring("illegal block"); newline -> l finish skipsymbol while nextsymbol # nl; skipsymbol; ! trailing junk a_ebk = a_ebk+1; a_ffb = 0 acp(fid, recattr, chan, 16_36) dropchan(chan) end routine copy(record (fabf)name from, string (255) to) ! ! copy from file FROM to file TO ! use block-IO for speed ! record (fabf) f = from, t record (namf) n = 0 record (rabf) rf = 0, rt = 0 string (255) es, rs bytearray buff(1:512) integer status, blocks f_ifi = 0; ! must be zero f_fac = 16_22; ! bio, get status = open(f, 0, 0) signal 15, status, f_stv if status&1 = 0 t = f; ! most of the output FAB fields are as in the input file t_ifi = 0; ! must be zero t_fac = 16_21; ! bio, put t_fop = t_fop+16_20000000; ! ofp t_fna = addr(to)+1; t_fns = length(to) t_dna = 0; t_dns = 0 t_nam == n n_bid = 2; n_bln = 16_38 n_esa = addr(es)+1; n_ess = 127 n_rsa = addr(rs)+1; n_rss = 127 n_rfl == f_nam; ! related NAM block gives filename defaults status = create(t, 0, 0) signal 15, status, t_stv if status&1 = 0 rf_bid = 1; rf_bln = 16_44 rf_fab == f rf_rbf = addr(buff(1)); rf_rsz = 512 rf_ubf = addr(buff(1)); rf_usz = 512 rt = rf; rt_fab == t status = connect(rf, 0, 0) signal 15, status, rf_stv if status&1 = 0 status = connect(rt, 0, 0) signal 15, status, rt_stv if status&1 = 0 blocks = 0 cycle status = readblock(rf, 0, 0) exit if status = 16_1827a; ! eof signal 15, status, rf_stv if status&1 = 0 rt_rsz = rf_rsz; ! bytes transferred status = writeblock(rt, 0, 0) signal 15, status, rt_stv if status&1 = 0 blocks = blocks+1 repeat status = close(f, 0, 0) signal 15, status, f_stv if status&1 = 0 status = close(t, 0, 0) signal 15, status, t_stv if status&1 = 0 length(rs) = n_rsl write(blocks,0); printstring(" block") printsymbol('s') if blocks # 1 printstring(" copied to ".rs); newline end routine append(record (fabf)name f, string (255) to) bytearray buff(0:511) record (fabf) t = 0 record (namf) n = 0 record (rabf) rf = 0, rt = 0 string (255) rs, junk, junkk integer status, i to = to.";0" unless to -> junk.(";").junkk t_bid = 3; t_bln = 16_50 t_fna = addr(to)+1; t_fns = length(to) t_dna = f_nam_rsa; t_dns = f_nam_rsl t_fac = 1; ! put t_fop = 16_40; ! sqo t_nam == n n_bid = 2; n_bln = 16_38 n_rsa = addr(rs)+1; n_rss = 127 rf_bid = 1; rf_bln = 16_44 rf_rop = 16_00010000; ! loc rf_ubf = addr(buff(0)); rf_usz = 512 rf_fab == f rt_bid = 1; rt_bln = 16_44 rt_fab == t rt_rop = 16_100; ! eof status = open(t, 0, 0) signal 15, status&16_fffffff8, t_stv if status&1 = 0 status = open(f, 0, 0) if status&1 = 0 start i = close(t, 0, 0) signal 15, status, f_stv finish unless f_rfm = t_rfm and f_mrs = t_mrs start status = close(f, 0, 0) status = close(t, 0, 0) signal 15, 16_18570 finish status = connect(rt, 0, 0) signal 15, status, rt_stv if status&1 = 0 status = connect(rf, 0, 0) signal 15, status, rf_stv if status&1 = 0 i = 0 cycle status = get(rf, 0, 0) exit if status = 16_1827a; ! eof signal 15, status, rf_stv if status&1 = 0 rt_rbf = rf_rbf; rt_rsz = rf_rsz status = put(rt, 0, 0) signal 15, status, rt_stv if status&1 = 0 i = i+1 repeat status = close(f, 0, 0) signal 15, status, f_stv if status&1 = 0 status = close(t, 0, 0) signal 15, status, t_stv if status&1 = 0 write(i, 0); printstring(" record") printsymbol('s') unless i = 1 printstring(" appended to ") length(rs) = n_rsl printstring(rs); newline end routine perform(string (255) filespec, default) ! ! the main command interpreter ! integer marker = 16_12345678 string (255) es record (fabf) f = 0 record (namf) n = 0 string (255) rs switch com('?':'Z'+1) string (255) comline, dir, prmpt, file, junk, filex, filexx integer ok = 0, firsttime = 0, ii bytename bb on 6, 15 start -> com('Z'+1) if event_event = 6; ! probably strange command character if event_sub = fnf start ; ! couldn't find file length(es) = n_esl printstring("No files """.es."""") newline return else if event_sub = nmf; ! no more files return finish report(event_sub, event_extra) return if ok = 0; ! unsafe -> retry finish restart: setup(filespec, default, es, rs, f, n) checkname(f) firsttime = 0 comloop: return if firsttime = 1 and n_fnb&16_100 = 0; ! no wildcards ok = 0 locate(f); ! get next file ok = 1 length(rs) = n_rsl unless rs -> dir.("]").file start ; ! NJR trap rs -> dir.(">").file dir -> filex.("<").filexx dir = filex."[".filexx rs = dir."]".file finish if firsttime = 0 start length(es) = n_esl printstring("Current filespec ".es) newline firsttime = 1 finish prmpt = file." " for ii = 2, 1, length(prmpt) - 3 cycle ; ! can ignore ";n " bb == charno(prmpt, ii) bb = bb - 'A' + 'a' if 'A' <= bb <= 'Z' repeat prmpt = " ".prmpt while length(prmpt) < 19 again: retry: prompt(prmpt) readline(comline) comline -> (" ").comline while comline # "" and charno(comline, 1) = ' ' junk = "" unless comline -> comline.(" ").junk junk -> (" ").junk while junk # "" and charno(junk, 1) = ' ' -> comloop if comline = "" -> com(charno(comline,1)) com('?'): ! current filespec length(es) = n_esl printstring("Current filespec ".es) newline -> again com('A'): ! append prompt("append to:") readline(junk) while junk = "" append(f, junk) -> again com('C'): ! copy prompt("copy to: ") readline(junk) while junk = "" copy(f, junk) -> again com('D'): ! delete if safe = 1 start ; ! confirm deletion unless charno(comline, length(comline)) = '!' or c (junk # "" and charno(junk, 1) = '!') start prompt("delete ? ") readline(junk) junk -> (" ").junk while junk # "" and charno(junk, 1) = ' ' -> again if junk = "" or charno(junk, 1) # 'Y' finish finish if directory(n_fid,dir) start file -> filex.(".").junk junk = dir.".".filex."]" unless dirempty(junk) start printstring("cannot delete a non-empty directory") newline -> again finish finish d(f) printstring("deleted") newline -> comloop com('E'): com('X'): ! exit return com('F'): ! filespec prompt("filespec: ") readline(junk) while junk = "" perform(junk, es) printstring("Returning to previous filespec") newline -> comloop com('H'): ! help help -> again com('I'): ! file info i(n_fid, rs) -> again com('K'): ! count records in file nlines(f) -> again com('L'): ! list remaining files l(f, rs) com('N'): ! new name for file prompt("new name: ") readline(junk) while junk = "" name(rs, junk, filexx) filexx -> filex.("]").junk if filex = dir start printstring("renamed to ".junk) newline else printstring("renamed to ".filexx) newline finish -> comloop com('O'): ! change owner (privileged) o(n_fid, dir) -> again com('P'): ! change protection p(n_fid, dir) -> again com('Q'): ! quit program stop com('R'): ! restart -> restart com('S'): ! subdirectory unless directory(n_fid, dir) start printstring(file." is not a directory") newline -> again finish file -> filex.(".").junk; ! drop extension junk = dir.".".filex."]"; ! form new directory name perform(junk, defnam); ! do stuff on subdirectory printstring("Returning from subdirectory") newline -> again com('T'): ! type if junk = "" and length(comline) > 1 start junk = substring(comline,2,length(comline)) ii = 1 ii = ii+1 while ii <= length(junk) and c '0' <= charno(junk,ii) <= '9' length(junk) = ii-1 finish t(f, stoi(junk)) -> again com('U'): ! unscrew u(n_fid, dir) -> again com('W'): ! when (priv) dates(n_fid, dir) -> again com('Z'): ! clear Tektronix screen & reprompt print symbol(27); print symbol(140); newline wait(950) -> again com(*): ! everything else printstring("command ".comline." ?") newline -> again end begin externalpredicatespec batchmode alias "IMP_BATCH_MODE" string (255) junk, thisfile on 9, 15 start stop if event_event = 9 exit(event_sub) finish if Qualifier Present ("IDENTIFY") start Select Output (0) Print String (Product Code." version ".Version.".".Release) Print String (".".Revision) if Revision # "0" Newline return unless Qualifier Present ("FILES") finish if batchmode start printstring("CLEAN must be run interactively"); newline return finish Safe = 1 if Qualifier Present ("CONFIRM") This File = Qualifier S ("FILES") This File = "*.*;*" if This File = "" { Default is *.*;* } while This File # "" cycle thisfile = thisfile."[".junk while thisfile -> thisfile.("<").junk thisfile = thisfile."]".junk while thisfile -> thisfile.(">").junk perform(thisfile, defnam) This File = Qualifier S ("FILES") repeat end endoffile