plan 9 kernel history: overview | file list | diff list

1991/1022/port/devenv.c (diff list | history)

1990/0227/sys/src/9/port/devenv.c:299,3041990/03042/sys/src/9/port/devenv.c:299,305 (short | long)
1990/0227    
		if(waserror()){ 
			unlock(e); 
			unlock(&envalloc); 
1990/03042    
			unlock(pg); 
1990/0227    
			nexterror(); 
		} 
		if(e->pgref == 0) 
1990/03042/sys/src/9/port/devenv.c:143,1491990/0802/sys/src/9/port/devenv.c:143,149 (short | long)
1990/0227    
				goto Free; 
			} 
			if(p2+p2->n > envalloc.end) 
				panic("compactpte copying too much"); 
1990/0802    
				panic("compactenv copying too much"); 
1990/0227    
			memcpy(p1, p2, p2->n*sizeof(Envval)); 
			p2e->val = p1; 
			if(p2e != e) 
1990/0802/sys/src/9/port/devenv.c:155,1611990/11211/sys/src/9/port/devenv.c:155,161 (short | long)
1990/0227    
	envalloc.vfree = p1; 
	if(envalloc.end-envalloc.vfree < n){ 
		print("env compact failed\n"); 
		error(0, Enoenv); 
1990/11211    
		error(Enoenv); 
1990/0227    
	} 
} 
 
1990/0802/sys/src/9/port/devenv.c:173,1791990/11211/sys/src/9/port/devenv.c:173,179
1990/0227    
	ne = envalloc.efree; 
	if(!ne){ 
		print("out of envs\n"); 
		error(0, Enoenv); 
1990/11211    
		error(Enoenv); 
1990/0227    
	} 
	envalloc.efree = ne->next; 
	lock(ne); 
1990/0802/sys/src/9/port/devenv.c:224,2301990/11211/sys/src/9/port/devenv.c:224,230
1990/0227    
			ans = 0; 
		else{ 
			lock(e); 
			devdir(c, s+1, e->name, e->val? e->val->len : 0, 0666, dp); 
1990/11211    
			devdir(c, (Qid){s+1,0}, e->name, e->val? e->val->len : 0, 0666, dp); 
1990/0227    
			unlock(e); 
			ans = 1; 
		} 
1990/0802/sys/src/9/port/devenv.c:244,2531990/11211/sys/src/9/port/devenv.c:244,253
1990/0227    
{ 
	Pgrp *pg; 
 
	if(!(c->qid&CHDIR)){ 
1990/11211    
	if(!(c->qid.path&CHDIR)){ 
1990/0227    
		pg = u->p->pgrp; 
		lock(pg); 
		pg->etab[c->qid-1].chref++; 
1990/11211    
		pg->etab[c->qid.path-1].chref++; 
1990/0227    
		unlock(pg); 
	} 
	return devclone(c, nc); 
1990/0802/sys/src/9/port/devenv.c:259,2681990/11211/sys/src/9/port/devenv.c:259,268
1990/0227    
	Pgrp *pg; 
 
	if(devwalk(c, name, 0, 0, envgen)){ 
		if(!(c->qid&CHDIR)){ 
1990/11211    
		if(!(c->qid.path&CHDIR)){ 
1990/0227    
			pg = u->p->pgrp; 
			lock(pg); 
			pg->etab[c->qid-1].chref++; 
1990/11211    
			pg->etab[c->qid.path-1].chref++; 
1990/0227    
			unlock(pg); 
			return 1; 
		} 
1990/0802/sys/src/9/port/devenv.c:284,2981990/11211/sys/src/9/port/devenv.c:284,298
1990/0227    
	Pgrp *pg; 
 
	if(omode & (OWRITE|OTRUNC)){ 
		if(c->qid & CHDIR) 
			error(0, Eperm); 
1990/11211    
		if(c->qid.path & CHDIR) 
			error(Eperm); 
1990/0227    
		pg = u->p->pgrp; 
		lock(pg); 
		ep = &pg->etab[c->qid-1]; 
1990/11211    
		ep = &pg->etab[c->qid.path-1]; 
1990/0227    
		e = ep->env; 
		if(!e){ 
			unlock(pg); 
			error(0, Egreg); 
1990/11211    
			error(Egreg); 
1990/0227    
		} 
		lock(&envalloc); 
		lock(e); 
1990/0802/sys/src/9/port/devenv.c:333,3401990/11211/sys/src/9/port/devenv.c:333,340
1990/0227    
	Pgrp *pg; 
	int i; 
 
	if(c->qid != CHDIR) 
		error(0, Eperm); 
1990/11211    
	if(c->qid.path != CHDIR) 
		error(Eperm); 
1990/0227    
	pg = u->p->pgrp; 
	lock(pg); 
	lock(&envalloc); 
1990/0802/sys/src/9/port/devenv.c:346,3521990/11211/sys/src/9/port/devenv.c:346,352
1990/0227    
	e = envalloc.efree; 
	if(e == 0){ 
		print("out of envs\n"); 
		error(0,Enoenv); 
1990/11211    
		error(Enoenv); 
1990/0227    
	} 
	envalloc.efree = e->next; 
	e->next = 0; 
1990/0802/sys/src/9/port/devenv.c:358,3681990/11211/sys/src/9/port/devenv.c:358,368
1990/0227    
				break; 
		if(i == pg->nenv){ 
			print("out of pgroup envs\n"); 
			error(0, Enoenv); 
1990/11211    
			error(Enoenv); 
1990/0227    
		} 
	}else 
		i = pg->nenv++; 
	c->qid = i+1; 
1990/11211    
	c->qid.path = i+1; 
1990/0227    
	pg->etab[i].env = e; 
	pg->etab[i].chref = 1; 
	unlock(&envalloc); 
1990/0802/sys/src/9/port/devenv.c:380,3941990/11211/sys/src/9/port/devenv.c:380,394
1990/0227    
	Envp *ep; 
	Pgrp *pg; 
 
	if(c->qid & CHDIR) 
		error(0, Eperm); 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eperm); 
1990/0227    
	pg = u->p->pgrp; 
	lock(pg); 
	ep = &pg->etab[c->qid-1]; 
1990/11211    
	ep = &pg->etab[c->qid.path-1]; 
1990/0227    
	e = ep->env; 
	if(!e){ 
		unlock(pg); 
		error(0, Enonexist); 
1990/11211    
		error(Enonexist); 
1990/0227    
	} 
	ep->env = 0; 
	ep->chref--; 
1990/0802/sys/src/9/port/devenv.c:401,4071990/11211/sys/src/9/port/devenv.c:401,407
1990/0227    
{	int dumpenv(void); 
	dumpenv();  /*DEBUG*/ 
	print("envwstat\n"); 
	error(0, Egreg); 
1990/11211    
	error(Egreg); 
1990/0227    
} 
 
void 
1990/0802/sys/src/9/port/devenv.c:409,4191990/11211/sys/src/9/port/devenv.c:409,419
1990/0227    
{ 
	Pgrp *pg; 
 
	if(c->qid & CHDIR) 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return; 
	pg = u->p->pgrp; 
	lock(pg); 
	pg->etab[c->qid-1].chref--; 
1990/11211    
	pg->etab[c->qid.path-1].chref--; 
1990/0227    
	unlock(pg); 
} 
 
1990/0802/sys/src/9/port/devenv.c:444,4571990/11211/sys/src/9/port/devenv.c:444,457
1990/0227    
	Pgrp *pg; 
	char *a = va; 
 
	if(c->qid & CHDIR) 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return devdirread(c, a, n, 0, 0, envgen); 
	pg = u->p->pgrp; 
	lock(pg); 
	e = pg->etab[c->qid-1].env; 
1990/11211    
	e = pg->etab[c->qid.path-1].env; 
1990/0227    
	if(!e){ 
		unlock(pg); 
		error(0, Eio); 
1990/11211    
		error(Eio); 
1990/0227    
	} 
	lock(e); 
	ev = e->val; 
1990/0802/sys/src/9/port/devenv.c:481,4901990/11211/sys/src/9/port/devenv.c:481,490
1990/0227    
		return 0; 
	pg = u->p->pgrp; 
	lock(pg); 
	e = pg->etab[c->qid-1].env; /* caller checks for CHDIR */ 
1990/11211    
	e = pg->etab[c->qid.path-1].env; /* caller checks for CHDIR */ 
1990/0227    
	if(!e){ 
		unlock(pg); 
		error(0, Eio); 
1990/11211    
		error(Eio); 
1990/0227    
	} 
	lock(&envalloc); 
	lock(e); 
1990/0802/sys/src/9/port/devenv.c:500,5061990/11211/sys/src/9/port/devenv.c:500,506
1990/0227    
	ev = e->val; 
	vn = ev? ev->len : 0; 
	if(c->offset > vn) 
		error(0, Egreg); /* perhaps should zero fill */ 
1990/11211    
		error(Egreg); /* perhaps should zero fill */ 
1990/0227    
	memcpy(ev->dat+c->offset, a, n); 
	e->val->len = c->offset+n; 
	poperror(); 
1990/0802/sys/src/9/port/devenv.c:543,5581990/11211/sys/src/9/port/devenv.c:543,545
1990/0227    
			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); 
} 
                 
1990/11211/sys/src/9/port/devenv.c:90,961991/0318/sys/src/9/port/devenv.c:90,96 (short | long)
1990/0227    
				compactenv(e, n); 
				p = envalloc.vfree; 
				envalloc.vfree += n; 
				memcpy(p, e->val, e->val->n*sizeof(Envval)); 
1991/0318    
				memmove(p, e->val, e->val->n*sizeof(Envval)); 
1990/0227    
				p->e = e; 
				e->val->e = 0; 
				e->val = p; 
1990/11211/sys/src/9/port/devenv.c:144,1501991/0318/sys/src/9/port/devenv.c:144,150
1990/0227    
			} 
			if(p2+p2->n > envalloc.end) 
