Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/devenv.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/devenv.c 1990/0227
## diff -e /dev/null /n/bootesdump/1990/0227/sys/src/9/mips/devenv.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"

#include	"devtab.h"

/*
 * An environment value is kept in some number of contiguous
 * Envvals, with the Env's val pointing at the first.
 * Envvals are allocated from the end of a fixed arena, which
 * is compacted when the arena end is reached.
 * A `piece' (number of contiguous Envvals) is free to be
 * reclaimed if its e pointer is 0.
 *
 * Locking: an env's val can change by compaction, so lock
 * an env before using its value.  A pgrp env[] slot can go
 * to 0 and the corresponding env freed (by envremove()), so
 * lock the pgrp around the use of a value retrieved from a slot.
 * Lock in order: pgrp, envalloc, env (but ok to skip envalloc
 * lock if there is no possibility of blocking).
 */

struct Envval
{
	ulong	n;	/* number of Envval's (including this) in this piece */
	ulong	len;	/* how much of dat[] is valid */
	Env	*e;	/* the Env whose val points here */
	char	dat[4]; /* possibly extends into further envvals after this */
};

/* number of contiguous Envvals needed to hold n characters */
#define EVNEEDED(n) ((n)<4? 1 : 1+((n)+(sizeof(Envval))-1-4)/(sizeof(Envval)))

struct
{
	Lock;
	Envval	*arena;
	Envval	*vfree;
	Envval	*end;
	Env	*efree;
	Env	*earena;
}envalloc;

void	compactenv(Env *, ulong);

void
envreset(void)
{
	int i, n;

	n = EVNEEDED(conf.nenvchar);
	envalloc.arena = ialloc(n*sizeof(Envval), 0);
	envalloc.vfree = envalloc.arena;
	envalloc.end = envalloc.arena+n;

	envalloc.earena = ialloc(conf.nenv*sizeof(Env), 0);
	envalloc.efree = envalloc.earena;
	for(i=0; i<conf.nenv-1; i++)
		envalloc.earena[i].next = &envalloc.earena[i+1];
	envalloc.earena[conf.nenv-1].next = 0;
}

void
envinit(void)
{
}

/*
 * Make sure e->val points at a value big enough to hold nchars chars.
 * The caller should fix e->val->len.
 * envalloc and e should be locked
 */
void
growenval(Env *e, ulong nchars)
{
	Envval *p;
	ulong n, nfree;

	n = EVNEEDED(nchars);
	if(p = e->val){		/* assign = */
		if(p->n < n){
			if(p+p->n == envalloc.vfree){
				compactenv(e, n - p->n);
				p = e->val;
				envalloc.vfree += n - p->n;
			}else{
				compactenv(e, n);
				p = envalloc.vfree;
				envalloc.vfree += n;
				memcpy(p, e->val, e->val->n*sizeof(Envval));
				p->e = e;
				e->val->e = 0;
				e->val = p;
			}
			p->n = n;
		}
	}else{
		compactenv(e, n);
		p = envalloc.vfree;
		envalloc.vfree += n;
		p->n = n;
		p->e = e;
		e->val = p;
	}
}

/*
 * Make sure there is room for n Envval's at the end of envalloc.vfree.
 * Call this with envalloc and e locked.
 */
void
compactenv(Env *e, ulong n)
{
	Envval *p1, *p2;
	Env *p2e;

	if(envalloc.end-envalloc.vfree >= n)
		return;
	p1 = envalloc.arena;	/* dest */
	p2 = envalloc.arena;	/* source */
	while(p2 < envalloc.vfree){
		p2e = p2->e;
		if(p2e == 0){
    Free:
			p2 += p2->n;
			continue;
		}
		if(p2e<envalloc.earena || p2e>=envalloc.earena+conf.nenv){
			print("%lux not an env\n", p2e);
			panic("compactenv");
		}
		if(p1 != p2){
			if(p2e != e)
				lock(p2e);
			if(p2->e != p2e){	/* freed very recently */
				print("compactenv p2e moved\n");
				if(p2->e)
					panic("compactenv p2->e %lux\n", p2->e);
				unlock(p2e);
				goto Free;
			}
			if(p2+p2->n > envalloc.end)
				panic("compactpte copying too much");
			memcpy(p1, p2, p2->n*sizeof(Envval));
			p2e->val = p1;
			if(p2e != e)
				unlock(p2e);
		}
		p2 += p1->n;
		p1 += p1->n;
	}
	envalloc.vfree = p1;
	if(envalloc.end-envalloc.vfree < n){
		print("env compact failed\n");
		error(0, Enoenv);
	}
}

/*
 * Return an env with a copy of e's value.
 * envalloc and e should be locked,
 * and the value returned will be locked too.
 */
Env *
copyenv(Env *e, int trunc)
{
	Env *ne;
	int n;

	ne = envalloc.efree;
	if(!ne){
		print("out of envs\n");
		error(0, Enoenv);
	}
	envalloc.efree = ne->next;
	lock(ne);
	if(waserror()){
		unlock(ne);
		nexterror();
	}
	ne->next = 0;
	ne->pgref = 1;
	strncpy(ne->name, e->name, NAMELEN);
	if(e->val && !trunc){
		n = e->val->len;
		/*
		 * growenval can't hold the lock on another env
		 * because compactenv assumes only one is held
		 */
		unlock(e);
		growenval(ne, n);
		lock(e);
		if(n != e->val->len){
			print("e changed in copyenv\n");
			if(n > ne->val->len)
				n = ne->val->len;
		}
		if((char*)(ne->val+ne->val->n) < ne->val->dat+n)
			panic("copyenv corrupt");
		memcpy(ne->val->dat, e->val->dat, n);
		ne->val->len = n;
	}
	poperror();
	return ne;
}

int
envgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp)
{
	Env *e;
	Pgrp *pg;
	int ans;

	pg = u->p->pgrp;
	lock(pg);
	if(s >= pg->nenv)
		ans = -1;
	else{
		e = pg->etab[s].env;
		if(e == 0)
			ans = 0;
		else{
			lock(e);
			devdir(c, s+1, e->name, e->val? e->val->len : 0, 0666, dp);
			unlock(e);
			ans = 1;
		}
	}
	unlock(pg);
	return ans;
}

Chan*
envattach(char *spec)
{
	return devattach('e', spec);
}

Chan*
envclone(Chan *c, Chan *nc)
{
	Pgrp *pg;

	if(!(c->qid&CHDIR)){
		pg = u->p->pgrp;
		lock(pg);
		pg->etab[c->qid-1].chref++;
		unlock(pg);
	}
	return devclone(c, nc);
}

int
envwalk(Chan *c, char *name)
{
	Pgrp *pg;

	if(devwalk(c, name, 0, 0, envgen)){
		if(!(c->qid&CHDIR)){
			pg = u->p->pgrp;
			lock(pg);
			pg->etab[c->qid-1].chref++;
			unlock(pg);
			return 1;
		}
	}
	return 0;
}

