home *** CD-ROM | disk | FTP | other *** search
/ Frostbyte's 1980s DOS Shareware Collection / floppyshareware.zip / floppyshareware / USCX / SETPGMS.ZIP / ENV_SET.ASM next >
Assembly Source File  |  1987-01-15  |  27KB  |  702 lines

  1.                  PAGE   60,132 
  2.  
  3.                  ;Usage is: call envsub  ds:si -> length,string
  4.  
  5.                  ;      length is 1 byte long, <128
  6.                  ;         if high bit on, primary environment is set.
  7.                  ;      string is of form: name=value
  8.  
  9.                  ;   Copyright 1987, A. B. Krueger GPW MI 48236
  10.                  ;   All rights reserved. Contact "ARNY KRUEGER"
  11.                  ;   at the EXEC-PC BBS (414-964-5160) for permission 
  12.                  ;   to use commercially.
  13.                  ;
  14.  
  15.                  ;Clone of SET command that demonstrates updating
  16.                  ;      the environment string.
  17.                  ;If there is no secondary command processor, the
  18.                  ;      global environment is updated
  19.                  ;If there is a secondary command processor, then
  20.                  ;      its enviroment is updated
  21.  
  22. sb               segment at 0      ;equates storage blocks and psp's
  23.  
  24. sb_kind          db     ' '        ;type of storage block: 'M' or 'Z'
  25. sb_psp           dw     ?          ;psp segment address
  26. sb_length        dw     ?          ;sb length in paragraphs
  27. sb_head_length   equ    10h        ;length of sb header
  28.  
  29.                  org    0h         ;program segement prefix equates
  30. psp_ret_int      dw     ?          ;int 20h
  31.                  org    2Ch
  32. psp_env          dw     ?          ;segment address of environment
  33.                  org    50h
  34. psp_dos_function dw     ?          ;address of function dispatcher
  35.                  org    80h
  36. psp_parm_string  db     ?          ;1 byte length plus parm string
  37.  
  38. psp_length       equ    100h
  39.  
  40. sb               ends
  41.  
  42. code_seg         segment para public
  43.                  assume cs:code_seg,ds:code_seg,es:sb
  44.                  public env_set
  45.                        
  46.                  ;local  data
  47.  
  48. cr               equ    13
  49. lf               equ    10
  50.  
  51. sb_count         dw    0            ;count of sb's encountered
  52. sb_shell         dw    0            ;segment address of shell  sb
  53. sb_shell_env     dw    0            ;segment address of global env sb
  54. sb_secondary     dw    0            ;segment address of secondary command.com
  55. sb_secondary_env dw    0            ;segment address of secondary command env
  56.  
  57. fatal_msg       equ    80h 
  58. error_msg       equ    40h 
  59. info_msg        equ    20h
  60. msg_flag        db     fatal_msg+error_msg
  61.                 db     'Copyright 1987, A. B. Krueger GPW MI 48236'
  62. secondary_msg   db     info_msg,'Secondary '
  63. command_found   db     info_msg,'COMMAND.COM found',cr,lf,'$'
  64. bad_dos_msg     db     fatal_msg,'Must be running under DOS 2.0 or above',cr,lf,'$'
  65. bad_sb_msg      db     fatal_msg,'Bad storage block',cr,lf,'$'
  66. bad_env_msg     db     error_msg,'Bad environment block',cr,lf,'$'
  67. command_lost    db     error_msg,'Shell never found',cr,lf,'$'
  68. addbadmsg       db     error_msg,'Environment corrupt',cr,lf,'$'
  69. addmsg          db     info_msg,'Addition requested',cr,lf,'$'
  70. removemsg       db     info_msg,'Removal requested',cr,lf,'$'
  71. env_set_nospace db     error_msg,'No space in environment string',cr,lf,'$'
  72. env_set_syntax  db     error_msg,'Set string syntax error',cr,lf,'$'
  73.  
  74. type_string     proc   near          ;type message at offset in dx
  75.                 push   ax            ;save registers
  76.                 push   cx
  77.                 push   dx
  78.                 push   si
  79.  
  80.                 mov    si,dx         ;get message level
  81.                 lodsb 
  82.                 and    al,msg_flag   ;compare to what sells
  83.                 jz     type_ret      ;if not on list, send to bit bucket
  84.  
  85.                 mov    dx,si
  86.                 mov    ax,0900h
  87.                 int    21h
  88. type_ret:
  89.                 pop    si
  90.                 pop    dx
  91.                 pop    cx
  92.                 pop    ax
  93.                 ret
  94. type_string     endp
  95.  
  96. get_first_sb    proc   near       ;get first storage block, point es at it
  97.                 push   ax
  98.                 push   bx
  99.                 mov    ax,5200h       
  100.                 int    21h        ;es:bx points to memory block anchor+2
  101.                 dec    bx
  102.                 dec    bx
  103.                 mov    es,es:[bx] ;get first memory block address into es
  104.                 pop    bx
  105.                 pop    ax
  106.                 ret
  107. get_first_sb    endp
  108.  
  109. get_next_sb     proc   near
  110.                 push   ax
  111.                 mov    ax,es             ;get current paragraph
  112.                 add    ax,sb_length      ;add in number of paragraphs
  113.                 inc    ax                ;add 1 for header
  114.                 mov    es,ax             ;set new extra segment address
  115.                 pop    ax
  116.                 ret
  117. get_next_sb     endp
  118.  
  119.  
  120. find_secondary_env proc  near       ;find env sb's for current program sb
  121.                 push   ax           ;pointed to by es
  122.                 push   es
  123.                 mov    ax,es        ;get address of secondary cp's sb
  124.                 inc    ax           ;get its psp address
  125. find_secondary_env_loop:
  126.                 call   get_next_sb  ;get next sb
  127.                 cmp    ax,sb_psp    ;match secondary's psp?
  128.                 jne    find_secondary_env_next    ;if not, skip
  129.  
  130.                 mov    sb_secondary_env,es        ;otherwise, save
  131.                 jmp    find_secondary_env_exit    ;and check no further
  132.                                                   ;lest we trash a .BAT block
  133. find_secondary_env_next:
  134.                 cmp    sb_kind,'Z'                ;last block?
  135.                 jne    find_secondary_env_loop
  136.  
  137. find_secondary_env_exit:
  138.                 pop    es
  139.                 pop    ax
  140.                 ret
  141. find_secondary_env endp
  142.  
  143. command_test    proc   near         ;test program storage block at es:0
  144.                 push   ax
  145.                 push   bx
  146.                 push   cx
  147.                 push   dx
  148.                 push   ds
  149.                 push   es
  150.                 push   si
  151.  
  152.                 cmp    sb_count,2
  153.                 ja     command_second
  154.  
  155.                 mov    dx,offset command_found
  156.                 call   type_string
  157.                 mov    sb_shell,es
  158.                 jmp    command_test_good
  159.  
  160. command_second: 
  161.                 cmp    sb_shell,0                       ;did we find shell?
  162.                 je     command_first_bad                ;if not, error
  163.  
  164.                 cmp    word ptr es:psp_env+sb_head_length,0  ;check environment of program
  165.                 je     command_test_good                 ;if no environment, quit
  166.  
  167.                 push   sb_shell
  168.                 pop    ds                               ;ds points to shell
  169.                 mov    al,byte ptr es:sb_head_length+psp_length 
  170.                 cmp    al,0E9h                          ;a JMP?
  171.                 jne    command_test_good                ;if not, no harm done
  172.  
  173.                 cmp    al,byte ptr ds:sb_head_length+psp_length   ;check 1st instruction 
  174.                 jne    command_first_bad
  175.  
  176.                 mov    si,sb_head_length+psp_length               
  177.                 mov    di,sb_head_length+psp_length               
  178.                 mov    cx,10      ;look at 10 words of code
  179.                 repz   cmpsw
  180.                 clc
  181.                 jcxz   command_test_found   ;if they all match, fine
  182.  
  183.                 jmp    command_test_good    ;if not, no harm done
  184.  
  185. command_test_found:
  186.                 push   cs
  187.                 pop    ds
  188.                 mov    sb_secondary,es
  189.  
  190.                 mov    ax,es:psp_env+sb_head_length     ;get env address
  191.                 dec    ax                               ;back up over sb header
  192.                 mov    sb_secondary_env,ax              ;and save it
  193.  
  194.                 call   find_secondary_env               ;look for other env's
  195.  
  196.                 mov    dx,offset secondary_msg
  197.                 call   type_string
  198.                 jmp    command_test_good
  199.  
  200. command_first_bad:
  201.                 mov    dx,offset command_lost
  202.                 call   type_string
  203.                 stc
  204.                 jmp    command_test_end
  205.  
  206. command_test_good:
  207.                 clc
  208. command_test_end:
  209.                 pop    si
  210.                 pop    es
  211.                 pop    ds
  212.                 pop    dx
  213.                 pop    cx
  214.                 pop    bx
  215.                 pop    ax
  216.  
  217.                 ret
  218. command_test    endp
  219.  
  220.  
  221.  
  222. prog_test       proc   near         ;test block for program
  223.                 push   ax           ;save registers
  224.                 push   cx
  225.                 push   dx
  226.                 push   es
  227.  
  228.                 mov    ax,sb_psp             ;get PSP of owner
  229.                 cmp    ax,0                  ;if zero, it is free
  230.                 je     prog_exit
  231.  
  232.                 cmp    ax,8                  ;if PSP of owner is at 8
  233.                 je     prog_exit             ;block owned by config.sys
  234.                 
  235.                 sub    ax,sb_head_length     ;get address of sb containg program
  236.                 cmp    ax,sb_shell           ;is owner the primary shell?
  237.                 je     prog_exit
  238.                 push   es
  239.                 pop    ax
  240.                 cmp    ax,sb_psp             ;compare to address of owner
  241.                 ja     prog_exit             ;if owner below SB, system-owned
  242.  
  243.                 add    ax,sb_length          ;add in length
  244.                 cmp    ax,sb_psp             ;compare to owner's PSP
  245.                 JB     prog_exit             ;if end below owner PSP, no program
  246.                 cmp    sb_length,10          ;is block long enough to have a psp?
  247.                 jbe    prog_exit             ;if not, no program
  248.  
  249.                 mov    ax,word ptr es:psp_dos_function+sb_head_length 
  250.                 cmp    ax,word ptr cs:psp_dos_function   ;check PSP validity  
  251.                 jne    prog_exit           
  252.  
  253.                 mov    ax,word ptr es:psp_ret_int+sb_head_length
  254.                 cmp    ax,word ptr cs:psp_ret_int     ;check PSP validity
  255.                 jne    prog_exit                ;if invalid, skip looking for env
  256.  
  257.                 call   command_test
  258.                 clc
  259. prog_exit:
  260.  
  261.                 pop    es                       ;restore registers
  262.                 pop    dx
  263.                 pop    cx
  264.                 pop    ax
  265.                 ret
  266.  
  267. prog_test       endp
  268.  
  269. sb_scan         proc   near           ;loop cx storage blocks
  270.  
  271.                 mov    al,sb_kind     ;get storage block type byte
  272.                 cmp    al,04dh        ;ordinary storage block
  273.                 je     sb_scan_got 
  274.                 cmp    al,05ah
  275.                 jne    sb_scan_bad
  276.                 mov    cx,1           ;last block
  277.  
  278. sb_scan_got:        
  279.                 inc    sb_count              ;count storage blocks
  280.  
  281.                 cmp    sb_count,3
  282.                 jne    sb_scan_not_global
  283.                       
  284.                 mov    sb_shell_env,es
  285.                 jmp    sb_scan_get
  286.  
  287. sb_scan_not_global:
  288.                 call   prog_test             ;look for program
  289.  
  290.                 loop   sb_scan_get 
  291.                 jmp    sb_scan_end
  292.  
  293. sb_scan_get:
  294.                 call   get_next_sb
  295.                 jmp    sb_scan
  296.  
  297. sb_scan_end:
  298.                 clc
  299.                 jmp    sb_scan_exit
  300.  
  301. sb_scan_bad:
  302.                 mov    al,2
  303.                 mov    dx,offset bad_sb_msg
  304.                 stc
  305.  
  306. sb_scan_exit:          
  307.                 ret
  308. sb_scan         endp
  309.  
  310.  
  311. sb_anal         proc   near           ;proc to analyze storage blocks
  312.                                       ; to find environment(s)
  313.                 push   ax
  314.                 push   cx
  315.                 push   dx             ;carry flag = error
  316.                 push   es             ;error level in al
  317.                 mov    ah,30h         ;get release number
  318.                 int    21h
  319.                 cmp    al,01h         ;above dos 1.x?
  320.                 jna    sb_bad_dos
  321.  
  322.                 cld                  ;clear direction flag
  323.                 call   get_first_sb
  324.                 mov    cx,9999        ;scan all blocks
  325.                 call   sb_scan 
  326.                 jc     sb_send_msg    ;if any errors, exit
  327.  
  328.                 jmp    sb_exit
  329.  
  330. sb_bad_dos:
  331.                 mov    al,1
  332.                 mov    dx,offset bad_dos_msg
  333.                 stc
  334.                 jmp    sb_send_msg
  335.  
  336. sb_bad_env:
  337.                 mov    al,3
  338.                 mov    dx,offset bad_env_msg
  339.                 stc
  340. sb_send_msg:             
  341.                 pushf
  342.                 call   type_string
  343.                 popf    
  344. sb_exit:
  345.                 pop    es
  346.                 pop    dx
  347.                 pop    cx
  348.                 pop    ax
  349.  
  350.                 ret
  351. sb_anal         endp
  352.  
  353. make_upper     proc    near          ;make cx bytes at es:di upper case
  354.  
  355.                push    ax            ;save registers modified
  356.                push    cx
  357.                push    di
  358.                push    ds
  359.                push    si
  360.  
  361.                push    es
  362.                pop     ds
  363.                mov     si,di
  364. make_upper_loop:
  365.                lodsb                  ;get a byte
  366.                cmp     al,'a'           ;if lower case:
  367.                jb      make_upper_next
  368.                cmp     al,'z'
  369.                ja      make_upper_next
  370.                and     al,255-'a'+'A'   ;make upper case
  371. make_upper_next:
  372.                stosb                  ;store out results
  373.                loop    make_upper_loop
  374.  
  375.                pop     si            ;restore registers
  376.                pop     ds
  377.                pop     di
  378.                pop     cx
  379.                pop     ax
  380.                ret
  381. make_upper     endp
  382.  
  383.  
  384.  
  385. env_var_name  proc     near               ;find environment variable name at
  386.               push     ax                 ;  ds:si, length in cx
  387.               push     bx                 ;at exit, ds:di points to name
  388.               push     di                 ;         name length in cx
  389.               push     es                 ;variable contents length to dx
  390.  
  391.               push     cx                 ;save length and pointer
  392.               push     si                 ;for error exits
  393.  
  394.               jcxz     env_var_name_bad   ;if length is 0, exit
  395.  
  396.  
  397.               push     cs                 ;scan works at es:di
  398.               pop      es
  399.               mov      di,si
  400.               mov      al,' '             ;scan for non-blank
  401.  
  402. env_var_strip:
  403.               repz     scasb              ;look for non-blank
  404.               jcxz     env_var_name_bad   ;if all blank, error!
  405.  
  406.               inc      cx                 ;back up over non-blank character
  407.               dec      di
  408.               mov      si,di              ;save start of non-blank string  
  409.               mov      bx,cx              ;save length
  410.  
  411.               repnz    scasb              ;look for a blank
  412.               mov      dx,di              ;save location of ' ' or end 
  413.  
  414.               mov      cx,bx              ;reset search length
  415.               mov      di,si              ;reset search pointer
  416.               mov      al,'='             ;search for equals sign
  417.               repnz    scasb
  418.               jne      env_var_name_bad   ;if not found, error
  419.  
  420.               cmp      di,dx              ;compare location of '=' and ' '
  421.               ja       env_var_name_bad   ;found ' ' first? then exit
  422.  
  423.               mov      dx,bx              ;restore search length
  424.               add      dx,si              ;add start
  425.               sub      dx,di              ;subtract where '=' was
  426.  
  427.               pop      ax                 ;pop old si from stack
  428.               pop      ax                 ;pop old cx from stack
  429.  
  430.               mov      cx,di              ;where we found '='
  431.               sub      cx,si              ;subtract string start
  432.               dec      cx                 ;minus 1 for '='
  433.               clc                         ;all is well
  434.               jmp      env_var_name_exit
  435.  
  436. env_var_name_bad:
  437.               pop      si                 ;restore pointer and length
  438.               pop      cx
  439.               xor      dx,dx              ;contents length assumed zero
  440.               stc                         ;problems  - set carry
  441.  
  442. env_var_name_exit:                       
  443.               pop      es
  444.               pop      di
  445.               pop      bx                 ;restore registers
  446.               pop      ax
  447.               ret
  448.  
  449. env_var_name  endp
  450.  
  451. get_sb_size   proc     near              ;get byte size of sb at es:0 in cx
  452.               push     ax
  453.               mov      ax,sb_length      ;get length of env in paragraphs
  454.               mov      cl,4              ;times 16
  455.               shl      ax,cl
  456.               mov      cx,ax
  457.               pop      ax
  458.               ret
  459. get_sb_size   endp
  460.  
  461. env_var_find  proc     near              ;find environment variable
  462.                                          ;named in ds:si,name length in cx 
  463.                                          ;return string start in es:di
  464.                                          ;length of entire string in cx 
  465.               push     ax                ;save registers
  466.               push     bx
  467.               push     dx
  468.  
  469.               mov      bx,cx             ;save length of name
  470.               push     es                ;save env block address      
  471.               push     ds                ;set  es:di to source string
  472.               pop      es                ;     "
  473.               mov      di,si             ;make name upper case
  474.               call     make_upper        ;altering input string
  475.               pop      es                ;restore es to environment block
  476.  
  477.               call     get_sb_size       ;get size of sb in bytes
  478.  
  479.               mov      di,sb_head_length ;start at data portion of block
  480.               mov      dx,cx             ;save block length
  481.  
  482. env_var_find_loop:
  483.               push     si                ;save string pointers
  484.               push     di
  485.  
  486.               mov      cx,bx             ;compare for length of name
  487.               mov      ah,1              ;say not compare
  488.               repz     cmpsb             ;compare item to name for name length
  489.               jne      env_var_find_next ;if not found, scan on
  490.  
  491.               cmp      byte ptr es:[di],'='   ;check next byte for '='
  492.               jne      env_var_find_next ;if found, go calc length
  493.  
  494.               mov      ah,0              ;say compare ok
  495. env_var_find_next:                      
  496.               pop      di                ;restore string pointers
  497.               pop      si                
  498.  
  499.               xor      al,al             ;look for end of current substring
  500.               mov      cx,dx             ;search remainder of string
  501.               mov      dx,di             ;save search start
  502.               repnz    scasb             ;search for a zero
  503.               jne      env_var_find_end  ;none found, error
  504.  
  505.               cmp      ah,0              ;did original compare fly?
  506.               je       env_var_find_found;if so, then pass length, etc
  507.                             
  508.               cmp      byte ptr es:[di],0  ;check next byte for zero
  509.               je       env_var_find_end  ;if found, name not found
  510.                                           
  511.               mov      dx,cx             ;save length of string remaining
  512.               jmp      env_var_find_loop ;and loop on
  513.  
  514. env_var_find_end:
  515.               xor      cx,cx             ;length = 0, none found
  516.               stc                        ;set error flag
  517.               jmp      env_var_find_exit
  518.  
  519. env_var_find_found:
  520.               mov      cx,di             ;save count of end of string
  521.               mov      di,dx             ;restore search start
  522.               sub      cx,di             ;calc length of search
  523.               dec      cx                ;less length of zero
  524.               clc                        ;no errors
  525.  
  526. env_var_find_exit:
  527.               pop      dx
  528.               pop      bx                ;restore registers
  529.               pop      ax
  530.               ret
  531. env_var_find  endp
  532.  
  533.  
  534. null_var      dw       -1
  535.  
  536. env_var_add   proc near                     ;add  environment variable
  537.                                             ;expression ->ds:si, length in cx
  538.               push    ax                    ;save registers
  539.               push    bx
  540.               push    dx
  541.  
  542.               mov     dx,offset addmsg
  543.               call    type_string
  544.               mov     bx,cx
  545.               push    si
  546.               mov     si,offset null_var  ;send on wild goose chase
  547.               mov     cx,2                ;looking for  x'ffff'
  548.               call    env_var_find        ;es:di points to end of env
  549.               pop     si
  550.               jnc     env_var_add_env_bad 
  551.                                           ;es:di now points to end of env
  552.               call    get_sb_size         ;get length of env area in cx
  553.               add     cx,sb_head_length   ;add head length for offsets
  554.               sub     cx,bx               ;deduct length of string
  555.               sub     cx,2                ;deduct length of flag
  556.               cmp     di,cx               ;compare to where we add
  557.               ja      env_var_add_bad     ;if no space, too bad
  558.  
  559.               mov     cx,bx               ;length of string to add
  560.               rep     movsb               ;do the deed
  561.               xor     ax,ax               ;make flag of two zeros
  562.               stosw                       ;add is on
  563.  
  564.               jmp     env_var_add_good 
  565.  
  566. env_var_add_env_bad:
  567.               mov     dx,offset addbadmsg
  568.               call    type_string
  569.  
  570. env_var_add_bad:
  571.               stc
  572.               jmp     env_var_add_exit
  573.  
  574. env_var_add_good:
  575.               clc
  576. env_var_add_exit:
  577.               pop     dx                  ;restore registers
  578.               pop     bx
  579.               pop     ax
  580.               ret
  581.  
  582. env_var_add   endp
  583.  
  584.  
  585. env_var_remove proc near                ;remove environment variable
  586.                                         ;at es:di, length in cx 
  587.               push    cx
  588.               push    dx
  589.               push    ds
  590.               push    di
  591.               push    si
  592.  
  593.               cld                      ;move left to right
  594.  
  595.               mov     dx,offset removemsg
  596.               call    type_string
  597.  
  598.               inc     cx                  ;add 1 for zero byte
  599.               mov     dx,cx               ;save length of var
  600.               call    get_sb_size         ;cx gets length of env area
  601.               add     cx,sb_head_length   ;add header length for offsets
  602.               sub     cx,di               ;deduct where we start
  603.               sub     cx,dx               ;deduct length of removed variable
  604.  
  605.               mov     si,di               ;move from next variable
  606.               add     si,dx               ;add my length
  607.                 
  608.               push    es                  ;do all the work in es:
  609.               pop     ds
  610.  
  611.               rep     movsb               ;do the move
  612.                 
  613.               pop     si
  614.               pop     di
  615.               pop     ds
  616.               pop     dx
  617.               pop     cx
  618.               ret
  619. env_var_remove  endp
  620.  
  621.  
  622. env_set       proc    near                ;change environment per ds:si
  623.               push    ax                  
  624.               push    bx                  ;ds:si points to:
  625.               push    cx                  ; length  db  ?
  626.               push    di
  627.               push    ds                  ; data    db  'name=value'
  628.               push    es
  629.               push    si
  630.  
  631.               xor     ax,ax               ;set length of local set string
  632.               lodsb                       ;get length, push di forward
  633.               mov     cx,ax               ;length of set string in cx
  634.               and     cl,0ffh-80h         ;length < 128 
  635.               call    sb_anal             ;analyze the storage block chain
  636.                                           ;to find command processor(s)
  637.  
  638.               and     al,80h              ;was use primary switch on?
  639.               jnz     env_set_shell       ;if so, skip secondaries
  640.  
  641.               cmp     sb_secondary_env,0  ;is there a secondary command proc?
  642.               je      env_set_shell       ;if not, use primary
  643.  
  644.               mov     es,sb_secondary_env ;command processor is secondary
  645.               jmp     env_set_command
  646.  
  647. env_set_shell:                            ;command processor is shell
  648.               mov     es,sb_shell_env
  649. env_set_command:  
  650.               call    env_var_name        ;find what we want set at call
  651.                                           ;ds:si -> expression, cx has length
  652.                                           ;at return ds:si -> name
  653.                                           ;cx is length of name
  654.               jc      env_set_syntax_err  ;if not found, error             
  655.  
  656.               mov     bx,cx               ;calculate new length of set string
  657.               inc     bx                  ;add 1 for '='
  658.               add     bx,dx               ;add length of set string
  659.  
  660.               call    env_var_find        ;find variable in environment block
  661.                                           ;at return, es:di -> start of env str
  662.                                           ;cx is length of env str
  663.               jc      env_set_add         ;if not found, just add
  664.  
  665.               call    env_var_remove      ;remove variable at es:di from env
  666.               cmp     dx,0                ;check out length of data to add
  667.               je      env_set_exit        ;if zero, just exit
  668.  
  669. env_set_add:                              
  670.               mov     cx,bx               ;restore length of variable
  671.               call    env_var_add         ;add new variable to set string
  672.               jc      env_set_no_space
  673.               jmp     env_set_exit
  674.  
  675. env_set_no_space:
  676.               mov     dx,offset env_set_nospace
  677.               jmp     env_set_type
  678.  
  679. env_set_syntax_err:
  680.               mov     dx,offset env_set_syntax
  681. env_set_type:
  682.               push    cs
  683.               pop     ds
  684.               call    type_string
  685. env_set_error:
  686.               stc
  687. env_set_exit:
  688.               pop     si
  689.               pop     es
  690.               pop     ds
  691.               pop     di
  692.               pop     cx
  693.               pop     bx
  694.               pop     ax
  695.               ret
  696. env_set       endp
  697.  
  698. code_seg      ends   
  699.               end     
  700.  
  701. 
  702.