[comp.lang.pascal] How to SET environment variables inside your program

phys169@csc.canterbury.ac.nz (12/07/90)

In case anyone wants to know how to set environment variables from within a
Turbo Pascal program (so they're set when you exit the program), here's the
code. (I think someone may have asked for it yonks ago). Basically it means
changing your program's environment segment to your parent's environment
segment, since each level of call gets its own environment space. I've used int
$2E to do the actual setting, partly because it is easier, and also as an
example in how to call it (you might have stack problems in DOS 2, though, and
not all early versions of DOS support it).

--snip---SETDEMO.PAS--------
program SetDemo; {Demonstrate setting environment variables within a Pascal program}
                 {note : no effect in Turbo Intercative Environment}
                 {WARNING: might not work in DOS pre ver 3 (due to use of int $2E)}
{$M 4000,000,000}
uses DOS;
                {Sept 1990, by Mark Aitchison}

const ProgramName = 'SETDEMO';
      CommandSyntax=' var=value ';
      Version     = '1.1' {$IFOPT R+} +'a' {$ENDIF} ;
      Author      = 'M.Aitchison@canterbury.ac.nz';
      CopyrightNotice ='(C) 1990 by '+Author+'.'^M^J+
                    'You may use & distribute this program.';
      ValidOptions= '';
      WhatItDoes  = 'Use '+ProgramName+' to set environment variables, like the SET internal command';
      {really a demonstration of how you can do it inside other programs}

type PSP = record Junk :array[0..$15] of byte;
                  Parent : word;
                  MoreJunk : array[$18..$2B] of byte;
                  Environment : word;
                  YetMoreJunk : array[$2E..$7F] of byte;
                  CommandParameters : string[127];
                  end;
var reg : registers;
    st  : string;
    ParentPointer,
    PSPpointer : ^PSP;
    ENVpointer : pointer;

procedure InvokeCommand(segment,offset : word);
inline($5A/$59     {pop dx & cx}
      /$55/$1E     {push bp & ds}
      /$8E/$D9     {mov ds,cx}
      /$8e/$c1     {mov es,cx}
      /$89/$d6     {mov si,dx}
      /$CD/$2E     {int 2Eh}
      /$1F/$5E     {pop ds & bp}
      );

begin
PSPpointer:=ptr(PrefixSeg,0);
ENVpointer:=ptr(PSPpointer^.Environment,0);
Parentpointer:=ptr(PSPpointer^.Parent,0);
PSPpointer^.Environment:=ParentPointer^.Environment;
if seg(ENVpointer^)<>PSPpointer^.Environment then with reg do
   begin
   AH:=$49; {Free memory of my original environment 'cause I'm using daddy's}
   ES:=seg(ENVpointer^);
   MsDos(reg);
   end;
st:='SET '+PSPpointer^.CommandParameters+^M;
InvokeCommand(seg(st[0]),ofs(st[0]));
{doing it without int $2E is left as an easy exercise for the reader}
end.