#include #include "dat.h" #include "fns.h" const char **environ = nil; static const char **envpbufend = nil; static char *envsbuf = nil; static char *envsbufend = nil; static char *envsbuffree = nil; extern int radix; enum VarType { VNUM, VSTR }; typedef struct VarTab VarTab; struct VarTab { const char *name; union { struct { int (*get)(void); void (*set)(int); } num; struct { const char* (*get)(void); void (*set)(const char *); } str; }; enum VarType type; VarTab *next; }; static VarTab *vartab = nil; static const char* _getenv(const char *name) { int n = strlen(name); const char **ep = environ; while(*ep && (strncmp(*ep, name, n) != 0 || (*ep)[n] != '=')) ep++; if(!*ep) return nil; return *ep+n+1; } const char* getenv(const char *name) { VarTab *v = vartab; while(v) { if(strcmp(v->name, name) == 0) { static char numbuf[20]; switch(v->type) { case VNUM: sprint(numbuf, (strcmp(name, "r") == 0 || radix == 10) ? "%d" : (radix == 16) ? "%ux" : (radix == 8) ? "%o" : "0x%ux", v->num.get()); return numbuf; case VSTR: return v->str.get(); } } v = v->next; } return _getenv(name); } static int _putenv(const char *name, const char *val) { int n = strlen(name); const char **ep = environ; char *sp = envsbuf; if(!*ep) envsbuffree = sp; while(sp < envsbuffree) { char *np = sp + strlen(sp) + 1; if(strncmp(sp, name, n) == 0 && sp[n] == '=') { memmove(sp, np, envsbuffree - np); envsbuffree -= (np - sp); } else { *ep++ = sp; sp = np; } } if(ep+1 >= envpbufend || sp+n+1+strlen(val)+1 > envsbufend) { *ep = nil; return -1; } *ep++ = sp; envsbuffree = sp + sprint(sp, "%s=%s", name, val) + 1; *ep = nil; return 0; } int putenv(const char *name, const char *val) { VarTab *v = vartab; while(v) { if(strcmp(v->name, name) == 0) { switch(v->type) { case VNUM: v->num.set(strtoul(val, 0, (strcmp(name, "r") == 0) ? 0 : radix)); return 0; case VSTR: v->str.set(val); return 0; } } v = v->next; } return _putenv(name, val); } int nbindenv(const char *name, int (*get)(void), void (*set)(int)) { VarTab *v = malloc(sizeof(VarTab)); v->name = name; v->num.get = get; v->num.set = set; v->type = VNUM; v->next = vartab; vartab = v; return 0; } int sbindenv(const char *name, const char* (*get)(void), void (*set)(const char*)) { VarTab *v = malloc(sizeof(VarTab)); v->name = name; v->str.get = get; v->str.set = set; v->type = VSTR; v->next = vartab; vartab = v; return 0; } int envinit(const char **pbuf, int pbufsize, char *sbuf, int sbufsize); int envinit(const char **pbuf, int pbufsize, char *sbuf, int sbufsize) { environ = pbuf; envsbuf = sbuf; *environ = nil; envpbufend = pbuf+pbufsize/sizeof(*pbuf); envsbufend = sbuf+sbufsize/sizeof(*sbuf); return 0; } void printenv(void) { const char **ep = environ; VarTab *v = vartab; while(v) { print("*%s=%s\n", v->name, getenv(v->name)); v = v->next; } while(*ep) print("%s\n", *ep++); }