bencollver

28.02.2026, 00:52 |
save & restore environment (Developers) |
I ran into a situation in SvarDOS where the EDR-DOS command interpreter was creating duplicate environment variables. For example, when i ran the SET command, i might see multiple PATH= variables in its output. I believe it was related to running out of space in the environment. The way i worked around this problem was by increasing the size of the environment, and also by running COMMAND /C instead of CALL to run helper .bat files. With COMMAND /C the original environment is restored when the helper .bat file completes.
I found myself wishing for a utility to back up and restore the environment. As an exercise, i wrote a couple of AWK scripts to do it.
mkenvset.awk
# Usage: awk -f mkenvset.awk >envset.bat
# Run envset.bat to restore all environment variables
BEGIN {
for (k in ENVIRON) {
printf "SET %s=%s\n", k, ENVIRON[k]
}
}
mkenvdel.awk
# Usage: awk -f mkenvdel.awk >envdel.bat
# Run envdel.bat to delete all environment variables
BEGIN {
for (k in ENVIRON) {
printf "SET %s=\n", k
}
}
I imagine using them like so:
awk -f mkenvset.awk >envset.bat
call helper.bat
awk -f mkenvdel.awk >envdel.bat
call envdel.bat
call envset.bat
This would effectively restore the original environment without using a COMMAND /C sub-shell.
What do you think? Is it a bad idea? Why? |
Rugxulo

Usono, 28.02.2026, 03:18
@ bencollver
|
save & restore environment |
> awk -f mkenvset.awk >envset.bat
> call helper.bat
> awk -f mkenvdel.awk >envdel.bat
> call envdel.bat
> call envset.bat
>
> This would effectively restore the original environment without using a
> COMMAND /C sub-shell.
>
> What do you think? Is it a bad idea? Why?
4DOS and NT's CMD both have "SETLOCAL". So if you don't need any vars to persist, try that.
If you insist on this way (presumably to run on older shells), I'd suggest putting it in a single .BAT like "SAVEENV.BAT [on | off]". The AWK scripts are small enough to be in-place, but even an embedded AWK script (or ten) is easy to use. |
bencollver

28.02.2026, 04:26
@ Rugxulo
|
save & restore environment |
> 4DOS and NT's CMD both have "SETLOCAL". So if you don't need any vars to
> persist, try that.
Thanks for that information. 4DOS is really "where it's at" isn't it?
> If you insist on this way (presumably to run on older shells), I'd suggest
> putting it in a single .BAT like "SAVEENV.BAT [on | off]". The AWK scripts
> are small enough to be in-place, but even an embedded AWK script (or ten)
> is easy to use.
Here's an attempt at SAVEENV.BAT:
@echo off
if x%1 == xon goto save
if x%1 == xoff goto restore
goto usage
:usage
echo SAVEENV.BAT ON
echo This saves the environment.
echo.
echo SAVEENV.BAT OFF
echo This restores the saved environment.
echo.
goto the_end
:save
echo BEGIN{ >%TEMP%\envset.awk
echo print "@echo off" >>%TEMP%\envset.awk
echo for(k in ENVIRON){printf "SET %%s=%%s\n",k,ENVIRON[k]} >>%TEMP%\envset.awk
echo } >>%TEMP%\envset.awk
awk -f %TEMP%\envset.awk >%TEMP%\envset.bat
goto the_end
:restore
echo BEGIN{ >%TEMP%\envdel.awk
echo print "@echo off" >>%TEMP%\envdel.awk
echo for(k in ENVIRON){printf "SET %%s=\n",k} >>%TEMP%\envdel.awk
echo } >>%TEMP%\envdel.awk
awk -f %TEMP%\envdel.awk >%TEMP%\envdel.bat
call %TEMP%\envdel.bat
call %TEMP%\envset.bat
goto the_end
:the_end |
boeckmann
Aachen, Germany, 28.02.2026, 10:23
@ bencollver
|
save & restore environment |
> I ran into a situation in SvarDOS where the EDR-DOS command interpreter [...]
Is it really the EDR command.com or SvarCOM, the default SvarDOS command interpreter? |
bencollver

