/* * Das Environment Programm fr den ATARI ST * * Initialisieren, Ver„ndern und L”schen von Environment Variablen * Es wird die Systemvariable THE_ENV benutzt. * * Das Initialiseren des Environment-Bereichs l„uft leider nicht im * AUTO-Ordner, das sich das Desktop (bzw. das AES) den alten Environment- * Bereich berschreibt, daher erst nach Starten des Desktop's verwenden. * * Es werden 'multiple character constants' verwendet, d.h. 'XBRA' ist als * Integer-Wert zul„ssig, daher bei Lattice mit -cm compilieren. * * (C) 8.1.1989 Ralf Meister * Version mit Zeilen-Verl„ngerung durch ein \ am Ende der Zeile * (C) 1.2.1989 Ralf Meister * Version mit lesbarer XBRA Kennung * (C) 23.9.1989 Ralf Meister */ #include "portab.h" #include "osbind.h" #include "stdio.h" #include "stdlib.h" /* Begrenze die Speicheranforderung des Programms, Lattice spezifisch */ long _MNEED = 0x100; #define THE_ENV 0x4be /* Systemvariable THE_ENV */ #define MAGIC 'RMEN' /* Flag zum Erkennen der richtigen Version */ #define MIN_SIZE 0x100 /* Minimale Gr”že des Environments, hier 1/4k */ #define DEF_SIZE 0x400 /* Default Gr”že hier 1k */ #define MAX_STR 120 /* Maximale L„nge eines Strings */ #define MAX_NAM 32 /* Maximale L„nge eines Namens */ /* Definition der Struktur der Basepage, nur die erforderlichen Eintr„ge */ typedef struct pd PD; struct pd { char res1[36]; /* Bereich, der uns nicht interessiert */ PD *p_parent; /* Zeiger auf Basepage des Vater's */ long res2; char *p_env; /* Zeiger auf Environment Bereich */ char res3[80]; char p_cmdlin[128]; }; /* Struktur vor dem Speicherblock des Environment Bereiches, damit man ber- prfen kann, ob die Environment Variablen von diesem Programm stammen */ typedef struct envblock ENVBLOCK; struct envblock { int size; /* Gr”že des reservierten Speichers */ int xbra; /* die Konstante 'XBRA' */ int magic; /* Kontrollwert */ int old_vec; /* Alte Adresse hier merken */ }; /* Definition von Datenstrukturen zum Speichern der verschiedenen Aufgaben */ typedef enum { NOTHING,PRINT,DELETE,CREATE,KILL,SET,SETFILE } KIND; typedef struct { KIND kind; /* Art der Aufgabe */ char *arg; /* Eventuelle Parameter */ } TASK; #define MAX_TASK 5 /* Maximale Anzahl von Aufgaben */ /* Globale Variablen */ int waitforkey=FALSE; /* Warten auf Tastendruck nach Beenden des Programms */ int help=FALSE; /* Flag fr Hilfe */ int res=FALSE; /* Flag fr resident halten */ int size=DEF_SIZE; /* Default Gr”že des Bereichs, hier 2k */ /* die zu erledigenden Aufgaben */ TASK task_list[MAX_TASK];/* TRUE verschiedene Eintr„ge sollten reichen */ int task_nr=0; /* Ausgeben einer Fehlermeldung auf stderr und ggfs. warten auf Taste */ void error(str) char *str; { fprintf(stderr,"%s\n",str); if(waitforkey) while(!kbhit()); exit(1); } /* Reserviere den Speicher am Ende des verfgbaren Speichers */ char *get_mem(size) int size; { int length; char *ptr,*dummy; if( (length=Malloc(-1)) > size ) if( (dummy=(char *)Malloc(length-size)) > 0) if( (ptr=(char *)Malloc(size)) > 0 ) { Mfree(dummy); return(ptr); }; error("No more memory"); return NULL; } /* Bilde einen Environment Bereich, mit/ohne šberschreiben des alten */ void create(arg,del) char *arg; int del; { int stack; char *old_env; register char *env; register ENVBLOCK *block; register PD *basepage; extern PD *_pbase; /* Die Adresse unserer Basepage */ /* Stelle die Gr”že des zu benutzenden Speichers fest */ if(arg!=NULL && *arg!='\0') /* Wenn kein Parameter, dann default */ { size=atoi(arg); if(sizemagic=MAGIC; /* Setze den Prfwert */ block->size=size; /* Und die Gr”že des Environments */ block->xbra='XBRA'; /* Den Wert fr 'XBRA' setzen */ block->old_vec=(int)old_env;/* und den alten Pointer setzen */ env+=sizeof(ENVBLOCK); /* Zeige auf Datenbereich */ stack=Super(0); /* In den Supervisormodus gehen */ *(char **)THE_ENV=env; /* Den Pointer setzen */ Super(stack); /* wieder in den Usermode gehen */ *env='\0'; /* Nock keine Variablen gespeichert */ res=TRUE; /* Flag fr resident lassen setzen */ /* Den Zeiger in allen vorhergehenden Basepage'en setzen */ basepage=_pbase; while(basepage!=NULL) { basepage->p_env=env; basepage=basepage->p_parent; } printf("Allocate %d Bytes for environment\n",size); } /* Hole die Adresse, auf die THE_ENV zeigt */ char *get_env() { int stack; register char *env; register ENVBLOCK *block; stack=Super(0); /* In den Supervisor-Modus gehen */ env=*(char **)THE_ENV; Super(stack); /* wieder in den User-Mode gehen */ if(env==NULL) error("No valid environment"); block=(ENVBLOCK *)(env-sizeof(ENVBLOCK));/* Den Zeiger auf Block setzen */ if( block->magic != MAGIC ) error("No valid environment"); return(env); } /* Ausgeben der Environment Variablen, auf die THE_ENV zeigt */ void print() { char *env; env=get_env(); puts("List of environment variables:"); while(*env) /* Wenn der erste Buchstabe = 0 ende */ { while(*env) /* sonst solange die Buchstaben != 0 */ putchar(*env++); /* ausgeben */ putchar('\n'); /* Fr jede Variable eine neue Zeile */ env++; /* Hinter das Variablenende lesen */ } putchar('\n'); } /* Hole Namen einer Variablen */ void split(name,str) char *name,*str; { register char *ptr1,*ptr2; ptr1=str; ptr2=name; while(*ptr1 && *ptr1!='=' && ptr2-name= oder sein */ void add(str,env) char *str,*env; { char name[MAX_NAM]; ENVBLOCK *block; register char *ptr; split(name,str); /* Hole dir den Namen */ delete(name,env); /* Die alte Variable l”schen */ block=(ENVBLOCK *)(env-sizeof(ENVBLOCK)); ptr=env; /* Das Ende der Variablen suchen */ while(*ptr) while(*ptr++); /* Jetzt zeigt *ptr auf das abschliežende '\0' */ /* Prfe, ob genug Speicher da ist (+2 fr "\0\0" am Schluž) */ if(ptr-env+strlen(str)+2>block->size) error("Environment space too small"); while((*ptr++=*str++)); *ptr++='\0'; } /* Teste, ob ein Character in einer Liste von Buchstaben vorhanden ist */ int in(ch,str) register char ch,*str; { while(*str) if(ch==*str++) return TRUE; return FALSE; } /* Die Datei einlesen und die standard Variablen aus dem File setzen */ void set_file(fname) char *fname; { FILE *fh; char read_buffer[MAX_STR],buffer[4*MAX_STR]; /* Grožer Puffer */ register char *ptr1,*ptr2; char *env; if( (fh=fopen(fname,"ra"))==NULL) error("Can't open file"); env=get_env(); while(fgets(read_buffer,MAX_STR,fh)!=NULL) { ptr1=read_buffer; /* die Zeiger zum Durchsuchen setzen */ ptr2=buffer; /* Kommentarzeilen berlesen */ if(in(*ptr1,"*#;%+!&$\n")) continue; do *ptr2++=*ptr1++; while(!in(*ptr1," =\n\t") && *ptr1); /* bis Tokenende lesen */ if(*ptr1!='\n' && *ptr1) /* šberlese Blanks und TABS */ while(in(*ptr1," \t")) ptr1++; if(*ptr1=='=') /* Also Form var=value */ { while(*ptr1!='\n' && *ptr1) /* Kopiere den Rest der Zeile */ *ptr2++=*ptr1++; /* Geht die Zeile weiter (erkennt man an '\\\n' ?? */ while(*(ptr1-1)=='\\' && *ptr1=='\n') { /* Lese neue Zeile ein un kopiere weiter */ if(fgets(read_buffer,MAX_STR,fh)==NULL) error("Unexpected end of file"); ptr2--; /* Lasse '\\\n' weg */ ptr1=read_buffer; /* Den ptr1 auf neue Zeile setzen */ while(*ptr1!='\n' && *ptr1) { if(ptr2-buffer>=4*MAX_STR) error("Too long environment variable"); *ptr2++=*ptr1++; } } } /* Das Stringende - Zeichen hinzufgen */ *ptr2++='\0'; add(buffer,env); } } /* Eine kleine Help-Meldung auf dem Bildschirm zeigen */ void usage() { puts("ENVIRON [-w][-h][-p][-f ][-s ][-d ]\ [-c ][-k ] "); puts(" h print this tiny help message"); puts(" w wait for key before terminating"); puts(" p print the environment variables"); puts(" f set variables from "); puts(" s set variable "); puts(" d delete variable "); puts(" c create environment space without overwriting exiting one"); puts(" k kill old environment space and create new"); puts("\n set variable "); puts(" no same as -p"); help=TRUE; } /* Das Hauptprogramm : untersuche Parameterzeile und verteile die Arbeit */ void main(argc,argv) int argc; char *argv[]; { int next; char *odata,option; char *env; int i; puts("ENVIRON environment utility V1.4\n(C) Ralf Meister 1989\n"); for(next=1;(odata=argopt(argc,argv,"sSfFcCkKDD",&next,&option))!=NULL;) { if(task_nr==MAX_TASK) error("Too many different tasks"); switch(option) { case 'h': case 'H': usage(); break; case 'w': case 'W': waitforkey=TRUE; break; case 'd': case 'D': task_list[task_nr].kind=DELETE; task_list[task_nr++].arg=odata; break; case 's': case 'S': task_list[task_nr].kind=SET; task_list[task_nr++].arg=odata; break; case 'f': case 'F': task_list[task_nr].kind=SETFILE; task_list[task_nr++].arg=odata; break; case 'p': case 'P': task_list[task_nr].kind=PRINT; task_list[task_nr++].arg=NULL; break; case 'c': case 'C': task_list[task_nr].kind=CREATE; task_list[task_nr++].arg=odata; break; case 'k': case 'K': task_list[task_nr].kind=KILL; task_list[task_nr++].arg=odata; break; default : fprintf(stderr,"Invalid option %c\n",option); usage(); error(""); } } /* Wenn keine Hilfe notwendig war */ if(!help) { /* Die Aufgaben der Reihe nach ausfhren */ for(i=0;i Ausdrucken */ if(next==argc && task_nr==0) print(); /* Ansonsten die Variablen der Parameterzeile setzen */ if(next