Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "all.h"
2
 
3
static int
4
readmsg(Chan *c, void *abuf, int n, int *ninep)
5
{
6
	int fd, len;
7
	uchar *buf;
8
 
9
	buf = abuf;
10
	fd = c->chan;
11
	qlock(&c->rlock);
12
	if(readn(fd, buf, 3) != 3){
13
		qunlock(&c->rlock);
14
		print("readn(3) fails: %r\n");
15
		return -1;
16
	}
17
	if((50 <= buf[0] && buf[0] <= 87 && (buf[0]&1)==0 && GBIT16(buf+1) == 0xFFFF)
18
	|| buf[0] == 86	/* Tattach */){
19
		*ninep = 1;
20
		/* assume message boundaries */
21
		n = read(fd, buf+3, n-3);
22
		if(n < 0){
23
			qunlock(&c->rlock);
24
			return -1;
25
		}
26
		return n+3;
27
	}
28
 
29
	*ninep = 2;
30
	if(read(fd, buf+3, 1) != 1){
31
		qunlock(&c->rlock);
32
		print("read(1) fails: %r\n");
33
		return -1;
34
	}
35
	len = GBIT32(buf);
36
	if(len > n){
37
		print("msg too large\n");
38
		qunlock(&c->rlock);
39
		return -1;
40
	}
41
	if(readn(fd, buf+4, len-4) != len-4){
42
		print("readn(%d) fails: %r\n", len-4);
43
		qunlock(&c->rlock);
44
		return -1;
45
	}
46
	qunlock(&c->rlock);
47
	return len;
48
}
49
 
50
int
51
startserveproc(void (*f)(Chan*, uchar*, int), char *name, Chan *c, uchar *b, int nb)
52
{
53
	int pid;
54
 
55
	switch(pid = rfork(RFMEM|RFPROC)){
56
	case -1:
57
		panic("can't fork");
58
	case 0:
59
		break;
60
	default:
61
		return pid;
62
	}
63
	procname = name;
64
	f(c, b, nb);
65
	_exits(nil);
66
	return -1;	/* can't happen */
67
}
68
 
69
void
70
serve(Chan *chan)
71
{
72
	int i, nin, p9, npid;
73
	uchar inbuf[1024];
74
	void (*s)(Chan*, uchar*, int);
75
	int *pid;
76
	Waitmsg *w;
77
 
78
	p9 = 0;
79
	if((nin = readmsg(chan, inbuf, sizeof inbuf, &p9)) < 0)
80
		return;
81
 
82
	switch(p9){
83
	default:
84
		print("unknown 9P type\n");
85
		return;
86
	case 1:
87
		s = serve9p1;
88
		break;
89
	case 2:
90
		s = serve9p2;
91
		break;
92
	}
93
 
94
	pid = malloc(sizeof(pid)*(conf.nserve-1));
95
	if(pid == nil)
96
		return;
97
	for(i=1; i<conf.nserve; i++)
98
		pid[i-1] = startserveproc(s, "srv", chan, nil, 0);
99
 
100
	(*s)(chan, inbuf, nin);
101
 
102
	/* wait till all other servers for this chan are done */
103
	for(npid = conf.nserve-1; npid > 0;){
104
		w = wait();
105
		if(w == 0)
106
			break;
107
		for(i = 0; i < conf.nserve-1; i++)
108
			if(pid[i] == w->pid)
109
				npid--;
110
		free(w);
111
	}
112
	free(pid);
113
}
114