Environment Strings, Teil 3: Anwendung unter GEM

Da wir nun wissen, wie Environment-Strings funktionieren und wie sie anzuwenden sind, wollen wir sehen, was unter GEM damit anzufangen ist. Alles in Teil 2 Gesagte gilt natürlich auch für GEM.

Das Environment des GEM wird beim Start des AES festgelegt. Dazu ein kleiner Ausflug zu MS-DOS (gibt’s auch noch), das ja bekanntlich unserem TOS sehr ähnlich ist. Nach dem Booten befindet man sich dort in der Kommando-Shell command.com. Das Environment wird mittels autoexec.bat gesetzt. GEM (befindet sich auf der Platte) kann nun aus der Shell mit diesem Environment gestartet werden. Der ST beherbergt GEM im ROM. Dort wird es nach dem Booten gestartet, und dort wird auch das Environment erzeugt. Atari hat eine Einflußmöglichkeit für den Anwender leider vergessen.

Wer das Programm env.tos aus Teil 1 einmal direkt vom Desktop aus gestartet hat, bekam das Environment des GEM zu Gesicht. In den allermeisten Fällen gibt es hier nichts Vernünftiges zu sehen. Schade, aber warum nicht? Wie gesagt, das GEM-Environment wird bei Start des AES festgelegt. Das AES ist ein Programm wie jedes andere und bekommt beim Aufruf (mit Pexec) natürlich einen Zeiger auf die Environment-Strings mit auf den Weg. Ich habe einen Auszug der Systeminitialisierung des TOS 1.4 disassembliert (rom.lst). Die Grundinitialisierung ist an dieser Stelle schon erledigt. Es wird zunächst die Systemvariable _cmdload getestet. Ist sie TRUE (!= 0), wird das Programm „command.prg“ gestartet, nachdem der AUTO-Ordner abgearbeitet wurde. _cmdload kann durch ein Programm im Boot-Sektor gesetzt werden, im Normalfall steht hier FALSE (0). In diesem Fall wird nach Abarbeitung des AUTO-Ordners das AES gestartet. Dazu wird mit Pexec(5,...) eine Basepage für das ROM-Programm erzeugt, das dann mit Pexec(4,...) gestartet wird. Dabei wird die Adresse des Environments ($840) übergeben, das zuvor erzeugt wurde. Hier sollte „PATH=X:\“ stehen (X = Boot-Laufwerk), was spärlich genug ist. Durch mehrere bugs entsteht aber immer „PATH= “. Können wir daran nun drehen, ohne gleich das ROM zu patchen? Ja, denn vor Start des AES wird ja der AUTO-Ordner ausgeführt. Installieren wir dort ein Programm, das das AES startet, können wir ein vernünftiges Environment setzen. Setenv.c ist die Quelle eines solchen Programms. Es vollzieht den Ablauf im ROM nach, erzeugt jedoch ein Environment, das mit der Datei setenv.inf konfiguriert werden kann. Jede Zeile in der Datei erzeugt einen Environment-String. Setenv.inf könnte z.B. so aus sehen:

PATH=c:\bin;c:\turbo_c\bin;.
SHELL=c:\bin\mupfel.prg LIB=c:\lib
INCLUDE=c:\include TMP=e:\tmp
CLIPBRD=e:\clipbrd

Ist setenv.inf nicht vorhanden, wird „PATH=;x:;.“ (x=Boot-Laufwerk) erzeugt. Setenv.prg sollte als letztes Programm im AUTO-Ordner stehen, folgende Programme werden natürlich nicht mehr ausgeführt. Setenv.inf muß im Root-Directory des Bootlaufwerks stehen. Einige TOS-Versionen (nicht 1.4) überschreiben das sechste Zeichen des Environments mit ';'. Im Zweifelsfall sollte PATH deshalb in der ersten Zeile stehen und als sechstes Zeichen ';' enthalten. Zu beachten ist außerdem, daß einige Festplattentreiber auf ähnliche Weise Environment-Strings setzen. Hier können Konflikte auftreten.

Es sei betont, daß wir das Environment für GEM gesetzt haben. Wegen des Vererbungsprinzips kann dies nach Start des GEM nicht mehr verändert werden, wohl aber für folgende Programme. Übrigens wird unser GEM-Environment auch an Accessories vererbt.

Die Environment-Variablen, die wir GEM verpaßt haben, können wir mit der Funktion shel_envrn abfragen. Da die Funktion oft falsch dokumentiert ist, hier die Deklaration in C: int shel_envrn(char **sh_epvalue, char *sh_eparm). In sh_eparm übergibt man den Variablennamen, sh_epvalue enthält nach dem Aufruf einen Zeiger auf den Inhalt der Variablen bzw. NULL, falls die Variable nicht existiert. Hierzu das Demo-Programm path.prg, das PATH abfragt.