void
envstat(Chan *c, char *db)
{
	devstat(c, db, 0, 0, envgen);
}

Chan *
envopen(Chan *c, int omode)
{
	Env *e, *ne;
	Envp *ep;
	Pgrp *pg;

	if(omode & (OWRITE|OTRUNC)){
		if(c->qid & CHDIR)
			error(0, Eperm);
		pg = u->p->pgrp;
		lock(pg);
		ep = &pg->etab[c->qid-1];
		e = ep->env;
		if(!e){
			unlock(pg);
			error(0, Egreg);
		}
		lock(&envalloc);
		lock(e);
		if(waserror()){
			unlock(e);
			unlock(&envalloc);
			nexterror();
		}
		if(e->pgref == 0)
			panic("envopen");
		if(e->pgref == 1){
			if((omode&OTRUNC) && e->val){
				e->val->e = 0;
				e->val = 0;
			}
		}else{
			ne = copyenv(e, omode&OTRUNC);
			e->pgref--; /* it will still be positive */
			ep->env = ne;
			unlock(ne);
		}
		poperror();
		unlock(e);
		unlock(&envalloc);
		unlock(pg);
	}
	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	return c;
}

void
envcreate(Chan *c, char *name, int omode, ulong perm)
{
	Env *e;
	Pgrp *pg;
	int i;

	if(c->qid != CHDIR)
		error(0, Eperm);
	pg = u->p->pgrp;
	lock(pg);
	lock(&envalloc);
	if(waserror()){
		unlock(&envalloc);
		unlock(pg);
		nexterror();
	}
	e = envalloc.efree;
	if(e == 0){
		print("out of envs\n");
		error(0,Enoenv);
	}
	envalloc.efree = e->next;
	e->next = 0;
	e->pgref = 1;
	strncpy(e->name, name, NAMELEN);
	if(pg->nenv == conf.npgenv){
		for(i = 0; i<pg->nenv; i++)
			if(pg->etab[i].chref == 0)
				break;
		if(i == pg->nenv){
			print("out of pgroup envs\n");
			error(0, Enoenv);
		}
	}else
		i = pg->nenv++;
	c->qid = i+1;
	pg->etab[i].env = e;
	pg->etab[i].chref = 1;
	unlock(&envalloc);
	unlock(pg);
	c->offset = 0;
	c->mode = openmode(omode);
	poperror();
	c->flag |= COPEN;
}

void
envremove(Chan *c)
{
	Env *e;
	Envp *ep;
	Pgrp *pg;

	if(c->qid & CHDIR)
		error(0, Eperm);
	pg = u->p->pgrp;
	lock(pg);
	ep = &pg->etab[c->qid-1];
	e = ep->env;
	if(!e){
		unlock(pg);
		error(0, Enonexist);
	}
	ep->env = 0;
	ep->chref--;
	envpgclose(e);
	unlock(pg);
}

void
envwstat(Chan *c, char *db)
{	int dumpenv(void);
	dumpenv();  /*DEBUG*/
	print("envwstat\n");
	error(0, Egreg);
}

void
envclose(Chan * c)
{
	Pgrp *pg;

	if(c->qid & CHDIR)
		return;
	pg = u->p->pgrp;
	lock(pg);
	pg->etab[c->qid-1].chref--;
	unlock(pg);
}

void
envpgclose(Env *e)
{
	lock(&envalloc);
	lock(e);
	if(--e->pgref <= 0){
		if(e->val){
			e->val->e = 0;
			e->val = 0;
		}
		e->next = envalloc.efree;
		envalloc.efree = e;
	}
	unlock(e);
	unlock(&envalloc);
}

long
envread(Chan *c, void *va, long n)
{
	Env *e;
	Envval *ev;
	char *p;
	long vn;
	Pgrp *pg;
	char *a = va;

	if(c->qid & CHDIR)
		return devdirread(c, a, n, 0, 0, envgen);
	pg = u->p->pgrp;
	lock(pg);
	e = pg->etab[c->qid-1].env;
	if(!e){
		unlock(pg);
		error(0, Eio);
	}
	lock(e);
	ev = e->val;
	vn = ev? e->val->len : 0;
	if(c->offset+n > vn)
		n = vn - c->offset;
	if(n <= 0)
		n = 0;
	else
		memcpy(a, ev->dat+c->offset, n);
	unlock(e);
	unlock(pg);
	return n;
}

long
envwrite(Chan *c, void *va, long n)
{
	Env *e;
	char *p;
	Envval *ev;
	long vn;
	Pgrp *pg;
	char *a = va;

	if(n <= 0)
		return 0;
	pg = u->p->pgrp;
	lock(pg);
	e = pg->etab[c->qid-1].env; /* caller checks for CHDIR */
	if(!e){
		unlock(pg);
		error(0, Eio);
	}
	lock(&envalloc);
	lock(e);
	if(waserror()){
		unlock(e);
		unlock(&envalloc);
		unlock(pg);
		nexterror();
	}
	if(e->pgref>1)
		panic("envwrite to non-duped env");
	growenval(e, c->offset+n);
	ev = e->val;
	vn = ev? ev->len : 0;
	if(c->offset > vn)
		error(0, Egreg); /* perhaps should zero fill */
	memcpy(ev->dat+c->offset, a, n);
	e->val->len = c->offset+n;
	poperror();
	unlock(e);
	unlock(&envalloc);
	unlock(pg);
	return n;
}

void
dumpenv(void)
{
	Env *e;
	Envp *ep;
	Envval *ev;
	Pgrp *pg;
	int i;
	char hold;

	pg = u->p->pgrp;
	for(ep=pg->etab, i=0; i<pg->nenv; i++, ep++)
		print("P%d(%lux %d)",i, ep->env, ep->chref);
	for(e=envalloc.earena; e<&envalloc.earena[conf.nenv]; e++)
		if(e->pgref){
			print("E{%lux %d '%s'}[", e, e->pgref, e->name);
			if(e->val){
				hold = e->val->dat[e->val->len];
				e->val->dat[e->val->len] = 0;
				print("%s", e->val->dat);
				e->val->dat[e->val->len] = hold;
			}
			print("]");
		}else if(e->val)
			print("whoops, free env %lux has val=%lux\n",e,e->val);
	for(i=0, e=envalloc.efree; e; e=e->next)
		i++;
	print("\n%d free envs", i);
	for(i=0, ev=envalloc.arena; ev<envalloc.vfree; ev+=ev->n)
		if(!ev->e)
			i += ev->n*sizeof(Envval);
	print(" %d free enval chars\n", i+((char *)envalloc.end-(char*)envalloc.vfree));
}

void
envuserstr(Error *e, char *buf)
{
	consuserstr(e, buf);
}