28.02.2026, 15:20
@ boeckmann
|
save & restore environment |
> > I ran into a situation in SvarDOS where the EDR-DOS command interpreter
> [...]
>
> Is it really the EDR command.com or SvarCOM, the default SvarDOS command
> interpreter?
It was really EDR command.com, and here's how i reproduced it:
Downloaded and extracted the TCC sources:
C:\>curl -O gopher://tilde.pink/9/~bencollver/files/dos386/devel/tcc/src.zip
C:\>unzip src.zip
Verify shell
C:\>ver
Enhanced DR-DOS based on Caldera OpenDOS 7.01
Copyright (c) 1976, 1997 Caldera, Inc. All rights reserved.
Patches to original OpenDOS source code Copyright (c) 2002-2011 Udo Kuhnt
C:\>command.com /? | find "DOS"
Enhanced DR-DOS based on Caldera OpenDOS 7.01
Patches to original OpenDOS source code Copyright (c) 2002-2011 Udo Kuhnt
C:\>find "SHELL=" config.sys
---------------- CONFIG.SYS
SHELL=C:\COMMAND.COM C:\ /E:2048 /P
Configure Watcom build environment
C:\>cd watcom
C:\WATCOM>owsetenv
Open Watcom Build Environment
C:\WATCOM>cd ..
Configure HX
C:\>set DPMILDR=136
C:\>set HDPMI=32
C:\>path %PATH%;C:\HX\BIN
C:\>hxldr32
HXLdr32 V1.13 Installed. Win32 console apps may possibly run now in DOS
Edit TCC win32\mkall.bat
Change one line.
OLD: set CALL=\command.com /c
NEW: set CALL=call
C:\>cd src\win32
C:\SRC\WIN32>oed mkall.bat
1921
/set CALL=\\command.com/s/.*/set CALL=call/p
set CALL=call
w
1910
q
Compile TCC
Takes a while for the script to complete or fail.
C:\SRC\WIN32>mkall.bat
Verify duplicate variables in environment
C:\SRC\WIN32>set | find "D="
CD=C:\SRC\WIN32
D=-dTCC_TARGET_PE -dTCC_TARGET_I386
D=-DTCC_TARGET_PE -DTCC_TARGET_I386
D=-DTCC_TARGET_PE -DTCC_TARGET_I386
C:\> |
boeckmann
Aachen, Germany, 28.02.2026, 19:26
@ bencollver
|
save & restore environment |
Is it the EDR command version from the SvarDOS package (this comes from https://github.com/SvarDOS/edrdos )?
The code involved should be:
https://github.com/SvarDOS/edrdos/blob/cd65cc5e671...05ff2531099dddc348/command/comint.c#L1647-L1661
The intended logic is like this: delete environment variable if it already exists, then append the variable with the changed content at the end of the environment. If "D" occurs multiple times, this logic somehow fails. |
Rugxulo

Usono, 01.03.2026, 00:24
@ bencollver
|
save & restore environment |
> > 4DOS and NT's CMD both have "SETLOCAL". So if you don't need any vars to
> > persist, try that.
>
> Thanks for that information. 4DOS is really "where it's at" isn't it?
Yes and no. It's brilliant, but I always avoided it to write "portable" scripts. But it does make some things easier. (Honestly, it no worse than relying on a POSIX shell!)
> > If you insist on this way (presumably to run on older shells), I'd
> suggest
> > putting it in a single .BAT like "SAVEENV.BAT [on | off]". The AWK
> scripts
> > are small enough to be in-place, but even an embedded AWK script (or
> ten)
> > is easy to use.
>
> Here's an attempt at SAVEENV.BAT:
Here's an old example of mine that may give you ideas: invnas97.bat |
bencollver

01.03.2026, 15:12
@ boeckmann
|
save & restore environment |
> Is it the EDR command version from the SvarDOS package (this comes from
> https://github.com/SvarDOS/edrdos )?
Here's what i am using:
https://github.com/SvarDOS/edrdos/releases/tag/v20250427 |
bencollver

08.03.2026, 00:45
@ boeckmann
|
save & restore environment |
I reduced it to a test case.
COMMAND.COM is from EDR DOS 20250427
CMD701.COM is from Caldera OpenDOS 7.01
C:\>type test.bat
SET D=-dTCC_TARGET_PE -dTCC_TARGET_I386
SET D=-DTCC_TARGET_PE -DTCC_TARGET_I386
SET
C:\>command.com /c test.bat
OS=DRDOS
VER=7
COMSPEC=C:\COMMAND.COM
TEMP=C:\TEMP
NLSPATH=C:\SVARDOS\NLS
WATTCP.CFG=C:\SVARDOS
PATH=C:\SVARDOS;C:\CWSDPMI;C:\UNZIP32;C:\V8POWER;C:\WHICH
PROMPT=$P$G
LANG=EN
DOS32A=/QUIET
D=-dTCC_TARGET_PE -dTCC_TARGET_I386
D=-DTCC_TARGET_PE -DTCC_TARGET_I386
C:\>cmd701.com /c test.bat
OS=DRDOS
VER=7
COMSPEC=C:\COMMAND.COM
TEMP=C:\TEMP
NLSPATH=C:\SVARDOS\NLS
WATTCP.CFG=C:\SVARDOS
PATH=C:\SVARDOS;C:\CWSDPMI;C:\UNZIP32;C:\V8POWER;C:\WHICH
PROMPT=$P$G
LANG=EN
DOS32A=/QUIET
D=-DTCC_TARGET_PE -DTCC_TARGET_I386
If i run the script in DEBUG.COM, it gives a 3rd version of the output:
C:\>debug command.com /c test.bat
- g
OS=DRDOS
VER=7
COMSPEC=C:\COMMAND.COM
TEMP=C:\TEMP
NLSPATH=C:\SVARDOS\NLS
WATTCP.CFG=C:\SVARDOS
PATH=C:\SVARDOS;C:\CWSDPMI;C:\UNZIP32;C:\V8POWER;C:\WHICH
PROMPT=$P$G
LANG=EN
DOS32A=/QUIET
D=-dTCC_TARGET_PE -dTCC_TARGET_I386
Program terminated normally (0000)
-
This discouraged me because i was hoping to use DEBUG.COM to trace what was happening within COMMAND.COM.
Oddly, if i edit test.bat and change the variable name, then i can no longer reproduce the problem even on EDR DOS COMMAND.COM. It creates a duplicate environment variable named D, but will not produce one named A, B, C, E, or even DD.
p.s.
I compared OpenDOS 7.01 COMMAND.COM with EDR DOS 20250427.
command\csup.asm get_key has only one difference.
So far as i can tell, it should work the same.
--- old-getkey.asm 2026-03-07 14:40:31.343231149 -0800
+++ new-getkey.asm 2026-03-07 14:40:54.172230574 -0800
@@ -8,7 +8,7 @@
push ds
pop es ; Calculate the length of the
mov di,04[bp] ; key by scaning the string for
- mov al,0 ; a zero byte.
+ xor al,al ; a zero byte.
mov cx,-1
repnz scasb
neg cx ; CX is the length of the sting + 2
command\csup.asm env_del has only one difference.
So far as i can tell, it should work the same.
--- old-envdel.txt 2026-03-07 14:10:03.196277219 -0800
+++ new-envdel.txt 2026-03-07 14:10:24.636276679 -0800
@@ -28,7 +28,7 @@
env_d15:
lodsb
stosb ; Copy through AL checking for the end
- or al,al
+ test al,al
jnz env_d15 ; of the environment after each
jmps env_d10 ; end of string.
env_d20:
After converting the spacing
command\comint.c cmd_set has a couple of differences,
after converting to ANSI C and fixing the indentation.
--- old-cmdset.txt 2026-03-07 14:01:29.396290167 -0800
+++ new-cmdset.txt 2026-03-07 13:42:03.099319559 -0800
@@ -46,8 +46,6 @@
syntax(); /* or the '=' is missing return */
return;
} /* a syntax error. */
-
- s++;
#if 0
/* msdos doesn't do this */
@@ -67,7 +65,9 @@
crlfflg = YES;
return;
}
- if ( (*s-- = c) != 0 ) { /* Add the definition to the end*/
+ *s++ = c;
+
+ if ( *s != 0 ) { /* Add the definition to the end*/
/* of the environment if the new*/
if ( env_ins( key ) ) { /* definition is not NULL */
printf( MSG_ENVFULL ); /* check for an error. */
The asm PROC get_key begins with:
1E push ds
07 pop es
?? mov di,04[bp]
?? xor al,al
COMMAND.COM is 63601 bytes large (F871)
C:\>debug command.com /c test.bat
-s 100 l F871 1E 07
1954:20D2
1954:22B3
1954:242D
1954:2440
1954:3D2A
1954:2E26
1954:408B
1954:40A1
1954:40E3
1954:4109
1954:4140
1954:4156
1954:42A9
1954:446A
1954:B262
Unassembling these offsets, only one matches the PROC get_key signature.
-u 1954:3D2A
1954:3D2A 1E PUSH DS
1954:3D2B 07 POP ES
1954:3D2C 8B7E04 MOV DI,[BP+04]
1954:3D2F 32C0 XOR AL,AL
1954:3D31 B9FFFF MOV CX,FFFF
1954:3D34 F2AE REPNE SCASB
1954:3D36 F7D9 NEG CX
1954:3D38 83E902 SUB CX,+02
1954:3D3B 8BD1 MOV DX,CX
1954:3D3D 33C0 XOR AX,AX
1954:3D3F 8EC3 MOV ES,BX
1954:3D41 33FF XOR DI,DI
1954:3D43 57 PUSH DI
1954:3D44 8BCA MOV CS,DX
1954:3D46 8B7604 MOV SI,[BP+04]
1954:3D49 F3A6 REPE CMPSB |
jadoxa

Queensland, Australia, 08.03.2026, 01:39
@ bencollver
|
save & restore environment |
> COMMAND.COM is from EDR DOS 20250427
This is failing because it is not getting the key, it is getting the prefix of the key.
C:\>type test.bat
set d11=d11
set d12=d12
set d13=d13
set D1=d1
set D1=D1
set
C:\>command.com /c set | tail -1
COMSPEC=J:\COMMAND.COM
C:\>command.com /c test.bat | tail -4
COMSPEC=J:\COMMAND.COM
D13=D13
D1=d1
D1=D1
(COMSPEC is J: because I'm actually running this in MSDOS Player in Win10.)
When it gets the key it doesn't check there's an equals after it, hence the key will match any other variable that starts with it. |
bencollver

08.03.2026, 02:05
@ jadoxa
|
save & restore environment |
> > COMMAND.COM is from EDR DOS 20250427
>
> This is failing because it is not getting the key, it is getting the prefix
> of the key.
> ...
> When it gets the key it doesn't check there's an equals after it, hence the
> key will match any other variable that starts with it.
Thanks!
Maybe that was what the removed s++; line was for:
to include the = (equal sign) in the key. |
boeckmann
Aachen, Germany, 08.03.2026, 22:23
@ bencollver
|
save & restore environment |
> > > COMMAND.COM is from EDR DOS 20250427
> >
> > This is failing because it is not getting the key, it is getting the
> prefix
> > of the key.
> > ...
> > When it gets the key it doesn't check there's an equals after it, hence
> the
> > key will match any other variable that starts with it.
>
> Thanks!
>
> Maybe that was what the removed s++; line was for:
>
> to include the = (equal sign) in the key.
Yes, get_key does not check for '='. The following seems to fix it (includes the = as part of the key for deletion.
diff --git a/command/comint.c b/command/comint.c
index 5068153..2d785c1 100644
--- a/command/comint.c
+++ b/command/comint.c
@@ -1641,6 +1641,7 @@ GLOBAL VOID CDECL cmd_set( BYTE *s )
}
#endif
+ s++; /* skip over = (include in key name) */
c = *s; /* Save Character */
*s = '\0'; /* terminate keyword */
strupr( key ); /* make keyword upper case */
@@ -1649,7 +1650,7 @@ GLOBAL VOID CDECL cmd_set( BYTE *s )
crlfflg = YES;
return;
}
- *s++ = c;
+ *s = c; /* recover first character of value */
if ( *s != 0 ) { /* Add the definition to the end*/
/* of the environment if the new*/
|
boeckmann
Aachen, Germany, 09.03.2026, 17:15
@ boeckmann
|
save & restore environment |
Fixed by https://github.com/SvarDOS/edrdos/commit/579ab148df4d6af82752155137e0cad6a31b1a34 |
bencollver

09.03.2026, 20:09
@ boeckmann
|
save & restore environment |
> Fixed by
> https://github.com/SvarDOS/edrdos/commit/579ab148df4d6af82752155137e0cad6a31b1a34
Thanks! I verified that it fixed the problem on my end.
https://github.com/SvarDOS/edrdos/actions/runs/22862905914 |