home *** CD-ROM | disk | FTP | other *** search
- name UUENCODE
- page 55,132
- title 'UUENCODE.ASM'
- ;
- ; UUENCODE.ASM -- UUEncodes a Binary File
- ;
- ; Cmd line processing, general layout from UU.ASM by Theodore A. Kaldis
- ;
- ;Author: David Kirschbaum
- ; Toad Hall
- ; kirsch@usasoc.soc.mil
- ;Released to Public Domain
- ;
- ; To assemble and link this program into the executable UUENCODE.COM:
- ; (It will NOT run compiled as an .EXE program!)
-
- ; MASM UUE;
- ; LINK UUE;
- ; (If you just have EXE2BIN:
- ; EXE2BIN UUE
- ; REN UUE.BIN UUENCODE.COM (or whatever)
- ; (If you have Public Domain EXE2COM or equivalent:
- ; EXE2COM UUE
- ; REN UUE.COM UUENCODE.COM (or whatever)
- ; (Delete the bogus .OBJ file.)
-
- Comment ~
- v2.0, 10 Mar 91
-
- - Keith Petersen says we have to make other "weird" modes work
- in the "begin" line (like "begin 0600 foobar.arc").
- Seems to be working in the uudecode. No changes required here
- in the uuencode side.
- - He also asked for the "no overwrite" protection. Installed from
- the xxencode code (but only if NOT STDOUT).
-
- - Never did incorporate some tweaks from Germany because they were
- too confused with table-related additions (which was broken in
- the uudecode side of the house). Incorporating them now with the
- v1.9b comments.
-
- - Keith also found we were doing our "no cmdline entry" handling
- backwards: prompting for a filename, and then showing usage only
- if no filename entry. Reversing that so we show usage, and THEN
- prompt for the filename. All error msgs are going to STDERR
- (unless it's a "-?" switch, where I'm sending it out via Svc 9,
- to permit redirection).
-
- - Tightened up error messages a bit (to include Svc 9 Int 21H display
- for <DOS 2.2 error msg!), common routines, etc.
-
- - Added "-?" for just help, moved usage and <DOS 2.x msgs to buffer space
- at program end.
-
- v1.9b, 01 Nov 1989 (TapirSoft Gisbert W.Selke)
- - tweaked for speed, or rather, style. No noticeable increase in
- overall speed...
- - fixed a bug with file names starting with a slash (and no other slashes
- in the name) or consisting of one character only (without extension).
-
- v1.9, 29 Jul 89
- - Had a strange bug in UUD19.
- In the process of fixing that, took a relook at this code
- and did a little tweaking.
- Toad Hall
-
- v1.8, 5 Jul 89
-
- - Version number bumped to v1.8 (skipping v1.4 thru v1.7)
- just to get in synch with the companion uudecode program.
-
- - Thanks to Karl-L. Noell <NOELL%DWIFH1.BITNET@CUNYVM.CUNY.EDU>
- for two bug reports:
- 1 - Target filename prompt bug:
-
- | When I call up UUE12 or UUD17 without filename, a prompt appears:
- | Input path/file:
- | but answering to that prompt always yields the message
- | "Input file error."
-
- Dumb error, fixed.
-
- 2 - Excessive uuencoded line length at the 45000-byte input point:
-
- | There is one effect, but it doesn't cause any harm:
- | when I uuencode large binary files, the resulting *.UUE always has
- | line 1001 3 bytes longer as you'll see from the following cut:
-
- | Line
- | 1000: M!)(0A")3S,<EVET'2%/THAT7@AOB$0AIY[+*1@)6S(I<)",-ZPD(\J`JAWPH
- | 1001: P1SJAV\VFJ+/YP6:,0$$!-Q]T0J?D3%2F<XHO2V>&.=RN#%OYP!:<(H8\P$9*F"E#
- | 1002: M%UA5L3N,TR%C\*86_8E$%!#4(E(JYY.BA$XSJ-.2`72G;K82@GDBQ9YEP"=S
-
- | Obviously it has to do with your "READSIZE 45000" which is reached in
- | that line (1000 lines * 45 bytes). Anyway the UUDECODE works fine, I've
- | tried it with your UUD12 and with UUDECODE 2.14 . The byte count 'P'
- | (instead of 'M') tells us, that there are 3 bytes more in this line.
-
- Karl-L was right .. I should've checked to see if we had a full line
- (60 chars) of uuencoded bytes BEFORE we check if our binary buffer's
- been used up. That'll insure the full line gets written out as soon
- as it becomes full.
-
- The fix seems to be working fine, testing with various odd sized files
- (to include monster ones that insure that 45000-byte refill).
-
- Added a little logo at the end (overrun by buffers) just to identify
- the program.
-
- ~
-
- ;v1.3, 9 Nov 88
- ; - Tightening again.
- ; BP holds binary character count throughout each line uuencoding.
- ; Tightened uuencoding algorithm itself (fewer shifts & register shuffling).
- ; - Bumping prompted input filename input to 80 chars.
- ; - Different (faster) way of testing:
- ; (1) if we've hit end of the binary read buffer.
- ; (2) if we've completed 60 uuencoded output characters.
- ; - Changing READSIZE to a MOD 3 so we lessen problems from reading
- ; non-MOD 3 numbers of binary characters (until the LAST read).
- ; This (and other fixes) finally fixed the problem with 'non-MOD 3'
- ; sized binary files adding bogus uuencoded bytes to the end.
- ; - Found (and fixed) new bug: one junk byte sneaking in after a binary
- ; buffer refill from file read. (Problem was uuencoded buffer overlying
- ; binary buffer.)
- ;
- ;v1.1, 7 Sep 88
- ; - Provisional compilation .. Set STDOUT to 1 to enable redirection.
- ; Else it'll use the default "filename.uue" format.
- ; - Fixed bug in filename parsing (need to find the SECOND '\' when
- ; stripping paths!
-
- ;v1.0, 6 Sep 88
- ;Hacked together from Kaldis' UU.ASM, the public domain UUENCODE.C,
- ; UUENCODE.PAS, etc.
- ;Uses same algorithm (kinda) as the Turbo Pascal UUENCODE.PAS (not the
- ;C version which does too much bit fiddling).
- ;
- ; - The last few uuencoded characters are coming out different from the
- ; products of UUENCODE.PAS and my Unix mainframe's uuencode. (Actually,
- ; they're ALL different!) Doesn't seem to matter: .ARC files, when
- ; uuencoded and then uudecoded again, still check out. Might bite us
- ; somewhere, but haven't had any problems in lots of tests.
- ;
- ; David Kirschbaum
- ; Toad Hall
- ; kirsch@usasoc.soc.mil
-
- ;-------------------------------------------
- LF EQU 10
- CR EQU 13
- FALSE equ 0
- TRUE equ NOT FALSE
-
- READSIZE EQU 45000 ;max bytes for a binary file read.
- ;Small enough to fit within our
- ; 64Kb code/data space.
- ;Size must be an even divisor of 3.
-
- LINELEN EQU 60 ;nr chars in a uuencoded line
-
- STDOUT EQU 0 ;change to non-0 to enable redirection
-
- Cseg SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:Cseg,DS:Cseg, ES:Cseg
-
- org 80H ;PSP cmdline start v1.8
- cmd_tail label byte ;v1.8
-
- org 100H
-
- UuEncode PROC near
- jmp Start ;jump over data
-
- pr_inp DB CR,LF,'Input path/file: '
- PR_INP_LEN EQU $-pr_inp
-
- err_inp DB 'Input file error.'
- ERR_INP_LEN EQU $-err_inp
-
- err_out DB 'Output file error.'
- ERR_OUT_LEN EQU $-err_out
-
- end_msg DB '`',CR,LF,'end',CR,LF
- END_MSG_LEN EQU $-end_msg
-
- no_action db 'No action' ;v2.0
- NO_ACTION_LEN EQU $-no_action ;v2.0
-
- exist$ db ' exists! Aborting!' ;v2.0
- EXIST$_LEN equ $-exist$ ;v2.0
-
- inp_handle DW 0 ;input file handle
- out_handle DW 1 ;output file handle (default StdOut)
- read_count DW data_buf ;nr binary bytes read
- last_flag db FALSE ;set true when partial read
- overwrite db FALSE ;set true if "-o" cmdline switch v2.0
-
- ;-------------------------------------------
-
- Start:
- ; Insure we're DOS 2.0 or above (or handles won't work!)
- mov ah,30h ;get DOS version
- int 21h
- cmp al,2 ;2.0 or above?
- jae Chk_Cmd ;yep, ok
-
- mov dx,OFFSET msg_v1 ;'DOS 2.0 or above'
- jmp Msg9_Term ;display, terminate (AL=1) v2.0
-
- Msg_Die:
- call Say_Error ;write to StdErr, AH unchanged v2.0
- jmp Terminate ;terminate v2.0
-
- ;-------------------------------------------
- ;Check our PSP command line for a target filename.
- Chk_Cmd:
-
- ;v1.8 Moved command line parsing to a separate subroutine
- ; (since we may have to do it twice)
-
- call Parse_CmdLine ;parse PSP cmdline v1.8
- jnc Open_Inp_Fil ;we have input v1.8
- ;(already AsciiZed) v1.8
- ;DI -> AsciiZ 0 v1.8
-
- ;v1.8 No PSP cmdline input.
- ; Let's prompt our user:
- ;v2.0 But first show usage.
-
- mov dx,offset usage$ ;'Usage..' v2.0
- mov cx,USAGE_LEN ;msg length v2.0
- call Say_Error ;display to STDERR v2.0
-
- mov dx,OFFSET pr_inp ;'Input/file name:' prompt
- mov cx,PR_INP_LEN ;nr chars to display
- mov bx,2 ;STDERR
- mov ah,40H ;write to file/device v2.0
- int 21H
-
- ;Get user's kbd input
- ;v1.8 via regular DOS buffered keyboard input call
-
- mov di,offset cmd_tail-1 ;1 byte before PSP cmdline v1.8
- mov byte ptr [di],80 ;tell DOS max of 80 chars v1.8
- mov dx,di ;DX -> buffer v1.8
- mov ah,0AH ;buffered kbd input svc v1.8
- int 21H
- call Parse_CmdLine ;parse the input
- jnc Open_Inp_Fil ;got input (already AsciiZed)
- ;try to open
- ;DI -> AsciiZ 0
-
- ;v2.0 No user entry at all. Error msg, die.
-
- mov ah,1 ;ERRORLEVEL 1 v2.0
- mov dx,offset no_action ;'No action' v2.0
- mov cx,NO_ACTION_LEN ;msg length v2.0
- jmp Msg_Die ;display, terminate v2.0
-
- ;We have an input filename. Open it.
-
- Open_Inp_Fil:
- mov dx,offset inp_fil ;input filename buffer
- mov si,dx ;remember input filename
- ;buff start
- mov ax,3D00h ;open file
- int 21h
- jnb Inp_Open ;went ok
- jmp Inp_Err ;input file open error, die
-
- ;-------------------------------------------
- Inp_Open:
- mov inp_handle,ax ;save input file handle
-
- ;Take input file name (up to file separator) (no paths)
- ;move "filename.typ" into our uuencoded buffer and write to file.
- ;First scan for any paths, drives, etc.
- ;SI -> input filename buffer start
- ;DI -> the last filename char+1, so we can compute length.
-
- mov cx,di ;last char+1
- sub cx,si ;-start = nr chars+1 v2.0
- dec di ;adjust to end of string
-
- ;We'll start at the end and scan back toward the front.
- ;Remember, scasb decrements DI even if it finds the scan char,
- ;so we'll have to adjust after the find.
-
- mov al,'\' ;first scan for paths
- std ;going backwards
- repne scasb
- cld ;set back forward again
- jz Found_Path ;DI points to char before '\'
- mov di,si ;back to start
- cmp byte ptr [di+1],':' ;how about a drive?
- jne Name_Start ;nope, use buffer start
- ;else fall thru and bump di past 'd:'
-
- ;DI's now pointing at the REAL target file name starting char
- ;(past the drive, paths, etc.)
- ;We first move the original target file name into our uue buffer
- ;(which is initialized with the "start 644 " characters).
- ;This uue buffer will be written as the first line of our uuencoded file.
-
- Found_Path:
- inc di ;adjust for scasb or 'd:'
- inc di
- Name_Start:
- mov si,di ;move from input name start
- mov dx,si ;save starting point a sec
- mov di,offset uue_filename ;move to within uue buffer
- OutName_Loop:
- lodsb ;snarf each char
- or al,al ;0 means filename end
- jz OutName_Done ;done
- stosb ;stuff filename char
- jmp OutName_Loop ;keep going
-
- OutName_Done:
- mov ax,0A0DH ;get CR/LF
- stosw ;stuff it in uuencode buffer
-
- ;target file name has now been moved into a starting uuencoded file
- ;text line (to include CR/LF).
-
- IF STDOUT ;use StdOut redirection
- mov cx,di ;ptr to last filename char +1
- ELSE ;create 'filename.uue'
-
- push di ;remember that ending psn
-
- ;Now to create our output file name: filename.uue
-
- mov si,dx ;SI is PSP target filename start
- mov di,offset out_fil ;move to output file name buffer
- mov dx,di ;we'll need it here also
- Uue_Name_Loop:
- lodsb ;snarf each char
- or al,al ;0 means filename end
- jne Check_Dot ;nope
- mov al,'.' ;no file type, so fake it
- Check_Dot:
- stosb ;stuff name char into output name
- cmp al,'.' ;go up to separator
- jne Uue_Name_Loop ;not yet
- ;We've now moved the file name (plus the '.') into our output buffer.
- ;Time for the type
- mov ax,'uu' ;'uue'
- stosw ;stuff
- mov ax,'e' ;'e', DOS AsciiZ terminator
- mov [di],ax ;stuff
-
- ;DX has output filename starting ofs.
- ;ptr to last byte in uue buffer is on the stack.
- xor cx,cx ;normal file attrib (R/W)
-
- ;v2.0 User asked for output file overwrite protection.
- ; Ok .. let's check for output filename existence
- ; before we create it.
- ; DX -> AsciiZ filename
-
- cmp overwrite,TRUE ;'-o' cmdline switch?
- jz Out_Create ;that's right, overwrite if exists
-
- mov ah,4EH ;find first
- int 21H
- cmp al,2 ;file not found?
- jz Out_Create ;fine, create it
- cmp al,18 ;no more files to be found?
- jz Out_Create ;fine, create it
-
- ;File exists, so we'll message and abort.
-
- pop cx ;clear stack
- mov cx,di ;last char in output name
- sub cx,dx ;last -first = length
- mov bx,2 ;STDERR
- add cx,bx ;adjust count
- mov ah,40H ;write to file/device
- int 21H
- mov dx,offset exist$ ;' exists! Aborting!'
- mov cx,EXIST$_LEN ;msg length
- mov al,5 ;fake "Access denied" errorlevel
- jmp Msg_Die ;display, terminate
-
- Out_Create:
- mov ah,3CH ;create file
- int 21H
- pop cx ;restore uue ptr into CX
- jnb Create_Ok ;ok
- jmp Out_Err ;'Output file error', die
-
- Create_Ok:
- mov out_handle,ax ;save output handle
-
- ENDIF ;StdOut or filename.uue
-
- mov dx,offset uue_out ;'start 644 filename.typ', CR/LF
- sub cx,dx ;last char-buff start = bytes to write
- call Write_File ;write that record
-
- ;Write_File set DI to offset uue_out+1,BP=0
-
- Comment ~ Replaced with Gisbert's v1.9b code
- Read_Loop:
- CALL Read_File ;do the initial binary read
- jz Write_Uue_End ;nothing read, done with input
-
- ;Read_File set SI to offset data_buf, didn't touch DI output buffer ptr,
- ;or BP binary byte counter.
-
- Uue_Loop:
- ;SI and BP are incrementing as we uuencode 45 bytes of binary data
- ;into 60 bytes of 'ready to Asciify' data.
-
- mov cx,0604H ;handy constant
- ;CL=4,CH=6
-
- lodsb ;hunk[1]
- mov ah,al ;AH, AL=hunk[1]
- shr al,1 ;quad[1] = hunk[1] SHR 2
- shr al,1 ;(faster this way)
- stosb ;= quad[1], stuff
-
- lodsb ;AL=hunk[2]
- mov dl,al ;save hunk[2] a sec
- shl ah,cl ;hunk[1] SHL 4
- shr al,cl ;hunk[2] SHR 4
- add al,ah ;shifted hunk[1]+shifted hunk[2]
- stosb ;= quad[2], stuff
-
- mov ah,dl ;AH=orig hunk[2]
- lodsb ;AL=hunk[3]
- mov dl,al ;save hunk[3] in DL a sec
- shl ah,1 ;hunk[2] SHL 2
- shl ah,1 ;(faster this way)
- mov cl,ch ;CL now 6
- shr al,cl ;hunk[3] SHR 6
- add al,ah ;shifted hunk[2]+shifted hunk[3]
- stosb ;= quad[3], stuff
-
- mov al,dl ;AL=orig hunk[3]
- stosb ;= quad[4], stuff
-
- ;That 3-byte hunk is done. See if our binary buffer's empty.
- ;Notice we ALWAYS assume we did all 3 binary bytes.
- ;If we didn't (e.g., had a non-MOD 3 nr of binary bytes in our file),
- ;we'll correct that later with an adjustment to the binary counter
- ;character in the uuencoded line.
-
- add bp,3 ;+3
-
- ;v1.8 Trying to work around that "extra 4 chars"
- ; written to output at the 45000-byte buffer end.
- ; To do this, we first check to see if our uuencoded output line
- ; is full yet (e.g., 45 binary bytes read, 64 uuencoded chars
- ; ready to be output):
-
- cmp bp,45 ;done a line of binary data yet? v1.8
- jnz Chk_BuffEnd ;nope v1.8
- call Write_Uue ;stuff binary count in record, v1.8
- ;Asciify entire record,
- ;append CR/LF, write to file
- ;Reset BP binary counter=0,
- ;DI back to output buffer start +1
-
- Chk_BuffEnd: ; v1.8
- cmp si,read_count ;hit data end yet?
- jb Uue_Loop ;nope,not yet v1.8
- ;keep uuencoding input buffer v1.8
-
- cmp last_flag,1 ;Was last read the binary file EOF?
- jne Read_Loop ;nope, do another read, maybe end.
-
- ;-------------------------------------------
- Comment ends ~
-
- ;v1.9b New Code
- Read_Loop:
- CALL Read_File ;do the initial binary read
- jz Write_Uue_End ;nothing read, done with input
-
- mov cl,6 ;handy constant v1.9b
-
- ;Read_File set SI to offset data_buf, didn't touch DI output buffer ptr,
- ;or BP binary byte counter.
-
- Uue_Loop:
- ;SI and BP are incrementing as we uuencode 45 bytes of binary data
- ;into 60 bytes of 'ready to Asciify' data.
-
- lodsb ;hunk[1]
- mov ah,al ;AH, AL=hunk[1]
- shr al,1 ;quad[1] = hunk[1] SHR 2
- shr al,1 ;(faster this way)
- stosb ;= quad[1], stuff
-
- lodsb ;AL=hunk[2]
- mov dl,al ;save hunk[2] a sec
- shr ax,1 ;combine low 2 bits of hunk[1] v1.9b
- shr ax,1 ;and high 4 bits of hunk[2] v1.9b
- shr ax,1 ;(4 single shifts are still v1.9b
- shr ax,1 ;faster than one shift by CL) v1.9b
- stosb ;= quad[2], stuff
-
- mov ah,dl ;AH=orig hunk[2]
- lodsb ;AL=hunk[3]
- mov dl,al ;save hunk[3] in DL a sec
- shr ax,cl ;hunk[2] SHL 2 OR hunk[3] SHR 6 v1.9b
- stosb ;= quad[3], stuff
-
- mov al,dl ;AL=orig hunk[3]
- stosb ;= quad[4], stuff
-
- ;That 3-byte hunk is done. See if our binary buffer's empty.
- ;Notice we ALWAYS assume we did all 3 binary bytes.
- ;If we didn't (e.g., had a non-MOD 3 nr of binary bytes in our file),
- ;we'll correct that later with an adjustment to the binary counter
- ;character in the uuencoded line.
-
- add bp,3 ;+3
-
- ;v1.8 Trying to work around that "extra 4 chars"
- ; written to output at the 45000-byte buffer end.
- ; To do this, we first check to see if our uuencoded output line
- ; is full yet (e.g., 45 binary bytes read, 64 uuencoded chars
- ; ready to be output):
-
- cmp bp,45 ;done a line of binary data yet? v1.8
- jnz Chk_BuffEnd ;nope v1.8
- call Write_Uue ;stuff binary count in record, v1.8
- ;Asciify entire record,
- ;append CR/LF, write to file
- ;Reset BP binary counter=0,
- ;DI back to output buffer start +1
- mov cl, 6 ;restore handy constant v1.9b
-
- Chk_BuffEnd: ; v1.8
- cmp si,read_count ;hit data end yet?
- jb Uue_Loop ;nope,not yet v1.8
- ;keep uuencoding input buffer v1.8
-
- cmp last_flag,1 ;Was last read the binary file EOF?
- jne Read_Loop ;nope, do another read, maybe end.
-
- ;-------------------------------------------
-
-
- Write_Uue_End:
- or bp,bp ;any bytes uuencoded?
- jz No_Partial_Write ;none, so no trailing to write
-
- ;In converting 3 binary bytes to 4 quad chars, we may have bumped SI
- ;beyond the actual number of binary bytes read.
- ;By subtracting the original count of bytes read from SI,
- ;we'll get the number of 'bogus' binary bytes in that last quad.
- ;Subtract that from the BP binary counter, and we'll get the TRUE
- ;number of binary bytes in that uuencoded line.
- ;It's up to the uudecoding program to catch that difference
- ;and ignore the extra quads. (The ones I've tested seem to.)
-
- sub si,read_count ;check for overrun
- sub bp,si ;subtract any bogus bytes
- call Write_Uue ;write partial line
-
- No_Partial_Write:
- mov dx,offset end_msg ;'end',CR/LF
- mov cx,END_MSG_LEN ;nr bytes to move
- call Write_File ;do the last write
-
- ;DOS closes open files at termination.
- ;However, just to be neat:
-
- IF NOT STDOUT ;no StdOut
- mov bx,out_handle ;output file handle
- mov ah,3EH ;close the file
- int 21H
- ENDIF
-
- Terminate:
- mov ah,4Ch ;terminate, ERRORLEVEL ?
- int 21h
-
- ;v2.0 Enter here for a msg display via svc 9, Int 21H
- ; (msg address in DX)
- Msg9_Term:
- push ax ;save errorlevel
- mov ah,9
- int 21H
- pop ax ;restore
- jmp Terminate
-
- UuEncode endp
-
- ;-------------------------------------------
-
- Write_Uue PROC NEAR
- ;Enter with DI pointing to char beyond last uuencoded char.
- ;Stuff CR/LF, compute line length, write to file.
-
- ;v1.9 push si ;save input ptr a sec
- MOV DX,offset uue_out ;output line start (length byte)
- mov cx,di ;current output pointer
- sub cx,dx ;- buffer start = nr bytes in line
- ;+1, but that's ok since we're adding
- ;the line_len byte
- push cx ;save full line length for later
- ;Do the last masking of the line of quads
- ;v1.9 mov si,dx ;point to line start for 'from'
- mov di,dx ;moving to same place
- mov ax,bp ;binary bytes in this line
- ;v1.9 mov [si],al ;stuff binary length byte
- mov [di],al ;stuff binary length byte v1.9
- ; (uuencode later)
- mov ah,20H ;get a handy constant
-
- ;Gotta process every byte, masking, checking for spaces, etc.
- ;This includes that length byte.
- mov bx,(3FH SHL 8) + 96 ;get another handy constant
- ;BH=3FH, BL=96
- Mask_Loop:
- ; lodsb ;get output line char
- mov al,[di] ;get output line char v1.9
- and al,bh ;3FH ;six-bit mask
- add al,ah ;plus asciifying offset
- cmp al,ah ;end up with a space
- jne Not_Space ;nope
- mov al,bl ;96 ;use space substitute "`"
- Not_Space:
- stosb ;stuff it back in line buffer
- loop Mask_Loop ;do them all
-
- pop cx ;restore char count for bytes to write
- ;DI now points at char just beyond uuencoded char line
- mov ax,0A0DH ;Get CR/LF
- mov [di],ax ;stuff them in buffer
- inc cx ;add in CR/LF to length
- inc cx
- ;v1.9 pop si ;restore SI
-
- Write_File:
- MOV BX,out_handle ;output file handle
- MOV AH,40h ;write to file/device
- INT 21h
- jb Out_Err ;write error
- mov di,dx ;point DI back to uue_out start
- inc di ;bump past length byte
- xor bp,bp ;reset byte ctr
- RET ;write done
-
- ;Output file write error
- Out_Err:
- MOV DX,OFFSET err_out ;'Output file error'
- MOV CX,ERR_OUT_LEN ;msg length
- jmp short Fatal_Error ;common code
-
- Write_Uue ENDP
-
- ;-------------------------------------------
- ;Read a chunk of raw binary data
- Read_File PROC NEAR
- MOV DX,offset data_buf ;into binary input buffer
- mov cx,READSIZE ;nr bytes to read
- MOV BX,inp_handle ;input file handle
- MOV AH,3Fh ;read from file/device
- INT 21h
- jb Inp_Err ;failed
-
- ;AX has nr of bytes read
- mov si,dx ;SI needs offset data_buf
- mov bx,dx ;buffer start
- add bx,ax ;+bytes read = data end
-
- ;BX points to the next 'empty' byte (data_buf start + bytes read)
-
- cmp ax,cx ;read a full buffer?
- je Read_Full ;yep, no fiddling required
-
- ;We've read less than a buffer full. Let's make sure the last bytes
- ;are nulls if bytes read are not MOD 3.
- mov word ptr [bx],0 ;stuff 2 nulls there
- mov last_flag,1 ;turn EOF flag on
-
- Read_Full:
- mov read_count,bx ;point to data end
- or ax,ax ;set flags for return
- RET ;read done
-
- ;-------------------------------------------
- ;Input file read error. Error value in AL
- Inp_Err:
- MOV DX,OFFSET err_inp ;'Input file error'
- MOV CX,ERR_INP_LEN ;msg length
- ;Common code added here
- Fatal_Error:
- call Say_Error ;display error msg, AL unchanged v2.0
- jmp Terminate ;terminate v2.0
-
- Read_File ENDP
-
- ;-------------------------------------------
- Say_Error proc near
- ;DX -> error msg
- ;CX = msg len
-
- push ax ;save AX v2.0
-
- push dx ;msg address v2.0
- push cx ;msg length
- mov dx,offset crlf ;precede msgs w/CRLF
- mov cx,CRLF_LEN ;length
- call ErrOut ;display it
-
- pop cx ;restore
- pop dx ; original error msg
- call ErrOut ;display it
-
- mov dx,offset crlf ;precede msgs w/CRLF
- mov cx,CRLF_LEN ;length
- call ErrOut ;display it
-
- pop ax ;restore AX (error level maybe)
- ret
-
- ErrOut: mov bx,2 ;Std ErrOut handle
- mov ah,40h ;write to file/device
- int 21h
- ret
-
- Say_Error ENDP
-
- ;v1.8 Command line processing subroutine
-
- Parse_CmdLine proc near
-
- MOV SI,offset cmd_tail ;move cmd line parm v1.8
- MOV DI,offset inp_fil ;to our filename buffer
- CLD ;insure fwd
- LODSB ;cmd line length byte
- or al,al ;nothing there?
- jz PC_NoInput ;yep, nothing there
-
- mov ah,20H ;get a handy space
- Strip_Ct:
- lodsb ;next cmd line char
- cmp al,ah ;gobble leading spaces,tabs, etc.
- jbe Strip_Ct
-
- ;v2.0 Check for a "-o" switch on command line
-
- cmp al,'/' ;this kind of switch?
- jz GotSwitch ;yep
- cmp al,'-' ;switch?
- jnz NotSwitch ;nope, must be name char
- GotSwitch:
- mov dx,ax ;save this char a second
- mov ax,[si] ;snarf next 2 chars
- cmp al,'?' ;Wants help? v2.0
- jz JustHelp ;yep, help, die v2.0
-
- and al,5FH ;mask 1st char to uppercase
- cmp ax,' O' ;O and space means switch
- mov ax,dx ;restore in case not
- jnz NotSwitch ;nope, must be name
-
- ;We have the overwrite switch
-
- not overwrite ;toggle flag to TRUE
- inc si ;bump past 'o'
- inc si ;and past space
- lodsb ;next char should be name
-
- Ct_Char:
- cmp al,ah ;ctrl char? (e.g., CR)
- jbe PC_Input ;yep, done
- NotSwitch:
- stosb ;stuff filename byte
- lodsb ;snarf next cmdline char
- jmp Ct_Char ;and loop
-
-
- PC_NoInput:
- stc ;no input, return CF set
- ret
-
- PC_Input:
- mov byte ptr [di],0 ;Asciize filename input
- clc ;got input, return CF clear
- ret
-
- ;v2.0 New code
- JustHelp:
- pop ax ;clear original call to be neat
- mov dx,offset usage$ ;'Usage:'
- mov al,1 ;ERRORLEVEL 1
- IF STDOUT
- ;With output going to STDOUT, we'd better send usage to STDERR
- mov cx,USAGE_LEN ;msg length
- jmp Fatal_Error ;display STDERR, terminate
- ELSE
- jmp Msg9_Term ;display via Svc 9, terminate
- ENDIF
-
- Parse_CmdLine endp
-
-
- ;using pointers here at code end for various buffers.
- ;the uue_out buffer is normally 60 uuencoded chars, plus CR/LF
- ;It's initialized with the default uuencode file header.
- ;No, I don't know the magic in '644'.
-
- EVEN ;v1.2
-
- uue_out db 'begin 644 ' ;first write contains this + name
-
- ;The rest of these buffers don't take any code space.
-
- uue_filename equ $ ;where we move filename.uue
-
- ;Leave room for LINELEN+2 chars for uue_out buffer.
-
- inp_fil equ uue_out + LINELEN +2 ;80 chars long
-
- ;Leave room for 80 chars for inp_fil filename buffer.
-
- out_fil equ inp_fil + 80 ;15 bytes long
-
- data_buf equ out_fil ;leave room for uue_out
-
- logo db 'UUENCODE v2.0',0 ;v2.0
- db 'David P Kirschbaum, Toad Hall, '
- db 'Given to the public domain',0
-
- IF STDOUT
- usage$ db 'UUENCODE [d:][\path\]binary.fil [>output] <RETURN>'
- db CR,LF,'(Uses redirection)'
- ELSE
- usage$ db 'UUENCODE [-o] [d:][\path\]binary.fil <RETURN>',CR,LF
- db 'produces binary.UUE on current drive\path',CR,LF
- db '(providing binary.UUE doesn''t already exist).',CR,LF ;v2.0
- db '-o switch forces overwrite of existing binary.UUE' ;v2.0
-
- ENDIF
- USAGE_LEN equ $-usage$ ;v2.0
- db CR,LF,'$' ;for Svc 9 display v2.0
-
- msg_v1 DB 'This program requires DOS V2.0 or higher.'
- crlf db CR,LF ;v2.0
- CRLF_LEN EQU $-crlf ;v2.0
- db '$' ;Svc 9 display only v2.0
-
- Cseg ENDS
- END UuEncode