home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / waffle / aser28.zip / UUD20.ASM < prev    next >
Assembly Source File  |  1991-03-12  |  22KB  |  746 lines

  1.         name    UUD
  2.         page    55,132
  3.         title   'UUDECODE.ASM'
  4. ;
  5. ; UUDECODE.ASM -- UUDecodes a UUEncoded Binary File
  6. ;
  7. ; Copyright (C) 1988, by Theodore A. Kaldis
  8. ;
  9. ; To assemble and link this program into the executable UUDECODE.COM:
  10. ; (It will NOT run assembled as an .EXE program!)
  11.  
  12. ;        MASM UUD;
  13. ;        LINK UUD;
  14. ;        (If you just have EXE2BIN:
  15. ;          EXE2BIN UUD
  16. ;          REN UUD.BIN UUDECODE.COM (or whatever)
  17. ;        (If you have Public Domain EXE2COM or equivalent:
  18. ;          EXE2COM UUD
  19. ;          REN UUD.COM UUDECODE.COM (or whatever)
  20. ;        (Delete the .OBJ file)
  21.  
  22. ; See version 1.1 for .EXE equivalent.
  23.  
  24. Comment ~
  25. v2.0, 10 Mar 91
  26. - Keith Petersen says we must handle "begin 0600 foobar.arc" type
  27.   headers .. which we surprisingly can't!
  28.   He found the bug:
  29. |David, I found the bug in TOADUU19's uudecode.  I added one line to the
  30. |source code and changed a comment which said that AH already had a
  31. |space in it.
  32. |
  33. |Here's the fix:
  34. |
  35. |;Put a space into AH for fast comparisons
  36. |    mov    ah,' '
  37. |Strip_Spc:
  38.  
  39. - He also wanted file overwrite protection like TOADXX, so I added that
  40.   as well.  New command line parm (/o or /O) to force overwrite if
  41.   file exists.  Else abort without overwrite.
  42.  
  43. - He then found a bug in the "no filename" handling.  I added usage
  44.   before the filename prompt.
  45.  
  46. - While I'm here, tightened up error msg writing a little (preceding
  47.   and following all msgs with CR/LF, etc.)
  48.  
  49. v1.8, 5 Jul 89
  50.  
  51. Thanks to Karl-L. Noell <NOELL%DWIFH1.BITNET@CUNYVM.CUNY.EDU>
  52. for a bug report:
  53.  
  54. |  When I call up UUE12 or UUD17 without filename, a prompt appears:
  55. |  Input path/file:
  56. |  but answering to that prompt always yields the message
  57. |  "Input file error."
  58.  
  59. Karl-L's right .. stupid .. donno how I missed it.  Fixed.
  60.  
  61. Added a little logo at the end (overrun by buffers) just to identify
  62. the program.
  63.  
  64. Toad Hall
  65. ~
  66.  
  67. ;v1.7, 9 Nov 88
  68. ; - Versions since 1.3 BROKE (a new Truncated line test).
  69. ;   Trying again.
  70. ; - Handling headers, tailers, truncated lines ok.
  71. ; - Moving some start-up data and code down into buffer space
  72. ;   just as an exercise.
  73. ; - Previously cut down input buffer size to limit buffer requirements.
  74. ;   However, since DOS needs 64Kb to load a .COM file anyway,
  75. ;   might as well use the entire 64Kb segment allocated us.
  76.  
  77. ;(notes on versions 1.4 thru 1.6 discarded.)
  78.  
  79. ;v1.3, 7 Sep 88
  80. ; - Tightened up seeking for 'begin' and 'end'.
  81. ; - Added 'start' error.
  82. ; - Tightened up line reading, uudecoding a little.
  83. ; - made console/error msgs REALLY go to standard ErrOut device (2)
  84. ; - Renamed to UUD13.ASM (differenciate from UUE, UU).
  85.  
  86. ;V1.2, 6 Sep 88
  87. ; - Changing to .COM format.
  88. ; - moved a bunch of buffers (file names, input and output buffers)
  89. ;   to be just pointers at code end (not taking up file space).
  90. ; - Reduced max file read from 0FE00H to 0F000H (to stay within 64Kb
  91. ;   for program and buffers).
  92.  
  93. ;V1.1, 6 Sep 88
  94. ; Toad Hall Tweak
  95. ; - General tightening.
  96. ; - Added comments.
  97. ;
  98. ;
  99. ; David Kirschbaum
  100. ; Toad Hall
  101. ; kirsch@usasoc.soc.mil
  102.  
  103. ;-------------------------------------------
  104. CR        EQU    0DH
  105. LF        EQU    0AH
  106. SPC        EQU    20H
  107. FALSE        EQU    0
  108. TRUE        EQU    NOT FALSE
  109. ;-------------------------------------------
  110. CSEG    SEGMENT PARA PUBLIC 'CODE'
  111.     ASSUME  CS:CSEG,DS:CSEG, ES:CSEG
  112.  
  113.     org    0
  114. cseg_ofs    label    byte        ;fake out MASM            v1.9
  115.     org    80H
  116.  
  117. cmd_tail    label    byte        ;v1.8
  118.  
  119.     org    100H
  120.  
  121. ;-------------------------------------------
  122. Uudecode    PROC    near
  123.     jmp    Start        ;jump over data
  124.  
  125. ;This data will be used during the uudecode run.
  126.  
  127. err_inp        DB    'Input file error.'
  128. ERR_INP_LEN    EQU    $-err_inp
  129. err_out        DB    'Output file error.'
  130. ERR_OUT_LEN    EQU    $-err_out
  131. err_begin    db    'start not found.'
  132. ERR_START_LEN    EQU    $-err_begin
  133.  
  134. err_end        DB    'End not found.'
  135. ERR_END_LEN    EQU    $-err_end
  136.  
  137. exist$        db    ' exists. Aborting!'                ;v2.0
  138. EXIST$_LEN    equ    $ - exist$                    ;v2.0
  139.  
  140. inp_handle    DW    0
  141. out_handle    DW    0
  142. uuptr        DW    UUBUFF        ;points at next byte in uuencoded
  143.                     ; input buffer UUBUFF
  144. uuEndptr    DW    UUBUFF        ;points beyond uuencoded data
  145.                     ; (e.g., buffer end)
  146. outptr        DW    OUT_BUF        ;pointer to binary output buffer 
  147.                     ; (where to stuff NEXT uudecoded byte)
  148.  
  149. overwrite    db    FALSE        ;is set to true for overwriting    v2.0
  150.  
  151. ;-------------------------------------------
  152.  
  153. Start:
  154.     call    Init            ;cmd line parsing, file opening
  155.  
  156. ;v1.7 If we make it back, all's ok.
  157. ;We should have input file opened.
  158.  
  159.     call    Read_File        ;do the initial read
  160.  
  161. Get_Out_Fil:
  162.     mov    di,offset OUT_BUF    ;clear DI
  163.     call    Get_Line        ;read a line of input
  164.  
  165. ;Look for uuencoded file's 'begin'
  166. ;(Don't like this very much .. could be stuck here until we've gone
  167. ;through the entire doggone file!  Oh, well ..it works anyway..
  168. ;(Also gobbles up any headers or other garbage at file start.)
  169. ;Tried a 'CMPSB'  or 'SCASB' of the input buffer against a 'begin'
  170. ;in our own code space, but it was a mess!
  171.  
  172.     lodsw                ;snarf 2 plaintext chars
  173.     cmp    ax,'eb'            ;'be'?
  174.     jne    Get_Out_Fil        ;nope, next line
  175.     lodsw                ;next 2
  176.     cmp    ax,'ig'            ;'gi'?
  177.     jne    Get_Out_Fil        ;nope, next line
  178.     lodsw                ;next 2
  179.     cmp    ax,' n'            ;'n '?
  180.     jne    Get_Out_Fil        ;nope, next line
  181.  
  182.     mov    di,offset OUT_FIL    ;to output buffer
  183.  
  184. ;Put a space into AH for fast comparisons
  185.     mov    ah,' '
  186. Strip_Spc:
  187.  
  188. ;Gobble spaces until we hit the mode number after 'begin'
  189.     lodsb
  190.     cmp    al,ah            ;space?
  191.     jbe    Strip_Spc        ;gobble spaces, tabs, ctrl chars 
  192.  
  193. Strip_Num:
  194. ;Hit the number, now gobble until the space after number
  195.     lodsb
  196.     cmp    al,ah            ;space?
  197.     jne    Strip_Num        ;gobble until space
  198.  
  199. ;v1.7 now gobble any spaces between number and name ... sigh ...
  200. Strip_Spc2:
  201.     lodsb
  202.     cmp    al,ah            ;space?
  203.     jbe    Strip_Spc2        ;gobble until real char
  204.  
  205. ;We should now be at the first char of the original target's filename.
  206. ;Move output filename from LINE_IN buffer to our output filename buffer.
  207. ;Since LINE_IN has been padded with spaces, a space will indicate
  208. ;name end.
  209. Get_Out:
  210.     cmp    al,ah            ;space means done
  211.     je    Out_Fin            ;yep, name end
  212.     stosb                ;input byte > OUT_FIL filename buff
  213.     lodsb                ;next filename char
  214.     jmp    Get_Out            ;and keep going
  215.  
  216. ;-------------------------------------------
  217. Out_Fin:
  218.     mov    dx,offset OUT_FIL    ;output filename buffer
  219.     xor    cx,cx            ;normal file attribs (R/W)
  220.     mov    [di],cl            ;AsciiZ output filename
  221.  
  222. ;v2.0    User requested overwrite protection for the output filename.
  223. ;    Ok .. let's check for output filename existence before we
  224. ;    do the create.
  225.  
  226.     cmp    overwrite,TRUE        ;"-o" commandline switch?
  227.     jz    Out_Create        ;yep, no checking
  228.  
  229.     mov    ah,4EH            ;find first
  230.     int    21H
  231.     cmp    al,2            ;file not found?
  232.     jz    Out_Create        ;fine, doesn't exist
  233.     cmp    al,18            ;no more files to be found?
  234.     jz    Out_Create        ;fine
  235.  
  236. ;v2.0 File exists.  Error message, die.
  237. ;     DI -> filename AsciiZ 0
  238. ;     DX -> filename 1st char
  239.  
  240.     mov    cx,di            ;last char
  241.     sub    cx,dx            ;- first char = chars to write
  242.     call    Say_Error        ;display filename
  243.  
  244.     mov    dx,OFFSET exist$    ;'File exists'
  245.     mov    cx,EXIST$_LEN        ;msg length
  246.     mov    al,5            ;fake "Access denied" errorlevel
  247.     jmp    Fatal_Error        ;display, terminate
  248.  
  249.  
  250. Out_Create:                ;v2.0
  251. ;End of v2.0 change
  252.  
  253.     mov    ah,3Ch            ;create output file
  254.     int     21h
  255.     jnc    Out_Open        ;went ok
  256.      jmp    Out_Err            ;output file create error
  257.  
  258.  
  259. ;-------------------------------------------
  260. Out_Open:
  261.     mov    out_handle,ax        ;remember output file handle
  262.     mov    di,offset OUT_BUF    ;prepare to clear outptr
  263. New_Line:
  264.     call    Get_Line        ;read in uuencoded line
  265.  
  266. ;First char is nr of binary bytes used to produce this line. (Asciified)
  267. ;If there's an empty last line, it'll just be a space or '`'
  268.     lodsb                ;snarf uuencoded binary byte count
  269.     or    al,al            ;empty line?
  270.     jz    Prog_End        ;yep
  271.  
  272.     mov    bx,2020H        ;a handy constant
  273.     sub    al,bl    ;20H        ;Deasciify
  274.     or    al,al            ;null?
  275.     je    Prog_End        ;yep, must be done
  276.  
  277. ;v1.7 keeping line's binary byte count in BP
  278.     xor    ah,ah            ;clear msb
  279.     mov    bp,ax            ;BP=binary byte count
  280.  
  281. ;uuencoded stuff (input) is in 'quads' (4-char packets),
  282. ;binary output is in 'hunks' (3 byte packets)
  283. ;4 chars = 3 bytes
  284. NN_0:
  285.     mov    cx,0604H        ;handy constant
  286.                     ;CL=4, CH=6
  287.  
  288.     lodsb                ;quad[1]
  289.     mov    ah,al            ;AH=quad[1]
  290.     lodsb                ;AL=quad[2]
  291.     mov    dl,al            ;save quad[2]
  292.     sub    ax,bx            ;remove standard offset
  293.  
  294.     shl    ah,1            ;quad[1] SHL 2
  295.     shl    ah,1            ;(faster this way)
  296.     shr    al,cl            ;quad[2] SHR 4
  297.     or    al,ah            ;shifted quad[2] OR shifted quad[1]
  298.     stosb                ;=hunk[1], stuff in OUT_BUF
  299.     dec    bp            ;decr binary byte ctr
  300.     jz    New_Line        ;uuencoded line is done
  301.  
  302.     mov    ah,dl            ;AH=unshifted quad[2]
  303.     lodsb                ;AL=quad[3]
  304.     mov    dl,al            ;save quad[3]
  305.     sub    ax,bx            ;remove standard offset
  306.  
  307.     shl    ah,cl            ;quad[2] SHL 4
  308.     shr    al,1            ;quad[2] SHR 2
  309.     shr    al,1            ;(faster this way)
  310.     or    al,ah            ;shifted quad[3] OR shifted quad[2]
  311.     stosb                ;=hunk[2], stuff in OUT_BUF
  312.     dec    bp            ;decr binary byte ctr
  313.     jz    New_Line        ;uuencoded line is done
  314.  
  315.     mov    ah,dl            ;AH=unshifted quad[3]
  316.     lodsb                ;AL=quad[4]
  317.     sub    ax,bx            ;remove standard offset
  318.  
  319.     mov    cl,ch            ;6
  320.     shl    ah,cl            ;quad[3] SHL 6
  321.     or    al,ah            ;shifted quad[4] OR shifted quad[3]
  322.     stosb                ;=hunk[3], stuff in OUT_BUF
  323.     dec    bp            ;decr binary byte ctr
  324.     jnz    NN_0            ;uuencoded line not done
  325.     jmp    short New_Line        ;line done, get new line
  326.  
  327. ;-------------------------------------------
  328. ;Now we look for the uuencoded file's 'end'.
  329. ;We'll write out what we've got, even if we don't find the 'end'.
  330.  
  331. Prog_End:
  332.     call    Get_Line        ;should be file's last line
  333.     lodsw                ;load next 2 chars
  334.     cmp    ax,'ne'            ;'en'?
  335.     jne    End_Err_C        ;'No end found'
  336.      lodsb
  337.      cmp    al,'d'
  338.      je    File_End        ;ok, got the 'end'
  339. End_Err_C:
  340.     call    End_Err            ;say we had an end error
  341. File_End:
  342.     call    Write_File        ;do our final output write
  343. ;Seems there's no need to close files .. DOS must do it!
  344. File_End_X:
  345.     mov    ah,4Ch            ;terminate, ERRORLEVEL ?
  346.     int     21h
  347. Uudecode    endp
  348.  
  349. ;-------------------------------------------
  350. ;Reads in a line of uuencoded text
  351. ;Didn't like the original logic here (how it physically looks for a CR (0DH)
  352. ;as an End of Line indicator (EOL), then gobbles until a LF (0DH).
  353. ;Unix text and uuencoded files only have LFs as EOL,
  354. ;MACs only have CR EOLs (I think).
  355. ;Well, we're handling CR/LF and LF EOLs, and that'll do for now.
  356.  
  357. ;The first char of a uuencoded line is usually an 'M' (ASCII 77).  This is
  358. ;the nr of binary bytes used to create this uuencoded line (Asciified).
  359.  
  360. Get_Line    PROC    NEAR
  361.     mov    si,uuptr        ;current raw input buffer psn
  362.  
  363. ;This is looped to (from below) if the line was garbage (e.g., some sort
  364. ;of file header.  It refreshes the outbuf pointer to buffer start,
  365. ;and sets up the uuencoded line buffer LINE_IN anew.
  366.  
  367. Flush_Lin:
  368.     mov    outptr,di        ;save outbuf ptr in outptr
  369.                     ;for Write_File test
  370.  
  371. ;BP holds the constant 'maximum line length'.
  372. ;I never heard of a uuencode that used lines longer than 60 bytes,
  373. ;plus length byte and CR/LF.
  374.     mov    bp,80            ;max allowable uuencoded line len 
  375.  
  376. ;Prepare our uuencoded line buffer LINE_IN for transfer of a line.
  377. ;Remember, this same sequence is used to get the uuencode protocol's
  378. ;first line ('begin 6xx filename.typ'),normal uuencoded lines,
  379. ;and the last uuencode protocol line ('end').
  380. ;We're preparing an 80-char line (maximum allowed).
  381.  
  382.     mov    di,offset LINE_IN    ;uuencoded line buffer start
  383.     xor    ax,ax
  384.     stosw                ;clear first 2 bytes
  385.     mov    cx,(78/2)        ;clear remaining 78 bytes    v1.9
  386.     mov    ax,2020H        ;fill with spaces
  387.     rep    stosw
  388.     mov    di,offset LINE_IN    ;uuencoded line buffer start
  389.  
  390. Next_Chr:
  391.     cmp    si,uuEndptr        ;hit end yet?
  392.     jb    Not_Mt            ;not empty yet
  393.      call    Write_File        ;write our binary output (if any)
  394.      call    Read_File        ;read more uuencoded input
  395. Not_Mt:
  396.     lodsb                ;snarf uuencoded line char
  397.     cmp    al,96            ;special '`' in place of spaces
  398.     jne    Not_Hi            ;wasn't a space substitute
  399.      mov    al,' '            ;replace with space
  400.      jmp    short Was_Space        ;and skip the next test
  401.  
  402. ;We check for both CR End-Of_Line (EOL) and LF EOL.            v1.9
  403. ;(This handles DOS and Unix files.)
  404.  
  405. Not_Hi:    cmp    al,CR            ;CR means line end
  406.     je    Eol_CR            ;end of line, got line
  407.     cmp    al,LF            ;How about Unix EOL?
  408.     je    Eol_LF            ;Yep, was Unix EOL, got line
  409. Was_Space:
  410.     stosb                ;stuff uuencoded line char
  411.     dec    bp            ;count down allowable length
  412.     jnz    Next_Chr        ;Ok, not yet
  413.  
  414. ;This line is longer than 80 chars, so it CAN'T be a uuencoded line.
  415. ;Continue to gobble it up, throwing it away, until EOL,
  416. ;then flush and continue.
  417. ;This only happens for headers.  We never hit trailers at all.
  418.  
  419. Strip_Head:
  420.     cmp    si,uuEndptr        ;beyond uubuf data?
  421.     jb    Strip_NoRead        ;nope
  422.      call    Read_File        ;refill the uubuf
  423. Strip_NoRead:
  424.     lodsb                ;look for a LF
  425.     cmp    al,LF            ;LF yet?
  426.     jne    Strip_Head        ;nope, keep going w/this line
  427.  
  428.     mov    di,offset OUT_BUF    ;clear DI to clear outptr
  429.     jmp    Flush_Lin        ;EOL, keep working thru raw
  430.                     ;input buffer
  431.  
  432. ;-------------------------------------------
  433. ;Hit CR, got a uuencoded line (DOS files).
  434. ;SI -> LF just past the CR.
  435.  
  436. Eol_CR:
  437.     inc    si            ;bump raw input buffer ptr past LF
  438.  
  439. ;Hit LF EOL (Unix files).
  440. ;SI -> next raw buff char.
  441.  
  442. Eol_LF:
  443.     mov    uuptr,si        ;remember current raw buff ptr
  444.     mov    di,outptr        ;restore binary output ptr
  445.     mov    si,offset LINE_IN    ;ptr to inbuffer start
  446.     ret                ;done
  447.  
  448. Get_Line    ENDP
  449.  
  450. ;-------------------------------------------
  451. ;Write a chunk of uudecoded data (if any) to output file.
  452. Write_File    PROC    NEAR
  453.  
  454.     mov    dx,offset OUT_BUF    ;output binary buffer start
  455.     mov    cx,dx            ;prepare to reinit outptr
  456.     xchg    cx,outptr        ;outptr=output buffer start,
  457.                     ;CX=outptr
  458.     sub    cx,dx            ;-buffer start=buffer byte count 
  459.  
  460. ;IF CX=0, there's no uudecoded data to write, just exit.
  461. ;If CX went below 0 (e.g., outptr pointed BELOW OUT_BUF start),
  462. ;we have an error of some sort (my code logic?).
  463. ;Ignore that also.  It'll get cleaned up later.
  464.  
  465.     jbe    Write_Good        ;error
  466.      mov    bx,out_handle        ;output file handle
  467.      mov    ah,40h            ;write to file/device
  468.      int     21h
  469.      jb    Out_Err            ;write error
  470. Write_Good:
  471.     ret                ;write done
  472.  
  473. ;Output file write error
  474. Out_Err:
  475.     mov    dx,OFFSET err_out    ;'Output file write error'
  476.     mov    cx,ERR_OUT_LEN        ;msg length
  477.     jmp    short Fatal_Error    ;common code, error value in AL
  478.  
  479. Write_File    ENDP
  480.  
  481. ;-------------------------------------------
  482. ;Read a chunk of input (uuencoded) data into our uuencode buffer.
  483. ;I don't think we'll EVER try to read past EOF (since the 'end' line
  484. ;should've been detected and program terminated).
  485. ;Let's assume that 'read past EOF' is an error of some sort and die.
  486. ;('Coding by trial and error')
  487.  
  488. Read_File    PROC    NEAR
  489.  
  490.     mov    dx,offset UUBUFF    ;read into uuencode input buffer
  491.     mov    cx,offset UU200        ;code space - 200H stack bytes
  492. ;v1.9    not    cx            ;= remaining segment memory
  493.     mov    bx,inp_handle        ;input file handle
  494.     mov    ah,3Fh            ;read from file/device
  495.     int     21h
  496.     jb    Inp_Err            ;failed
  497.     or    ax,ax            ;read anything?
  498.     jz    Read_EOF        ;nope, EOF
  499.  
  500.     mov    si,dx            ;point to input UUBUFF start
  501.     add    ax,si            ;chars read+UUBUFF start
  502.     mov    uuEndptr,ax        ;points beyond last UUBUFF char
  503.     ret                ;read done
  504.  
  505. Read_EOF:
  506.  
  507. ;-------------------------------------------
  508. ;Input file read error.  Error value in AL
  509. Inp_Err:
  510.     mov    dx,OFFSET err_inp    ;'Input file error'
  511.     mov    cx,ERR_INP_LEN        ;msg length
  512. ;Common code added here
  513. Fatal_Error:
  514.     push    ax            ;save error in AL
  515.     call    Say_Error        ;common code
  516.     pop    ax            ;restore error in AL
  517.     jmp    File_End_X        ;terminate
  518.  
  519. Read_File    ENDP
  520.  
  521. ;-------------------------------------------
  522. ;Unexpected End of File.  (No 'end')
  523. End_Err        PROC    NEAR
  524.  
  525.     mov    dx,OFFSET err_end    ;'End not found'
  526.     mov    cx,ERR_END_LEN        ;msg length
  527. Say_Error:                ;common code
  528.     push    dx            ;v2.0
  529.     push    cx
  530.     mov    dx,offset crlf        ;Precede all err msgs w/CR/LF    v2.0
  531.     mov    cx,CRLF_LEN
  532.     call    ErrOut            ;display CR/LF
  533.     pop    cx            ;restore orig msg len        v2.0
  534.     pop    dx            ;ptr to msg            v2.0
  535.     call    ErrOut            ;display it
  536.     mov    dx,offset crlf        ;Follow all err msgs w/CR/LF    v2.0
  537.     mov    cx,CRLF_LEN
  538.  
  539. ErrOut:
  540.     mov    bx,2            ;Std ErrOut handle
  541.     mov    ah,40h            ;write to file/device
  542.     int     21h
  543.     ret
  544.  
  545. End_Err        ENDP
  546.  
  547.  
  548. ;using pointers beyond runtime code and/or code end for various buffers.
  549. ;This does NOT take up any space in our program.
  550.  
  551.         EVEN
  552.  
  553. ;v1.7 LINE_IN is not used until after Init,
  554. ;so it can overwrite this code and data.
  555. LINE_IN    equ    $            ;80 bytes long
  556.  
  557. ;Some start-up data moved down here to minimize memory requirements.
  558. msg_v1        DB    CR,LF,'This Program Requires DOS Version 2.0 '
  559.         DB      'or higher.'
  560. crlf        db    CR,LF,'$'
  561. CRLF_LEN    EQU    2                    ;v2.0
  562. pr_inp        DB    CR,LF,'Input path/file:  '
  563. PR_INP_LEN    EQU    $-pr_inp
  564. no_action    db    'No action'
  565. NO_ACTION_LEN    equ    $-no_action
  566.  
  567. ;v1.7 Some start-up code.
  568. Init    proc    near
  569.  
  570. ;First make sure we have DOS 2.0 or higher, or handles won't work.
  571.     mov    ah,30h            ;get DOS version
  572.     int     21h
  573.     cmp    al,2            ;2.0 or above?
  574.     jae    Chk_CmdLine        ;yep, ok
  575.      mov    dx,OFFSET msg_v1    ;'DOS 2.0 or above'
  576. Msg_Die:
  577.      mov    ah,9            ;display string
  578.      int     21h
  579.      mov    ax,4C01H        ;terminate, ERRORLEVEL 1
  580.      int    21H
  581.  
  582. ;Now check cmd line for uuencoded source file.
  583. Chk_CmdLine:
  584.     call    Parse_CmdLine        ;get cmdline target filename    v1.8
  585.     jnc    Open_Inp_Fil        ;fine, got one            v1.8
  586.                     ;DI -> AsciiZed filename
  587.                     ;0 terminator.
  588.  
  589. ;Let's be nice and prompt the user for an input filename
  590. ;v1.8    using normal buffered keyboard input:
  591.  
  592. ;v2.0    First, display usage to the dummy.
  593.     mov    dx,offset usage$    ;'Usage: '
  594.     mov    cx,USAGE_LEN        ;nr chars to display
  595.     call    Say_Error        ;display to STDERR
  596.  
  597.     mov    dx,OFFSET pr_inp    ;'Input/file name:' prompt
  598.     mov    cx,PR_INP_LEN        ;nr chars to display
  599.     mov    bx,2            ;Std ErrOut handle (always to con)
  600.     mov    ah,40h            ;write to file or device
  601.     int     21h
  602.  
  603. ;Now get the user kbd input:
  604.  
  605.     mov    di,offset cmd_tail-1    ;1 byte before PSP cmdline    v1.8
  606.     mov    byte ptr [di],80    ;tell DOS max of 80 chars    v1.8
  607.     mov    dx,di            ;DX -> buffer            v1.8
  608.     mov    ah,0AH            ;buffered kbd input svc        v1.8
  609.     int    21H
  610.     call    Parse_CmdLine        ;parse the input        v1.8
  611.     jnc    Open_Inp_Fil        ;got input (already AsciiZed)    v1.8
  612.                     ;try to open            v1.8
  613.                     ;DI -> AsciiZ 0            v1.8
  614. ;Okay, he doesn't wanna play...
  615.      mov    dx,offset no_action    ;'No action'            v2.0
  616.     mov    cx,NO_ACTION_LEN    ;length                v2.0
  617.     mov    al,1            ;ERRORLEVEL 1            v2.0
  618.     jmp    Fatal_Error        ;display msg, die        v2.0
  619.  
  620.  
  621. Open_Inp_Fil:
  622.     mov    dx,offset INP_FIL    ;input file name buffer
  623.     mov    ax,3D00h        ;open file
  624.     int     21h
  625.     jb    Open_Die        ;failed, terminate w/error
  626.      mov    inp_handle,ax        ;save input file handle
  627.      ret                ;go uudecode
  628.  
  629. Open_Die:
  630.      jmp    Inp_Err            ;input file open error, die
  631. Init    endp
  632.  
  633.  
  634. ;v1.8 Command line processing subroutine
  635.  
  636. Parse_CmdLine    proc    near
  637.  
  638.     mov    si,offset cmd_tail    ;move cmd line parm
  639.     mov    di,offset INP_FIL    ;to our filename buffer
  640.     cld                ;insure fwd
  641.     lodsb                ;cmd line length byte
  642.     or    al,al            ;nothing there?
  643.     jz    PC_NoInput        ;yep, nothing there
  644.  
  645.     mov    ah,20H            ;get a handy space
  646. Strip_Ct:
  647.     lodsb                ;next cmd line char
  648.     cmp    al,ah            ;gobble leading spaces,tabs, etc.
  649.     jbe    Strip_Ct
  650. Ct_Char:
  651.     cmp    al,ah            ;ctrl char? (e.g., CR)
  652.     jbe    PC_Input        ;yep, done
  653.  
  654. ;v2.0    Check for a "-o" switch on command line
  655.  
  656.     cmp    al,'/'            ;this kind of switch?
  657.     jz    GotSwitch        ;yep
  658.      cmp    al,'-'            ;switch?
  659.      jnz    NotSwitch        ;nope, must be name char
  660. GotSwitch:
  661.     mov    dx,ax            ;save this char a second
  662.     mov    ax,[si]            ;snarf next 2 chars
  663.     cmp    al,'?'            ;-? or /?            v2.0
  664.     jz    JustHelp        ;yep, help and die        v2.0
  665.  
  666.     and    al,5FH            ;mask 1st char to uppercase
  667.     cmp    ax,' O'            ;O and space means switch
  668.     mov    ax,dx            ;restore in case not
  669.     jnz    NotSwitch        ;nope, must be name
  670.  
  671. ;v2.0    We have the overwrite switch
  672.  
  673.     not    overwrite        ;toggle flag to TRUE
  674.     inc    si            ;bump past 'o'
  675.     inc    si            ;and past space
  676.     lodsb                ;next char should be name
  677.  
  678. NotSwitch:
  679. ;end of v2.0 changes
  680.     stosb                ;stuff filename byte
  681.     lodsb                ;snarf next cmdline char
  682.     jmp    short Ct_Char        ;and loop
  683.  
  684. PC_NoInput:
  685.     stc                ;no input, return CF set
  686.     ret
  687.  
  688. PC_Input:
  689.     mov    byte ptr [di],0        ;Asciize filename input
  690.     clc                ;got input, return CF clear
  691.     ret
  692.  
  693. JustHelp:
  694.     mov    dx,offset usage$
  695.     jmp    Msg_Die            ;display, terminate
  696.  
  697. Parse_CmdLine    endp
  698.  
  699.  
  700.         EVEN
  701.  
  702. ;INP_FIL is used by Init startup, so it must sit below the code.
  703. INP_FIL    equ    $            ;80 bytes long,
  704.                     ; input filename buffer.
  705.                     ; Overwrites OUT_FIL buffer
  706.                     ; and uuencode buffers.
  707.  
  708. ;OUT_FIL, OUT_BUF, and UUBUFF aren't used until AFTER Init completes.
  709. ;They can overwrite Init code, startup data, INP_FIL filename buffer, etc.
  710. ;However, UUBUFF and LINE_IN ARE used to get the output filename OUT_FIL),
  711. ; so UUBUFF and LINE_IN can't overwrite OUT_FIL.
  712.  
  713. ;LINE_IN needs 80 bytes:
  714. OUT_FIL    equ    LINE_IN + 80        ;15 bytes long,
  715.                     ; output filename buffer.
  716.                     ; Sits below LINE_IN,
  717.                     ; overwrites Init code/data.
  718. OUT_BUF    equ    LINE_IN + 80        ;80 bytes long,
  719.                     ; uudecoded data buffer.
  720.                     ; Sits below LINE_IN,
  721.                     ; overwrites OUT_FIL filename
  722.                     ; and Init code/data.
  723. ;OUT_BUF needs 80 bytes
  724. UUBUFF    equ    OUT_BUF + 80        ; uuencoded file read buffer.
  725.                     ; Sits below OUT_BUF,
  726.                     ; uses remaining code space.
  727. ;UU200    equ    NOT(UUBUFF + 200H)    ;200H bytes oughtta be enough    v1.9
  728. UU200    equ    (offset cseg_ofs - offset UUBUFF) - 200H
  729.                     ;for the stack.
  730.  
  731. logo    db    'UUDECODE v2.0',0
  732.     db    'Originally by Theodore A. Kaldis',0
  733.     db    'Thoroughly rehacked by David P Kirschbaum, Toad Hall',0
  734.  
  735. usage$    db    'UUDECODE [-?][-o] [d:][\path\]binary.UUE <RETURN>',CR,LF
  736.     db    'Using the filename.typ in the "begin" line,',CR,LF
  737.     db    'produces uudecoded filename.typ on current drive\path',CR,LF
  738.     db    '(providing filename.typ doesn''t already exist).',CR,LF
  739.     db    '-o switch forces overwrite of existing filename.typ',CR,LF
  740.     db    '-? produces this help message.'
  741.  
  742. USAGE_LEN    equ    $ - offset usage$
  743.     db    CR,LF,'$'                    ;v2.0
  744. CSEG    ENDS
  745.     END    Uudecode
  746.