1990/0802    
				panic("compactenv copying too much"); 
1990/0227    
			memcpy(p1, p2, p2->n*sizeof(Envval)); 
1991/0318    
			memmove(p1, p2, p2->n*sizeof(Envval)); 
1990/0227    
			p2e->val = p1; 
			if(p2e != e) 
				unlock(p2e); 
1990/11211/sys/src/9/port/devenv.c:200,2061991/0318/sys/src/9/port/devenv.c:200,206
1990/0227    
		} 
		if((char*)(ne->val+ne->val->n) < ne->val->dat+n) 
			panic("copyenv corrupt"); 
		memcpy(ne->val->dat, e->val->dat, n); 
1991/0318    
		memmove(ne->val->dat, e->val->dat, n); 
1990/0227    
		ne->val->len = n; 
	} 
	poperror(); 
1990/11211/sys/src/9/port/devenv.c:461,4671991/0318/sys/src/9/port/devenv.c:461,467
1990/0227    
	if(n <= 0) 
		n = 0; 
	else 
		memcpy(a, ev->dat+c->offset, n); 
1991/0318    
		memmove(a, ev->dat+c->offset, n); 
1990/0227    
	unlock(e); 
	unlock(pg); 
	return n; 
1990/11211/sys/src/9/port/devenv.c:501,5071991/0318/sys/src/9/port/devenv.c:501,507
1990/0227    
	vn = ev? ev->len : 0; 
	if(c->offset > vn) 
1990/11211    
		error(Egreg); /* perhaps should zero fill */ 
1990/0227    
	memcpy(ev->dat+c->offset, a, n); 
1991/0318    
	memmove(ev->dat+c->offset, a, n); 
1990/0227    
	e->val->len = c->offset+n; 
	poperror(); 
	unlock(e); 
1991/0318/sys/src/9/port/devenv.c:435,4411991/0411/sys/src/9/port/devenv.c:435,441 (short | long)
1990/0227    
} 
 
long 
envread(Chan *c, void *va, long n) 
1991/0411    
envread(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
	Env *e; 
	Envval *ev; 
1991/0318/sys/src/9/port/devenv.c:456,4671991/0411/sys/src/9/port/devenv.c:456,467
1990/0227    
	lock(e); 
	ev = e->val; 
	vn = ev? e->val->len : 0; 
	if(c->offset+n > vn) 
		n = vn - c->offset; 
1991/0411    
	if(offset+n > vn) 
		n = vn - offset; 
1990/0227    
	if(n <= 0) 
		n = 0; 
	else 
1991/0318    
		memmove(a, ev->dat+c->offset, n); 
1991/0411    
		memmove(a, ev->dat+offset, n); 
1990/0227    
	unlock(e); 
	unlock(pg); 
	return n; 
1991/0318/sys/src/9/port/devenv.c:468,4741991/0411/sys/src/9/port/devenv.c:468,474
1990/0227    
} 
 
long 
envwrite(Chan *c, void *va, long n) 
1991/0411    
envwrite(Chan *c, void *va, long n, ulong offset) 
1990/0227    
{ 
	Env *e; 
	char *p; 
1991/0318/sys/src/9/port/devenv.c:496,5081991/0411/sys/src/9/port/devenv.c:496,508
1990/0227    
	} 
	if(e->pgref>1) 
		panic("envwrite to non-duped env"); 
	growenval(e, c->offset+n); 
1991/0411    
	growenval(e, offset+n); 
1990/0227    
	ev = e->val; 
	vn = ev? ev->len : 0; 
	if(c->offset > vn) 
1991/0411    
	if(offset > vn) 
1990/11211    
		error(Egreg); /* perhaps should zero fill */ 
1991/0318    
	memmove(ev->dat+c->offset, a, n); 
1990/0227    
	e->val->len = c->offset+n; 
1991/0411    
	memmove(ev->dat+offset, a, n); 
	e->val->len = offset+n; 
1990/0227    
	poperror(); 
	unlock(e); 
	unlock(&envalloc); 
1991/0411/sys/src/9/port/devenv.c:270,2751991/0419/sys/src/9/port/devenv.c:270,281 (short | long)
1990/0227    
	return 0; 
} 
 
1991/0419    
Chan* 
envclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
} 
 
1990/0227    
void 
envstat(Chan *c, char *db) 
{ 
1991/0419/sys/src/9/port/devenv.c:270,2811991/0427/sys/src/9/port/devenv.c:270,275 (short | long)
1990/0227    
	return 0; 
} 
 
1991/0419    
Chan* 
envclwalk(Chan *c, char *name) 
{ 
	return devclwalk(c, name); 
} 
                 