Nachzuladende Programme kann man in den Verzeichnissen der GEM-Environment-Variablen PATH suchen. Dazu bietet das AES die Funktion shel_find, mit der auch das Desktop zu startende Programme sucht. Die Deklaration in C ist: int shel_find(char *sh_pbuff). In sh_pbuff übergibt man den Namen des gesuchten Programms. Shel_find sucht dann im aktuellen Verzeichnis und in allen Verzeichnissen von PATH. Shel_find liefert 1, falls das Programm gefunden wurde, sonst 0. Sh Jpbuff bleibt unverändert im zweiten Fall, ansonsten steht hier der komplette Zugriffspfad. Enthält PATH als sechstes Zeichen (s.o.), so wird auch das Wurzelverzeichnis des aktuellen Laufwerks durchsucht. Daß eine zugehörige Resource-Datei evtl, im gleichen Verzeichnis steht, stört nicht, denn shel_find wird auch von rsrc_load benutzt, um die Resource-Datei zu finden. Zu dieser Funktion das Programm sh_find.prg, das eine Datei namens „find_me.prg“ sucht und den Zugriffspfad ausgibt. Eine solche Datei (Inhalt spielt keine Rolle) kann nun irgendwo auf der Platte versteckt werden; falls das Directory in PATH enthalten ist, wird sie auch gefunden.

Ich hoffe, mit diesem Beitrag die Benutzung der Environment-Strings auf dem ST etwas populärer gemacht zu haben.

Literatur:

[1] Atari ST Profibuch, Jankowski, Reschke, Rabich, Sybex 1988


*** rom.lst             ***
*** TOS 1.4  'Power Up' ***

GEMDOS      equ 1
PEXEC       equ 75

_bootdev    equ     $446
_cmdload    equ     $482
_sysbase    equ     $4f2
exec_os     equ     $4fe

* Grundinitialisierung ist erledigt 
fc046e      tst.w   _cmdload
fc0474      beq     $fc0494             ; 0 -> AES (ROM) starten

fc0476      bsr     $fc0bfa             ; \auto\*.prg ausführen
fc047a      move.l  #$fc0000,_sysbase   ; Anfang OS
fc0484      pea     $fc052b(pc)         ; envptr = ""
fc0488      pea     $fc052b (pc)        ; cmdline = ""
fc048c      pea     $fc0518 (pc)        ; prgfile = "COMMAND.PRG"
fc0490      clr.w   -(sp)               ; mode
fc0492      bra     $fc04fc             ; Pexec (0,prgfile,cmdline, envptr)

fc0494      bsr     $fc0bfa             ; \auto\*.prg ausführen
fc0498      move.l  #$fc0000,_sysbase   ; anfang os 
fc04a2      lea     $fc050c(pc),a0      ; AES environment
fc04a6      move.l  #$840,a1
fc04ac      cmpi.b  #'#',(a0)           ; nach $840 kopieren
fc04b0      bne     $fc04b4             ; # = Platzhalter
fc04b2      move.l  a1,a2               ; für Boot-Laufwerk
fc04b4      move.b  (a0)+,(a1)+
fc04b6      bpl     $fc04ac
fc04b8      move.b  _bootdev,d0         ; bug, sollte move.w sein!
fc04be      add.b   #'A',d0             ; Boot-Laufwerk bei #
fc04c2      move.b  d0,(a2)             ; eintragen
fc04c4      pea     $840                ; envptr
fc04ca      pea     $fc052b             ; cmdline = ""
fc04d0      pea     $fc052b(pc)         ; prgfile = ""
fc04d4      move.w  #5,-(sp)            ; basepage erzeugen
fc04d8      move.w  #PEX£C,-(sp)        ; mit
fc04dc      trap    #GEMDOS             ; Pexec (5,prgfile,cmdline,envptr) 
fc04de      adda.w  #14,sp              ; bug, sollte 16 sein!
fc04e2      move.l  d0,a0               ; in p_tbase
fc04e4      move.l  exec_os,8(a0)       ; Anfangsadresse AES eintragen
fc04ec      pea     $840                ; envptr
fc04f2      move.l  a0,-(sp)            ; basepage
fc04f4      pea     $fc052b(pc)         ; prgfile = ""
fc04f8      move.w  #4,-(sp)            ; AES starten mit

