home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / SYSUTL / SETENVJW.ZIP / SETENV.ASM next >
Encoding:
Assembly Source File  |  1991-06-15  |  36.6 KB  |  1,680 lines

  1. title Set Environment Variable Program.
  2. page 60,120            ; page length = 60
  3.                 ; page width  = 120
  4. ;
  5. ;    This program places a variable in the environment.
  6. ;
  7. ;    SETENV : Copyright (c) 1988 to 1991 by John Wolchak.  
  8. ;      I give permission to alter the code, but not to copy 
  9. ;      or redistribute the altered code without my explicit 
  10. ;      permission.  If you alter the code, please document 
  11. ;      changes and send me a copy, so all can have it.  The 
  12. ;      file Setenv.Doc must always accompany the SETENV 
  13. ;      program when a copy is made for another machine.  
  14. ;      This code, to the best of my knowledge works well.  
  15. ;      I disclaim any responsibility for the codes actions 
  16. ;      (use at your own risk).  
  17. ;
  18. ;    John Wolchak.
  19. ;    56 Physics Building
  20. ;    University of Saskatchewan.
  21. ;    Saskatoon, Saskatchewan
  22. ;    Canada     S7K 0W0
  23. ;    Phone: (306) 966-4852
  24. ;    NetNorth (BITNET): Wolchak@Sask
  25. ;    Inter_Network: Wolchak@Admin.Usask.Ca
  26. ;
  27. ;    To assemble:
  28. ;    masm setenv,,,
  29. ;    link setenv,,,
  30. ;    exe2bin setenv.exe setenv.com
  31. ;
  32. code segment
  33. assume cs:code,ds:code
  34. org 100h
  35.  
  36. start:        jmp beginning
  37. ;
  38. ;        Data Area
  39. ;
  40. exit_code    db    03h        ; Environment variable created.
  41.                     ; PSP is Program Segment Prefix.
  42. cpsp        dw    00h        ; The psp of command.com.
  43. env_off        dw    00h        ; Environment offset address.
  44. env_siz        dw    00h        ; Environment size in bytes.
  45. dos_maj        db    00h        ; DOS major version.
  46. dos_min        db    00h        ; DOS minor version.
  47. set        db    "set "
  48. s_rce        dw    03h        ; Size of Root Comm Env.
  49. l_rce        db    "rce"
  50. u_rce        db    "RCE"
  51. v_rce        dw    00h        ; RCE value.
  52. a_rce        dw    00h        ; Segment address.
  53. ;d_rce        db    0ffh dup(0)    ; Data string of Set command.
  54. s_data        dw    00h        ; Size of environment data.
  55. a_env_var    dw    00h        ; Address of environment variable.
  56. s_env_var    dw    00h        ; Environment variable size.
  57. ;d_env_var    db    0ffh dup(0)    ; Environment data.
  58. ;null        db    00h,00h        ; Environment tail.
  59. y_prompt    dw    08h        ; Size of '%prompt '.
  60. x_prompt    dw    06h        ; Size.
  61. l_prompt    db    "prompt"
  62. u_prompt    db    "PROMPT"
  63. o_prompt    dw    00h        ; Offset of prompt.
  64. s_def        dw    03h        ; Size of default.
  65. l_def        db    "def"
  66. u_def        db    "DEF"
  67. x_def        dw    00h        ; Default value size.
  68. ;v_def        dw    100 dup(0)    ; Default value.
  69. s_echo        dw    06h        ; Size of echo.
  70. l_echo        db    "noecho"
  71. u_echo        db    "NOECHO"
  72. v_echo        dw    00h        ; Echo on.
  73. s_upper        dw    05h        ; Size of upper.
  74. l_upper        db    "upper"
  75. u_upper        db    "UPPER"
  76. v_upper        dw    00h        ; Upper case on.
  77. o_tmp        dw    00h        ; Save temporary address.
  78. s_timo        dw    05h        ; Size of timo.
  79. l_timo        db    "timo="
  80. u_timo        db    "TIMO="
  81. v_timo        dw    00h        ; Time out infinit.
  82. c_brk        db    00h        ; Control break status.
  83. d_ent        db    00h        ; Entry days.
  84. h_ent        db    00h        ; Entry hours.
  85. m_ent        db    00h        ; Entry minutes.
  86. s_ent        db    00h        ; Entry seconds.
  87. d_stt        db    00h        ; Stop time day.
  88. h_stt        db    00h        ; Stop time hours.
  89. m_stt        db    00h        ; Stop time minutes.
  90. s_stt        db    00h        ; Stop time seconds.
  91. f_stt        db    00h        ; Stop flag exit type.
  92. s_rep        dw    03h        ; Size of replace.
  93. l_rep        db    "rep"
  94. u_rep        db    "REP"
  95. v_rep        dw    00h
  96. w_rep        dw    00h        ; Replace old value size.
  97. ;x_rep        dw    100 dup(0)    ; Replace old value.
  98. y_rep        dw    00h        ; Replace new value size.
  99. ;z_rep        dw    100 dup(0)    ; Replace new value.
  100. s_chgup        dw    05h        ; Size of Change upper.
  101. l_chgup        db    "chgup"
  102. u_chgup        db    "CHGUP"
  103. v_chgup        dw    00h        ; Change upper flag.
  104. s_dosv        dw    04h        ; Size of Dos Major.
  105. l_dosv        db    "dosv"
  106. u_dosv        db    "DOSV"
  107. s_dosm        dw    04h        ; Size of Dos Minor.
  108. l_dosm        db    "dosm"
  109. u_dosm        db    "DOSM"
  110. s_cwd        dw    03h        ; Size of Current directory.
  111. l_cwd        db    "cwd"
  112. u_cwd        db    "CWD"
  113. ;d_cwd        db    0ffh dup(0)    ; Data area (temporary).
  114. s_time        dw    04h        ; Current time.
  115. l_time        db    "time"
  116. u_time        db    "TIME"
  117. s_date        dw    04h        ; Current date.
  118. l_date        db    "date"
  119. u_date        db    "DATE"
  120. z_date        db    "1"        ; Date format.
  121. s_drive        dw    05h        ; Size of drive.
  122. l_drive        db    "drive"
  123. u_drive        db    "DRIVE"
  124. s_path        dw    05h        ; Size of Path.
  125. d_path        db    "PATH="
  126. s_comspec    dw    08h        ; Size of Comspec.
  127. d_comspec    db    "COMSPEC="
  128. s_prompt    dw    07h        ; Size of Prompt=.
  129. d_prompt    db    "PROMPT="
  130. s_setenv    dw    07h        ; Size of Setenv=.
  131. d_setenv    db    "SETENV="
  132. author        db    "Set Environment Variable Program V1.6 (c) 15-Jun-1991 "
  133.         db    "by John Wolchak.",13,10
  134. d_cwd        db    "Usage is:  SETENV <variable> <value>",13,10,9,9
  135.         db    "<variable> by it's self to erase variable.",13,10,9,9
  136.         db    "<value> can be: '%rep<del><txt1><del><txt2><del>' text replace."
  137.         db    13,10,9,9
  138.         db    "<value> can be: '%chgup' upper case environment variable data."
  139.         db    13,10,9,9
  140.         db    "  '%prompt %noecho %upper %def<del><text><del> <message>'."
  141.         db    13,10,9,9
  142. d_rce        db    "     '%noecho' for no echo, '%upper' for upper case only."
  143.         db    13,10,9,9
  144.         db    "     '%def<del><text><del>' to supply a default."
  145.         db    13,10,9,9
  146.         db    "     '%timo=hh:mm:ss' prompt time out, time length."
  147.         db    13,10,9,9
  148.         db    "<value> can include keys such as:",13,10,9,9
  149.         db    "  %dosv / %dosm for DOS major / minor version."
  150.         db    13,10,9,9
  151. v_def        db    "  %time / %daten for current time / date format 'n'."
  152.         db    13,10,9,9
  153.         db    "  %cwd for current directory,   %drive for drive letter."
  154.         db    13,10,9,9
  155. x_rep        db    "  %+n / %-n for default drive plus / minus 'n'."
  156.         db    13,10
  157.         db    "Root environment change usage: SETENV %rce <variable> <value>"
  158.         db    13,10
  159. z_rep        db    "Example:  setenv drivedir %drive:%cwd  ",13,10
  160.         db    "Note:     Use %% to represent a single % in BAT files."
  161.         db    13,10
  162.         db    "       SETENV return codes:",9,9
  163. d_env_var    db    "no command, help issued     00h",13,10
  164.         db    "root environment set        01h",9
  165.         db    "environment variable erased    02h",13,10
  166.         db    "environment variable created    03h",9
  167.         db    "environment space over written    04h",13,10
  168.         db    "environment variable updated    05h",9
  169.         db    "unmatched delimiter        06h",13,10
  170.         db    "don't know about MS-DOS V1.x    07h",9
  171.         db    "environment variable not found    08h",13,10
  172.         db    "offset drive will be invalid    09h",9
  173.         db    "environment space is full    10h"
  174.         db    "$"
  175. ;
  176. ;    If the help is changed then the variables d_cwd, d_rce
  177. ;        v_def, x_rep, z_rep, and d_env_var need to be
  178. ;        changed to  the size of the comments above.
  179. ;        v_def, x_rep, and z_rep are approximately 100
  180. ;        d_cwd, d_rce, and d_env_var are approximately 255
  181. ;        remember the DOS command line is 123 and you can %rep///
  182. ;
  183. ;        Code Area
  184. ;
  185. Beginning:
  186.         mov sp, offset stack    ; Set up local stack.
  187.         mov si, 80h        ; Offset of command line.
  188.         lodsb            ; Get a byte.
  189.         cmp al, 00h        ; Is there any data.
  190.         jnz get_ver        ; Yes. Jump.
  191. dis_help:
  192.         mov dx, offset author    ; Help message.
  193.         mov ah, 09h        ; Display it.
  194.         int 21h
  195.         mov exit_code, 00h    ; No command, help issued.
  196.         jmp nor_term        ; Exit.
  197.  
  198. get_ver:    
  199.         mov ah, 30h        ; Get DOS version number.
  200.         int 21h
  201.  
  202.         mov dos_maj, al
  203.         mov dos_min, ah
  204.  
  205.         cmp ah, 01h
  206.         jnz cont
  207.         mov exit_code, 07h    ; No MS-DOS version 1.x.
  208.         jmp nor_term        ; Exit.
  209.  
  210. ;        Get rid of leading spaces and tabs.
  211. cont:
  212.         lodsb            ; Get a byte.
  213.         cmp al, " "        ; Is it a leading blank.
  214.         jz cont            ; Yes.  Loop.
  215.         cmp al, 09h        ; Is it a leading tab.
  216.         jz cont            ; Yes.  Loop.
  217.         cmp al, "%"        ; Is it a special one.
  218.         jz rce            ; Yes.  Use it.
  219.         cmp al, 0dh        ; Is it a carriage return.
  220.         jz dis_help        ; Yes. dis_help.
  221. cont_on:
  222.         dec si
  223.         jmp var
  224.  
  225. rce:
  226. ;        Handle %rce.
  227.         push si
  228.         mov di, si        ; Set destination.
  229.         mov si, offset l_rce    ; Set source.
  230.         mov cx, s_rce
  231.         rep cmpsb        ; Is it %rce.
  232.         jz set_rce        ; Yes, Jump out.
  233.  
  234.         pop si
  235.         push si
  236.         mov di, si        ; Set destination.
  237.         mov si, offset u_rce    ; Set source.
  238.         mov cx, s_rce
  239.         rep cmpsb        ; Is it %RCE.
  240.         jz set_rce        ; Yes, Jump out.
  241.  
  242.         pop si
  243.         jmp cont_on
  244. set_rce:
  245.         pop si
  246.         inc si
  247.         inc si
  248.         inc si
  249.         mov v_rce, 01h        ; Root Command Environment.
  250.  
  251. ;        Get rid of leading spaces and tabs.
  252. var:
  253.         lodsb            ; Get a byte.
  254.         cmp al, " "        ; Is it a leading blank.
  255.         jz var            ; Yes.  Loop.
  256.         cmp al, 09h        ; Is it a leading tab.
  257.         jz var            ; Yes.  Loop.
  258.  
  259.         dec si            ; Backup for the character.
  260.         mov a_env_var, si    ; Offset of the variable.
  261.         mov di, offset d_env_var ; Offset of env. variable.
  262.  
  263. ;        Get the variable name,
  264. ;        and convert to upper case.
  265. get_var:
  266.         lodsb            ; Get a byte.
  267.         cmp al, " "        ; Is it the end of the variable?
  268.         jz var_end        ; Yes.  Jump out.
  269.         cmp al, 09h        ; Is it the end of the variable?
  270.         jz var_end        ; Yes.  Jump out.
  271.         cmp al, "="        ; Is it the end of the variable?
  272.         jz var_end        ; Yes. Jump out.
  273.         cmp al, 0dh        ; Is it the end.
  274.         jz no_data        ; Yes. We got it.
  275.         cmp al, "z"        ; Is
  276.         jg not_lower        ;   it
  277.         cmp al, "a"        ;     lower
  278.         jb not_lower        ;       case?
  279.         sub al, 20h        ; Make it upper case.
  280. not_lower:
  281.         stosb            ; Save the byte.
  282.         jmp get_var
  283.  
  284. no_data:
  285.         mov al, 0dh
  286.         mov [si], al
  287. var_end:
  288.         mov al, "="        ; Set the end of variable.
  289.         stosb            ; Save it.
  290.         mov -1[si], al        ; And the command line.
  291.  
  292.         mov ax, si        ; Get the offset.
  293.         mov bx, a_env_var    ; Beginning of the variable.
  294.         sub ax, bx        ; Get the variable lenght.
  295.         mov s_env_var, ax    ; And save it.
  296.  
  297. var_end1:
  298.         lodsb            ; Get a byte.
  299.         cmp al, " "        ; Is it a blank.
  300.         jz var_end1        ; Loop.
  301.         cmp al, 09h        ; Is it a tab.
  302.         jz var_end1        ; Loop.
  303.         dec si
  304.  
  305.         mov al, [si]        ; Get a byte.
  306.         cmp al, "%"        ; Is it a special one.
  307.         jz prompt        ; Yes. Jump out.
  308.  
  309. ;        Get the data part.
  310. get_data:
  311.         mov al, [si]        ; Get a byte.
  312.         cmp al, "%"        ; Is it a special one.
  313.         jz percent_near        ; Yes. Jump out.
  314. get_next:
  315.         lodsb            ; Get a byte.
  316.         cmp al, 0dh        ; Is it the end.
  317.         jz data_end_near    ; Yes. We got it.
  318.         stosb            ; Save the byte.
  319.         jmp get_data
  320.  
  321. data_end_near:
  322.         jmp data_end
  323. percent_near:
  324.         jmp percent
  325.  
  326. ;        Handle %prompt.
  327. prompt:
  328.         mov o_prompt, si
  329.         inc si
  330.         push di
  331.         push si
  332.  
  333.         mov di, si        ; Set destination.
  334.         mov si, offset l_prompt    ; Set Source.
  335.         mov cx, x_prompt
  336.         rep cmpsb        ; Is it %prompt.
  337.         jz sub_fun_near        ; Yes.
  338.  
  339.         pop si
  340.         push si
  341.         mov di, si        ; Set destination.
  342.         mov si, offset u_prompt    ; Set source.
  343.         mov cx, x_prompt
  344.         rep cmpsb        ; Is it %PROMPT.
  345.         jz sub_fun_near        ; Yes.
  346.  
  347. ;        Then check for replace
  348.         jmp replace
  349.  
  350. sub_fun_near:
  351.         jmp sub_fun
  352.  
  353. get_prompt:
  354.         pop si
  355.         push si
  356.         dec si
  357.  
  358.         mov ax, si        ; Jump
  359.         mov cx, y_prompt    ;   the
  360.         add ax, cx        ;     %prompt
  361.         mov si, ax        ;       string.
  362.  
  363. ;        Display the prompt.
  364. prompt1:
  365.         lodsb            ; Scan for
  366.         cmp al, 0dh        ;   a return.
  367.         jz prompt2
  368.  
  369.         mov dl, al        ; Output Character.
  370.         mov ah, 02h
  371.         int 21h
  372.         jmp prompt1
  373. prompt2:
  374.         pop si
  375.         push si
  376.         mov di, si
  377.         mov bx, di
  378.  
  379. ;        Check do we time out.
  380.         cmp v_timo, 00h        ; Do we timeout?
  381.         jnz check0        ; Yes. Jumpout.
  382.         jmp prompt3
  383.  
  384. check0:
  385. ;        Get the current time, and set the stop time.
  386.         mov ah, 2ch        ; Get the
  387.         int 21h            ;   current time.
  388.         mov dl, d_ent        ; No day.
  389.  
  390.         add dh, s_ent        ; Add the seconds
  391.         cmp dh, 3ch
  392.         jb get0
  393.         sub dh, 3ch        ; and correct.
  394.         inc cl
  395. get0:
  396.         add cl, m_ent        ; Add the minutes
  397.         cmp cl, 3ch
  398.         jb get1
  399.         sub cl, 3ch        ; and correct.
  400.         inc ch
  401. get1:
  402.         add ch, h_ent        ; Add the hours
  403.         cmp ch, 18h
  404.         jb get2
  405.         sub ch, 18h        ; and correct.
  406.         inc dl            ; New day.
  407. get2:
  408.         mov s_stt, dh        ; Save
  409.         mov m_stt, cl        ;   the
  410.         mov h_stt, ch        ;     stop
  411.         mov d_stt, dl        ;       time.
  412. ;        end of get and set time.
  413.  
  414. ;        Get and check time.
  415.         mov al, 00h        ; Set for
  416.         mov f_stt, al        ;   read input.
  417.  
  418.         mov ah, 33h        ; Check Ctrl-Break.
  419.         mov al, 00h
  420.         int 21
  421.         mov c_brk, dl        ; Save current setting.
  422.         mov ah, 33h        ; Set Ctrl-Break.
  423.         mov al, 01h
  424.         mov dl, 01h
  425.         int 21
  426. check1:
  427.         mov ah, 0bh        ; Check
  428.         int 21h            ;   input
  429.         cmp al, 00h        ;     waiting.
  430.         jnz check9        ; Yes. Jump out.
  431.  
  432.         mov ah, 2ch        ; Get the
  433.         int 21h            ;   current time.
  434.  
  435.         cmp d_stt, 00h        ; Over a midnight?
  436.         jz check3
  437.         cmp ch, 00h        ; New hour?
  438.         jnz check1
  439.         cmp cl, 00h        ; New minute?
  440.         jnz check1
  441.         cmp dh, 00h        ; New second?
  442.         jnz check1
  443.         cmp dl, 00h        ; New hundredth second?
  444.         jz check1
  445.         mov al, d_stt        ; Decrement
  446.         dec al            ;   a day
  447.         mov d_stt, al        ;     and save.
  448. check2:
  449.         mov ah, 2ch        ; Get the
  450.         int 21h            ;   current time.
  451.  
  452.         cmp dh, 00h        ; Loop until
  453.         jz check2        ;   the second changes.
  454.  
  455.         jmp check1
  456.  
  457. check3:
  458.         cmp ch, h_stt        ; Correct hour?
  459.         jb check1        ; No. Loop.
  460.         cmp cl, m_stt        ; Correct minute?
  461.         jb check1        ; No. Loop.
  462.         cmp dh, s_stt        ; Correct second?
  463.         jb check1        ; No. Loop.
  464.         mov al, 01h        ; Set for
  465.         mov f_stt, al        ;   timeout.
  466.  
  467. check9:
  468.         mov ah, 33h        ; Restore Ctrl-Break.
  469.         mov al, 01h
  470.         mov dl, c_brk
  471.         int 21
  472.  
  473.         cmp f_stt, 00h        ; Is someone typing?
  474.         jz prompt3        ; Yes. Jump out.
  475.         mov al, 0dh        ; Fake carriage return read
  476.         jmp prompt7
  477.  
  478. ;        end of check time.
  479.  
  480. prompt3:
  481. ;        Read the response.
  482.         mov ah, 08h        ; Read keyboard.
  483.         int 21h
  484.  
  485.         cmp v_upper, 01h    ; Upper case on.
  486.         jnz not_upper
  487.         cmp al, "z"        ; Is
  488.         jg not_upper        ;   it
  489.         cmp al, "a"        ;     lower
  490.         jb not_upper        ;       case?
  491.         sub al, 20h        ; Make it upper case.
  492. not_upper:
  493.  
  494.         cmp al, 08h        ; Got a backspace character.
  495.         jz prompt4
  496.         cmp al, 7fh        ; Got a delete character.
  497.         jnz prompt6
  498.  
  499. prompt4:
  500.         mov dx, di        ; Current pointer.
  501.         cmp bx, dx        ; Have we moved?
  502.         jz prompt3        ; No. Jump.
  503.  
  504.         cmp v_echo, 00h        ; Do we echo the character.
  505.         jnz prompt5
  506.  
  507.         mov dl, 08h        ; Print a backspace.
  508.         mov ah, 02h
  509.         int 21h
  510.  
  511.         mov dl, " "        ; Print a space.
  512.         mov ah, 02h
  513.         int 21h
  514.  
  515.         mov dl, 08h        ; Print a backspace.
  516.         mov ah, 02h
  517.         int 21h
  518.  
  519. prompt5:
  520.         dec di
  521.         cmp v_echo, 00h        ; Do we echo the character.
  522.         jmp prompt3
  523.  
  524. prompt6:
  525.         cmp v_echo, 00h        ; Do we echo the character.
  526.         jnz prompt7
  527.  
  528.         mov dl, al        ; Output Character.
  529.         mov ah, 02h
  530.         int 21h
  531.  
  532. prompt7:
  533.         stosb            ; Save the byte.
  534.         cmp al, 0dh        ; Got a return.
  535.         jnz prompt3
  536.  
  537.         mov dl, 0dh        ; Print a return.
  538.         mov ah, 02h
  539.         int 21h
  540.         mov dl, 0ah        ; Print a linefeed.
  541.         mov ah, 02h
  542.         int 21h
  543.  
  544.         pop si
  545.         push si
  546.         mov al, [si]
  547.         cmp al ,0dh        ; Is it a return.
  548.         jnz prompt9        ; No.  Jump out.
  549.  
  550.         mov di, si        ; Move
  551.         mov si, offset v_def    ;   the default
  552.         mov cx, x_def        ;     in place.
  553.         rep movsb
  554.  
  555.         mov al, 0dh
  556.         stosb
  557. prompt9:
  558.         pop si
  559.         pop di
  560.  
  561.         jmp get_data
  562.  
  563. ;        white space in front of function
  564. sub_fun:
  565.         mov si, di
  566. sub_fun0:
  567.         lodsb
  568.         mov o_tmp, si
  569.         cmp al, " "        ; Is it space?
  570.         jz sub_fun0        ; Yes. Ignore.
  571.         cmp al, 09h        ; Is it a tab?
  572.         jz sub_fun0        ; Yes. Ignore.
  573.         cmp al, "%"        ; Is it a special one.
  574.         jz echo         ; Yes.  Use it.
  575. sub_fun1:
  576.         dec si
  577.         mov ax, si        ; Get current pointer.
  578.         mov bx, o_prompt    ; Get prompt value start.
  579.         sub ax, bx        ; To get prompt noise length.
  580.         mov y_prompt, ax    ; Save it.
  581.  
  582.         jmp get_prompt
  583.  
  584.  
  585. ;        Handle %noecho.
  586. echo:
  587.         mov si, o_tmp        ; Set destination.
  588.         mov di, offset l_echo    ; Set Source.
  589.         mov cx, s_echo
  590.         rep cmpsb        ; Is it %noecho.
  591.         jz get_echo        ; Yes.
  592.  
  593.         mov si, o_tmp        ; Set destination.
  594.         mov di, offset u_echo    ; Set source.
  595.         mov cx, s_echo
  596.         rep cmpsb        ; Is it %NOECHO.
  597.         jz get_echo        ; Yes.
  598.  
  599.         jmp upper
  600.  
  601. get_echo:
  602.         mov v_echo, 01h        ; Set no echo.
  603.         jmp sub_fun0
  604.  
  605. ;        Handle %upper.
  606. upper:
  607.         mov si, o_tmp        ; Set destination.
  608.         mov di, offset l_upper    ; Set Source.
  609.         mov cx, s_upper
  610.         rep cmpsb        ; Is it %upper.
  611.         jz get_upper        ; Yes.
  612.  
  613.         mov si, o_tmp        ; Set destination.
  614.         mov di, offset u_upper    ; Set source.
  615.         mov cx, s_upper
  616.         rep cmpsb        ; Is it %UPPER.
  617.         jz get_upper        ; Yes.
  618.  
  619.         jmp timo
  620.  
  621. get_upper:
  622.         mov v_upper, 01h    ; Set upper case.
  623.         jmp sub_fun0
  624.  
  625. ;        Handle %timo.
  626. timo:
  627.         mov si, o_tmp        ; Set destination.
  628.         mov di, offset l_timo    ; Set Source.
  629.         mov cx, s_timo
  630.         rep cmpsb        ; Is it %timo.
  631.         jz get_timo        ; Yes.
  632.  
  633.         mov si, o_tmp        ; Set destination.
  634.         mov di, offset u_timo    ; Set source.
  635.         mov cx, s_timo
  636.         rep cmpsb        ; Is it %TIMO.
  637.         jz get_timo        ; Yes.
  638.  
  639.         jmp default
  640.  
  641. get_timo:
  642. ;        mov si, di
  643. timo1:
  644.         lodsb
  645.         cmp al, ":"        ; Time
  646.         jz timo2        ;   dividers
  647.         cmp al, "."        ;     semi-colon
  648.         jz timo2        ;       and period.
  649.         cmp al, "-"
  650.         jz timo2
  651.  
  652.         cmp al, "0"        ; Is
  653.         jb timo3        ;   it
  654.         cmp al, "9"        ;     a 
  655.         jg timo3        ;       digit?
  656.  
  657.         sub al, 30h        ; Make it binary.
  658.         mov bh, al        ; Temp. save it.
  659.         mov al, s_ent        ; Get the seconds.
  660.         mov bl, 0ah        ; Multiply 
  661.         mul bl            ;   by ten.
  662.         add al, bh        ; Add next digit.
  663.         mov s_ent, al        ; Save the seconds.
  664.         jmp timo1
  665.  
  666. timo2:
  667.         mov al, h_ent
  668.         mov d_ent, al
  669.         mov al, m_ent        ; Roll
  670.         mov h_ent, al        ;   over
  671.         mov al, s_ent        ;     the time
  672.         mov m_ent, al        ;       components.
  673.         mov al, 00h
  674.         mov s_ent, al
  675.         jmp timo1
  676.  
  677. timo3:
  678.         mov v_timo, 01h        ; Set time out.
  679.         dec si
  680.         jmp sub_fun0
  681.  
  682. ;        Handle %def.
  683. default:
  684.         mov si, o_tmp        ; Set destination.
  685.         mov di, offset l_def    ; Set Source.
  686.         mov cx, s_def
  687.         rep cmpsb        ; Is it %def.
  688.         jz get_default        ; Yes.
  689.  
  690.         mov si, o_tmp        ; Set destination.
  691.         mov di, offset u_def    ; Set source.
  692.         mov cx, s_def
  693.         rep cmpsb        ; Is it %DEF.
  694.         jz get_default        ; Yes.
  695.  
  696.         mov si, o_tmp
  697.         jmp sub_fun1
  698.  
  699. get_default:
  700.         lodsb            ; Get the delimiter.
  701.         mov dl, al        ; Save it.
  702.         mov di, offset v_def    ; Get address for save of value.
  703.         mov x_def, si        ; Save the start of the value.
  704. default1:
  705.         lodsb            ; Get a byte.
  706.         cmp al, 0dh        ; Is it a return?
  707.         jz default2        ; Yes. Jump out.
  708.  
  709.         cmp al, dl        ; Is it the delimiter?
  710.         jz default3        ; Yes. Jump out.
  711.         stosb            ; Save it.
  712.         jmp default1
  713. default2:
  714.         mov -1[si], dl        ; No
  715.         mov ah, " "        ;   delimiter
  716.         mov [si], ah        ;     so
  717.         mov ah, ">"        ;       create
  718.         mov 1[si], ah        ;         the
  719.         mov 2[si], al        ;           info.
  720.         dec si
  721.         mov cs:[exit_code], 06h    ; Unmatched delimter.
  722.         jmp default1
  723.  
  724. default3:
  725.         mov ax, si        ; Get current pointer.
  726.         mov bx, x_def        ; Get default value start.
  727.         sub ax, bx        ; To get lenght of default value.
  728.         dec ax
  729.         mov x_def, ax        ; Save it.
  730.  
  731.         jmp sub_fun0
  732.  
  733. ;        Handle %rep.
  734. replace:
  735.         pop si
  736.         push si
  737.         mov di, si        ; Set destination.
  738.         mov si, offset l_rep    ; Set Source.
  739.         mov cx, s_rep
  740.         rep cmpsb        ; Is it %rep.
  741.         jz get_replace        ; Yes.
  742.  
  743.         pop si
  744.         push si
  745.         mov di, si        ; Set destination.
  746.         mov si, offset u_rep    ; Set Source.
  747.         mov cx, s_rep
  748.         rep cmpsb        ; Is it %REP.
  749.         jz get_replace        ; Yes.
  750.  
  751.         jmp chgup        ; No. Jump out.
  752.  
  753. get_replace:
  754.         mov si, di
  755.         lodsb            ; Get the delimiter.
  756.         mov dl, al        ; Save it.
  757.         mov di, offset x_rep    ; Get address for save of value.
  758.         mov cx, 00h
  759. replace1:
  760.         lodsb            ; Get a byte.
  761.         cmp al, 0dh        ; Is it a return?
  762.         jz replace2        ; Yes. Jump out.
  763.  
  764.         cmp al, dl        ; Is it the delimiter?
  765.         jz replace3        ; Yes. Jump out.
  766.         stosb            ; Save it.
  767.         inc cx            ; Increment the count
  768.         jmp replace1
  769. replace2:
  770.         dec si
  771.         mov cs:[exit_code], 06h    ; Unmatched delimter.
  772. ;        You could take out the next line.
  773.         jmp nor_term        ; Exit.
  774.  
  775. replace3:
  776.         mov w_rep, cx        ; Save size.
  777.         mov di, offset z_rep    ; Get address for save of value.
  778.         mov cx, 00h
  779. replace4:
  780.         lodsb            ; Get a byte.
  781.         cmp al, 0dh        ; Is it a return?
  782.         jz replace5        ; Yes. Jump out.
  783.  
  784.         cmp al, dl        ; Is it the delimiter?
  785.         jz replace6        ; Yes. Jump out.
  786.         stosb            ; Save it.
  787.         inc cx            ; Increment the count
  788.         jmp replace4
  789.  
  790. replace5:
  791.         dec si
  792.         mov cs:[exit_code], 06h    ; Unmatched delimter.
  793. replace6:
  794.         mov y_rep, cx        ; Save size.
  795.         mov v_rep, 0ffh        ; Flag the replace.
  796.  
  797.         pop si
  798.         pop di
  799.         inc si
  800.         jmp data_end
  801.  
  802. ;        Handle %chgup.
  803. chgup:
  804.         pop si
  805.         push si
  806.         mov di, si        ; Set destination.
  807.         mov si, offset l_chgup    ; Set Source.
  808.         mov cx, s_chgup
  809.         rep cmpsb        ; Is it %chgup.
  810.         jz get_chgup        ; Yes.
  811.  
  812.         pop si
  813.         push si
  814.         mov di, si        ; Set destination.
  815.         mov si, offset u_chgup    ; Set Source.
  816.         mov cx, s_chgup
  817.         rep cmpsb        ; Is it %CHGUP.
  818.         jz get_chgup        ; Yes.
  819.  
  820.         pop si
  821.         pop di
  822.         dec si
  823.         jmp get_data        ; No. Jump out.
  824.  
  825. get_chgup:
  826.         mov v_chgup, 0ffh
  827.         pop si
  828.         pop di
  829.         inc si
  830.         jmp data_end
  831.  
  832. percent:
  833.         mov al, 1[si]
  834.         cmp al, "+"        ; Is it a plus.
  835.         jz off_drive
  836.  
  837.         cmp al, "-"        ; Is it a minus.
  838.         jnz cwd
  839.  
  840. ;        Offset from a given drive.
  841. off_drive:
  842.         mov dh, al        ; Save the sign.
  843.         mov dl, 2[si]
  844.         cmp dl, "0"        ; Is
  845.         jb off_drive0        ;   it
  846.         cmp dl, "9"        ;     a
  847.         jg off_drive0        ;       number.
  848.         sub dl, 30h        ; Make it binary.
  849.  
  850.         mov ah, 19h        ; Get the disk drive.
  851.         int 21h
  852.  
  853.         add al, "a"        ; Make it a letter.
  854.         cmp dh, "+"
  855.         jz off_drive1
  856.         sub al, dl        ; Subtract from current drive.
  857.         cmp al, "a"        ; If less then A
  858.         jge off_drive2        ;   we have an error.
  859. let_error:
  860.         mov exit_code, 09h    ; Offset of drive will be invalid.
  861.         mov al, "%"        ; Put percent back.
  862. off_drive0:
  863.         jmp get_next
  864.  
  865. off_drive1:
  866.         add al, dl        ; Add from current drive.
  867.         cmp al, "z"        ; If greater then Z
  868.         jg let_error        ;   we have an error.
  869.  
  870. off_drive2:
  871.         stosb            ; Save the letter.
  872.         inc si            ; Skip
  873.         inc si            ;   over
  874.         inc si            ;     %+n, or %-n.
  875.  
  876.         jmp get_data
  877.  
  878.  
  879. ;        Handle %cwd.
  880. cwd:
  881.         push di
  882.         push si
  883.  
  884.         mov di, si        ; Set destination.
  885.         inc di
  886.         mov si, offset l_cwd    ; Set Source.
  887.         mov cx, s_cwd
  888.         rep cmpsb        ; Is it %cwd.
  889.         jz get_cwd        ; Yes.
  890.  
  891.         pop si
  892.         push si
  893.         mov di, si        ; Set destination.
  894.         inc di
  895.         mov si, offset u_cwd    ; Set source.
  896.         mov cx, s_cwd
  897.         rep cmpsb        ; Is it %CWD.
  898.         jz get_cwd        ; Yes.
  899.  
  900.         pop si
  901.         pop di
  902.         jmp dosv        ; No. Jump out.
  903.  
  904. get_cwd:
  905.         mov bx, di
  906.         pop si
  907.         pop di
  908.         mov si, bx
  909.  
  910.         mov al, "\"        ; Put in the
  911.         stosb            ;   root backslash.
  912.         push si
  913.         mov si, offset d_cwd    ; Place to put the directory name.
  914.  
  915.         mov ah, 47h        ; Get current directory.
  916.         mov dl, 00h        ; Current disk drive.
  917.         int 21h
  918.  
  919. cwd1:
  920.         lodsb            ; Find the
  921.         cmp al, 00h        ;   string
  922.         jz cwd2            ;     terminator (zero).
  923.  
  924.         stosb            ; Store it.
  925.         jmp cwd1
  926.  
  927. cwd2:
  928.         pop si
  929.         jmp get_data
  930.  
  931.  
  932. ;        Handle %dosv.
  933. dosv:
  934.         push di
  935.         push si
  936.  
  937.         mov di, si        ; Set destination.
  938.         inc di
  939.         mov si, offset l_dosv    ; Set Source.
  940.         mov cx, s_dosv
  941.         rep cmpsb        ; Is it %dosv.
  942.         jz get_dosv        ; Yes.
  943.  
  944.         pop si
  945.         push si
  946.         mov di, si        ; Set destination.
  947.         inc di
  948.         mov si, offset u_dosv    ; Set source.
  949.         mov cx, s_dosv
  950.         rep cmpsb        ; Is it %DOSV.
  951.         jz get_dosv        ; Yes.
  952.  
  953.         pop si
  954.         pop di
  955.         jmp dosm        ; No. Jump out.
  956.  
  957. get_dosv:
  958.         mov bx, di
  959.         pop si
  960.         pop di
  961.         mov si, bx
  962.  
  963.         mov ah, 30h        ; Get DOS version number.
  964.         int 21h
  965.  
  966.         add al, "0"        ; Make it a number.
  967.         stosb            ; Store it.
  968.  
  969.         jmp get_data
  970.  
  971.  
  972. ;        Handle %dosm.
  973. dosm:
  974.         push di
  975.         push si
  976.  
  977.         mov di, si        ; Set destination.
  978.         inc di
  979.         mov si, offset l_dosm    ; Set Source.
  980.         mov cx, s_dosm
  981.         rep cmpsb        ; Is it %dosm.
  982.         jz get_dosm        ; Yes.
  983.  
  984.         pop si
  985.         push si
  986.         mov di, si        ; Set destination.
  987.         inc di
  988.         mov si, offset u_dosm    ; Set source.
  989.         mov cx, s_dosm
  990.         rep cmpsb        ; Is it %DOSM.
  991.         jz get_dosm        ; Yes.
  992.  
  993.         pop si
  994.         pop di
  995.         jmp drive        ; No. Jump out.
  996.  
  997. get_dosm:
  998.         mov bx, di
  999.         pop si
  1000.         pop di
  1001.         mov si, bx
  1002.  
  1003.         mov ah, 30h        ; Get DOS version number.
  1004.         int 21h
  1005.  
  1006.         mov al, ah        ; Get minor version.
  1007.         cmp al, 0ah        ; Is it less then ten.
  1008.         jb dosm0        ; Yes. Jump out.
  1009.  
  1010.         call ascii        ; Do the minor version
  1011.         jmp dosm1
  1012. dosm0:
  1013.         add al, "0"        ; Make it a number.
  1014.         stosb            ; Store it.
  1015.  
  1016. dosm1:
  1017.         jmp get_data
  1018.  
  1019. ;        Handle %drive.
  1020. drive:
  1021.         push di
  1022.         push si
  1023.  
  1024.         mov di, si        ; Set destination.
  1025.         inc di
  1026.         mov si, offset l_drive    ; Set Source.
  1027.         mov cx, s_drive
  1028.         rep cmpsb        ; Is it %drive.
  1029.         jz get_drive        ; Yes.
  1030.  
  1031.         pop si
  1032.         push si
  1033.         mov di, si        ; Set destination.
  1034.         inc di
  1035.         mov si, offset u_drive    ; Set source.
  1036.         mov cx, s_drive
  1037.         rep cmpsb        ; Is it %DRIVE.
  1038.         jz get_drive        ; Yes.
  1039.  
  1040.         pop si
  1041.         pop di
  1042.         jmp time        ; No. Jump out.
  1043.  
  1044. get_drive:
  1045.         mov bx, di
  1046.         pop si
  1047.         pop di
  1048.         mov si, bx
  1049.  
  1050.         mov ah, 19h        ; Get the disk drive.
  1051.         int 21h
  1052.  
  1053.         add al, "a"        ; Make it a letter.
  1054.         stosb            ; Store it.
  1055.  
  1056.         jmp get_data
  1057.  
  1058.  
  1059.  
  1060. ;        Handle %time.
  1061. time:
  1062.         push di
  1063.         push si
  1064.  
  1065.         mov di, si        ; Set destination.
  1066.         inc di
  1067.         mov si, offset l_time    ; Set Source.
  1068.         mov cx, s_time
  1069.         rep cmpsb        ; Is it %time.
  1070.         jz get_time        ; Yes.
  1071.  
  1072.         pop si
  1073.         push si
  1074.         mov di, si        ; Set destination.
  1075.         inc di
  1076.         mov si, offset u_time    ; Set source.
  1077.         mov cx, s_time
  1078.         rep cmpsb        ; Is it %TIME.
  1079.         jz get_time        ; Yes.
  1080.  
  1081.         pop si
  1082.         pop di
  1083.         jmp date        ; No. Jump out.
  1084.  
  1085. get_time:
  1086.         mov bx, di
  1087.         pop si
  1088.         pop di
  1089.         mov si, bx
  1090.  
  1091.         mov ah, 2ch        ; Get the
  1092.         int 21h            ;   current time.
  1093.  
  1094.         mov bh, ":"        ; Separator.
  1095.         mov al, ch        ; Do the
  1096.         call ascii        ;   hours.
  1097.         mov al, bh        ; Do the
  1098.         stosb            ;   separator.
  1099.         mov al, cl        ; Do the
  1100.         call ascii        ;   minutes.
  1101.         mov al, bh        ; Do the
  1102.         stosb            ;   separator.
  1103.         mov al, dh        ; Do the
  1104.         call ascii        ;   seconds.
  1105.         
  1106.         jmp get_data
  1107.  
  1108.  
  1109. ;        Handle %date.
  1110. date:
  1111.         push di
  1112.         push si
  1113.  
  1114.         mov di, si        ; Set destination.
  1115.         inc di
  1116.         mov si, offset l_date    ; Set Source.
  1117.         mov cx, s_date
  1118.         rep cmpsb        ; Is it %date.
  1119.         jz get_date        ; Yes.
  1120.  
  1121.         pop si
  1122.         push si
  1123.         mov di, si        ; Set destination.
  1124.         inc di
  1125.         mov si, offset u_date    ; Set source.
  1126.         mov cx, s_date
  1127.         rep cmpsb        ; Is it %DATE.
  1128.         jz get_date        ; Yes.
  1129.  
  1130.         pop si
  1131.         pop di
  1132.         jmp get_next        ; No. Jump out.
  1133.  
  1134. get_date:
  1135.         mov bx, di
  1136.         pop si
  1137.         pop di
  1138.         mov si, bx
  1139.  
  1140.         lodsb            ; Get a byte.
  1141.         cmp al, "1"        ; Format one.
  1142.         jz date1        ; Yes. Jumpout.
  1143.         cmp al, "2"        ; Format two.
  1144.         jz date1        ; Yes. Jumpout.
  1145.         cmp al, "3"        ; Format three.
  1146.         jz date1        ; Yes. Jumpout.
  1147.         dec si
  1148.         mov al, z_date        ; Get the default.
  1149. date1:
  1150.         mov z_date, al        ; Save format.
  1151.         mov bh, "-"        ; Separator.
  1152.         
  1153.         mov ah, 2ah        ; Get the
  1154.         int 21h            ;   current date.
  1155.  
  1156.         cmp z_date, "3"
  1157.         jnz date2
  1158.         sub cx, 1900        ; Remove the century.
  1159.         mov al, cl        ; Do the
  1160.         call ascii        ;   year.
  1161.         mov al, bh        ; Do the
  1162.         stosb            ;   separator.
  1163. date2:
  1164.         cmp z_date, "1"
  1165.         jz date3
  1166.         mov al, dh        ; Do the
  1167.         call ascii        ;   month.
  1168.         mov al, bh        ; Do the
  1169.         stosb            ;   separator.
  1170. date3:
  1171.         mov al, dl        ; Do the
  1172.         call ascii        ;   Day.
  1173.  
  1174.         cmp z_date, "3"
  1175.         jz date9
  1176.         mov al, bh        ; Do the
  1177.         stosb            ;   separator.
  1178.  
  1179.         cmp z_date, "2"
  1180.         jz date4
  1181.  
  1182.         mov al, dh        ; Do the
  1183.         call ascii        ;   month.
  1184.         mov al, bh        ; Do the
  1185.         stosb            ;   separator.
  1186. date4:
  1187.         mov al, dh        ; Do the
  1188.         sub cx, 1900        ; Remove the century.
  1189.         mov al, cl        ; Do the
  1190.         call ascii        ;   year.
  1191. ;
  1192. ;        mov al, dl        ; Do the
  1193. ;        call ascii        ;   Day.
  1194. ;        mov al, bh        ; Do the
  1195. ;        stosb            ;   separator.
  1196. ;        mov al, dh        ; Do the
  1197. ;        call ascii        ;   month.
  1198. ;        mov al, bh        ; Do the
  1199. ;        stosb            ;   separator.
  1200. ;        sub cx, 1900        ; Remove the century.
  1201. ;        mov al, cl        ; Do the
  1202. ;        call ascii        ;   year.
  1203. date9:        
  1204.         jmp get_data
  1205.  
  1206.  
  1207. ;        convert a binary number to two digit decimal.
  1208. ascii:
  1209.         mov bl, 0ah        ; Divide
  1210.         cbw            ;   by
  1211.         div bl            ;     ten.
  1212.         add al, "0"        ; Make it a number.
  1213.         stosb            ; Store tens.
  1214.         add ah, "0"        ; Make it a number.
  1215.         mov al, ah
  1216.         stosb            ; Store ones.
  1217.         ret
  1218.  
  1219.  
  1220. ;        End of data now finish it.
  1221. data_end:
  1222.         mov al, 00h        ; Save
  1223.         stosb            ;   two
  1224.         stosb            ;     nulls.
  1225.         mov ax, di        ; Get the offset.
  1226.         mov bx, offset d_env_var ; The beginng of the variable.
  1227.         sub ax, bx        ; Get the data lenght.
  1228.         mov s_data, ax        ; And save it.
  1229.  
  1230.         cmp v_rep, 0ffh        ; Are we going to replace.
  1231.         jz get_psp        ; Yes. Jump.
  1232.         cmp v_rce, 00h        ; Are we going to do root.
  1233.         jz get_psp        ; No.  Jump over.
  1234.         jmp set_root
  1235.  
  1236. get_psp:
  1237.         push ds            ; Save the segment base.
  1238.  
  1239. ;        PSP of program.
  1240.         mov si, 16h
  1241.         mov ax, [si]
  1242.  
  1243. ;        Parent PSP Segment of program.
  1244.         mov ds, ax        ; Set the data segment.
  1245.         mov si, 16h        ; Parent PSP Segment.
  1246.         mov ax, [si]
  1247.  
  1248. ;        Parent PSP Segment of command.com.
  1249.         mov ds, ax        ; Set the data segment.
  1250.         mov si, 16h        ; Parent PSP Segment.
  1251.         mov ax, [si]
  1252.         mov cs:[cpsp], ax
  1253.  
  1254. ;        Check if the Environment Address is usable.
  1255.         mov si, 2ch        ; Environment space
  1256.         mov bx, [si]        ;   of command.com.
  1257.         cmp bx, 00h        ; If it's zero we
  1258.         jz zero_add        ;   do a long search.
  1259.  
  1260.         sub bx, 01h        ; We will have to back
  1261.         mov ax, bx        ;   up to env. definition.
  1262.  
  1263. zero_add:
  1264. ;        Segment where the environment space is.
  1265.         mov ds, ax
  1266.         mov si, 00h
  1267.  
  1268. get4d:
  1269. ;        Look for 4dh on segment boundary.
  1270.         mov al, [si]
  1271.         cmp al, 4dh
  1272.         jz got4d
  1273.  
  1274. inc_seg:
  1275.         mov ax, si        ; Increment
  1276.         add ax, 10h        ;   to the next
  1277.         mov si, ax        ;      segment boundary.
  1278.         jmp get4d
  1279.  
  1280. got4d:
  1281.         mov ax, 1[si]        ; Get the psp.
  1282.         cmp cs:[cpsp], ax    ; Is it the same as cpsp?
  1283.         jnz inc_seg        ; No.  Jump out.
  1284.  
  1285.         mov ah, 00h
  1286.         mov al, 3[si]        ; Get the number of segments.
  1287.         mov bx, 10h
  1288.         mul bx            ; Get the number of bytes.
  1289.         mov cs:[env_siz], ax    ; Save it.
  1290.  
  1291.         mov ax, si        ; Increment
  1292.         add ax, 10h        ;   to the environment
  1293.         mov si, ax        ;      segment boundary.
  1294.         mov cs:[env_off], ax    ; Save it.
  1295.  
  1296. ;        Just a double check for environment space.
  1297. ;        Check for PATH= or PROMPT= or COMPEC= or SETENV=.
  1298.         mov ax, ds        ; Get the data segment
  1299.         mov es, ax        ; and put it in extra segment.
  1300.         mov di, si        ; This is our destination.
  1301.  
  1302.         pop ds            ; Restore the data segment.
  1303.         mov si, offset d_path    ; Check
  1304.         mov cx, s_path        ;   for
  1305.         rep cmpsb        ;     PATH=.
  1306.         jz got_env
  1307.  
  1308.         mov di, env_off        ; Restore the destination.
  1309.         mov si, offset d_prompt    ; Check
  1310.         mov cx, s_prompt    ;   for
  1311.         rep cmpsb        ;     PROMPT=.
  1312.         jz got_env
  1313.  
  1314.         mov di, env_off        ; Restore the destination.
  1315.         mov si, offset d_comspec ;Check
  1316.         mov cx, s_comspec    ;    for
  1317.         rep cmpsb        ;      COMSPEC=.
  1318.         jz got_env
  1319.  
  1320.         mov di, env_off        ; Restore the destination.
  1321.         mov si, offset d_setenv    ; Check
  1322.         mov cx, s_setenv    ;   for
  1323.         rep cmpsb        ;     SETENV=.
  1324.         jz got_env
  1325.  
  1326.         push ds            ; Save the data segment.
  1327.         mov ax, es        ; Get the
  1328.         mov ds, ax        ;   data segment
  1329.         mov si, cs:[env_off]    ;     and source
  1330.         jmp get4d        ;       to scan some more.
  1331.  
  1332. got_env:
  1333.         push ds            ; Save the data segment.
  1334.         mov ax, es        ; Get the
  1335.         mov ds, ax        ;   data segment
  1336.         mov si, cs:[env_off]    ;     and source.
  1337.  
  1338.         mov di, offset cs:[d_env_var]    ; First character
  1339.         mov bl, cs:[di]        ;   of environment variable.
  1340.         jmp zero1
  1341. ;        Scan through environment for the end,
  1342. ;        we need two null bytes.
  1343. loop:
  1344.         lodsb            ; Get a byte.
  1345.         cmp al, 00h        ; Is it null?
  1346.         jz zero1        ; Yes. Got first null.
  1347.         jmp loop        ; Keep looking.
  1348.  
  1349. ;        Is the variable there?
  1350. zero1:
  1351.         lodsb            ; Get a byte.
  1352.         cmp al, 00h        ; Is it zero?
  1353.         jz write_near        ; Yes.  Jump out.
  1354.         cmp al, bl        ; Is it the env. variable?
  1355.         jnz loop        ; No.  Jump out.
  1356.  
  1357.         dec si            ; We are N+1.
  1358.         mov ax, ds        ; Get the data segment
  1359.         mov es, ax        ; and put it in extra segment.
  1360.         mov di, si        ; This is our destination.
  1361.  
  1362.         mov dx, si        ; Save the address of env. var.
  1363.         pop ds            ; Restore the data segment.
  1364.         mov si, offset d_env_var ; Set the source.
  1365.         mov cx, s_env_var    ; Length of variable.
  1366.         rep cmpsb        ; Does it exist?
  1367.         jz update
  1368.  
  1369.         push ds            ; Save the data segment.
  1370.         mov ax, es        ; Get the extra segment.
  1371.         mov ds, ax        ; and put it in data segment.
  1372.         mov si, di        ; Setup the source.
  1373.         jmp loop
  1374.  
  1375. write_near:
  1376.         jmp write
  1377. subst_near:
  1378.         jmp substitute
  1379. change_near:
  1380.         jmp change
  1381.  
  1382. ;        The environment variable is there.
  1383. ;        Now update the environment variable.
  1384. update:
  1385.         cmp cs:[v_rep], 0ffh    ; Do we replace?
  1386.         jz subst_near        ; Yes. Go there.
  1387.  
  1388.         cmp cs:[v_chgup], 0ffh    ; Do we upper case string?
  1389.         jz change_near        ; Yes. Go there.
  1390.  
  1391. update0:
  1392.         push ds            ; Save the data segment.
  1393.         mov ax, es        ; Get the extra segment.
  1394.         mov ds, ax        ; and put it in data segment.
  1395.         mov di, dx        ; This is our destination.
  1396.         mov si, di        ; Setup the source.
  1397.         
  1398. update1:
  1399.         lodsb            ; Skip
  1400.         cmp al, 00h        ;   over
  1401.         jnz update1        ;     the variable.
  1402.  
  1403.         lodsb            ; Look ahead to see
  1404.         dec si            ;   if the next byte
  1405.         cmp al, 00h        ;     is zero if not
  1406.         jz update3        ;       compress the data.
  1407.  
  1408. update2:
  1409.         lodsb            ; Compress
  1410.         stosb            ;   the data
  1411.         cmp al, 00h        ;     for a
  1412.         jnz update2        ;       variable.
  1413.  
  1414.         lodsb            ; Get a byte.
  1415.         dec si
  1416.         cmp al, 00h        ; Is it zero?
  1417.         jnz update2        ; No.  Get next.
  1418.  
  1419. update3:
  1420.         mov al, cs:[exit_code]
  1421.         cmp al, 05h
  1422.         jg update4
  1423.         mov cs:[exit_code], 05h    ; Environment variable updated.
  1424. update4:
  1425.         mov cx, cs:[s_data]    ; Length of data.
  1426.         mov dx, cs:[s_env_var]    ; Length of name.
  1427.         sub cx, dx
  1428.         sub cx, 02h        ; Minus 2 zeroes.
  1429.         cmp cx, 00h        ; Is it just the name.
  1430.         jnz write1        ; No. Jump out.
  1431.  
  1432.         mov cx, si        ; End of old environment.
  1433.         mov dx, di        ; Current position.
  1434.         sub cx, dx
  1435.         mov al, 00h        ; Zero
  1436.         rep stosb        ;  the rest.
  1437.         mov cs:[exit_code], 02h    ; Environment variable erased.
  1438.         jmp nor_term
  1439.  
  1440. ;        The environment variable isn't there.
  1441. ;        Now move the data into place.
  1442. write:
  1443.         mov ax, ds        ; Get the data segment
  1444.         mov es, ax        ; and put it in extra segment.
  1445.         dec si            ; We are N+1.
  1446.         mov di, si        ; This is our destination.
  1447.  
  1448. write1:
  1449.         mov cx, cs:[s_data]    ; Environment variable & data.
  1450.         dec cx            ; No
  1451.         dec cx            ;   nulls.
  1452.         mov ax, cs:[s_env_var]    ; Environment variable size.
  1453.         cmp ax, cx        ; Same size.
  1454.         jne write2        ; No. Jump out.
  1455.         mov cs:[exit_code], 08h    ; Environment variable not found.
  1456.         jmp nor_term
  1457.  
  1458. write2:
  1459.         pop ds            ; Restore the data segment.
  1460.         mov si, offset d_env_var ; Set the source.
  1461.         mov cx, s_data        ; Set the length.
  1462. write3:
  1463.         mov ah, es:[di]        ; Get destination byte.
  1464. write4:
  1465.         cmp ah, 00h        ; Is it a zero?
  1466.         jnz not_zero        ; No.  Jump out.
  1467.         lodsb            ; Get byte.
  1468.         stosb            ; Save byte.
  1469.         loop write3        ; Loop.
  1470.  
  1471. ;        Exit the program.
  1472. nor_term:
  1473.         mov al, cs:[exit_code]    ; Set termination code.
  1474.         mov ah, 4ch        ; Termination.
  1475.         int 21h
  1476.  
  1477. not_zero:
  1478.         mov ax, di        ; Get the current offset.
  1479.         mov bx, env_off        ; Get environment start.
  1480.         sub ax, bx        ; Subtract the start of env.
  1481.         mov bx, env_siz        ; Get environment size.
  1482.         cmp ax, bx        ; Greater the environment size.
  1483.         jge reset        ; Yes.  Jump.
  1484.         mov ah, 00h        ; Make it zero.
  1485.         mov al, exit_code    ; Get exit code.
  1486.         cmp al, 05h        ; If update then do not
  1487.         jge write4        ;   reduce the error code.
  1488.         mov exit_code, 04h    ; Environment space over written.
  1489.         jmp write4        ;   and redo.
  1490.  
  1491. reset:
  1492.         dec di
  1493.         dec di
  1494.         mov al, 00h        ; Put zero back.
  1495.         stosb
  1496.         stosb
  1497.         mov exit_code, 10h    ; Set code for out of env.,
  1498.         jmp nor_term        ;   and terminate.
  1499.  
  1500. ;        Replace old text with new text.
  1501. substitute:
  1502.         push dx
  1503.         push ds
  1504.         push es
  1505.         push si
  1506.         push di
  1507.  
  1508.         mov ax, es        ; Switch
  1509.         mov bx, ds        ;   the
  1510.         mov es, bx        ;     segments
  1511.         mov ds, ax        ;       around.
  1512.  
  1513.         mov ax, di        ; Switch
  1514.         mov di, si        ;   the
  1515.         mov si, ax        ;     registrars.
  1516.  
  1517.         mov bx, offset x_rep    ; Get first byte
  1518.         mov dl, cs:[bx]        ;   of old data.
  1519. subst1:
  1520.         lodsb            ; Get byte.
  1521.         cmp al, 00h        ; End of variable space.
  1522.         jz subst5        ; Yes. Jump out.
  1523.  
  1524.         cmp al, dl        ; First byte of data?
  1525.         jz subst3        ; Yes. Jump out
  1526. subst2:
  1527.         stosb            ; Save byte.
  1528.         jmp subst1
  1529.  
  1530. ;        Test for old text.
  1531. subst3:
  1532.         push ds
  1533.         push es
  1534.         push di
  1535.         push si
  1536.  
  1537.         mov ax, es        ; Switch
  1538.         mov bx, ds        ;   the
  1539.         mov es, bx        ;     segments
  1540.         mov ds, ax        ;       around.
  1541.  
  1542.         mov di, si
  1543.         dec di            ; Data N+1.
  1544.         mov si, offset x_rep    ; Old data value.
  1545.         mov cx, cs:[w_rep]    ; Old data size.
  1546.         rep cmpsb
  1547.         jz subst4
  1548.  
  1549.         mov al, dl        ; Get byte back.
  1550.         pop si
  1551.         pop di
  1552.         pop es
  1553.         pop ds
  1554.         jmp subst2
  1555.  
  1556. ;        Put in new text.
  1557. subst4:
  1558.         pop si
  1559.         pop di
  1560.         mov ax, ds
  1561.         mov es, ax
  1562.  
  1563.         mov bx, si
  1564.         dec si            ; Data N+1.
  1565.         push si
  1566.  
  1567.         mov si, offset z_rep    ; New data value.
  1568.         mov cx, y_rep        ; New data size.
  1569.         rep movsb
  1570.  
  1571.         pop si
  1572.         mov cx, si
  1573.         mov ax, w_rep        ; Add size of
  1574.         add cx, ax        ;   new value.
  1575.         mov si, cx        ; Advance the size.
  1576.  
  1577.         pop es
  1578.         pop ds
  1579.         jmp subst1
  1580.  
  1581. subst5:
  1582.         stosb            ; Save two
  1583.         stosb            ;   nulls.
  1584.         pop di
  1585.         pop si
  1586.         pop es
  1587.         pop ds
  1588.  
  1589.         mov v_rep, 00h        ; Turn off replace.
  1590.         push si
  1591.         push di
  1592.  
  1593.         mov si, offset d_env_var
  1594.         mov cx, 00h
  1595. subst6:
  1596.         lodsb            ; Get
  1597.         inc cx            ;   the
  1598.         cmp al, 00h        ;     size.
  1599.         jnz subst6
  1600.  
  1601.         inc cx
  1602.         mov s_data, cx        ; Save the size.
  1603.  
  1604.         pop di
  1605.         pop si
  1606.         pop dx
  1607.         jmp update0
  1608.  
  1609. ;        Replace old text with new text.
  1610. change:
  1611.         mov ax, es        ; Switch
  1612.         mov ds, ax        ;   the
  1613.         mov si, di        ;     registers.
  1614.  
  1615. change1:
  1616.         lodsb            ; Get a byte.
  1617.         cmp al, 00h        ; Is it null?
  1618.         jz change9        ; Yes. End of variable.
  1619.  
  1620.         cmp al, "z"        ; Is
  1621.         jg change2        ;   it
  1622.         cmp al, "a"        ;     lower
  1623.         jb change2        ;       case?
  1624.         sub al, 20h        ; Make it upper case.
  1625.         stosb            ; Replace it.
  1626.         jmp change1        ; Next byte.
  1627.  
  1628. change2:
  1629.         inc di
  1630.         jmp change1        ; Keep looking.
  1631.  
  1632. change9:
  1633.         mov cs:[exit_code], 05h    ; Environment variable updated.
  1634.         jmp nor_term
  1635.  
  1636. ;        Root environment.
  1637. set_root:
  1638.         mov si, offset set    ; Move in the 'set='
  1639.         mov di, offset d_rce    ;   into the data area.
  1640.         inc di            ; Leave room for size.
  1641.         mov cx, 04h
  1642.         rep movsb        ; Move string.
  1643.  
  1644.         mov si, offset d_env_var ; Environment data.
  1645.         mov cx, s_data
  1646.         dec cx            ; Ignore the
  1647.         dec cx            ;   two nulls.
  1648.         rep movsb        ; Move string.
  1649.  
  1650.         mov al, 0dh        ; Put in the CR to terminate.
  1651.         stosb
  1652.         mov ax, s_data        ; Set the size and
  1653.         inc al            ;   add the
  1654.         inc al            ;     size for 'set='.
  1655.         mov byte ptr d_rce, al    ; Save the count.
  1656.  
  1657.         mov bx, offset lastloc+15 ; bx := program size
  1658.         mov cx, 04h        ;   in paragraphs.
  1659.         shr bx, cl
  1660.         mov ax, 4a00h        ; Deallocate unused memory.
  1661.         int 21h
  1662.  
  1663.         mov si, offset d_rce    ; Point at command.
  1664.         int 02eh        ; Execute the DOS command.
  1665.  
  1666.         mov ax, cs
  1667.         mov ss, ax
  1668.         mov ds, ax
  1669.         mov es, ax
  1670.         mov cs:[exit_code], 01h    ; Set code for environment
  1671.         jmp nor_term        ;   root set and terminate.
  1672.  
  1673.         db    128 dup (?)    ; Stack.
  1674. stack        label    byte
  1675.  
  1676. lastloc        label    byte        ; End of program.
  1677. code ends
  1678.      end start
  1679. 
  1680.