1990/0227    
void 
envstat(Chan *c, char *db) 
{ 
1991/0427/sys/src/9/port/devenv.c:211,2251991/0705/sys/src/9/port/devenv.c:211,225 (short | long)
1990/0227    
envgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) 
{ 
	Env *e; 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
	int ans; 
 
	pg = u->p->pgrp; 
	lock(pg); 
	if(s >= pg->nenv) 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
	if(s >= eg->nenv) 
1990/0227    
		ans = -1; 
	else{ 
		e = pg->etab[s].env; 
1991/0705    
		e = eg->etab[s].env; 
1990/0227    
		if(e == 0) 
			ans = 0; 
		else{ 
1991/0427/sys/src/9/port/devenv.c:229,2351991/0705/sys/src/9/port/devenv.c:229,235
1990/0227    
			ans = 1; 
		} 
	} 
	unlock(pg); 
1991/0705    
	unlock(eg); 
1990/0227    
	return ans; 
} 
 
1991/0427/sys/src/9/port/devenv.c:242,2541991/0705/sys/src/9/port/devenv.c:242,254
1990/0227    
Chan* 
envclone(Chan *c, Chan *nc) 
{ 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
 
1990/11211    
	if(!(c->qid.path&CHDIR)){ 
1990/0227    
		pg = u->p->pgrp; 
		lock(pg); 
1990/11211    
		pg->etab[c->qid.path-1].chref++; 
1990/0227    
		unlock(pg); 
1991/0705    
		eg = u->p->egrp; 
		lock(eg); 
		eg->etab[c->qid.path-1].chref++; 
		unlock(eg); 
1990/0227    
	} 
	return devclone(c, nc); 
} 
1991/0427/sys/src/9/port/devenv.c:256,2691991/0705/sys/src/9/port/devenv.c:256,269
1990/0227    
int 
envwalk(Chan *c, char *name) 
{ 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
 
	if(devwalk(c, name, 0, 0, envgen)){ 
1990/11211    
		if(!(c->qid.path&CHDIR)){ 
1990/0227    
			pg = u->p->pgrp; 
			lock(pg); 
1990/11211    
			pg->etab[c->qid.path-1].chref++; 
1990/0227    
			unlock(pg); 
1991/0705    
			eg = u->p->egrp; 
			lock(eg); 
			eg->etab[c->qid.path-1].chref++; 
			unlock(eg); 
1990/0227    
			return 1; 
		} 
	} 
1991/0427/sys/src/9/port/devenv.c:281,2971991/0705/sys/src/9/port/devenv.c:281,297
1990/0227    
{ 
	Env *e, *ne; 
	Envp *ep; 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
 
	if(omode & (OWRITE|OTRUNC)){ 
1990/11211    
		if(c->qid.path & CHDIR) 
			error(Eperm); 
1990/0227    
		pg = u->p->pgrp; 
		lock(pg); 
1990/11211    
		ep = &pg->etab[c->qid.path-1]; 
1991/0705    
		eg = u->p->egrp; 
		lock(eg); 
		ep = &eg->etab[c->qid.path-1]; 
1990/0227    
		e = ep->env; 
		if(!e){ 
			unlock(pg); 
1991/0705    
			unlock(eg); 
1990/11211    
			error(Egreg); 
1990/0227    
		} 
		lock(&envalloc); 
1991/0427/sys/src/9/port/devenv.c:299,3051991/0705/sys/src/9/port/devenv.c:299,305
1990/0227    
		if(waserror()){ 
			unlock(e); 
			unlock(&envalloc); 
1990/03042    
			unlock(pg); 
1991/0705    
			unlock(eg); 
1990/0227    
			nexterror(); 
		} 
		if(e->pgref == 0) 
1991/0427/sys/src/9/port/devenv.c:318,3241991/0705/sys/src/9/port/devenv.c:318,324
1990/0227    
		poperror(); 
		unlock(e); 
		unlock(&envalloc); 
		unlock(pg); 
1991/0705    
		unlock(eg); 
1990/0227    
	} 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
1991/0427/sys/src/9/port/devenv.c:330,3461991/0705/sys/src/9/port/devenv.c:330,346
1990/0227    
envcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	Env *e; 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
	int i; 
 
1990/11211    
	if(c->qid.path != CHDIR) 
		error(Eperm); 
1990/0227    
	pg = u->p->pgrp; 
	lock(pg); 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
1990/0227    
	lock(&envalloc); 
	if(waserror()){ 
		unlock(&envalloc); 
		unlock(pg); 
1991/0705    
		unlock(eg); 
1990/0227    
		nexterror(); 
	} 
	e = envalloc.efree; 
1991/0427/sys/src/9/port/devenv.c:352,3721991/0705/sys/src/9/port/devenv.c:352,372
1990/0227    
	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) 
1991/0705    
	if(eg->nenv == conf.npgenv){ 
		for(i = 0; i<eg->nenv; i++) 
			if(eg->etab[i].chref == 0) 
1990/0227    
				break; 
		if(i == pg->nenv){ 
			print("out of pgroup envs\n"); 
1991/0705    
		if(i == eg->nenv){ 
			print("out of egroup envs\n"); 
1990/11211    
			error(Enoenv); 
1990/0227    
		} 
	}else 
		i = pg->nenv++; 
1991/0705    
		i = eg->nenv++; 
1990/11211    
	c->qid.path = i+1; 
1990/0227    
	pg->etab[i].env = e; 
	pg->etab[i].chref = 1; 
1991/0705    
	eg->etab[i].env = e; 
	eg->etab[i].chref = 1; 
1990/0227    
	unlock(&envalloc); 
	unlock(pg); 
1991/0705    
	unlock(eg); 
1990/0227    
	c->offset = 0; 
	c->mode = openmode(omode); 
	poperror(); 
1991/0427/sys/src/9/port/devenv.c:378,3991991/0705/sys/src/9/port/devenv.c:378,399
1990/0227    
{ 
	Env *e; 
	Envp *ep; 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eperm); 
1990/0227    
	pg = u->p->pgrp; 
	lock(pg); 
1990/11211    
	ep = &pg->etab[c->qid.path-1]; 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
	ep = &eg->etab[c->qid.path-1]; 
1990/0227    
	e = ep->env; 
	if(!e){ 
		unlock(pg); 
1991/0705    
		unlock(eg); 
1990/11211    
		error(Enonexist); 
1990/0227    
	} 
	ep->env = 0; 
	ep->chref--; 
	envpgclose(e); 
	unlock(pg); 
1991/0705    
	unlock(eg); 
1990/0227    
} 
 
void 
1991/0427/sys/src/9/port/devenv.c:407,4201991/0705/sys/src/9/port/devenv.c:407,420
1990/0227    
void 
envclose(Chan * c) 
{ 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return; 
	pg = u->p->pgrp; 
	lock(pg); 
1990/11211    
	pg->etab[c->qid.path-1].chref--; 
1990/0227    
	unlock(pg); 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
	eg->etab[c->qid.path-1].chref--; 
	unlock(eg); 
1990/0227    
} 
 
void 
1991/0427/sys/src/9/port/devenv.c:441,4561991/0705/sys/src/9/port/devenv.c:441,456
1990/0227    
	Envval *ev; 
	char *p; 
	long vn; 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
	char *a = va; 
 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return devdirread(c, a, n, 0, 0, envgen); 
	pg = u->p->pgrp; 
	lock(pg); 
1990/11211    
	e = pg->etab[c->qid.path-1].env; 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
	e = eg->etab[c->qid.path-1].env; 
1990/0227    
	if(!e){ 
		unlock(pg); 
1991/0705    
		unlock(eg); 
1990/11211    
		error(Eio); 
1990/0227    
	} 
	lock(e); 
1991/0427/sys/src/9/port/devenv.c:463,4691991/0705/sys/src/9/port/devenv.c:463,469
1990/0227    
	else 
1991/0411    
		memmove(a, ev->dat+offset, n); 
1990/0227    
	unlock(e); 
	unlock(pg); 
1991/0705    
	unlock(eg); 
1990/0227    
	return n; 
} 
 
