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

1991/1114/port/net.c (diff list | history)

1991/1107/sys/src/9/port/net.c:5,101991/1108/sys/src/9/port/net.c:5,12 (short | long)
1991/1107    
#include	"fns.h" 
#include	"errno.h" 
 
1991/1108    
#include	"fcall.h" 
 
1991/1107    
enum 
{ 
	Qlisten=	1, 
1991/1107/sys/src/9/port/net.c:11,161991/1108/sys/src/9/port/net.c:13,19
1991/1107    
	Qclone=		2, 
	Q2nd=		3, 
	Q3rd=		4, 
1991/1108    
	Qinf=		5, 
1991/1107    
}; 
 
/* 
1991/1107/sys/src/9/port/net.c:40,461991/1108/sys/src/9/port/net.c:43,49
1991/1107    
	} 
 
	/* second level contains clone plus all the conversations */ 
	if(c->qid.path == (CHDIR | Q2nd)){ 
1991/1108    
	if(STREAMID(c->qid.path) == 0){ 
1991/1107    
		if(i == 0){ 
			q.path = Qclone; 
			devdir(c, q, "clone", 0, 0666, dp); 
1991/1107/sys/src/9/port/net.c:53,611991/1108/sys/src/9/port/net.c:56,61
1991/1107    
		return 1; 
	} 
 
	if((c->qid.path & CHDIR) == 0) 
		return -1; 
                 
	/* third level depends on the number of info files */ 
	switch(i){ 
	case 0: 
1991/1107/sys/src/9/port/net.c:73,871991/1108/sys/src/9/port/net.c:73,139
1991/1107    
		devdir(c, q, "listen", 0, 0666, dp); 
		break; 
	default: 
		if(i >= 3 + np->ninfo) 
			return -1; 
		i -= 3; 
		q.path = Qlisten + i + 1; 
1991/1108    
		if(i >= np->ninfo) 
			return -1; 
		q.path = STREAMQID(STREAMID(c->qid.path), Qinf+i); 
1991/1107    
		devdir(c, q, np->info[i].name, 0, 0666, dp); 
1991/1108    
		break; 
1991/1107    
	} 
	return 1; 
} 
 
1991/1108    
int	  
netwalk(Chan *c, char *name, Network *np) 
{ 
	if(strcmp(name, "..") == 0) { 
		switch(STREAMTYPE(c->qid.path)){ 
		case Q2nd: 
			c->qid.path = CHDIR; 
			break; 
		case Q3rd: 
			c->qid.path = CHDIR|Q2nd; 
			break; 
		default: 
			panic("netwalk %lux", c->qid.path); 
		} 
		return 1; 
	} 
 
	return devwalk(c, name, (Dirtab*)np, 0, netgen); 
} 
 
void 
netstat(Chan *c, char *db, Network *np) 
{ 
	int i; 
	Dir dir; 
 
	for(i=0;; i++) 
		switch(netgen(c, (Dirtab*)np, 0, i, &dir)){ 
		case -1: 
			/* 
			 * devices with interesting directories usually don't get 
			 * here, which is good because we've lost the name by now. 
			 */ 
			if(c->qid.path & CHDIR){ 
				devdir(c, c->qid, ".", 0L, CHDIR|0700, &dir); 
				convD2M(&dir, db); 
				return; 
			} 
			print("netstat %c %lux\n", devchar[c->type], c->qid.path); 
			error(Enonexist); 
		case 0: 
			break; 
		case 1: 
			if(eqqid(c->qid, dir.qid)){ 
				convD2M(&dir, db); 
				return; 
			} 
			break; 
		} 
} 
 
1991/1107    
Chan * 
netopen(Chan *c, int omode, Network *np) 
{ 
1991/1107/sys/src/9/port/net.c:125,1311991/1108/sys/src/9/port/net.c:177,183
1991/1107    
long 
netread(Chan *c, void *a, long n, ulong offset, Network *np) 
{ 
	int i; 
1991/1108    
	int t; 
1991/1107    
	char buf[256]; 
 
	if(c->stream) 
1991/1107/sys/src/9/port/net.c:134,1431991/1108/sys/src/9/port/net.c:186,195
1991/1107    
	if(c->qid.path&CHDIR) 
		return devdirread(c, a, n, (Dirtab*)np, 0, netgen); 
 
	if(c->qid.path <= Qlisten || c->qid.path > Qlisten + np->ninfo) 
1991/1108    
	t = STREAMTYPE(c->qid.path); 
	if(t < Qinf || t >= Qinf + np->ninfo) 
1991/1107    
		error(Ebadusefd); 
 
	i = c->qid.path - Qlisten - 1; 
	(*np->info[i].fill)(c, buf, sizeof(buf)); 
1991/1108    
	(*np->info[t-Qinf].fill)(c, buf, sizeof(buf)); 
1991/1107    
	return stringread(c, a, n, buf, offset); 
} 
1991/1108/sys/src/9/port/net.c:34,401991/1109/sys/src/9/port/net.c:34,40 (short | long)
1991/1107    
		case 0: 
			q.path = CHDIR | Q2nd; 
			strcpy(buf, np->name); 
			devdir(c, q, buf, 0, 0666, dp); 
1991/1109    
			devdir(c, q, buf, 0, eve, 0666, dp); 
1991/1107    
			break; 
		default: 
			return -1; 
1991/1108/sys/src/9/port/net.c:46,561991/1109/sys/src/9/port/net.c:46,56
1991/1108    
	if(STREAMID(c->qid.path) == 0){ 
1991/1107    
		if(i == 0){ 
			q.path = Qclone; 
			devdir(c, q, "clone", 0, 0666, dp); 
1991/1109    
			devdir(c, q, "clone", 0, eve, 0666, dp); 
1991/1107    
		}else if(i < np->nconv){ 
			q.path = CHDIR|STREAMQID(i, Q3rd); 
			sprint(buf, "%d", i); 
			devdir(c, q, buf, 0, 0666, dp); 
1991/1109    
			devdir(c, q, buf, 0, eve, 0666, dp); 
1991/1107    
		}else 
			return -1; 
		return 1; 
1991/1108/sys/src/9/port/net.c:60,761991/1109/sys/src/9/port/net.c:60,76
1991/1107    
	switch(i){ 
	case 0: 
		q.path = STREAMQID(STREAMID(c->qid.path), Sdataqid); 
		devdir(c, q, "data", 0, 0666, dp); 
1991/1109    
		devdir(c, q, "data", 0, eve, 0666, dp); 
1991/1107    
		break; 
	case 1: 
		q.path = STREAMQID(STREAMID(c->qid.path), Sctlqid); 
		devdir(c, q, "ctl", 0, 0666, dp); 
1991/1109    
		devdir(c, q, "ctl", 0, eve, 0666, dp); 
1991/1107    
		break; 
	case 2: 
		if(np->listen == 0) 
			return 0; 
		q.path = STREAMQID(STREAMID(c->qid.path), Qlisten); 
		devdir(c, q, "listen", 0, 0666, dp); 
1991/1109    
		devdir(c, q, "listen", 0, eve, 0666, dp); 
1991/1107    
		break; 
	default: 
		i -= 3; 
1991/1108/sys/src/9/port/net.c:77,831991/1109/sys/src/9/port/net.c:77,83
1991/1108    
		if(i >= np->ninfo) 
			return -1; 
		q.path = STREAMQID(STREAMID(c->qid.path), Qinf+i); 
1991/1107    
		devdir(c, q, np->info[i].name, 0, 0666, dp); 
1991/1109    
		devdir(c, q, np->info[i].name, 0, eve, 0666, dp); 
1991/1108    
		break; 
1991/1107    
	} 
	return 1; 
1991/1108/sys/src/9/port/net.c:117,1231991/1109/sys/src/9/port/net.c:117,123
1991/1108    
			 * here, which is good because we've lost the name by now. 
			 */ 
			if(c->qid.path & CHDIR){ 
				devdir(c, c->qid, ".", 0L, CHDIR|0700, &dir); 
1991/1109    
				devdir(c, c->qid, ".", 0L, eve, CHDIR|0700, &dir); 
1991/1108    
				convD2M(&dir, db); 
				return; 
			} 
1991/1109/sys/src/9/port/net.c:43,551991/1114/sys/src/9/port/net.c:43,55 (short | long)
1991/1107    
	} 
 
	/* second level contains clone plus all the conversations */ 
1991/1108    
	if(STREAMID(c->qid.path) == 0){ 
1991/1114    
	if(STREAMTYPE(c->qid.path) == Q2nd){ 
1991/1107    
		if(i == 0){ 
			q.path = Qclone; 
1991/1109    
			devdir(c, q, "clone", 0, eve, 0666, dp); 
1991/1107    
		}else if(i < np->nconv){ 
			q.path = CHDIR|STREAMQID(i, Q3rd); 
			sprint(buf, "%d", i); 
1991/1114    
		}else if(i <= np->nconv){ 
			q.path = CHDIR|STREAMQID(i-1, Q3rd); 
			sprint(buf, "%d", i-1); 
1991/1109    
			devdir(c, q, buf, 0, eve, 0666, dp); 
1991/1107    
		}else 
			return -1; 
1991/1114/sys/src/9/port/net.c:25,301991/1115/sys/src/9/port/net.c:25,35 (short | long)
1991/1107    
	Qid q; 
	char buf[32]; 
	Network *np = vp; 
1991/1115    
	int t; 
	int id; 
	Netprot *p; 
	int perm; 
	char *o; 
1991/1107    
 
	q.vers = 0; 
 
1991/1114/sys/src/9/port/net.c:34,401991/1115/sys/src/9/port/net.c:39,45
1991/1107    
		case 0: 
			q.path = CHDIR | Q2nd; 
			strcpy(buf, np->name); 
1991/1109    
			devdir(c, q, buf, 0, eve, 0666, dp); 
1991/1115    
			devdir(c, q, buf, 0, eve, 0555, dp); 
1991/1107    
			break; 
		default: 
			return -1; 
1991/1114/sys/src/9/port/net.c:43,491991/1115/sys/src/9/port/net.c:48,55
1991/1107    
	} 
 
	/* second level contains clone plus all the conversations */ 
1991/1114    
	if(STREAMTYPE(c->qid.path) == Q2nd){ 
1991/1115    
	t = STREAMTYPE(c->qid.path); 
	if(t == Q2nd || t == Qclone){ 
1991/1107    
		if(i == 0){ 
			q.path = Qclone; 
1991/1109    
			devdir(c, q, "clone", 0, eve, 0666, dp); 
1991/1114/sys/src/9/port/net.c:50,561991/1115/sys/src/9/port/net.c:56,62
1991/1114    
		}else if(i <= np->nconv){ 
			q.path = CHDIR|STREAMQID(i-1, Q3rd); 
			sprint(buf, "%d", i-1); 
1991/1109    
			devdir(c, q, buf, 0, eve, 0666, dp); 
1991/1115    
			devdir(c, q, buf, 0, eve, 0555, dp); 
1991/1107    
		}else 
			return -1; 
		return 1; 
1991/1114/sys/src/9/port/net.c:57,761991/1115/sys/src/9/port/net.c:63,91
1991/1107    
	} 
 
	/* third level depends on the number of info files */ 
1991/1115    
	id = STREAMID(c->qid.path); 
	p = &np->prot[id]; 
	if(*p->owner){ 
		o = p->owner; 
		perm = p->mode; 
	} else { 
		o = eve; 
		perm = 0666; 
	} 
1991/1107    
	switch(i){ 
	case 0: 
		q.path = STREAMQID(STREAMID(c->qid.path), Sdataqid); 
1991/1109    
		devdir(c, q, "data", 0, eve, 0666, dp); 
1991/1115    
		devdir(c, q, "data", 0, o, perm, dp); 
1991/1107    
		break; 
	case 1: 
		q.path = STREAMQID(STREAMID(c->qid.path), Sctlqid); 
1991/1109    
		devdir(c, q, "ctl", 0, eve, 0666, dp); 
1991/1115    
		devdir(c, q, "ctl", 0, o, perm, dp); 
1991/1107    
		break; 
	case 2: 
		if(np->listen == 0) 
			return 0; 
		q.path = STREAMQID(STREAMID(c->qid.path), Qlisten); 
1991/1109    
		devdir(c, q, "listen", 0, eve, 0666, dp); 
1991/1115    
		devdir(c, q, "listen", 0, o, perm, dp); 
1991/1107    
		break; 
	default: 
		i -= 3; 
1991/1114/sys/src/9/port/net.c:77,831991/1115/sys/src/9/port/net.c:92,98
1991/1108    
		if(i >= np->ninfo) 
			return -1; 
		q.path = STREAMQID(STREAMID(c->qid.path), Qinf+i); 
1991/1109    
		devdir(c, q, np->info[i].name, 0, eve, 0666, dp); 
1991/1115    
		devdir(c, q, np->info[i].name, 0, eve, 0444, dp); 
1991/1108    
		break; 
1991/1107    
	} 
	return 1; 
1991/1114/sys/src/9/port/net.c:117,1231991/1115/sys/src/9/port/net.c:132,138
1991/1108    
			 * here, which is good because we've lost the name by now. 
			 */ 
			if(c->qid.path & CHDIR){ 
1991/1109    
				devdir(c, c->qid, ".", 0L, eve, CHDIR|0700, &dir); 
1991/1115    
				devdir(c, c->qid, ".", 0L, eve, CHDIR|0555, &dir); 
1991/1108    
				convD2M(&dir, db); 
				return; 
			} 
1991/1114/sys/src/9/port/net.c:134,1431991/1115/sys/src/9/port/net.c:149,176
1991/1108    
		} 
} 
 
1991/1115    
void 
netwstat(Chan *c, char *db, Network *np) 
{ 
	Dir dir; 
	Netprot *p; 
 
	p = &np->prot[STREAMID(c->qid.path)]; 
	lock(np); 
	if(strncmp(p->owner, u->p->user, NAMELEN)){ 
		unlock(np); 
		error(Eperm); 
	} 
	convM2D(db, &dir); 
	strncpy(p->owner, dir.uid, NAMELEN); 
	p->mode = dir.mode; 
	unlock(np); 
} 
 
1991/1107    
Chan * 
netopen(Chan *c, int omode, Network *np) 
{ 
	int conv; 
1991/1115    
	int id; 
1991/1107    
 
	if(c->qid.path & CHDIR){ 
		if(omode != OREAD) 
1991/1114/sys/src/9/port/net.c:146,1591991/1115/sys/src/9/port/net.c:179,197
1991/1107    
		switch(STREAMTYPE(c->qid.path)){ 
		case Sdataqid: 
		case Sctlqid: 
1991/1115    
			id = STREAMID(c->qid.path); 
			if(netown(np, id, u->p->user, omode&7) < 0) 
				error(Eperm); 
1991/1107    
			break; 
		case Qlisten: 
			conv = (*np->listen)(c); 
			c->qid.path = STREAMQID(conv, Sctlqid); 
1991/1115    
			streamopen(c, np->devp); 
			id = (*np->listen)(c); 
			streamclose(c); 
			c->qid.path = STREAMQID(id, Sctlqid); 
1991/1107    
			break; 
		case Qclone: 
			conv = (*np->clone)(c); 
			c->qid.path = STREAMQID(conv, Sctlqid); 
1991/1115    
			id = (*np->clone)(c); 
			c->qid.path = STREAMQID(id, Sctlqid); 
1991/1107    
			break; 
		default: 
			if(omode != OREAD) 
1991/1114/sys/src/9/port/net.c:191,1951991/1115/sys/src/9/port/net.c:229,272
1991/1107    
		error(Ebadusefd); 
 
1991/1108    
	(*np->info[t-Qinf].fill)(c, buf, sizeof(buf)); 
1991/1107    
	return stringread(c, a, n, buf, offset); 
1991/1115    
	return stringread(a, n, buf, offset); 
} 
 
int 
netown(Network *np, int id, char *o, int omode) 
{ 
	static int access[] = { 0400, 0200, 0600, 0100 }; 
	Netprot *p; 
	int mode; 
	int t; 
 
	p = &np->prot[id]; 
	lock(np); 
	if(*p->owner){ 
		if(strncmp(o, p->owner, NAMELEN) == 0)	/* User */ 
			mode = p->mode; 
		else if(strncmp(o, eve, NAMELEN) == 0)	/* Bootes is group */ 
			mode = p->mode<<3; 
		else 
			mode = p->mode<<6;		/* Other */ 
 
		t = access[omode&3]; 
		if((t & mode) == t){ 
			unlock(np); 
			return 0; 
		} else { 
			unlock(np); 
			return -1; 
		} 
	} 
	strncpy(p->owner, o, NAMELEN); 
	np->prot[id].mode = 0660; 
	unlock(np); 
	return 0; 
} 
 
void 
netdisown(Network *np, int id) 
{ 
	*np->prot[id].owner = 0; 
1991/1107    
} 
1991/1115/sys/src/9/port/net.c:180,1871991/1116/sys/src/9/port/net.c:180,185 (short | long)
1991/1107    
		case Sdataqid: 
		case Sctlqid: 
1991/1115    
			id = STREAMID(c->qid.path); 
			if(netown(np, id, u->p->user, omode&7) < 0) 
				error(Eperm); 
1991/1107    
			break; 
		case Qlisten: 
1991/1115    
			streamopen(c, np->devp); 
1991/1115/sys/src/9/port/net.c:203,2081991/1116/sys/src/9/port/net.c:201,208
1991/1107    
			streamopen(c, np->devp); 
			if(np->protop && c->stream->devq->next->info != np->protop) 
				pushq(c->stream, np->protop); 
1991/1116    
			if(netown(np, id, u->p->user, omode&7) < 0) 
				error(Eperm); 
1991/1107    
			break; 
		} 
	} 
1991/1116/sys/src/9/port/net.c:170,1761991/1122/sys/src/9/port/net.c:170,176 (short | long)
1991/1107    
Chan * 
netopen(Chan *c, int omode, Network *np) 
{ 
1991/1115    
	int id; 
1991/1122    
	int id = 0; 
1991/1107    
 
	if(c->qid.path & CHDIR){ 
		if(omode != OREAD) 
1991/1122/sys/src/9/port/net.c:3,91992/0111/sys/src/9/port/net.c:3,9 (short | long)
Move error.h to ../port. Change errors to actual strings.
rsc Fri Mar 4 12:44:25 2005
1991/1107    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
1992/0111    
#include	"../port/error.h" 
1991/1107    
 
1991/1108    
#include	"fcall.h" 
 
1992/0111/sys/src/9/port/net.c:1,51992/0321/sys/src/9/port/net.c:1,5 (short | long)
Move lib.h to ../port.
rsc Fri Mar 4 12:44:25 2005
1991/1107    
#include	"u.h" 
#include	"lib.h" 
1992/0321    
#include	"../port/lib.h" 
1991/1107    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0321/sys/src/9/port/net.c:268,2721992/0416/sys/src/9/port/net.c:268,273 (short | long)
1991/1115    
void 
netdisown(Network *np, int id) 
{ 
1992/0416    
if(np == 0) panic("np == 0"); 
1991/1115    
	*np->prot[id].owner = 0; 
1991/1107    
} 
1992/0416/sys/src/9/port/net.c:5,121992/0619/sys/src/9/port/net.c:5,10 (short | long)
1991/1107    
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1991/1107    
 
1991/1108    
#include	"fcall.h" 
                 
1991/1107    
enum 
{ 
	Qlisten=	1, 
1992/0619/sys/src/9/port/net.c:15,201992/0623/sys/src/9/port/net.c:15,34 (short | long)
1991/1107    
}; 
 
/* 
1992/0623    
 *  find protection structure 
 */ 
static Netprot* 
findprot(Network *np, int id) 
{ 
	Netprot *p; 
 
	for(p = np->prot; p; p = p->next) 
		if(p->id == id) 
			break; 
	return p; 
} 
 
/* 
1991/1107    
 *  generate a 3 level directory 
 */ 
int 
1992/0619/sys/src/9/port/net.c:24,301992/0623/sys/src/9/port/net.c:38,43
1991/1107    
	char buf[32]; 
	Network *np = vp; 
1991/1115    
	int t; 
	int id; 
	Netprot *p; 
	int perm; 
	char *o; 
1992/0619/sys/src/9/port/net.c:61,691992/0623/sys/src/9/port/net.c:74,81
1991/1107    
	} 
 
	/* third level depends on the number of info files */ 
1991/1115    
	id = STREAMID(c->qid.path); 
	p = &np->prot[id]; 
	if(*p->owner){ 
1992/0623    
	p = findprot(np, STREAMID(c->qid.path)); 
	if(p && *p->owner){ 
1991/1115    
		o = p->owner; 
		perm = p->mode; 
	} else { 
1992/0619/sys/src/9/port/net.c:153,1591992/0623/sys/src/9/port/net.c:165,173
1991/1115    
	Dir dir; 
	Netprot *p; 
 
	p = &np->prot[STREAMID(c->qid.path)]; 
1992/0623    
	p = findprot(np, STREAMID(c->qid.path)); 
	if(p == 0) 
		error(Enonexist); 
1991/1115    
	lock(np); 
	if(strncmp(p->owner, u->p->user, NAMELEN)){ 
		unlock(np); 
1992/0619/sys/src/9/port/net.c:169,1741992/0623/sys/src/9/port/net.c:183,189
1991/1107    
netopen(Chan *c, int omode, Network *np) 
{ 
1991/1122    
	int id = 0; 
1992/0623    
	Netprot *p; 
1991/1107    
 
	if(c->qid.path & CHDIR){ 
		if(omode != OREAD) 
1992/0619/sys/src/9/port/net.c:199,2051992/0623/sys/src/9/port/net.c:214,222
1991/1107    
			streamopen(c, np->devp); 
			if(np->protop && c->stream->devq->next->info != np->protop) 
				pushq(c->stream, np->protop); 
1991/1116    
			if(netown(np, id, u->p->user, omode&7) < 0) 
1992/0623    
			p = findprot(np, id); 
if(p == 0) print("netopen: can't find %d\n", id); 
			if(netown(p, u->p->user, omode&7) < 0) 
1991/1116    
				error(Eperm); 
1991/1107    
			break; 
		} 
1992/0619/sys/src/9/port/net.c:227,2451992/0623/sys/src/9/port/net.c:244,279
1991/1107    
		error(Ebadusefd); 
 
1991/1108    
	(*np->info[t-Qinf].fill)(c, buf, sizeof(buf)); 
1991/1115    
	return stringread(a, n, buf, offset); 
1992/0623    
	return readstr(offset, a, n, buf); 
1991/1115    
} 
 
1992/0623    
void 
netadd(Network *np, Netprot *p, int id) 
{ 
	Netprot **l, *pp; 
 
	memset(p, 0, sizeof(Netprot)); 
	p->id = id; 
 
	l = &np->prot; 
	for(pp = np->prot; pp; pp = pp->next){ 
		if(pp->id == id) 
			panic("netadd"); 
		l = &pp->next; 
	} 
	*l = p; 
} 
 
Lock netlock; 
 
1991/1115    
int 
netown(Network *np, int id, char *o, int omode) 
1992/0623    
netown(Netprot *p, char *o, int omode) 
1991/1115    
{ 
	static int access[] = { 0400, 0200, 0600, 0100 }; 
	Netprot *p; 
	int mode; 
	int t; 
 
	p = &np->prot[id]; 
	lock(np); 
1992/0623    
	lock(&netlock); 
1991/1115    
	if(*p->owner){ 
		if(strncmp(o, p->owner, NAMELEN) == 0)	/* User */ 
			mode = p->mode; 
1992/0619/sys/src/9/port/net.c:250,2711992/0623/sys/src/9/port/net.c:284,304
1991/1115    
 
		t = access[omode&3]; 
		if((t & mode) == t){ 
			unlock(np); 
1992/0623    
			unlock(&netlock); 
1991/1115    
			return 0; 
		} else { 
			unlock(np); 
1992/0623    
			unlock(&netlock); 
1991/1115    
			return -1; 
		} 
	} 
	strncpy(p->owner, o, NAMELEN); 
	np->prot[id].mode = 0660; 
	unlock(np); 
1992/0623    
	p->mode = 0660; 
	unlock(&netlock); 
1991/1115    
	return 0; 
} 
 
void 
netdisown(Network *np, int id) 
1992/0623    
netdisown(Netprot *p) 
1991/1115    
{ 
1992/0416    
if(np == 0) panic("np == 0"); 
1991/1115    
	*np->prot[id].owner = 0; 
1992/0623    
	p->owner[0] = 0; 
1991/1107    
} 
1992/0623/sys/src/9/port/net.c:65,701992/0625/sys/src/9/port/net.c:65,72 (short | long)
1991/1107    
			q.path = Qclone; 
1991/1109    
			devdir(c, q, "clone", 0, eve, 0666, dp); 
1991/1114    
		}else if(i <= np->nconv){ 
1992/0625    
			if(findprot(np, i-1) == 0) 
				return 0; 
1991/1114    
			q.path = CHDIR|STREAMQID(i-1, Q3rd); 
			sprint(buf, "%d", i-1); 
1991/1115    
			devdir(c, q, buf, 0, eve, 0555, dp); 
1992/0623/sys/src/9/port/net.c:75,811992/0625/sys/src/9/port/net.c:77,85
1991/1107    
 
	/* third level depends on the number of info files */ 
1992/0623    
	p = findprot(np, STREAMID(c->qid.path)); 
	if(p && *p->owner){ 
1992/0625    
	if(p == 0) 
		return 0; 
	if(*p->owner){ 
1991/1115    
		o = p->owner; 
		perm = p->mode; 
	} else { 
1992/0623/sys/src/9/port/net.c:215,2211992/0625/sys/src/9/port/net.c:219,224
1991/1107    
			if(np->protop && c->stream->devq->next->info != np->protop) 
				pushq(c->stream, np->protop); 
1992/0623    
			p = findprot(np, id); 
if(p == 0) print("netopen: can't find %d\n", id); 
			if(netown(p, u->p->user, omode&7) < 0) 
1991/1116    
				error(Eperm); 
1991/1107    
			break; 
1992/0625/sys/src/9/port/net.c:42,471992/0711/sys/src/9/port/net.c:42,48 (short | long)
1991/1115    
	int perm; 
	char *o; 
1991/1107    
 
1992/0711    
	USED(ntab); 
1991/1107    
	q.vers = 0; 
 
	/* top level directory contains the name of the network */ 
1992/0711/sys/src/9/port/net.c:164,1891992/0819/sys/src/9/port/net.c:164,169 (short | long)
1991/1108    
		} 
} 
 
1991/1115    
void 
netwstat(Chan *c, char *db, Network *np) 
{ 
	Dir dir; 
	Netprot *p; 
                 
1992/0623    
	p = findprot(np, STREAMID(c->qid.path)); 
	if(p == 0) 
		error(Enonexist); 
1991/1115    
	lock(np); 
	if(strncmp(p->owner, u->p->user, NAMELEN)){ 
		unlock(np); 
		error(Eperm); 
	} 
	convM2D(db, &dir); 
	strncpy(p->owner, dir.uid, NAMELEN); 
	p->mode = dir.mode; 
	unlock(np); 
} 
                 
1991/1107    
Chan * 
netopen(Chan *c, int omode, Network *np) 
{ 
1992/0711/sys/src/9/port/net.c:305,3081992/0819/sys/src/9/port/net.c:285,320
1992/0623    
netdisown(Netprot *p) 
1991/1115    
{ 
1992/0623    
	p->owner[0] = 0; 
1992/0819    
} 
 
#undef	CHDIR	/* BUG */ 
#include "/sys/src/libc/9syscall/sys.h" 
 
void 
netwstat(Chan *c, char *db, Network *np) 
{ 
	Dir dir; 
	Netprot *p; 
 
	p = findprot(np, STREAMID(c->qid.path)); 
	if(p == 0) 
		error(Enonexist); 
	lock(np); 
 
	/* 
	 *  A network channel's ownership/permissions can be changed only if the 
	 *  wstat is by the owner or (HACK!) if it is performed using an fwstat. 
	 *  The latter allows processes started by a network listener to gain 
	 *  ownership of the connection.  The open file descriptor is used as 
	 *  a capability for the connection. 
	 */ 
	if(strncmp(p->owner, u->p->user, NAMELEN) != 0 && u->scallnr != FWSTAT){ 
		unlock(np); 
		error(Eperm); 
	} 
	convM2D(db, &dir); 
	strncpy(p->owner, dir.uid, NAMELEN); 
	p->mode = dir.mode; 
 
	unlock(np); 
1991/1107    
} 
1992/0819/sys/src/9/port/net.c:7,171992/0906/sys/src/9/port/net.c:7,17 (short | long)
1991/1107    
 
enum 
{ 
	Qlisten=	1, 
	Qclone=		2, 
	Q2nd=		3, 
	Q3rd=		4, 
1991/1108    
	Qinf=		5, 
1992/0906    
	Qlisten	= 1, 
	Qclone	= 2, 
	Q2nd	= 3, 
	Q3rd	= 4, 
	Qinf	= 5, 
1991/1107    
}; 
 
/* 
1992/0906/sys/src/9/port/net.c:151,1571992/1217/sys/src/9/port/net.c:151,157 (short | long)
1991/1108    
				convD2M(&dir, db); 
				return; 
			} 
			print("netstat %c %lux\n", devchar[c->type], c->qid.path); 
1992/1217    
			print("netstat %C %lux\n", devchar[c->type], c->qid.path); 
1991/1108    
			error(Enonexist); 
		case 0: 
			break; 
1992/1217/sys/src/9/port/net.c:157,1621993/0323/sys/src/9/port/net.c:157,164 (short | long)
1991/1108    
			break; 
		case 1: 
			if(eqqid(c->qid, dir.qid)){ 
1993/0323    
				if(c->flag&CMSG) 
					dir.mode |= CHMOUNT; 
1991/1108    
				convD2M(&dir, db); 
				return; 
			} 
1993/0323/sys/src/9/port/net.c:136,1691993/0330/sys/src/9/port/net.c:136,142 (short | long)
1991/1108    
void 
netstat(Chan *c, char *db, Network *np) 
{ 
	int i; 
	Dir dir; 
                 
	for(i=0;; i++) 
		switch(netgen(c, (Dirtab*)np, 0, i, &dir)){ 
		case -1: 
			/* 
			 * devices with interesting directories usually don't get 
			 * here, which is good because we've lost the name by now. 
			 */ 
			if(c->qid.path & CHDIR){ 
1991/1115    
				devdir(c, c->qid, ".", 0L, eve, CHDIR|0555, &dir); 
1991/1108    
				convD2M(&dir, db); 
				return; 
			} 
1992/1217    
			print("netstat %C %lux\n", devchar[c->type], c->qid.path); 
1991/1108    
			error(Enonexist); 
		case 0: 
			break; 
		case 1: 
			if(eqqid(c->qid, dir.qid)){ 
1993/0323    
				if(c->flag&CMSG) 
					dir.mode |= CHMOUNT; 
1991/1108    
				convD2M(&dir, db); 
				return; 
			} 
			break; 
		} 
1993/0330    
	devstat(c, db, (Dirtab*)np, 1, netgen); 
1991/1108    
} 
 
1991/1107    
Chan * 
1993/0330/sys/src/9/port/net.c:136,1421993/0501/sys/src/9/port/net.c:136,169 (short | long)
1991/1108    
void 
netstat(Chan *c, char *db, Network *np) 
{ 
1993/0330    
	devstat(c, db, (Dirtab*)np, 1, netgen); 
1993/0501    
	int i; 
	Dir dir; 
 
	for(i=0;; i++) 
		switch(netgen(c, (Dirtab*)np, 0, i, &dir)){ 
		case -1: 
		/* 
		 * devices with interesting directories usually don't get 
		 * here, which is good because we've lost the name by now. 
		 */ 
			if(c->qid.path & CHDIR){ 
				devdir(c, c->qid, c->path->elem, 0L, eve, CHDIR|0555, &dir); 
				convD2M(&dir, db); 
				return; 
			} 
			print("netstat %C %lux\n", devchar[c->type], c->qid.path); 
			error(Enonexist); 
		case 0: 
			break; 
		case 1: 
			if(eqqid(c->qid, dir.qid)){ 
				if(c->flag&CMSG) 
					dir.mode |= CHMOUNT; 
				convD2M(&dir, db); 
				return; 
			} 
			break; 
		} 
1991/1108    
} 
 
1991/1107    
Chan * 
1993/0330/sys/src/9/port/net.c:159,1681993/0501/sys/src/9/port/net.c:186,197
1991/1115    
			id = (*np->listen)(c); 
			streamclose(c); 
			c->qid.path = STREAMQID(id, Sctlqid); 
1993/0501    
			ptclone(c, 1, id); 
1991/1107    
			break; 
		case Qclone: 
1991/1115    
			id = (*np->clone)(c); 
			c->qid.path = STREAMQID(id, Sctlqid); 
1993/0501    
			ptclone(c, 0, id); 
1991/1107    
			break; 
		default: 
			if(omode != OREAD) 
1993/0330/sys/src/9/port/net.c:175,1811993/0501/sys/src/9/port/net.c:204,210
1991/1107    
			if(np->protop && c->stream->devq->next->info != np->protop) 
				pushq(c->stream, np->protop); 
1992/0623    
			p = findprot(np, id); 
			if(netown(p, u->p->user, omode&7) < 0) 
1993/0501    
			if(netown(p, up->user, omode&7) < 0) 
1991/1116    
				error(Eperm); 
1991/1107    
			break; 
		} 
1993/0330/sys/src/9/port/net.c:283,2891993/0501/sys/src/9/port/net.c:312,318
1992/0819    
	 *  ownership of the connection.  The open file descriptor is used as 
	 *  a capability for the connection. 
	 */ 
	if(strncmp(p->owner, u->p->user, NAMELEN) != 0 && u->scallnr != FWSTAT){ 
1993/0501    
	if(strncmp(p->owner, up->user, NAMELEN) != 0 && up->scallnr != FWSTAT){ 
1992/0819    
		unlock(np); 
		error(Eperm); 
	} 
1993/0501/sys/src/9/port/net.c:180,1951993/0508/sys/src/9/port/net.c:180,194 (short | long)
1991/1107    
		case Sdataqid: 
		case Sctlqid: 
1991/1115    
			id = STREAMID(c->qid.path); 
1993/0508    
			id = (*np->open)(c, id); 
1991/1107    
			break; 
		case Qlisten: 
1991/1115    
			streamopen(c, np->devp); 
			id = (*np->listen)(c); 
			streamclose(c); 
			c->qid.path = STREAMQID(id, Sctlqid); 
1993/0501    
			ptclone(c, 1, id); 
1991/1107    
			break; 
		case Qclone: 
1991/1115    
			id = (*np->clone)(c); 
1993/0508    
			id = (*np->open)(c, -1); 
1991/1115    
			c->qid.path = STREAMQID(id, Sctlqid); 
1993/0501    
			ptclone(c, 0, id); 
1991/1107    
			break; 
1993/0501/sys/src/9/port/net.c:200,2081993/0508/sys/src/9/port/net.c:199,204
1991/1107    
		switch(STREAMTYPE(c->qid.path)){ 
		case Sdataqid: 
		case Sctlqid: 
			streamopen(c, np->devp); 
			if(np->protop && c->stream->devq->next->info != np->protop) 
				pushq(c->stream, np->protop); 
1992/0623    
			p = findprot(np, id); 
1993/0501    
			if(netown(p, up->user, omode&7) < 0) 
1991/1116    
				error(Eperm); 
1993/0501/sys/src/9/port/net.c:221,2291993/0508/sys/src/9/port/net.c:217,222
1991/1108    
	int t; 
1991/1107    
	char buf[256]; 
 
	if(c->stream) 
		return streamread(c, a, n); 
                 
	if(c->qid.path&CHDIR) 
		return devdirread(c, a, n, (Dirtab*)np, 0, netgen); 
 
1993/0501/sys/src/9/port/net.c:242,2471993/0508/sys/src/9/port/net.c:235,241
1992/0623    
 
	memset(p, 0, sizeof(Netprot)); 
	p->id = id; 
1993/0508    
	p->net = np; 
1992/0623    
 
	l = &np->prot; 
	for(pp = np->prot; pp; pp = pp->next){ 
1993/0508/sys/src/9/port/net.c:60,661993/0522/sys/src/9/port/net.c:60,66 (short | long)
1991/1107    
	} 
 
	/* second level contains clone plus all the conversations */ 
1991/1115    
	t = STREAMTYPE(c->qid.path); 
1993/0522    
	t = NETTYPE(c->qid.path); 
1991/1115    
	if(t == Q2nd || t == Qclone){ 
1991/1107    
		if(i == 0){ 
			q.path = Qclone; 
1993/0508/sys/src/9/port/net.c:68,741993/0522/sys/src/9/port/net.c:68,74
1991/1114    
		}else if(i <= np->nconv){ 
1992/0625    
			if(findprot(np, i-1) == 0) 
				return 0; 
1991/1114    
			q.path = CHDIR|STREAMQID(i-1, Q3rd); 
1993/0522    
			q.path = CHDIR|NETQID(i-1, Q3rd); 
1991/1114    
			sprint(buf, "%d", i-1); 
1991/1115    
			devdir(c, q, buf, 0, eve, 0555, dp); 
1991/1107    
		}else 
1993/0508/sys/src/9/port/net.c:77,831993/0522/sys/src/9/port/net.c:77,83
1991/1107    
	} 
 
	/* third level depends on the number of info files */ 
1992/0623    
	p = findprot(np, STREAMID(c->qid.path)); 
1993/0522    
	p = findprot(np, NETID(c->qid.path)); 
1992/0625    
	if(p == 0) 
		return 0; 
	if(*p->owner){ 
1993/0508/sys/src/9/port/net.c:89,1051993/0522/sys/src/9/port/net.c:89,105
1991/1115    
	} 
1991/1107    
	switch(i){ 
	case 0: 
		q.path = STREAMQID(STREAMID(c->qid.path), Sdataqid); 
1993/0522    
		q.path = NETQID(NETID(c->qid.path), Ndataqid); 
1991/1115    
		devdir(c, q, "data", 0, o, perm, dp); 
1991/1107    
		break; 
	case 1: 
		q.path = STREAMQID(STREAMID(c->qid.path), Sctlqid); 
1993/0522    
		q.path = NETQID(NETID(c->qid.path), Nctlqid); 
1991/1115    
		devdir(c, q, "ctl", 0, o, perm, dp); 
1991/1107    
		break; 
	case 2: 
		if(np->listen == 0) 
			return 0; 
		q.path = STREAMQID(STREAMID(c->qid.path), Qlisten); 
1993/0522    
		q.path = NETQID(NETID(c->qid.path), Qlisten); 
1991/1115    
		devdir(c, q, "listen", 0, o, perm, dp); 
1991/1107    
		break; 
	default: 
1993/0508/sys/src/9/port/net.c:106,1121993/0522/sys/src/9/port/net.c:106,112
1991/1107    
		i -= 3; 
1991/1108    
		if(i >= np->ninfo) 
			return -1; 
		q.path = STREAMQID(STREAMID(c->qid.path), Qinf+i); 
1993/0522    
		q.path = NETQID(NETID(c->qid.path), Qinf+i); 
1991/1115    
		devdir(c, q, np->info[i].name, 0, eve, 0444, dp); 
1991/1108    
		break; 
1991/1107    
	} 
1993/0508/sys/src/9/port/net.c:117,1231993/0522/sys/src/9/port/net.c:117,123
1991/1108    
netwalk(Chan *c, char *name, Network *np) 
{ 
	if(strcmp(name, "..") == 0) { 
		switch(STREAMTYPE(c->qid.path)){ 
1993/0522    
		switch(NETTYPE(c->qid.path)){ 
1991/1108    
		case Q2nd: 
			c->qid.path = CHDIR; 
			break; 
1993/0508/sys/src/9/port/net.c:176,1951993/0522/sys/src/9/port/net.c:176,195
1991/1107    
		if(omode != OREAD) 
			error(Eperm); 
	} else { 
		switch(STREAMTYPE(c->qid.path)){ 
		case Sdataqid: 
		case Sctlqid: 
1991/1115    
			id = STREAMID(c->qid.path); 
1993/0522    
		switch(NETTYPE(c->qid.path)){ 
		case Ndataqid: 
		case Nctlqid: 
			id = NETID(c->qid.path); 
1993/0508    
			id = (*np->open)(c, id); 
1991/1107    
			break; 
		case Qlisten: 
1991/1115    
			id = (*np->listen)(c); 
			c->qid.path = STREAMQID(id, Sctlqid); 
1993/0522    
			c->qid.path = NETQID(id, Nctlqid); 
1993/0501    
			ptclone(c, 1, id); 
1991/1107    
			break; 
		case Qclone: 
1993/0508    
			id = (*np->open)(c, -1); 
1991/1115    
			c->qid.path = STREAMQID(id, Sctlqid); 
1993/0522    
			c->qid.path = NETQID(id, Nctlqid); 
1993/0501    
			ptclone(c, 0, id); 
1991/1107    
			break; 
		default: 
1993/0508/sys/src/9/port/net.c:196,2041993/0522/sys/src/9/port/net.c:196,204
1991/1107    
			if(omode != OREAD) 
				error(Ebadarg); 
		} 
		switch(STREAMTYPE(c->qid.path)){ 
		case Sdataqid: 
		case Sctlqid: 
1993/0522    
		switch(NETTYPE(c->qid.path)){ 
		case Ndataqid: 
		case Nctlqid: 
1992/0623    
			p = findprot(np, id); 
1993/0501    
			if(netown(p, up->user, omode&7) < 0) 
1991/1116    
				error(Eperm); 
1993/0508/sys/src/9/port/net.c:220,2261993/0522/sys/src/9/port/net.c:220,229
1991/1107    
	if(c->qid.path&CHDIR) 
		return devdirread(c, a, n, (Dirtab*)np, 0, netgen); 
 
1991/1108    
	t = STREAMTYPE(c->qid.path); 
1993/0522    
	t = NETTYPE(c->qid.path); 
	if(t == Nctlqid) 
		readnum(offset, a, n, NETID(c->qid.path), NUMSIZE); 
 
1991/1108    
	if(t < Qinf || t >= Qinf + np->ninfo) 
1991/1107    
		error(Ebadusefd); 
 
1993/0508/sys/src/9/port/net.c:294,3001993/0522/sys/src/9/port/net.c:297,303
1992/0819    
	Dir dir; 
	Netprot *p; 
 
	p = findprot(np, STREAMID(c->qid.path)); 
1993/0522    
	p = findprot(np, NETID(c->qid.path)); 
1992/0819    
	if(p == 0) 
		error(Enonexist); 
	lock(np); 
1993/0522/sys/src/9/port/net.c:32,381995/0804/sys/src/9/port/net.c:32,38 (short | long)
1991/1107    
 *  generate a 3 level directory 
 */ 
int 
netgen(Chan *c, void *vp, int ntab, int i, Dir *dp) 
1995/0804    
netgen(Chan *c, void *vp, int, int i, Dir *dp) 
1991/1107    
{ 
	Qid q; 
	char buf[32]; 
1993/0522/sys/src/9/port/net.c:42,481995/0804/sys/src/9/port/net.c:42,47
1991/1115    
	int perm; 
	char *o; 
1991/1107    
 
1992/0711    
	USED(ntab); 
1991/1107    
	q.vers = 0; 
 
	/* top level directory contains the name of the network */ 
1995/0804/sys/src/9/port/net.c:1,3201996/0531/sys/src/9/port/net.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:31:31 2005
1991/1107    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1991/1107    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
1992/0111    
#include	"../port/error.h" 
1991/1107    
                 
enum 
{ 
1992/0906    
	Qlisten	= 1, 
	Qclone	= 2, 
	Q2nd	= 3, 
	Q3rd	= 4, 
	Qinf	= 5, 
1991/1107    
}; 
                 
/* 
1992/0623    
 *  find protection structure 
 */ 
static Netprot* 
findprot(Network *np, int id) 
{ 
	Netprot *p; 
                 
	for(p = np->prot; p; p = p->next) 
		if(p->id == id) 
			break; 
	return p; 
} 
                 
/* 
1991/1107    
 *  generate a 3 level directory 
 */ 
int 
1995/0804    
netgen(Chan *c, void *vp, int, int i, Dir *dp) 
1991/1107    
{ 
	Qid q; 
	char buf[32]; 
	Network *np = vp; 
1991/1115    
	int t; 
	Netprot *p; 
	int perm; 
	char *o; 
1991/1107    
                 
	q.vers = 0; 
                 
	/* top level directory contains the name of the network */ 
	if(c->qid.path == CHDIR){ 
		switch(i){ 
		case 0: 
			q.path = CHDIR | Q2nd; 
			strcpy(buf, np->name); 
1991/1115    
			devdir(c, q, buf, 0, eve, 0555, dp); 
1991/1107    
			break; 
		default: 
			return -1; 
		} 
		return 1; 
	} 
                 
	/* second level contains clone plus all the conversations */ 
1993/0522    
	t = NETTYPE(c->qid.path); 
1991/1115    
	if(t == Q2nd || t == Qclone){ 
1991/1107    
		if(i == 0){ 
			q.path = Qclone; 
1991/1109    
			devdir(c, q, "clone", 0, eve, 0666, dp); 
1991/1114    
		}else if(i <= np->nconv){ 
1992/0625    
			if(findprot(np, i-1) == 0) 
				return 0; 
1993/0522    
			q.path = CHDIR|NETQID(i-1, Q3rd); 
1991/1114    
			sprint(buf, "%d", i-1); 
1991/1115    
			devdir(c, q, buf, 0, eve, 0555, dp); 
1991/1107    
		}else 
			return -1; 
		return 1; 
	} 
                 
	/* third level depends on the number of info files */ 
1993/0522    
	p = findprot(np, NETID(c->qid.path)); 
1992/0625    
	if(p == 0) 
		return 0; 
	if(*p->owner){ 
1991/1115    
		o = p->owner; 
		perm = p->mode; 
	} else { 
		o = eve; 
		perm = 0666; 
	} 
1991/1107    
	switch(i){ 
	case 0: 
1993/0522    
		q.path = NETQID(NETID(c->qid.path), Ndataqid); 
1991/1115    
		devdir(c, q, "data", 0, o, perm, dp); 
1991/1107    
		break; 
	case 1: 
1993/0522    
		q.path = NETQID(NETID(c->qid.path), Nctlqid); 
1991/1115    
		devdir(c, q, "ctl", 0, o, perm, dp); 
1991/1107    
		break; 
	case 2: 
		if(np->listen == 0) 
			return 0; 
1993/0522    
		q.path = NETQID(NETID(c->qid.path), Qlisten); 
1991/1115    
		devdir(c, q, "listen", 0, o, perm, dp); 
1991/1107    
		break; 
	default: 
		i -= 3; 
1991/1108    
		if(i >= np->ninfo) 
			return -1; 
1993/0522    
		q.path = NETQID(NETID(c->qid.path), Qinf+i); 
1991/1115    
		devdir(c, q, np->info[i].name, 0, eve, 0444, dp); 
1991/1108    
		break; 
1991/1107    
	} 
	return 1; 
} 
                 
1991/1108    
int	  
netwalk(Chan *c, char *name, Network *np) 
{ 
	if(strcmp(name, "..") == 0) { 
1993/0522    
		switch(NETTYPE(c->qid.path)){ 
1991/1108    
		case Q2nd: 
			c->qid.path = CHDIR; 
			break; 
		case Q3rd: 
			c->qid.path = CHDIR|Q2nd; 
			break; 
		default: 
			panic("netwalk %lux", c->qid.path); 
		} 
		return 1; 
	} 
                 
	return devwalk(c, name, (Dirtab*)np, 0, netgen); 
} 
                 
void 
netstat(Chan *c, char *db, Network *np) 
{ 
1993/0501    
	int i; 
	Dir dir; 
                 
	for(i=0;; i++) 
		switch(netgen(c, (Dirtab*)np, 0, i, &dir)){ 
		case -1: 
		/* 
		 * devices with interesting directories usually don't get 
		 * here, which is good because we've lost the name by now. 
		 */ 
			if(c->qid.path & CHDIR){ 
				devdir(c, c->qid, c->path->elem, 0L, eve, CHDIR|0555, &dir); 
				convD2M(&dir, db); 
				return; 
			} 
			print("netstat %C %lux\n", devchar[c->type], c->qid.path); 
			error(Enonexist); 
		case 0: 
			break; 
		case 1: 
			if(eqqid(c->qid, dir.qid)){ 
				if(c->flag&CMSG) 
					dir.mode |= CHMOUNT; 
				convD2M(&dir, db); 
				return; 
			} 
			break; 
		} 
1991/1108    
} 
                 
1991/1107    
Chan * 
netopen(Chan *c, int omode, Network *np) 
{ 
1991/1122    
	int id = 0; 
1992/0623    
	Netprot *p; 
1991/1107    
                 
	if(c->qid.path & CHDIR){ 
		if(omode != OREAD) 
			error(Eperm); 
	} else { 
1993/0522    
		switch(NETTYPE(c->qid.path)){ 
		case Ndataqid: 
		case Nctlqid: 
			id = NETID(c->qid.path); 
1993/0508    
			id = (*np->open)(c, id); 
1991/1107    
			break; 
		case Qlisten: 
1991/1115    
			id = (*np->listen)(c); 
1993/0522    
			c->qid.path = NETQID(id, Nctlqid); 
1993/0501    
			ptclone(c, 1, id); 
1991/1107    
			break; 
		case Qclone: 
1993/0508    
			id = (*np->open)(c, -1); 
1993/0522    
			c->qid.path = NETQID(id, Nctlqid); 
1993/0501    
			ptclone(c, 0, id); 
1991/1107    
			break; 
		default: 
			if(omode != OREAD) 
				error(Ebadarg); 
		} 
1993/0522    
		switch(NETTYPE(c->qid.path)){ 
		case Ndataqid: 
		case Nctlqid: 
1992/0623    
			p = findprot(np, id); 
1993/0501    
			if(netown(p, up->user, omode&7) < 0) 
1991/1116    
				error(Eperm); 
1991/1107    
			break; 
		} 
	} 
	c->mode = openmode(omode); 
	c->flag |= COPEN; 
	c->offset = 0; 
	return c; 
} 
                 
long 
netread(Chan *c, void *a, long n, ulong offset, Network *np) 
{ 
1991/1108    
	int t; 
1991/1107    
	char buf[256]; 
                 
	if(c->qid.path&CHDIR) 
		return devdirread(c, a, n, (Dirtab*)np, 0, netgen); 
                 
1993/0522    
	t = NETTYPE(c->qid.path); 
	if(t == Nctlqid) 
		readnum(offset, a, n, NETID(c->qid.path), NUMSIZE); 
                 
1991/1108    
	if(t < Qinf || t >= Qinf + np->ninfo) 
1991/1107    
		error(Ebadusefd); 
                 
1991/1108    
	(*np->info[t-Qinf].fill)(c, buf, sizeof(buf)); 
1992/0623    
	return readstr(offset, a, n, buf); 
1991/1115    
} 
                 
1992/0623    
void 
netadd(Network *np, Netprot *p, int id) 
{ 
	Netprot **l, *pp; 
                 
	memset(p, 0, sizeof(Netprot)); 
	p->id = id; 
1993/0508    
	p->net = np; 
1992/0623    
                 
	l = &np->prot; 
	for(pp = np->prot; pp; pp = pp->next){ 
		if(pp->id == id) 
			panic("netadd"); 
		l = &pp->next; 
	} 
	*l = p; 
} 
                 
Lock netlock; 
                 
1991/1115    
int 
1992/0623    
netown(Netprot *p, char *o, int omode) 
1991/1115    
{ 
	static int access[] = { 0400, 0200, 0600, 0100 }; 
	int mode; 
	int t; 
                 
1992/0623    
	lock(&netlock); 
1991/1115    
	if(*p->owner){ 
		if(strncmp(o, p->owner, NAMELEN) == 0)	/* User */ 
			mode = p->mode; 
		else if(strncmp(o, eve, NAMELEN) == 0)	/* Bootes is group */ 
			mode = p->mode<<3; 
		else 
			mode = p->mode<<6;		/* Other */ 
                 
		t = access[omode&3]; 
		if((t & mode) == t){ 
1992/0623    
			unlock(&netlock); 
1991/1115    
			return 0; 
		} else { 
1992/0623    
			unlock(&netlock); 
1991/1115    
			return -1; 
		} 
	} 
	strncpy(p->owner, o, NAMELEN); 
1992/0623    
	p->mode = 0660; 
	unlock(&netlock); 
1991/1115    
	return 0; 
} 
                 
void 
1992/0623    
netdisown(Netprot *p) 
1991/1115    
{ 
1992/0623    
	p->owner[0] = 0; 
1992/0819    
} 
                 
#undef	CHDIR	/* BUG */ 
#include "/sys/src/libc/9syscall/sys.h" 
                 
void 
netwstat(Chan *c, char *db, Network *np) 
{ 
	Dir dir; 
	Netprot *p; 
                 
1993/0522    
	p = findprot(np, NETID(c->qid.path)); 
1992/0819    
	if(p == 0) 
		error(Enonexist); 
	lock(np); 
                 
	/* 
	 *  A network channel's ownership/permissions can be changed only if the 
	 *  wstat is by the owner or (HACK!) if it is performed using an fwstat. 
	 *  The latter allows processes started by a network listener to gain 
	 *  ownership of the connection.  The open file descriptor is used as 
	 *  a capability for the connection. 
	 */ 
1993/0501    
	if(strncmp(p->owner, up->user, NAMELEN) != 0 && up->scallnr != FWSTAT){ 
1992/0819    
		unlock(np); 
		error(Eperm); 
	} 
	convM2D(db, &dir); 
	strncpy(p->owner, dir.uid, NAMELEN); 
	p->mode = dir.mode; 
                 
	unlock(np); 
1991/1107    
} 


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