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 <u.h>
2
#include <libc.h>
3
#include <auth.h>
4
#include <fcall.h>
5
#include "iotrack.h"
6
#include "dat.h"
7
#include "dosfs.h"
8
#include "fns.h"
9
 
10
#include "errstr.h"
11
 
12
#define	Reqsize	(sizeof(Fcall)+Maxfdata)
13
Fcall	*req;
14
Fcall	*rep;
15
 
16
uchar	mdata[Maxiosize];
17
char	repdata[Maxfdata];
18
uchar	statbuf[STATMAX];
19
int	errno;
20
char	errbuf[ERRMAX];
21
void	rmservice(void);
22
char	srvfile[64];
23
char	*deffile;
24
int	doabort;
25
int	trspaces;
26
 
27
void	(*fcalls[])(void) = {
28
	[Tversion]	rversion,
29
	[Tflush]	rflush,
30
	[Tauth]	rauth,
31
	[Tattach]	rattach,
32
	[Twalk]		rwalk,
33
	[Topen]		ropen,
34
	[Tcreate]	rcreate,
35
	[Tread]		rread,
36
	[Twrite]	rwrite,
37
	[Tclunk]	rclunk,
38
	[Tremove]	rremove,
39
	[Tstat]		rstat,
40
	[Twstat]	rwstat,
41
};
42
 
43
void
44
usage(void)
45
{
46
	fprint(2, "usage: %s [-v] [-s] [-f devicefile] [srvname]\n", argv0);
47
	exits("usage");
48
}
49
 
50
void
51
main(int argc, char **argv)
52
{
53
	int stdio, srvfd, pipefd[2];
54
 
55
	rep = malloc(sizeof(Fcall));
56
	req = malloc(Reqsize);
57
	if(rep == nil || req == nil)
58
		panic("out of memory");
59
	stdio = 0;
60
	ARGBEGIN{
61
	case ':':
62
		trspaces = 1;
63
		break;
64
	case 'r':
65
		readonly = 1;
66
		break;
67
	case 'v':
68
		++chatty;
69
		break;
70
	case 'f':
71
		deffile = ARGF();
72
		break;
73
	case 's':
74
		stdio = 1;
75
		break;
76
	case 'p':
77
		doabort = 1;
78
		break;
79
	default:
80
		usage();
81
	}ARGEND
82
 
83
	if(argc == 0)
84
		strcpy(srvfile, "#s/dos");
85
	else if(argc == 1)
86
		snprint(srvfile, sizeof srvfile, "#s/%s", argv[0]);
87
	else
88
		usage();
89
 
90
	if(stdio){
91
		pipefd[0] = 0;
92
		pipefd[1] = 1;
93
	}else{
94
		close(0);
95
		close(1);
96
		open("/dev/null", OREAD);
97
		open("/dev/null", OWRITE);
98
		if(pipe(pipefd) < 0)
99
			panic("pipe");
100
		srvfd = create(srvfile, OWRITE|ORCLOSE, 0600);
101
		if(srvfd < 0)
102
			panic(srvfile);
103
		fprint(srvfd, "%d", pipefd[0]);
104
		close(pipefd[0]);
105
		atexit(rmservice);
106
		fprint(2, "%s: serving %s\n", argv0, srvfile);
107
	}
108
	srvfd = pipefd[1];
109
 
110
	switch(rfork(RFNOWAIT|RFNOTEG|RFFDG|RFPROC|RFNAMEG)){
111
	case -1:
112
		panic("fork");
113
	default:
114
		_exits(0);
115
	case 0:
116
		break;
117
	}
118
 
119
	iotrack_init();
120
 
121
	if(!chatty){
122
		close(2);
123
		open("#c/cons", OWRITE);
124
	}
125
 
126
	io(srvfd);
127
	exits(0);
128
}
129
 
130
void
131
io(int srvfd)
132
{
133
	int n, pid;
134
 
135
	pid = getpid();
136
 
137
	fmtinstall('F', fcallfmt);
138
	for(;;){
139
		/*
140
		 * reading from a pipe or a network device
141
		 * will give an error after a few eof reads.
142
		 * however, we cannot tell the difference
143
		 * between a zero-length read and an interrupt
144
		 * on the processes writing to us,
145
		 * so we wait for the error.
146
		 */
147
		n = read9pmsg(srvfd, mdata, sizeof mdata);
148
		if(n < 0)
149
			break;
150
		if(n == 0)
151
			continue;
152
		if(convM2S(mdata, n, req) == 0)
153
			continue;
154
 
155
		if(chatty)
156
			fprint(2, "dossrv %d:<-%F\n", pid, req);
157
 
158
		errno = 0;
159
		if(!fcalls[req->type])
160
			errno = Ebadfcall;
161
		else
162
			(*fcalls[req->type])();
163
		if(errno){
164
			rep->type = Rerror;
165
			rep->ename = xerrstr(errno);
166
		}else{
167
			rep->type = req->type + 1;
168
			rep->fid = req->fid;
169
		}
170
		rep->tag = req->tag;
171
		if(chatty)
172
			fprint(2, "dossrv %d:->%F\n", pid, rep);
173
		n = convS2M(rep, mdata, sizeof mdata);
174
		if(n == 0)
175
			panic("convS2M error on write");
176
		if(write(srvfd, mdata, n) != n)
177
			panic("mount write");
178
	}
179
	chat("server shut down");
180
}
181
 
182
void
183
rmservice(void)
184
{
185
	remove(srvfile);
186
}
187
 
188
char *
189
xerrstr(int e)
190
{
191
	if (e < 0 || e >= sizeof errmsg/sizeof errmsg[0])
192
		return "no such error";
193
	if(e == Eerrstr){
194
		errstr(errbuf, sizeof errbuf);
195
		return errbuf;
196
	}
197
	return errmsg[e];
198
}
199
 
200
int
201
eqqid(Qid q1, Qid q2)
202
{
203
	return q1.path == q2.path && q1.type == q2.type && q1.vers == q2.vers;
204
}