Blob


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