& ! & ! SUBROUTINE: check account & ! & ! & ! & !save the cluster map & ! 10010 FOR I% = 0% TO 7% 10020 CLUSTER.MAP%(I%) = FNWORD%(249%+I%) & !these are the last eight words of the block 10030 NEXT I% 10100 ! & !get correct cluster, block and offset for this link & ! 10110 OFFSET% = FNLINK%(LINK.NB%) \ & !the function GETs the right cluster and finds the offset \ & BYTE.OFFSET% = OFFSET% \ & WORD.OFFSET% = OFFSET%/2% 10200 ! & !save the values of the other links (in case we leave this cluster & ! 10210 LINK.DTB% = FNWORD%(WORD.OFFSET% + 0%) 10500 ! & !data from date/time blockette & !(including link to password blockette) & ! 10510 OFFSET% = FNLINK%(LINK.DTB%) \ & !the function GETs the correct cluster and finds the offset \ & BYTE.OFFSET% = OFFSET% \ & WORD.OFFSET% = OFFSET%/2% 10520 KB.LAST% = FNBYTE%(BYTE.OFFSET% + 3%) 10530 DATE.LAST% = FNWORD%(WORD.OFFSET% + 2%) \ & TIME.LAST% = FNWORD%(WORD.OFFSET% + 3%) 10535 IF DATE.LAST% = 0% THEN DATE.LAST% = FNDATE.TO.NUMBER%(DATE$(0%)) 10540 IF FNCHECK% & THEN PRINT "["; \ & PRINT USING "###", PROJ%; \ & PRINT ","; \ & PRINT USING "###", PROG%; \ & PRINT "]"; \ & PRINT " Last signed in "; \ & PRINT "detached"; IF KB.LAST% = 255% \ & PRINT "at KB"; NUM1$(KB.LAST%);":"; IF KB.LAST% <> 255% \ & PRINT TAB(34);"on ";DATE$(DATE.LAST%); \ & PRINT " at ";TIME$(TIME.LAST%) 10900 ! & !done & ! 10990 RETURN 11000 ! & ! & ! SUBROUTINE: get specifications & ! & ! & ! 11100 ! & !accounts & !ask, do default, initialize counter & ! 11110 PRINT "Which accounts"; \ & INPUTLINE ACCTS$ \ & ACCTS$ = CVT$$(ACCTS$,2%+4%+32%) & !get it, remove spaces and delimiters, change to capitals, 11120 IF ACCTS$ = "" & THEN SKIP.ACCT.CHECK% = TRUE% \ & GOTO 11300 11130 I% = 0% 11200 ! & !pull them off one at a time & !not many error checks here & ! 11210 BRACKET% = INSTR(1%,ACCTS$,"]") 11220 IF BRACKET% <> 0% & THEN I% = I% + 1% & ELSE NUM.ACCTS% = I% \ & GOTO 11300 & !if there is another account, count it and continue 11230 ACCT$ = LEFT(ACCTS$,BRACKET%-1%) \ & ACCTS$ = RIGHT(ACCTS$,BRACKET%+2%) & !assume character after the bracket is a comma. Drop it and the & !bracket at the end 11240 ACCT$ = RIGHT(ACCT$,2%) & !assume first character is [ and drop it 11250 COMMA% = INSTR(1%,ACCT$,",") \ & PROJ$ = LEFT(ACCT$,COMMA%-1%) \ & PROG$ = RIGHT(ACCT$,COMMA%+1%) & !assume there is a comma 11260 IF PROJ$ = "*" & THEN PROJ%(I%) = 255% & ELSE PROJ%(I%) = VAL(PROJ$) & !assume no illegal numbers 11270 IF PROG$ = "*" & THEN PROG%(I%) = 255% & ELSE PROG%(I%) = VAL(PROG$) & !assume no illegal numbers 11280 GOTO 11210 & !try again 11300 ! & !keyboards & !ask, do default, initialize counter & ! 11310 PRINT "Which keyboards"; \ & MAT INPUT KBS$ 11320 IF KBS$(1%) = "" & THEN SKIP.KB.CHECK% = TRUE% \ & GOTO 11500 11330 I% = 0% 11400 ! & !interpret them one at a time & !note that J% counts enties and I% counts keyboards. They may not & !be the same. & ! 11410 FOR J% = 1% TO NUM 11420 IF LEFT(KBS$(J%),3%) = "DET" & THEN I% = I% + 1% \ & KB%(I%) = 255% \ & GOTO 11470 & !for detached keyboards 11430 HYPHEN%LAST BAS[.050020]LAST .BAS[.050020]    X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>?\\\\\\\\\`:#@'="\abcdefghi\\\\\\\jklmnopqr\\\\\\\~stuvwxyz\\\\\\\\\\\\\\\\\\\\\\{ABCDEFGHI\\\\\\}JKLMNOPQR\\\\\\\\STUVWXYZ\\\\\\0123456789\\\\\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~@ggh<i|o<m<4p<p<k|Zn<l fr rwx<x<x<x޺<w@]@@fjnr]Ze@@|> | |v<H|  |  |xz|  |zt f r   < &^ @&@'*/V,"?Lh:hmBmz|z{x`y~|fN|@@|@͂|@ ݃ƃ<ns<|Ŏ |️|ep|u|-@率|<ᄇ2ֻr||ZRM | ntB|xyvZw|J=|R>|J? nnaa|bddf%(I%) = 255%) & AND (PROG% = PROG%(I%) OR PROG%(I%) = 255%) & THEN GOTO 12200 12140 NEXT I% 12150 FNCHECK% = FALSE% \ & GOTO 12900 & !didn't make it past this check 12200 ! & !check keyboards & ! 12210 IF SKIP.KB.CHECK% THEN GOTO 12300 12220 FOR I% = 1% TO NUM.KBS% 12230 IF KB.LAST% = KB%(I%) & THEN GOTO 12300 12240 NEXT I% 12250 FNCHECK% = FALSE% \ & GOTO 12900 & !didn't make it past this check 12300 ! & !check dates & ! 12310 IF SKIP.DATE.CHECK% THEN GOTO 12900 12320 IF FIRST.DATE% <= DATE.LAST% & AND DATE.LAST% <= LAST.DATE% & THEN FNCHECK% = TRUE% & ELSE FNCHECK% = FALSE% 12900 ! & !end & ! 12990 FNEND 18000 ! & ! & ! FUNCTIONS & ! & ! 18100 ! & !pull a word from the buffer & !for convenience, the words are numbered as words even though the & !buffer is character (and hence byte) oriented. Words are normally & !numbered starting at zero, but the characters in the buffer must be & !numbered starting at one, so another adjustment is needed. & ! 18110 DEF* FNWORD%(W%) 18120 FIRSTBYTE% = W% * 2% + 1% 18180 FNWORD% = ASCII( MID(BUFF$,FIRSTBYTE% ,1%) ) & + SWAP%( ASCII( MID(BUFF$,FIRSTBYTE%+1%,1%) ) ) 18190 FNEND 18200 ! & !pull a byte from the buffer & !Since the bytes are generally numbered starting at zero but the & !characters are numbered begining at one, an adjustment is needed. & ! 18210 DEF* FNBYTE%(B%) 18280 FNBYTE% = ASCII(MID(BUFF$,B%+1%,1%)) 18290 FNEND 18300 ! & !convert a link & !If the link indicates another cluster, the correct cluster is GETted & !by the function. & ! & !In a link word the bits have the following meaning: & ! & ! 0 - 8 byte within the block & ! 9 - 11 cluster (16 blocks) number & ! 12 - 15 block within the cluster & ! 18310 DEF* FNLINK%(LINK%) 18320 CLUSTER.NUMBER% = ( LINK% AND 3584% ) / 512% \ & BLOCK.NUMBER% = SWAP%( LINK% AND -4096% ) / 16% \ & BYTE.NUMBER% = LINK% AND 511% 18330 IF CLUSTER.NUMBER% <> CURRENT.CLUSTER% & THEN GET #1%, BLOCK CLUSTER.MAP%(CLUSTER.NUMBER%) \ & CURRENT.CLUSTER% = CLUSTER.NUMBER% 18380 FNLINK% = BLOCK.NUMBER% * 512% + BYTE.NUMBER% 18390 FNEND 18400 ! & !convert date to number & ! 18410 DEF FNDATE.TO.NUMBER%(D$) 18420 D$ = CVT$$(D$,-1%) \ & D$ = "0" + D$ IF LEN(D$) = 8% \ & DAY% = VAL(LEFT(D$,2%)) \ & MON$ = MID(D$,4%,3%) \ & YEAR% = VAL(RIGHT(D$,8%)) 18430 FOR M% = 1% TO 12% 18440 IF MON$(M%) = MON$ & THEN MON% = MON%(M%) \ & M1% = M% 18450 NEXT M% 18460 IF YEAR%/4%*4% = YEAR% & AND M1% > 2% & THEN MON% = MON% + 1% 18470 FNDATE.TO.NUMBER% = ( YEAR% - 70 ) * 1000 + MON% + DAY% 18490 FNEND 18500 ! & !find the first digit in a string & ! 18510 DEF* FNFIND.DIGIT%(STR$) 18520 FOR I.FIND.DIGIT% = 1% TO LEN(STR$) 18530 C% = ASCII(MID(STR$,I.FIND.DIGIT%,1%)) 18540 IF 48% <= C% AND C% <= 57% & THEN FNFIND.DIGIT% = I.FIND.DIGIT% \ & GOTO 18590 18550 NEXT I.FIND.DIGIT% 18560 FNFIND.DIGIT% = 0% 18590 FNEND 32767 END LAST BAS[.050020]LAST .BAS[.050020]   X14|H [4;Ik(&'( k ߫H&P` \RrPP2PPzPP{PPPPP2P~\$\\TD 0D \~ hi) +\ ^( n ^( np\^txY\^ˀ\!kVk<\F˰<˴ˬ\VVkˤ1`@lP ABCDEFGHIJKLMNOPQRSTUVWXYZ$.?0123456789<@<SЬTЬ UQS>