2011-03-30 12:46:40 +00:00
|
|
|
#include "u.h"
|
|
|
|
#include "../port/lib.h"
|
|
|
|
#include "mem.h"
|
|
|
|
#include "dat.h"
|
|
|
|
#include "fns.h"
|
|
|
|
#include "../port/error.h"
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
2022-01-23 21:33:58 +00:00
|
|
|
Maxenvsize = 1*MB,
|
|
|
|
Maxvalsize = Maxenvsize/2,
|
|
|
|
|
2015-08-02 19:39:33 +00:00
|
|
|
DELTAENV = 32,
|
2011-03-30 12:46:40 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static Egrp *envgrp(Chan *c);
|
2022-01-23 21:33:58 +00:00
|
|
|
static int envwritable(Chan *c);
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
static Egrp confegrp; /* global environment group containing the kernel configuration */
|
|
|
|
|
2022-01-23 21:33:58 +00:00
|
|
|
#define PATH(p,i) ((uvlong)(p) << 32 | (i))
|
|
|
|
#define QID(quidpath) ((uint)(quidpath) & 0x7FFFFFFF)
|
|
|
|
|
2011-03-30 12:46:40 +00:00
|
|
|
static Evalue*
|
2022-01-23 21:33:58 +00:00
|
|
|
envindex(Egrp *eg, uvlong qidpath)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2022-01-23 21:33:58 +00:00
|
|
|
Evalue *e;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
i = QID(qidpath);
|
|
|
|
if(i >= eg->nent)
|
|
|
|
return nil;
|
|
|
|
e = eg->ent[i];
|
|
|
|
if(e != nil && e->path != qidpath)
|
|
|
|
return nil;
|
|
|
|
return e;
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2022-01-23 21:33:58 +00:00
|
|
|
static Evalue**
|
|
|
|
envhash(Egrp *eg, char *name)
|
|
|
|
{
|
|
|
|
uint c, h = 0;
|
|
|
|
while(c = *name++)
|
|
|
|
h = h*131 + c;
|
|
|
|
return &eg->hash[h % ENVHASH];
|
|
|
|
}
|
|
|
|
|
|
|
|
static Evalue*
|
|
|
|
lookupname(Evalue *e, char *name)
|
|
|
|
{
|
|
|
|
while(e != nil){
|
|
|
|
if(strcmp(e->name, name) == 0)
|
|
|
|
break;
|
|
|
|
e = e->hash;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
return e;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
envgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
|
|
|
|
{
|
|
|
|
Egrp *eg;
|
|
|
|
Evalue *e;
|
2022-01-23 21:33:58 +00:00
|
|
|
Qid q;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2022-01-23 21:33:58 +00:00
|
|
|
eg = envgrp(c);
|
2011-03-30 12:46:40 +00:00
|
|
|
if(s == DEVDOTDOT){
|
2022-01-23 21:33:58 +00:00
|
|
|
c->qid.vers = eg->vers;
|
2018-06-03 21:30:05 +00:00
|
|
|
devdir(c, c->qid, "#e", 0, eve, 0775, dp);
|
2011-03-30 12:46:40 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
rlock(eg);
|
2022-01-23 21:33:58 +00:00
|
|
|
if((c->qid.type & QTDIR) == 0) {
|
|
|
|
e = envindex(eg, c->qid.path);
|
|
|
|
if(e == nil)
|
|
|
|
goto Notfound;
|
|
|
|
} else if(name != nil) {
|
|
|
|
if(strlen(name) >= sizeof(up->genbuf))
|
|
|
|
goto Notfound;
|
|
|
|
e = lookupname(*envhash(eg, name), name);
|
|
|
|
if(e == nil)
|
|
|
|
goto Notfound;
|
|
|
|
} else if(s < eg->nent) {
|
|
|
|
e = eg->ent[s];
|
|
|
|
if(e == nil) {
|
|
|
|
runlock(eg);
|
|
|
|
return 0; /* deleted, try next */
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Notfound:
|
2011-03-30 12:46:40 +00:00
|
|
|
runlock(eg);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* make sure name string continues to exist after we release lock */
|
2022-01-23 21:33:58 +00:00
|
|
|
kstrcpy(up->genbuf, e->name, sizeof(up->genbuf));
|
|
|
|
mkqid(&q, e->path, e->vers, QTFILE);
|
|
|
|
devdir(c, q, up->genbuf, e->len, eve,
|
2018-06-03 21:30:05 +00:00
|
|
|
eg == &confegrp || eg != up->egrp ? 0664: 0666, dp);
|
2011-03-30 12:46:40 +00:00
|
|
|
runlock(eg);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Chan*
|
|
|
|
envattach(char *spec)
|
|
|
|
{
|
|
|
|
Chan *c;
|
|
|
|
Egrp *egrp = nil;
|
|
|
|
|
2014-08-13 21:09:47 +00:00
|
|
|
if(spec != nil && *spec != '\0') {
|
|
|
|
if(strcmp(spec, "c") != 0)
|
2011-03-30 12:46:40 +00:00
|
|
|
error(Ebadarg);
|
2014-08-13 21:09:47 +00:00
|
|
|
egrp = &confegrp;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
c = devattach('e', spec);
|
|
|
|
c->aux = egrp;
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Walkqid*
|
|
|
|
envwalk(Chan *c, Chan *nc, char **name, int nname)
|
|
|
|
{
|
2022-01-23 21:33:58 +00:00
|
|
|
return devwalk(c, nc, name, nname, nil, 0, envgen);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
envstat(Chan *c, uchar *db, int n)
|
|
|
|
{
|
2022-01-23 21:33:58 +00:00
|
|
|
return devstat(c, db, n, nil, 0, envgen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void*
|
|
|
|
envrealloc(Egrp *eg, void *old, int newsize)
|
|
|
|
{
|
|
|
|
int oldsize = old != nil ? msize(old) : 0;
|
|
|
|
void *new;
|
|
|
|
|
|
|
|
if(newsize == 0){
|
|
|
|
eg->alloc -= oldsize;
|
|
|
|
free(old);
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
if(newsize < 0 || eg != &confegrp && (eg->alloc + newsize) - oldsize > Maxenvsize)
|
|
|
|
error(Enomem);
|
|
|
|
new = realloc(old, newsize);
|
|
|
|
if(new == nil)
|
|
|
|
error(Enomem);
|
|
|
|
eg->alloc += msize(new) - oldsize;
|
|
|
|
setmalloctag(new, getcallerpc(&eg));
|
|
|
|
return new;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Chan*
|
|
|
|
envopen(Chan *c, int omode)
|
|
|
|
{
|
|
|
|
Egrp *eg;
|
|
|
|
Evalue *e;
|
|
|
|
|
|
|
|
eg = envgrp(c);
|
|
|
|
if(c->qid.type & QTDIR) {
|
|
|
|
if(omode != OREAD)
|
|
|
|
error(Eperm);
|
|
|
|
}
|
|
|
|
else {
|
2022-01-23 21:33:58 +00:00
|
|
|
int trunc = omode & OTRUNC;
|
|
|
|
if(omode != OREAD && !envwritable(c))
|
2011-03-30 12:46:40 +00:00
|
|
|
error(Eperm);
|
|
|
|
if(trunc)
|
|
|
|
wlock(eg);
|
|
|
|
else
|
|
|
|
rlock(eg);
|
2022-01-23 21:33:58 +00:00
|
|
|
e = envindex(eg, c->qid.path);
|
2014-08-13 21:09:47 +00:00
|
|
|
if(e == nil) {
|
2011-03-30 12:46:40 +00:00
|
|
|
if(trunc)
|
|
|
|
wunlock(eg);
|
|
|
|
else
|
|
|
|
runlock(eg);
|
|
|
|
error(Enonexist);
|
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
if(trunc && e->len > 0) {
|
|
|
|
e->value = envrealloc(eg, e->value, 0); /* free */
|
2011-03-30 12:46:40 +00:00
|
|
|
e->len = 0;
|
2022-01-23 21:33:58 +00:00
|
|
|
e->vers++;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
c->qid.vers = e->vers;
|
2011-03-30 12:46:40 +00:00
|
|
|
if(trunc)
|
|
|
|
wunlock(eg);
|
|
|
|
else
|
|
|
|
runlock(eg);
|
|
|
|
}
|
|
|
|
c->mode = openmode(omode);
|
2015-11-22 01:39:57 +00:00
|
|
|
incref(eg);
|
|
|
|
c->aux = eg;
|
2011-03-30 12:46:40 +00:00
|
|
|
c->offset = 0;
|
2015-11-22 01:39:57 +00:00
|
|
|
c->flag |= COPEN;
|
2011-03-30 12:46:40 +00:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2011-08-17 21:27:31 +00:00
|
|
|
static Chan*
|
2011-03-30 12:46:40 +00:00
|
|
|
envcreate(Chan *c, char *name, int omode, ulong)
|
|
|
|
{
|
|
|
|
Egrp *eg;
|
2022-01-23 21:33:58 +00:00
|
|
|
Evalue *e, **h;
|
|
|
|
int n, i;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2022-01-23 21:33:58 +00:00
|
|
|
if(c->qid.type != QTDIR || !envwritable(c))
|
2011-03-30 12:46:40 +00:00
|
|
|
error(Eperm);
|
|
|
|
|
2022-01-23 21:33:58 +00:00
|
|
|
n = strlen(name)+1;
|
|
|
|
if(n > sizeof(up->genbuf))
|
2012-02-08 01:32:03 +00:00
|
|
|
error(Etoolong);
|
2012-02-07 23:00:42 +00:00
|
|
|
|
2011-03-30 12:46:40 +00:00
|
|
|
omode = openmode(omode);
|
|
|
|
eg = envgrp(c);
|
|
|
|
wlock(eg);
|
|
|
|
if(waserror()) {
|
|
|
|
wunlock(eg);
|
|
|
|
nexterror();
|
|
|
|
}
|
|
|
|
|
2022-01-23 21:33:58 +00:00
|
|
|
h = envhash(eg, name);
|
|
|
|
if(lookupname(*h, name) != nil)
|
2011-03-30 12:46:40 +00:00
|
|
|
error(Eexist);
|
|
|
|
|
2022-01-23 21:33:58 +00:00
|
|
|
for(i = eg->low; i < eg->nent; i++)
|
|
|
|
if(eg->ent[i] == nil)
|
|
|
|
break;
|
2015-08-02 19:39:33 +00:00
|
|
|
|
2022-01-23 21:33:58 +00:00
|
|
|
if(i >= eg->nent){
|
|
|
|
if((eg->nent % DELTAENV) == 0)
|
|
|
|
eg->ent = envrealloc(eg, eg->ent, (eg->nent+DELTAENV) * sizeof(Evalue*));
|
|
|
|
i = eg->nent++;
|
|
|
|
eg->ent[i] = nil;
|
|
|
|
eg->low = i;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
|
|
|
|
e = envrealloc(eg, nil, sizeof(Evalue)+n);
|
|
|
|
memmove(e->name, name, n);
|
2015-08-02 19:39:33 +00:00
|
|
|
e->value = nil;
|
|
|
|
e->len = 0;
|
2022-01-23 21:33:58 +00:00
|
|
|
e->vers = 0;
|
|
|
|
e->path = PATH(++eg->path, i);
|
|
|
|
e->hash = *h, *h = e;
|
|
|
|
eg->ent[i] = e;
|
|
|
|
eg->low = i+1;
|
|
|
|
eg->vers++;
|
|
|
|
mkqid(&c->qid, e->path, e->vers, QTFILE);
|
2011-03-30 12:46:40 +00:00
|
|
|
wunlock(eg);
|
|
|
|
poperror();
|
2015-11-22 01:39:57 +00:00
|
|
|
incref(eg);
|
|
|
|
c->aux = eg;
|
2011-03-30 12:46:40 +00:00
|
|
|
c->offset = 0;
|
|
|
|
c->mode = omode;
|
|
|
|
c->flag |= COPEN;
|
2011-08-17 21:27:31 +00:00
|
|
|
return c;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
envremove(Chan *c)
|
|
|
|
{
|
|
|
|
Egrp *eg;
|
2022-01-23 21:33:58 +00:00
|
|
|
Evalue *e, **h;
|
|
|
|
int i;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2022-01-23 21:33:58 +00:00
|
|
|
if(c->qid.type & QTDIR || !envwritable(c))
|
2011-03-30 12:46:40 +00:00
|
|
|
error(Eperm);
|
|
|
|
|
|
|
|
eg = envgrp(c);
|
|
|
|
wlock(eg);
|
2022-01-23 21:33:58 +00:00
|
|
|
e = envindex(eg, c->qid.path);
|
2015-08-03 20:08:10 +00:00
|
|
|
if(e == nil){
|
|
|
|
wunlock(eg);
|
|
|
|
error(Enonexist);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
for(h = envhash(eg, e->name); *h != nil; h = &(*h)->hash){
|
|
|
|
if(*h == e){
|
|
|
|
*h = e->hash;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
i = QID(c->qid.path);
|
|
|
|
eg->ent[i] = nil;
|
|
|
|
if(i < eg->low)
|
|
|
|
eg->low = i;
|
2015-08-03 20:08:10 +00:00
|
|
|
eg->vers++;
|
2022-01-23 21:33:58 +00:00
|
|
|
|
|
|
|
/* free */
|
|
|
|
envrealloc(eg, e->value, 0);
|
|
|
|
envrealloc(eg, e, 0);
|
|
|
|
|
2011-03-30 12:46:40 +00:00
|
|
|
wunlock(eg);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
envclose(Chan *c)
|
|
|
|
{
|
2015-11-22 01:39:57 +00:00
|
|
|
if(c->flag & COPEN){
|
|
|
|
/*
|
|
|
|
* cclose can't fail, so errors from remove will be ignored.
|
|
|
|
* since permissions aren't checked,
|
|
|
|
* envremove can't not remove it if its there.
|
|
|
|
*/
|
|
|
|
if(c->flag & CRCLOSE && !waserror()){
|
|
|
|
envremove(c);
|
|
|
|
poperror();
|
|
|
|
}
|
|
|
|
closeegrp((Egrp*)c->aux);
|
|
|
|
c->aux = nil;
|
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static long
|
|
|
|
envread(Chan *c, void *a, long n, vlong off)
|
|
|
|
{
|
|
|
|
Egrp *eg;
|
|
|
|
Evalue *e;
|
|
|
|
|
|
|
|
if(c->qid.type & QTDIR)
|
2022-01-23 21:33:58 +00:00
|
|
|
return devdirread(c, a, n, nil, 0, envgen);
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
eg = envgrp(c);
|
|
|
|
rlock(eg);
|
2015-08-02 19:39:33 +00:00
|
|
|
if(waserror()){
|
2011-03-30 12:46:40 +00:00
|
|
|
runlock(eg);
|
2015-08-02 19:39:33 +00:00
|
|
|
nexterror();
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
e = envindex(eg, c->qid.path);
|
2015-08-02 19:39:33 +00:00
|
|
|
if(e == nil)
|
|
|
|
error(Enonexist);
|
2022-01-23 21:33:58 +00:00
|
|
|
if(off >= e->len)
|
2011-03-30 12:46:40 +00:00
|
|
|
n = 0;
|
2022-01-23 21:33:58 +00:00
|
|
|
else if(off + n > e->len)
|
|
|
|
n = e->len - off;
|
2011-03-30 12:46:40 +00:00
|
|
|
if(n <= 0)
|
|
|
|
n = 0;
|
|
|
|
else
|
2022-01-23 21:33:58 +00:00
|
|
|
memmove(a, e->value+off, n);
|
2011-03-30 12:46:40 +00:00
|
|
|
runlock(eg);
|
2015-08-02 19:39:33 +00:00
|
|
|
poperror();
|
2011-03-30 12:46:40 +00:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static long
|
|
|
|
envwrite(Chan *c, void *a, long n, vlong off)
|
|
|
|
{
|
|
|
|
Egrp *eg;
|
|
|
|
Evalue *e;
|
2022-01-23 21:33:58 +00:00
|
|
|
int diff;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
eg = envgrp(c);
|
|
|
|
wlock(eg);
|
2015-08-02 19:39:33 +00:00
|
|
|
if(waserror()){
|
2011-03-30 12:46:40 +00:00
|
|
|
wunlock(eg);
|
2015-08-02 19:39:33 +00:00
|
|
|
nexterror();
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
e = envindex(eg, c->qid.path);
|
2015-08-02 19:39:33 +00:00
|
|
|
if(e == nil)
|
|
|
|
error(Enonexist);
|
2022-01-23 21:33:58 +00:00
|
|
|
if(off > Maxvalsize || n > (Maxvalsize - off))
|
|
|
|
error(Etoobig);
|
|
|
|
diff = (off+n) - e->len;
|
|
|
|
if(diff > 0)
|
|
|
|
e->value = envrealloc(eg, e->value, e->len+diff);
|
|
|
|
else
|
|
|
|
diff = 0;
|
|
|
|
memmove(e->value+off, a, n); /* might fault */
|
|
|
|
if(off > e->len)
|
|
|
|
memset(e->value+e->len, 0, off-e->len);
|
|
|
|
e->len += diff;
|
|
|
|
e->vers++;
|
2011-03-30 12:46:40 +00:00
|
|
|
eg->vers++;
|
|
|
|
wunlock(eg);
|
2015-08-02 19:39:33 +00:00
|
|
|
poperror();
|
2011-03-30 12:46:40 +00:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
Dev envdevtab = {
|
|
|
|
'e',
|
|
|
|
"env",
|
|
|
|
|
|
|
|
devreset,
|
|
|
|
devinit,
|
|
|
|
devshutdown,
|
|
|
|
envattach,
|
|
|
|
envwalk,
|
|
|
|
envstat,
|
|
|
|
envopen,
|
|
|
|
envcreate,
|
|
|
|
envclose,
|
|
|
|
envread,
|
|
|
|
devbread,
|
|
|
|
envwrite,
|
|
|
|
devbwrite,
|
|
|
|
envremove,
|
|
|
|
devwstat,
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
envcpy(Egrp *to, Egrp *from)
|
|
|
|
{
|
2022-01-23 21:33:58 +00:00
|
|
|
Evalue *e, *ne, **h;
|
|
|
|
int i, n;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
rlock(from);
|
2022-01-23 21:33:58 +00:00
|
|
|
if(waserror()){
|
|
|
|
runlock(from);
|
|
|
|
nexterror();
|
|
|
|
}
|
|
|
|
to->nent = 0;
|
|
|
|
to->ent = envrealloc(to, nil, ROUND(from->nent, DELTAENV) * sizeof(Evalue*));
|
|
|
|
for(i = 0; i < from->nent; i++){
|
|
|
|
e = from->ent[i];
|
|
|
|
if(e == nil)
|
|
|
|
continue;
|
|
|
|
h = envhash(to, e->name);
|
|
|
|
n = strlen(e->name)+1;
|
|
|
|
ne = envrealloc(to, nil, sizeof(Evalue)+n);
|
|
|
|
memmove(ne->name, e->name, n);
|
|
|
|
ne->value = nil;
|
|
|
|
ne->len = 0;
|
|
|
|
ne->vers = 0;
|
|
|
|
ne->path = PATH(++to->path, to->nent);
|
|
|
|
ne->hash = *h, *h = ne;
|
|
|
|
to->ent[to->nent++] = ne;
|
|
|
|
if(e->len > 0){
|
|
|
|
ne->value = envrealloc(to, ne->value, e->len);
|
2011-03-30 12:46:40 +00:00
|
|
|
memmove(ne->value, e->value, e->len);
|
|
|
|
ne->len = e->len;
|
|
|
|
}
|
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
to->low = to->nent;
|
2011-03-30 12:46:40 +00:00
|
|
|
runlock(from);
|
2022-01-23 21:33:58 +00:00
|
|
|
poperror();
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
closeegrp(Egrp *eg)
|
|
|
|
{
|
2022-01-23 21:33:58 +00:00
|
|
|
Evalue *e;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if(decref(eg) || eg == &confegrp)
|
|
|
|
return;
|
|
|
|
for(i = 0; i < eg->nent; i++){
|
|
|
|
e = eg->ent[i];
|
|
|
|
if(e == nil)
|
|
|
|
continue;
|
|
|
|
free(e->value);
|
|
|
|
free(e);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
free(eg->ent);
|
|
|
|
free(eg);
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static Egrp*
|
|
|
|
envgrp(Chan *c)
|
|
|
|
{
|
|
|
|
if(c->aux == nil)
|
|
|
|
return up->egrp;
|
|
|
|
return c->aux;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2022-01-23 21:33:58 +00:00
|
|
|
envwritable(Chan *c)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2014-08-13 21:09:47 +00:00
|
|
|
return c->aux == nil || c->aux == up->egrp || iseve();
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* to let the kernel set environment variables
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ksetenv(char *ename, char *eval, int conf)
|
|
|
|
{
|
|
|
|
Chan *c;
|
|
|
|
char buf[2*KNAMELEN];
|
|
|
|
|
|
|
|
snprint(buf, sizeof(buf), "#e%s/%s", conf?"c":"", ename);
|
2018-06-03 21:30:05 +00:00
|
|
|
c = namec(buf, Acreate, OWRITE, 0666);
|
2011-03-30 12:46:40 +00:00
|
|
|
devtab[c->type]->write(c, eval, strlen(eval), 0);
|
|
|
|
cclose(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return a copy of configuration environment as a sequence of strings.
|
|
|
|
* The strings alternate between name and value. A zero length name string
|
|
|
|
* indicates the end of the list
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
getconfenv(void)
|
|
|
|
{
|
|
|
|
Egrp *eg = &confegrp;
|
2022-01-23 21:33:58 +00:00
|
|
|
Evalue *e;
|
2011-03-30 12:46:40 +00:00
|
|
|
char *p, *q;
|
2022-01-23 21:33:58 +00:00
|
|
|
int i, n;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
|
|
|
rlock(eg);
|
2022-01-23 21:33:58 +00:00
|
|
|
n = 1;
|
|
|
|
for(i = 0; i < eg->nent; i++){
|
|
|
|
e = eg->ent[i];
|
|
|
|
if(e == nil)
|
|
|
|
continue;
|
|
|
|
n += strlen(e->name)+e->len+2;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2022-01-23 21:33:58 +00:00
|
|
|
p = malloc(n);
|
|
|
|
if(p == nil){
|
|
|
|
runlock(eg);
|
2011-03-30 12:46:40 +00:00
|
|
|
error(Enomem);
|
2022-01-23 21:33:58 +00:00
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
q = p;
|
2022-01-23 21:33:58 +00:00
|
|
|
for(i = 0; i < eg->nent; i++){
|
|
|
|
e = eg->ent[i];
|
|
|
|
if(e == nil)
|
|
|
|
continue;
|
|
|
|
n = strlen(e->name)+1;
|
|
|
|
memmove(q, e->name, n);
|
|
|
|
q += n;
|
2011-03-30 12:46:40 +00:00
|
|
|
memmove(q, e->value, e->len);
|
|
|
|
q[e->len] = 0;
|
|
|
|
/* move up to the first null */
|
|
|
|
q += strlen(q) + 1;
|
|
|
|
}
|
2014-08-13 21:09:47 +00:00
|
|
|
*q = '\0';
|
2011-03-30 12:46:40 +00:00
|
|
|
runlock(eg);
|
2022-01-23 21:33:58 +00:00
|
|
|
|
2011-03-30 12:46:40 +00:00
|
|
|
return p;
|
|
|
|
}
|