home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Crawly Crypt Collection 1
/
crawlyvol1.bin
/
utility
/
system
/
mb45_bin
/
data1.ins
next >
Wrap
Text File
|
1992-03-24
|
18KB
|
330 lines
GEMENV v1.1
Environment Variable Manager for the GEM Desktop
Public Domain Program by Ian Lepore
Overview
Environment variables (referred to as "env vars" in much of this
document) are a facility for storing information in character-string
format for a duration that exceeds the run of a single program. (My,
that sounds stuffy.) Many popular operating systems support env vars,
among them MSDOS, Unix, and GEMDOS. Unfortunately, while GEMDOS
supports env vars, the GEM desktop doesn't, so it's a feature that goes
largely unused on the ST.
This program was written to bring to GEM desktop users all the power of
environment variables that command-shell users have been enjoying for
years. With some software, such as the public domain Sozobon C
compiler, env vars are required for the software to work correctly.
About Environment Variables
Environment variables are stored in memory. They are character strings
with a format of "VARIABLE=VALUE". Every program inherits a copy of
the env vars owned by its parent (the program that started it). DOS is
responsible for making a copy of the parent's env data area at the time
that it starts a new program. It places a pointer to this copy in the
program's basepage, so that the program can access the env var data
through the pointer.
When programming in C, there are two functions for accessing env vars,
getenv() and putenv(). These functions retrieve or store a value in
the env data area. However, since each program receives a copy of its
parent's env vars, using putenv() won't make permanent changes to the
system's env data area; it can only affect the program's local copy.
(GEMENV.PRG uses the ST cookie jar to work around this problem.)
Therefore, the biggest use of env vars for most programs involves
reading the values that are already there. Programs such as compilers
often read env vars to get device and path information such as where to
search for #include files or runtime libraries.
When using GEM, the desktop is the parent program to all programs that
are started by clicking on a file. These programs, therefore, inherit
a copy of the desktop's env data area. Unfortunately, the desktop
doesn't keep much useful information in its env data area. In fact,
it's only a few bytes long, and contains the string "PATH=C:\" (or
"PATH=A:\"). GEM itself uses this env var (PATH=) to locate RSC files
when they are not found in the current default directory.
Using GEMENV
The GEMENV program has two different modes, depending on whether it is
run from the AUTO folder or from the desktop. When run from AUTO, it
prepares the system to support env vars, and loads the initial env vars
from a file called ROOT.ENV, which must be in the root directory of the
boot drive. This process is described in greater detail in the section
labeled "How GEMENV Works."
When run from the desktop, the program does a check to see if it was
installed from the AUTO folder at bootup time. If not, the program
will complain that a root environment doesn't exist. In this case, you
can still use the program to create an initial set of env vars and save
them into a ROOT.ENV file, and then reboot to install them into the
system. (If you obtained this program as part of Ian's Sozobon C
release, the Sozobon installation program will have created your
initial ROOT.ENV file for you.)
The main interface to the program is a large dialog box that lists all
the current in-memory env vars and their values. At the bottom of the
dialog is a series of buttons providing access to the major functions
of the program. The displayed variables are also active buttons:
clicking on a variable in the scolling area of the dialog will bring up
the edit dialog which allows you to edit or delete a variable.
Most of the buttons are self-explanatory, but several need further
explanation. The CANCEL button will allow you to exit the program
without saving any changes you've done into the system env data area.
The OK button saves all changes INTO MEMORY ONLY, and then exits.
The OPTIONS button provides access to the LOAD FILE and SAVE FILE
options. It is possible to start the program, use the LOAD option to
load a set of variables from a file, make changes to the variables, use
the SAVE option to store them, and then exit via CANCEL so that the
changes don't affect the current in-memory variables even though
they've been stored to a file. It can be handy to keep several
different configurations stored in different files, especially if you
use more than one C compiler. Remember that at bootup time, GEMENV
will only install itself if a ROOT.ENV file exists, so this file should
contain your most common configuration.
The OPTIONS dialog also provides a choice between PC FORMAT and TOS
FORMAT environment variables. This choice affects the way the
variables are formatted in memory. TOS FORMAT variables treat the
variable's name and value as two separate strings, each with its own
null terminator character (eg, "VARIABLE=\0VALUE\0"). The more common
PC FORMAT stores the variable name and value as a single string (eg,
"VARIABLE=VALUE\0"). It is recommended that you use PC FORMAT unless
your software specifically requires TOS FORMAT. (You may need to use
TOS FORMAT if you're using TOS 1.0 -- I'm not sure about this yet.)
GEMENV places few restrictions on the names or values stored in env
vars. The only hardcore restrictions are that variable names can't
contain an '=' character (since that delimits the name from the value),
and you can't store binary data in the name or value string. (Mainly
because GEMENV doesn't have a hex editor, but also because a binary
zero in any position would be mistaken for the end of the value
string.) In general, the programs which use env vars dictate what the
names of env vars must be and what types of data should appear in the
value string. Most programs require uppercase names, and some require
uppercase values, but these are not universal standards.
The GEM desktop really likes to see a PATH= variable in the set
somewhere, and the value string must be a list of valid pathnames
separated with semicolons between each name, and with the trailing
backslash on each pathname. Most ST software that uses a PATH=
variable is also happy with this format. (And, if you design your own
software, you should stay compatible with this if you access the PATH=
variable.) As mentioned previously, GEM will search the paths listed
in PATH= for .RSC files, If you want, you can put all your resource
files in one place and put that pathname in the PATH= list. This can
also be handy when you have installed applications. By putting all
your installed aps and their RSC files into one path, and listing that
path in the PATH= var, you'll never run into the "cannot load RSC file"
glitches that installed aps are prone to.
There will always be two special variables in your configuration which
you cannot delete: ENV$ROOTSIZE and ENV$OPTIONS. ENV$OPTIONS stores
the state of the buttons in the options dialog, so that whenever
you use the program, the options will be as you last set them. The
ENV$ROOTSIZE variable tells the program how much memory to allocate for
env data area at bootup time. Since you might add to the env vars at
any time by running GEMENV, a little extra memory is always allocated
when the ROOT.ENV file is loaded. The program, by default, uses the
size of the current env data, rounded up to the next 1k boundry.
Typically, ENV$ROOTSIZE will always equal 1024 unless you have a lot of
vars. You can manually change this value upwards if you need to, but
it can never be made smaller than the current size rounded up to the
next 1k (if you try, the program overrides you when you save.)
The format of the ROOT.ENV file (and other .ENV files) is compatible
with a normal text editor. Each line contains a single entry in the
format NAME=VALUE, and the lines are terminated with a CRLF sequence
(or simply LF). An installation utility program might want to create
or modify the ROOT.ENV file, and that's fine, given that it follows a
couple simple rules:
- There MUST be an ENV$ROOTSIZE variable, and it MUST be an even
multiple of 1024 bytes, and the value MUST be larger than the
total size of all the env data in the file.
- There MUST be an ENV$OPTIONS variable. If one exists already,
don't monkey with the values in it. If you are creating a .ENV
file from scratch, create this as ENV$OPTIONS=TYY. If you use
any other value beside TYY, don't come crying to me if the
GEMENV fails to work correctly!
If you are modifying an existing ROOT.ENV file programmatically, please
be aware that the user may be fond of the values s/he currently has
stored in the variables. To add your software path, for example, don't
just create a new PATH= variable, append your path to what's already
there. If for some reason you just can't take the time to code up a
fancy modification program to handle the data that's already there,
then at the very least create a ROOT.BAK for the user which contains
the current data before you modify it.
How GEMENV Works
As mentioned above, whenever a program starts, DOS provides that
program a copy of its parent's env data area. This applies to the
process that TOS uses to start the GEM desktop as well. After all the
AUTO programs have finished running, TOS creates a basepage for the
desktop using the standard DOS Pexec() call. However, rather than
loading a file from disk to execute, it jumps through the exec_os
vector at $4FE in low memory after the basepage is created.
When the GEMENV program is run from the AUTO folder it detects that
fact by trying to do an appl_init() call and getting a bad status
because GEM isn't available yet. When this happens, it bypasses the
normal dialog stuff it does when run from the desktop. Instead, it
loads the env vars from the ROOT.ENV file, and checks the value of the
ENV$ROOTSIZE variable. It allocates that much memory and stores the
env vars (in TOS or PC format, as indicated by the ENV$OPTIONS var.)
After the env data area is set up, GEMENV installs a cookie in the
system cookie jar so that it can locate the installed data area later,
when run from the desktop. (If a cookie jar doesn't exist yet in the
system, one is installed in the standard Atari-recommended fashion.)
The cookie used is "ENV$", which isn't likely to conflict with any
existing cookies (and GEMENV will work even if there is a conflict,
although it's quite likely that the any other user of an "ENV$" cookie
would die.)
Next, the program saves the current contents of the exec_os system
vector, and places a 'hook' into that vector, so that when TOS jumps
through the vector to start the desktop, a routine in the resident
portion of GEMENV will get control instead. Once this is done, GEMENV
issues a Ptermres() call to remain resident, keeping only a small
program stub (about 300 bytes) and the env data itself. The stub and
the data are adjacent; GEMENV's installation will not fragment your
free memory area like some TSRs do.
When all the other AUTO programs are done, and TOS starts the desktop,
the stub left resident by GEMENV gets control. All this stub does is
replace the environment data pointer in the current program basepage
with a pointer to the data area loaded from the ROOT.ENV file. It then
restores the old value of the exec_os vector, then jumps through that
vector. Because the env data pointer in the desktop's basepage was
changed, the desktop starts with the full contents of the ROOT.ENV data
area instead of the minimal PATH=C:\ data area that TOS created for it.
When the desktop starts other programs, it will pass copies of this
full data area along to everyone else.
Note that GEMENV does not leave any hooks in any system vectors once
the desktop has started. After replacing the env pointer and passing
control along to the desktop, the resident portion of GEMENV never
executes anything again; it just sits there providing a data area for
everyone else. In this sense, GEMENV is a passive TSR that is unlikely
to interfere with anything else in the system.
Also note that there are other programs in the world that use the
exec_os vector. Foremost among these are the replacement desktop
programs that install themselves in place of the GEM desktop. Because
a replacement desktop truly steals the exec_os vector (rather than
borrowing it and then jumping through it as GEMENV does), it may be
necessary to play with the order of the files in your AUTO folder a bit
to ensure that GEMENV can briefly gain control of the system. In
general, if GEMENV reports successfull installation while AUTO stuff is
running, and then complains about no root env data when you run it from
the desktop, try rearranging your AUTO folder.
Programming Notes
It was mentioned earlier that your programs can't modify the system env
data because they are really only modifying their own local copy of the
env data when the putenv() function is used. Your programs can,
however, use the same technique that GEMENV uses to modify the main
system env data area.
This techique involves locating the root data area via the ENV$ cookie,
then accessing that memory directly. I'm not going to go into a long
discussion of using the cookie jar; see the appropriate Atari docs for
info on how to locate the ENV$ cookie. The value of the ENV$ cookie is
a 32-bit pointer to the following data structure:
struct gemenv_control {
long magic;
short version;
char *pdata;
long sdata;
long reserved[4];
};
The 'magic' field must contain the value 0x04021959. If it does not,
someone else is also using ENV$ as a cookie, and you found them, not
GEMENV. In this case, just keep searching, you may find another ENV$
cookie that points to the right magic value.
The version word is the installed GEMENV version, encoded as 0xVVRR,
where VV is the major version and RR is the release. The current v1.1
value is 0x0101.
The pdata field is the pointer to the root env data area. It is this
pointer that you would use to access the env vars directly. (But,
NEVER EVER modify this pointer! (Or, for that matter, anything else in
this structure.) Doing so will break GEMENV, and it will NOT cause the
desktop to see a new set of env vars; that can only be done via the
exec_os hook.)
The sdata field is the size of the root env data area. If you modify
the root area, you must ensure that the modifications don't exceed this
size.
The reserved array is just that: reserved. Right now, this will be
four longwords of zeroes. Someday, I'm going to provide a programmatic
interface so that you don't have to manipulate the root data directly
but can call gputenv() and ggetenv() to access the global data instead
of your program's local copy. When I do that, the vectors for the
functions will go here.
Credits and Disclaimers
I'd like to thank Mike Dorman for helping me test this program, and Bob
Goff for both testing, and for obtaining the Atari docs on the cookie
jar for me. I'd like to thank David Stabb for inspiring the program,
although I'm sure that by now he's quite forgotten how or why he was
inspirational in this project. :-)
This program, the executable code, documents, and source code are all
in the public domain, and the author specifically releases any and all
rights associated with it. You are free to modify and/or use this work
in any way you see fit. You may include or distribute this work as a
part of your own product or program, be it public domain, shareware, or
commercial. If you incorporate this into your own product, there is no
need to include any reference to me or my work on it unless you feel
like it. I just want to see it distributed widely, and I want to see
ST applications start to make better use of environment variables.
This software is delivered on an as-is basis, and no warranties are
made, including warranty of suitability for a particular purpose. The
author assumes no responsibility for the consequences of using this
software, even if the consequences result from defects in this
program. Besides, I don't have enough money to make suing me worth
your while. :-)
Ian Lepore
moderator, BIX atari.st and c.language conferences
07/19/91
--------------------------------------------------------
< OK TO PORT >
This information comes from the atari.st conference
on BIX (r), the BYTE Information Exchange.
For additional information about BIX, call 800-227-2983
or 603-924-7681.
---------------------------------------------------------