AURPS@ASUACAD.BITNET (05/05/91)
Does anyone know how to permanently change a DOS environment variable from within an executing program? PUTENV() changes/creates a variable but it is only in effect while the program is running. As soon as I go back to DOS, the environment is restored to its original variables. I'm using Turbo C. Thanks for any help, Rick Schatzman
mike@bria.UUCP (mike.stefanik) (05/07/91)
In an article, AURPS@ASUACAD.BITNET writes: >Does anyone know how to permanently change a DOS environment variable from >within an executing program? PUTENV() changes/creates a variable but it >is only in effect while the program is running. As soon as I go back to >DOS, the environment is restored to its original variables. I'm using >Turbo C. The problem that you are running into is that a child process (and I use the term "process" loosely insofar as DOS is concerned) cannot change the environment of it's parent. Of course, you can allways go hunting through memory, but that wouldn't be portable, would it? :-) Here is the situation that you have visually: +---------------+ | COMMAND.COM | (has the original copy of the environment) +---------------+ | +---------------+ | PROGRAM.EXE | (has a copy of command.com's environment) +---------------+ So, when command.com created the child, it gave it a *copy* of the environment table. Changes that are made, are made to the copy of the table, not the original. When the child dies, so goes the table as well. -- Michael Stefanik, MGI Inc, Los Angeles | Opinions stated are never realistic Title of the week: Systems Engineer | UUCP: ...!uunet!bria!mike ------------------------------------------------------------------------------- If MS-DOS didn't exist, who would UNIX programmers have to make fun of?
shaunc@gold.gvg.tek.com (Shaun Case) (05/07/91)
In article <91125.051531AURPS@ASUACAD.BITNET> AURPS@ASUACAD.BITNET writes: >Does anyone know how to permanently change a DOS environment variable from >within an executing program? PUTENV() changes/creates a variable but it >is only in effect while the program is running. As soon as I go back to >DOS, the environment is restored to its original variables. I'm using >Turbo C. I've tried a few things, and the following is what has worked for me. It also happens to be portable betweem different MSDOS C compilers and versions of MSDOS. Additionally, this is really an MSDOS-specific question, so I have directed followups to comp.os.msdos.programmer. To set a master environment variable, try using the following batchfile with your program: File GO.BAT: ------------- cut here -------------- echo off REM use '@echo off' if you have dos 3.3 or higher set REM your program name here: test command /c setvar REM use 'call setvar' if you have dos 3.3 or higher set ------------- cut here -------------- here is test.c: ------------- cut here -------------- /********************* set_env_var.c Shaun Case, 1991 Public Domain *********************/ #include <stdio.h> int main() { FILE *batfile; char varname[134]; char value[134]; printf("\nEnter variable name: "); gets(varname); printf("Enter value: "); gets(value); puts(""); if ((batfile = fopen("SETVAR.BAT", "w")) == NULL) { puts("Unable to open SETVAR.BAT, Omot. Bailing.\n\n"); return 1; } fprintf(batfile, "SET %s=%s\n", varname, value); fclose(batfile); return 0; } ------------- cut here -------------- I got the following output: COMSPEC=C:\4DOS.COM CMDLINE=go PATH=f:\tmp;c:\sys\util;c:\sys\bat;d:\borlandc\bin;d:\tc;C:\DOS;C:\WIN386;C:\;C:\TCP;c:\vga;c:\f-prot TEMP=f:\tmp TMP=f:\tmp FTPINIT=c:\tcp\init.tbl FTP_ATTR=0x71,0x74,0x21 FTP_CONFIG=c:\tcp\ftp.cfg USER=@Man PROMPT=$p$g Enter variable name: hodag Enter value: badger_nemesis COMSPEC=C:\4DOS.COM CMDLINE=setvar PATH=f:\tmp;c:\sys\util;c:\sys\bat;d:\borlandc\bin;d:\tc;C:\DOS;C:\WIN386;C:\;C:\TCP;c:\vga;c:\f-prot TEMP=f:\tmp TMP=f:\tmp FTPINIT=c:\tcp\init.tbl FTP_ATTR=0x71,0x74,0x21 FTP_CONFIG=c:\tcp\ftp.cfg USER=@Man PROMPT=$p$g HODAG=badger_nemesis -- shaunc@gold.gvg.tek.com atman%ecst.csuchico.edu@RELAY.CS.NET Postmaster of 1:119/666 1@9651 (WWIVnet) It's enough to destroy a young moose's faith! -- Bullwinkle
robc@cup.portal.com (Rob X Cowan) (05/07/91)
> Does anyone know how to permanently change a DOS environment variable from > within an executing program? PUTENV() changes/creates a variable but it > is only in effect while the program is running. As soon as I go back to > DOS, the environment is restored to its original variables. I'm using > Turbo C. > > Thanks for any help, > Rick Schatzman The following code demonstrates how to access the global environment string. It's not the only way, nor the best, but it'll get you started. masterenvstring is a pointer to the start of the environment list, in which each variable is an ASCIIZ string of the format <NAME>=<VALUE>. The list is terminated by a double null. masterenvsize is the size of the Memory Control block that is allocated for the environment string; I didn't put any code to deal with its manipulation, but you'll have to deal with it if you plan on adding entries or you risk a system halt by COMMAND.COM.. fun. /* * Demonstrates traversal of master environment string * Rob S. Cowan 9105.07 */ #include <dos.h> char *env_seekend(char far *); void main(void) { union REGS in, out; struct SREGS segs; char far *masterenvstr; int masterenvsize; /* * I don't remember if 2E is a supported function or not.. Nothing * must be linked ahead of COMMAND.COM, or that address will be * returned. */ in.x.ax = 0x352E; /* Get PSP of COMMAND.COM (sortof) */ intdosx(&in, &out, &segs); /* Get env asciiz string : seg stored at offset 2C of PSP */ masterenvstr = MK_FP(*(unsigned *)MK_FP(segs.es, 0x2C), 0); /* Get size of env block from MCB preceding it */ masterenvsize = (*(unsigned *)MK_FP(FP_SEG(masterenvstr) - 1, 3)) << 4; /* * You must take care to accommodate the memory requirements of * the environment string. If you wish to add entries you will * have to allocate/deallocate it with the MCB that precedes the * environment. */ } /* * Environment strings are a list of consecutive ASCIIZ strings * terminated by a null entry. This function will traverse to the * end of this list and return the address of the null entry. */ char *env_seekend(char far *envtrav) { for(;;) { if (!*envtrav++) if (!*envtrav) return envtrav; } } Prost, -Rob robc@cup.portal.com
robc@cup.portal.com (Rob X Cowan) (05/08/91)
> Does anyone know how to permanently change a DOS environment variable from > within an executing program? PUTENV() changes/creates a variable but it > is only in effect while the program is running. As soon as I go back to > DOS, the environment is restored to its original variables. I'm using > Turbo C. > > Thanks for any help, > Rick Schatzman I forgot to mention that int 2Eh (command.com interface) also has a way to actually access its own SET command. Can't remember how right now, but it should be easier than direct access, if your not up to that. -Rob robc@cup.portal.com
eyer@azu.informatik.uni-stuttgart.de (Eyer) (05/08/91)
In article <42119@cup.portal.com> robc@cup.portal.com (Rob X Cowan) writes: > >> Does anyone know how to permanently change a DOS environment variable from >> within an executing program? PUTENV() changes/creates a variable but it >> is only in effect while the program is running. As soon as I go back to >> DOS, the environment is restored to its original variables. I'm using >> Turbo C. >> >> Thanks for any help, >> Rick Schatzman > > I forgot to mention that int 2Eh (command.com interface) also has a >way to actually access its own SET command. Can't remember how right now, >but it should be easier than direct access, if your not up to that. > >-Rob The use of int 2Eh is following (I took it from Dave William's TechRef) : entry DS:DI pointer to an ASCIIZ command line in the form : count byte ASCII string carriage return null byte It is reported that this int will destroy all registers, including SP. I wouldn't use this method, because it might *NOT* be suported by further releases of DOS, and it is actually *NOT* supported by 4DOS. The other thing is that the transient part of COMMAND.COM will be reloaded if necessary, what is quite memory-wasting. I would use the direct memory access : in your PSP (Programm Segment Prefix), you will find the PSP of the father-process. You can so go up to the command interpreter, even if it is not called COMMAND.COM (for instance 4DOS), because it is his own father. And in the PSP, there is the pointer to the environment. So you can change the master environment. Since I never tried this, I take no responsibility of what I wrote. Manu (Emmanuel Eyer)
elkassas@ebg.eb.ele.tue.nl (sherif el kassas) (05/08/91)
In article <42119@cup.portal.com>, robc@cup.portal.com (Rob X Cowan) writes: => [stuff deleted] => I forgot to mention that int 2Eh (command.com interface) also has a => way to actually access its own SET command. Can't remember how right now, => but it should be easier than direct access, if your not up to that. => => -Rob => robc@cup.portal.com Well, that's how i'd do it ! any better ideas ? Sherif #include <standard_disclaimer> ----8<-------------------------------------- /* * file: test2e.c * demo for changing environment vars ...etc * compile with: * TCC test2e.c * note that u'll need tasm or masm ! */ #include <dos.h> #include <string.h> char *command = " set t=this is a test \r"; void int2e(char far *command_line) { unsigned seg, ofs; seg = FP_SEG(command_line); ofs = FP_OFF(command_line); asm jmp start asm my_ss dw 00 asm my_sp dw 00 start: asm push bp asm push ds asm mov ax, ss asm mov cs:my_ss, ax asm mov cs:my_sp, sp asm mov si, ofs asm mov ax, seg asm mov ds, ax asm int 2Eh asm cli asm mov sp, cs:my_sp asm mov ax, cs:my_ss asm mov ss, ax asm sti asm pop ds asm pop bp } main() { command[0] = strlen(command)-1; int2e(command); }
defaria@hpcupt3.cup.hp.com (Andy DeFaria) (05/10/91)
>/ hpcupt3:comp.lang.c / AURPS@ASUACAD.BITNET / 5:15 am May 5, 1991 / >Does anyone know how to permanently change a DOS environment variable from >within an executing program? PUTENV() changes/creates a variable but it >is only in effect while the program is running. As soon as I go back to >DOS, the environment is restored to its original variables. I'm using >Turbo C. My understanding is that you have to change the "master environment" by walking back the PSP (or something like that). I had gotten some Turbo Pascal code to do this but I recall some big problems with this whole approach and I abandoned it. It had something to do with the face that if you try to change an existing environment variables value then the new value can't be larger that the old value and if it is a new environment variable then you have to be careful about running out of environment space (and there is only a couple of bytes of extra environment space). Like I said I could dig up the information if you like.