1991/0427/sys/src/9/port/devenv.c:474,4891991/0705/sys/src/9/port/devenv.c:474,489
1990/0227    
	char *p; 
	Envval *ev; 
	long vn; 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
	char *a = va; 
 
	if(n <= 0) 
		return 0; 
	pg = u->p->pgrp; 
	lock(pg); 
1990/11211    
	e = pg->etab[c->qid.path-1].env; /* caller checks for CHDIR */ 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
	e = eg->etab[c->qid.path-1].env; /* caller checks for CHDIR */ 
1990/0227    
	if(!e){ 
		unlock(pg); 
1991/0705    
		unlock(eg); 
1990/11211    
		error(Eio); 
1990/0227    
	} 
	lock(&envalloc); 
1991/0427/sys/src/9/port/devenv.c:491,4971991/0705/sys/src/9/port/devenv.c:491,497
1990/0227    
	if(waserror()){ 
		unlock(e); 
		unlock(&envalloc); 
		unlock(pg); 
1991/0705    
		unlock(eg); 
1990/0227    
		nexterror(); 
	} 
	if(e->pgref>1) 
1991/0427/sys/src/9/port/devenv.c:506,5121991/0705/sys/src/9/port/devenv.c:506,512
1990/0227    
	poperror(); 
	unlock(e); 
	unlock(&envalloc); 
	unlock(pg); 
1991/0705    
	unlock(eg); 
1990/0227    
	return n; 
} 
 
1991/0427/sys/src/9/port/devenv.c:516,5271991/0705/sys/src/9/port/devenv.c:516,527
1990/0227    
	Env *e; 
	Envp *ep; 
	Envval *ev; 
	Pgrp *pg; 
1991/0705    
	Egrp *eg; 
1990/0227    
	int i; 
	char hold; 
 
	pg = u->p->pgrp; 
	for(ep=pg->etab, i=0; i<pg->nenv; i++, ep++) 
1991/0705    
	eg = u->p->egrp; 
	for(ep=eg->etab, i=0; i<eg->nenv; i++, ep++) 
1990/0227    
		print("P%d(%lux %d)",i, ep->env, ep->chref); 
	for(e=envalloc.earena; e<&envalloc.earena[conf.nenv]; e++) 
		if(e->pgref){ 
1991/0705/sys/src/9/port/devenv.c:543,5451991/0927/sys/src/9/port/devenv.c:543,560 (short | long)
1990/0227    
			i += ev->n*sizeof(Envval); 
	print(" %d free enval chars\n", i+((char *)envalloc.end-(char*)envalloc.vfree)); 
} 
1991/0927    
 
/* 
 *  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); 
} 
1991/0927/sys/src/9/port/devenv.c:7,661991/1018/sys/src/9/port/devenv.c:7,47 (short | long)
1990/0227    
 
#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 */ 
1991/1018    
	Envval	*next;		/* for hashing & easy deletion from hash list */ 
	Envval	*prev; 
	ulong	len;		/* length of val that is valid */ 
	int	ref; 
	char	*val; 
1990/0227    
}; 
 
/* number of contiguous Envvals needed to hold n characters */ 
#define EVNEEDED(n) ((n)<4? 1 : 1+((n)+(sizeof(Envval))-1-4)/(sizeof(Envval))) 
1991/1018    
enum{ 
	MAXENV	= (BY2PG - sizeof(Envval)), 
	EVHASH	= 64, 
	EVFREE	= 16, 
	ALIGN	= 16, 
}; 
1990/0227    
 
struct 
{ 
	Lock; 
	Envval	*arena; 
	Envval	*vfree; 
	Envval	*end; 
	Env	*efree; 
	Env	*earena; 
1991/1018    
	Envval	*free[EVFREE+1]; 
	char	*block;			/* the free page we are allocating from */ 
	char	*lim;			/* end of block */ 
1990/0227    
}envalloc; 
 
void	compactenv(Env *, ulong); 
1991/1018    
QLock	evlock; 
Envval	evhash[EVHASH]; 
char	*evscratch;		/* for constructing the contents of a file */ 
1990/0227    
 
1991/1018    
Envval	*newev(char*, ulong); 
Envval	*evalloc(ulong); 
void	evfree(Envval*); 
 
1990/0227    
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; 
1991/1018    
	evscratch = ialloc(BY2PG, 0); 
1990/0227    
} 
 
void 
1991/0927/sys/src/9/port/devenv.c:68,2351991/1018/sys/src/9/port/devenv.c:49,75
1990/0227    
{ 
} 
 
