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 "stdinc.h"
2
 
3
#include "9.h"
4
 
5
static struct {
6
	VtLock*	lock;
7
 
8
	Con*	con;
9
	int	confd[2];
10
	ushort	tag;
11
} cbox;
12
 
13
static ulong
14
cmd9pStrtoul(char* s)
15
{
16
	if(strcmp(s, "~0") == 0)
17
		return ~0UL;
18
	return strtoul(s, 0, 0);
19
}
20
 
21
static uvlong
22
cmd9pStrtoull(char* s)
23
{
24
	if(strcmp(s, "~0") == 0)
25
		return ~0ULL;
26
	return strtoull(s, 0, 0);
27
}
28
 
29
static int
30
cmd9pTag(Fcall*, int, char **argv)
31
{
32
	cbox.tag = strtoul(argv[0], 0, 0)-1;
33
 
34
	return 1;
35
}
36
 
37
static int
38
cmd9pTwstat(Fcall* f, int, char **argv)
39
{
40
	Dir d;
41
	static uchar buf[DIRMAX];
42
 
43
	memset(&d, 0, sizeof d);
44
	nulldir(&d);
45
	d.name = argv[1];
46
	d.uid = argv[2];
47
	d.gid = argv[3];
48
	d.mode = cmd9pStrtoul(argv[4]);
49
	d.mtime = cmd9pStrtoul(argv[5]);
50
	d.length = cmd9pStrtoull(argv[6]);
51
 
52
	f->fid = strtol(argv[0], 0, 0);
53
	f->stat = buf;
54
	f->nstat = convD2M(&d, buf, sizeof buf);
55
	if(f->nstat < BIT16SZ){
56
		vtSetError("Twstat: convD2M failed (internal error)");
57
		return 0;
58
	}
59
 
60
	return 1;
61
}
62
 
63
static int
64
cmd9pTstat(Fcall* f, int, char** argv)
65
{
66
	f->fid = strtol(argv[0], 0, 0);
67
 
68
	return 1;
69
}
70
 
71
static int
72
cmd9pTremove(Fcall* f, int, char** argv)
73
{
74
	f->fid = strtol(argv[0], 0, 0);
75
 
76
	return 1;
77
}
78
 
79
static int
80
cmd9pTclunk(Fcall* f, int, char** argv)
81
{
82
	f->fid = strtol(argv[0], 0, 0);
83
 
84
	return 1;
85
}
86
 
87
static int
88
cmd9pTwrite(Fcall* f, int, char** argv)
89
{
90
	f->fid = strtol(argv[0], 0, 0);
91
	f->offset = strtoll(argv[1], 0, 0);
92
	f->data = argv[2];
93
	f->count = strlen(argv[2]);
94
 
95
	return 1;
96
}
97
 
98
static int
99
cmd9pTread(Fcall* f, int, char** argv)
100
{
101
	f->fid = strtol(argv[0], 0, 0);
102
	f->offset = strtoll(argv[1], 0, 0);
103
	f->count = strtol(argv[2], 0, 0);
104
 
105
	return 1;
106
}
107
 
108
static int
109
cmd9pTcreate(Fcall* f, int, char** argv)
110
{
111
	f->fid = strtol(argv[0], 0, 0);
112
	f->name = argv[1];
113
	f->perm = strtol(argv[2], 0, 8);
114
	f->mode = strtol(argv[3], 0, 0);
115
 
116
	return 1;
117
}
118
 
119
static int
120
cmd9pTopen(Fcall* f, int, char** argv)
121
{
122
	f->fid = strtol(argv[0], 0, 0);
123
	f->mode = strtol(argv[1], 0, 0);
124
 
125
	return 1;
126
}
127
 
128
static int
129
cmd9pTwalk(Fcall* f, int argc, char** argv)
130
{
131
	int i;
132
 
133
	if(argc < 2){
134
		vtSetError("usage: Twalk tag fid newfid [name...]");
135
		return 0;
136
	}
137
	f->fid = strtol(argv[0], 0, 0);
138
	f->newfid = strtol(argv[1], 0, 0);
139
	f->nwname = argc-2;
140
	if(f->nwname > MAXWELEM){
141
		vtSetError("Twalk: too many names");
142
		return 0;
143
	}
144
	for(i = 0; i < argc-2; i++)
145
		f->wname[i] = argv[2+i];
146
 
147
	return 1;
148
}
149
 
150
static int
151
cmd9pTflush(Fcall* f, int, char** argv)
152
{
153
	f->oldtag = strtol(argv[0], 0, 0);
154
 
155
	return 1;
156
}
157
 
158
static int
159
cmd9pTattach(Fcall* f, int, char** argv)
160
{
161
	f->fid = strtol(argv[0], 0, 0);
162
	f->afid = strtol(argv[1], 0, 0);
163
	f->uname = argv[2];
164
	f->aname = argv[3];
165
 
166
	return 1;
167
}
168
 
