Skip to main content
Stack Overflow
  1. About
  2. For Teams

Return to Revisions

7 of 9
Fix a problem that caused mis-rendering.
pradyunsg
  • 19.9k
  • 11
  • 49
  • 99

It must have been a millennium ago that I've tried to change the environment of the current DOS session by means of a program. The problem is: that program runs within its own DOS shell, so it has to operate on its parent environment. It takes a walk, starting at the DOS Info Block, all along the chain of Memory Control Blocks, to find the location of that parent environment. Once I had found out how to do this, my need for manipulating environment variables had vanished. I'll give you the Turbo Pascal code below, but I guess there are at least three better ways to do the trick:

  1. Create a batch file that: (a) calls a Python script (or whatever) that generates a temporay batch file containing the appropriate SET commands; (b) calls the temporary batch file (the SET commands are executed in the current shell); and (c) removes the temporary batch file.

  2. Create a Python script that writes something like "VAR1=val1\nVAR2=val2\nVAR3=val3\n" to STDOUT. Use it this way in your batch file:

    for /f "delims=|" %%X in ('*callYourPythonScript*') do set %%X
    

    et voilà: variables VAR1, VAR2 and VAR3 have been given a value.

  3. Modify the Windows Registry and broadcast the setting change as described here by Alexander Prokofyev.

And here goes the Pascal code (you may need a Dutch dictionary and a Pascal programming book) of a program that just reports memory locations. It still seems to work under Windows XP, be it reporting we're running DOS 5.00. This is only a first beginning, there's a lot of low level programming to do in order to manipulate the selected environment. And as the pointer structure may seem correct, I'm not so sure if the environment model of 1994 still holds these days...

