[Back to DOS SWAG index]  [Back to Main SWAG index]  [Original]

{----------------------------------------------------------}
{  Unit to get/set environment vars                        }
{  Kai Pijpstra, Groningen, the Netherlands, 1996          }
{----------------------------------------------------------}
unit Environ;
{$R-,X+}
interface

type
  PCharArray = ^TCharArray;
  TCharArray = array[0..0] of char;

  PPSP = ^TPSP;
  TPSP = record
    Int20hInstruction   : word;
    MemorySize          : word;
    Reserved1           : byte;
    DOSFuncDispatcher   : array[0..4] of byte;
    Int22h              : pointer;
    Int23h              : pointer;
    Int24h              : pointer;
    ParentSegment       : word;
    FileHandleArray     : array[0..19] of byte;
    EnvSegment          : word;
    LastSSSP            : pointer;
    HandleArraySize     : word;
    HandleArrayPtr      : pointer;
    PreviousPSP         : pointer;
    Reserved3           : array[0..19] of byte;

    Int21hRetf          : array[0..2] of byte;
    Reserved4           : array[0..8] of byte;
    FCB1                : array[0..15] of byte;
    FCB2                : array[0..19] of byte;
    ParamString         : string[127];
  end;

function  GetPSP:PPSP;
{ Get current PSP }

function  GetMasterPSP:PPSP;
{ Get PSP of Master COMMAND.COM }

function  EnvFromPSP(PSP:PPSP):PCharArray;
{ Retrieve pointer to environment from PSP }

function  GetEnvStr(Env:PCharArray; SubStr:string):PCharArray;
{ Find a substring in the environment }

procedure DelEnvStr(Env:PCharArray; SubStr:string);
{ Delete a substring in the environment }

procedure AddEnvStr(Env:PCharArray; SubStr:string);
{ Add a substring to the environment }

implementation
uses dos;
type
  PMCB = ^TMCB;
  TMCB = record
    Ident               : char;
    OwnerPSPSeg         : word;
    Size                : word;
    reserved            : array[0..10] of byte;
    ProgramName         : array[0..7] of char;
    Data                : array[0..0] of byte;
  end;

function ASCIIZLength(S:PCharArray):integer;
var I:integer;
begin
  I:=0;
  while S^[I]<>#0 do Inc(I);
  ASCIIZLength:=I;
end;

function PtrVal(P:Pointer):LongInt;
begin
  PtrVal:=Seg(P^)*16+Ofs(P^)
end;

function PtrDiff(P1,P2:pointer):LongInt;
begin
  PtrDiff:=PtrVal(P2)-PtrVal(P1);
end;

{----------------------------------------------------------}
const
  EnvSize       : word = 0;

function GetFP(S:String):string;
var I:Integer;
begin
  I:=Pos('=',S);
  if I=0 then GetFP:=''
  else GetFP:=Copy(S,1,I);
end;

function GetEnvSize(PSP:PPSP):word;
begin
  GetEnvSize:=PMCB(ptr(PSP^.EnvSegment-1,0))^.Size*16;
end;

function GetPSP:PPSP;
var regs:registers; PSP:PPSP;
begin
  with regs do begin
    ah:=$62;
    MsDos(regs);
    PSP:=ptr(bx,0);
    EnvSize:=GetEnvSize(PSP);
  end;
  GetPSP:=PSP;
end;

function GetMasterPSP:PPSP;
var DPSP,PSP:PPSP;
begin
  DPSP:=GetPSP;
  repeat
    PSP:=DPSP;
    DPSP:=ptr(PSP^.ParentSegment,0);
  until(PSP=DPSP);
  EnvSize:=GetEnvSize(PSP);
  GetMasterPSP:=PSP;
end;

function GetEnvStr(Env:PCharArray; SubStr:string):PCharArray;
var I,Start:word; S:String;
  function GetNextString(var S:String):boolean;
  begin
    GetNextString:=Env^[I]<>#0;
    S:='';
    while Env^[I]<>#0 do begin
      S:=S+Env^[I];
      Inc(I);
    end;
  end;
begin
  GetEnvStr:=nil;
  I:=0; Start:=0;
  SubStr:=GetFP(SubStr);
  repeat
    if not GetNextString(S) then exit;
    if Pos(SubStr,S)<>0 then begin
      GetEnvStr:=ptr(Seg(Env^),Start);
      exit;
    end;
    Inc(I);
    Start:=I;
  until 1+1=3;
end;

function FindEnvEnd(Env:PCharArray):word;
var I:word;
begin
  I:=0;
  while Env^[I]<>#0 do begin
    while Env^[I]<>#0 do Inc(I);
    Inc(I);
  end;
  FindEnvEnd:=I;
end;

procedure DelEnvStr(Env:PCharArray; SubStr:string);
var NewEnv:PCharArray; S:PCharArray; Diff,SSize:word;
begin
  GetMem(NewEnv,EnvSize);
  Move(Env^,NewEnv^,EnvSize);
  S:=GetEnvStr(NewEnv,SubStr);
  if S<>nil then begin
    SSize:=ASCIIZLength(S)+1;
    Diff:=PtrDiff(NewEnv,S);
    Move(NewEnv^[Diff+SSize],NewEnv^[Diff],EnvSize-(Diff+SSize));
    Move(NewEnv^,Env^,EnvSize);
  end;
  FreeMem(NewEnv,EnvSize);
end;

procedure AddEnvStr(Env:PCharArray; SubStr:string);
var NewEnv:PCharArray; EEnd,SSize:word;
begin
  GetMem(NewEnv,EnvSize);
  Move(Env^,NewEnv^,EnvSize);
  DelEnvStr(NewEnv,SubStr);
  EEnd:=FindEnvEnd(NewEnv);
  SubStr:=SubStr+#0#0;
  SSize:=Length(SubStr);
  while(SSize>0)and(SSize+EEnd>EnvSize) do Dec(SSize);
  if SSize>0 then begin
    Move(SubStr[1],NewEnv^[EEnd],SSize);
    Move(NewEnv^,Env^,EnvSize);
  end;
  FreeMem(NewEnv,EnvSize);
end;

function EnvFromPSP;
begin
  EnvFromPSP:=ptr(PSP^.EnvSegment,0);
end;

{----------------------------------------------------------}

end.

{TEST PROGRAM

uses Crt,Environ;

procedure WriteLnASCIIZ(S:PCharArray);
var I:integer;
begin
  I:=0;
  while S^[I]<>#0 do begin
    Write(S^[I]);
    Inc(I);
  end;
end;

procedure WriteEnv(Env:PCharArray);
var I:integer;
begin
  I:=0;
  while Env^[I]<>#0 do begin
    while Env^[I]<>#0 do begin
      Write(Env^[I]);
      Inc(I);
    end;
    WriteLn;
    Inc(I);
  end;
end;

var ENV:PCharArray; PSP:PPSP;
  I:integer;
begin
  ClrScr;
  PSP:=GetMasterPSP;
  Env:=EnvFromPSP(PSP);
  DelEnvStr(Env,'KAI=');
  WriteEnv(Env);
  WriteLn('--');
  AddEnvStr(Env,'KAI=GEK !!');
  WriteEnv(Env);
end.

[Back to DOS SWAG index]  [Back to Main SWAG index]  [Original]