169
static int
170
cmd9pTauth(Fcall* f, int, char** argv)
171
{
172
	f->afid = strtol(argv[0], 0, 0);
173
	f->uname = argv[1];
174
	f->aname = argv[2];
175
 
176
	return 1;
177
}
178
 
179
static int
180
cmd9pTversion(Fcall* f, int, char** argv)
181
{
182
	f->msize = strtoul(argv[0], 0, 0);
183
	if(f->msize > cbox.con->msize){
184
		vtSetError("msize too big");
185
		return 0;
186
	}
187
	f->version = argv[1];
188
 
189
	return 1;
190
}
191
 
192
typedef struct Cmd9p Cmd9p;
193
struct Cmd9p {
194
	char*	name;
195
	int	type;
196
	int	argc;
197
	char*	usage;
198
	int	(*f)(Fcall*, int, char**);
199
};
200
 
201
static Cmd9p cmd9pTmsg[] = {
202
	"Tversion", Tversion, 2, "msize version", cmd9pTversion,
203
	"Tauth", Tauth, 3, "afid uname aname", cmd9pTauth,
204
	"Tflush", Tflush, 1, "oldtag", cmd9pTflush,
205
	"Tattach", Tattach, 4, "fid afid uname aname", cmd9pTattach,
206
	"Twalk", Twalk, 0, "fid newfid [name...]", cmd9pTwalk,
207
	"Topen", Topen, 2, "fid mode", cmd9pTopen,
208
	"Tcreate", Tcreate, 4, "fid name perm mode", cmd9pTcreate,
209
	"Tread", Tread, 3, "fid offset count", cmd9pTread,
210
	"Twrite", Twrite, 3, "fid offset data", cmd9pTwrite,
211
	"Tclunk", Tclunk, 1, "fid", cmd9pTclunk,
212
	"Tremove", Tremove, 1, "fid", cmd9pTremove,
213
	"Tstat", Tstat, 1, "fid", cmd9pTstat,
214
	"Twstat", Twstat, 7, "fid name uid gid mode mtime length", cmd9pTwstat,
215
	"nexttag", 0, 0, "", cmd9pTag,
216
};
217
 
218
static int
219
cmd9p(int argc, char* argv[])
220
{
221
	int i, n;
222
	Fcall f, t;
223
	uchar *buf;
224
	char *usage;
225
	u32int msize;
226
 
227
	usage = "usage: 9p T-message ...";
228
 
229
	ARGBEGIN{
230
	default:
231
		return cliError(usage);
232
	}ARGEND
233
	if(argc < 1)
234
		return cliError(usage);
235
 
236
	for(i = 0; i < nelem(cmd9pTmsg); i++){
237
		if(strcmp(cmd9pTmsg[i].name, argv[0]) == 0)
238
			break;
239
	}
240
	if(i == nelem(cmd9pTmsg))
241
		return cliError(usage);
242
	argc--;
243
	argv++;
244
	if(cmd9pTmsg[i].argc && argc != cmd9pTmsg[i].argc){
245
		vtSetError("usage: %s %s",
246
			cmd9pTmsg[i].name, cmd9pTmsg[i].usage);
247
		return 0;
248
	}
249
 
250
	memset(&t, 0, sizeof(t));
251
	t.type = cmd9pTmsg[i].type;
252
	if(t.type == Tversion)
253
		t.tag = NOTAG;
254
	else
255
		t.tag = ++cbox.tag;
256
	msize = cbox.con->msize;
257
	if(!cmd9pTmsg[i].f(&t, argc, argv))
258
		return 0;
259
	buf = vtMemAlloc(msize);
260
	n = convS2M(&t, buf, msize);
261
	if(n <= BIT16SZ){
262
		vtSetError("%s: convS2M error", cmd9pTmsg[i].name);
263
		vtMemFree(buf);
264
		return 0;
265
	}
266
	if(write(cbox.confd[0], buf, n) != n){
267
		vtSetError("%s: write error: %r", cmd9pTmsg[i].name);
268
		vtMemFree(buf);
269
		return 0;
270
	}
271
	consPrint("\t-> %F\n", &t);
272
 
273
	if((n = read9pmsg(cbox.confd[0], buf, msize)) <= 0){
274
		vtSetError("%s: read error: %r", cmd9pTmsg[i].name);
275
		vtMemFree(buf);
276
		return 0;
277
	}
278
	if(convM2S(buf, n, &f) == 0){
279
		vtSetError("%s: convM2S error", cmd9pTmsg[i].name);
280
		vtMemFree(buf);
281
		return 0;
282
	}
283
	consPrint("\t<- %F\n", &f);
284
 
285
	vtMemFree(buf);
286
	return 1;
287
}
288
 