/* 
 * 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; 
1991/0318    
				memmove(p, e->val, e->val->n*sizeof(Envval)); 
1990/0227    
				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) 
1990/0802    
				panic("compactenv copying too much"); 
1991/0318    
			memmove(p1, p2, p2->n*sizeof(Envval)); 
1990/0227    
			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"); 
1990/11211    
		error(Enoenv); 
1990/0227    
	} 
} 
                 
/* 
 * 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"); 
1990/11211    
		error(Enoenv); 
1990/0227    
	} 
	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"); 
1991/0318    
		memmove(ne->val->dat, e->val->dat, n); 
1990/0227    
		ne->val->len = n; 
	} 
	poperror(); 
	return ne; 
} 
                 
int 
envgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) 
{ 
	Env *e; 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e; 
1990/0227    
	int ans; 
 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
1991/1018    
	qlock(&eg->ev); 
1991/0705    
	if(s >= eg->nenv) 
1990/0227    
		ans = -1; 
	else{ 
1991/0705    
		e = eg->etab[s].env; 
1990/0227    
		if(e == 0) 
1991/1018    
		e = &eg->etab[s]; 
		if(!e->name) 
1990/0227    
			ans = 0; 
		else{ 
			lock(e); 
1990/11211    
			devdir(c, (Qid){s+1,0}, e->name, e->val? e->val->len : 0, 0666, dp); 
1990/0227    
			unlock(e); 
1991/1018    
			devdir(c, (Qid){s+1, (ulong)e->val}, e->name->val, e->val? e->val->len : 0, 0666, dp); 
1990/0227    
			ans = 1; 
		} 
	} 
1991/0705    
	unlock(eg); 
1991/1018    
	qunlock(&eg->ev); 
1990/0227    
	return ans; 
} 
 
1991/0927/sys/src/9/port/devenv.c:242,2551991/1018/sys/src/9/port/devenv.c:82,87
1990/0227    
Chan* 
envclone(Chan *c, Chan *nc) 
{ 
1991/0705    
	Egrp *eg; 
1990/0227    
                 
1990/11211    
	if(!(c->qid.path&CHDIR)){ 
1991/0705    
		eg = u->p->egrp; 
		lock(eg); 
		eg->etab[c->qid.path-1].chref++; 
		unlock(eg); 
1990/0227    
	} 
	return devclone(c, nc); 
} 
 
1991/0927/sys/src/9/port/devenv.c:256,2731991/1018/sys/src/9/port/devenv.c:88,95
1990/0227    
int 
envwalk(Chan *c, char *name) 
{ 
1991/0705    
	Egrp *eg; 
1990/0227    
 
	if(devwalk(c, name, 0, 0, envgen)){ 
1990/11211    
		if(!(c->qid.path&CHDIR)){ 
1991/0705    
			eg = u->p->egrp; 
			lock(eg); 
			eg->etab[c->qid.path-1].chref++; 
			unlock(eg); 
1990/0227    
			return 1; 
		} 
	} 
	return 0; 
1991/1018    
	return devwalk(c, name, 0, 0, envgen); 
1990/0227    
} 
 
void 
1991/0927/sys/src/9/port/devenv.c:279,3261991/1018/sys/src/9/port/devenv.c:101,131
1990/0227    
Chan * 
envopen(Chan *c, int omode) 
{ 
	Env *e, *ne; 
	Envp *ep; 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e; 
	int mode; 
1990/0227    
 
	if(omode & (OWRITE|OTRUNC)){ 
1990/11211    
		if(c->qid.path & CHDIR) 
1991/1018    
	mode = openmode(omode); 
	if(c->qid.path & CHDIR){ 
		if(omode != OREAD) 
1990/11211    
			error(Eperm); 
1991/1018    
	}else{ 
1991/0705    
		eg = u->p->egrp; 
		lock(eg); 
		ep = &eg->etab[c->qid.path-1]; 
1990/0227    
		e = ep->env; 
		if(!e){ 
1991/0705    
			unlock(eg); 
1990/11211    
			error(Egreg); 
1991/1018    
		qlock(&eg->ev); 
		e = &eg->etab[c->qid.path-1]; 
		if(!e->name){ 
			qunlock(&eg->ev); 
			error(Enonexist); 
1990/0227    
		} 
		lock(&envalloc); 
		lock(e); 
		if(waserror()){ 
			unlock(e); 
			unlock(&envalloc); 
1991/0705    
			unlock(eg); 
1990/0227    
			nexterror(); 
1991/1018    
		if(omode == (OWRITE|OTRUNC) && e->val){ 
			qlock(&evlock); 
			evfree(e->val); 
			qunlock(&evlock); 
			e->val = 0; 
1990/0227    
		} 
		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); 
1991/0705    
		unlock(eg); 
1991/1018    
		qunlock(&eg->ev); 
1990/0227    
	} 
	c->mode = openmode(omode); 
1991/1018    
	c->mode = mode; 
1990/0227    
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
1991/0927/sys/src/9/port/devenv.c:329,3751991/1018/sys/src/9/port/devenv.c:134,175
1990/0227    
void 
envcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
	Env *e; 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e, *ne; 
1990/0227    
	int i; 
 
1990/11211    
	if(c->qid.path != CHDIR) 
		error(Eperm); 
1991/1018    
	omode = openmode(omode); 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
1990/0227    
	lock(&envalloc); 
	if(waserror()){ 
		unlock(&envalloc); 
1991/0705    
		unlock(eg); 
1990/0227    
		nexterror(); 
	} 
	e = envalloc.efree; 
	if(e == 0){ 
		print("out of envs\n"); 
1991/1018    
	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); 
1990/11211    
		error(Enoenv); 
1990/0227    
	} 
	envalloc.efree = e->next; 
	e->next = 0; 
	e->pgref = 1; 
	strncpy(e->name, name, NAMELEN); 
1991/0705    
	if(eg->nenv == conf.npgenv){ 
		for(i = 0; i<eg->nenv; i++) 
			if(eg->etab[i].chref == 0) 
1990/0227    
				break; 
1991/0705    
		if(i == eg->nenv){ 
			print("out of egroup envs\n"); 
1990/11211    
			error(Enoenv); 
1990/0227    
		} 
	}else 
1991/0705    
		i = eg->nenv++; 
1990/11211    
	c->qid.path = i+1; 
1991/0705    
	eg->etab[i].env = e; 
	eg->etab[i].chref = 1; 
1990/0227    
	unlock(&envalloc); 
1991/0705    
	unlock(eg); 
1991/1018    
	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}; 
1990/0227    
	c->offset = 0; 
	c->mode = openmode(omode); 
	poperror(); 
1991/1018    
	c->mode = omode; 
1990/0227    
	c->flag |= COPEN; 
} 
 
1991/0927/sys/src/9/port/devenv.c:376,5471991/1018/sys/src/9/port/devenv.c:176,403
1990/0227    
void 
envremove(Chan *c) 
{ 
	Env *e; 
	Envp *ep; 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e; 
1990/0227    
 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eperm); 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
	ep = &eg->etab[c->qid.path-1]; 
1990/0227    
	e = ep->env; 
	if(!e){ 
1991/0705    
		unlock(eg); 
1991/1018    
	qlock(&eg->ev); 
	e = &eg->etab[c->qid.path-1]; 
	if(!e->name){ 
		qunlock(&eg->ev); 
1990/11211    
		error(Enonexist); 
1990/0227    
	} 
	ep->env = 0; 
	ep->chref--; 
	envpgclose(e); 
1991/0705    
	unlock(eg); 
1991/1018    
	qunlock(&eg->ev); 
1990/0227    
} 
 
void 
envwstat(Chan *c, char *db) 
{	int dumpenv(void); 
	dumpenv();  /*DEBUG*/ 
	print("envwstat\n"); 
1990/11211    
	error(Egreg); 
1991/1018    
{ 
	error(Eperm); 
1990/0227    
} 
 
void 
envclose(Chan * c) 
{ 
1991/0705    
	Egrp *eg; 
1991/1018    
} 
1990/0227    
 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return; 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
	eg->etab[c->qid.path-1].chref--; 
	unlock(eg); 
1991/1018    
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); 
1990/0227    
} 
 
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); 
1991/1018    
	qlock(&evlock); 
	if(e->name) 
		evfree(e->name); 
	if(e->val) 
		evfree(e->val); 
	e->name = e->val = 0; 
	qunlock(&evlock); 
1990/0227    
} 
 
