xref: /plan9-contrib/sys/src/9/port/devenv.c (revision 6a0c38e7e48be1382e8d74973bfe1ab438d920a3)
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