289
static int
290
cmdDot(int argc, char* argv[])
291
{
292
	long l;
293
	Dir *dir;
294
	int fd, r;
295
	vlong length;
296
	char *f, *p, *s, *usage;
297
 
298
	usage = "usage: . file";
299
 
300
	ARGBEGIN{
301
	default:
302
		return cliError(usage);
303
	}ARGEND
304
	if(argc != 1)
305
		return cliError(usage);
306
 
307
	if((dir = dirstat(argv[0])) == nil)
308
		return cliError(". dirstat %s: %r", argv[0]);
309
	length = dir->length;
310
	free(dir);
311
 
312
	r = 1;
313
	if(length != 0){
314
		/*
315
		 * Read the whole file in.
316
		 */
317
		if((fd = open(argv[0], OREAD)) < 0)
318
			return cliError(". open %s: %r", argv[0]);
319
		f = vtMemAlloc(dir->length+1);
320
		if((l = read(fd, f, length)) < 0){
321
			vtMemFree(f);
322
			close(fd);
323
			return cliError(". read %s: %r", argv[0]);
324
		}
325
		close(fd);
326
		f[l] = '\0';
327
 
328
		/*
329
		 * Call cliExec() for each line.
330
		 */
331
		for(p = s = f; *p != '\0'; p++){
332
			if(*p == '\n'){
333
				*p = '\0';
334
				if(cliExec(s) == 0){
335
					r = 0;
336
					consPrint("%s: %R\n", s);
337
				}
338
				s = p+1;
339
			}
340
		}
341
		vtMemFree(f);
342
	}
343
 
344
	if(r == 0)
345
		vtSetError("errors in . %#q", argv[0]);
346
	return r;
347
}
348
 
349
static int
350
cmdDflag(int argc, char* argv[])
351
{
352
	char *usage;
353
 
354
	usage = "usage: dflag";
355
 
356
	ARGBEGIN{
357
	default:
358
		return cliError(usage);
359
	}ARGEND
360
	if(argc)
361
		return cliError(usage);
362
 
363
	Dflag ^= 1;
364
	consPrint("dflag %d\n", Dflag);
365
 
366
	return 1;
367
}
368
 
369
static int
370
cmdEcho(int argc, char* argv[])
371
{
372
	char *usage;
373
	int i, nflag;
374
 
375
	nflag = 0;
376
	usage = "usage: echo [-n] ...";
377
 
378
	ARGBEGIN{
379
	default:
380
		return cliError(usage);
381
	case 'n':
382
		nflag = 1;
383
		break;
384
	}ARGEND
385
 
386
	for(i = 0; i < argc; i++){
387
		if(i != 0)
388
			consPrint(" %s", argv[i]);
389
		else
390
			consPrint(argv[i]);
391
	}
392
	if(!nflag)
393
		consPrint("\n");
394
 
395
	return 1;
396
}
397
 
398
static int
399
cmdBind(int argc, char* argv[])
400
{
401
	ulong flag = 0;
402
	char *usage;
403
 
404
	usage = "usage: bind [-b|-a|-c|-bc|-ac] new old";
405
 
406
	ARGBEGIN{
407
	case 'a':
408
		flag |= MAFTER;
409
		break;
410
	case 'b':
411
		flag |= MBEFORE;
412
		break;
413
	case 'c':
414
		flag |= MCREATE;
415
		break;
416
	default:
417
		return cliError(usage);
418
	}ARGEND
419
 
420
	if(argc != 2 || (flag&MAFTER)&&(flag&MBEFORE))
421
		return cliError(usage);
422
 
423
	if(bind(argv[0], argv[1], flag) < 0){
424
		/* try to give a less confusing error than the default */
425
		if(access(argv[0], 0) < 0)
426
			return cliError("bind: %s: %r", argv[0]);
427
		else if(access(argv[1], 0) < 0)
428
			return cliError("bind: %s: %r", argv[1]);
429
		else
430
			return cliError("bind %s %s: %r", argv[0], argv[1]);
431
	}
432
	return 1;
433
}
434
 
435
int
436
cmdInit(void)
437
{
438
	cbox.lock = vtLockAlloc();
439
	cbox.confd[0] = cbox.confd[1] = -1;
440
 
441
	cliAddCmd(".", cmdDot);
442
	cliAddCmd("9p", cmd9p);
443
	cliAddCmd("dflag", cmdDflag);
444
	cliAddCmd("echo", cmdEcho);
445
	cliAddCmd("bind", cmdBind);
446
 
447
	if(pipe(cbox.confd) < 0)
448
		return 0;
449
	if((cbox.con = conAlloc(cbox.confd[1], "console", 0)) == nil){
450
		close(cbox.confd[0]);
451
		close(cbox.confd[1]);
452
		cbox.confd[0] = cbox.confd[1] = -1;
453
		return 0;
454
 
455
	}
456
	cbox.con->isconsole = 1;
457
 
458
	return 1;
459
}