long 
1991/0411    
envread(Chan *c, void *va, long n, ulong offset) 
1991/1018    
envread(Chan *c, void *a, long n, ulong offset) 
1990/0227    
{ 
1991/1018    
	Egrp *eg; 
1990/0227    
	Env *e; 
	Envval *ev; 
	char *p; 
	long vn; 
1991/0705    
	Egrp *eg; 
1990/0227    
	char *a = va; 
 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return devdirread(c, a, n, 0, 0, envgen); 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
	e = eg->etab[c->qid.path-1].env; 
1990/0227    
	if(!e){ 
1991/0705    
		unlock(eg); 
1990/11211    
		error(Eio); 
1991/1018    
	qlock(&eg->ev); 
	e = &eg->etab[c->qid.path-1]; 
	if(!e->name){ 
		qunlock(&eg->ev); 
		error(Enonexist); 
1990/0227    
	} 
	lock(e); 
	ev = e->val; 
	vn = ev? e->val->len : 0; 
1991/0411    
	if(offset+n > vn) 
1991/1018    
	vn = ev ? ev->len : 0; 
	if(offset + n > vn) 
1991/0411    
		n = vn - offset; 
1990/0227    
	if(n <= 0) 
		n = 0; 
	else 
1991/0411    
		memmove(a, ev->dat+offset, n); 
1990/0227    
	unlock(e); 
1991/0705    
	unlock(eg); 
1991/1018    
		memmove(a, ev->val + offset, n); 
	qunlock(&eg->ev); 
1990/0227    
	return n; 
} 
 
long 
1991/0411    
envwrite(Chan *c, void *va, long n, ulong offset) 
1991/1018    
envwrite(Chan *c, void *a, long n, ulong offset) 
1990/0227    
{ 
1991/1018    
	Egrp *eg; 
1990/0227    
	Env *e; 
	char *p; 
	Envval *ev; 
	long vn; 
1991/0705    
	Egrp *eg; 
1990/0227    
	char *a = va; 
1991/1018    
	ulong olen; 
1990/0227    
 
	if(n <= 0) 
		return 0; 
1991/1018    
	if(offset + n > MAXENV) 
		error(Etoobig); 
1991/0705    
	eg = u->p->egrp; 
	lock(eg); 
	e = eg->etab[c->qid.path-1].env; /* caller checks for CHDIR */ 
1990/0227    
	if(!e){ 
1991/0705    
		unlock(eg); 
1990/11211    
		error(Eio); 
1991/1018    
	qlock(&eg->ev); 
	e = &eg->etab[c->qid.path-1]; 
	if(!e->name){ 
		qunlock(&eg->ev); 
		error(Enonexist); 
1990/0227    
	} 
	lock(&envalloc); 
	lock(e); 
	if(waserror()){ 
		unlock(e); 
		unlock(&envalloc); 
1991/0705    
		unlock(eg); 
1990/0227    
		nexterror(); 
	} 
	if(e->pgref>1) 
		panic("envwrite to non-duped env"); 
1991/0411    
	growenval(e, offset+n); 
1990/0227    
	ev = e->val; 
	vn = ev? ev->len : 0; 
1991/0411    
	if(offset > vn) 
1990/11211    
		error(Egreg); /* perhaps should zero fill */ 
1991/0411    
	memmove(ev->dat+offset, a, n); 
	e->val->len = offset+n; 
1990/0227    
	poperror(); 
	unlock(e); 
	unlock(&envalloc); 
1991/0705    
	unlock(eg); 
1991/1018    
	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); 
1990/0227    
	return n; 
} 
 
void 
dumpenv(void) 
1991/1018    
/* 
 * called with evlock qlocked 
 */ 
Envval * 
newev(char *s, ulong n) 
1990/0227    
{ 
	Env *e; 
	Envp *ep; 
	Envval *ev; 
1991/0705    
	Egrp *eg; 
1990/0227    
	int i; 
	char hold; 
1991/1018    
	uchar *t; 
	int h; 
1990/0227    
 
1991/0705    
	eg = u->p->egrp; 
	for(ep=eg->etab, i=0; i<eg->nenv; i++, ep++) 
1990/0227    
		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)); 
1991/1018    
	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; 
1990/0227    
} 
1991/0927    
 
/* 
1991/1018/sys/src/9/port/devenv.c:28,331991/1022/sys/src/9/port/devenv.c:28,34 (short | long)
1991/1018    
	Envval	*free[EVFREE+1]; 
	char	*block;			/* the free page we are allocating from */ 
	char	*lim;			/* end of block */ 
1991/1022    
	int	npage;			/* total pages gotten from newpage() */ 
1990/0227    
}envalloc; 
 
1991/1018    
QLock	evlock; 
1991/1018/sys/src/9/port/devenv.c:366,3741991/1022/sys/src/9/port/devenv.c:367,376
1991/1018    
			b += ALIGN + sizeof *ev; 
		} 
		b = (char*)VA(kmap(newpage(0, 0, 0))); 
1991/1022    
		envalloc.npage++; 
1991/1018    
		envalloc.lim = b + BY2PG; 
	} 
                 
1991/1022    
	 
1991/1018    
	ev = (Envval*)b; 
	ev->val = b + sizeof *ev; 
	ev->ref = 1; 
1991/1018/sys/src/9/port/devenv.c:398,4031991/1022/sys/src/9/port/devenv.c:400,442
1991/1018    
		n = EVFREE; 
	ev->next = envalloc.free[n]; 
	envalloc.free[n] = ev; 
1991/1022    
} 
 
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); 
1990/0227    
} 
1991/0927    
 
/* 
1991/1022/sys/src/9/port/devenv.c:391,3961991/1024/sys/src/9/port/devenv.c:391,398 (short | long)
1991/1018    
 
	if(ev->prev) 
		ev->prev->next = ev->next; 
1991/1024    
	else 
		panic("evfree"); 
1991/1018    
	if(ev->next) 
		ev->next->prev = ev->prev; 
	n = (ev->len + ALIGN - 1) & ~(ALIGN - 1); 
1991/1022/sys/src/9/port/devenv.c:399,4041991/1024/sys/src/9/port/devenv.c:401,407
1991/1018    
	if(n > EVFREE) 
		n = EVFREE; 
	ev->next = envalloc.free[n]; 
1991/1024    
	ev->prev = 0; 
1991/1018    
	envalloc.free[n] = ev; 
1991/1022    
} 
 
1991/1024/sys/src/9/port/devenv.c:433,4381991/1030/sys/src/9/port/devenv.c:433,449 (short | long)
1991/1022    
	for(i = 0; i < EVHASH; i++){ 
		j = 0; 
		for(ev = evhash[i].next; ev; ev = ev->next){ 
1991/1030    
			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); 
1991/1022    
			if(j++ == 1000){ 
				print("hash bucket %d circular\n", i); 
				break; 
1991/1030/sys/src/9/port/devenv.c:467,4691991/1102/sys/src/9/port/devenv.c:467,478 (short | long)
1991/0927    
	(*devtab[c->type].write)(c, eval, strlen(eval), 0); 
	close(c); 
} 
1991/1102    
 
void 
ksetterm(char *f) 
{ 
	char buf[2*NAMELEN]; 
 
	sprint(buf, f, conffile); 
	ksetenv("terminal", buf); 
} 
1991/1102/sys/src/9/port/devenv.c:156,1631991/1105/sys/src/9/port/devenv.c:156,163 (short | long)
1991/1018    
	if(ne) 
		e = ne; 
	else if(eg->nenv == conf.npgenv){ 
		print("out of egroup envs\n"); 
		qunlock(&eg->ev); 
1991/1105    
		print("out of egroup envs\n"); 
1990/11211    
		error(Enoenv); 
1990/0227    
	} 
1991/1018    
	i = e - eg->etab + 1; 
1991/1105/sys/src/9/port/devenv.c:405,4581991/1108/sys/src/9/port/devenv.c:405,410 (short | long)
1991/1018    
	envalloc.free[n] = ev; 
1991/1022    
} 
 
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){ 
1991/1030    
			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); 
1991/1022    
			if(j++ == 1000){ 
				print("hash bucket %d circular\n", i); 
				break; 
			} 
		} 
	} 
	qunlock(&evlock); 
1990/0227    
} 
1991/0927    
                 
/* 
 *  to let the kernel set environment variables 
 */ 
1991/1108/sys/src/9/port/devenv.c:66,721991/1109/sys/src/9/port/devenv.c:66,72 (short | long)
1991/1018    
		if(!e->name) 
1990/0227    
			ans = 0; 
		else{ 
1991/1018    
			devdir(c, (Qid){s+1, (ulong)e->val}, e->name->val, e->val? e->val->len : 0, 0666, dp); 
1991/1109    
			devdir(c, (Qid){s+1, (ulong)e->val}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp); 
1990/0227    
			ans = 1; 
		} 
	} 