void
enverrstr(Error *e, char *buf)
{
	rooterrstr(e, buf);
}

.
## diffname port/devenv.c 1990/03042
## diff -e /n/bootesdump/1990/0227/sys/src/9/mips/devenv.c /n/bootesdump/1990/03042/sys/src/9/mips/devenv.c
301a
			unlock(pg);
.
## diffname port/devenv.c 1990/0802
## diff -e /n/bootesdump/1990/03042/sys/src/9/mips/devenv.c /n/bootesdump/1990/0802/sys/src/9/mips/devenv.c
146c
				panic("compactenv copying too much");
.
## diffname port/devenv.c 1990/11211
## diff -e /n/bootesdump/1990/0802/sys/src/9/mips/devenv.c /n/bootesdump/1990/11211/sys/src/9/mips/devenv.c
546,558d
503c
		error(Egreg); /* perhaps should zero fill */
.
487c
		error(Eio);
.
484c
	e = pg->etab[c->qid.path-1].env; /* caller checks for CHDIR */
.
454c
		error(Eio);
.
451c
	e = pg->etab[c->qid.path-1].env;
.
447c
	if(c->qid.path & CHDIR)
.
416c
	pg->etab[c->qid.path-1].chref--;
.
412c
	if(c->qid.path & CHDIR)
.
404c
	error(Egreg);
.
391c
		error(Enonexist);
.
387c
	ep = &pg->etab[c->qid.path-1];
.
383,384c
	if(c->qid.path & CHDIR)
		error(Eperm);
.
365c
	c->qid.path = i+1;
.
361c
			error(Enoenv);
.
349c
		error(Enoenv);
.
336,337c
	if(c->qid.path != CHDIR)
		error(Eperm);
.
295c
			error(Egreg);
.
291c
		ep = &pg->etab[c->qid.path-1];
.
287,288c
		if(c->qid.path & CHDIR)
			error(Eperm);
.
265c
			pg->etab[c->qid.path-1].chref++;
