; ; NUNEW v1.0 ; 02/01/87 ; ; NuNEW is an RCP/M utility which displays your log of file transfer ; activity (i.e. NUKMD.LOG, LOG.SYS, etc) in various formats. Normal ; users are only able to view current uploads, while the sysop (and ; someone with WHEEL access) has a command line choice of 5 additional ; display options: ; ; WHEEL Option Description ; ------------ ----------- ; E Show *all* uploads and downloads ; D Show *all* downloads ; A Show *only* .ARK/.ARC file member downloads ; L Show *only* .LBR file member downloads ; P Show *only* private uploads ; ; ; NuNEW offers a number of enhancements which make it a perfect companion ; utility for those of you logging your file transfer activity via NUKMD ; or other remote file transfer utilities. Regardless of your log file's ; size, display of requested information begins with virtually no delay. ; ; (Note: NEW.ASM was copyrighted and released to public domain [1985] by ; Irv Hoff -- NuNEW is a direct upgrade.) ; ; Tom Brady ; Decibel PBBS ; (404) 288-6858 ; 300/1200/2400 bps ; ; ----- ; ; Remove the apostrophe from before the ASEG instruction, if using ; Microsoft's macro-assembler MACRO-80 (known as M80). Everyone ; else can ignore the next line. ; ; ASEG ; Required by M80 ; ; ----- ; NO EQU 0 YES EQU NOT NO ; ; User choices ; WHEEL EQU 3EH ; Location of your WHEEL byte CLOCK EQU yes ; Yes, if .LOG/.SYS contains TIME xfrs ; took place LOGSYS EQU no ; Yes, if your log file is stored as LOG.SYS, ; rather than *.LOG (i.e. MBBS systems). LOGDRV EQU 'C' ; .LOG/.SYS stored on this drive LOGUSR EQU 15 ; .LOG/.SYS stored in this user area ; PGPAWS: EQU yes ; Yes, page pausing wanted ; ; ======= ; ; Program starts here ; ORG 100H ; LXI H,0 DAD SP SHLD STACK ; Save current return to CCP address LXI SP,STACK ; Reset the stack ; ; If WHEEL is on, check for command line option requests. ; LDA WHEEL ORA A ; Ok to check? JZ START ; No, skip rest LXI H,FCB+1 MOV A,M ; Get the show option ORA A ; Anything? JZ START ; No, show uploads only, else... STA OPTION ; Save it ; ; Show program name and version number ; START: CALL ILPRT DB CR,LF,'NuNEW v',MAIN+'0','.',VERS+'0',' - ' DB MONTH/10+'0',MONTH MOD 10+'0','/' DB DAY/10+'0',DAY MOD 10+'0','/' DB YEAR/10+'0',YEAR MOD 10+'0',' ' DB CR,LF,LF,0 ; LDA 4 ; Get current drive/user STA DRUSER ; Store it MVI E,LOGUSR ; Set to user area of .LOG file MVI C,SETUSR CALL BDOS MVI A,LOGDRV ; Set to drive of .LOG file SUI 41H MOV E,A MVI C,SELDSK CALL BDOS ; ; Open source file ; LXI D,FILE MVI C,OPEN CALL BDOS INR A ; Check for no open JZ NONE ; No file, exit CALL ILPRT DB '[ ^S = pause / ^C, ^X or ^K = abort ]',CR,LF,LF,0 LXI D,FILE MVI C,35 ; Determine end-of-file CALL BDOS LXI D,BUFFER+81 MVI A,CR ; Force first line through STAX D DCR E LDA OPTION CPI 'P' ; Uploads? JZ HEADU CPI ' ' ; Uploads? JZ HEADU ; HEAD: CALL ILPRT DB 'd/u Filename Parent Size Speed Date ' ; IF CLOCK DB 'Time ' ENDIF ; DB 0 LDA OPTION CPI 'E' ; Everything? JNZ HEADD ; No CALL ILPRT DB 'Xfer by',0 JMP READX ; HEADD: CALL ILPRT DB 'Downloaded by',LF,CR,0 JMP READX ; HEADU: CALL ILPRT DB 'D/U Filename Size Speed Date ' ; IF CLOCK DB 'Time ' ENDIF ; DB 'Uploaded by',LF,CR,0 ; READX: PUSH D LXI H,RECORD ; Decrement record counter MOV E,M ; Get 16 bit number into DE INX H MOV D,M DCX D ; Now that we have the number, decrement MOV M,D ; And now store it again DCX H MOV M,E MOV A,E ; Now lets see if we are at the end CPI 0FFH ; First check high # JNZ READLP ; Ok, go on - else, check low number MOV A,D CPI 0FFH ; One past zero, so get last record JZ TDONE ; At the end, so finished ; ; Read sector from source file ; READLP: LXI D,TBUF ; Set the DMA for our read MVI C,STDMA CALL BDOS ; And do it now LXI D,FILE ; Now read the record MVI C,READ CALL BDOS POP D ; Restore register ORA A ; Read ok? JNZ RDERR ; No, abort LXI H,TBUF+127 ; Set up end of buffer MVI B,128 ; The buffer will be filled up backwards ; ONEMOR: MOV A,M ; Get character ANI 7FH CPI LF ; Check for end of line -- LF is our marker JZ WRDISK ; that we'll use to determine each line CPI 7FH JZ NXTONE CPI 1AH ; Check for CTRL-Z, end-of-file marker JZ NXTONE XCHG MOV M,A ; Store character in our working buffer XCHG DCR E ; Decrement counters (DE=work buffer) ; NXTONE: DCR L ; (HL=DMA) DCR B ; (B=Counter for number of char.) JZ READX ; If zero, go read another record JMP ONEMOR ; ; Write sector to output file (with buffering) ; WRDISK: DCR B ; Decrement our counter PUSH PSW ; As well as the flags DCR L ; Decrement our DMA buffer PUSH H ; Save it PUSH B ; Save counter XCHG ; HL will now be our working buffer MOV M,A ; Go save CR LDA OPTION CPI 'E' ; Show all? JZ WRDLOP ; Yes, else... INR L ; See if it is an upload MOV A,M STA STORE2 ; Store this away for later DCR L ; ; Check xfr types ; CPI 'S' ; Send? JNZ CKOPT ; No LDA OPTION CPI 'D' ; Downloads? JZ WRDLOP ; Ok JMP SENDX ; Yes, skip incorrect ; CKOPT: CPI 'L' ; .LBR? JNZ CKOPT1 ; No LDA OPTION ; Get command option CPI 'L' ; .LBR? JZ WRDLOP ; Ok CPI 'D' ; Downloads? JZ WRDLOP ; Ok JMP SENDX ; No, skip ; CKOPT1: CPI 'A' ; .ARK/.ARC? JNZ CKOPT2 ; No LDA OPTION CPI 'A' ; .ARK/.ARC? JZ WRDLOP ; Ok CPI 'D' ; Downloads? JZ WRDLOP ; Ok JMP SENDX ; No, skip ; CKOPT2: CPI 'P' ; Private? JNZ CKOPT3 ; No LDA OPTION CPI 'P' ; Private? JZ WRDLOP ; Ok JMP SENDX ; No, skip ; CKOPT3: CPI 'R' ; Upload? JNZ SENDX ; No LDA OPTION CPI ' ' ; Anything else? JNZ SENDX ; Yes, no good ; WRDLOP: MOV A,M ; Get byte from read buffer MOV B,A ; Save the character for now CPI CR ; CR? JZ SENDLF ; Yes, send it and start over CPI LF ; LF? JNZ WRDL0 ; No, continue output ; IF PGPAWS PUSH PSW ; Save LF LDA LINECT CPI 20 ; Page yet? CZ MORE ; Yes, pause POP PSW ; Restore LF or CR ENDIF ; JMP SEND ; Continue next line ; ; Will show entire .LOG in reverse if requested ; WRDL0: LDA COLUMN CPI 79 ; End of display? JZ WRD2 ; Yes ORA A ; First column? JNZ WRDL3 ; If not, exit INR A STA COLUMN ; Won't be in first column any longer ; ; Shows "P" entries only if wheel byte is set for SYSOP's use ; MOV A,B ; Get the character back STA STORE CPI 'P' ; This line a private upload? JNZ WRDL1 ; If not, exit LDA OPTION CPI 'E' ; Everything? JNZ WRDL00 ; No STA PRIVT ; Mark '*' JMP WRDL4 ; WRDL00: CPI 'P' ; Private? JNZ WRDL13 ; No STA PRIVT ; Mark '*' JMP WRDL4 ; WRDL1: CPI 'S' ; Download? JNZ WRDL11 LDA OPTION CPI 'D' JZ WRDL4 JMP WRDL13 ; Yes, incorrect ; WRDL11: CPI 'L' JNZ WRDL12 ; No LDA OPTION CPI 'D' JZ WRDL4 CPI 'L' JZ WRDL4 JMP WRDL13 ; WRDL12: CPI 'A' JNZ WRDL14 ; No LDA OPTION CPI 'D' JZ WRDL4 CPI 'A' JZ WRDL4 ; WRDL13: CPI 'E' ; Everything? JZ WRDL4 ; Yes, no skip XRA A STA STORE STA COLUMN JMP NEXT ; WRDL14: CPI 'R' ; Upload? JNZ WRDL13 ; No LDA OPTION CPI 'P' JNZ WRDL4 JMP WRDL13 ; WRD2: XRA A STA STORE ; Otherwise reset flag to zero ; WRDL3: LDA STORE ; Storing into memory? ORA A JZ NEXT ; If not, exit ; WRDL4: LDA COLUMN ; Increment the column counter INR A STA COLUMN LDA COLUMN ; Get the column count back CPI 3 ; User's modem speed is in column 2 JNZ WR1 ; If not column 2, continue MOV A,B ; Otherwise get the character STA STORE ; Store it for conversion to baud rate JMP NEXT ; Do not print the "MSPEED" number ; WR1: CPI 11 JC NEXT ; Skip everything through column 9 CPI 14 JC SEND ; Print everything through column 12 JNZ WR4 LDA PRIVT ; Going to distinguish a "P" line? ORA A JZ WR2 XRA A STA PRIVT MVI B,'*' CALL SEND1 JMP WR3 ; WR2: MVI B,':' ; Stick in a colon after column 12 CALL SEND1 ; WR3: MVI B,' ' ; Send a space JMP SEND ; WR4: CPI 22 ; Print through column 20 JC SEND JNZ WR5 CALL SEND1 ; Send character in colum 21 MVI B,'.' ; Add a period after the file name JMP SEND ; WR5: CPI 27 JC SEND ; Print file type and some spaces LDA OPTION CPI ' ' ; Uploads? LDA COLUMN JZ WR5B ; Yes, an orphan... LDA OPTION CPI 'P' ; Uploads? LDA COLUMN JZ WR5B ; More orphans... CPI 34 ; Parent possible, print through column 34 JC SEND JNZ WR5A ; Done here, print type CALL SEND1 ; Send character in column 33 MVI B,'.' ; Add a period after the file name JMP SEND ; WR5A: CPI 39 JC SEND ; Print file type JMP WR5C ; WR5B: CPI 39 JC NEXT ; Ignore the "big gap" ; WR5C: CPI 43 JC SEND ; Print the file size JZ WR6 JMP WR7 ; Continue with date ; WR6: CALL SEND1 ; Print space CALL BAUD ; Print the baud rate and a space JMP NEXT ; WR7: CPI 52 JC SEND ; Print the date JNZ WR8 JMP SEND ; Add a space ; WR8: IF CLOCK CPI 58 JC SEND ; Print the time program was sent JNZ SEND ; If not column 57, continue ENDIF ; CALL SEND1 ; Add two spaces JMP NEXT ; Continue with rest of line (name) ; SEND: PUSH H ; Keep buffer address MOV A,B ; Get the character back CALL OUTCHR POP H ; Get input buffer address back ; NEXT: INR L ; Done with sector? JMP WRDLOP ; No, get another byte ; SEND1: PUSH H ; Keep buffer address MOV A,B ; Get the character back CALL OUTCHR POP H ; Get input buffer address back RET ; SENDLF: XRA A STA COLUMN ; Othewise in column 0 now CALL ABORT ; Want to quit already? ; SENDL1: IF PGPAWS LDA LINECT INR A STA LINECT ; Increment line counter ENDIF ; CALL ILPRT DB CR,0 ; SENDX: XRA A ; Now restore everything so STA COLUMN ; We can get on with our business LXI D,BUFFER+80 POP B POP H POP PSW JZ READX ; If out of character in DMA buffer, JMP ONEMOR ; go read a sector ; ; ----------- ; SUBROUTINES ; ----------- ; ; Display message and pause for user input ; IF PGPAWS MORE: PUSH H ; Save TBUF address PUSH D PUSH B XRA A STA LINECT ; Clear counter POP PSW MVI A,CR ; Only need CR PUSH PSW CALL ILPRT DB CR,LF,' [Hit any key to continue]',CR,0 JMP ABORT0 ENDIF ; ; Aborts the display when requested, but only at end of line ; ABORT: PUSH H ; Save the TBUF address PUSH D PUSH B MVI C,CONST ; Check to see if key pressed CALL BDOS ORA A JZ ABORT3 ; If no key pressed, then continue ; ABORT0: MVI C,RDCON ; Otherwise wait for another character CALL BDOS ANI 7FH ; Remove parity, insure upper-case ; ABORT1: CPI 'C'-40H ; ^C? JZ ABORT2 CPI 'K'-40H ; ^K? JZ ABORT2 CPI 'X'-40H ; ^X? JZ ABORT2 ANI 5FH ; Convert to upper case CPI 'C' JZ ABORT2 CPI 'K' JZ ABORT2 CPI 'X' JNZ ABORT3 ; ABORT2: POP B ; Reset the stack POP D POP H POP H ; Clear CALL from stack CALL EXIT DB CR,LF,LF,'++ ABORTED ++','$' ; ABORT3: POP B POP D POP H RET ; ; Shows the received baud rate ; BAUD: LDA STORE CPI '0' JZ B110 CPI '1' JZ B300 CPI '5' JZ B1200 CPI '6' JZ B2400 MVI B,' ' CALL SEND1 CALL SEND1 CALL SEND1 CALL SEND1 JMP BFIN2 ; B110: MVI B,' ' CALL SEND1 MVI B,'1' CALL SEND1 MVI B,'1' CALL SEND1 JMP BFIN1 ; B300: MVI B,' ' CALL SEND1 MVI B,'3' JMP BFINSH ; B1200: MVI B,'1' CALL SEND1 MVI B,'2' JMP BFINSH ; B2400: MVI B,'2' CALL SEND1 MVI B,'4' ; BFINSH: CALL SEND1 MVI B,'0' CALL SEND1 ; BFIN1: MVI B,'0' CALL SEND1 ; BFIN2: MVI B,' ' CALL SEND1 MVI B,'b' CALL SEND1 MVI B,'p' CALL SEND1 MVI B,'s' CALL SEND1 MVI B,' ' JMP SEND1 ; ; Print message then exit to CP/M ; EXIT: POP D ; Get message address MVI C,PRINT ; Print message CALL BDOS CALL ILPRT ; Print CRLF before quitting DB CR,LF,0 LDA DRUSER ; Get original drive/user area back RAR RAR RAR RAR ANI 0FH ; Just look at the user area MOV E,A MVI C,SETUSR ; Restore original user area CALL BDOS LDA DRUSER ; Get the original drive/user back ANI 0FH ; Just look at the drive for now MOV E,A MVI C,SELDSK ; Restore original drive CALL BDOS LHLD STACK SPHL RET ; ; Inline print routine - prints string pointed to by stack until a zero ; is found. Returns to caller at the next address after the zero ter- ; minator. ; ILPRT: XTHL ; Save HL, get message address ; ILPLP: MOV A,M ; Get the character CALL TYPE ; Show on the CRT INX H ; Next character location MOV A,M ; Get the character ORA A ; If Zero, all done JNZ ILPLP ; Else keep going XTHL ; Restore HL, ret address RET ; Return past the end of the message ; ; Output a character to the new file buffer - first, see if there is ; room in the buffer for this character. ; OUTCHR: PUSH PSW ; Store the character for now CALL TYPE POP PSW RET ; ; Transfer is done - close destination file ; TDONE: MVI C,CLOSE LXI D,FILE CALL BDOS TDONE2: CALL EXIT DB CR,LF,LF,'[End of listing]','$' ; ; Send character in A register to console ; TYPE: PUSH B PUSH D PUSH H MOV E,A ; Character to 'E' for CP/M MVI C,WRCON ; Write to console CALL BDOS POP H POP D POP B RET ; ; Error messages ; RDERR: CALL EXIT DB CR,LF,'++ File read error ++','$' ; NONE: CALL EXIT DB CR,'++ No transfer log file found ++','$' ; ; .LOG file definition -- no need to define, since it looks for ; wild-card matching of your .LOG file. If LOGSYS is YES, your log ; file is normally stored as LOG.SYS and defined as such below. ; FILE: DB 0 ; IF NOT LOGSYS DB '????????LOG' ENDIF ; IF LOGSYS DB 'LOG SYS' ENDIF ; DB 0,0,0,0,0 DB 0,0,0,0,0 DB 0,0,0,0,0 DB 0,0,0,0,0,0 ; RECORD: DB 0,0,0 ; COLUMN: DB 0 ; Column of .LOG line DRUSER: DB 0 ; Original drive/user, for return LENGTH: DB 0 ; Maximum length of useable memory LINECT: DB 0 ; Line counter OPTION: DB ' ' ; Option flag PRIVT: DB 0 ; Flag for private uploads STORE: DB 0 STORE2: DB 0 ; ; ----- ; ; Equates ; CR EQU 0DH ; Carriage return EOF EQU 1AH ; End of file - ^Z FCB EQU 5CH ; Command buffer LF EQU 0AH ; Line feed TBUF EQU 80H ; Default buffer address ; MAIN EQU 1 VERS EQU 0 MONTH EQU 2 DAY EQU 1 YEAR EQU 87 ; ; ----- ; ; BDOS equates ; BDOS EQU 5 ; CP/M BDOS entry address RDCON EQU 1 ; Get character from console WRCON EQU 2 ; Write character to console PRINT EQU 9 ; Print string (DE) until '$' CONST EQU 11 ; Get console status function SELDSK EQU 14 ; Select requested disk drive OPEN EQU 15 ; Open disk file CLOSE EQU 16 ; Close disk file READ EQU 33 ; Read random file STDMA EQU 26 ; Set DMA address SETUSR EQU 32 ; Set user area on disk ; ; ----- ; DS 100 ; Room for 50-level stack ; ; Set write buffer to even page boundry ; BUFFER DS 81 ; Write buffer starts here STACK EQU BUFFER-2 ; END