1991/1109/sys/src/9/port/devenv.c:196,2011991/1115/sys/src/9/port/devenv.c:196,202 (short | long)
1990/0227    
void 
envwstat(Chan *c, char *db) 
1991/1018    
{ 
1991/1115    
	USED(c, db); 
1991/1018    
	error(Eperm); 
1990/0227    
} 
 
1991/1109/sys/src/9/port/devenv.c:202,2071991/1115/sys/src/9/port/devenv.c:203,209
1990/0227    
void 
envclose(Chan * c) 
{ 
1991/1115    
	USED(c); 
1991/1018    
} 
1990/0227    
 
1991/1018    
void 
1991/1115/sys/src/9/port/devenv.c:268,2741991/1121/sys/src/9/port/devenv.c:268,275 (short | long)
1990/0227    
 
	if(n <= 0) 
		return 0; 
1991/1018    
	if(offset + n > MAXENV) 
1991/1121    
	olen = (offset + n + ALIGN - 1) & ~(ALIGN - 1); 
	if(olen > MAXENV) 
1991/1018    
		error(Etoobig); 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
1991/1115/sys/src/9/port/devenv.c:338,3451991/1121/sys/src/9/port/devenv.c:339,346
1991/1018    
	char *b, *lim; 
	ulong size; 
 
	n = (n - 1) / ALIGN; 
	size = (n + 1) * ALIGN; 
1991/1121    
	size = (n + ALIGN - 1) & ~(ALIGN - 1); 
	n = (size - 1) / ALIGN; 
1991/1018    
	p = &envalloc.free[n < EVFREE ? n : EVFREE]; 
	for(ev = *p; ev; ev = *p){ 
		if(ev->len == size){ 
1991/1121/sys/src/9/port/devenv.c:3,91992/0111/sys/src/9/port/devenv.c:3,9 (short | long)
Move error.h to ../port. Change errors to actual strings.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1992/0111    
#include	"../port/error.h" 
1990/0227    
 
#include	"devtab.h" 
 
1992/0111/sys/src/9/port/devenv.c:1,51992/0321/sys/src/9/port/devenv.c:1,5 (short | long)
Move lib.h to ../port.
rsc Fri Mar 4 12:44:25 2005
1990/0227    
#include	"u.h" 
#include	"lib.h" 
1992/0321    
#include	"../port/lib.h" 
1990/0227    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0321/sys/src/9/port/devenv.c:66,721992/0331/sys/src/9/port/devenv.c:66,72 (short | long)
1991/1018    
		if(!e->name) 
1990/0227    
			ans = 0; 
		else{ 
1991/1109    
			devdir(c, (Qid){s+1, (ulong)e->val}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp); 
1992/0331    
			devdir(c, (Qid){s+1, (ulong)e->name}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp); 
1990/0227    
			ans = 1; 
		} 
	} 
1992/0331/sys/src/9/port/devenv.c:42,481992/0622/sys/src/9/port/devenv.c:42,48 (short | long)
1990/0227    
void 
envreset(void) 
{ 
1991/1018    
	evscratch = ialloc(BY2PG, 0); 
1992/0622    
	evscratch = xalloc(BY2PG); 
1990/0227    
} 
 
void 
1992/0622/sys/src/9/port/devenv.c:7,481992/0623/sys/src/9/port/devenv.c:7,20 (short | long)
1990/0227    
 
#include	"devtab.h" 
 
struct Envval 
1992/0623    
enum 
1990/0227    
{ 
1991/1018    
	Envval	*next;		/* for hashing & easy deletion from hash list */ 
	Envval	*prev; 
	ulong	len;		/* length of val that is valid */ 
	int	ref; 
	char	*val; 
1992/0623    
	Maxenvsize = 16300, 
1990/0227    
}; 
 
1991/1018    
enum{ 
	MAXENV	= (BY2PG - sizeof(Envval)), 
	EVHASH	= 64, 
	EVFREE	= 16, 
	ALIGN	= 16, 
}; 
1990/0227    
                 
struct 
{ 
1991/1018    
	Envval	*free[EVFREE+1]; 
	char	*block;			/* the free page we are allocating from */ 
	char	*lim;			/* end of block */ 
1991/1022    
	int	npage;			/* total pages gotten from newpage() */ 
1990/0227    
}envalloc; 
                 
1991/1018    
QLock	evlock; 
Envval	evhash[EVHASH]; 
char	*evscratch;		/* for constructing the contents of a file */ 
1990/0227    
                 
1991/1018    
Envval	*newev(char*, ulong); 
Envval	*evalloc(ulong); 
void	evfree(Envval*); 
                 
1990/0227    
void 
envreset(void) 
{ 
1992/0622    
	evscratch = xalloc(BY2PG); 
1990/0227    
} 
 
void 
1992/0622/sys/src/9/port/devenv.c:54,771992/0623/sys/src/9/port/devenv.c:26,47
1990/0227    
envgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) 
{ 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e; 
1990/0227    
	int ans; 
1992/0623    
	Evalue *e; 
1990/0227    
 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
1991/0705    
	if(s >= eg->nenv) 
1990/0227    
		ans = -1; 
	else{ 
1991/1018    
		e = &eg->etab[s]; 
		if(!e->name) 
1990/0227    
			ans = 0; 
		else{ 
1992/0331    
			devdir(c, (Qid){s+1, (ulong)e->name}, e->name->val, e->val? e->val->len : 0, eve, 0666, dp); 
1990/0227    
			ans = 1; 
		} 
1992/0623    
	qlock(eg); 
 
	for(e = eg->entries; e && s; e = e->link) 
		s--; 
 
	if(e == 0) { 
		qunlock(eg); 
		return -1; 
1990/0227    
	} 
1991/1018    
	qunlock(&eg->ev); 
1990/0227    
	return ans; 
1992/0623    
 
	devdir(c, (Qid){e->path, 0}, e->name, e->len, eve, 0666, dp); 
	qunlock(eg); 
	return 1; 
1990/0227    
} 
 
Chan* 
1992/0622/sys/src/9/port/devenv.c:103,1321992/0623/sys/src/9/port/devenv.c:73,103
1990/0227    
envopen(Chan *c, int omode) 
{ 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e; 
	int mode; 
1990/0227    
                 
1991/1018    
	mode = openmode(omode); 
1992/0623    
	Evalue *e; 
	 
	eg = u->p->egrp; 
1991/1018    
	if(c->qid.path & CHDIR){ 
		if(omode != OREAD) 
1990/11211    
			error(Eperm); 
1991/1018    
	}else{ 
1991/0705    
		eg = u->p->egrp; 
1991/1018    
		qlock(&eg->ev); 
		e = &eg->etab[c->qid.path-1]; 
		if(!e->name){ 
			qunlock(&eg->ev); 
1992/0623    
	} 
	else { 
		qlock(eg); 
		for(e = eg->entries; e; e = e->link) 
			if(e->path == c->qid.path) 
				break; 
 
		if(e == 0) { 
			qunlock(eg); 
1991/1018    
			error(Enonexist); 
1990/0227    
		} 
1991/1018    
		if(omode == (OWRITE|OTRUNC) && e->val){ 
			qlock(&evlock); 
			evfree(e->val); 
			qunlock(&evlock); 
			e->val = 0; 
1992/0623    
		if(omode == (OWRITE|OTRUNC) && e->value) { 
			free(e->value); 
			e->value = 0; 
			e->len = 0; 
1990/0227    
		} 
1991/1018    
		qunlock(&eg->ev); 
1992/0623    
		qunlock(eg); 
1990/0227    
	} 
1991/1018    
	c->mode = mode; 
1992/0623    
	c->mode = openmode(omode); 
1990/0227    
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
1992/0622/sys/src/9/port/devenv.c:136,1741992/0623/sys/src/9/port/devenv.c:107,142
1990/0227    
envcreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e, *ne; 
1990/0227    
	int i; 
1992/0623    
	Evalue *e; 
1990/0227    
 
1990/11211    
	if(c->qid.path != CHDIR) 
		error(Eperm); 
1992/0623    
 
1991/1018    
	omode = openmode(omode); 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	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){ 
		qunlock(&eg->ev); 
1991/1105    
		print("out of egroup envs\n"); 
1990/11211    
		error(Enoenv); 
1992/0623    
 
	qlock(eg); 
	if(waserror()) { 
		qunlock(eg); 
		nexterror(); 
1990/0227    
	} 
1991/1018    
	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}; 
1992/0623    
 
	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(); 
 
1990/0227    
	c->offset = 0; 
1991/1018    
	c->mode = omode; 
1990/0227    
	c->flag |= COPEN; 
1992/0622/sys/src/9/port/devenv.c:178,1961992/0623/sys/src/9/port/devenv.c:146,177
1990/0227    
envremove(Chan *c) 
{ 
1991/0705    
	Egrp *eg; 
1991/1018    
	Env *e; 
1992/0623    
	Evalue *e, **l; 
1990/0227    
 
1990/11211    
	if(c->qid.path & CHDIR) 
		error(Eperm); 
1992/0623    
 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
	e = &eg->etab[c->qid.path-1]; 
	if(!e->name){ 
		qunlock(&eg->ev); 
1992/0623    
	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); 
1990/11211    
		error(Enonexist); 
1990/0227    
	} 
	envpgclose(e); 
1991/1018    
	qunlock(&eg->ev); 
1992/0623    
 
	*l = e->link; 
	qunlock(eg); 
	free(e->name); 
	if(e->value) 
		free(e->value); 
	free(e); 
1990/0227    
} 
 
void 
1992/0622/sys/src/9/port/devenv.c:206,2601992/0623/sys/src/9/port/devenv.c:187,219
1991/1115    
	USED(c); 
1991/1018    
} 
1990/0227    
 
1991/1018    
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); 
1990/0227    
} 
                 
