14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * David Korn <dgk@research.att.com> * 184887Schin * * 194887Schin ***********************************************************************/ 204887Schin #pragma prototyped 214887Schin 224887Schin #include <ast.h> 234887Schin #include <cdt.h> 244887Schin 254887Schin #define env_change() (++ast.env_serial) 264887Schin 274887Schin typedef struct _venv_ Evar_t; 284887Schin struct _venv_ 294887Schin { 304887Schin union 314887Schin { 324887Schin Evar_t *next; 334887Schin char *ptr; 344887Schin } un; 354887Schin Dtlink_t link; 364887Schin int index; 374887Schin }; 384887Schin 394887Schin typedef struct _env_ 404887Schin { 414887Schin Dt_t *dt; 424887Schin Evar_t *freelist; 434887Schin char **env; 444887Schin int count; 454887Schin int extra; 464887Schin int max; 474887Schin int flags; 484887Schin } Env_t; 494887Schin 504887Schin #define _BLD_env 1 514887Schin #include <env.h> 524887Schin 534887Schin #define ENV_VALID 2 /* set if env is valid */ 544887Schin #define ENV_PMALLOC 1 /* set if Evar_t->un.ptr *s malloced */ 554887Schin #define ENV_VMALLOC 2 /* set of Evar_t was malloced */ 564887Schin #define ENV_BITS 3 574887Schin 584887Schin /* 594887Schin * Compares the name portion of name=... only. 604887Schin */ 614887Schin static int compare(Dt_t *dt, Void_t* key1, Void_t* key2, Dtdisc_t* disc) 624887Schin { 634887Schin register int c,d; 644887Schin const unsigned char *s1=(unsigned const char*)key1; 654887Schin const unsigned char *s2=(unsigned const char*)key2; 664887Schin while((c= *s1++) && c!='=' && c==*s2) 674887Schin s2++; 684887Schin if(c=='=') 694887Schin c = 0; 704887Schin if((d=*s2)=='=') 714887Schin d = 0; 724887Schin return(c-d); 734887Schin } 744887Schin 754887Schin static Dtdisc_t env_disc = 764887Schin { 774887Schin 0, -1, 784887Schin sizeof(char*), 794887Schin 0, 804887Schin 0, 814887Schin compare 824887Schin }; 834887Schin 844887Schin /* 854887Schin * return a pointer to the environment in sorted order 864887Schin * NULL is returned if there if there is nospace 874887Schin */ 884887Schin char **env_get(Env_t* ep) 894887Schin { 904887Schin register Evar_t *vp; 914887Schin register int n=ep->extra; 924887Schin if(ep->flags&ENV_VALID) 934887Schin return(ep->env+n); 944887Schin if(ep->count > ep->max) 954887Schin { 964887Schin if(ep->flags&ENV_MALLOCED) 974887Schin free((void*)ep->env); 984887Schin if(!(ep->env = (char**)malloc(sizeof(char*)*(ep->count+1)))) 994887Schin return(0); 1004887Schin ep->flags |= ENV_MALLOCED; 1014887Schin ep->max = ep->count; 1024887Schin } 1034887Schin for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=(Evar_t*)dtnext(ep->dt,vp)) 1044887Schin { 1054887Schin vp->index = (n<<ENV_BITS) | (vp->index&((1<<ENV_BITS)-1)); 1064887Schin ep->env[n++] = vp->un.ptr; 1074887Schin } 1084887Schin ep->env[n] = 0; 1094887Schin ep->flags |= ENV_VALID; 1104887Schin environ = ep->env+ep->extra; 1114887Schin return(ep->env+ep->extra); 1124887Schin } 1134887Schin 1144887Schin /* 1154887Schin * add name=value pair given by <str> to <ep> 1164887Schin * if malloced is set, the variable will be freed when reassigned 1174887Schin * The environment list may become invalidated 1184887Schin * Returns 1 for success, 0 for failure 1194887Schin */ 1204887Schin int env_add(Env_t *ep, const char *str, int flags) 1214887Schin { 1224887Schin Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str); 1234887Schin if(vp && strcmp(str,vp->un.ptr)==0) 1244887Schin return(1); 1254887Schin if(flags&ENV_STRDUP) 1264887Schin str = strdup(str); 1274887Schin if(vp) 1284887Schin { 1294887Schin if(vp->index&ENV_PMALLOC) 1304887Schin free((void*)vp->un.ptr); 1314887Schin vp->un.ptr = (char*)str; 1324887Schin if(ep->env && (ep->flags&ENV_VALID)) 1334887Schin ep->env[vp->index>>ENV_BITS] = vp->un.ptr; 1344887Schin } 1354887Schin else 1364887Schin { 1374887Schin ep->flags &= ~ENV_VALID; 1384887Schin if(vp = ep->freelist) 1394887Schin ep->freelist = vp->un.next; 1404887Schin else if(vp = newof((Evar_t*)0,Evar_t,2,0)) 1414887Schin { 1424887Schin vp->index = ENV_VMALLOC; 1434887Schin ep->freelist = (vp+1); 1444887Schin ep->freelist->un.next = 0; 1454887Schin } 1464887Schin else 1474887Schin return(0); 1484887Schin vp->un.ptr = (void*)str; 1494887Schin if(!(vp=dtinsert(ep->dt,vp))) 1504887Schin return(0); 1514887Schin ep->count++; 1524887Schin } 1534887Schin if(flags) 1544887Schin vp->index |= ENV_PMALLOC; 1554887Schin else 1564887Schin vp->index &= ~ENV_PMALLOC; 1574887Schin env_change(); 1584887Schin return(1); 1594887Schin } 1604887Schin 1614887Schin /* 1624887Schin * delete name from <ep> 1634887Schin * The environment list may become invalidated 1644887Schin * Returns 1 for success, 0 for if name is not present 1654887Schin */ 1664887Schin int env_delete(Env_t *ep, const char *str) 1674887Schin { 1684887Schin Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str); 1694887Schin if(!vp) 1704887Schin return(0); 1714887Schin ep->flags &= ~ENV_VALID; 1724887Schin if(vp->index&ENV_PMALLOC) 1734887Schin free((void*)vp->un.ptr); 1744887Schin dtdelete(ep->dt,vp); 1754887Schin vp->un.next = ep->freelist; 1764887Schin ep->freelist = vp; 1774887Schin env_change(); 1784887Schin return(1); 1794887Schin } 1804887Schin 1814887Schin /* 1824887Schin * open up a structure to support environment variables 1834887Schin * initialize with environment give by <envp> 1844887Schin * If <extra> > 0, <extra> slots will be left at beginning of 1854887Schin * environment list when env_get() is involed. 1864887Schin * If <extra>==ENV_USABLE, then the original environ can be 1874887Schin * used and returned. Otherwise, a new one will be returned 1884887Schin */ 1894887Schin Env_t *env_open(char **envp, int extra) 1904887Schin { 1914887Schin char **env; 1924887Schin Env_t *ep; 1934887Schin Evar_t *vp; 1944887Schin int n=2; 1954887Schin if(!(ep = newof((Env_t*)0,Env_t,1,0))) 1964887Schin return(0); 1974887Schin if(!(ep->dt = dtopen(&env_disc,Dtoset))) 1984887Schin return(0); 1994887Schin if(env=envp) 2004887Schin { 2014887Schin while(*env++); 2024887Schin n = (env+2)-envp; 2034887Schin } 2044887Schin if(extra==ENV_STABLE) 2054887Schin { 2064887Schin ep->env = envp; 2074887Schin ep->max = n-1; 2084887Schin } 2094887Schin else 2104887Schin ep->count = ep->extra = extra; 2114887Schin ep->freelist = vp = newof((Evar_t*)0,Evar_t,n,0); 2124887Schin vp->index = ENV_VMALLOC; 2134887Schin while(--n>0) 2144887Schin { 2154887Schin vp->un.next = (vp+1); 2164887Schin vp++; 2174887Schin } 2184887Schin vp->un.next = 0; 2194887Schin if(env) 2204887Schin { 2214887Schin for(env=envp; *env; env++) 2224887Schin env_add(ep,*env,0); 2234887Schin } 2244887Schin return(ep); 2254887Schin } 2264887Schin 2274887Schin /* 2284887Schin * close <ep> and free up all space used by it 2294887Schin */ 2304887Schin void env_close(Env_t *ep) 2314887Schin { 2324887Schin Evar_t *vp, *vpnext,*top; 2334887Schin if(ep->env && (ep->flags&ENV_MALLOCED)) 2344887Schin free((void*)ep->env); 2354887Schin for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=vpnext) 2364887Schin { 2374887Schin vpnext = (Evar_t*)dtnext(ep->dt,vp); 2384887Schin env_delete(ep,vp->un.ptr); 2394887Schin } 2404887Schin for(top=0,vp = ep->freelist; vp; vp = vpnext) 2414887Schin { 2424887Schin vpnext = vp->un.next; 2434887Schin if(vp->index&ENV_VMALLOC) 2444887Schin { 2454887Schin vp->un.next = top; 2464887Schin top = vp; 2474887Schin } 2484887Schin } 2494887Schin for(vp=top; vp; vp = vpnext) 2504887Schin { 2514887Schin vpnext = vp->un.next; 2524887Schin free((void*)vp); 2534887Schin } 2544887Schin dtclose(ep->dt); 2554887Schin } 256