[comp.sys.ibm.pc] Setting large environments

madd@bu-cs.UUCP (07/13/88)

In a previous article I gave a sample program showing one way that you
could make an initial environment that was pretty large.
Unfortunately I didn't have time to properly fix things up before I
sent it off, so this is to complete what I'd started and to fix a
couple of problems that I've noticed.

The following program is called "envmake".  If you add it to your
shell= line in \config.sys, it will look for the file \envmake.def and
will read environment entries from there to build an environment.
Each line should be left-justified and should be of the form
<variable>=<setting> just as with the "set" command in command.com.
After building the environment it runs a permanent command.com,
putting the user into the familiar mashdos world.  Note that this
program will eat up several k of your computer's memory.  Some people
won't like it for that, others will like it just for the larger
environment.  You decide.  This may be the only simple way to get a
large environment on some versions of MS-DOS.

This particular program is designed to be an example.  Some things
that you might like to add might be variable environment size (though
MS-DOS memory allocation) and some means of running a command other
than command.com.  Since this is completely off-the-cuff, I have not
been able to test it.  I've used similar routines before in a similar
application, so it should be close.  I think that the stack size could
be reduced but without testing it I'm not sure.  At any rate, I hope
this is useful to someone.

Happy hacking,

jim frost
madd@bu-it.bu.edu

-- cut here --

{ envmake.pas:

  this is a Turbo Pascal 4.0 program that sets up an environment
  before calling the initial COMMAND.COM.  It should be called from
  the shell= line in CONFIG.SYS.

  written by jim frost on 7.12.88.  comments to madd@bu-it.bu.edu.
  this program is in the public domain.
}

{$m 1024,0,0 } { 1k stack, no heap }
{$i-}

program envmake;

uses dos;

const prog = 'envmake';
      fname = '\envmake.def';
      elen = 1023;                 { 1 less than 1024; adjust as necessary }

var env  : array[0..elen] of char; { environment area }
    ptr  : integer;                { ptr in environment area }
    eseg,                          { segment addr of environment }
    eofs : word;                   { offset addr of environment }
    f    : text;                   { file to get defs from }
    s    : string[255];            { string from file of defs }

{ add to the environment buffer }

procedure addenv;
var eq : boolean;
    a  : integer;
begin

  { if we've reached the end of the environment, don't add this }

  if ptr+length(s)+2 > elen then begin
    writeln(prog,': environment area full');
    exit
  end;

  eq:= false;
  for a:= 1 to length(s) do begin
    if s[a] = '=' then
      eq:= true;
    if not eq then                  { capitalize up to '=' }
      env[ptr]:= upcase(s[a]);
    else
      env[ptr]:= s[a];
    inc(ptr)
  end;
  env[ptr]:= #0;                    { terminate string }
  inc(ptr);
  env[ptr]:= #0                     { terminate environment }
end;

begin

  { this gets the pointer to the environment area we've allocated and
    adjusts it to align with a paragraph boundary.  if we were using
    the MS-DOS memory allocation stuff this wouldn't be necessary }

  eseg:= seg(env)+(ofs(env) mod 16);
  eofs:= ofs(env) mod 16;
  if eofs <> 0 then begin
    inc(eseg);
    ptr:= 16 - eofs
  end;
  memw[prefixseg:$2c]:= eseg; { tell dos about it }

  { environment is now at env[ptr], so fill it }

  assign(f,fname);
  reset(f);
  if ioresult <> 0 then
    writeln(prgname,': could not open ',fname)
  else begin
    while not eof(f) do begin
      readln(f,s);
      addenv
    end;
    close(f)
  end;
  exec('\command.com','/p');

  { if we get to here, it's real bad.  tell the user what happened and
    just hang.  if we exit we'll get an error from MS-DOS anyway. }

  writeln('exec: command.com execution failure (',doserror,')');
  repeat until false
end.