PAGE 75,128 TITLE FILESYST - File subsystem for CCBBS. PAGE .XLIST INCLUDE CCBBS.MAC INCLUDE CCBBS.DEF .LIST ;----------------------------------------------- ;SYSTEM DATA SEGMENT ;----------------------------------------------- SYSDATA SEGMENT PARA PUBLIC 'DATA' EXTRN TIMEOUT:WORD EXTRN FDIRH:WORD CTBL0 DB 'AKWCX' ;DOWNLOAD PROTOCOLS CTBL1 DB 'AWCX' ;UPLOAD PROTOCOLS CTBL2 DB 'QAKWCXH' ;DOWNLOAD COMMANDS JTBL2 DW DNLO37 ;QUIT DW DNLO40 ;ASCII DW DNLO80 ;KERMIT DW DNLO60 ;XMODEM DW DNLO60 ;XMODEM DW DNLO60 ;XMODEM DW DNLO38 ;HELP CTBL3 DB 'QAWCXH' ;UPLOAD COMMANDS JTBL3 DW UPLO37 ;QUIT DW UPLO40 ;ASCII DW UPLO62 ;WXMODEM DW UPLO61 ;CXMODEM DW UPLO60 ;XMODEM DW UPLO38 ;HELP CTBL4 DB 'GHDMU?L' ;FILE COMMANDS JTBL4 DW GDBYE ;GOODBYE DW FIHELP ;HELP DW DNLOAD ;DOWNLOAD DW MMENU1 ;MAIN MENU DW UPLOAD ;UPLOAD DW FILE11 ;EXPERT HELP DW FIDIR ;LIST FILE DIRECTORY CTBL4A DB 'XX' ;FILE MENU 2 CHAR CMDS JTBL4A DW FILE30 ;DUMMY FILE COMMAND DW STREND-KPKTS KPKTS DB 'Sp% -# 1 ' STREND EQU $ SYSDATA ENDS ;----------------------------------------------- ;CODE SEGMENT ;----------------------------------------------- CSEG SEGMENT PARA PUBLIC 'CODE' EXTRN GETBUF:NEAR,FREBUF:NEAR,FEOF:NEAR,PADB:NEAR EXTRN BLANKF:NEAR,CMPSTR:NEAR,DQCMD:NEAR,DQTIOA:NEAR EXTRN GDBYE:NEAR,ILINEB:NEAR,LOGDSK:NEAR,MMENU1:NEAR EXTRN MOVSTL:NEAR,MOVSTR:NEAR,PTIME:NEAR,QUERY:NEAR EXTRN SENDF:NEAR,SENDHF:NEAR,STRIP:NEAR,TXPRT:NEAR EXTRN UNCMD:NEAR,WRMSG:NEAR,XLATE:NEAR,CONT:NEAR EXTRN ERROR:NEAR,CONR:NEAR,BINASP:NEAR,CKCTLK:NEAR EXTRN ELPTIM:NEAR,CONW:NEAR,CLRIBF:NEAR,WRBLK:NEAR EXTRN STM8B:NEAR,APPBYT:NEAR,QYES:NEAR,TSYSOP:NEAR EXTRN BINASC:NEAR,DATASC:NEAR,LOSTC:NEAR EXTRN STM7B:NEAR,BINASD:NEAR,DTEASC:NEAR,YIELD:NEAR EXTRN SKEOF:NEAR,WFBLK:NEAR,RFBLK:NEAR,DOSDAT:NEAR EXTRN WTBUFE:NEAR,PSECNO:NEAR,TAYSOP:NEAR,POSTCD:NEAR EXTRN QMSGNO:NEAR,WMSGNO:NEAR,QYESNO:NEAR EXTRN DSPSEC:NEAR,ASCBIN:NEAR,MOVMSG:NEAR,WSNOOP:NEAR EXTRN CKFSPC:NEAR,MVCSTR:NEAR,LALIGN:NEAR PUBLIC FILESS,CRCXXX,OPNLF ASSUME CS:CSEG,DS:NOTHING,ES:SYSDATA FILESYS PROC NEAR ;-------------------------------------------------------- ;FILE SUBSYSTEM MENU ;-------------------------------------------------------- FILESS: MOV DI,WORD PTR [BX+USRST] ;USER RECORD TEST BYTE PTR [DI+UESTAT],4 ;REJECTED? JZ FILE00 ;NO PROBLEM MOV AX,406 ;WHEN VALIDATED ... CALL WMSGNO ;DISPLAY MSG JMP MMENU1 ;MAIN MENU FILE00: MOV AX,64 ;'ENTERING ... CALL WMSGNO FILE10: CALL PTIME ;REMAINING TIME CALL TXPRT ;EXPERT MODE? JNZ FILE12 ;YES FILE11: MOV AX,62 ;FULL MENU CALL WMSGNO FILE12: CALL ILINEB ;FORMAT BUFFER MOV AX,239 ;FILE FUNCTION CALL MOVMSG CALL QUERY ;PROMPT FOR COMMAND JNC FILE20 JMP POSTCD ;HANDLE EXCEPTION FILE20: CALL DQCMD ;GET NEXT COMMAND JC FILE10 ;NO CMD, SO PROMPT AGAIN CALL LALIGN ;STRIP LEADING BLANKS CALL XLATE ;TRANSLATE TO UPPER CASE MOV CX,WORD PTR [SI-2] ;DATA LENGTH OR CX,CX ;NULL COMMAND? JZ FILE10 ;YES - PROMPT AGAIN CMP CX,2 ;MAX COMMAND LENGTH JAE FILE40 ;HANDLE EXTENDED COMMAND LODSB ;GET COMMAND MOV DI,OFFSET CTBL4 ;FILE COMMAND LIST MOV CX,(JTBL4-CTBL4) ;COMMAND TABLE SIZE REPNZ SCASB ;CHECK FOR MATCH JNZ FILE30 ;UNKNOWN COMMAND SUB DI,OFFSET CTBL4+1 ;OFFSET IN STRING SHL DI,1 ;TABLE WIDTH JMP JTBL4[DI] ;PERFORM COMMAND FILE30: CALL UNCMD ;UNKNOWN COMMAND ROUTINE JMP FILE10 ;PROMPT AGAIN FILE40: JNZ FILE30 ;FOR NOW MOV DI,OFFSET CTBL4A ;2 CHAR FILE MENU COMMANDS MOV CX,(JTBL4A-CTBL4A) ;COMMAND TABLE SIZE IN BYTES SHR CX,1 ;CONVERT TO WORDS LODSW ;GET COMMAND CHARS REPNZ SCASW ;CHECK FOR MATCH JNZ FILE30 ;NO MATCH SUB DI,OFFSET CTBL4A+2 ;OFFSET IN STRING JMP JTBL4A[DI] ;EXECUTE COMMAND FIHELP: MOV AX,6 ;HELP FILE NUMBER CALL SENDHF ;DISPLAY HELP FILE JMP FILE10 ;REPEAT PROMPT TPFILE: PUSH AX PUSH SI MOV SI,WORD PTR [BX+USRST] ;USER RECORD MOV AX,DS:MSGCKPT+MDPSECT ;PUBLIC SECTIONS NOT AX ;PRIVATE SECTIONS TEST WORD PTR [SI+UESECT],AX ;USER HAVE ANY? POP SI POP AX RET ;-------------------------------------------------------------- ;DISPLAY SELECTED FILE DIRECTORY ENTRIES ; BP-2 USER SECTION MASK ; BP-4 BLOCK NUMBER ; BP-6 FILE CLASS ; BP-8 FILE BUFFER ; BP-10 FILE COUNT ;-------------------------------------------------------------- FIDIR: PUSH BP MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,10 ;ALLOCATE LOCAL STORAGE XOR AX,AX MOV [BP-8],AX ;FILE BUFFER MOV [BP-10],AX ;FILE COUNT CMP WORD PTR [BX+USRIN],0 ;CLASS ALREADY IN BUFFER? JNZ FIDR00 ;YES MOV AX,5 ;HELP FILE NUMBER CALL SENDHF ;SEND HELP FILE FIDR00: MOV SI,63 ;FILE DIRECTORY PROMPT MSG MOV AX,DS:MSGCKPT+MDFCLAS ;DEFAULT TO NEW ARRIVALS CALL PSECNO ;PARSE RESPONSE JNC FIDR02 ;RESPONSE OK CMP WORD PTR [BX+USRIN],0 ;ANY STACKED REQUESTS? JNZ FIDR00 ;TRY THOSE JMP FIDR80 ;NO - EXIT FIDR02: MOV [BP-6],AX ;FILE CLASS MOV DI,WORD PTR [BX+USRST] ;USER RECORD MOV AX,WORD PTR [DI+UESECT] ;USER SECTION MASK MOV [BP-2],AX MOV AX,128 ;BUFFER SIZE CALL GETBUF ;GET FILE BUFFER MOV [BP-8],SI ;BUFFER ADDRESS MOV CX,FDIRH ;DIRECTORY FILE HANDLE CALL SKEOF ;FIND END OF FILE MOV [BP-4],AX ;BLOCK NUMBER MOV AX,29 ;^K TO ABORT ... CALL WMSGNO FIDR10: DEC WORD PTR [BP-4] ;PREVIOUS BLOCK JNS FIDR12 ;READ ENTRY JMP FIDR80 ;END OF FILE FIDR12: CALL YIELD ;LET SOMEONE ELSE RUN MOV AX,[BP-4] ;FILE BLOCK MOV CX,FDIRH ;DIRECTORY FILE HANDLE MOV SI,[BP-8] ;BUFFER ADDRESS CALL RFBLK ;READ FILE BLOCK MOV DI,[BP-8] ;FILE BUFFER MOV AX,[BP-6] ;FILE CLASS TEST WORD PTR [DI+FDCLAS],AX ;RIGHT CATEGORY? JZ FIDR10 ;NO CMP WORD PTR [DI+FDNAME],0 ;DELETED ENTRY? JZ FIDR10 ;YES - SKIP CMP WORD PTR [DI+FDSECT],0 ;FILE ASSIGNED TO SECTION? JZ FIDR20 ;NO MOV AX,[BP-2] ;USER SECTION MASK TEST WORD PTR [DI+FDSECT],AX ;AUTHORIZED? JZ FIDR10 ;NO - SKIP FIDR20: INC WORD PTR [BP-10] ;COUNT FILE CALL ILINEB ;FORMAT BUFFER ADD DI,FDNAME ;FILE NAME MOV CX,12 ;LENGTH OF NAME CALL MOVSTL ;MOVE TO BUFFER INC WORD PTR [SI-2] ;DELIMITER MOV DI,[BP-8] ;FILE BUFFER MOV AX,WORD PTR [DI+FDSIZE] ;LSB FILE SIZE MOV DX,WORD PTR [DI+FDSIZE+2] MOV CX,7 ;SIZE OF SIZE FIELD CALL BINASD ;CONVERT TO ASCII ADD WORD PTR [SI-2],2 ;DELIMITER MOV CX,WORD PTR [DI+FDCDAT] ;MSB CREATION DATE MOV DX,WORD PTR [DI+FDCDAT+2] CALL DTEASC ;PUT IN BUFFER MOV AX,235 ;DELIMITER CALL MOVMSG ;MOVE TO BUFFER MOV DI,[BP-8] ;FILE BUFFER ADD DI,FDDESC ;FILE DESCRIPTION MOV CX,40 ;LENGTH OF DESCRIPTION CALL MOVSTL ;MOVE TO BUFFER CALL WRMSG ;WRITE LINE JC FIDR90 ;NO MORE CALL CKCTLK ;CANCEL? JC FIDR90 ;YES JMP FIDR10 ;NEXT ENTRY FIDR80: CMP WORD PTR [BP-10],0 ;ANY FILES LISTED? JNZ FIDR90 ;YES - SKIP MESSAGE MOV AX,88 ;NO FILES FOUND CALL WMSGNO ;DISPLAY MESSAGE FIDR90: MOV SI,[BP-8] ;FILE BUFFER CALL FREBUF ;FREE IT MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE PREVIOUS FRAME JMP FILE10 ;FILE MENU ;DOWNLOAD A FILE ; BP-2 FILE NAME AS ENTERED ; BP-4 FILE HANDLE ; BP-6 FILE NAME STRING FOR DOS ; BP-8 GROUP NAME STRING ; BP-10 BLOCK COUNT ; BP-12 TRANSFER TIME/LAST BLOCK ACK'ED ; BP-14 TRANSMIT BUFFER ADDRESS ; BP-16 RECEIVE BUFFER ADDRESS (HANDSHAKING) ; BP-18 LOCAL FILE HANDLE/REMOTE PARITY SETTING ; BP-20 FILE TRANSFER TYPE ; 00 = BASIC XMODEM ; 01 = USE CRC INSTEAD OF SUM FOR BLOCK CHECK ; 02 = USE WINDOWED PROTOCOL ; 04 = HONOR X-ON X-OFF FLOW CONTROL ; 08 = USE DLE TO HIDE CONTROL CHARS ; 10 = USE 1024 BYTE BUFFERS ; 20 = SEND FILE NAME PRIOR TO FILE ; 40 = KERMIT ; 80 = ASCII ; 4000 = 1ST EOT SENT ; BP-22 FILE DIRECTORY ENTRY ; BP-24 # OF ERRORS ; BP-26 LAST ERROR CODE DNLOAD: MOV DI,WORD PTR [BX+USRST] ;USER RECORD TEST BYTE PTR [DI+UESTAT],8 ;PENDING? JZ DNLO00 ;NO PROBLEM MOV AX,406 ;WHEN VALIDATED ... CALL WMSGNO ;DISPLAY MSG JMP FILE10 ;FILE MENU DNLO00: PUSH BP MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,26 ;ALLOCATE LOCAL STORAGE XOR AX,AX ;ZERO MOV [BP-2],AX MOV [BP-4],AX MOV [BP-6],AX MOV [BP-8],AX MOV [BP-10],AX MOV [BP-12],AX MOV [BP-14],AX MOV [BP-16],AX MOV [BP-18],AX MOV [BP-20],AX ;DEFAULT TO XMODEM MOV [BP-22],AX MOV [BP-24],AX MOV [BP-26],AX DNLO10: CALL DQTIOA ;FILENAME JNC DNLO20 ;EXISTS MOV AX,65 ;ENTER FILE NAME CALL QMSGNO JC DNLO2X ;LOST CARRIER JMP DNLO10 ;GO HANDLE DNLO20: MOV CX,WORD PTR [SI-2] ;COMMAND LENGTH MOV [BP-2],SI ;FILE NAME AS ENTERED JCXZ DNLO2X ;EXIT CALL XLATE ;UPPER CASE CMP CX,12 ;MAX VALID NAME JBE DNLO24 ;NO PROBLEM CMP CX,50 ;TO LONG FOR MESSAGE? JBE DNLO21 ;NO PROBLEM MOV WORD PTR [SI-2],50 ;TRUNCATE DNLO21: CALL ILINEB ;FORMAT BUFFER MOV DI,[BP-2] ;FILE NAME CALL MOVSTR MOV AX,224 ;NOT VALID CALL MOVMSG CALL WRMSG DNLO2X: JMP DNLO90 ;EXIT DNLO24: MOV AX,[BP-2] ;TARGET FILE NAME PUSH AX ;PASS AS PARAMETER CALL CKFDIR ;CHECK FILE DIRECTORY JC DNLO28 ;NOT FOUND MOV [BP-22],SI ;FILE DIRECTORY STRING CMP WORD PTR [SI+FDSECT],0 ;ASSIGNED TO SECTION? JZ DNLO25 ;NO MOV DI,WORD PTR [BX+USRST] ;USER RECORD MOV AX,[DI+UESECT] ;SECTION BITS TEST WORD PTR [SI+FDSECT],AX ;AUTHORIZED JZ DNLO28 ;NO - TELL HIM 'NOT FOUND' DNLO25: TEST WORD PTR [BX+CBMDM],MDMKBD ;LOCAL USER? JNZ DNLO26 ;SKIP DIRECTORY UPDATE INC WORD PTR [SI+FDACNT] ;COUNT FILE ACCESS PUSH CX PUSH DX CALL DOSDAT ;GET DATE MOV WORD PTR [SI+FDADAT],CX MOV WORD PTR [SI+FDADAT+2],DX POP DX POP CX MOV AX,DX ;BLOCK NUMBER CALL WFBLK ;UPDATE BLOCK DNLO26: MOV SI,[BP-6] ;EXISTING STRING CALL FREBUF ;FREE IT MOV AX,37 ;BUFFER LENGTH CALL GETBUF ;GET A BUFFER MOV DI,[BP-22] ;DIRECTORY ENTRY ADD DI,FDPATH ;FILE PATH MOV CX,MSGSIZ-FDPATH ;PATH MAX LENGTH CALL MOVSTL ;MOVE TO BUFFER CALL STRIP ;TRIM TRAILING BLANKS MOV DI,[BP-22] ;DIRECTORY ENTRY ADD DI,FDNAME ;FILE NAME MOV CX,FDOWNR-FDNAME ;FILE NAME MAX LENGTH CALL MOVSTL ;MOVE TO BUFFER CALL STRIP ;TRIM TRAILING BLANKS XOR AX,AX ;DELIMITER CALL APPBYT ;MOVE TO BUFFER MOV [BP-6],SI ;SAVE STRING CALL OPNDF ;TRY TO OPEN FILE JNC DNLO30 ;OK DNLO28: CALL ILINEB ;FORMAT BUFFER MOV AX,212 ;FILE CALL MOVMSG MOV DI,[BP-2] ;FILE NAME CALL MOVSTR MOV AX,213 ;NOT FOUND CALL MOVMSG CALL WRMSG CALL ILINEB ;FORMAT BUFFER MOV AX,214 ;FILE CALL MOVMSG MOV DI,[BP-2] ;FILE NAME CALL MOVSTR MOV AX,215 ;NOT FOUND CALL MOVMSG CALL LOGDSK ;LOG TO CALLERS FILE JMP DNLO90 ;EXIT DNLO30: CMP WORD PTR [BX+USRIN],0 ;TYPE ALREADY IN BUFFER? JNZ DNLO35 ;YES MOV SI,WORD PTR [BX+USRST] ;USER RECORD MOV AL,BYTE PTR [SI+UEDLPC] ;GET DEFAULT CMP AL,0 ;DEFAULT SET? JZ DNLO32 ;NO CMP AL,'A' ;ASCII? JZ DNLO32 ;YES - TEST ASCII FLAG CALL TXPRT ;EXPERT? JZ DNLO33 ;NO - MUST PROMPT JMP SHORT DNLO36 ;USE IT DNLO32: MOV DI,[BP-22] ;DIRECTORY ENTRY TEST WORD PTR [DI+FDSTAT],1 ;ASCII FILE? JNZ DNLO33 ;NO MOV AX,66 ;BINARY FILE CALL WMSGNO DNLO33: CALL ILINEB ;INIT BUFFER MOV AX,67 ;DOWNLOAD TYPE CALL MOVMSG ;MOVE TO BUFFER MOV DI,WORD PTR [BX+USRST] ;USER RECORD MOV DL,BYTE PTR [DI+UEDLPC] ;DEFAULT CMP DL,0 ;ANYTHING? JZ DNLO34 ;NO MOV AL,'[' CALL APPBYT ;ADD TO STRING MOV AL,DL ;DEFAULT PROTOCOL CALL APPBYT ;ADD TO STRING MOV AL,']' CALL APPBYT ;ADD TO STRING MOV AL,' ' CALL APPBYT ;ADD TO STRING DNLO34: CALL QUERY ;PROMPT USER JC DNLO37 ;LOST CARRIER DNLO35: CALL DQCMD ;GET RESPONSE MOV AL,DL ;SET DEFAULT CALL LALIGN ;STRIP LEADING BLANKS MOV CX,WORD PTR [SI-2] ;LENGTH JCXZ DNLO36 ;USE DEFAULT CALL XLATE ;UPPER CASE LODSB ;GET CMD CHAR MOV DI,WORD PTR [BX+USRST] ;USER RECORD CMP BYTE PTR [DI+UEDLPC],0 ;ALREADY HAVE DEFAULT? JNZ DNLO36 ;YES MOV DI,OFFSET CTBL1 ;VALID DOWNLOAD DEFAULTS MOV CX,CTBL1-CTBL0 ;STRING LENGTH REPNZ SCASB ;CHECK FOR MATCH JNZ DNLO36 ;NOT VALID MOV DI,WORD PTR [BX+USRST] ;USER RECORD MOV BYTE PTR [DI+UEDLPC],AL ;SET AS DEFAULT DNLO36: MOV DI,OFFSET CTBL2 ;COMMAND TABLE MOV CX,(JTBL2-CTBL2) ;TABLE SIZE REPNZ SCASB ;CHECK FOR MATCH JNZ DNLO32 ;NO - REPEAT PROMPT SUB DI,OFFSET CTBL2+1 ;OFFSET IN STRING SHL DI,1 ;TABLE WIDTH JMP JTBL2[DI] ;GO TO ROUTINE DNLO37: JMP DNLO90 ;EXIT DNLO38: MOV AX,9 ;HELP FILE NUMBER CALL SENDHF ;SEND HELP FILE JMP DNLO32 ;REPEAT PROMPT ;ASCII DOWNLOAD DNLO40: CALL XFRTIM ;CALCULATE TRANSFER TIME JNC DNL40A ;TIME OK JMP DNLO52 ;NOT ENOUGH TIME DNL40A: MOV AX,70 ;XFER CAN BE SUSPENDED CALL WMSGNO MOV AX,71 ;READY TO SEND CALL WMSGNO MOV WORD PTR [BP-20],80H ;MARK ASCII TRANSFER CALL GXBUF ;GET TRANSMIT BUFFER DNLO41: CALL CONR ;WAIT FOR C/R CMP AL,13 ;C/R? JNZ DNLO41 ;NO AND WORD PTR [BX+CBFLG],NOT SFSNP ;DISABLE SNOOP DNLO42: CALL FABUF ;FILL INPUT BUFFER JZ DNLO47 ;END OF FILE DNLO43: CALL CONT ;ANY INPUT? JZ DNLO44 ;NO CALL CONR ;GET INPUT CMP AL,24 ;CANCEL? JNZ DNLO44 ;NO MOV AX,72 ;ABORTED CALL WMSGNO JMP DNLO90 ;EXIT DNLO44: CALL WRBLK ;WRITE BLOCK INC WORD PTR [BP-10] ;COUNT BLOCK ; CALL DLSTAT ;DISPLAY STATS JMP DNLO42 ;GET NEXT BLOCK DNLO47: MOV AL,26 ;END OF FILE CHAR CALL CONW ;WRITE EOF TEST WORD PTR [BX+CBMDM],MDMKBD JNZ DNLO48 ;LOCAL USER MOV AX,86 ;BELLS CALL WMSGNO DNLO48: MOV AX,73 ;END OF FILE CALL WMSGNO OR WORD PTR [BX+CBFLG],SFSNP ;ENABLE SNOOP DNLO49: CALL ILINEB ;FORMAT BUFFER MOV DI,[BP-6] ;FILE NAME STRING CALL MOVSTR DEC WORD PTR [SI-2] ;TRUNCATE DELIMITER MOV AX,218 ;DOWNLOADED CALL MOVMSG CALL MFTYPE ;ANNOTATE TRANSFER TYPE CALL LOGDSK ;LOG TO DISK MOV DI,WORD PTR [BX+USRST] ;USER RECORD INC WORD PTR [DI+UEDNLD] ;DOWNLOAD COUNT DNLO52: JMP DNLO90 ;EXIT ;XMODEM DOWNLOAD DNLO60: CALL XFRTIM ;CALCULATE TRANSFER TIME JC DNLO69 ;NOT ENOUGH TIME TEST WORD PTR [BX+CBMDM],MDMKBD JNZ DNLO70 ;LOCAL USER TEST WORD PTR [BX+DTESTAT],MPARE PUSHF ;SAVE TEST RESULTS JZ DNLO61 ;NO SWITCH TO 8 BIT NEEDED MOV AX,68 ;PLEASE SWITCH CALL WMSGNO DNLO61: MOV AX,69 ;READY TO SEND CALL WMSGNO POPF ;REMEMBER PARITY STATUS JZ DNLO62 ;NO SWITCH TO 8 BIT CALL STM8B ;SET 8 BIT NO PARITY DNLO62: CALL SNDXMD ;TRANSMIT FILE JC DNLO69 ;ABORTED JMP DNLO49 ;LOG DOWNLOAD DNLO69: JMP DNLO90 ;EXIT DNLO70: MOV AX,3C00H ;CREATE REQUEST CALL OPNLF ;OPEN LOCAL FILE JNC DNLO72 ;OPEN OK STC JMP DNLO90 DNLO72: MOV [BP-18],AX ;LOCAL FILE HANDLE CALL GXBUF ;GET FILE BUFFER DNLO74: CALL FABUF ;FILL BUFFER JZ DNLO78 ;END OF FILE CALL WLBUF ;WRITE TO FILE JC DNLO77 ;WRITE ERROR CMP AX,CX ;WRITE ALL BYTES? JZ DNLO74 ;YES MOV AX,241 ;OUT OF SPACE CALL WMSGNO ;TELL USER JMP SHORT DNLO78 ;CLOSE FILE DNLO77: ERR 0BH ;LOCAL FILE ERROR DNLO78: CALL CLSLF ;CLOSE LOCAL FILE JMP DNLO49 ;LOG DOWNLOAD ;KERMIT DOWNLOAD DNLO80: CALL XFRTIM ;CALCULATE TRANSFER TIME JC DNLO69 ;NOT ENOUGH TIME MOV WORD PTR [BP-20],40H ;MARK KERMIT PROTOCOL MOV AX,69 ;READY TO SEND CALL WMSGNO ;SEND MESSAGE MOV AX,WORD PTR [BX+DTESTAT] ;MODEM STATUS MOV [BP-18],AX ;SAVE MODEM STATUS TEST AX,MPARE ;7 BIT PROTOCOL? JZ DNLO82 ;NO PROBLEM CALL STM8B ;SWITCH TO 8 BIT DNLO82: CALL SNDKDL ;TRANSMIT FILE PUSHF ;SAVE ABORT STATUS TEST WORD PTR [BP-18],MPARE ;WAS 7 BIT? JZ DNLO89 ;NO PROBLEM CALL STM7B ;SWITCH TO 7 BIT DNLO89: POPF ;RECOVER STATUS JC DNLO69 ;ABORTED JMP DNLO49 ;LOG DOWNLOAD DNLO90: MOV SI,[BP-2] ;FILE NAME CALL FREBUF ;FREE IT MOV SI,[BP-6] ;FILE NAME STRING CALL FREBUF ;FREE IT MOV SI,[BP-14] ;XMIT BUFFER CALL FREBUF ;FREE IT MOV SI,[BP-16] ;RECEIVE BUFFER CALL FREBUF ;FREE IT MOV SI,[BP-22] ;DIRECTORY ENTRY CALL FREBUF ;FREE IT CALL CLSDF ;CLOSE FILE MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLER'S FRAME JMP FILE10 ;FILE MENU ;ANNOTATE FILE TRANSFER TYPE MFTYPE: MOV AX,227 ;ASSUME XMODEM AND WORD PTR [BP-20],0FFH ;CLEAR SESSION FLAGS CMP WORD PTR [BP-20],0 ;XMODEM? JZ MFTY10 ;YES MOV AX,225 ;TRY ASCII TEST WORD PTR [BP-20],80H ;GOOD GUESS? JNZ MFTY10 ;YES MOV AX,228 ;CXMODEM CMP WORD PTR [BP-20],1 ;IS IT? JZ MFTY10 ;YES MOV AX,226 ;KERMIT TEST WORD PTR [BP-20],40H ;OK? JNZ MFTY10 ;YES MOV AX,229 ;WXMODEM CMP WORD PTR [BP-20],15 ;HOW ABOUT IT? JZ MFTY10 ;YUP MOV AX,230 ;YMODEM CMP WORD PTR [BP-20],11H ;OK? JZ MFTY10 ;YES MOV AX,231 ;ZMODEM MFTY10: CALL MOVMSG ;MOVE TO BUFFER RET BLDFN: MOV SI,[BP-6] ;FILE NAME STRING CALL FREBUF MOV AX,MLCNAM-MFPATH ;MAX PATH LENGTH MOV CX,AX ;SAVE FOR MOVE CALL GETBUF ;GET BUFFER MOV DI,OFFSET DS:MSGCKPT+MFPATH CMP BYTE PTR [DI],0 ;ANY? JZ BLDF10 ;NO CALL MOVSTL ;MOVE TO BUFFER CALL STRIP ;STRIP BLANKS MOV [BP-8],SI ;SAVE PATH BLDF10: MOV AX,WORD PTR [SI-2] ;LENGTH MOV SI,[BP-2] ;FILE NAME ADD AX,WORD PTR [SI-2] ;LENGTH INC AX ;ALLOW FOR DELIMITER CALL GETBUF MOV DI,[BP-8] ;DIRECTORY STRING CALL MOVSTR MOV DI,[BP-2] ;FILE NAME CALL MOVSTR MOV AL,0 ;DELIMITER CALL APPBYT ;ADD TO STRING MOV [BP-6],SI ;SAVE BUFFER ADDRESS RET OPNDF: MOV AX,3D00H ;OPEN FOR INPUT MOV DX,[BP-6] ;FILE NAME STRING INT 21H ;DOS REQUEST JNC OPNDF1 ;OPEN OK RET OPNDF1: MOV [BP-4],AX ;FILE HANDLE RET OPNUF: MOV AH,3CH ;CREATE FILE MOV DX,[BP-6] ;FILE NAME STRING XOR CX,CX ;NORMAL FILE INT 21H ;DOS REQUEST JNC OPNDF1 ;OPEN OK RET CLSDF: PUSH BX MOV BX,[BP-4] ;FILE HANDLE OR BX,BX ;ANYTHING? JZ CLSDFX ;NO MOV AH,3EH ;CLOSE INT 21H ;DOS REQUEST MOV WORD PTR [BP-4],0 ;SHOW FILE CLOSED CLSDFX: POP BX RET ;--------------------------------------------------------- ;OPEN LOCAL FILE ; ENTRY: AX=REQUEST TYPE (3D00H IS INPUT) ; RETURNS: AX=FILE HANDLE IF C=0 ;--------------------------------------------------------- OPNLF: PUSH AX ;REQUEST TYPE MOV AX,85 ;LOCAL FILESPEC CALL QMSGNO ;ASK JC OPNLFX ;LOST CARRIER CALL DQCMD ;GET RESPONSE CALL LALIGN ;STRIP LEADING BLANKS CALL XLATE ;UPPER CASE MOV DX,SI ;STRING ADDRESS ADD SI,WORD PTR [SI-2] ;POINT PAST END MOV BYTE PTR [SI],0 ;TERMINATE STRING POP AX ;REQUEST TYPE XOR CX,CX ;NORMAL FILE INT 21H ;DOS REQUEST JNC OPNLFX ;OPEN OK MOV AX,87 ;CAN NOT OPEN CALL WMSGNO STC OPNLFX: RET WLBUF: MOV AH,40H ;WRITE REQUEST CALL RWLB WLBUFX: RET RLBUF: PUSH DI MOV DI,[BP-14] ;DATA BUFFER MOV WORD PTR [DI-2],131 ;SET LENGTH TO MAX MOV AH,3FH ;READ REQUEST CALL RWLB MOV WORD PTR [DI-2],AX ;ACTUAL LENGTH READ OR AX,AX ;END OF FILE? POP DI RET RWLB: PUSH DX PUSH DI MOV DI,[BP-14] ;DATA ADDRESS MOV DX,DI MOV CX,WORD PTR [DI-2] ;DATA LENGTH PUSH BX MOV BX,[BP-18] ;LOCAL FILE HANDLE INT 21H ;DOS REQUEST POP BX POP DI POP DX CALL YIELD ;BE GOOD NEIGHBOR RET CLSLF: MOV AH,3EH ;CLOSE PUSH BX MOV BX,[BP-18] ;LOCAL FILE HANDLE OR BX,BX ;ANYTHING? JZ CLSLFX ;NO INT 21H ;DOS REQUEST MOV WORD PTR [BP-18],0 ;SHOW FILE CLOSED CLSLFX: POP BX RET KILULF: MOV AH,41H ;DELETE FILE MOV DX,[BP-6] ;FILE NAME STRING INT 21H ;DOS REQUEST JNC KILULX ;NO PROBLEM ERR 5 KILULX: RET ;GET TRANSMIT BUFFER GXBUF: MOV AX,133 ;BUFFER SIZE CALL GETBUF ;GET BUFFER MOV [BP-14],SI ;XMIT BUFFER CALL LSZER ;SEEK TO START OF FILE RET ;FILL TRANSMIT BUFFER FOR ASCII DOWNLOAD FABUF: MOV CX,132 ;DATA LENGTH MOV DX,[BP-14] ;DATA ADDRESS CALL FRBUF ;READ DATA INTO BUFFER MOV SI,[BP-14] ;BUFFER ADDRESS MOV WORD PTR [SI-2],AX ;ACTUAL DATA LENGTH OR AX,AX ;CHECK END OF FILE RET ;FILL TRANSMIT BUFFER FOR XMODEM DOWNLOAD FXBUF: MOV DX,[BP-14] ;START OF BUFFER ADD DX,3 ;SKIP OVER HEADER MOV CX,128 ;DATA LENGTH CALL FRBUF ;FILL BUFFER MOV SI,[BP-14] ;BUFFER ADDRESS MOV WORD PTR [SI-2],AX ;ACTUAL DATA LENGTH OR AX,AX ;CHECK END OF FILE JNZ FXBU10 ;NOT YET RET FXBU10: CMP AX,128 ;FULL BUFFER? JZ FXBU20 ;NO PROBLEM MOV CX,128 ;FULL BUFFER SUB CX,AX ;LENGTH TO CLEAR MOV DI,SI ;START OF BUFFER ADD DI,3 ;SKIP HEADER ADD DI,AX ;SKIP DATA XOR AX,AX ;NULLS PUSH ES PUSH DS POP ES REP STOSB ;CLEAR END OF RECORD POP ES FXBU20: INC WORD PTR [BP-10] ;COUNT BLOCK ;COMPUTE CHECK SUM MOV SI,[BP-14] ;BUFFER ADDRESS ADD SI,3 ;SKIP HEADER MOV CX,128 ;BLOCK SIZE TEST WORD PTR [BP-20],1 ;USE CRC? JNZ FXBU22 ;YES CALL CLCSUM ;CALCULATE CHECK SUM JMP SHORT FXBU30 ;STORE IN BUFFER FXBU22: CALL CRCXXX ;CALCULATE CHECK SUM XCHG AH,AL ;XMODEM CONVENTION FXBU30: LEA DI,[SI+128] ;END OF DATA MOV [DI],AX ;PUT CHECKSUM IN BLOCK ;BUILD HEADER FXBU40: MOV SI,[BP-14] ;BUFFER ADDRESS MOV WORD PTR [SI-2],132 ;SHOW FULL BLOCK TEST WORD PTR [BP-20],1 ;CRC? JZ FXBU50 ;NO INC WORD PTR [SI-2] ;ALLOW FOR 2 BYTE CRC FXBU50: MOV DI,SI ;START OF BUFFER MOV AL,1 ;SOH MOV [DI],AL INC DI MOV AX,[BP-10] ;BLOCK NUMBER MOV [DI],AL INC DI XOR AX,-1 ;MUST YIELD NON-ZERO MOV [DI],AL INC DI RET ;CALCULATE CHECK SUM IN AX CLCSUM: PUSH SI PUSH CX XOR AX,AX ;INITIALIZE CHECKSUM CLCS10: ADD AL,BYTE PTR [SI] ;ADD TO CHECKSUM INC SI LOOP CLCS10 POP CX POP SI RET ;CALCULATE CRC IN AX CRCXXX: PUSH CX PUSH DX PUSH SI XOR DX,DX ;INITIALIZE CRC CRCB10: LODSB ;GET NEXT CHAR CALL CRCBIT ;CALCULATE NEW CRC LOOP CRCB10 ;KEEP IT MOVING MOV AX,DX ;RETURN CRC IN AX POP SI POP DX POP CX RET CRCBIT: PUSH CX MOV CX,8 ;BITS PER BYTE XOR DH,AL ;AL * 2 ^16 + DX CRCB60: SAL DX,1 JNB CRCB70 XOR DX,1021H CRCB70: LOOP CRCB60 POP CX RET ;READ FILE DATA INTO BUFFER FRBUF: PUSH BX MOV AH,3FH ;READ REQUEST MOV BX,[BP-4] ;FILE HANDLE INT 21H ;DOS REQUEST POP BX JNC FRBUFX ;GOOD READ ERR 6 FRBUFX: RET ;RESET FILE TO CORRECT BLOCK FLBLK: PUSH BX MOV AX,[BP-10] ;BLOCK COUNT MOV CX,128 ;BLOCK SIZE MUL CX ;CONVERT TO OFFSET MOV CX,DX ;MSW OFFSET MOV DX,AX ;LSW OFFSET MOV AX,4200H ;LSEEK MOV BX,[BP-4] ;FILE HANDLE INT 21H ;DOS FUNCTION CALL POP BX RET ;GET PROTOCOL BUFFER GPBUF: MOV AX,40 ;BUFFER SIZE CALL GETBUF ;GET BUFFER MOV [BP-16],SI ;PROTOCOL BUFFER RET ;CALCULATE TRANSFER TIME XFRTIM: CALL LSEND ;SEEK TO END OF FILE MOV CX,128 ;BLOCK SIZE DIV CX ;CALCULATE BLOCKS OR DX,DX ;REMAINDER? JZ XFRT10 ;NO INC AX ;ROUND UP XFRT10: MOV [BP-10],AX ;BLOCK COUNT CALL ILINEB ;FORMAT BUFFER MOV AX,221 ;FILE SIZE CALL MOVMSG MOV AX,[BP-10] ;BLOCKS CALL BINASP MOV AX,222 ;BLOCKS CALL MOVMSG CALL WRMSG MOV AX,[BP-10] ;BLOCKS MOV CX,139 ;BYTES PER BLOCK MUL CX ;TOTAL BYTES MOV CX,240 ;2400 BAUD TEST WORD PTR [BX+DTESTAT],MSP024 JNZ XFRT20 MOV CX,120 ;1200 BAUD TEST WORD PTR [BX+DTESTAT],MSP012 JNZ XFRT20 MOV CX,30 ;300 BAUD TEST WORD PTR [BX+DTESTAT],MSP003 JNZ XFRT20 MOV CX,960 ;9600 BAUD TEST WORD PTR [BX+DTESTAT],MSP096 JNZ XFRT20 MOV CX,480 ;4800 BAUD TEST WORD PTR [BX+DTESTAT],MSP048 JNZ XFRT20 MOV CX,5000 ;LOCAL XFER TEST WORD PTR [BX+CBMDM],MDMKBD JNZ XFRT20 ;LOCAL DISPLAY MOV CX,1440 ;UNKNOWN SPEED XFRT20: DIV CX ;TIME IN SECONDS XOR DX,DX MOV CX,60 DIV CX ;MIN IN AX SEC IN DX MOV [BP-12],AX ;XFER TIME IN MINUTES CALL ILINEB ;FORMAT BUFFER MOV AX,223 ;TRANSFER TIME CALL MOVMSG MOV AX,[BP-12] ;TIME IN MINUTES OR AX,AX ;ANY MINUTES? JZ XFRT30 ;NO CALL BINASP MOV AX,192 ;MINUTES CALL MOVMSG XFRT30: MOV AX,DX ;SECONDS CALL BINASP MOV AX,193 ;SECONDS CALL MOVMSG CALL WRMSG CALL TAYSOP ;PRIVILEDGED USER? JNZ XFRT40 ;YES CALL ELPTIM ;ELAPSED TIME MOV AH,60 ;MIN/HOUR MOV AL,CH ;HOURS MUL AH ;CONVERT TO MINUTES XOR CH,CH ;CBW ADD AX,CX ;TOTAL MINUTES MOV CX,WORD PTR [BX+USRLMT] ;ALLOWED TIME SUB CX,AX ;REMAINING TIME JB XFRT39 ;OUT OF TIME CMP CX,WORD PTR [BP-12] ;TRANSFER TIME JNB XFRT40 ;NO PROBLEM XFRT39: MOV AX,83 ;NOT ENOUGH TIME CALL WMSGNO STC ;SHOW NOT ALLOWED XFRT40: RET LSZER: MOV AL,0 ;USE OFFSET FROM START JMP SHORT LSEND1 LSEND: MOV AL,2 ;USE OFFSET FROM END LSEND1: XOR CX,CX ;MSW OF OFFSET MOV DX,CX ;LSW OF OFFSET MOV AH,42H ;LSEEK PUSH BX MOV BX,[BP-4] ;FILE HANDLE INT 21H ;DOS REQUEST POP BX JNC LSEND2 ;NO ERROR ERR 6 LSEND2: RET SNDXMD: MOV WORD PTR [BP-10],0 ;CLEAR BLOCK COUNT MOV WORD PTR [BP-12],0 ;LAST BLOCK ACK'ED CALL GXBUF ;GET XMIT BUFFER CALL WTBUFE ;WAIT FOR OUTPUT CALL CLRIBF ;CLEAR INPUT BUFFER ;WAIT FOR START SNDX10: CALL CONR ;WAIT FOR INPUT JNC SNDX12 ;NO PROBLEM JMP SNDX90 ;LOST CARRIER - ABORT SNDX12: CMP AL,24 ;CANCEL? JNZ SNDX13 ;NO PROBLEM JMP SNDX90 ;YES - ABORT SNDX13: CMP AL,21 ;NAK? JZ SNDX15 ;YES - BASIC XMODEM CMP AL,'C' ;XMODEM-CRC? JNZ SNDX14 ;NO MOV WORD PTR [BP-20],1 ;USE CRC FOR ERROR CHECKING JMP SHORT SNDX15 ;ENTER COMMON CODE SNDX14: CMP AL,'W' ;WINDOWED XMODEM? JNZ SNDX10 ;NO - KEEP WATCHING MOV WORD PTR [BP-20],15 ;CRC+WINDOWED+FLOW+DLE ;SEND ONE BLOCK SNDX15: AND WORD PTR [BX+CBFLG],NOT SFSNP ;DISABLE SNOOP MOV WORD PTR [BX+CBRTV],1086 ;60 SEC TIMEOUT CALL CLRIBF ;CLEAR INPUT BUFFER SNDX16: CALL FXBUF ;FILL OUTPUT BUFFER JNZ SNDX20 ;GO WRITE BLOCK JMP SNDX80 ;END OF FILE SNDX20: CALL WRBLK ;WRITE BLOCK CALL DLSTAT ;DISPLAY STATUS ;GET RESPONSE FROM RECEIVER CALL WTBUFE ;WAIT FOR OUTPUT COMPLETE TEST WORD PTR [BP-20],2 ;WINDOWED? JZ SNDX30 ;NO CALL CONT ;ANY INPUT? JNZ SNDX30 ;YES SNDX25: MOV AX,[BP-10] ;BLOCK COUNT INC AX ;NEXT BLOCK TO SEND AND AX,3 ;BLOCK # IN WINDOW MOV CX,[BP-12] ;LAST BLOCK ACK'ED AND CX,3 ;RELATIVE BLOCK # CMP AX,CX ;WINDOW FULL? JZ SNDX30 ;YES - WAIT FOR ACK JMP SNDX16 ;SEND NEXT BLOCK SNDX30: CALL CONR ;WAIT FOR RESPONSE JNC SNDX34 ;RECEIVED CHAR TEST WORD PTR [BX+CBFLG],SFLC ;LOST CARRIER JNZ SNDX31 ;YES - EXIT TEST WORD PTR [BX+CBFLG],SFTO ;TIME OUT? JNZ SNDX32 ;YES SNDX31: JMP SNDX90 ;NO - ASSUME CANCEL REQUEST SNDX32: MOV WORD PTR [BP-26],2 ;SHOW TIME OUT INC WORD PTR [BP-24] ;COUNT ERROR TEST BYTE PTR [BX+CBMSR],MSRCD ;STILL HAVE CARRIER? JZ SNDX31 ;NO - EXIT JMP SNDX20 ;RESEND LAST BLOCK SNDX34: CMP AL,6 ;ACK? JNZ SNDX40 ;NO TEST WORD PTR [BP-20],2 ;WINDOWED? JZ SNDX16 ;NO - NEXT BLOCK CALL CONR ;GET BLOCK # AND AX,3 ;WINDOW BITS MOV CX,[BP-12] ;LAST BLOCK ACK'ED AND CL,0FCH ;CLEAR WINDOW BITS OR AX,CX ;FULL BLOCK NUMBER MOV [BP-12],AX ;LAST BLOCK ACK'ED JMP SNDX25 ;CHECK WINDOW FULL SNDX40: INC WORD PTR [BP-24] ;COUNT ERROR CMP AL,21 ;NAK? JNZ SNDX50 ;TRY CANCEL MOV WORD PTR [BP-26],3 ;NAK TEST WORD PTR [BP-20],2 ;WINDOWED? JZ SNDX20 ;NO - RESEND BLOCK CALL CONR ;GET BLOCK # MOV DL,AL ;SAVE BLOCK # DEC AL ;LAST GOOD BLOCK AND AL,3 ;VALID RANGE XOR AH,AH ;CBW MOV [BP-12],AX ;LAST GOOD BLOCK MOV AX,[BP-10] ;BLOCK NUMBER AND AL,0FCH ;CLEAR WINDOWED BITS AND DL,3 ;ISOLATE WINDOWED BITS OR AL,DL ;NEW BLOCK NUMBER CMP AX,[BP-10] ;PAST LAST BLOCK? JBE SNDX45 ;NO PROBLEM SUB AX,4 ;BACK UP ONE WINDOW LENGTH SNDX45: DEC AX ;CONVERT TO ZERO OFFSET MOV [BP-10],AX ;LAST GOOD BLOCK CALL FLBLK ;SEEK TO NAK'ED BLOCK JMP SNDX16 ;RE-SEND NAK'ED BLOCK SNDX50: CMP AL,24 ;CANCEL? JZ SNDX90 ;YES MOV WORD PTR [BP-26],1 ;INVALID RESPONSE JMP SNDX30 ;KEEP LOOKING SNDX80: MOV AL,4 ;EOT CALL CONW ;SEND EOT OR WORD PTR [BP-20],4000H ;SHOW EOT SENT CALL CONR ;WAIT FOR RESPONSE JC SNDX90 ;LOST CARRIER CMP AL,6 ;ACK? JNZ SNDX40 ;CHECK FOR NAK MOV AL,4 ;EOT CALL CONW ;SEND 2ND EOT CLC JMP SHORT SNDX99 ;EXIT SNDX90: TEST WORD PTR [BP-20],4000H ;EOT SENT? JNZ SNDX99 ;YES - GOOD XFER STC SNDX99: PUSHF OR WORD PTR [BX+CBFLG],SFSNP ;ENABLE SNOOP MOV AX,TIMEOUT ;DEFAULT TIMEOUT MOV WORD PTR [BX+CBRTV],AX ;RESTORE NORMAL TIMEOUT POPF RET ;TRANSMIT A FILE WITH KERMIT PROTOCOL SNDKDL: MOV WORD PTR [BP-10],0 ;CLEAR BLOCK COUNT AND WORD PTR [BX+CBFLG],NOT SFSNP ;TURN OFF SNOOP MOV WORD PTR [BX+CBRTV],100 ;5 SEC TIMEOUT CALL GXBUF ;GET TRANSMIT BUFFER CALL GPBUF ;GET PROTOCOL BUFFER ;BUILD SEND-INIT PACKET MOV SI,[BP-14] ;BUFFER ADDRESS MOV WORD PTR [SI-2],3 ;POINT TO TYPE FIELD MOV DI,OFFSET KPKTS ;SEND-INIT PACKET CALL MVCSTR ;MOVE TO BUFFER CALL KSDPKT ;SEND PACKET JNC SNDK20 ;GOOD RESPONSE SNDK12: JMP SNDK80 ;ABORT SNDK20: CALL CKACK ;GOOD ACK? JNZ SNDK12 ;NO - ABORT INC WORD PTR [BP-10] ;BLOCK COUNT ;PROCESS RECEIVERS PARAMETERS HERE ;SEND FILE-HEADER PACKET MOV SI,[BP-14] ;BUFFER ADDRESS MOV DI,[BP-2] ;FILE NAME MOV WORD PTR [SI-2],4 ;ALLOCATE HEADER MOV BYTE PTR [SI+3],'F' ;SHOW PACKET TYPE CALL MOVSTR ;MOVE IN FILE NAME CALL KSDPKT ;SEND PACKET JNC SNDK44 ;GOOD RESPONSE SNDK42: JMP SNDK80 ;ABORT SNDK44: CALL CKNAK ;GOOD ACK OR NEXT NAK? JNZ SNDK42 ;NO - ABORT SNDK48: INC WORD PTR [BP-10] ;NEXT BLOCK ;SEND DATA SNDK50: CALL DLSTAT ;DISPLAY STATS MOV SI,[BP-14] ;BUFFER ADDRESS MOV CX,WORD PTR [SI-6] ;BUFFER LENGTH CMP CX,94 ;MAX PACKET LENGTH JLE SNDK51 ;NO PROBLEM MOV CX,94 ;LIMIT PACKET LENGTH SNDK51: SUB CX,15 ;HEADER & TRAILER LEA DX,[SI+4] ;START OF DATA CALL FRKBUF ;PUT DATA INTO BUFFER OR AX,AX ;END OF FILE? JZ SNDK61 ;YES ADD AX,4 ;TOTAL LENGTH MOV WORD PTR [SI-2],AX ;MARK STRING LENGTH MOV BYTE PTR [SI+3],'D' ;PACKET TYPE CALL KSDPKT ;SEND PACKET JNC SNDK56 ;GOOD RESPONSE SNDK54: JMP SNDK80 ;ABORT SNDK56: CMP BYTE PTR [SI+3],'Y' ;ACK? JNZ SNDK58 ;NO - CHECK NAK CMP BYTE PTR [SI+1],'#' ;ANY DATA? JZ SNDK48 ;NO - SEND NEXT BLOCK CMP BYTE PTR [SI+4],'X' ;INTERRUPT? JZ SNDK60 ;YES - GO TO EOF CMP BYTE PTR [SI+4],'Z' ;INTERRUPT? JZ SNDK60 ;GO TO EOF JMP SNDK48 ;NEXT BLOCK SNDK58: CALL CKNAK ;NAK OF NEXT BLOCK? JZ SNDK48 ;YES - TAKE AS ACK JMP SNDK80 ;ABORT ;SEND EOF PACKET SNDK60: INC WORD PTR [BP-10] ;INCREMENT BLOCK COUNT SNDK61: MOV SI,[BP-14] ;TRANSMIT BUFFER MOV WORD PTR [SI-2],4 ;HEADER LENGTH MOV BYTE PTR [SI+3],'Z' ;EOF PACKET CALL KSDPKT ;SEND PACKET JNC SNDK64 ;GOOD RESPONSE SNDK62: JMP SNDK80 ;ABORT SNDK64: CALL CKNAK ;ACK OF CURRENT OR NAK OF NEXT? JZ SNDK70 ;YES - SEND BREAK JMP SNDK62 ;ABORT ;SEND BREAK SNDK70: INC WORD PTR [BP-10] ;NEXT BLOCK MOV SI,[BP-14] ;TRANSMIT BUFFER MOV WORD PTR [SI-2],4 ;HEADER LENGTH MOV BYTE PTR [SI+3],'B' ;PACKET TYPE CALL KSDPKT ;SEND PACKET JNC SNDK74 ;GOOD RESPONSE SNDK72: JMP SNDK80 ;ABORT SNDK74: CALL CKACK ;PROPER ACK? JZ SNDK90 ;DONE CMP BYTE PTR [SI+3],'N' ;NAK? JNZ SNDK80 ;NO - ABORT CMP BYTE PTR [SI+2],' ' ;BLOCK 0? JZ SNDK90 ;TREAT AS ACK ;ABORT SNDK80: STC JMP SHORT SNDK92 ;EXIT SNDK90: CLC SNDK92: PUSHF MOV AX,TIMEOUT ;SYSTEM TIMEOUT VALUE OR WORD PTR [BX+CBFLG],SFSNP ;ENABLE SNOOP MOV WORD PTR [BX+CBRTV],AX ;RESTORE NORMAL TIMEOUT POPF RET ;COMPUTE LENGTH AND CHECKSUM FOR KERMIT BLOCK KBLKCK: PUSH SI ;BUFFER POINTER PUSH CX PUSH DX XOR DX,DX ;INIT COUNTER MOV BYTE PTR [SI],1 ;MARK CHARACTER AND WORD PTR [BP-10],63 ;BLOCK # MOD 64 MOV CX,WORD PTR [BP-10] ;BLOCK COUNT KBLK10: ADD CL,' ' ;CONVERT TO CHARACTER MOV BYTE PTR [SI+2],CL ;STORE IN PACKET MOV CX,WORD PTR [SI-2] ;DATA LENGTH DEC CX ;KERMIT LENGTH CONVENTION ADD CL,' ' ;CONVERT TO CHAR FORMAT MOV BYTE PTR [SI+1],CL ;STORE IN BUFFER ADD WORD PTR [SI-2],3 ;CHECKSUM & DELIMITER MOV CX,[SI-2] ;BUFFER LENGTH SUB CX,4 ;COUNT FOR BLOCK CHECK CALL KCKSUM ;CALCULATE CHECKSUM MOV BYTE PTR [SI],DL ;STORE CHECKSUM MOV BYTE PTR [SI+1],13 ;CARRIAGE RETURN MOV BYTE PTR [SI+2],10 ;LINE FEED POP DX POP CX POP SI RET KCKSUM: INC SI ;SKIP MARK CHARACTER XOR DX,DX ;CLEAR CHECKSUM REGISTER KCKS10: LODSB ;GET NEXT CHAR ADD DL,AL ;ADD TO CHECKSUM LOOP KCKS10 ;KEEP IT MOVING MOV DH,DL AND DH,0C0H ;ISOLATE HIGH BITS MOV CL,6 ;SHIFT FACTOR SHR DH,CL ;DIVIDE BY 64 ADD DL,DH ;ADD IN HIGH BITS AND DL,3FH ;FORCE TO CORRECT RANGE ADD DL,' ' ;CONVERT TO PRINTABLE RET ;READ A KERMIT PACKET KRDPKT: CALL CLRIBF ;CLEAR INPUT BUFFER CALL WTBUFE ;WAIT FOR OUTPUT DONE MOV SI,[BP-16] ;BUFFER ADDRESS MOV DI,SI ;CURRENT BUFFER POSITION MOV WORD PTR [SI-2],0 ;CLEAR COUNT MOV CL,13 ;CARRIAGE RETURN MOV CH,1 ;START OF HEADER KRDP10: CALL CONR ;READ FROM LINE JNC KRDP20 ;GOOD READ TEST WORD PTR [BX+CBFLG],SFLC ;LOST CARRIER JNZ KRDP11 ;YES TEST WORD PTR [BX+CBFLG],SFTO ;TIME OUT? JNZ KRDP12 ;YES KRDP11: MOV AL,1 ;LOST CARRIER ERROR CODE JMP KRDP80 ;ABORT KRDP12: CMP WORD PTR [SI-2],4 ;HEADER RECEIVED? JLE KRDP14 ;NO JMP KRDP30 ;VALIDATE PACKET KRDP14: MOV AL,16 ;TIME OUT ERROR CODE JMP KRDP80 ;ABORT KRDP20: CMP WORD PTR [SI-2],0 ;FIRST CHARACTER? JNZ KRDP22 ;NO CMP AL,18H ;CANCEL? JNZ KRDP21 ;NO MOV AL,2 ;CANCEL ERROR CODE JMP KRDP80 ;ABORT KRDP21: CMP AL,CH ;START OF HEADER? JNZ KRDP10 ;NO - SKIP KRDP22: CMP AL,CL ;END OF PACKET? JZ KRDP30 ;YES MOV [DI],AL ;PLACE IN BUFFER INC DI INC WORD PTR [SI-2] ;COUNT CHARACTER MOV AX,WORD PTR [SI-2] ;CURRENT COUNT ADD AX,8 ;ACCOUNT FOR HEADER CMP AX,WORD PTR [SI-6] ;BUFFER FULL? JL KRDP10 ;READ NEXT CHARACTER KRDP30: XOR CX,CX MOV AL,4 ;INVALID LENGTH ERROR CODE CMP WORD PTR [SI-2],4 ;READ AT LEAST A HEADER? JLE KRDP80 ;NO - ABORT MOV CL,BYTE PTR [SI+1] ;LENGTH FIELD SUB CL,' ' ;CONVERT TO BINARY CALL KCKSUM ;CALCULATE CHECKSUM CMP DL,BYTE PTR [SI] ;COMPARE WITH RECEIVED MOV SI,WORD PTR [BP-16] ;RESTORE BUFFER POINTER JZ KRDP90 ;GOOD PACKET MOV AL,8 ;BAD CHECKSUM ERROR CODE KRDP80: STC ;SHOW ABORT RET KRDP90: XOR AX,AX ;SHOW GOOD PACKET RET ;SEND KERMIT PACKET AND READ RESPONSE KSDPKT: CALL KBLKCK ;COMPUTE CHECKSUM MOV CX,10 ;RETRY COUNT KSDP10: PUSH CX MOV SI,[BP-14] ;TRANSMIT BUFFER CALL WRBLK ;SEND BUFFER CALL KRDPKT ;READ RESPONSE POP CX ;RETRY COUNT JNC KSDP30 ;GOOD READ TEST AL,3 ;ABORT WITHOUT RETRY? JNZ KSDP90 ;YES KSDP20: LOOP KSDP10 ;TRY AGAIN JMP KSDP90 ;ABORT KSDP30: CMP BYTE PTR [SI+3],'N' ;NAK? JNZ KSDP80 ;NO - RETURN MOV AX,[BP-10] ;CURRENT BLOCK ADD AL,' ' ;CONVERT TO CHAR CMP AL,BYTE PTR [SI+2] ;NAK THIS BLOCK? JZ KSDP20 ;YES - RESEND KSDP80: XOR AX,AX ;SHOW GOOD RETURN RET KSDP90: STC ;SHOW BAD RETURN RET ;CHECK FOR ACK OF CURRENT BLOCK OR NAK OF NEXT - RETURNS Z=1 IF SO CKNAK: CMP BYTE PTR [SI+3],'N' ;NAK? JNZ CKACK ;NO - TRY ACK MOV AX,[BP-10] ;BLOCK COUNT INC AX ;NEXT BLOCK NUMBER AND AX,63 ;MOD 64 CKNAK1: ADD AL,' ' ;CONVERT TO CHAR CMP AL,BYTE PTR [SI+2] ;BLOCK COUNT IN BUFFER CKNAKX: RET CKACK: CMP BYTE PTR [SI+3],'Y' ;ACK? JNZ CKNAKX ;NO - EXIT MOV AX,[BP-10] ;BLOCK COUNT JMP CKNAK1 ;ENTER COMMON CODE ;FILL A KERMIT OUTPUT BUFFER FRKBUF: PUSH DX PUSH SI PUSH DI XOR SI,SI ;CLEAR COUNT REGISTER FRKB10: PUSH CX ;REMAINING COUNT MOV CX,1 ;READ ONE BYTE CALL FRBUF ;READ CHAR INTO BUFFER OR AX,AX ;END OF FILE? JNZ FRKB15 ;NO POP CX ;REMAINING COUNT JMP FRKB90 ;YES - EXIT FRKB15: MOV DI,DX ;CURRENT DATA CHAR CMP BYTE PTR [DI],'#' ;PREFIX CHAR? JNZ FRKB20 ;NO PROBLEM MOV BYTE PTR [DI+1],'#' ;REPLICATE IT JMP FRKB70 ;ADJUST COUNT FRKB20: CMP BYTE PTR [DI],7FH ;DELETE CHAR? JZ FRKB30 ;YES - GO PREFIX CMP BYTE PTR [DI],0FFH ;DELETE CHAR? JZ FRKB30 ;YES - GO PREFIX TEST BYTE PTR [DI],60H ;CONTROL CHAR JNZ FRKB80 ;NO PROBLEM FRKB30: MOV AL,BYTE PTR [DI] ;GET CHAR XOR AL,40H ;MAKE PRINTABLE MOV BYTE PTR [DI+1],AL ;PUT IN BUFFER MOV BYTE PTR [DI],'#' ;PREFIX FRKB70: INC SI ;COUNT PREFIX CHAR INC DX ;ADVANCE BUFFER POINTER POP CX ;BUFFER LENGTH DEC CX ;REMAINING COUNT PUSH CX FRKB80: INC SI ;COUNT CHAR INC DX ;NEXT BUFFER POSITION POP CX ;REMAINING COUNT CMP CX,2 ;ALMOST FULL? JZ FRKB90 ;TAKE NO CHANCES LOOP FRKB10 ;GET NEXT FILE CHAR FRKB90: MOV AX,SI ;DATA LENGTH POP DI POP SI POP DX RET ;DISPLAY STATUS OF CURRENT DOWNLOAD DLSTAT: TEST WORD PTR [BX+CBFLG],SFWINV ;WINDOW OPEN? JNZ DLST00 ;YES RET DLST00: PUSH AX PUSH CX PUSH SI CALL ILINEB ;INIT BUFFER MOV AX,216 ;LAST BLOCK SENT CALL MOVMSG ;MOVE TO BUFFER MOV AX,[BP-10] ;BLOCK NUMBER CALL BINASP ;ADD TO BUFFER TEST WORD PTR [BP-20],2 ;WINDOWED? JZ DLST10 ;NO MOV AX,217 ;LAST BLOCK ACKED CALL MOVMSG ;MOVE TO BUFFER MOV AX,[BP-12] ;BLOCK NUMBER CALL BINASP ;ADD TO BUFFER DLST10: CALL WSNOOP ;DISPLAY MESSAGE TEST WORD PTR [BP-20],0C0H ;KERMIT OR ASCII? JZ DLST15 ;NO - GIVE ERROR REPORT SUB WORD PTR [BX+CBCURSE],100H ;BACK UP IN WINDOW JMP SHORT DLST90 ;EXIT DLST15: CALL ILINEB ;INIT BUFFER MOV AX,232 ;NUMBER OF ERRORS CALL MOVMSG ;MOVE TO BUFFER MOV AX,[BP-24] ;ERROR COUNT CALL BINASP ;ADD TO BUFFER CMP WORD PTR [BP-26],0 ;ANY ERROR CODE? JZ DLST20 ;NO MOV AX,233 ;LAST ERROR CODE CALL MOVMSG ;MOVE TO BUFFER MOV AX,[BP-26] ;ERROR CODE ADD AX,367 ;MSG TABLE-1 CALL MOVMSG ;MOVE TO BUFFER DLST20: CALL WSNOOP ;DISPLAY MESSAGE SUB WORD PTR [BX+CBCURSE],200H ;BACK UP IN WINDOW DLST90: POP SI POP CX POP AX RET ;DISPLAY STATUS OF CURRENT UPLOAD ULSTAT: TEST WORD PTR [BX+CBFLG],SFWINV ;WINDOW OPEN? JNZ ULST00 ;YES RET ULST00: PUSH AX PUSH CX PUSH SI CALL ILINEB ;INIT BUFFER MOV AX,367 ;LAST BLOCK SENT CALL MOVMSG ;MOVE TO BUFFER MOV AX,[BP-10] ;BLOCK NUMBER DEC AX ;LAST RECEIVED CALL BINASP ;ADD TO BUFFER CALL WSNOOP ;DISPLAY MESSAGE TEST WORD PTR [BP-20],0C0H ;KERMIT OR ASCII? JZ ULST15 ;NO - GIVE ERROR REPORT SUB WORD PTR [BX+CBCURSE],100H ;BACK UP IN WINDOW JMP SHORT ULST90 ;EXIT ULST15: CALL ILINEB ;INIT BUFFER MOV AX,232 ;NUMBER OF ERRORS CALL MOVMSG ;MOVE TO BUFFER MOV AX,[BP-28] ;ERROR COUNT CALL BINASP ;ADD TO BUFFER CMP WORD PTR [BP-30],0 ;ANY ERROR CODE? JZ ULST20 ;NO MOV AX,233 ;LAST ERROR CODE CALL MOVMSG ;MOVE TO BUFFER MOV AX,[BP-30] ;ERROR CODE ADD AX,367 ;MSG TABLE-1 CALL MOVMSG ;MOVE TO BUFFER ULST20: CALL WSNOOP ;DISPLAY MESSAGE TEST WORD PTR DS:MSGCKPT+MSOPTS,SFLTR ;LINE TRACE ON? JNZ ULST90 ;YES - DON'T OVERLAY SUB WORD PTR [BX+CBCURSE],200H ;BACK UP IN WINDOW ULST90: POP SI POP CX POP AX RET ;UPLOAD A FILE ; BP-2 FILE NAME AS ENTERED ; BP-4 FILE HANDLE ; BP-6 FILE NAME STRING FOR DOS ; BP-8 PATH NAME STRING ; BP-10 BLOCK COUNT ; BP-12 WORK REG/FILE SIZE - LSW ; BP-14 RECEIVE BUFFER ; BP-16 TRANSMIT BUFFER ADDRESS (HANDSHAKING) ; BP-18 LOCAL FILE HANDLE ; BP-20 TRANSFER TYPE / FLAGS ; 00 = BASIC XMODEM ; 01 = USE CRC INSTEAD OF SUM FOR BLOCK CHECK ; 02 = USE WINDOWED PROTOCOL ; 04 = HONOR X-ON X-OFF FLOW CONTROL ; 08 = USE DLE TO HIDE CONTROL CHARS ; 10 = USE 1024 BYTE BUFFERS ; 20 = SEND FILE NAME PRIOR TO FILE ; 40 = KERMIT ; 80 = ASCII ; 2000 = 1ST CAN RECEIVED ; 4000 = 1ST EOT RECEIVED ; 8000 = NAK PENDING ; BP-22 FILE SIZE - MSW ; BP-24 FILE DIRECTORY BLOCK ; BP-26 FILE DIRECTORY ENTRY ; BP-28 ERROR COUNT ; BP-30 LAST ERROR CODE ;------------------------------------------------------------ UPLOAD: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME SUB SP,30 ;ALLOCATE LOCAL STORAGE XOR AX,AX ;ZERO MOV [BP-2],AX MOV [BP-4],AX MOV [BP-6],AX MOV [BP-8],AX MOV [BP-10],AX MOV [BP-12],AX MOV [BP-14],AX MOV [BP-16],AX MOV [BP-18],AX MOV [BP-20],AX MOV [BP-22],AX MOV [BP-24],AX MOV [BP-26],AX MOV [BP-28],AX MOV [BP-30],AX OR WORD PTR CBFLG[BX],SFDFC ;DISABLE FLOW CONTROL UPLO10: CALL DQTIOA ;FILENAME JNC UPLO20 ;EXISTS MOV AX,74 ;ENTER FILE NAME CALL QMSGNO JC UPLO2X ;LOST CARRIER JMP UPLO10 ;GO HANDLE UPLO20: MOV CX,WORD PTR [SI-2] ;COMMAND LENGTH MOV [BP-2],SI ;FILE NAME AS ENTERED JCXZ UPLO2X ;EXIT CALL VFNAME ;VALID FILE NAME? JNC UPLO23 ;YES CMP CX,50 ;TOO LONG FOR MSG? JBE UPLO21 ;NO PROBLEM MOV WORD PTR [SI-2],50 ;TRUNCATE UPLO21: CALL ILINEB ;FORMAT BUFFER MOV DI,[BP-2] ;FILE NAME CALL MOVSTR MOV AX,224 ;NOT VALID CALL MOVMSG CALL WRMSG UPLO2X: JMP UPLO90 ;EXIT UPLO23: CALL BLDFN ;BUILD STRING MOV AX,[BP-2] ;FILE NAME PUSH AX ;PASS AS PARAMETER CALL CKFDIR ;LOOK IN DIRECTORY JC UPLO30 ;NO FILE MOV [BP-24],DX ;DIRECTORY BLOCK MOV [BP-26],SI ;DIRECTORY ENTRY CALL TSYSOP ;SYSOP? JNZ UPLO24 ;YES TEST WORD PTR [SI+FDSTAT],2 ;SYSOP ONLY OWNER? JNZ UPLO25 ;YES - DENY ACCESS MOV DI,WORD PTR [BX+USRST] ;USER RECORD ADD DI,UENAM ;USER NAME FIELD ADD SI,FDOWNR ;OWNER NAME MOV CX,FDDESC-FDOWNR ;FIELD LENGTH PUSH ES PUSH DS POP ES REPZ CMPSB ;COMPARE FIELDS POP ES JZ UPLO24 ;CHECK FOR OVERWRITE JMP SHORT UPLO25 ;FILE EXISTS UPLO24: MOV AX,75 ;OVERWRITE? CALL QYESNO ;ASK FOR OK JC UPLO25 ;DEFAULT TO NO JZ UPLO30 ;OVERWRITE EXISTING FILE UPLO25: CALL ILINEB ;FORMAT BUFFER MOV AX,212 ;FILE CALL MOVMSG MOV DI,[BP-2] ;FILE NAME CALL MOVSTR MOV AX,219 ;ALREADY EXISTS CALL MOVMSG CALL WRMSG JMP UPLO90 ;EXIT UPLO30: CALL OPNUF ;OPEN NEW FILE JNC UPLO32 ;NO PROBLEM JMP UPLO21 ;NAME NOT VALID UPLO32: CALL CKFSPC ;GET FREE DISK SPACE PUSH DX ;RESULT CALL ILINEB ;FORMAT BUFFER MOV AX,220 ;UPLOAD DISK HAS CALL MOVMSG POP AX ;K BYTES CALL BINASP MOV AX,234 ;AVAILABLE CALL MOVMSG CALL WRMSG CMP WORD PTR [BX+USRIN],0 ;STACKED CMD? JNZ UPLO35 ;GO HANDLE MOV DI,WORD PTR [BX+USRST] ;USER RECORD MOV AL,BYTE PTR [DI+UEULPC] ;DEFAULT CMP AL,0 ;SET? JZ UPLO33 ;NO CALL TXPRT ;EXPERT? JZ UPLO33 ;NO - MUST PROMPT JMP SHORT UPLO36 ;USE IT UPLO33: CALL ILINEB ;INIT BUFFER MOV AX,76 ;UPLOAD TYPE CALL MOVMSG ;MOVE TO BUFFER MOV DI,WORD PTR [BX+USRST] ;USER RECORD MOV DL,BYTE PTR [DI+UEULPC] ;DEFAULT CMP DL,0 ;ANYTHING? JZ UPLO34 ;NO MOV AL,'[' CALL APPBYT ;MOVE TO BUFFER MOV AL,DL ;DEFAULT CALL APPBYT ;MOVE TO BUFFER MOV AL,']' CALL APPBYT ;MOVE TO BUFFER MOV AL,' ' CALL APPBYT ;MOVE TO BUFFER UPLO34: CALL QUERY ;ASK USER JC UPLO37 ;LOST CARRIER UPLO35: CALL DQCMD ;GET RESPONSE MOV AL,DL ;SET DEFAULT CALL LALIGN ;STRIP LEADING BLANKS MOV CX,WORD PTR [SI-2] ;LENGTH JCXZ UPLO36 ;USE DEFAULT CALL XLATE ;MAKE UC LODSB ;GET CMD CHAR MOV DI,WORD PTR [BX+USRST] ;USER RECORD CMP BYTE PTR [DI+UEULPC],0 ;ANY DEFAULT? JNZ UPLO36 ;YES MOV DI,OFFSET CTBL1 ;VALID DOWNLOAD DEFAULTS MOV CX,CTBL2-CTBL1 ;STRING LENGTH REPNZ SCASB ;CHECK FOR MATCH JNZ UPLO36 ;NOT VALID MOV DI,WORD PTR [BX+USRST] ;USER RECORD MOV BYTE PTR [DI+UEULPC],AL ;SET DEFAULT UPLO36: MOV DI,OFFSET CTBL3 ;COMMAND TABLE MOV CX,(JTBL3-CTBL3) ;TABLE SIZE REPNZ SCASB ;CHECK FOR MATCH JNZ UPLO33 ;NO - REPEAT PROMPT SUB DI,OFFSET CTBL3+1 ;OFFSET IN STRING SHL DI,1 ;TABLE WIDTH JMP JTBL3[DI] ;GO TO ROUTINE UPLO37: CALL CLSDF ;CLOSE EMPTY FILE CALL KILULF ;DELETE EMPTY FILE JMP UPLO90 ;EXIT UPLO38: MOV AX,9 ;HELP FILE NUMBER CALL SENDHF ;SEND HELP FILE JMP UPLO33 ;REPEAT PROMPT ;ASCII UPLOAD UPLO40: MOV AX,78 ;TERMINATE WITH ^K CALL WMSGNO MOV AX,79 ;READY TO RECEIVE CALL WMSGNO MOV WORD PTR [BP-20],80H ;MARK ASCII TRANSFER CALL GXBUF ;GET RECEIVE BUFFER UPLO42: CALL RABLK ;RECEIVE ONE BLOCK JC UPLO50 ;LOST CARRIER CALL WABUF ;WRITE BLOCK TO FILE JNC UPLO44 ;OK MOV AX,241 ;OUT OF SPACE CALL WMSGNO ;TELL USER JMP SHORT UPLO50 ;ABORT UPLOAD UPLO44: CMP AL,11 ;^K JZ UPLO48 ;END OF FILE INC WORD PTR [BP-10] ;COUNT BLOCK CALL ULSTAT ;DISPLAY STATS JMP UPLO42 ;GET NEXT BLOCK UPLO48: MOV AX,80 ;UPLOAD COMPLETE CALL WMSGNO JMP UPLO80 ;UPDATE DIRECTORY UPLO50: MOV AX,82 ;UPLOAD ABORT CALL WMSGNO JMP UPLO37 ;DELETE PARTIAL FILE ;XMODEM UPLOAD UPLO60: MOV BYTE PTR [BP-18],21 ;XMODEM HANDSHAKING CHAR MOV WORD PTR [BP-20],0 ;SET FLAGS FOR XMODEM JMP SHORT UPLO65 UPLO61: MOV BYTE PTR [BP-18],'C' ;CRC HANDSHAKING CHAR MOV WORD PTR [BP-20],1 ;SET FLAGS FOR CMODEM JMP SHORT UPLO65 UPLO62: MOV BYTE PTR [BP-18],'W' ;WINDOWED XMODEM MOV WORD PTR [BP-20],15 ;SET FLAGS FOR WXMODEM UPLO65: TEST WORD PTR [BX+CBMDM],MDMKBD JNZ UPLO70 ;LOCAL USER TEST WORD PTR [BX+DTESTAT],MPARE PUSHF ;SAVE TEST RESULTS JZ UPLO67 ;NO SWITCH TO 8 BIT NEEDED MOV AX,68 ;PLEASE SWITCH CALL WMSGNO UPLO67: MOV AX,77 ;READY TO RECEIVE CALL WMSGNO POPF ;REMEMBER PARITY STATUS JZ UPLO69 ;NO SWITCH TO 8 BIT CALL STM8B ;SET 8 BIT NO PARITY UPLO69: CALL RECXMU ;RECEIVE FILE JNC UPLO80 ;UPDATE DIRECTORY JMP UPLO50 ;DELETE PARTIAL FILE UPLO70: MOV AX,3D00H ;OPEN FOR INPUT CALL OPNLF ;OPEN LOCAL FILE JNC UPLO72 ;OPEN OK JMP UPLO50 ;DELETE PARTIAL FILE UPLO72: MOV [BP-18],AX ;LOCAL FILE HANDLE CALL GXBUF ;GET BUFFER UPLO74: CALL RLBUF ;READ BLOCK JZ UPLO78 ;END OF FILE ADD WORD PTR [BP-12],AX ;FILE SIZE JNC UPLO75 ;NO OVERFLOW INC WORD PTR [BP-22] ;MSW FILE SIZE UPLO75: CALL WABUF ;WRITE BLOCK JNC UPLO74 ;OK MOV AX,241 ;OUT OF SPACE CALL WMSGNO ;TELL CALLER JMP UPLO50 ;ABORT TRANSFER UPLO77: ERR 0BH ;LOCAL FILE ERROR UPLO78: CALL CLSLF ;CLOSE LOCAL FILE UPLO80: CALL CLSDF ;CLOSE FILE MOV SI,[BP-14] ;RECEIVE BUFFER CALL FREBUF ;NO LONGER NEEDED MOV AX,128 ;DIRECTORY RECORD SIZE CALL GETBUF ;GET BUFFER CALL BLANKF ;INIT TO BLANKS MOV WORD PTR [SI-2],128 ;SET TO MAX LENGTH MOV [BP-14],SI ;USE RECEIVE BUFFER SLOT MOV DI,SI ;DIRECTORY RECORD XOR AX,AX ;INIT TO ZEROS MOV WORD PTR [DI+FDVERS],AX ;VERSION = 0 MOV WORD PTR [DI+FDSTAT],AX ;STATUS = 0 MOV WORD PTR [DI+FDACNT],AX ;COUNT = 0 ;SEE IF USER HAS ACCESS TO PRIVATE SECTIONS MOV AX,DS:MSGCKPT+MDPSECT ;PUBLIC SECTIONS NOT AX ;PRIVATE SECTIONS PUSH DI MOV DI,[BX+USRST] ;USER RECORD AND AX,[DI+UESECT] ;VALID SECTIONS POP DI JZ UPLO83 ;NO PRIVATE SECTIONS MOV DX,DS:MSGCKPT+MDFSECT ;DEFAULT SECTION AND DX,DS:MSGCKPT+MDPSECT ;USE DEFAULT ONLY IF PUBLIC OR DX,AX ;VALID SECTIONS UPLO8A: MOV AX,60 ;SECTION # PROMPT CALL QMSGNO ;ASK USER JNC UPLO81 ;GOOD RESPONSE JMP UPLO87 ;LOST CARRIER UPLO81: CALL DQCMD ;GET RESPONSE CALL LALIGN ;STRIP LEADING BLANKS CMP BYTE PTR [SI],'?' ;HELP? JNZ UPLO82 ;NO CALL DSPSEC ;DISPLAY SECTIONS JMP UPLO8A ;ASK AGAIN UPLO82: MOV CX,WORD PTR [SI-2] ;LENGTH JCXZ UPLO83 ;USE DEFAULT CALL ASCBIN ;CONVERT TO BINARY MOV CX,AX ;SECTION NUMBER XOR AX,AX ;CLEAR MASK STC ;SHIFT FROM CARRY RCL AX,CL ;SHIFT TO FLAG POSITION AND AX,DX ;VALID? JNZ UPLO84 ;YES MOV AX,61 ;INVALID SECTION # CALL WMSGNO ;DISPLAY JMP UPLO8A ;ASK AGAIN UPLO83: MOV AX,DS:MSGCKPT+MDFSECT ;DEFAULT FILE SECTION UPLO84: MOV WORD PTR [DI+FDSECT],AX ;SECTION MOV AX,DS:MSGCKPT+MDFCLAS ;DEFAULT FILE CLASS MOV WORD PTR [DI+FDCLAS],AX ;CLASS MOV AX,DS:MSGCKPT+MDFSTAT ;DEFAULT FILE STATUS MOV WORD PTR [DI+FDSTAT],AX ;STATUS MOV AH,2AH ;GET DATE INT 21H ;DOS FUNCTION CALL MOV WORD PTR [DI+FDCDAT],CX ;CREATION DATE MOV WORD PTR [DI+FDADAT],CX ;ACCESS DATE MOV WORD PTR [DI+FDADAT+2],DX MOV WORD PTR [DI+FDCDAT+2],DX MOV AX,[BP-12] ;WORK REG MOV WORD PTR [DI+FDSIZE],AX ;FILE SIZE - LSW MOV AX,[BP-22] ;FILE SIZE - MSW MOV WORD PTR [DI+FDSIZE+2],AX ;FILE SIZE - MSW ADD DI,FDNAME ;FILE NAME MOV SI,[BP-2] ;FILE NAME STRING MOV CX,FDOWNR-FDNAME ;LENGTH OF FILE NAME CALL MOVPAD ;MOVE AND PAD MOV SI,WORD PTR [BX+USRST] ;USER RECORD MOV CX,UELNK-UENAM ;LENGTH OF NAME FIELD PUSH ES PUSH DS POP ES REP MOVSB ;OWNER POP ES CALL FIDESC ;GET FILE DESCRIPTION MOV CX,FDPATH-FDDESC ;LENGTH OF DESCRIPTION CALL MOVPAD ;MOVE AND PAD MOV SI,[BP-8] ;PATH NAME STRING MOV CX,128-FDPATH ;PATH LENGTH CALL MOVPAD ;MOVE AND PAD MOV SI,[BP-14] ;BUFFER ADDRESS MOV CX,FDIRH ;DIRECTORY FILE HANDLE MOV AX,[BP-24] ;DIRECTORY BLOCK OR AX,AX ;EXIST? JNZ UPLO85 ;REUSE EXISTING BLOCK CALL SKEOF ;SEEK TO END OF FILE MOV DS:MSGCKPT+MLASTD,AX ;UPDATE STATS UPLO85: CALL WFBLK ;WRITE BLOCK JNC UPLO87 ;NO ERROR ERR 13 UPLO87: MOV AX,FDIRH ;DIRECTORY HANDLE CALL FEOF ;TCLOSE FILE CALL ILINEB ;FORMAT BUFFER MOV DI,[BP-6] ;FILE NAME STRING CALL MOVSTR DEC WORD PTR [SI-2] ;TRUNCATE DELIMITER MOV AX,238 ;UPLOADED CALL MOVMSG CALL MFTYPE ;ANNOTATE TRANSFER TYPE CALL LOGDSK ;LOG TO DISK MOV DI,WORD PTR [BX+USRST] ;USER RECORD INC WORD PTR [DI+UEUPLD] ;UPLOAD COUNT UPLO90: MOV SI,[BP-2] ;FILE NAME CALL FREBUF ;FREE IT MOV SI,[BP-6] ;FILE NAME STRING CALL FREBUF ;FREE IT MOV SI,[BP-8] ;PATH NAME STRING CALL FREBUF ;FREE IT MOV SI,[BP-14] ;RECEIVE BUFFER CALL FREBUF ;FREE IT MOV SI,[BP-16] ;TRANSMIT BUFFER CALL FREBUF ;FREE IT MOV SI,[BP-26] ;DIRECTORY ENTRY CALL FREBUF ;FREE IT AND WORD PTR [BX+CBFLG],NOT SFDFC ;ENABLE FLOW CONTROL CALL CLSDF ;CLOSE FILE MOV SP,BP ;FREE LOCAL STORAGE POP BP ;RESTORE CALLERS FRAME JMP FILE10 ;FILE MENU FIDESC: CALL ILINEB ;FORMAT BUFFER PUSH DI MOV AX,236 ;ENTER 40 CHAR ... CALL MOVMSG MOV DI,[BP-2] ;FILE NAME CALL MOVSTR MOV AX,237 ;>? CALL MOVMSG CALL QUERY CALL DQCMD ;GET RESPONSE CALL LALIGN ;STRIP LEADING BLANKS CMP WORD PTR [SI-2],40 ;TOO LONG? JLE FIDESX ;NO PROBLEM MOV WORD PTR [SI-2],40 ;TRUNCATE FIDESX: POP DI RET ;----------------------------------------------------------- ;SEARCH FILE DIRECTORY ; ON ENTRY: [BP+4] -> FILE NAME ; RETURNS: SI -> DIRECTORY BLOCK ; DX = BLOCK NUMBER ; ELSE: CARRY = FILE NOT FOUND ; NOTE: THE CALLER IS RESPONSIBLE FOR ; FREEING THE DIRECTORY STRING CKFDIR: PUSH BP ;SAVE CALLER'S FRAME MOV BP,SP ;ESTABLISH LOCAL FRAME MOV CX,FDIRH ;FILE DIRECTORY HANDLE CALL SKEOF ;FIND END OF FILE MOV DX,AX ;BLOCK COUNT MOV AX,128 ;BLOCK SIZE CALL GETBUF ;GET BUFFER CKFD10: DEC DX ;PREVIOUS BLOCK JS CKFD80 ;END OF FILE MOV AX,DX ;BLOCK TO READ CALL RFBLK ;READ DIRECTORY ENTRY JNC CKFD20 ;GOOD READ ERR 13 ;ERROR IN FILE DIRECTORY CKFD20: MOV DI,[BP+4] ;FILE NAME PUSH SI ;BUFFER ADD SI,FDNAME ;FILE NAME IN BUFFER CALL CMPSTR ;MATCH? JNZ CKFD30 ;NO CMP WORD PTR [DI-2],12 ;MAX LENGTH NAME? JZ CKFD40 ;YES - MATCH IS VALID ADD SI,[DI-2] ;LENGTH OF NAME CMP BYTE PTR [SI],' ' ;END OF NAME? JZ CKFD40 ;YES CKFD30: POP SI ;BUFFER ADDRESS CALL YIELD ;YIELD SYSTEM JMP CKFD10 ;TRY NEXT ENTRY CKFD40: POP SI ;BUFFER ADDRESS CLC ;SHOW FILE FOUND JMP SHORT CKFD90 ;EXIT CKFD80: CALL FREBUF ;FREE DIRECTORY STRING STC ;SHOW NOT FOUND CKFD90: MOV SP,BP ;RELEASE LOCAL FRAME POP BP ;RESTORE CALLER'S FRAME RET 2 ;VALIDATE FILE NAME VFNAME: PUSH AX PUSH CX PUSH DI CALL XLATE ;UPPER CASE CMP CX,12 ;MAX VALID NAME JA VFNA80 ;YES - INVALID MOV DI,SI MOV AL,'.' ;FILE DELIMITER PUSH ES PUSH DS POP ES REPNZ SCASB ;SEARCH FOR PERIOD POP ES JNZ VFNA10 ;NOT TYPE SPECIFIED CMP CX,3 ;MAX FILE TYPE LENGTH JA VFNA80 ;INVALID INC CX ;COUNT PERIOD VFNA10: MOV AX,[SI-2] ;TOTAL LENGTH SUB AX,CX ;FILE NAME LENGTH CMP AX,8 ;MAXIMUM LENGTH JBE VFNA90 ;OK VFNA80: STC ;SHOW NOT VALID JMP SHORT VFNA92 ;EXIT VFNA90: CLC ;SHOW GOOD ROUTINE VFNA92: POP DI POP CX POP AX RET MOVPAD: PUSH AX PUSH CX PUSH SI MOV AX,CX ;FIELD SIZE MOV CX,[SI-2] ;LENGTH SUB AX,CX ;LENGTH TO BLANK PUSH ES PUSH DS POP ES REP MOVSB ;MOVE TO DIRECTORY POP ES MOV CX,AX ;LENGTH TO BLANK JCXZ MOVPAX ;NOTHING TO PAD MOV AL,' ' ;BLANK PUSH ES PUSH DS POP ES REP STOSB ;BLANK FIELD POP ES MOVPAX: POP SI POP CX POP AX RET RABLK: MOV SI,[BP-14] ;BUFFER ADDRESS MOV WORD PTR [SI-2],0 ;CLEAR LENGTH MOV DI,SI ;CURRENT POSITION RABL10: CALL CONR ;READ ONE CHAR JNC RABL20 ;READ OK RET RABL20: CMP AL,11 ;END OF FILE? JZ RABL30 ;YES MOV [DI],AL ;PUT IN BUFFER INC DI INC WORD PTR [SI-2] ;COUNT CHAR CMP WORD PTR [SI-2],128 ;BLOCK FULL? JB RABL10 ;NO RABL30: PUSH AX MOV AX,WORD PTR [SI-2] ;BLOCK LENGTH ADD [BP-12],AX ;FILE SIZE JNC RABL40 ;NO OVERFLOW INC WORD PTR [BP-22] ;MSW FILE LENGTH RABL40: POP AX CLC ;SHOW GOOD RETURN RET WABUF: PUSH AX PUSH CX PUSH DX PUSH DI MOV DI,[BP-14] ;RECEIVE BUFFER MOV CX,WORD PTR [DI-2] ;DATA LENGTH MOV DX,DI ;DATA ADDRESS WABUF1: MOV AH,40H ;WRITE TO FILE PUSH BX MOV BX,[BP-4] ;FILE HANDLE INT 21H ;DOS REQUEST POP BX JC WABUX ;HARD ERROR CMP AX,CX ;WRITE ALL BYTES? WABUX: POP DI POP DX POP CX POP AX RET WXBUF: PUSH AX PUSH CX PUSH DX PUSH DI MOV CX,128 ;DATA LENGTH MOV DX,[BP-14] ;DATA ADDRESS ADD DX,3 ;SKIP HEADER JMP WABUF1 ;ENTER COMMON LOGIC ;RECEIVE A FILE USING XMODEM PROTOCOL RECXMU: CALL CLRIBF ;PURGE INPUT BUFFER CALL WTBUFE ;WAIT FOR OUTPUT MOV WORD PTR [BP-10],1 ;SET BLOCK COUNT CALL GXBUF ;GET RECEIVE BUFFER AND WORD PTR [BX+CBFLG],NOT SFSNP ;DISABLE SNOOP MOV WORD PTR [BX+CBRTV],182 ;10 SEC TIMEOUT MOV CX,10 ;LOOP COUNT JMP SHORT RECX11 ;NUDGE SENDER RECX05: MOV BYTE PTR [BP-18],'C' ;CRC CHECKING MOV WORD PTR [BP-20],1 ;TRANSFER TYPE MOV CX,4 ;LOOP COUNT JMP SHORT RECX11 ;NUDGE SENDER RECX10: MOV BYTE PTR [BP-18],21 ;NAK MOV WORD PTR [BP-20],0 ;TRANSFER TYPE MOV CX,4 ;LOOP COUNT RECX11: MOV AL,BYTE PTR [BP-18] ;HANDSHAKING CHAR CALL CONW ;READY TO RECEIVE RECX12: CALL ULSTAT ;DISPLAY UPLOAD STATS RECX2A: CALL CONR ;WAIT FOR INPUT JNC RECX14 ;RECEIVED CHAR TEST BYTE PTR [BX+CBFLG],SFLC ;LOST CARRIER? JNZ RECX13 ;YES CMP WORD PTR [BP-10],1 ;EXPECTING FIRST BLOCK? JZ RECX2B ;YES MOV WORD PTR [BP-30],2 ;TIME OUT JMP RECX70 ;SEND NAK RECX2B: LOOP RECX11 ;TRY AGAIN CMP BYTE PTR [BP-20],15 ;WAS IT WXMODEM? JZ RECX05 ;YES - TRY CXMODEM CMP BYTE PTR [BP-20],1 ;WAS IT CXMODEM? JZ RECX10 ;YES - TRY PLAIN XMODEM RECX13: JMP RECX80 ;ABORT RECX14: CMP AL,1 ;START OF HEADER? JZ RECX20 ;YES - GO FILL BUFFER CMP AL,4 ;EOT JZ RECX30 ;END OF FILE CMP AL,24 ;CANCEL JZ RECX40 ;ABANDON FILE CMP AL,22 ;SYN? JZ RECX2A ;DISCARD SYN JMP RECX2A ;READ ANOTHER CHAR RECX20: MOV WORD PTR [BX+CBRTV],91 ;5 SEC TIMEOUT MOV SI,[BP-14] ;BUFFER ADDRESS MOV DI,SI ;CURRENT POSITION MOV WORD PTR [SI-2],0 ;CLEAR COUNT XOR DX,DX ;NO PREVIOUS CHAR RECX21: TEST WORD PTR [BP-20],8 ;DLE CHECKING? JZ RECX23 ;NO CMP DL,16 ;PREVIOUS CHAR = DLE? MOV DL,AL ;SAVE CURRENT AS PREVIOUS JNZ RECX22 ;NO XOR AL,64 ;ADJUST CHARACTER JMP SHORT RECX23 ;STORE CHAR RECX22: CMP AL,16 ;DLE? JZ RECX24 ;DISCARD DLE RECX23: MOV [DI],AL ;PUT CHAR IN BUFFER INC DI INC WORD PTR [SI-2] ;COUNT INPUT CMP WORD PTR [SI-2],132 ;BUFFER FULL? JL RECX24 ;KEEP IT MOVING JG RECX50 ;GO ANALYZE BLOCK TEST WORD PTR [BP-20],1 ;USE CRC CHECKING? JZ RECX50 ;NO - BLOCK IS FULL RECX24: CALL CONR ;READ NEXT CHAR JNC RECX21 ;ADD TO BUFFER TEST BYTE PTR [BX+CBFLG],SFTO ;TIME-OUT? JZ RECX40 ;NO - CANCEL UPLOAD JMP RECX50 ;ANALYZE BLOCK RECX30: TEST WORD PTR [BP-20],4000H ;1ST EOT? JNZ RECX32 ;NO - MUST BE VALID OR WORD PTR [BP-20],4000H ;1ST ACK RECEIVED MOV AL,21 ;NAK JMP RECX74 ;NAK EOT RECX32: TEST WORD PTR [BP-20],8000H ;NAK PENDING? JNZ RECX40 ;CAN'T BE VALID MOV AL,6 ;ACK CALL CONW ;SEND JMP RECX90 ;EXIT RECX40: TEST WORD PTR [BP-20],2000H ;1ST CAN? JNZ RECX42 ;NO - MUST BE VALID OR WORD PTR [BP-20],2000H ;1ST CAN RECEIVED MOV AL,21 ;NAK JMP RECX74 ;NAK CAN RECX42: MOV AL,24 ;CANCEL CALL CONW MOV AL,24 CALL CONW JMP RECX80 ;ABORT RECX50: MOV AX,132 ;BLOCK LENGTH WITH CHECKSUM TEST WORD PTR [BP-20],1 ;CRC CHECKING? JZ RECX51 ;NO INC AX ;INCREMENT LENGTH RECX51: CMP WORD PTR [SI-2],AX ;CORRECT BLOCK LENGTH? JZ RECX52 ;YES MOV WORD PTR [BP-30],4 ;SHORT BLOCK JMP RECX70 ;NAK BLOCK RECX52: MOV AL,BYTE PTR [SI+1] ;BLOCK COUNT XOR AL,255 ;COMPLEMENT BLOCK NUMBER CMP BYTE PTR [SI+2],AL ;MATCH RECEIVED? JZ RECX54 ;YES MOV WORD PTR [BP-30],5 ;BAD BLOCK NUMBER JMP RECX70 ;NAK BLOCK RECX54: MOV AX,[BP-10] ;EXPECTED BLOCK CMP BYTE PTR [SI+1],AL ;MATCH RECEIVED? JAE RECX56 ;EQUAL OR ABOVE JMP RECX72 ;ACK PREVIOUSLY RECEIVED BLOCK RECX56: JZ RECX58 ;GOOD BLOCK NUMBER TEST WORD PTR [BP-20],2 ;WINDOWED PROTOCOL? JZ RECX57 ;NO - NAK BLOCK TEST WORD PTR [BP-20],8000H ;NAK PENDING? JZ RECX57 ;NO - NAK BLOCK JMP RECX12 ;IGNORE BLOCK RECX57: MOV WORD PTR [BP-30],6 ;WRONG BLOCK NUMBER JMP RECX70 ;NAK FOR BAD BLOCK NUMBER RECX58: ADD SI,3 ;SKIP HEADER MOV CX,128 ;DATA LENGTH TEST WORD PTR [BP-20],1 ;USE CRC? JNZ RECX60 ;YES CALL CLCSUM ;CALCULATE CHECK SUM CMP BYTE PTR [SI+128],AL ;CHECK SUM MATCH? JMP SHORT RECX61 ;ANALYZE RESULT RECX60: CALL CRCXXX ;CALCULATE CRC XCHG AH,AL ;XMODEM CONVENTION CMP WORD PTR [SI+128],AX ;CHECK SUM MATCH? RECX61: JZ RECX62 ;MATCH OK MOV WORD PTR [BP-30],7 ;BAD CHECKSUM JMP RECX70 ;NAK FOR BAD CHECKSUM RECX62: CALL WXBUF ;WRITE BLOCK TO DISK JNC RECX64 ;OK JMP RECX40 ;ABORT RECX64: INC WORD PTR [BP-10] ;NEXT BLOCK NUMBER ADD WORD PTR [BP-12],128 ;ACCUMULATE FILE SIZE JNC RECX66 ;NO OVERFLOW INC WORD PTR [BP-22] ;MSW FILE SIZE RECX66: JMP RECX72 ;ACK GOOD BLOCK ;NAK CURRENT BLOCK RECX70: MOV AL,21 ;NAK OR WORD PTR [BP-20],8000H ;SHOW NAK PENDING INC WORD PTR [BP-28] ;COUNT ERROR JMP SHORT RECX74 ;SEND IT ;ACK CURRENT BLOCK RECX72: MOV AL,6 ;ACK AND WORD PTR [BP-20],1FFFH ;CLEAR NAK CAN & EOT FLAGS RECX74: CALL CONW ;SEND ACK OR NAK TEST WORD PTR [BP-20],2 ;WINDOWED PROTOCOL? JZ RECX79 ;NO MOV AX,[BP-10] ;BLOCK NUMBER TEST WORD PTR [BP-20],8000H ;NAK? JNZ RECX78 ;YES DEC AX ;LAST GOOD BLOCK RECX78: AND AX,3 ;ISOLATE LOW BITS CALL CONW ;SEND WINDOWED BLOCK # MOV WORD PTR [BX+CBRTV],1086 ;60 SECOND TIMEOUT RECX79: JMP RECX12 ;WAIT FOR NEXT BLOCK RECX80: TEST WORD PTR [BP-20],4000H ;EOT RECEIVED? JNZ RECX90 ;YES - CONSIDER GOOD STC ;SHOW ABORT JMP SHORT RECX92 ;EXIT RECX90: CLC ;SHOW GOOD RETURN RECX92: PUSHF OR WORD PTR [BX+CBFLG],SFSNP ;ENABLE SNOOP MOV AX,TIMEOUT ;SYSTEM TIMEOUT VALUE MOV WORD PTR [BX+CBRTV],AX ;RESTORE NORMAL TIMEOUT POPF RET FILESYS ENDP CSEG ENDS END