|
Packit Service |
a8c26c |
/***********************************************************************
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* This software is part of the ast package *
|
|
Packit Service |
a8c26c |
* Copyright (c) 1982-2011 AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* and is licensed under the *
|
|
Packit Service |
a8c26c |
* Eclipse Public License, Version 1.0 *
|
|
Packit Service |
a8c26c |
* by AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* A copy of the License is available at *
|
|
Packit Service |
a8c26c |
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
Packit Service |
a8c26c |
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Information and Software Systems Research *
|
|
Packit Service |
a8c26c |
* AT&T Research *
|
|
Packit Service |
a8c26c |
* Florham Park NJ *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* David Korn <dgk@research.att.com> *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
***********************************************************************/
|
|
Packit Service |
a8c26c |
#pragma prototyped
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include <ast.h>
|
|
Packit Service |
a8c26c |
#include <cdt.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#define env_change() (++ast.env_serial)
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
typedef struct _venv_ Evar_t;
|
|
Packit Service |
a8c26c |
struct _venv_
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
union
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
Evar_t *next;
|
|
Packit Service |
a8c26c |
char *ptr;
|
|
Packit Service |
a8c26c |
} un;
|
|
Packit Service |
a8c26c |
Dtlink_t link;
|
|
Packit Service |
a8c26c |
int index;
|
|
Packit Service |
a8c26c |
};
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
typedef struct _env_
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
Dt_t *dt;
|
|
Packit Service |
a8c26c |
Evar_t *freelist;
|
|
Packit Service |
a8c26c |
char **env;
|
|
Packit Service |
a8c26c |
int count;
|
|
Packit Service |
a8c26c |
int extra;
|
|
Packit Service |
a8c26c |
int max;
|
|
Packit Service |
a8c26c |
int flags;
|
|
Packit Service |
a8c26c |
} Env_t;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#define _BLD_env 1
|
|
Packit Service |
a8c26c |
#include <env.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#define ENV_VALID 2 /* set if env is valid */
|
|
Packit Service |
a8c26c |
#define ENV_PMALLOC 1 /* set if Evar_t->un.ptr *s malloced */
|
|
Packit Service |
a8c26c |
#define ENV_VMALLOC 2 /* set of Evar_t was malloced */
|
|
Packit Service |
a8c26c |
#define ENV_BITS 3
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* Compares the name portion of name=... only.
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
static int compare(Dt_t *dt, Void_t* key1, Void_t* key2, Dtdisc_t* disc)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
register int c,d;
|
|
Packit Service |
a8c26c |
const unsigned char *s1=(unsigned const char*)key1;
|
|
Packit Service |
a8c26c |
const unsigned char *s2=(unsigned const char*)key2;
|
|
Packit Service |
a8c26c |
while((c= *s1++) && c!='=' && c==*s2)
|
|
Packit Service |
a8c26c |
s2++;
|
|
Packit Service |
a8c26c |
if(c=='=')
|
|
Packit Service |
a8c26c |
c = 0;
|
|
Packit Service |
a8c26c |
if((d=*s2)=='=')
|
|
Packit Service |
a8c26c |
d = 0;
|
|
Packit Service |
a8c26c |
return(c-d);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static Dtdisc_t env_disc =
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
0, -1,
|
|
Packit Service |
a8c26c |
sizeof(char*),
|
|
Packit Service |
a8c26c |
0,
|
|
Packit Service |
a8c26c |
0,
|
|
Packit Service |
a8c26c |
compare
|
|
Packit Service |
a8c26c |
};
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* return a pointer to the environment in sorted order
|
|
Packit Service |
a8c26c |
* NULL is returned if there if there is nospace
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
char **env_get(Env_t* ep)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
register Evar_t *vp;
|
|
Packit Service |
a8c26c |
register int n=ep->extra;
|
|
Packit Service |
a8c26c |
if(ep->flags&ENV_VALID)
|
|
Packit Service |
a8c26c |
return(ep->env+n);
|
|
Packit Service |
a8c26c |
if(ep->count > ep->max)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if(ep->flags&ENV_MALLOCED)
|
|
Packit Service |
a8c26c |
free((void*)ep->env);
|
|
Packit Service |
a8c26c |
if(!(ep->env = (char**)malloc(sizeof(char*)*(ep->count+1))))
|
|
Packit Service |
a8c26c |
return(0);
|
|
Packit Service |
a8c26c |
ep->flags |= ENV_MALLOCED;
|
|
Packit Service |
a8c26c |
ep->max = ep->count;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=(Evar_t*)dtnext(ep->dt,vp))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
vp->index = (n<<ENV_BITS) | (vp->index&((1<
|
|
Packit Service |
a8c26c |
ep->env[n++] = vp->un.ptr;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
ep->env[n] = 0;
|
|
Packit Service |
a8c26c |
ep->flags |= ENV_VALID;
|
|
Packit Service |
a8c26c |
environ = ep->env+ep->extra;
|
|
Packit Service |
a8c26c |
return(ep->env+ep->extra);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* add name=value pair given by <str> to <ep>
|
|
Packit Service |
a8c26c |
* if malloced is set, the variable will be freed when reassigned
|
|
Packit Service |
a8c26c |
* The environment list may become invalidated
|
|
Packit Service |
a8c26c |
* Returns 1 for success, 0 for failure
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
int env_add(Env_t *ep, const char *str, int flags)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str);
|
|
Packit Service |
a8c26c |
if(vp && strcmp(str,vp->un.ptr)==0)
|
|
Packit Service |
a8c26c |
return(1);
|
|
Packit Service |
a8c26c |
if(flags&ENV_STRDUP)
|
|
Packit Service |
a8c26c |
str = strdup(str);
|
|
Packit Service |
a8c26c |
if(vp)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if(vp->index&ENV_PMALLOC)
|
|
Packit Service |
a8c26c |
free((void*)vp->un.ptr);
|
|
Packit Service |
a8c26c |
vp->un.ptr = (char*)str;
|
|
Packit Service |
a8c26c |
if(ep->env && (ep->flags&ENV_VALID))
|
|
Packit Service |
a8c26c |
ep->env[vp->index>>ENV_BITS] = vp->un.ptr;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
ep->flags &= ~ENV_VALID;
|
|
Packit Service |
a8c26c |
if(vp = ep->freelist)
|
|
Packit Service |
a8c26c |
ep->freelist = vp->un.next;
|
|
Packit Service |
a8c26c |
else if(vp = newof((Evar_t*)0,Evar_t,2,0))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
vp->index = ENV_VMALLOC;
|
|
Packit Service |
a8c26c |
ep->freelist = (vp+1);
|
|
Packit Service |
a8c26c |
ep->freelist->un.next = 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
return(0);
|
|
Packit Service |
a8c26c |
vp->un.ptr = (void*)str;
|
|
Packit Service |
a8c26c |
if(!(vp=dtinsert(ep->dt,vp)))
|
|
Packit Service |
a8c26c |
return(0);
|
|
Packit Service |
a8c26c |
ep->count++;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if(flags)
|
|
Packit Service |
a8c26c |
vp->index |= ENV_PMALLOC;
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
vp->index &= ~ENV_PMALLOC;
|
|
Packit Service |
a8c26c |
env_change();
|
|
Packit Service |
a8c26c |
return(1);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* delete name from <ep>
|
|
Packit Service |
a8c26c |
* The environment list may become invalidated
|
|
Packit Service |
a8c26c |
* Returns 1 for success, 0 for if name is not present
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
int env_delete(Env_t *ep, const char *str)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
Evar_t *vp = (Evar_t*)dtmatch(ep->dt,(void*)str);
|
|
Packit Service |
a8c26c |
if(!vp)
|
|
Packit Service |
a8c26c |
return(0);
|
|
Packit Service |
a8c26c |
ep->flags &= ~ENV_VALID;
|
|
Packit Service |
a8c26c |
if(vp->index&ENV_PMALLOC)
|
|
Packit Service |
a8c26c |
free((void*)vp->un.ptr);
|
|
Packit Service |
a8c26c |
dtdelete(ep->dt,vp);
|
|
Packit Service |
a8c26c |
vp->un.next = ep->freelist;
|
|
Packit Service |
a8c26c |
ep->freelist = vp;
|
|
Packit Service |
a8c26c |
env_change();
|
|
Packit Service |
a8c26c |
return(1);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* open up a structure to support environment variables
|
|
Packit Service |
a8c26c |
* initialize with environment give by <envp>
|
|
Packit Service |
a8c26c |
* If <extra> > 0, <extra> slots will be left at beginning of
|
|
Packit Service |
a8c26c |
* environment list when env_get() is involed.
|
|
Packit Service |
a8c26c |
* If <extra>==ENV_USABLE, then the original environ can be
|
|
Packit Service |
a8c26c |
* used and returned. Otherwise, a new one will be returned
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
Env_t *env_open(char **envp, int extra)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
char **env;
|
|
Packit Service |
a8c26c |
Env_t *ep;
|
|
Packit Service |
a8c26c |
Evar_t *vp;
|
|
Packit Service |
a8c26c |
int n=2;
|
|
Packit Service |
a8c26c |
if(!(ep = newof((Env_t*)0,Env_t,1,0)))
|
|
Packit Service |
a8c26c |
return(0);
|
|
Packit Service |
a8c26c |
if(!(ep->dt = dtopen(&env_disc,Dtoset)))
|
|
Packit Service |
a8c26c |
return(0);
|
|
Packit Service |
a8c26c |
if(env=envp)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
while(*env++);
|
|
Packit Service |
a8c26c |
n = (env+2)-envp;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if(extra==ENV_STABLE)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
ep->env = envp;
|
|
Packit Service |
a8c26c |
ep->max = n-1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
ep->count = ep->extra = extra;
|
|
Packit Service |
a8c26c |
ep->freelist = vp = newof((Evar_t*)0,Evar_t,n,0);
|
|
Packit Service |
a8c26c |
vp->index = ENV_VMALLOC;
|
|
Packit Service |
a8c26c |
while(--n>0)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
vp->un.next = (vp+1);
|
|
Packit Service |
a8c26c |
vp++;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
vp->un.next = 0;
|
|
Packit Service |
a8c26c |
if(env)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
for(env=envp; *env; env++)
|
|
Packit Service |
a8c26c |
env_add(ep,*env,0);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
return(ep);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* close <ep> and free up all space used by it
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
void env_close(Env_t *ep)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
Evar_t *vp, *vpnext,*top;
|
|
Packit Service |
a8c26c |
if(ep->env && (ep->flags&ENV_MALLOCED))
|
|
Packit Service |
a8c26c |
free((void*)ep->env);
|
|
Packit Service |
a8c26c |
for(vp=(Evar_t*)dtfirst(ep->dt);vp; vp=vpnext)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
vpnext = (Evar_t*)dtnext(ep->dt,vp);
|
|
Packit Service |
a8c26c |
env_delete(ep,vp->un.ptr);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
for(top=0,vp = ep->freelist; vp; vp = vpnext)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
vpnext = vp->un.next;
|
|
Packit Service |
a8c26c |
if(vp->index&ENV_VMALLOC)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
vp->un.next = top;
|
|
Packit Service |
a8c26c |
top = vp;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
for(vp=top; vp; vp = vpnext)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
vpnext = vp->un.next;
|
|
Packit Service |
a8c26c |
free((void*)vp);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
dtclose(ep->dt);
|
|
Packit Service |
a8c26c |
}
|