fc04fc      move.w  #PEXEC,-(sp)        ; Pexec (4,prgfile,basepage,envptr)
fc0500      trap    #GEMDOS
fc0502      adda.w  #14,sp              ; bug, sollte 16 sein!
fc0506      jmp     $fc0030             ; Neustart OS

fc050c 50 41 54 48 3d 00 23 3a 5c 00 00 ff 43 4f 4d 4d
                                     'PATH=.#:\...COMM
fc051c 41 4e 44 2e 50 52 47 00 47 45 4d 2e 50 52 47 00
                                      'AND.PRG.GEM.PRG.
fc052c 00 00 80 01 70 03 61 00 00 f4 20 79 00 00 04 7a
                                      '...p.a..t y...z

/*==============================================*
 *                                              *
 * setenv.c                                     *
 *                                              *
 * startet AES im AUTO-Ordner                   *
 * und setzt Environment-Variablen              *
 *                                              *
 * sollte letztes Programm im AUTO-Ordner sein  *
 *                                              *
 * Linken mit Option -s=512 (512 byte Stack reichen) *
 *                                              *
 * 20.01.90 Jan Bolt (c) MAXON Computer 1991    *
 *                                              *
 * TURBO C                                      *
 *==============================================*/

#include <stdio.h>
#include <tos.h>

#define ENV_LEN 256

#define _bootdev (int *)0x446 
#define _cmdload (int *)0x482 
#define _sysbase (void **)0x4f2 
#define exec_os  (void **)0x4fe

#define ROM_START (void *)0xfc0000

char *envstr(void)      /* environment strings generieren */
{
    char c;
    int fd, i = 0;

    static char env[ENV_LEN+1] = "PATB=;#:;.\0”;

    if ((fd = Fopen("setenv.inf",0)) < 0) 
        env[6] = 'a' + *_bootdev; 
    else 
    {
        while (Fread(fd, 1, &c) == 1 && i < (ENV_LEN-2))
        {
            switch (c)
            {
                case '\r' ; break; 
                case ’\n' : env[i++] = '\0'; break; 
                default   : env[i++] = c;
            }
        }
        env(i++] = '\0'; 
        env[i] = '\0';
        Fclose(fd);
    }
    return env;
}

void do_main (void)
{
    BASPAG *basepage;
    char *envp;     /* Zeiger auf environment */

    *_sysbase = ROM_START; /* Beginn OS setzen */

    if (*_cmdload)  /* command prg starten */
    {
        Pexec(0, "command.prg", (COMMAND *)"", NULL);
    }
    else            /* AES starten */
    {
        envp = envstr(); /* environment holen */ 
        basepage = (BASPAG *)Pexec(5, NULL, NULL, envp);
        basepage->p_tbase = *exec_os;
        Pexec(4, NULL, (void *)basepage, envp);
    }
}

/*====== Hauptprogramm ======*/

int main()
{
    Supexec (do_main) ; /* do_main im Supervisor Modus ausführen */

    return 0;
}

/*==============================================*
 *                                              *
 * path.c                                       *
 *                                              *
 * Anzeigen der AES Environment Variablen PATH  *
 *                                              *
 * 31.12.89 Jan Bolt    Version 210990          *
 *                                              *
 * Turbo C    (c) MAXON Computer 1991           *
 *==============================================*/

#include <stdio.h>
#include <aes.h>

void alert(char *str)
{
    char tmp[128];

    sprintf (tmp, "[0][%s ][ OK ]", str); 
    form_alert(1, tmp);
}

/*====== Hauptprogramm ======*/

int main()
{
    char *path;

    if (appl_init() < 0) 
        return 1;

    shel_envrn(&path, "PATH="); 
    if (path != NULL) 
        alert(path);

    return (appl_exit() == 0);
}

/*==============================================*
 *                                              *
 * sh_find.c                                    *
 *                                              *
 * Demo shel_find                               *
 *                                              *
 * 21.01.90 Jain Bolt   Version 210990          *
 *                                              *
 * Turbo C  (c) MAXON Computer 1991             *
 *==============================================*/

#include <stdio.h>
#include <aes.h>

void alert(char *str, int k)
{
    char tmp[128];

    sprintf(tmp, "[0][%s |%d J[ OK ]", str, k); 
    form_alert(1, tmp );
}

/*====== Hauptprogramm ======*/

int main()
{
    int s;
    static char path[PATH_MAX] = "find_me.prg";

    if (appl_init() < 0) 
        return 1;

    s = shel_find(path); 
    alert(path, s);

    return (appl_exit() = 0);
}

Jan Bolt
Aus: ST-Computer 09 / 1991, Seite 137

Links

Copyright-Bestimmungen: siehe Über diese Seite