; * * * * * * * * * * * * * * * version 2.9 * * * * * * * * * * * * * * * ; [34c] Add sorted wildcard SENDs with starting filename ; * * * * * * * * * * * * * * * version 2.8 * * * * * * * * * * * * * * * ; [32c] Allow replacement of output filename with trailer from RECEIVE. ; * * * * * * * * * * * * * * * version 2.7 * * * * * * * * * * * * * * * ; [31] Fix display of file renaming. ; RonB, 05/05/84 ; [30c] Isolate ANSI escape sequences for machine independence. ; [29g] Add 8th bit quoting ; RonB, 04/15/84 ; * * * * * * * * * * * * * * * version 2.6 * * * * * * * * * * * * * * * ; [28d] Improve input filename processing, allow valid special chars ; RonB, 03/27/84 ; [23] Modification to GTCEOF to fix ASCII mode transfer ; * * * * * * * * * * * * * * * version 2.4 * * * * * * * * * * * * * * * ; [Rg] ^X/^Z file interruption. Slight mod to GTNFIL. Rg, 2/84 ; * * * * * * * * * * * * * * * version 2.1 * * * * * * * * * * * * * * * ; [par] Added calls to set parity, strip parity on input if ; other than none parity is called for. ; JD, 2/84 ; [16] Add file-mode ASCII or BINARY processing. ; RonB,01/02/84 ; [11] Capitalize and parse filename being received. ; RonB,12/27/83 ; [9] Fix filename parsing, and add wildcard ability. ; RonB,12/26/83 ; * * * * * * * * * * * * * * * version 2.0 * * * * * * * * * * * * * * * CSEG $ ; Get the file name (including host to micro translation) gofil: cld push ds pop es mov si, offset data mov di, offset fcb mov al,0 stosb mov cx,11 mov al,' ' rep stosb mov cx,24 mov al,0 rep stosb mov di, offset fcb+1 mov ah,0 gofil1: lodsb ;Get a filename character cmp al,'.' je gofil2 cmp al,0 je gofil4 cmp ah,8 jae gofil1 call gofl20 ;Capitalize, and replace strange chars ;[11] stosb inc ah jmps gofil1 gofil2: mov di, offset fcb+9 mov ah,0 gofil3: lodsb ;Get a file type character cmp al,'.' je gofil4 cmp al,0 je gofil4 cmp ah,3 jae gofil4 call gofl20 ;Capitalize, and replace strange chars ;[11] stosb inc ah jmps gofil3 gofil4: cmp byte ptr fcb+1,' ' ;Any chars in first field? ;[32c] begin jne gofil5 ; if not, set filename to '&' mov byte ptr fcb+1,'&' gofil5: mov si, offset fcb2+11 ;Replace with RECEIVE trailer mov di, offset fcb+11 mov temp2, di mov ah,' ' gofl5b: mov al,[si] ;Get character from replacement filename cmp al,'?' je gofl5c mov [di],al ;If not wild, simply replace existing letter cmp al,' ' je gofl5c mov ah,'-' ; and replace subsequent spaces with '-' gofl5c: cmp byte ptr [di],' ' jne gofl5d ;Replace spaces in filename with filler char mov [di],ah ; either a space or a '-'. cmp ah,' ' jne gofl5d mov temp2,di ;Mark location where last space occurred gofl5d: dec di dec si cmp si,offset fcb2+8 jne gofl5e mov ah,' ' gofl5e: cmp si,offset fcb2 jae gofl5b sub temp2,di dec temp2 cmp temp2,8 jbe gofl5f mov temp2,8 gofl5f: call clrfln mov dx, offset fcb ;Print the file name. call tfile ;[32c] end cmp flwflg, 0 ;Is file warning on? jnz gofl5x jmp gofil9 ;If not, just proceed. gofl5x: mov dx, offset fcb call openf ;See if the file exists. cmp al, 0FFH ;Does it exist? jnz gofil7 jmp gofil9 ;If not create it. gofil7: mov dx, offset scrfr ;Move cursor. call poscur ;[30c] mov dx, offset infms5 ;Inform the user we are renaming the file. call tmsg mov cx, temp2 ;Get the length of the file name. ;[32c] begin mov al, 0 ;Says if first field is full. gofil8: cmp cl, 8 ;Is the first field full? jne gofl81 mov al, 0FFH ;Set a flag saying so. gofl81: mov bx, offset fcb ;Get the FCB. add bx, cx ;Add in the character number. mov ah, '&' mov [bx], ah ;Replace the char with an ampersand. push ax push bx push cx mov dx, offset fcb ;See if the file exists. call openf pop cx pop bx cmp al, 0FFH ;Does it exist? pop ax jz gofl89 ;If not create it. cmp al, 0 ;Get the flag. jz gofl83 dec cl ;Decrement the number of chars. cmp cl, 0 jz gofl88 ;If no more, die. jmp gofl81 gofl83: inc cl ;Increment the number of chars. jmp gofil8 ;[32c] end gofl88: mov dx, offset screrr call poscur ;[30c] mov dx, offset ermes4 ;Tell the user that we can't rename it. call tmsg ret gofl89: push dx mov dx, offset fcb ;Print the file name. ;[31] call tfile ;[31] pop dx gofil9: mov dx, offset fcb ;Delete the file if it exists. call delete mov dx, offset fcb ;Now create it. call create cmp al, 0FFH ;Is the disk full? je gofl9x jmp rskp gofl9x: mov dx, offset screrr ;Position cursor. call poscur ;[30c] mov dx, offset erms11 call tmsg ret ; Make sure character in al is a legal filename character: ;[11] begin ; Mask 8th bit, capitalize, and replace all illegal ; special characters with '#' gofl20: and al, 7Fh ;mask eighth bit ;[28d] cmp al, '0' ;Check for digit jb gofl21 cmp al, '9' jbe gofl23 cmp al, 'A' ;Check for uppercase letter jb gofl21 cmp al, 'Z' jbe gofl23 cmp al, 'a' ;Check for lowercase letter jb gofl21 cmp al, 'z' ja gofl21 and al, 5Fh ;Capitalize lowercase jmps gofl23 gofl21: push di mov di, offset spchar ;Special chars. mov cx, 20 ;Twenty of them. repne scasb ;Search string for input char. je gofl22 mov al, '#' ;Replace illegal characters with '#' gofl22: pop di ;[28d] end gofl23: ret ;[11] end ; Get next filename from sorted directory list. Return skip on success, ; plain return at end. getfil: cmp cxzflg, 'Z' ;[Rg] file interrupt flag set to 'Z'? ;[34c] je gtfl9 mov si,dindex ;Any more entries in list? cmp si,dircnt jae gtfl9 cld gtfl4: push ds pop es mov ds,word ptr membuf mov cl,4 shl si,cl inc si push si mov di,offset fcb2+1 mov cl,11 repe cmpsb pop si jae gtfl6 ;If above starting filename, use it push es pop ds inc dindex mov si,dindex cmp si,dircnt jb gtfl4 mov dx,offset erms28 ;No filenames below starting filename call tcrmsg jmps gtfl9 gtfl6: mov di,offset fcb+1 mov cx,11 rep movsb ;Move the name to the FCB push es pop ds inc dindex ;Point to next entry call getopn jmp rskp gtfl9: mov wldflg, 0 ;Reset wild card flag. ret ;[34c] end ; open the file for sending getopn: mov filflg, 0FFH ;Nothing in the DMA. mov eoflag, 0 ;Not the end of file. mov dx, offset fcb call openf ;Open the file. ret ; Output the chars in a packet. ptchr: mov temp1, ax ;Save the size. mov bx, offset data ;Beginning of received packet data. mov outpnt, bx ;Remember where we are. mov ch, rquote ;Quote char. ptchr1: dec temp1 ;Decrement # of chars in packet. jnl pt1 jmp rskp ;Return successfully if done. pt1: dec chrcnt ;Decrement number of chars in dta. jns ptchr2 ;Continue if space left. call outbuf ;Output it if full. jmp r ; Error return if disk is full. ptchr2: mov bx, outpnt ;Get position in packet data buffer. mov ah, [bx] ;Grab a char inc bx mov outpnt, bx ;and bump pointer. mov al, 00h ;First assume no 8th bit ;[29g] begin cmp ebquot, 'N' ;No 8th bit if we can't quote je ptch21 cmp ebquot, 'Y' ; or if we can but aren't. je ptch21 cmp ah, ebquot ;Is this the 8th bit quote character? jne ptch21 mov ah, [bx] ;Get the quoted character inc bx mov outpnt, bx dec temp1 ;Decrement # of chars in packet. mov al, 80h ;Set the 8th bit. ;[29g] end ptch21: cmp ah, ch ;Is it the quote char? jne ptchr4 ;If not proceed. mov ah, [bx] ;Get the quoted character inc bx mov outpnt, bx ;and bump pointer. dec temp1 ;Decrement # of chars in packet. mov dl, ah ;Save the parity bit in dl. ;[29g] begin and dl, 80H and ah, 7FH ;Turn off the parity bit. cmp ah, ch ;Is it the quote char? je ptchr3 ;If so just go write it out. cmp ebquot, 'N' ;No 8th bit if we can't quote je ptch22 cmp ebquot, 'Y' ; or if we can but aren't. je ptch22 cmp ah, ebquot ;Is this the 8th bit quote character? je ptchr3 ;If so, just go write it out. ptch22: add ah, 40H ;Make it a control char again. ;[29g] end and ah, 7FH ;Modulo 128. ptchr3: or ah, dl ;Or in the parity bit. ptchr4: or ah, al ;Or in the quoted 8th bit. ;[29g] mov bx, bufpnt ;Destination buffer. mov [bx], ah ;Store it. inc bx mov bufpnt, bx ;Update the pointer jmp ptchr1 ;and loop to next char. ; output the buffer, reset bufpnt and chrcnt outbuf: push bx push cx mov dx, offset fcb call soutr ;Write the record. pop cx pop bx cmp al, 0 ;Successful. jz outbf1 cmp al, 1 jz outbf0 mov dx, offset screrr call poscur ;[30c] mov dx, offset erms17 ;Record length exceeds DTA. call tmsg ret outbf0: mov dx, offset screrr call poscur ;[30c] mov dx, offset erms11 ;Disk full error. call tmsg ret outbf1: mov bx, offset dma ;Addr for beginning. mov bufpnt, bx ;Store addr for beginning. mov ax, bufsiz-1 ;Buffer size. mov chrcnt, ax ;Number of chars left. jmp rskp ; Get the chars from the file. gtchr: mov ch, squote ;Keep quote char in c. cmp filflg, 0 ;Is there anything in the DMA? jz gtchr0 ;Yup, proceed. mov cl, 0 ;No chars yet. call inbuf jmp gtceof ;No more chars, go return EOF. gtchr0: mov al, spsiz ;Get the maximum packet size. sub al, 5 ;Subtract the overhead. mov ah, 0 mov temp1, ax ;Number of chars we're to get. mov bx, offset filbuf ;Where to put the data. mov cbfptr, bx ;Remember where we are. mov cl, 0 ;No chars. gtchr1: dec temp1 ;Decrement the number of chars left. jns gtchr2 ;Go on if there is more than one left. mov al, cl ;Return the count in A. mov ah, 0 jmp rskp gtchr2: mov ax, chrcnt dec ax jl gtchr3 mov chrcnt, ax jmp gtchr4 gtchr3: call inbuf ;Get another buffer full. jmp gtceof cmp chrcnt, 0 jne gtchr4 sub cl, 2 ;Don't count controllified Z. mov al, cl mov ah, 0 jmp rskp gtchr4: mov bx, bufpnt ;Position in DMA. mov ah, [bx] ;Get a char from the file. inc bx mov bufpnt, bx cmp ebquot, 'N' ;Can we not do 8th bit quoting? ;[29g] begin je gtch41 cmp ebquot, 'Y' ;Or are we not? je gtch41 mov dh, ah and ah, 7Fh and dh, 80h ;Is the 8th bit set? je gtch41 ;If not, no need for quoting dec temp1 ;Decrement the number of characters left mov dh, ebquot ;Insert 8th bit quote char. in packet buffer mov bx, cbfptr mov [bx], dh inc cbfptr inc cl ;Count the character gtch41: mov dl, ah ;Save the char. ;[29g] end and dl, 80H ;Turn off all but parity. and ah, 7FH ;Turn off the parity. cmp ah, ' ' ;Compare to a space. jl gtchr5 ;If less then its a control char, handle it. cmp ah, del ;Is the char a delete? jz gtchr5 ;Go quote it. cmp ah, ch ;Is it the quote char? je gtch42 ;If so, insert it in the buffer ;[29g] begin cmp ebquot, 'N' ;Can we not do 8th bit quoting? je gtchr8 cmp ebquot, 'Y' ;Or are we not? je gtchr8 cmp ah, ebquot ;Is this the 8th bit quote character? jne gtchr8 ;If not, proceed gtch42: dec temp1 ;Decrement the chars remaining. ;[29g] end mov bx, cbfptr ;Position in character buffer. mov [bx], ch ;Precede char with send quote. inc cbfptr inc cl ;Increment the char count. jmp gtchr8 gtchr5: or ah, dl ;Turn on the parity bit. cmp ah, ('Z'-100O) ;Is it a ^Z? jne gtchr7 ;If not just proceed. cmp binflg, 0 ;ASCII file? ;[16] begin je gtceof ;If so, terminate cmp eoflag, 0 ;EOF flag set? ;[16] end jz gtchr6 ;If not just go on. mov bx, bufpnt mov ax, chrcnt mov dh, al ;Get number of chars left in DMA. gtch51: dec dh jns gtch52 ;Any chars left? mov chrcnt, 0 ;If not, say so. mov al, cl ;Return the count in A. mov ah, 0 jmp rskp gtch52: mov ah, [bx] ;Get the next char. inc bx ;Move the pointer. cmp ah, ('Z'-100O) ;Is it a ^Z? jz gtch51 ;If so see if they rest are. gtchr6: mov ah, ('Z'-100O) ;Restore the ^Z. gtchr7: xchg ah, al mov ah, 0 mov temp2, ax ;Save the char. dec temp1 ;Decrement char counter. mov bx, cbfptr ;Position in character buffer. mov [bx], ch ;Put the quote in the buffer. inc cbfptr inc cl ;Increment the char count. mov ax, temp2 ;Get the control char back. xchg al, ah add ah, 40H ;Make the non-control. and ah, 7FH ;Modulo 200 octal. gtchr8: or dl, dl ;Do we have parity? ;[29g] jz gtch81 ;If not, just send it. ;[29g] or ah, dl ;Or in the parity bit. cmp parflg,parnon ;[par] no parity? je gtch81 ;[par] yes, keep going and ah,7fh ;[par] else turn off parity from file ;[par]*** should probably mention that we're losing eighth bit here push ax ;[29g] begin push cx mov dx, offset scrhi ;mention that high bit is being lost call poscur ;[30c] mov dx, offset hibit call tmsg pop cx pop ax ;[29g] end gtch81: mov bx, cbfptr ;Position in character buffer. mov [bx], ah ;Put the char in the buffer. inc cbfptr inc cl ;Increment the char count. jmp gtchr1 ;Go around again. gtceof: cmp cl, 0 ;Had we gotten any data? je gteof0 ;Nope. mov filflg,0FFh ;[23] fix ASCII extra buffers at eof mov eoflag,0FFh ;[23] mov al, cl mov ah, 0 jmp rskp gteof0: mov ah, 0FFH ;Get a minus one. ret ;Input the next DMA buffer. inbuf: mov ah, eoflag ;Have we reached the end? cmp ah, 0 jz inbuf0 ret ;Return if set. inbuf0: push bx push cx mov bx, offset dma ;Set the r/w buffer pointer. mov bufpnt, bx mov dx, offset fcb call sinr cmp al, 0 ;End of file? je inbuf1 ;Still have data left. mov eoflag, 0FFH ;Set End-of-file. mov filflg, 0 ;Buffer not empty. mov chrcnt, 0 ;Say no characters. pop cx pop bx ret inbuf1: mov al, 80H ;Use as counter for number of chars read. pop cx pop bx cmp filflg, 0 ;Ever used DMS? jnz inbf21 ;Nope, then don't change count. dec al ;Fix boundary error. inbf21: mov ah, 0 ;Zero the flag (buffer not empty). mov chrcnt, ax ;Number of chars read from file. mov filflg, 0 ;Buffer not empty. jmp rskp DSEG $ temp1 dw 0 temp2 dw 0 dma rb 80H filbuf rb 60H ;Character buffer. cpfcb rb 25H ;Save FCB in case of "*". rdbuf rb 80H cnt dw 0 fcb rb 36 fcb2 rb 12 ;replacement receive filename ;[32c] chrcnt dw 0 ;Number of chars in the file buffer. filcnt dw 0 ;Number of chars left to fill. outpnt dw 0 ;Position in packet. bufpnt dw 0 ;Position in file buffer. fcbptr dw 0 ;Position in FCB. datptr dw 0 ;Position in packet data buffer. cbfptr dw 0 ;Position in character buffer. siz dw 0 ;Size of data from gtchr. filflg db 0 ;Non-zero when nothing in DMA buffer. filsiz rw 02H ;Double word for filesize (in bytes.) eoflag db 0 ;EOF flag;non-zero on EOF. binflg db 0 ;ASCII/Binary flag - 0 if ASCII file ;[16] wldflg db 0 ;Assume no "*" in fn.