/* * Written by Tomas Rokicki. * * This routine replaces Manx's SET command. It should have exactly * equivalent functionality. Do not use the Manx SET command with it, * though; my library structure has an extra field which Manx ignores. * Thus, if the Manx set command modifies a library created by my set * command, or vice versa, a system crash could result. * * Another caveat: the Manx getenv() routine does not do a Forbid() * Permit() around it's library examining code, so it could * conceivably return bad data if someone's executing a set while it * is called. You might want to rewrite getenv(); it's simple enough. * * The following code could easily be hacked to provide setenv() and * getenv() library routines; I leave that as an exersize for the reader. */ #include "stdio.h" #include "exec/memory.h" /* * The increment size for the string space. */ #define ENVINC (128) /* * The pointer to the environment data. */ char **envloc = NULL ; long *envsize ; char *envname = "environment" ; /* * A library structure declaration, pieced together from various * include files and extended a bit. */ struct lib { struct lib *next, *prev ; char type, priority ; char *name ; short flags ; short negsize ; short possize ; short version ; short revision ; char *ID ; long checksum ; short opencount ; char *env ; long size ; } ; /* * The actual library structure. Note I have relative branches in the * vectors field, and actual assembled code in the code field. Be * careful if you change any of this! */ struct envlib { short vectors[12] ; struct lib lp ; short code[4] ; char name[12] ; } envinit = { { 0x6044, 0x0000, 0x0000, 0x603e, 0x0000, 0x0000, 0x6038, 0x0000, 0x0000, 0x602e, 0x0000, 0x0000 }, { NULL, NULL, 0, 0, NULL, 0, 24, 42 + 8 + 12 + 2, 1, 1, NULL, 0, 1, NULL, ENVINC }, { 0x200e, 0x4e75, 0x7000, 0x4e75 }, { 'e', 'n', 'v', 'i', 'r', 'o', 'n', 'm', 'e', 'n', 't', 0} } ; /* * The main routine is straightforward. If no arguments are given, we * print out the contents of the environment. If one ? is given as an * argument, we print out a blurb. Otherwise, we scan through the * argument list, adding new definitions. */ char *index() ; main(argc, argv) int argc ; char *argv[] ; { register char *p, *q ; argc-- ; argv++ ; openenv() ; if (argc <= 0) { if (envloc != NULL) for (q=*envloc; *q!=0; ) { puts(q) ; while (*q++) ; } } else if (argc==1 && argv[0][0]=='?' && argv[0][1]==0) { puts("Environment variable utility---Radical Eye Software") ; } else while (argc > 0) { if ((p = index(*argv, '=')) && p[1] != 0) { deleteenv(*argv) ; if (envloc==NULL) makeenv() ; for (;;) { q = *envloc ; while (*q!=0) while (*q++) ; if (q+strlen(*argv)+1 > *envloc + *envsize) biggerenv() ; else break ; } Forbid() ; strcpy(q, *argv) ; q[strlen(*argv)+1] = 0 ; Permit() ; } else { deleteenv(*argv) ; } argv++ ; argc-- ; } } /* * This routines opens the environment library if it exists and sets * the global pointer to the correct location. */ openenv() { register struct lib *lp, *_OpenLibrary() ; if (lp=_OpenLibrary(envname, 0L)) { _CloseLibrary(lp) ; envloc = &lp->env ; envsize = &lp->size ; } else envloc = NULL ; } /* * We need a simple memcopy routine. Only works for even numbers of bytes. */ memcop(dst, src, bytes) register short *dst, *src ; register long bytes ; { while (bytes > 0) { *dst = *src ; dst++ ; src++ ; bytes -= 2 ; } } /* * This is the tricky routine which adds a library. */ makeenv() { char *AllocMem() ; register struct lib *lp ; register struct envlib *elp ; register char *p ; elp = (struct envlib *)AllocMem((long)sizeof(struct envlib), (long)MEMF_PUBLIC) ; p = AllocMem((long)ENVINC, (long)MEMF_PUBLIC | MEMF_CLEAR) ; if (elp==NULL || p==NULL) { puts("Couldn't make environment library!") ; if (elp!=NULL) FreeMem(elp, (long)sizeof(struct envlib)) ; if (p!=NULL) FreeMem(p, (long)ENVINC) ; exit(1) ; } memcop(elp, &envinit, (long)sizeof(struct envlib)) ; lp = &(elp->lp) ; lp->name = elp->name ; lp->env = p ; AddLibrary(lp) ; envloc = &(lp->env) ; envsize = &(lp->size) ; return ; } /* * This routine makes the environment string space bigger if needed. */ biggerenv() { register char *p ; register long size ; register char *t ; size = *envsize + ENVINC ; p = AllocMem(size, (long)MEMF_PUBLIC | MEMF_CLEAR) ; if (p==NULL) { puts("Couldn't increase environment size.\n") ; exit(1) ; } Forbid() ; t = *envloc ; memcop(p, t, *envsize) ; *envloc = p ; *envsize = size ; Permit() ; size -= ENVINC ; FreeMem(t, size) ; } /* * This routine deletes a symbol definition and moves all other strings * down. We can afford to use a simple algorithm here. */ deleteenv(s) register char *s ; { register char *q ; register int i, j ; if (envloc==NULL) return ; if (q=index(s, '=')) i = q - s ; else i = strlen(s) ; Forbid() ; q = *envloc ; while (*q!=0) if ((j=index(q, '=')-q) && i==j && strncmp(q, s, i)==0) { s = q + strlen(q) + 1 ; while (*s != 0) { *q++ = *s++ ; if (*s == 0) *q++ = *s++ ; } *q++ = 0 ; *q++ = 0 ; Permit() ; return ; } else q += strlen(q) + 1 ; Permit() ; }