[comp.lang.pascal] Change ENV.

bgeer@javelin.es.com (Bob Geer) (01/14/91)

ZCCBJSB%EB0UB011.BITNET@cunyvm.cuny.edu ( Info-Pascal list) writes:


>Has anyone some code/idea to modify PERMANENTLY a DOS environtment
>variable from a TP program (any TP version)?

Each program run gets a new copy of the environment of the current
program.  For example, any changes to the environment of, say, a batch
program doesn't make its way to the previous copy so is lost when the
batch program terminates.  Those changes only propogate to programs
run from the batch file, or programs they subsequently run.

Dr. Dobb's Journal #122 (December 1986) contained an article about
MS-DOS' undocumented interrupt 2Eh which will change the `master' copy
of the environment but not any copies already propogated from it.
Below I've included a procedure fragment that I use to edit the path
string.

The string handed to 2Eh must be formatted in the DOS style: length
byte, string, <CR>, <NULL>.  The environment must be sufficiently
large to accept the string; I found I had to limit my path string to
127 bytes (with standard size environment space) to prevent hanging
DOS.  This has worked for me from DOS 2.0 thru DOS 4.01, but MS
doesn't guarantee undocumented interrupts.  I didn't want to soak up
bandwidth by including the whole program, & I'm unsure of my ability
to send or receive e-mail.