program MCBKETEN;
uses dos, HexConv;
{----------------------------------------------------------------------------}
{ Programma: MCBKETEN.EXE }
{ Broncode : MCBKETEN.PAS }
{ Doel : Tocht langs de MCB's met rapportage }
{ Datum : 11 januari 1994 }
{ Auteur : Meindert Meindertsma }
{ Versie : 1.00 }
{----------------------------------------------------------------------------}
type
 MCB_Ptr = ^MCB;
{ MCB_PtrPtr = ^MCB_Ptr; vervallen wegens DOS 2.11 -- zie verderop }
 MCB = record
 Signatuur : char;
 Eigenaar : word;
 Paragrafen : word;
 Gereserveerd : array[1..3] of byte;
 Naam : array[1..8] of char;
 end;
 BlokPtr = ^BlokRec;
 BlokRec = record
 Vorige : BlokPtr;
 DitSegment,
 Paragrafen : word;
 Signatuur : string[6];
 Eigenaar,
 Omgeving : word;
 Functie : String4;
 Oorsprong,
 Pijl : char;
 KorteNaam : string[8];
 LangeNaam : string;
 Volgende : BlokPtr;
 end;
 PSP_Ptr = ^PSP;
 PSP = record
 Vulsel1 : array[1..44] of byte;
 Omgeving : word;
 Vulsel2 : array[47..256] of byte;
 end;
var
 Zone : string[5];
 ProgGevonden,
 EindeKeten,
 Dos3punt2 : boolean;
 Regs : registers;
 ActMCB : MCB_Ptr;
 EersteSchakel, Schakel,
 LaatsteSchakel : BlokPtr;
 ActPSP : PSP_Ptr;
 EersteProg,
 Meester, Ouder,
 TerugkeerSegment,
 TerugkeerOffset,
 TerugkeerSegment2,
 OuderSegment : word;
 Specificatie : string[8];
 ReleaseNummer : string[2];
 i : byte;
{----------------------------------------------------------------------------}
{ PROCEDURES EN FUNCTIES }
{----------------------------------------------------------------------------}
function Coda (Omgeving : word; Paragrafen : word) : string;
var
 i : longint;
 Vorige, Deze : char;
 Streng : string;
begin
 i := 0;
 Deze := #0;
 repeat
 Vorige := Deze;
 Deze := char (ptr (Omgeving, i)^);
 inc (i);
 until ((Vorige = #0) and (Deze = #0)) or (i div 10ドル >= Paragrafen);
 if (i + 3) div 10ドル < Paragrafen then begin
 Vorige := char (ptr (Omgeving, i)^);
 inc (i);
 Deze := char (ptr (Omgeving, i)^);
 inc (i);
 if (Vorige = #01) and (Deze = #0) then begin
 Streng := '';
 Deze := char (ptr (Omgeving, i)^);
 inc (i);
 while (Deze <> #0) and (i div 10ドル < Paragrafen) do begin
 Streng := Streng + Deze;
 Deze := char (ptr (Omgeving, i)^);
 inc (i);
 end;
 Coda := Streng;
 end
 else Coda := '';
 end
 else Coda := '';
end {Coda};
{----------------------------------------------------------------------------}
{ HOOFDPROGRAMMA }
{----------------------------------------------------------------------------}
BEGIN
 {----- Initiatie -----}
 Zone := 'Lower';
 ProgGevonden := FALSE;
 EindeKeten := FALSE;
 Dos3punt2 := (dosversion >= 1403ドル) and (dosversion <= 1ドルD03);
 Meester := 0000ドル;
 Ouder := 0000ドル;
 Specificatie[0] := #8;
 str (hi (dosversion) : 2, ReleaseNummer);
 if ReleaseNummer[1] = ' ' then ReleaseNummer[1] := '0';
 {----- Pointer naar eerste MCB ophalen ------}
 Regs.AH := 52ドル; { functie 52ドル geeft adres van DOS Info Block in ES:BX }
 msdos (Regs);
{ ActMCB := MCB_PtrPtr (ptr (Regs.ES, Regs.BX - 4))^; NIET onder DOS 2.11 }
 ActMCB := ptr (word (ptr (Regs.ES, Regs.BX - 2)^), 0000ドル);
 {----- MCB-keten doorlopen -----}
 new (EersteSchakel);
 EersteSchakel^.Vorige := nil;
 Schakel := EersteSchakel;
 repeat
 with Schakel^ do begin
 DitSegment := seg (ActMCB^);
 Paragrafen := ActMCB^.Paragrafen;
 if DitSegment + Paragrafen >= $A000 then
 Zone := 'Upper';
 Signatuur := Zone + ActMCB^.Signatuur;
 Eigenaar := ActMCB^.Eigenaar;
 ActPSP := ptr (Eigenaar, 0);
 if not ProgGevonden then EersteProg := DitSegment + 1;
 if Eigenaar >= EersteProg
 then Omgeving := ActPSP^.Omgeving
 else Omgeving := 0;
 if DitSegment + 1 = Eigenaar then begin
 ProgGevonden := TRUE;
 Functie := 'Prog';
 KorteNaam[0] := #0;
 while (ActMCB^.Naam[ ord (KorteNaam[0]) + 1 ] <> #0) and
 (KorteNaam[0] < #8) do
 begin
 inc (KorteNaam[0]);
 KorteNaam[ ord (KorteNaam[0]) ] :=
 ActMCB^.Naam[ ord (KorteNaam[0]) ];
 end;
 if Eigenaar = prefixseg then begin
 TerugkeerSegment := word (ptr (prefixseg, 000ドルC)^);
 TerugkeerOffset := word (ptr (prefixseg, 000ドルA)^);
 LangeNaam := '-----> Terminate Vector = ' +
 WordHex (TerugkeerSegment) + ':' +
 WordHex (TerugkeerOffset ) ;
 end
 else
 LangeNaam := '';
 end {if ÆProgØ}
 else begin
 if Eigenaar = 0008ドル then begin
 if ActMCB^.Naam[1] = 'S' then
 case ActMCB^.Naam[2] of
 'D' : Functie := 'SysD';
 'C' : Functie := 'SysP';
 else Functie := 'Data';
 end {case}
 else Functie := 'Data';
 KorteNaam := '';
 LangeNaam := '';
 end {if Eigenaar = 0008ドル}
 else begin
 if DitSegment + 1 = Omgeving then begin
 Functie := 'Env ';
 LangeNaam := Coda (Omgeving, Paragrafen);
 if EersteProg = Eigenaar then Meester := Omgeving;
 end {if ÆEnvØ}
 else begin
 move (ptr (DitSegment + 1, 0)^, Specificatie[1], 8);
 if (Specificatie = 'PATH=' + #0 + 'CO') or
 (Specificatie = 'COMSPEC=' ) or
 (Specificatie = 'OS=DRDOS' ) then
 begin
 Functie := 'Env' + chr (39);
 LangeNaam := Coda (DitSegment + 1, Paragrafen);
 if (EersteProg = Eigenaar) and
 (Meester = 0000ドル )
 then
 Meester := DitSegment + 1;
 end
 else begin
 if Eigenaar = 0
 then Functie := 'Free'
 else Functie := 'Data';
 LangeNaam := '';
 if (EersteProg = Eigenaar) and
 (Meester = 0000ドル )
 then
 Meester := DitSegment + 1;
 end;
 end {else: not ÆEnvØ};
 KorteNaam := '';
 end {else: Eigenaar <> 0008ドル};
 end {else: not ÆProgØ};
 {----- KorteNaam redigeren -----}
 for i := 1 to length (KorteNaam) do
 if KorteNaam[i] < #32 then KorteNaam[i] := '.';
 KorteNaam := KorteNaam + ' ';
 {----- Oorsprong vaststellen -----}
 if EersteProg = Eigenaar
 then Oorsprong := '*'
 else Oorsprong := ' ';
 {----- Actueel proces (uitgaande Pijl) vaststellen -----}
 if Eigenaar = prefixseg
 then Pijl := '>'
 else Pijl := ' ';
 end {with Schakel^};
 {----- MCB-opeenvolging onderzoeken / schakelverloop vaststellen -----}
 if (Zone = 'Upper') and (ActMCB^.Signatuur = 'Z') then begin
 Schakel^.Volgende := nil;
 EindeKeten := TRUE;
 end
 else begin
 ActMCB := ptr (seg (ActMCB^) + ActMCB^.Paragrafen + 1, 0);
 if ((ActMCB^.Signatuur <> 'M') and (ActMCB^.Signatuur <> 'Z')) or
 ($FFFF - ActMCB^.Paragrafen < seg (ActMCB^) )
 then begin
 Schakel^.Volgende := nil;
 EindeKeten := TRUE;
 end
 else begin
 new (LaatsteSchakel);
 Schakel^.Volgende := LaatsteSchakel;
 LaatsteSchakel^.Vorige := Schakel;
 Schakel := LaatsteSchakel;
 end {else: (ÆMØ or ÆZØ) and Æteveel_ParagrafenØ};
 end {else: ÆLowerØ or not ÆZØ};
 until EindeKeten;
 {----- Terugtocht -----}
 while Schakel <> nil do with Schakel^ do begin
 {----- Ouder-proces vaststellen -----}
 TerugkeerSegment2 := TerugkeerSegment + (TerugkeerOffset div 10ドル);
 if (DitSegment <= TerugkeerSegment2) and
 (DitSegment + Paragrafen >= TerugkeerSegment2)
 then
 OuderSegment := Eigenaar;
 {----- Meester-omgeving markeren -----}
 if DitSegment + 1 = Meester then Oorsprong := 'M';
 {----- Schakel-verloop -----}
 Schakel := Schakel^.Vorige;
 end {while Schakel <> nil};
 {----- Rapportage -----}
 writeln ('Chain of Memory Control Blocks in DOS version ',
 lo (dosversion), '.', ReleaseNummer, ':');
 writeln;
 writeln ('MCB@ #Par Signat PSP@ Env@ Type !! Name File');
 writeln ('---- ---- ------ ---- ---- ---- -- -------- ',
 '-----------------------------------');
 Schakel := EersteSchakel;
 while Schakel <> nil do with Schakel^ do begin
 {----- Ouder-omgeving vaststellen -----}
 if Eigenaar = OuderSegment then begin
 if not Dos3punt2 then begin
 if (Functie = 'Env ') then begin
 Ouder := DitSegment + 1;
 Pijl := 'Û';
 end
 else
 Pijl := '<';
 end {if not Dos3punt2}
 else begin
 if ((Functie = 'Env' + chr (39)) or (Functie = 'Data')) and
 (Ouder = 0000ドル)
 then begin
 Ouder := DitSegment + 1;
 Pijl := 'Û';
 end
 else
 Pijl := '<';
 end {else: Dos3punt2};
 end {with Schakel^};
 {----- Keten-weergave -----}
 writeln (WordHex (DitSegment) , ' ',
 WordHex (Paragrafen) , ' ',
 Signatuur , ' ',
 WordHex (Eigenaar) , ' ',
 WordHex (Omgeving) , ' ',
 Functie , ' ',
 Oorsprong, Pijl , ' ',
 KorteNaam , ' ',
 LangeNaam );
 {----- Schakel-verloop -----}
 Schakel := Schakel^.Volgende;
 end {while Schakel <> nil};
 {----- Afsluiting rapportage -----}
 writeln;
 write ('* = First command interpreter at ');
 if ProgGevonden
 then writeln (WordHex (EersteProg), ':0000')
 else writeln ('?');
 write ('M = Master environment at ');
 if Meester > 0000ドル
 then writeln (WordHex (Meester), ':0000')
 else writeln ('?');
 write ('< = Parent proces at ');
 writeln (WordHex (OuderSegment), ':0000');
 write ('Û = Parent environment at ');
 if Ouder > 0000ドル
 then writeln (WordHex (Ouder), ':0000')
 else writeln ('?');
 writeln ('> = Current proces at ',
 WordHex (prefixseg), ':0000');
 writeln (' returns to ',
 WordHex (TerugkeerSegment), ':', WordHex (TerugkeerOffset));
END.

(Above ASCII 127, there may be some ASCII/ANSI translation issues in this presentation.)

Meindert Meindertsma

AltStyle によって変換されたページ (->オリジナル) /