xref: /inferno-os/emu/port/devpipe.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth #include	"dat.h"
2*37da2899SCharles.Forsyth #include	"fns.h"
3*37da2899SCharles.Forsyth #include	"error.h"
4*37da2899SCharles.Forsyth #include	<interp.h>
5*37da2899SCharles.Forsyth 
6*37da2899SCharles.Forsyth #define NETTYPE(x)	((ulong)(x)&0x1f)
7*37da2899SCharles.Forsyth #define NETID(x)	(((ulong)(x))>>5)
8*37da2899SCharles.Forsyth #define NETQID(i,t)	(((i)<<5)|(t))
9*37da2899SCharles.Forsyth 
10*37da2899SCharles.Forsyth typedef struct Pipe	Pipe;
11*37da2899SCharles.Forsyth struct Pipe
12*37da2899SCharles.Forsyth {
13*37da2899SCharles.Forsyth 	QLock	l;
14*37da2899SCharles.Forsyth 	Pipe*	next;
15*37da2899SCharles.Forsyth 	int	ref;
16*37da2899SCharles.Forsyth 	ulong	path;
17*37da2899SCharles.Forsyth 	Queue*	q[2];
18*37da2899SCharles.Forsyth 	int	qref[2];
19*37da2899SCharles.Forsyth 	Dirtab*	pipedir;
20*37da2899SCharles.Forsyth 	char*	user;
21*37da2899SCharles.Forsyth };
22*37da2899SCharles.Forsyth 
23*37da2899SCharles.Forsyth static struct
24*37da2899SCharles.Forsyth {
25*37da2899SCharles.Forsyth 	Lock	l;
26*37da2899SCharles.Forsyth 	ulong	path;
27*37da2899SCharles.Forsyth 	int	pipeqsize;
28*37da2899SCharles.Forsyth } pipealloc;
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth enum
31*37da2899SCharles.Forsyth {
32*37da2899SCharles.Forsyth 	Qdir,
33*37da2899SCharles.Forsyth 	Qdata0,
34*37da2899SCharles.Forsyth 	Qdata1
35*37da2899SCharles.Forsyth };
36*37da2899SCharles.Forsyth 
37*37da2899SCharles.Forsyth Dirtab pipedir[] =
38*37da2899SCharles.Forsyth {
39*37da2899SCharles.Forsyth 	".",		{Qdir,0,QTDIR},	0,		DMDIR|0500,
40*37da2899SCharles.Forsyth 	"data",		{Qdata0},	0,			0660,
41*37da2899SCharles.Forsyth 	"data1",	{Qdata1},	0,			0660,
42*37da2899SCharles.Forsyth };
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth static void
freepipe(Pipe * p)45*37da2899SCharles.Forsyth freepipe(Pipe *p)
46*37da2899SCharles.Forsyth {
47*37da2899SCharles.Forsyth 	if(p != nil){
48*37da2899SCharles.Forsyth 		free(p->user);
49*37da2899SCharles.Forsyth 		free(p->q[0]);
50*37da2899SCharles.Forsyth 		free(p->q[1]);
51*37da2899SCharles.Forsyth 		free(p->pipedir);
52*37da2899SCharles.Forsyth 		free(p);
53*37da2899SCharles.Forsyth 	}
54*37da2899SCharles.Forsyth }
55*37da2899SCharles.Forsyth 
56*37da2899SCharles.Forsyth static void
pipeinit(void)57*37da2899SCharles.Forsyth pipeinit(void)
58*37da2899SCharles.Forsyth {
59*37da2899SCharles.Forsyth 	pipealloc.pipeqsize = 32*1024;
60*37da2899SCharles.Forsyth }
61*37da2899SCharles.Forsyth 
62*37da2899SCharles.Forsyth /*
63*37da2899SCharles.Forsyth  *  create a pipe, no streams are created until an open
64*37da2899SCharles.Forsyth  */
65*37da2899SCharles.Forsyth static Chan*
pipeattach(char * spec)66*37da2899SCharles.Forsyth pipeattach(char *spec)
67*37da2899SCharles.Forsyth {
68*37da2899SCharles.Forsyth 	Pipe *p;
69*37da2899SCharles.Forsyth 	Chan *c;
70*37da2899SCharles.Forsyth 
71*37da2899SCharles.Forsyth 	c = devattach('|', spec);
72*37da2899SCharles.Forsyth 	p = malloc(sizeof(Pipe));
73*37da2899SCharles.Forsyth 	if(p == 0)
74*37da2899SCharles.Forsyth 		error(Enomem);
75*37da2899SCharles.Forsyth 	if(waserror()){
76*37da2899SCharles.Forsyth 		freepipe(p);
77*37da2899SCharles.Forsyth 		nexterror();
78*37da2899SCharles.Forsyth 	}
79*37da2899SCharles.Forsyth 	p->pipedir = malloc(sizeof(pipedir));
80*37da2899SCharles.Forsyth 	if (p->pipedir == 0)
81*37da2899SCharles.Forsyth 		error(Enomem);
82*37da2899SCharles.Forsyth 	memmove(p->pipedir, pipedir, sizeof(pipedir));
83*37da2899SCharles.Forsyth 	kstrdup(&p->user, up->env->user);
84*37da2899SCharles.Forsyth 	p->ref = 1;
85*37da2899SCharles.Forsyth 
86*37da2899SCharles.Forsyth 	p->q[0] = qopen(pipealloc.pipeqsize, 0, 0, 0);
87*37da2899SCharles.Forsyth 	if(p->q[0] == 0)
88*37da2899SCharles.Forsyth 		error(Enomem);
89*37da2899SCharles.Forsyth 	p->q[1] = qopen(pipealloc.pipeqsize, 0, 0, 0);
90*37da2899SCharles.Forsyth 	if(p->q[1] == 0)
91*37da2899SCharles.Forsyth 		error(Enomem);
92*37da2899SCharles.Forsyth 	poperror();
93*37da2899SCharles.Forsyth 
94*37da2899SCharles.Forsyth 	lock(&pipealloc.l);
95*37da2899SCharles.Forsyth 	p->path = ++pipealloc.path;
96*37da2899SCharles.Forsyth 	unlock(&pipealloc.l);
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth 	c->qid.path = NETQID(2*p->path, Qdir);
99*37da2899SCharles.Forsyth 	c->qid.vers = 0;
100*37da2899SCharles.Forsyth 	c->qid.type = QTDIR;
101*37da2899SCharles.Forsyth 	c->aux = p;
102*37da2899SCharles.Forsyth 	c->dev = 0;
103*37da2899SCharles.Forsyth 	return c;
104*37da2899SCharles.Forsyth }
105*37da2899SCharles.Forsyth 
106*37da2899SCharles.Forsyth static int
pipegen(Chan * c,char * name,Dirtab * tab,int ntab,int i,Dir * dp)107*37da2899SCharles.Forsyth pipegen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
108*37da2899SCharles.Forsyth {
109*37da2899SCharles.Forsyth 	int id, len;
110*37da2899SCharles.Forsyth 	Qid qid;
111*37da2899SCharles.Forsyth 	Pipe *p;
112*37da2899SCharles.Forsyth 
113*37da2899SCharles.Forsyth 	USED(name);
114*37da2899SCharles.Forsyth 	if(i == DEVDOTDOT){
115*37da2899SCharles.Forsyth 		devdir(c, c->qid, "#|", 0, eve, 0555, dp);
116*37da2899SCharles.Forsyth 		return 1;
117*37da2899SCharles.Forsyth 	}
118*37da2899SCharles.Forsyth 	i++;	/* skip . */
119*37da2899SCharles.Forsyth 	if(tab==0 || i>=ntab)
120*37da2899SCharles.Forsyth 		return -1;
121*37da2899SCharles.Forsyth 	tab += i;
122*37da2899SCharles.Forsyth 	p = c->aux;
123*37da2899SCharles.Forsyth 	switch(NETTYPE(tab->qid.path)){
124*37da2899SCharles.Forsyth 	case Qdata0:
125*37da2899SCharles.Forsyth 		len = qlen(p->q[0]);
126*37da2899SCharles.Forsyth 		break;
127*37da2899SCharles.Forsyth 	case Qdata1:
128*37da2899SCharles.Forsyth 		len = qlen(p->q[1]);
129*37da2899SCharles.Forsyth 		break;
130*37da2899SCharles.Forsyth 	default:
131*37da2899SCharles.Forsyth 		len = tab->length;
132*37da2899SCharles.Forsyth 		break;
133*37da2899SCharles.Forsyth 	}
134*37da2899SCharles.Forsyth 	id = NETID(c->qid.path);
135*37da2899SCharles.Forsyth 	qid.path = NETQID(id, tab->qid.path);
136*37da2899SCharles.Forsyth 	qid.vers = 0;
137*37da2899SCharles.Forsyth 	qid.type = QTFILE;
138*37da2899SCharles.Forsyth 	devdir(c, qid, tab->name, len, eve, tab->perm, dp);
139*37da2899SCharles.Forsyth 	return 1;
140*37da2899SCharles.Forsyth }
141*37da2899SCharles.Forsyth 
142*37da2899SCharles.Forsyth static Walkqid*
pipewalk(Chan * c,Chan * nc,char ** name,int nname)143*37da2899SCharles.Forsyth pipewalk(Chan *c, Chan *nc, char **name, int nname)
144*37da2899SCharles.Forsyth {
145*37da2899SCharles.Forsyth 	Walkqid *wq;
146*37da2899SCharles.Forsyth 	Pipe *p;
147*37da2899SCharles.Forsyth 
148*37da2899SCharles.Forsyth 	p = c->aux;
149*37da2899SCharles.Forsyth 	wq = devwalk(c, nc, name, nname, p->pipedir, nelem(pipedir), pipegen);
150*37da2899SCharles.Forsyth 	if(wq != nil && wq->clone != nil && wq->clone != c){
151*37da2899SCharles.Forsyth 		qlock(&p->l);
152*37da2899SCharles.Forsyth 		p->ref++;
153*37da2899SCharles.Forsyth 		if(c->flag & COPEN){
154*37da2899SCharles.Forsyth 			switch(NETTYPE(c->qid.path)){
155*37da2899SCharles.Forsyth 			case Qdata0:
156*37da2899SCharles.Forsyth 				p->qref[0]++;
157*37da2899SCharles.Forsyth 				break;
158*37da2899SCharles.Forsyth 			case Qdata1:
159*37da2899SCharles.Forsyth 				p->qref[1]++;
160*37da2899SCharles.Forsyth 				break;
161*37da2899SCharles.Forsyth 			}
162*37da2899SCharles.Forsyth 		}
163*37da2899SCharles.Forsyth 		qunlock(&p->l);
164*37da2899SCharles.Forsyth 	}
165*37da2899SCharles.Forsyth 	return wq;
166*37da2899SCharles.Forsyth }
167*37da2899SCharles.Forsyth 
168*37da2899SCharles.Forsyth static int
pipestat(Chan * c,uchar * db,int n)169*37da2899SCharles.Forsyth pipestat(Chan *c, uchar *db, int n)
170*37da2899SCharles.Forsyth {
171*37da2899SCharles.Forsyth 	Pipe *p;
172*37da2899SCharles.Forsyth 	Dir dir;
173*37da2899SCharles.Forsyth 	Dirtab *tab;
174*37da2899SCharles.Forsyth 
175*37da2899SCharles.Forsyth 	p = c->aux;
176*37da2899SCharles.Forsyth 	tab = p->pipedir;
177*37da2899SCharles.Forsyth 
178*37da2899SCharles.Forsyth 	switch(NETTYPE(c->qid.path)){
179*37da2899SCharles.Forsyth 	case Qdir:
180*37da2899SCharles.Forsyth 		devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir);
181*37da2899SCharles.Forsyth 		break;
182*37da2899SCharles.Forsyth 	case Qdata0:
183*37da2899SCharles.Forsyth 		devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, tab[1].perm, &dir);
184*37da2899SCharles.Forsyth 		break;
185*37da2899SCharles.Forsyth 	case Qdata1:
186*37da2899SCharles.Forsyth 		devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, tab[2].perm, &dir);
187*37da2899SCharles.Forsyth 		break;
188*37da2899SCharles.Forsyth 	default:
189*37da2899SCharles.Forsyth 		panic("pipestat");
190*37da2899SCharles.Forsyth 	}
191*37da2899SCharles.Forsyth 	n = convD2M(&dir, db, n);
192*37da2899SCharles.Forsyth 	if(n < BIT16SZ)
193*37da2899SCharles.Forsyth 		error(Eshortstat);
194*37da2899SCharles.Forsyth 	return n;
195*37da2899SCharles.Forsyth }
196*37da2899SCharles.Forsyth 
197*37da2899SCharles.Forsyth /*
198*37da2899SCharles.Forsyth  *  if the stream doesn't exist, create it
199*37da2899SCharles.Forsyth  */
200*37da2899SCharles.Forsyth static Chan*
pipeopen(Chan * c,int omode)201*37da2899SCharles.Forsyth pipeopen(Chan *c, int omode)
202*37da2899SCharles.Forsyth {
203*37da2899SCharles.Forsyth 	Pipe *p;
204*37da2899SCharles.Forsyth 
205*37da2899SCharles.Forsyth 	if(c->qid.type & QTDIR){
206*37da2899SCharles.Forsyth 		if(omode != OREAD)
207*37da2899SCharles.Forsyth 			error(Ebadarg);
208*37da2899SCharles.Forsyth 		c->mode = omode;
209*37da2899SCharles.Forsyth 		c->flag |= COPEN;
210*37da2899SCharles.Forsyth 		c->offset = 0;
211*37da2899SCharles.Forsyth 		return c;
212*37da2899SCharles.Forsyth 	}
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth 	openmode(omode);	/* check it */
215*37da2899SCharles.Forsyth 
216*37da2899SCharles.Forsyth 	p = c->aux;
217*37da2899SCharles.Forsyth 	qlock(&p->l);
218*37da2899SCharles.Forsyth 	if(waserror()){
219*37da2899SCharles.Forsyth 		qunlock(&p->l);
220*37da2899SCharles.Forsyth 		nexterror();
221*37da2899SCharles.Forsyth 	}
222*37da2899SCharles.Forsyth 	switch(NETTYPE(c->qid.path)){
223*37da2899SCharles.Forsyth 	case Qdata0:
224*37da2899SCharles.Forsyth 		devpermcheck(p->user, p->pipedir[1].perm, omode);
225*37da2899SCharles.Forsyth 		p->qref[0]++;
226*37da2899SCharles.Forsyth 		break;
227*37da2899SCharles.Forsyth 	case Qdata1:
228*37da2899SCharles.Forsyth 		devpermcheck(p->user, p->pipedir[2].perm, omode);
229*37da2899SCharles.Forsyth 		p->qref[1]++;
230*37da2899SCharles.Forsyth 		break;
231*37da2899SCharles.Forsyth 	}
232*37da2899SCharles.Forsyth 	poperror();
233*37da2899SCharles.Forsyth 	qunlock(&p->l);
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth 	c->mode = openmode(omode);
236*37da2899SCharles.Forsyth 	c->flag |= COPEN;
237*37da2899SCharles.Forsyth 	c->offset = 0;
238*37da2899SCharles.Forsyth 	c->iounit = qiomaxatomic;
239*37da2899SCharles.Forsyth 	return c;
240*37da2899SCharles.Forsyth }
241*37da2899SCharles.Forsyth 
242*37da2899SCharles.Forsyth static void
pipeclose(Chan * c)243*37da2899SCharles.Forsyth pipeclose(Chan *c)
244*37da2899SCharles.Forsyth {
245*37da2899SCharles.Forsyth 	Pipe *p;
246*37da2899SCharles.Forsyth 
247*37da2899SCharles.Forsyth 	p = c->aux;
248*37da2899SCharles.Forsyth 	qlock(&p->l);
249*37da2899SCharles.Forsyth 
250*37da2899SCharles.Forsyth 	if(c->flag & COPEN){
251*37da2899SCharles.Forsyth 		/*
252*37da2899SCharles.Forsyth 		 *  closing either side hangs up the stream
253*37da2899SCharles.Forsyth 		 */
254*37da2899SCharles.Forsyth 		switch(NETTYPE(c->qid.path)){
255*37da2899SCharles.Forsyth 		case Qdata0:
256*37da2899SCharles.Forsyth 			p->qref[0]--;
257*37da2899SCharles.Forsyth 			if(p->qref[0] == 0){
258*37da2899SCharles.Forsyth 				qhangup(p->q[1], 0);
259*37da2899SCharles.Forsyth 				qclose(p->q[0]);
260*37da2899SCharles.Forsyth 			}
261*37da2899SCharles.Forsyth 			break;
262*37da2899SCharles.Forsyth 		case Qdata1:
263*37da2899SCharles.Forsyth 			p->qref[1]--;
264*37da2899SCharles.Forsyth 			if(p->qref[1] == 0){
265*37da2899SCharles.Forsyth 				qhangup(p->q[0], 0);
266*37da2899SCharles.Forsyth 				qclose(p->q[1]);
267*37da2899SCharles.Forsyth 			}
268*37da2899SCharles.Forsyth 			break;
269*37da2899SCharles.Forsyth 		}
270*37da2899SCharles.Forsyth 	}
271*37da2899SCharles.Forsyth 
272*37da2899SCharles.Forsyth 
273*37da2899SCharles.Forsyth 	/*
274*37da2899SCharles.Forsyth 	 *  if both sides are closed, they are reusable
275*37da2899SCharles.Forsyth 	 */
276*37da2899SCharles.Forsyth 	if(p->qref[0] == 0 && p->qref[1] == 0){
277*37da2899SCharles.Forsyth 		qreopen(p->q[0]);
278*37da2899SCharles.Forsyth 		qreopen(p->q[1]);
279*37da2899SCharles.Forsyth 	}
280*37da2899SCharles.Forsyth 
281*37da2899SCharles.Forsyth 	/*
282*37da2899SCharles.Forsyth 	 *  free the structure on last close
283*37da2899SCharles.Forsyth 	 */
284*37da2899SCharles.Forsyth 	p->ref--;
285*37da2899SCharles.Forsyth 	if(p->ref == 0){
286*37da2899SCharles.Forsyth 		qunlock(&p->l);
287*37da2899SCharles.Forsyth 		freepipe(p);
288*37da2899SCharles.Forsyth 	} else
289*37da2899SCharles.Forsyth 		qunlock(&p->l);
290*37da2899SCharles.Forsyth }
291*37da2899SCharles.Forsyth 
292*37da2899SCharles.Forsyth static long
piperead(Chan * c,void * va,long n,vlong junk)293*37da2899SCharles.Forsyth piperead(Chan *c, void *va, long n, vlong junk)
294*37da2899SCharles.Forsyth {
295*37da2899SCharles.Forsyth 	Pipe *p;
296*37da2899SCharles.Forsyth 
297*37da2899SCharles.Forsyth 	p = c->aux;
298*37da2899SCharles.Forsyth 
299*37da2899SCharles.Forsyth 	USED(junk);
300*37da2899SCharles.Forsyth 	switch(NETTYPE(c->qid.path)){
301*37da2899SCharles.Forsyth 	case Qdir:
302*37da2899SCharles.Forsyth 		return devdirread(c, va, n, p->pipedir, nelem(pipedir), pipegen);
303*37da2899SCharles.Forsyth 	case Qdata0:
304*37da2899SCharles.Forsyth 		return qread(p->q[0], va, n);
305*37da2899SCharles.Forsyth 	case Qdata1:
306*37da2899SCharles.Forsyth 		return qread(p->q[1], va, n);
307*37da2899SCharles.Forsyth 	default:
308*37da2899SCharles.Forsyth 		panic("piperead");
309*37da2899SCharles.Forsyth 	}
310*37da2899SCharles.Forsyth 	return -1;	/* not reached */
311*37da2899SCharles.Forsyth }
312*37da2899SCharles.Forsyth 
313*37da2899SCharles.Forsyth static Block*
pipebread(Chan * c,long n,ulong offset)314*37da2899SCharles.Forsyth pipebread(Chan *c, long n, ulong offset)
315*37da2899SCharles.Forsyth {
316*37da2899SCharles.Forsyth 	Pipe *p;
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth 	p = c->aux;
319*37da2899SCharles.Forsyth 
320*37da2899SCharles.Forsyth 	switch(NETTYPE(c->qid.path)){
321*37da2899SCharles.Forsyth 	case Qdata0:
322*37da2899SCharles.Forsyth 		return qbread(p->q[0], n);
323*37da2899SCharles.Forsyth 	case Qdata1:
324*37da2899SCharles.Forsyth 		return qbread(p->q[1], n);
325*37da2899SCharles.Forsyth 	}
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth 	return devbread(c, n, offset);
328*37da2899SCharles.Forsyth }
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth /*
331*37da2899SCharles.Forsyth  *  a write to a closed pipe causes an exception to be sent to
332*37da2899SCharles.Forsyth  *  the prog.
333*37da2899SCharles.Forsyth  */
334*37da2899SCharles.Forsyth static long
pipewrite(Chan * c,void * va,long n,vlong junk)335*37da2899SCharles.Forsyth pipewrite(Chan *c, void *va, long n, vlong junk)
336*37da2899SCharles.Forsyth {
337*37da2899SCharles.Forsyth 	Pipe *p;
338*37da2899SCharles.Forsyth 	Prog *r;
339*37da2899SCharles.Forsyth 
340*37da2899SCharles.Forsyth 	USED(junk);
341*37da2899SCharles.Forsyth 	if(waserror()) {
342*37da2899SCharles.Forsyth 		/* avoid exceptions when pipe is a mounted queue */
343*37da2899SCharles.Forsyth 		if((c->flag & CMSG) == 0) {
344*37da2899SCharles.Forsyth 			r = up->iprog;
345*37da2899SCharles.Forsyth 			if(r != nil && r->kill == nil)
346*37da2899SCharles.Forsyth 				r->kill = "write on closed pipe";
347*37da2899SCharles.Forsyth 		}
348*37da2899SCharles.Forsyth 		nexterror();
349*37da2899SCharles.Forsyth 	}
350*37da2899SCharles.Forsyth 
351*37da2899SCharles.Forsyth 	p = c->aux;
352*37da2899SCharles.Forsyth 
353*37da2899SCharles.Forsyth 	switch(NETTYPE(c->qid.path)){
354*37da2899SCharles.Forsyth 	case Qdata0:
355*37da2899SCharles.Forsyth 		n = qwrite(p->q[1], va, n);
356*37da2899SCharles.Forsyth 		break;
357*37da2899SCharles.Forsyth 
358*37da2899SCharles.Forsyth 	case Qdata1:
359*37da2899SCharles.Forsyth 		n = qwrite(p->q[0], va, n);
360*37da2899SCharles.Forsyth 		break;
361*37da2899SCharles.Forsyth 
362*37da2899SCharles.Forsyth 	default:
363*37da2899SCharles.Forsyth 		panic("pipewrite");
364*37da2899SCharles.Forsyth 	}
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth 	poperror();
367*37da2899SCharles.Forsyth 	return n;
368*37da2899SCharles.Forsyth }
369*37da2899SCharles.Forsyth 
370*37da2899SCharles.Forsyth static long
pipebwrite(Chan * c,Block * bp,ulong junk)371*37da2899SCharles.Forsyth pipebwrite(Chan *c, Block *bp, ulong junk)
372*37da2899SCharles.Forsyth {
373*37da2899SCharles.Forsyth 	long n;
374*37da2899SCharles.Forsyth 	Pipe *p;
375*37da2899SCharles.Forsyth 	Prog *r;
376*37da2899SCharles.Forsyth 
377*37da2899SCharles.Forsyth 	USED(junk);
378*37da2899SCharles.Forsyth 	if(waserror()) {
379*37da2899SCharles.Forsyth 		/* avoid exceptions when pipe is a mounted queue */
380*37da2899SCharles.Forsyth 		if((c->flag & CMSG) == 0) {
381*37da2899SCharles.Forsyth 			r = up->iprog;
382*37da2899SCharles.Forsyth 			if(r != nil && r->kill == nil)
383*37da2899SCharles.Forsyth 				r->kill = "write on closed pipe";
384*37da2899SCharles.Forsyth 		}
385*37da2899SCharles.Forsyth 		nexterror();
386*37da2899SCharles.Forsyth 	}
387*37da2899SCharles.Forsyth 
388*37da2899SCharles.Forsyth 	p = c->aux;
389*37da2899SCharles.Forsyth 	switch(NETTYPE(c->qid.path)){
390*37da2899SCharles.Forsyth 	case Qdata0:
391*37da2899SCharles.Forsyth 		n = qbwrite(p->q[1], bp);
392*37da2899SCharles.Forsyth 		break;
393*37da2899SCharles.Forsyth 
394*37da2899SCharles.Forsyth 	case Qdata1:
395*37da2899SCharles.Forsyth 		n = qbwrite(p->q[0], bp);
396*37da2899SCharles.Forsyth 		break;
397*37da2899SCharles.Forsyth 
398*37da2899SCharles.Forsyth 	default:
399*37da2899SCharles.Forsyth 		n = 0;
400*37da2899SCharles.Forsyth 		panic("pipebwrite");
401*37da2899SCharles.Forsyth 	}
402*37da2899SCharles.Forsyth 
403*37da2899SCharles.Forsyth 	poperror();
404*37da2899SCharles.Forsyth 	return n;
405*37da2899SCharles.Forsyth }
406*37da2899SCharles.Forsyth 
407*37da2899SCharles.Forsyth static int
pipewstat(Chan * c,uchar * dp,int n)408*37da2899SCharles.Forsyth pipewstat(Chan *c, uchar *dp, int n)
409*37da2899SCharles.Forsyth {
410*37da2899SCharles.Forsyth 	Dir *d;
411*37da2899SCharles.Forsyth 	Pipe *p;
412*37da2899SCharles.Forsyth 	int d1;
413*37da2899SCharles.Forsyth 
414*37da2899SCharles.Forsyth 	if (c->qid.type&QTDIR)
415*37da2899SCharles.Forsyth 		error(Eperm);
416*37da2899SCharles.Forsyth 	p = c->aux;
417*37da2899SCharles.Forsyth 	if(strcmp(up->env->user, p->user) != 0)
418*37da2899SCharles.Forsyth 		error(Eperm);
419*37da2899SCharles.Forsyth 	d = smalloc(sizeof(*d)+n);
420*37da2899SCharles.Forsyth 	if(waserror()){
421*37da2899SCharles.Forsyth 		free(d);
422*37da2899SCharles.Forsyth 		nexterror();
423*37da2899SCharles.Forsyth 	}
424*37da2899SCharles.Forsyth 	n = convM2D(dp, n, d, (char*)&d[1]);
425*37da2899SCharles.Forsyth 	if(n == 0)
426*37da2899SCharles.Forsyth 		error(Eshortstat);
427*37da2899SCharles.Forsyth 	d1 = NETTYPE(c->qid.path) == Qdata1;
428*37da2899SCharles.Forsyth 	if(!emptystr(d->name)){
429*37da2899SCharles.Forsyth 		validwstatname(d->name);
430*37da2899SCharles.Forsyth 		if(strlen(d->name) >= KNAMELEN)
431*37da2899SCharles.Forsyth 			error(Efilename);
432*37da2899SCharles.Forsyth 		if(strcmp(p->pipedir[1+!d1].name, d->name) == 0)
433*37da2899SCharles.Forsyth 			error(Eexist);
434*37da2899SCharles.Forsyth 		kstrcpy(p->pipedir[1+d1].name, d->name, KNAMELEN);
435*37da2899SCharles.Forsyth 	}
436*37da2899SCharles.Forsyth 	if(d->mode != ~0UL)
437*37da2899SCharles.Forsyth 		p->pipedir[d1 + 1].perm = d->mode & 0777;
438*37da2899SCharles.Forsyth 	poperror();
439*37da2899SCharles.Forsyth 	free(d);
440*37da2899SCharles.Forsyth 	return n;
441*37da2899SCharles.Forsyth }
442*37da2899SCharles.Forsyth 
443*37da2899SCharles.Forsyth Dev pipedevtab = {
444*37da2899SCharles.Forsyth 	'|',
445*37da2899SCharles.Forsyth 	"pipe",
446*37da2899SCharles.Forsyth 
447*37da2899SCharles.Forsyth 	pipeinit,
448*37da2899SCharles.Forsyth 	pipeattach,
449*37da2899SCharles.Forsyth 	pipewalk,
450*37da2899SCharles.Forsyth 	pipestat,
451*37da2899SCharles.Forsyth 	pipeopen,
452*37da2899SCharles.Forsyth 	devcreate,
453*37da2899SCharles.Forsyth 	pipeclose,
454*37da2899SCharles.Forsyth 	piperead,
455*37da2899SCharles.Forsyth 	pipebread,
456*37da2899SCharles.Forsyth 	pipewrite,
457*37da2899SCharles.Forsyth 	pipebwrite,
458*37da2899SCharles.Forsyth 	devremove,
459*37da2899SCharles.Forsyth 	pipewstat,
460*37da2899SCharles.Forsyth };
461