void 
envpgclose(Env *e) 
{ 
1991/1018    
	qlock(&evlock); 
	if(e->name) 
		evfree(e->name); 
	if(e->val) 
		evfree(e->val); 
	e->name = e->val = 0; 
	qunlock(&evlock); 
1990/0227    
} 
                 
long 
1991/1018    
envread(Chan *c, void *a, long n, ulong offset) 
1990/0227    
{ 
1991/1018    
	Egrp *eg; 
1990/0227    
	Env *e; 
	Envval *ev; 
	long vn; 
1992/0623    
	Evalue *e; 
1990/0227    
 
1990/11211    
	if(c->qid.path & CHDIR) 
1990/0227    
		return devdirread(c, a, n, 0, 0, envgen); 
1992/0623    
 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
	e = &eg->etab[c->qid.path-1]; 
	if(!e->name){ 
		qunlock(&eg->ev); 
1992/0623    
	qlock(eg); 
	for(e = eg->entries; e; e = e->link) 
		if(e->path == c->qid.path) 
			break; 
 
	if(e == 0) { 
		qunlock(eg); 
1991/1018    
		error(Enonexist); 
1990/0227    
	} 
	ev = e->val; 
1991/1018    
	vn = ev ? ev->len : 0; 
	if(offset + n > vn) 
1991/0411    
		n = vn - offset; 
1992/0623    
 
	if(offset + n > e->len) 
		n = e->len - offset; 
1990/0227    
	if(n <= 0) 
		n = 0; 
	else 
1991/1018    
		memmove(a, ev->val + offset, n); 
	qunlock(&eg->ev); 
1992/0623    
		memmove(a, e->value+offset, n); 
	qunlock(eg); 
1990/0227    
	return n; 
} 
 
1992/0622/sys/src/9/port/devenv.c:261,4111992/0623/sys/src/9/port/devenv.c:220,259
1990/0227    
long 
1991/1018    
envwrite(Chan *c, void *a, long n, ulong offset) 
1990/0227    
{ 
1992/0623    
	char *s; 
	int vend; 
1991/1018    
	Egrp *eg; 
1990/0227    
	Env *e; 
	Envval *ev; 
1991/1018    
	ulong olen; 
1992/0623    
	Evalue *e; 
1990/0227    
 
	if(n <= 0) 
		return 0; 
1991/1121    
	olen = (offset + n + ALIGN - 1) & ~(ALIGN - 1); 
	if(olen > MAXENV) 
1992/0623    
 
	vend = offset+n; 
	if(vend > Maxenvsize) 
1991/1018    
		error(Etoobig); 
1992/0623    
 
1991/0705    
	eg = u->p->egrp; 
1991/1018    
	qlock(&eg->ev); 
	e = &eg->etab[c->qid.path-1]; 
	if(!e->name){ 
		qunlock(&eg->ev); 
1992/0623    
	qlock(eg); 
	for(e = eg->entries; e; e = e->link) 
		if(e->path == c->qid.path) 
			break; 
 
	if(e == 0) { 
		qunlock(eg); 
1991/1018    
		error(Enonexist); 
1990/0227    
	} 
	ev = e->val; 
1991/1018    
	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); 
1990/0227    
	return n; 
} 
 
1991/1018    
/* 
 * called with evlock qlocked 
 */ 
Envval * 
newev(char *s, ulong n) 
1990/0227    
{ 
	Envval *ev; 
1991/1018    
	uchar *t; 
	int h; 
1990/0227    
                 
1991/1018    
	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; 
                 
1991/1121    
	size = (n + ALIGN - 1) & ~(ALIGN - 1); 
	n = (size - 1) / ALIGN; 
1991/1018    
	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; 
1992/0623    
	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; 
1991/1018    
	} 
                 
	/* 
	 * 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))); 
1991/1022    
		envalloc.npage++; 
1991/1018    
		envalloc.lim = b + BY2PG; 
	} 
1991/1022    
	                 
1991/1018    
	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; 
1991/1024    
	else 
		panic("evfree"); 
1991/1018    
	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]; 
1991/1024    
	ev->prev = 0; 
1991/1018    
	envalloc.free[n] = ev; 
1992/0623    
	memmove(e->value+offset, a, n); 
	qunlock(eg); 
	return n; 
1991/1022    
} 
 
1991/0927    
/* 
1992/0623/sys/src/9/port/devenv.c:76,821992/0625/sys/src/9/port/devenv.c:76,82 (short | long)
1992/0623    
	Evalue *e; 
	 
	eg = u->p->egrp; 
1991/1018    
	if(c->qid.path & CHDIR){ 
1992/0625    
	if(c->qid.path & CHDIR) { 
1991/1018    
		if(omode != OREAD) 
1990/11211    
			error(Eperm); 
1992/0623    
	} 
1992/0623/sys/src/9/port/devenv.c:254,2591992/0625/sys/src/9/port/devenv.c:254,299
1992/0623    
	memmove(e->value+offset, a, n); 
	qunlock(eg); 
	return n; 
1992/0625    
} 
 
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); 
	} 
1991/1022    
} 
 
1991/0927    
/* 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)