.
262c
		if(!(c->qid.path&CHDIR)){
.
250c
		pg->etab[c->qid.path-1].chref++;
.
247c
	if(!(c->qid.path&CHDIR)){
.
227c
			devdir(c, (Qid){s+1,0}, e->name, e->val? e->val->len : 0, 0666, dp);
.
176c
		error(Enoenv);
.
158c
		error(Enoenv);
.
## diffname port/devenv.c 1991/0318
## diff -e /n/bootesdump/1990/1210/sys/src/9/mips/devenv.c /n/bootesdump/1991/0318/sys/src/9/port/devenv.c
504c
	memmove(ev->dat+c->offset, a, n);
.
464c
		memmove(a, ev->dat+c->offset, n);
.
203c
		memmove(ne->val->dat, e->val->dat, n);
.
147c
			memmove(p1, p2, p2->n*sizeof(Envval));
.
93c
				memmove(p, e->val, e->val->n*sizeof(Envval));
.
## diffname port/devenv.c 1991/0411
## diff -e /n/bootesdump/1991/0318/sys/src/9/port/devenv.c /n/bootesdump/1991/0411/sys/src/9/port/devenv.c
504,505c
	memmove(ev->dat+offset, a, n);
	e->val->len = offset+n;
.
502c
	if(offset > vn)
.
499c
	growenval(e, offset+n);
.
471c
envwrite(Chan *c, void *va, long n, ulong offset)
.
464c
		memmove(a, ev->dat+offset, n);
.
459,460c
	if(offset+n > vn)
		n = vn - offset;
.
438c
envread(Chan *c, void *va, long n, ulong offset)
.
## diffname port/devenv.c 1991/0419
## diff -e /n/bootesdump/1991/0411/sys/src/9/port/devenv.c /n/bootesdump/1991/0419/sys/src/9/port/devenv.c
272a
Chan*
envclwalk(Chan *c, char *name)
{
	return devclwalk(c, name);
}

.
## diffname port/devenv.c 1991/0427
## diff -e /n/bootesdump/1991/0419/sys/src/9/port/devenv.c /n/bootesdump/1991/0427/sys/src/9/port/devenv.c
273,278d
## diffname port/devenv.c 1991/0705
## diff -e /n/bootesdump/1991/0427/sys/src/9/port/devenv.c /n/bootesdump/1991/0705/sys/src/9/port/devenv.c
523,524c
	eg = u->p->egrp;
	for(ep=eg->etab, i=0; i<eg->nenv; i++, ep++)
.
519c
	Egrp *eg;
.
509c
	unlock(eg);
.
494c
		unlock(eg);
.
486c
		unlock(eg);
.
482,484c
	eg = u->p->egrp;
	lock(eg);
	e = eg->etab[c->qid.path-1].env; /* caller checks for CHDIR */
.
477c
	Egrp *eg;
.
466c
	unlock(eg);
.
453c
		unlock(eg);
.
449,451c
	eg = u->p->egrp;
	lock(eg);
	e = eg->etab[c->qid.path-1].env;
.
444c
	Egrp *eg;
.
414,417c
	eg = u->p->egrp;
	lock(eg);
	eg->etab[c->qid.path-1].chref--;
	unlock(eg);
.
410c
	Egrp *eg;
.
396c
	unlock(eg);
.
390c
		unlock(eg);
.
385,387c
	eg = u->p->egrp;
	lock(eg);
	ep = &eg->etab[c->qid.path-1];
.
381c
	Egrp *eg;
.
369c
	unlock(eg);
.
366,367c
	eg->etab[i].env = e;
	eg->etab[i].chref = 1;
.
364c
		i = eg->nenv++;
.
359,360c
		if(i == eg->nenv){
			print("out of egroup envs\n");
.
355,357c
	if(eg->nenv == conf.npgenv){
		for(i = 0; i<eg->nenv; i++)
			if(eg->etab[i].chref == 0)
.
343c
		unlock(eg);
.
338,339c
	eg = u->p->egrp;
	lock(eg);
.
333c
	Egrp *eg;
.
321c
		unlock(eg);
.
302c
			unlock(eg);
.
294c
			unlock(eg);
.
289,291c
		eg = u->p->egrp;
		lock(eg);
		ep = &eg->etab[c->qid.path-1];
.
284c
	Egrp *eg;
.
263,266c
			eg = u->p->egrp;
			lock(eg);
			eg->etab[c->qid.path-1].chref++;
			unlock(eg);
.
259c
	Egrp *eg;
.
248,251c
		eg = u->p->egrp;
		lock(eg);
		eg->etab[c->qid.path-1].chref++;
		unlock(eg);
.
245c
	Egrp *eg;
.
232c
	unlock(eg);
.
222c
		e = eg->etab[s].env;
.
217,219c
	eg = u->p->egrp;
	lock(eg);
	if(s >= eg->nenv)
.
214c
	Egrp *eg;
.
## diffname port/devenv.c 1991/0927
## diff -e /n/bootesdump/1991/0705/sys/src/9/port/devenv.c /n/bootesdump/1991/0927/sys/src/9/port/devenv.c
545a

/*
 *  to let the kernel set environment variables
 */
void
ksetenv(char *ename, char *eval)
{
	Chan *c;
	char buf[2*NAMELEN];

	sprint(buf, "#e/%s", ename);
	c = namec(buf, Acreate, OWRITE, 0600);
	(*devtab[c->type].write)(c, eval, strlen(eval), 0);
	close(c);
}
.
## diffname port/devenv.c 1991/1018
## diff -e /n/bootesdump/1991/0927/sys/src/9/port/devenv.c /n/bootesdump/1991/1018/sys/src/9/port/devenv.c
523,544c
	h = 0;
	for(t = (uchar*)s; t - (uchar*)s < n; t++)
		h = (h << 1) ^ *t;
	h &= EVHASH - 1;
	for(ev = evhash[h].next; ev; ev = ev->next)
		if(ev->len == n && memcmp(ev->val, s, n) == 0){
			ev->ref++;
			return ev;
		}
	ev = evalloc(n);
	ev->len = n;
	memmove(ev->val, s, n);
	if(ev->next = evhash[h].next)
		ev->next->prev = ev;
	evhash[h].next = ev;
	ev->prev = &evhash[h];
	return ev;
}

/*
 * called only from newev
 */
Envval *
evalloc(ulong n)
{
	Envval *ev, **p;
	char *b, *lim;
	ulong size;

	n = (n - 1) / ALIGN;
	size = (n + 1) * ALIGN;
	p = &envalloc.free[n < EVFREE ? n : EVFREE];
	for(ev = *p; ev; ev = *p){
		if(ev->len == size){
			*p = ev->next;
			ev->ref = 1;
			return ev;
		}
		p = &ev->next;
	}

	/*
	 * make sure we have enough space to allocate the buffer.
	 * if not, use the remaining space for the smallest buffers
	 */
	if(size > MAXENV)
		panic("evalloc");
	b = envalloc.block;
	lim = envalloc.lim;
	if(!b || lim < b + size + sizeof *ev){
		p = &envalloc.free[0];
		while(lim >= b + ALIGN + sizeof *ev){
			ev = (Envval*)b;
			ev->len = ALIGN;
			ev->val = b + sizeof *ev;
			ev->next = *p;
			*p = ev;
			b += ALIGN + sizeof *ev;
		}
		b = (char*)VA(kmap(newpage(0, 0, 0)));
		envalloc.lim = b + BY2PG;
	}

	ev = (Envval*)b;
	ev->val = b + sizeof *ev;
	ev->ref = 1;
	envalloc.block = b + size + sizeof *ev;
	return ev;
}

/*
 * called with evlock qlocked
 */
void
evfree(Envval *ev)
{
	int n;

	if(--ev->ref > 0)
		return;

	if(ev->prev)
		ev->prev->next = ev->next;
	if(ev->next)
		ev->next->prev = ev->prev;
	n = (ev->len + ALIGN - 1) & ~(ALIGN - 1);
	ev->len = n;
	n = (n - 1) / ALIGN;
	if(n > EVFREE)
		n = EVFREE;
	ev->next = envalloc.free[n];
	envalloc.free[n] = ev;
.
519,521c
	uchar *t;
	int h;
.
516,517d
513,514c
/*
 * called with evlock qlocked
 */
Envval *
newev(char *s, ulong n)
.
501,509c
	olen = ev ? ev->len : 0;
	qlock(&evlock);
	if(offset == 0 && n >= olen)
		e->val = newev(a, n);
	else{
		if(olen > offset)
			olen = offset;
		if(ev)
			memmove(evscratch, ev->val, olen);
		if(olen < offset)
			memset(evscratch + olen, '\0', offset - olen);
		memmove(evscratch + offset, a, n);
		e->val = newev(evscratch, offset + n);
	}
	if(ev)
		evfree(ev);
	qunlock(&evlock);
	qunlock(&eg->ev);
.
489,499d
483,487c
	qlock(&eg->ev);
	e = &eg->etab[c->qid.path-1];
	if(!e->name){
		qunlock(&eg->ev);
		error(Enonexist);
.
481a
	if(offset + n > MAXENV)
		error(Etoobig);
.
476,478c
	ulong olen;
.
474d
472a
	Egrp *eg;
.
471c
envwrite(Chan *c, void *a, long n, ulong offset)
.
464,466c
		memmove(a, ev->val + offset, n);
	qunlock(&eg->ev);
.
458,459c
	vn = ev ? ev->len : 0;
	if(offset + n > vn)
.
456d
450,454c
	qlock(&eg->ev);
	e = &eg->etab[c->qid.path-1];
	if(!e->name){
		qunlock(&eg->ev);
		error(Enonexist);
.
444,445d
442d
439a
	Egrp *eg;
.
438c
envread(Chan *c, void *a, long n, ulong offset)
.
423,434c
	qlock(&evlock);
	if(e->name)
		evfree(e->name);
	if(e->val)
		evfree(e->val);
	e->name = e->val = 0;
	qunlock(&evlock);
.
412,417c
void
envpgcopy(Env *t, Env *f)
{
	qlock(&evlock);
	if(t->name = f->name)
		t->name->ref++;
	if(t->val = f->val)
		t->val->ref++;
	qunlock(&evlock);
.
410c
}
.
401,404c
{
	error(Eperm);
.
396c
	qunlock(&eg->ev);
.
393,394d
386,390c
	qlock(&eg->ev);
	e = &eg->etab[c->qid.path-1];
	if(!e->name){
		qunlock(&eg->ev);
.
381a
	Env *e;
.
379,380d
371,372c
	c->mode = omode;
.
351,369c
	i = e - eg->etab + 1;
	e->val = 0;
	qlock(&evlock);
	e->name = newev(name, strlen(name)+1);
	qunlock(&evlock);
	if(i > eg->nenv)
		eg->nenv = i;
	qunlock(&eg->ev);
	c->qid = (Qid){i, 0};
.
339,348c
	qlock(&eg->ev);
	e = eg->etab;
	ne = 0;
	for(i = 0; i < eg->nenv; i++, e++)
		if(e->name == 0)
			ne = e;
		else if(strcmp(e->name->val, name) == 0){
			qunlock(&eg->ev);
			error(Einuse);
		}
	if(ne)
		e = ne;
	else if(eg->nenv == conf.npgenv){
		print("out of egroup envs\n");
		qunlock(&eg->ev);
.
337a
	omode = openmode(omode);
.
333a
	Env *e, *ne;
.
332d
323c
	c->mode = mode;
.
305,321c
		qunlock(&eg->ev);
.
297,303c
		if(omode == (OWRITE|OTRUNC) && e->val){
			qlock(&evlock);
			evfree(e->val);
			qunlock(&evlock);
			e->val = 0;
.
290,295c
		qlock(&eg->ev);
		e = &eg->etab[c->qid.path-1];
		if(!e->name){
			qunlock(&eg->ev);
			error(Enonexist);
.
288a
	}else{
.
286,287c
	mode = openmode(omode);
	if(c->qid.path & CHDIR){
		if(omode != OREAD)
.
284a
	Env *e;
	int mode;
.
282,283d
261,270c
	return devwalk(c, name, 0, 0, envgen);
.
259d
245,252d
232c
	qunlock(&eg->ev);
.
226,228c
			devdir(c, (Qid){s+1, (ulong)e->val}, e->name->val, e->val? e->val->len : 0, 0666, dp);
.
222,223c
		e = &eg->etab[s];
		if(!e->name)
.
218c
	qlock(&eg->ev);
.
214a
	Env *e;
.
213d
71,209d
52,63c
	evscratch = ialloc(BY2PG, 0);
.
48a
Envval	*newev(char*, ulong);
Envval	*evalloc(ulong);
void	evfree(Envval*);

.
47c
QLock	evlock;
Envval	evhash[EVHASH];
char	*evscratch;		/* for constructing the contents of a file */
.
39,44c
	Envval	*free[EVFREE+1];
	char	*block;			/* the free page we are allocating from */
	char	*lim;			/* end of block */
.
34,35c
enum{
	MAXENV	= (BY2PG - sizeof(Envval)),
	EVHASH	= 64,
	EVFREE	= 16,
	ALIGN	= 16,
};
.
28,31c
	Envval	*next;		/* for hashing & easy deletion from hash list */
	Envval	*prev;
	ulong	len;		/* length of val that is valid */
	int	ref;
	char	*val;
.
10,25d
## diffname port/devenv.c 1991/1022
## diff -e /n/bootesdump/1991/1018/sys/src/9/port/devenv.c /n/bootesdump/1991/1022/sys/src/9/port/devenv.c
400a
}

void
envdump(void)
{
	Envval *ev;
	int i, j;

	qlock(&evlock);
	print("pages allocated: %d\n", envalloc.npage);
	print("bytes left in page: %d\n", envalloc.lim - envalloc.block);
	for(i = 0; i < EVFREE + 1; i++){
		j = 0;
		if(i == EVFREE)
			print("big blocks:\n");
		else
			print("%d byte blocks:\n", (i + 1) * ALIGN);
		for(ev = envalloc.free[i]; ev; ev = ev->next){
			if(j++ == 1000){
				print("circular\n");
				break;
			}
			if(j < 10)
				print("\tenv %d %lux n%lux p%lux r%d\n",
					ev->len, ev, ev->next, ev->prev, ev->ref);
		}
	}
	for(i = 0; i < EVHASH; i++){
		j = 0;
		for(ev = evhash[i].next; ev; ev = ev->next){
			if(j++ == 1000){
				print("hash bucket %d circular\n", i);
				break;
			}
		}
	}
	qunlock(&evlock);
.
371c
	
.
368a
		envalloc.npage++;
.
30a
	int	npage;			/* total pages gotten from newpage() */
.
## diffname port/devenv.c 1991/1024
## diff -e /n/bootesdump/1991/1022/sys/src/9/port/devenv.c /n/bootesdump/1991/1024/sys/src/9/port/devenv.c
401a
	ev->prev = 0;
.
393a
	else
		panic("evfree");
.
## diffname port/devenv.c 1991/1030
## diff -e /n/bootesdump/1991/1024/sys/src/9/port/devenv.c /n/bootesdump/1991/1030/sys/src/9/port/devenv.c
435a
			uchar *t, *s;
			int h, n;

			s = (uchar*)ev->val;
			n = ev->len;
			h = 0;
			for(t = s; t - s < n; t++)
				h = (h << 1) ^ *t;
			h &= EVHASH - 1;
			if(h != i)
				print("hash conflict: %d %d\n", i, h);
.
## diffname port/devenv.c 1991/1102
## diff -e /n/bootesdump/1991/1030/sys/src/9/port/devenv.c /n/bootesdump/1991/1102/sys/src/9/port/devenv.c
469a

void
ksetterm(char *f)
{
	char buf[2*NAMELEN];

	sprint(buf, f, conffile);
	ksetenv("terminal", buf);
}
.
## diffname port/devenv.c 1991/1105
## diff -e /n/bootesdump/1991/1102/sys/src/9/port/devenv.c /n/bootesdump/1991/1105/sys/src/9/port/devenv.c
160a
		print("out of egroup envs\n");
.
159d
## diffname port/devenv.c 1991/1108
## diff -e /n/bootesdump/1991/1105/sys/src/9/port/devenv.c /n/bootesdump/1991/1108/sys/src/9/port/devenv.c
408,455d
## diffname port/devenv.c 1991/1109
## diff -e /n/bootesdump/1991/1108/sys/src/9/port/devenv.c /n/bootesdump/1991/1109/sys/src/9/port/devenv.c
69c
			devdir(c, (Qid){s+1, (ulong)e->val}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp);
.
## diffname port/devenv.c 1991/1115
## diff -e /n/bootesdump/1991/1109/sys/src/9/port/devenv.c /n/bootesdump/1991/1115/sys/src/9/port/devenv.c
204a
	USED(c);
.
198a
	USED(c, db);
.
## diffname port/devenv.c 1991/1121
## diff -e /n/bootesdump/1991/1115/sys/src/9/port/devenv.c /n/bootesdump/1991/1121/sys/src/9/port/devenv.c
341,342c
	size = (n + ALIGN - 1) & ~(ALIGN - 1);
	n = (size - 1) / ALIGN;
.
271c
	olen = (offset + n + ALIGN - 1) & ~(ALIGN - 1);
	if(olen > MAXENV)
.
## diffname port/devenv.c 1992/0111
## diff -e /n/bootesdump/1991/1121/sys/src/9/port/devenv.c /n/bootesdump/1992/0111/sys/src/9/port/devenv.c
6c
#include	"../port/error.h"
.
## diffname port/devenv.c 1992/0321
## diff -e /n/bootesdump/1992/0111/sys/src/9/port/devenv.c /n/bootesdump/1992/0321/sys/src/9/port/devenv.c
2c
#include	"../port/lib.h"
.
## diffname port/devenv.c 1992/0331
## diff -e /n/bootesdump/1992/0321/sys/src/9/port/devenv.c /n/bootesdump/1992/0331/sys/src/9/port/devenv.c
69c
			devdir(c, (Qid){s+1, (ulong)e->name}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp);
.
## diffname port/devenv.c 1992/0622
## diff -e /n/bootesdump/1992/0331/sys/src/9/port/devenv.c /n/bootesdump/1992/0622/sys/src/9/port/devenv.c
45c
	evscratch = xalloc(BY2PG);
.
## diffname port/devenv.c 1992/0623
## diff -e /n/bootesdump/1992/0622/sys/src/9/port/devenv.c /n/bootesdump/1992/0623/sys/src/9/port/devenv.c
353,408c
	memmove(e->value+offset, a, n);
	qunlock(eg);
	return n;
.
303,351c
	if(vend > e->len) {
		s = smalloc(offset+n);
		memmove(s, e->value, e->len);
		if(e->value)
			free(e->value);
		e->value = s;
		e->len = vend;
.
281,301d
275,278c
	qlock(eg);
	for(e = eg->entries; e; e = e->link)
		if(e->path == c->qid.path)
			break;

	if(e == 0) {
		qunlock(eg);
.
273a

.
271,272c

	vend = offset+n;
	if(vend > Maxenvsize)
.
265,267c
	Evalue *e;
.
263a
	char *s;
	int vend;
.
256,257c
		memmove(a, e->value+offset, n);
	qunlock(eg);
.
249,252c

	if(offset + n > e->len)
		n = e->len - offset;
.
243,246c
	qlock(eg);
	for(e = eg->entries; e; e = e->link)
		if(e->path == c->qid.path)
			break;

	if(e == 0) {
		qunlock(eg);
.
241a

.
236,238c
	Evalue *e;
.
209,231d
192,193c

	*l = e->link;
	qunlock(eg);
	free(e->name);
	if(e->value)
		free(e->value);
	free(e);
.
186,189c
	qlock(eg);

	l = &eg->entries;
	for(e = *l; e; e = e->link) {
		if(e->path == c->qid.path)
			break;
		l = &e->link;
	}

	if(e == 0) {
		qunlock(eg);
.
184a

.
181c
	Evalue *e, **l;
.
163,171c

	for(e = eg->entries; e; e = e->link)
		if(strcmp(e->name, name) == 0)
			error(Einuse);

	e = smalloc(sizeof(Evalue));
	e->name = smalloc(strlen(name)+1);
	strcpy(e->name, name);

	e->path = ++eg->path;
	e->link = eg->entries;
	eg->entries = e;
	c->qid = (Qid){e->path, 0};
	
	qunlock(eg);
	poperror();

.
146,161c

	qlock(eg);
	if(waserror()) {
		qunlock(eg);
		nexterror();
.
143a

.
139,140c
	Evalue *e;
.
129c
	c->mode = openmode(omode);
.
127c
		qunlock(eg);
.
121,125c
		if(omode == (OWRITE|OTRUNC) && e->value) {
			free(e->value);
			e->value = 0;
			e->len = 0;
.
113,118c
	}
	else {
		qlock(eg);
		for(e = eg->entries; e; e = e->link)
			if(e->path == c->qid.path)
				break;

		if(e == 0) {
			qunlock(eg);
.
106,109c
	Evalue *e;
	
	eg = u->p->egrp;
.
73,74c

	devdir(c, (Qid){e->path, 0}, e->name, e->len, eve, 0666, dp);
	qunlock(eg);
	return 1;
.
61,71c
	qlock(eg);

	for(e = eg->entries; e && s; e = e->link)
		s--;

	if(e == 0) {
		qunlock(eg);
		return -1;
.
57,58c
	Evalue *e;
.
45d
19,41d
12,16c
	Maxenvsize = 16300,
.
10c
enum
.
## diffname port/devenv.c 1992/0625
## diff -e /n/bootesdump/1992/0623/sys/src/9/port/devenv.c /n/bootesdump/1992/0625/sys/src/9/port/devenv.c
256a
}

void
envcpy(Egrp *to, Egrp *from)
{
	Evalue **l, *ne, *e;

	l = &to->entries;
	qlock(from);
	for(e = from->entries; e; e = e->link) {
		ne = smalloc(sizeof(Evalue));
		ne->name = smalloc(strlen(e->name)+1);
		strcpy(ne->name, e->name);
		if(e->value) {
			ne->value = smalloc(e->len);
			memmove(ne->value, e->value, e->len);
			ne->len = e->len;
		}
		ne->path = ++to->path;
		*l = ne;
		l = &ne->link;
	}
	qunlock(from);
}

void
closeegrp(Egrp *eg)
{
	Evalue *e, *next;

	if(decref(eg) == 0) {
		for(e = eg->entries; e; e = next) {
			next = e->link;
			free(e->name);
			if(e->value)
				free(e->value);
			free(e);
		}
		free(eg);
	}
.
79c
	if(c->qid.path & CHDIR) {
.
## diffname port/devenv.c 1992/0711
## diff -e /n/bootesdump/1992/0625/sys/src/9/port/devenv.c /n/bootesdump/1992/0711/sys/src/9/port/devenv.c
111a
	USED(perm);
.
30a
	USED(tab);
	USED(ntab);

.
## diffname port/devenv.c 1992/1107
## diff -e /n/bootesdump/1992/0711/sys/src/9/port/devenv.c /n/bootesdump/1992/1107/sys/src/9/port/devenv.c
270a
if(e->name == 0) panic("e->name == 0");
for(p = e->name; *p; p++) if(p - e->name >= NAMELEN) panic("e->name %.*s", NAMELEN, e->name);
.
266a
	char *p;
.
## diffname port/devenv.c 1993/0123
## diff -e /n/bootesdump/1992/1107/sys/src/9/port/devenv.c /n/bootesdump/1993/0123/sys/src/9/port/devenv.c
272,273d
267d
## diffname port/devenv.c 1993/0501
## diff -e /n/bootesdump/1993/0123/sys/src/9/port/devenv.c /n/fornaxdump/1993/0501/sys/src/brazil/port/devenv.c
316,324d
239c
	eg = up->egrp;
.
203c
	eg = up->egrp;
.
158c
	eg = up->egrp;
.
120c
	eg = up->egrp;
.
81c
	eg = up->egrp;
.
65d
34c
	eg = up->egrp;
.
## diffname port/devenv.c 1995/0108
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/devenv.c /n/fornaxdump/1995/0108/sys/src/brazil/port/devenv.c
259a
}

long
envbwrite(Chan *c, Block *bp, ulong offset)
{
	return devbwrite(c, bp, offset);
.
222a
Block*
envbread(Chan *c, long n, ulong offset)
{
	return devbread(c, n, offset);
}

.
## diffname port/devenv.c 1995/0726
## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/port/devenv.c /n/fornaxdump/1995/0726/sys/src/brazil/port/devenv.c
114d
109c
envcreate(Chan *c, char *name, int omode, ulong)
.
## diffname port/devenv.c 1995/0804
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/port/devenv.c /n/fornaxdump/1995/0804/sys/src/brazil/port/devenv.c
189d
187c
envclose(Chan*)
.
182d
180c
envwstat(Chan*, char*)
.
31,33d
26c
envgen(Chan *c, Dirtab*, int, int s, Dir *dp)
.
## diffname port/devenv.c 1996/0223
## diff -e /n/fornaxdump/1995/0804/sys/src/brazil/port/devenv.c /n/fornaxdump/1996/0223/sys/src/brazil/port/devenv.c
8d
## diffname port/devenv.c 1997/0327
## diff -e /n/fornaxdump/1996/0223/sys/src/brazil/port/devenv.c /n/emeliedump/1997/0327/sys/src/brazil/port/devenv.c
318,319c
	devtab[c->type]->write(c, eval, strlen(eval), 0);
	cclose(c);
.
261,265c
Dev envdevtab = {
	devreset,
	devinit,
	envattach,
	devclone,
	envwalk,
	envstat,
	envopen,
	envcreate,
	envclose,
	envread,
	devbread,
	envwrite,
	devbwrite,
	envremove,
	devwstat,
};
.
216,222c
static long
.
186c
static long
.
175,181c
static void
.
143c
static void
.
104c
static void
.
70c
static Chan*
.
64c
static void
.
52,58c
static int
.
46c
static Chan*
.
14,24c
static int
.
## diffname port/devenv.c 1997/0408
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/port/devenv.c /n/emeliedump/1997/0408/sys/src/brazil/port/devenv.c
233a
	'e',
	"env",

.
## diffname port/devenv.c 1998/0319
## diff -e /n/emeliedump/1997/0408/sys/src/brazil/port/devenv.c /n/emeliedump/1998/0319/sys/src/brazil/port/devenv.c
200a
	ulong offset = off;
.
195c
envwrite(Chan *c, void *a, long n, vlong off)
.
168a
	ulong offset = off;
.
165c
envread(Chan *c, void *a, long n, vlong off)
.
## diffname port/devenv.c 1998/0512
## diff -e /n/emeliedump/1998/0319/sys/src/brazil/port/devenv.c /n/emeliedump/1998/0512/sys/src/brazil/port/devenv.c
118c

.
59c

.
## diffname port/devenv.c 1999/0122
## diff -e /n/emeliedump/1998/0512/sys/src/brazil/port/devenv.c /n/emeliedump/1999/0122/sys/src/brazil/port/devenv.c
272c
		ne->qid.path = ++to->path;
.
230a
	e->qid.vers++;
	eg->vers++;
.
213,216c
	e = envlookup(eg, nil, c->qid.path);
.
176,179c
	e = envlookup(eg, nil, c->qid.path);
.
161a
	/*
	 * close can't fail, so errors from remove will be ignored anyway.
	 * since permissions aren't checked,
	 * envremove can't not remove it if its there.
	 */
	if(c->flag & CRCLOSE)
		envremove(c);
.
160c
envclose(Chan *c)
.
151a
	eg->vers++;
.
141c
		if(e->qid.path == c->qid.path)
.
138d
117c
	c->qid = e->qid;
.
114c
	e->qid.path = ++eg->path;
	e->qid.vers = 0;
	eg->vers++;
.
106,108c
	if(envlookup(eg, name, -1))
		error(Eexist);
.
75c
		if((omode & OTRUNC) && e->value) {
			e->qid.vers++;
.
67,70c
		e = envlookup(eg, nil, c->qid.path);
.
50a
	if(c->qid.path & CHDIR)
		c->qid.vers = up->egrp->vers;
.
35a
static Evalue*
envlookup(Egrp *eg, char *name, ulong qidpath)
{
	Evalue *e;
	for(e = eg->entries; e; e = e->link)
		if(e->qid.path == qidpath || (name && strcmp(e->name, name) == 0))
			return e;
	return nil;
}

.
31c
	devdir(c, e->qid, e->name, e->len, eve, 0666, dp);
.
## diffname port/devenv.c 1999/1230
## diff -e /n/emeliedump/1999/0122/sys/src/brazil/port/devenv.c /n/emeliedump/1999/1230/sys/src/9/port/devenv.c
19a
	if(s == DEVDOTDOT){
		devdir(c, c->qid, "#e", 0, eve, 0775, dp);
		return 1;
	}

.
## diffname port/devenv.c 2000/0121
## diff -e /n/emeliedump/1999/1230/sys/src/9/port/devenv.c /n/emeliedump/2000/0121/sys/src/9/port/devenv.c
243a
		}
.
241,242c
		if(e->value){
			memmove(s, e->value, e->len);
.
## diffname port/devenv.c 2001/0510
## diff -e /n/emeliedump/2000/0121/sys/src/9/port/devenv.c /n/emeliedump/2001/0510/sys/src/9/port/devenv.c
60c
	Evalue *e;
	Egrp *eg;
	int rv;

	if(c->qid.path == CHDIR && name[0] != '.'){
		rv = 0;
		eg = up->egrp;
		qlock(eg);
		for(e = eg->entries; e; e = e->link)
			if(strcmp(e->name, name) == 0){
				rv = 1;
				c->qid = e->qid;
			}
		qunlock(eg);
		return rv;
	} else
		return devwalk(c, name, 0, 0, envgen);
.
## diffname port/devenv.c 2001/0527
## diff -e /n/emeliedump/2001/0510/sys/src/9/port/devenv.c /n/emeliedump/2001/0527/sys/src/9/port/devenv.c
339c
	char buf[2*KNAMELEN];
.
278d
210c
	if(c->qid.type & QTDIR)
.
165c
	if(c->qid.type & QTDIR)
.
125c
	if(c->qid.type != QTDIR)
.
94c
	if(c->qid.type & QTDIR) {
.
84c
	return devstat(c, db, n, 0, 0, envgen);
.
82c
	if(c->qid.type & QTDIR)
.
79,80c
static int
envstat(Chan *c, uchar *db, int n)
.
60,76c
	return devwalk(c, nc, name, nname, 0, 0, envgen);
.
57,58c
static Walkqid*
envwalk(Chan *c, Chan *nc, char **name, int nname)
.
36c
	/* make sure name string continues to exist after we release lock */
	kstrcpy(up->genbuf, e->name, sizeof up->genbuf);
	devdir(c, e->qid, up->genbuf, e->len, eve, 0666, dp);
.
21c
		devdir(c, c->qid, "#e", 0, eve, DMDIR|0775, dp);
.
15c
envgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
.
## diffname port/devenv.c 2001/1204
## diff -e /n/emeliedump/2001/0527/sys/src/9/port/devenv.c /n/emeliedump/2001/1204/sys/src/9/port/devenv.c
181c
	 * cclose can't fail, so errors from remove will be ignored.
.
## diffname port/devenv.c 2002/0109
## diff -e /n/emeliedump/2001/1204/sys/src/9/port/devenv.c /n/emeliedump/2002/0109/sys/src/9/port/devenv.c
329a
}

/*
 * 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;
	Evalue *e;
	char *p, *q;
	int n;

	qlock(eg);
	if(waserror()) {
		qunlock(eg);
		nexterror();
	}
	
	/* determine size */
	n = 0;
	for(e=eg->entries; e; e=e->link)
		n += strlen(e->name) + e->len + 2;
	p = malloc(n + 1);
	if(p == nil)
		error(Enomem);
	q = p;
	for(e=eg->entries; e; e=e->link) {
		strcpy(q, e->name);
		q += strlen(q) + 1;
		memmove(q, e->value, e->len);
		q[e->len] = 0;
		/* move up to the first null */
		q += strlen(q) + 1;
	}
	*q = 0;
	
	poperror();
	qunlock(eg);
	return p;
.
325,326c
	
	snprint(buf, sizeof(buf), "#e%s/%s", conf?"c":"", ename);
.
321c
ksetenv(char *ename, char *eval, int conf)
.
316a
static Egrp*
envgrp(Chan *c)
{
	if(c->aux == nil)
		return up->egrp;
	return c->aux;
}

static int
envwriteable(Chan *c)
{
	return iseve() || c->aux == nil;
}

.
262a
	devshutdown,
.
233c
	eg = envgrp(c);
.
199c
	eg = envgrp(c);
.
154c
	eg = envgrp(c);
.
115c
	eg = envgrp(c);
.
84a
		if(omode != OREAD && !envwriteable(c))
			error(Eperm);
.
79c
	eg = envgrp(c);
.
69c
		c->qid.vers = envgrp(c)->vers;
.
56c
	Chan *c;
	Egrp *egrp = nil;

	if(spec && *spec) {
		if(strcmp(spec, "c") == 0)
			egrp = &confegrp;
		if(egrp == nil)
			error(Ebadarg);
	}

	c = devattach('e', spec);
	c->aux = egrp;
	return c;
.
25c
	eg = envgrp(c);
.
13a
static Egrp	*envgrp(Chan *c);
static int	envwriteable(Chan *c);

static Egrp	confegrp;	/* global environment group containing the kernel configuration */

.
8d
## diffname port/devenv.c 2002/0405
## diff -e /n/emeliedump/2002/0109/sys/src/9/port/devenv.c /n/emeliedump/2002/0405/sys/src/9/port/devenv.c
403c
	runlock(eg);
.
380c
		runlock(eg);
.
378c
	rlock(eg);
.
316c
	runlock(from);
.
302c
	rlock(from);
.
271c
	wunlock(eg);
.
255c
		wunlock(eg);
.
252c
	wlock(eg);
.
231c
	runlock(eg);
.
221c
		rlock(eg);
.
218c
	rlock(eg);
.
188c
	wunlock(eg);
.
182c
		wunlock(eg);
.
173c
	wlock(eg);
.
155c
	wunlock(eg);
.
137c
		wunlock(eg);
.
135c
	wlock(eg);
.
115c
		runlock(eg);
.
106c
			runlock(eg);
.
103c
		rlock(eg);
.
43c
	runlock(eg);
.
36c
		runlock(eg);
.
30,31c
	rlock(eg);
.
## diffname port/devenv.c 2002/0407
## diff -e /n/emeliedump/2002/0405/sys/src/9/port/devenv.c /n/emeliedump/2002/0407/sys/src/9/port/devenv.c
114c
		if(trunc)
			wunlock(eg);
		else
			runlock(eg);
.
108c
		if(trunc && e->value) {
.
105c
			if(trunc)
				wunlock(eg);
			else
				runlock(eg);
.
102c
		if(trunc)
			wlock(eg);
		else
			rlock(eg);
.
99a
		trunc = omode & OTRUNC;
.
92a
	int trunc;
.
## diffname port/devenv.c 2002/0409
## diff -e /n/emeliedump/2002/0407/sys/src/9/port/devenv.c /n/emeliedump/2002/0409/sys/src/9/port/devenv.c
235c
	if(offset > e->len)	/* protects against overflow converting vlong to ulong */
		n = 0;
	else if(offset + n > e->len)
.
## diffname port/devenv.c 2002/0426
## diff -e /n/emeliedump/2002/0409/sys/src/9/port/devenv.c /n/emeliedump/2002/0426/sys/src/9/port/devenv.c
231c
		runlock(eg);
.
## diffname port/devenv.c 2003/0325
## diff -e /n/emeliedump/2002/0426/sys/src/9/port/devenv.c /n/emeliedump/2003/0325/sys/src/9/port/devenv.c
404c
	for(i=0; i<eg->nent; i++){
		e = eg->ent[i];
.
399a
	}
.
398c
	for(i=0; i<eg->nent; i++){
		e = eg->ent[i];
.
388c
	int i, n;
.
343a
		free(eg->ent);
.
336,338c
	if(decref(eg) == 0){
		for(i=0; i<eg->nent; i++){
			e = eg->ent[i];
.
334c
	int i;
	Evalue *e;
.
327a
	to->nent = from->nent;
.
325,326c
		to->ent[i] = ne;
.
319c
		if(e->value){
.
315c
	to->ment = (from->nent+31)&~31;
	to->ent = smalloc(to->ment*sizeof(to->ent[0]));
	for(i=0; i<from->nent; i++){
		e = from->ent[i];
.
313d
311c
	int i;
	Evalue *ne, *e;
.
198a
	if(e == 0)
		error(Enonexist);
.
190,197d
188c
		}
.
184,186c
	e = 0;
	for(i=0; i<eg->nent; i++){
		if(eg->ent[i]->qid.path == c->qid.path){
			e = eg->ent[i];
			eg->nent--;
			eg->ent[i] = eg->ent[eg->nent];
			eg->vers++;
.
177c
	Evalue *e;
.
175a
	int i;
.
161,162c
	eg->ent[eg->nent++] = e;
.
157a
	if(eg->nent == eg->ment){
		eg->ment += 32;
		ent = smalloc(sizeof(eg->ent[0])*eg->ment);
		if(eg->nent)
			memmove(ent, eg->ent, sizeof(eg->ent[0])*eg->nent);
		free(eg->ent);
		eg->ent = ent;
	}
.
137a
	Evalue **ent;
.
46,55d
31,32c
	e = 0;
	if(name)
		e = envlookup(eg, name, -1);
	else if(s < eg->nent)
		e = eg->ent[s];
.
19c
envgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
.
17a
static Evalue*
envlookup(Egrp *eg, char *name, ulong qidpath)
{
	Evalue *e;
	int i;

	for(i=0; i<eg->nent; i++){
		e = eg->ent[i];
		if(e->qid.path == qidpath || (name && e->name[0]==name[0] && strcmp(e->name, name) == 0))
			return e;
	}
	return nil;
}

.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].