---------------------------------------
	{ new_path is type PATH, defined as follows: }
	PATH = RECORD
	  CASE BOOLEAN OF
	    TRUE  : (str   : STRING[255]) ;
	    FALSE : (bytes : ARRAY [0..255] OF BYTE) ;
	  END ; { path }

	{ MY_SP, MY_SS, TMPDS, TMPSI are integers }

         new_path.str := CONCAT('SET ', path_str.str) ;
         new_path.bytes[1+LENGTH(new_path.str)] := CARRIAGE_RETURN ;
         new_path.bytes[2+LENGTH(new_path.str)] := NULL ;
         WRITELN ('Setting path to:') ;
         WRITELN (new_path.str) ;
         TMPDS := SEG(new_path) ; { path command segment for dos }
         TMPSI := OFS(new_path) ; { path command offset  for dos }
         INLINE ($1E/                 { push ds ; save environment }
                 $55/                 { push bp ;   " }
                 $2E/$8E/$1E/TMPDS/   { mov ds,cs:TMPDS ; prepare for fn }
                 $2E/$8B/$36/TMPSI/   { mov si,cs:TMPSI }
                 $2E/$8C/$16/MY_SS/   { mov cs:MY_SS,ss ; save stack seg }
                 $2E/$89/$26/MY_SP/   { mov cs:MY_SP,sp ; & stack ptr }
                 $CD/$2E/             { int 2e ; call msdos }
                 $2E/$8E/$16/MY_SS/   { mov ss,cs:MY_SS }
                 $2E/$8B/$26/MY_SP/   { mov sp,cs:MY_SP }
                 $5D/                 { pop bp }
                 $1F) ;               { pop ds }
	{ continue pascal code here }
----------------------------------------
-- 
<> Bob `Bear' Geer <>               bgeer@javelin.sim.es.com              <>
<>      Alta-holic <>   speaking only for myself, one of my many tricks   <>
<> Salt Lake City, <>    "We must strive to be more than we are, Lal."    <>
<>          Ootah  <>           -- Cmdr. Data, learning schmaltz          <>

thoger@solan.unit.no (Terje Th|gersen) (01/15/91)

In article <1991Jan14.143941.10541@javelin.es.com> bgeer@javelin.es.com (Bob Geer) writes:

   ZCCBJSB%EB0UB011.BITNET@cunyvm.cuny.edu ( Info-Pascal list) writes:

   >Has anyone some code/idea to modify PERMANENTLY a DOS environtment
   >variable from a TP program (any TP version)?

   Each program run gets a new copy of the environment of the current
   program.  For example, any changes to the environment of, say, a batch
   program doesn't make its way to the previous copy so is lost when the
   batch program terminates.  Those changes only propogate to programs
   run from the batch file, or programs they subsequently run.

   Dr. Dobb's Journal #122 (December 1986) contained an article about
   MS-DOS' undocumented interrupt 2Eh which will change the `master' copy
   of the environment but not any copies already propogated from it.
   Below I've included a procedure fragment that I use to edit the path
   string.

	.......[deletions]....

   ----------------------------------------
   -- 
   <> Bob `Bear' Geer <>               bgeer@javelin.sim.es.com              <>
   <>      Alta-holic <>   speaking only for myself, one of my many tricks   <>
   <> Salt Lake City, <>    "We must strive to be more than we are, Lal."    <>
   <>          Ootah  <>           -- Cmdr. Data, learning schmaltz          <>


There's a problem with the Int2Eh approach, though. According to some
refences, the use of INt2e will abort an executing batchfile. 
Also, a program that used Int2eh (which was posted here recently)
bombed under QEMM 5.11, giving a exception #13..

A safer approach, as used by Microsoft in their WHAT.EXE, (a freebie that
came with masm 5.0) is as follows :

1) read the word at [PREFIXSEG:$16]. This is the segment adress of the PSP
of the parent of the current program. Read the word at that segment:$16, 
which will be the previous program in the chain. Repeat this until you
find a PSP in which the word at $16 points to its own PSP. 

This will be 'granddaddy', the Master DOS environment. The word at PSP:$2c
tells you where this master environment starts. This a series of ASCIIZ
(#0-terminated strings) that ends in #0#0. Now, 'all you have to do' (:-))
is to smack your environment variables in here, byte for byte..

I have a program that actually does this (TP 5.5 code), but I think it's
a bit rough yet to go public with. (I only got it working last saturday :-))

If you insert extra bytes into the env. area, you must be sure that you
don't go out of the max number allocated to the environment. There's a 
word in the PSP somewhere that gives you the size of the environment area
in 16-byte paragraphs, but I just can't remember which. (I don't have 
the code here, I'm afraid..) I think i found it in one of the public 
domain dos tech. ref. documents.

Now, having found the env. area, and knowing the max size of it, you'll
have to count up how much of it is in use. If the variable you're
using is not in the environment already, all you have to do is add it
at the end of the existing env., taking care to overwrite *one* of the
two #0's that marks the end, and remembering to add two #0's after your
string. 

If the variable is already in there I guess you could take different 
approaches, what I do is to copy the entire environment into a string
array, delete 'my' variable, and add the new value to the end, before
writing the whole array back. ( make sure you remember to exclude the 
length-byte at STRING[0]..)

That's it, I think.. 

Hope this is understandable to those interested... I'll polish up my code
and post it here, but as I've got my diploma thesis due very shortly now,
it might take some time.. (if anyone wants rough code with (very few) 
*norwegian* language comments, mail me :-))

Bye,

   -Terje
--
____________________________________________________________________________
thoger@solan.unit.no       |                 Institute of Physical Chemistry
THOGER AT NORUNIT.BITNET   | Div. of Computer Assisted Instrumental Analysis
                           |               Norwegian Institute of Technology

phys169@csc.canterbury.ac.nz (01/16/91)

In article <THOGER.91Jan14235932@solan15.solan.unit.no>, thoger@solan.unit.no (Terje Th|gersen) writes:
> There's a problem with the Int2Eh approach, though. According to some
> refences, the use of INt2e will abort an executing batchfile. 
> Also, a program that used Int2eh (which was posted here recently)
> bombed under QEMM 5.11, giving a exception #13..
> 
Was that my program? (Sorry, the NEWS has been down here for a while; I would
have missed any follow-ups). Yes, the int 2E method has 2 limitations that I
know of: (1) Bad effects in batch files, since the source of commands is now
             a batch file,
         (2) Early versions of DOS either didn't have int 2E or changed lots
             of registers, making life difficult, but not impossible. 

> A safer approach, as used by Microsoft in their WHAT.EXE, (a freebie that
> came with masm 5.0) is as follows :
> 
[stuff deleted about chasing back through the PSP chain]

That is the best method, but somebody told me there were problems sometimes
when trying to extend the memory. Possibly the problem is that programs down
the chain look at their PSP to determine the environment starting address once
at the start of execution, and assume it hasn't changed after that. Anyone know
for sure if any programs do that??

The ideal would be (in my opinion) just one copy of the environment, with a bit
of extra space at the end of it, in case it wants to grow.  Many o/s keep
giving sub-processes their own copy of the environment - I can see how that
*might* be nice sometimes, but I've never ever found it useful in practice. Any
comments?? 

> If you insert extra bytes into the env. area, you must be sure that you
> don't go out of the max number allocated to the environment. There's a 
> word in the PSP somewhere that gives you the size of the environment area
> in 16-byte paragraphs, but I just can't remember which. (I don't have 
> the code here, I'm afraid..) I think i found it in one of the public 
> domain dos tech. ref. documents.
> 
I think what you're looking for the the memory allocation block parameters, at
the segment just before the start of the environment, that contains the size
and segment of the next MCB.

Mark Aitchison.

einstein@cs.mcgill.ca (Michael CHOWET) (01/17/91)

In article <1991Jan16.053720.12146@csusac.csus.edu> 
laffeyt@athena.ecs.csus.edu (Tom Laffey) writes:

>There is a fairly complete article about DOS environments in a recent PC mag

  It isn't as recent as you might think. I remeber having come across it in
one of the winter '90 issues. My boss pointed it out for me, and I read it
over, and coded the program

>they include a program called FINDENV.PAS that shows how to
>get access to the "master", or root, copy of the environment. 

  I coded the example, and it does indeed use the method that's been 
mentioned here, namely that of tracing back PSPs. If anyone wants it, 
I can e-mail it (provided I can find it, first... :-)


==============================================================================
Today's message was brought to you by the letter 'S', the number 6, and

  		    =====> Einstein@cs.mcgill.ca  <====
             =====> Mike CHOWET | McGill CSUS VP External <=====

			Post back soon, now y'hear...
==============================================================================

cschmidt@lynx.northeastern.edu (02/08/91)

There was some discussion a while back about writing a program that
accesses the DOS environment of the parent or root process.
Techniques were presented for tracing back through the chain of PSPs
to find the root PSP, then using the value at offset $2C in the root
PSP as the segment address of the root copy of the DOS environment.

Turns out that in Tandy DOS version 03.10.01 the root PSP contains the
value zero at this offset.  I have discovered by inspection that the
root environment is stored in the DOS memory block directly following
the DOS memory block that contains the root PSP.  I can use this fact
as a workaround in the case when $2C contains zero.

(When a secondary copy of COMMAND.COM is loaded, that copy's PSP
contains the correct segment address of its copy of the environment.)

Are there any other versions of DOS that store zero at offset $2C in
the root PSP?  Can I be confident that by employing the workaround
described above, my programs will work with all versions of DOS?

I will summarize to the net replies received by mail.

Christopher Schmidt
cschmidt@lynx.northeastern.edu