home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1992 June / SIMTEL_0692.cdr / msdos / batutl / echsys10.arc / ENVSET.ASM < prev    next >
Assembly Source File  |  1989-09-25  |  28KB  |  727 lines

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