13e12c5d1SDavid du Colombier #include "u.h"
23e12c5d1SDavid du Colombier #include "../port/lib.h"
33e12c5d1SDavid du Colombier #include "mem.h"
43e12c5d1SDavid du Colombier #include "dat.h"
53e12c5d1SDavid du Colombier #include "fns.h"
63e12c5d1SDavid du Colombier #include "../port/error.h"
73e12c5d1SDavid du Colombier
83e12c5d1SDavid du Colombier enum
93e12c5d1SDavid du Colombier {
103e12c5d1SDavid du Colombier Maxenvsize = 16300,
113e12c5d1SDavid du Colombier };
123e12c5d1SDavid du Colombier
139a747e4fSDavid du Colombier static Egrp *envgrp(Chan *c);
149a747e4fSDavid du Colombier static int envwriteable(Chan *c);
159a747e4fSDavid du Colombier
169a747e4fSDavid du Colombier static Egrp confegrp; /* global environment group containing the kernel configuration */
179a747e4fSDavid du Colombier
18fb7f0c93SDavid du Colombier static Evalue*
envlookup(Egrp * eg,char * name,ulong qidpath)19fb7f0c93SDavid du Colombier envlookup(Egrp *eg, char *name, ulong qidpath)
20fb7f0c93SDavid du Colombier {
21fb7f0c93SDavid du Colombier Evalue *e;
22fb7f0c93SDavid du Colombier int i;
23fb7f0c93SDavid du Colombier
24fb7f0c93SDavid du Colombier for(i=0; i<eg->nent; i++){
25fb7f0c93SDavid du Colombier e = eg->ent[i];
26fb7f0c93SDavid du Colombier if(e->qid.path == qidpath || (name && e->name[0]==name[0] && strcmp(e->name, name) == 0))
27fb7f0c93SDavid du Colombier return e;
28fb7f0c93SDavid du Colombier }
29fb7f0c93SDavid du Colombier return nil;
30fb7f0c93SDavid du Colombier }
31fb7f0c93SDavid du Colombier
327dd7cddfSDavid du Colombier static int
envgen(Chan * c,char * name,Dirtab *,int,int s,Dir * dp)33fb7f0c93SDavid du Colombier envgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
343e12c5d1SDavid du Colombier {
353e12c5d1SDavid du Colombier Egrp *eg;
363e12c5d1SDavid du Colombier Evalue *e;
373e12c5d1SDavid du Colombier
387dd7cddfSDavid du Colombier if(s == DEVDOTDOT){
399a747e4fSDavid du Colombier devdir(c, c->qid, "#e", 0, eve, DMDIR|0775, dp);
407dd7cddfSDavid du Colombier return 1;
417dd7cddfSDavid du Colombier }
423e12c5d1SDavid du Colombier
439a747e4fSDavid du Colombier eg = envgrp(c);
449a747e4fSDavid du Colombier rlock(eg);
45fb7f0c93SDavid du Colombier e = 0;
46fb7f0c93SDavid du Colombier if(name)
47fb7f0c93SDavid du Colombier e = envlookup(eg, name, -1);
48fb7f0c93SDavid du Colombier else if(s < eg->nent)
49fb7f0c93SDavid du Colombier e = eg->ent[s];
503e12c5d1SDavid du Colombier
513e12c5d1SDavid du Colombier if(e == 0) {
529a747e4fSDavid du Colombier runlock(eg);
533e12c5d1SDavid du Colombier return -1;
543e12c5d1SDavid du Colombier }
553e12c5d1SDavid du Colombier
569a747e4fSDavid du Colombier /* make sure name string continues to exist after we release lock */
579a747e4fSDavid du Colombier kstrcpy(up->genbuf, e->name, sizeof up->genbuf);
589a747e4fSDavid du Colombier devdir(c, e->qid, up->genbuf, e->len, eve, 0666, dp);
599a747e4fSDavid du Colombier runlock(eg);
603e12c5d1SDavid du Colombier return 1;
613e12c5d1SDavid du Colombier }
623e12c5d1SDavid du Colombier
637dd7cddfSDavid du Colombier static Chan*
envattach(char * spec)643e12c5d1SDavid du Colombier envattach(char *spec)
653e12c5d1SDavid du Colombier {
669a747e4fSDavid du Colombier Chan *c;
679a747e4fSDavid du Colombier Egrp *egrp = nil;
689a747e4fSDavid du Colombier
699a747e4fSDavid du Colombier if(spec && *spec) {
709a747e4fSDavid du Colombier if(strcmp(spec, "c") == 0)
719a747e4fSDavid du Colombier egrp = &confegrp;
729a747e4fSDavid du Colombier if(egrp == nil)
739a747e4fSDavid du Colombier error(Ebadarg);
749a747e4fSDavid du Colombier }
759a747e4fSDavid du Colombier
769a747e4fSDavid du Colombier c = devattach('e', spec);
779a747e4fSDavid du Colombier c->aux = egrp;
789a747e4fSDavid du Colombier return c;
799a747e4fSDavid du Colombier }
809a747e4fSDavid du Colombier
819a747e4fSDavid du Colombier static Walkqid*
envwalk(Chan * c,Chan * nc,char ** name,int nname)829a747e4fSDavid du Colombier envwalk(Chan *c, Chan *nc, char **name, int nname)
839a747e4fSDavid du Colombier {
849a747e4fSDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, envgen);
853e12c5d1SDavid du Colombier }
863e12c5d1SDavid du Colombier
877dd7cddfSDavid du Colombier static int
envstat(Chan * c,uchar * db,int n)889a747e4fSDavid du Colombier envstat(Chan *c, uchar *db, int n)
893e12c5d1SDavid du Colombier {
909a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
919a747e4fSDavid du Colombier c->qid.vers = envgrp(c)->vers;
929a747e4fSDavid du Colombier return devstat(c, db, n, 0, 0, envgen);
933e12c5d1SDavid du Colombier }
943e12c5d1SDavid du Colombier
957dd7cddfSDavid du Colombier static Chan*
envopen(Chan * c,int omode)963e12c5d1SDavid du Colombier envopen(Chan *c, int omode)
973e12c5d1SDavid du Colombier {
983e12c5d1SDavid du Colombier Egrp *eg;
993e12c5d1SDavid du Colombier Evalue *e;
1009a747e4fSDavid du Colombier int trunc;
1013e12c5d1SDavid du Colombier
1029a747e4fSDavid du Colombier eg = envgrp(c);
1039a747e4fSDavid du Colombier if(c->qid.type & QTDIR) {
1043e12c5d1SDavid du Colombier if(omode != OREAD)
1053e12c5d1SDavid du Colombier error(Eperm);
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier else {
1089a747e4fSDavid du Colombier trunc = omode & OTRUNC;
1099a747e4fSDavid du Colombier if(omode != OREAD && !envwriteable(c))
1109a747e4fSDavid du Colombier error(Eperm);
1119a747e4fSDavid du Colombier if(trunc)
1129a747e4fSDavid du Colombier wlock(eg);
1139a747e4fSDavid du Colombier else
1149a747e4fSDavid du Colombier rlock(eg);
1157dd7cddfSDavid du Colombier e = envlookup(eg, nil, c->qid.path);
1163e12c5d1SDavid du Colombier if(e == 0) {
1179a747e4fSDavid du Colombier if(trunc)
1189a747e4fSDavid du Colombier wunlock(eg);
1199a747e4fSDavid du Colombier else
1209a747e4fSDavid du Colombier runlock(eg);
1213e12c5d1SDavid du Colombier error(Enonexist);
1223e12c5d1SDavid du Colombier }
1239a747e4fSDavid du Colombier if(trunc && e->value) {
1247dd7cddfSDavid du Colombier e->qid.vers++;
1253e12c5d1SDavid du Colombier free(e->value);
1263e12c5d1SDavid du Colombier e->value = 0;
1273e12c5d1SDavid du Colombier e->len = 0;
1283e12c5d1SDavid du Colombier }
1299a747e4fSDavid du Colombier if(trunc)
1309a747e4fSDavid du Colombier wunlock(eg);
1319a747e4fSDavid du Colombier else
1329a747e4fSDavid du Colombier runlock(eg);
1333e12c5d1SDavid du Colombier }
1343e12c5d1SDavid du Colombier c->mode = openmode(omode);
1353e12c5d1SDavid du Colombier c->flag |= COPEN;
1363e12c5d1SDavid du Colombier c->offset = 0;
1373e12c5d1SDavid du Colombier return c;
1383e12c5d1SDavid du Colombier }
1393e12c5d1SDavid du Colombier
1407dd7cddfSDavid du Colombier static void
envcreate(Chan * c,char * name,int omode,ulong)1417dd7cddfSDavid du Colombier envcreate(Chan *c, char *name, int omode, ulong)
1423e12c5d1SDavid du Colombier {
1433e12c5d1SDavid du Colombier Egrp *eg;
1443e12c5d1SDavid du Colombier Evalue *e;
145fb7f0c93SDavid du Colombier Evalue **ent;
1463e12c5d1SDavid du Colombier
1479a747e4fSDavid du Colombier if(c->qid.type != QTDIR)
1483e12c5d1SDavid du Colombier error(Eperm);
149*6a0c38e7SDavid du Colombier if(strlen(name) >= sizeof up->genbuf)
150*6a0c38e7SDavid du Colombier error("name too long"); /* protect envgen */
1513e12c5d1SDavid du Colombier
1523e12c5d1SDavid du Colombier omode = openmode(omode);
1539a747e4fSDavid du Colombier eg = envgrp(c);
1543e12c5d1SDavid du Colombier
1559a747e4fSDavid du Colombier wlock(eg);
1563e12c5d1SDavid du Colombier if(waserror()) {
1579a747e4fSDavid du Colombier wunlock(eg);
1583e12c5d1SDavid du Colombier nexterror();
1593e12c5d1SDavid du Colombier }
1603e12c5d1SDavid du Colombier
1617dd7cddfSDavid du Colombier if(envlookup(eg, name, -1))
1627dd7cddfSDavid du Colombier error(Eexist);
1633e12c5d1SDavid du Colombier
1643e12c5d1SDavid du Colombier e = smalloc(sizeof(Evalue));
1653e12c5d1SDavid du Colombier e->name = smalloc(strlen(name)+1);
1663e12c5d1SDavid du Colombier strcpy(e->name, name);
1673e12c5d1SDavid du Colombier
168fb7f0c93SDavid du Colombier if(eg->nent == eg->ment){
169fb7f0c93SDavid du Colombier eg->ment += 32;
170fb7f0c93SDavid du Colombier ent = smalloc(sizeof(eg->ent[0])*eg->ment);
171fb7f0c93SDavid du Colombier if(eg->nent)
172fb7f0c93SDavid du Colombier memmove(ent, eg->ent, sizeof(eg->ent[0])*eg->nent);
173fb7f0c93SDavid du Colombier free(eg->ent);
174fb7f0c93SDavid du Colombier eg->ent = ent;
175fb7f0c93SDavid du Colombier }
1767dd7cddfSDavid du Colombier e->qid.path = ++eg->path;
1777dd7cddfSDavid du Colombier e->qid.vers = 0;
1787dd7cddfSDavid du Colombier eg->vers++;
179fb7f0c93SDavid du Colombier eg->ent[eg->nent++] = e;
1807dd7cddfSDavid du Colombier c->qid = e->qid;
1813e12c5d1SDavid du Colombier
1829a747e4fSDavid du Colombier wunlock(eg);
1833e12c5d1SDavid du Colombier poperror();
1843e12c5d1SDavid du Colombier
1853e12c5d1SDavid du Colombier c->offset = 0;
1863e12c5d1SDavid du Colombier c->mode = omode;
1873e12c5d1SDavid du Colombier c->flag |= COPEN;
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier
1907dd7cddfSDavid du Colombier static void
envremove(Chan * c)1913e12c5d1SDavid du Colombier envremove(Chan *c)
1923e12c5d1SDavid du Colombier {
193fb7f0c93SDavid du Colombier int i;
1943e12c5d1SDavid du Colombier Egrp *eg;
195fb7f0c93SDavid du Colombier Evalue *e;
1963e12c5d1SDavid du Colombier
1979a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
1983e12c5d1SDavid du Colombier error(Eperm);
1993e12c5d1SDavid du Colombier
2009a747e4fSDavid du Colombier eg = envgrp(c);
2019a747e4fSDavid du Colombier wlock(eg);
202fb7f0c93SDavid du Colombier e = 0;
203fb7f0c93SDavid du Colombier for(i=0; i<eg->nent; i++){
204fb7f0c93SDavid du Colombier if(eg->ent[i]->qid.path == c->qid.path){
205fb7f0c93SDavid du Colombier e = eg->ent[i];
206fb7f0c93SDavid du Colombier eg->nent--;
207fb7f0c93SDavid du Colombier eg->ent[i] = eg->ent[eg->nent];
2087dd7cddfSDavid du Colombier eg->vers++;
209fb7f0c93SDavid du Colombier break;
210fb7f0c93SDavid du Colombier }
211fb7f0c93SDavid du Colombier }
2129a747e4fSDavid du Colombier wunlock(eg);
213fb7f0c93SDavid du Colombier if(e == 0)
214fb7f0c93SDavid du Colombier error(Enonexist);
2153e12c5d1SDavid du Colombier free(e->name);
2163e12c5d1SDavid du Colombier if(e->value)
2173e12c5d1SDavid du Colombier free(e->value);
2183e12c5d1SDavid du Colombier free(e);
2193e12c5d1SDavid du Colombier }
2203e12c5d1SDavid du Colombier
2217dd7cddfSDavid du Colombier static void
envclose(Chan * c)2223e12c5d1SDavid du Colombier envclose(Chan *c)
2233e12c5d1SDavid du Colombier {
2247dd7cddfSDavid du Colombier /*
2259a747e4fSDavid du Colombier * cclose can't fail, so errors from remove will be ignored.
2267dd7cddfSDavid du Colombier * since permissions aren't checked,
2277dd7cddfSDavid du Colombier * envremove can't not remove it if its there.
2287dd7cddfSDavid du Colombier */
2297dd7cddfSDavid du Colombier if(c->flag & CRCLOSE)
2307dd7cddfSDavid du Colombier envremove(c);
2313e12c5d1SDavid du Colombier }
2323e12c5d1SDavid du Colombier
2337dd7cddfSDavid du Colombier static long
envread(Chan * c,void * a,long n,vlong off)2347dd7cddfSDavid du Colombier envread(Chan *c, void *a, long n, vlong off)
2353e12c5d1SDavid du Colombier {
2363e12c5d1SDavid du Colombier Egrp *eg;
2373e12c5d1SDavid du Colombier Evalue *e;
2387dd7cddfSDavid du Colombier ulong offset = off;
2393e12c5d1SDavid du Colombier
2409a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
2413e12c5d1SDavid du Colombier return devdirread(c, a, n, 0, 0, envgen);
2423e12c5d1SDavid du Colombier
2439a747e4fSDavid du Colombier eg = envgrp(c);
2449a747e4fSDavid du Colombier rlock(eg);
2457dd7cddfSDavid du Colombier e = envlookup(eg, nil, c->qid.path);
2463e12c5d1SDavid du Colombier if(e == 0) {
2479a747e4fSDavid du Colombier runlock(eg);
2483e12c5d1SDavid du Colombier error(Enonexist);
2493e12c5d1SDavid du Colombier }
2503e12c5d1SDavid du Colombier
2519a747e4fSDavid du Colombier if(offset > e->len) /* protects against overflow converting vlong to ulong */
2529a747e4fSDavid du Colombier n = 0;
2539a747e4fSDavid du Colombier else if(offset + n > e->len)
2543e12c5d1SDavid du Colombier n = e->len - offset;
2553e12c5d1SDavid du Colombier if(n <= 0)
2563e12c5d1SDavid du Colombier n = 0;
2573e12c5d1SDavid du Colombier else
2583e12c5d1SDavid du Colombier memmove(a, e->value+offset, n);
2599a747e4fSDavid du Colombier runlock(eg);
2603e12c5d1SDavid du Colombier return n;
2613e12c5d1SDavid du Colombier }
2623e12c5d1SDavid du Colombier
2637dd7cddfSDavid du Colombier static long
envwrite(Chan * c,void * a,long n,vlong off)2647dd7cddfSDavid du Colombier envwrite(Chan *c, void *a, long n, vlong off)
2653e12c5d1SDavid du Colombier {
2663e12c5d1SDavid du Colombier char *s;
267c717cbbdSDavid du Colombier ulong len;
2683e12c5d1SDavid du Colombier Egrp *eg;
2693e12c5d1SDavid du Colombier Evalue *e;
2707dd7cddfSDavid du Colombier ulong offset = off;
2713e12c5d1SDavid du Colombier
2723e12c5d1SDavid du Colombier if(n <= 0)
2733e12c5d1SDavid du Colombier return 0;
274c717cbbdSDavid du Colombier if(offset > Maxenvsize || n > (Maxenvsize - offset))
2753e12c5d1SDavid du Colombier error(Etoobig);
2763e12c5d1SDavid du Colombier
2779a747e4fSDavid du Colombier eg = envgrp(c);
2789a747e4fSDavid du Colombier wlock(eg);
2797dd7cddfSDavid du Colombier e = envlookup(eg, nil, c->qid.path);
2803e12c5d1SDavid du Colombier if(e == 0) {
2819a747e4fSDavid du Colombier wunlock(eg);
2823e12c5d1SDavid du Colombier error(Enonexist);
2833e12c5d1SDavid du Colombier }
2843e12c5d1SDavid du Colombier
285c717cbbdSDavid du Colombier len = offset+n;
286c717cbbdSDavid du Colombier if(len > e->len) {
287c717cbbdSDavid du Colombier s = smalloc(len);
2887dd7cddfSDavid du Colombier if(e->value){
2893e12c5d1SDavid du Colombier memmove(s, e->value, e->len);
2903e12c5d1SDavid du Colombier free(e->value);
2917dd7cddfSDavid du Colombier }
2923e12c5d1SDavid du Colombier e->value = s;
293c717cbbdSDavid du Colombier e->len = len;
2943e12c5d1SDavid du Colombier }
2953e12c5d1SDavid du Colombier memmove(e->value+offset, a, n);
2967dd7cddfSDavid du Colombier e->qid.vers++;
2977dd7cddfSDavid du Colombier eg->vers++;
2989a747e4fSDavid du Colombier wunlock(eg);
2993e12c5d1SDavid du Colombier return n;
3003e12c5d1SDavid du Colombier }
3013e12c5d1SDavid du Colombier
3027dd7cddfSDavid du Colombier Dev envdevtab = {
3037dd7cddfSDavid du Colombier 'e',
3047dd7cddfSDavid du Colombier "env",
3057dd7cddfSDavid du Colombier
3067dd7cddfSDavid du Colombier devreset,
3077dd7cddfSDavid du Colombier devinit,
3089a747e4fSDavid du Colombier devshutdown,
3097dd7cddfSDavid du Colombier envattach,
3107dd7cddfSDavid du Colombier envwalk,
3117dd7cddfSDavid du Colombier envstat,
3127dd7cddfSDavid du Colombier envopen,
3137dd7cddfSDavid du Colombier envcreate,
3147dd7cddfSDavid du Colombier envclose,
3157dd7cddfSDavid du Colombier envread,
3167dd7cddfSDavid du Colombier devbread,
3177dd7cddfSDavid du Colombier envwrite,
3187dd7cddfSDavid du Colombier devbwrite,
3197dd7cddfSDavid du Colombier envremove,
3207dd7cddfSDavid du Colombier devwstat,
3217dd7cddfSDavid du Colombier };
3227dd7cddfSDavid du Colombier
3233e12c5d1SDavid du Colombier void
envcpy(Egrp * to,Egrp * from)3243e12c5d1SDavid du Colombier envcpy(Egrp *to, Egrp *from)
3253e12c5d1SDavid du Colombier {
326fb7f0c93SDavid du Colombier int i;
327fb7f0c93SDavid du Colombier Evalue *ne, *e;
3283e12c5d1SDavid du Colombier
3299a747e4fSDavid du Colombier rlock(from);
330fb7f0c93SDavid du Colombier to->ment = (from->nent+31)&~31;
331fb7f0c93SDavid du Colombier to->ent = smalloc(to->ment*sizeof(to->ent[0]));
332fb7f0c93SDavid du Colombier for(i=0; i<from->nent; i++){
333fb7f0c93SDavid du Colombier e = from->ent[i];
3343e12c5d1SDavid du Colombier ne = smalloc(sizeof(Evalue));
3353e12c5d1SDavid du Colombier ne->name = smalloc(strlen(e->name)+1);
3363e12c5d1SDavid du Colombier strcpy(ne->name, e->name);
3373e12c5d1SDavid du Colombier if(e->value){
3383e12c5d1SDavid du Colombier ne->value = smalloc(e->len);
3393e12c5d1SDavid du Colombier memmove(ne->value, e->value, e->len);
3403e12c5d1SDavid du Colombier ne->len = e->len;
3413e12c5d1SDavid du Colombier }
3427dd7cddfSDavid du Colombier ne->qid.path = ++to->path;
343fb7f0c93SDavid du Colombier to->ent[i] = ne;
3443e12c5d1SDavid du Colombier }
345fb7f0c93SDavid du Colombier to->nent = from->nent;
3469a747e4fSDavid du Colombier runlock(from);
3473e12c5d1SDavid du Colombier }
3483e12c5d1SDavid du Colombier
3493e12c5d1SDavid du Colombier void
closeegrp(Egrp * eg)3503e12c5d1SDavid du Colombier closeegrp(Egrp *eg)
3513e12c5d1SDavid du Colombier {
352fb7f0c93SDavid du Colombier int i;
353fb7f0c93SDavid du Colombier Evalue *e;
3543e12c5d1SDavid du Colombier
3553e12c5d1SDavid du Colombier if(decref(eg) == 0){
356fb7f0c93SDavid du Colombier for(i=0; i<eg->nent; i++){
357fb7f0c93SDavid du Colombier e = eg->ent[i];
3583e12c5d1SDavid du Colombier free(e->name);
3593e12c5d1SDavid du Colombier if(e->value)
3603e12c5d1SDavid du Colombier free(e->value);
3613e12c5d1SDavid du Colombier free(e);
3623e12c5d1SDavid du Colombier }
363fb7f0c93SDavid du Colombier free(eg->ent);
3643e12c5d1SDavid du Colombier free(eg);
3653e12c5d1SDavid du Colombier }
3663e12c5d1SDavid du Colombier }
3673e12c5d1SDavid du Colombier
3689a747e4fSDavid du Colombier static Egrp*
envgrp(Chan * c)3699a747e4fSDavid du Colombier envgrp(Chan *c)
3709a747e4fSDavid du Colombier {
3719a747e4fSDavid du Colombier if(c->aux == nil)
3729a747e4fSDavid du Colombier return up->egrp;
3739a747e4fSDavid du Colombier return c->aux;
3749a747e4fSDavid du Colombier }
3759a747e4fSDavid du Colombier
3769a747e4fSDavid du Colombier static int
envwriteable(Chan * c)3779a747e4fSDavid du Colombier envwriteable(Chan *c)
3789a747e4fSDavid du Colombier {
3799a747e4fSDavid du Colombier return iseve() || c->aux == nil;
3809a747e4fSDavid du Colombier }
3819a747e4fSDavid du Colombier
3823e12c5d1SDavid du Colombier /*
3833e12c5d1SDavid du Colombier * to let the kernel set environment variables
3843e12c5d1SDavid du Colombier */
3853e12c5d1SDavid du Colombier void
ksetenv(char * ename,char * eval,int conf)3869a747e4fSDavid du Colombier ksetenv(char *ename, char *eval, int conf)
3873e12c5d1SDavid du Colombier {
3883e12c5d1SDavid du Colombier Chan *c;
3899a747e4fSDavid du Colombier char buf[2*KNAMELEN];
3903e12c5d1SDavid du Colombier
3919a747e4fSDavid du Colombier snprint(buf, sizeof(buf), "#e%s/%s", conf?"c":"", ename);
3923e12c5d1SDavid du Colombier c = namec(buf, Acreate, OWRITE, 0600);
3937dd7cddfSDavid du Colombier devtab[c->type]->write(c, eval, strlen(eval), 0);
3947dd7cddfSDavid du Colombier cclose(c);
3953e12c5d1SDavid du Colombier }
3969a747e4fSDavid du Colombier
3979a747e4fSDavid du Colombier /*
3989a747e4fSDavid du Colombier * Return a copy of configuration environment as a sequence of strings.
3999a747e4fSDavid du Colombier * The strings alternate between name and value. A zero length name string
4009a747e4fSDavid du Colombier * indicates the end of the list
4019a747e4fSDavid du Colombier */
4029a747e4fSDavid du Colombier char *
getconfenv(void)4039a747e4fSDavid du Colombier getconfenv(void)
4049a747e4fSDavid du Colombier {
4059a747e4fSDavid du Colombier Egrp *eg = &confegrp;
4069a747e4fSDavid du Colombier Evalue *e;
4079a747e4fSDavid du Colombier char *p, *q;
408fb7f0c93SDavid du Colombier int i, n;
4099a747e4fSDavid du Colombier
4109a747e4fSDavid du Colombier rlock(eg);
4119a747e4fSDavid du Colombier if(waserror()) {
4129a747e4fSDavid du Colombier runlock(eg);
4139a747e4fSDavid du Colombier nexterror();
4149a747e4fSDavid du Colombier }
4159a747e4fSDavid du Colombier
4169a747e4fSDavid du Colombier /* determine size */
4179a747e4fSDavid du Colombier n = 0;
418fb7f0c93SDavid du Colombier for(i=0; i<eg->nent; i++){
419fb7f0c93SDavid du Colombier e = eg->ent[i];
4209a747e4fSDavid du Colombier n += strlen(e->name) + e->len + 2;
421fb7f0c93SDavid du Colombier }
4229a747e4fSDavid du Colombier p = malloc(n + 1);
4239a747e4fSDavid du Colombier if(p == nil)
4249a747e4fSDavid du Colombier error(Enomem);
4259a747e4fSDavid du Colombier q = p;
426fb7f0c93SDavid du Colombier for(i=0; i<eg->nent; i++){
427fb7f0c93SDavid du Colombier e = eg->ent[i];
4289a747e4fSDavid du Colombier strcpy(q, e->name);
4299a747e4fSDavid du Colombier q += strlen(q) + 1;
4309a747e4fSDavid du Colombier memmove(q, e->value, e->len);
4319a747e4fSDavid du Colombier q[e->len] = 0;
4329a747e4fSDavid du Colombier /* move up to the first null */
4339a747e4fSDavid du Colombier q += strlen(q) + 1;
4349a747e4fSDavid du Colombier }
4359a747e4fSDavid du Colombier *q = 0;
4369a747e4fSDavid du Colombier
4379a747e4fSDavid du Colombier poperror();
4389a747e4fSDavid du Colombier runlock(eg);
4399a747e4fSDavid du Colombier return p;
4409a747e4fSDavid du Colombier }
441