tCcmd.c - plan9port - [fork] Plan 9 from user space
(HTM) git clone git://src.adamsgaard.dk/plan9port
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
tCcmd.c (8093B)
---
1 #include "stdinc.h"
2
3 #include "9.h"
4
5 static struct {
6 QLock 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* f, int i, char **argv)
31 {
32 USED(f);
33 USED(i);
34 cbox.tag = strtoul(argv[0], 0, 0)-1;
35
36 return 1;
37 }
38
39 static int
40 cmd9pTwstat(Fcall* f, int i, char **argv)
41 {
42 Dir d;
43 static uchar buf[DIRMAX];
44
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]);
54
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 }
62
63 return 1;
64 }
65
66 static int
67 cmd9pTstat(Fcall* f, int i, char** argv)
68 {
69 USED(i);
70 f->fid = strtol(argv[0], 0, 0);
71
72 return 1;
73 }
74
75 static int
76 cmd9pTremove(Fcall* f, int i, char** argv)
77 {
78 USED(i);
79 f->fid = strtol(argv[0], 0, 0);
80
81 return 1;
82 }
83
84 static int
85 cmd9pTclunk(Fcall* f, int i, char** argv)
86 {
87 USED(i);
88 f->fid = strtol(argv[0], 0, 0);
89
90 return 1;
91 }
92
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]);
101
102 return 1;
103 }
104
105 static int
106 cmd9pTread(Fcall* f, int i, char** argv)
107 {
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);
112
113 return 1;
114 }
115
116 static int
117 cmd9pTcreate(Fcall* f, int i, char** argv)
118 {
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);
124
125 return 1;
126 }
127
128 static int
129 cmd9pTopen(Fcall* f, int i, char** argv)
130 {
131 USED(i);
132 f->fid = strtol(argv[0], 0, 0);
133 f->mode = strtol(argv[1], 0, 0);
134
135 return 1;
136 }
137
138 static int
139 cmd9pTwalk(Fcall* f, int argc, char** argv)
140 {
141 int i;
142
143 if(argc < 2){
144 werrstr("usage: Twalk tag fid newfid [name...]");
145 return 0;
146 }
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;
153 }
154 for(i = 0; i < argc-2; i++)
155 f->wname[i] = argv[2+i];
156
157 return 1;
158 }
159
160 static int
161 cmd9pTflush(Fcall* f, int i, char** argv)
162 {
163 USED(i);
164 f->oldtag = strtol(argv[0], 0, 0);
165
166 return 1;
167 }
168
169 static int
170 cmd9pTattach(Fcall* f, int i, char** argv)
171 {
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];
177
178 return 1;
179 }
180
181 static int
182 cmd9pTauth(Fcall* f, int i, char** argv)
183 {
184 USED(i);
185 f->afid = strtol(argv[0], 0, 0);
186 f->uname = argv[1];
187 f->aname = argv[2];
188
189 return 1;
190 }
191
192 static int
193 cmd9pTversion(Fcall* f, int i, char** argv)
194 {
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;
200 }
201 f->version = argv[1];
202
203 return 1;
204 }
205
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 };
214
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 };
231
232 static int
233 cmd9p(int argc, char* argv[])
234 {
235 int i, n;
236 Fcall f, t;
237 uchar *buf;
238 char *usage;
239 u32int msize;
240
241 usage = "usage: 9p T-message ...";
242
243 ARGBEGIN{
244 default:
245 return cliError(usage);
246 }ARGEND
247 if(argc < 1)
248 return cliError(usage);
249
250 for(i = 0; i < nelem(cmd9pTmsg); i++){
251 if(strcmp(cmd9pTmsg[i].name, argv[0]) == 0)
252 break;
253 }
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;
262 }
263
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;
279 }
280 if(write(cbox.confd[0], buf, n) != n){
281 werrstr("%s: write error: %r", cmd9pTmsg[i].name);
282 vtfree(buf);
283 return 0;
284 }
285 consPrint("\t-> %F\n", &t);
286
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;
291 }
292 if(convM2S(buf, n, &f) == 0){
293 werrstr("%s: convM2S error", cmd9pTmsg[i].name);
294 vtfree(buf);
295 return 0;
296 }
297 consPrint("\t<- %F\n", &f);
298
299 vtfree(buf);
300 return 1;
301 }
302
303 static int
304 cmdDot(int argc, char* argv[])
305 {
306 long l;
307 Dir *dir;
308 int fd, r;
309 vlong length;
310 char *f, *p, *s, *usage;
311
312 usage = "usage: . file";
313
314 ARGBEGIN{
315 default:
316 return cliError(usage);
317 }ARGEND
318 if(argc != 1)
319 return cliError(usage);
320
321 if((dir = dirstat(argv[0])) == nil)
322 return cliError(". dirstat %s: %r", argv[0]);
323 length = dir->length;
324 free(dir);
325
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]);
338 }
339 close(fd);
340 f[l] = '\0';
341
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);
351 }
352 s = p+1;
353 }
354 }
355 vtfree(f);
356 }
357
358 if(r == 0)
359 werrstr("errors in . %#q", argv[0]);
360 return r;
361 }
362
363 static int
364 cmdDflag(int argc, char* argv[])
365 {
366 char *usage;
367
368 usage = "usage: dflag";
369
370 ARGBEGIN{
371 default:
372 return cliError(usage);
373 }ARGEND
374 if(argc)
375 return cliError(usage);
376
377 Dflag ^= 1;
378 consPrint("dflag %d\n", Dflag);
379
380 return 1;
381 }
382
383 static int
384 cmdEcho(int argc, char* argv[])
385 {
386 char *usage;
387 int i, nflag;
388
389 nflag = 0;
390 usage = "usage: echo [-n] ...";
391
392 ARGBEGIN{
393 default:
394 return cliError(usage);
395 case 'n':
396 nflag = 1;
397 break;
398 }ARGEND
399
400 for(i = 0; i < argc; i++){
401 if(i != 0)
402 consPrint(" %s", argv[i]);
403 else
404 consPrint(argv[i]);
405 }
406 if(!nflag)
407 consPrint("\n");
408
409 return 1;
410 }
411
412 static int
413 cmdBind(int argc, char* argv[])
414 {
415 ulong flag = 0;
416 char *usage;
417
418 usage = "usage: bind [-b|-a|-c|-bc|-ac] new old";
419
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
433
434 if(argc != 2 || (flag&MAFTER)&&(flag&MBEFORE))
435 return cliError(usage);
436
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]);
446 }
447 #endif
448 return 1;
449 }
450
451 int
452 cmdInit(void)
453 {
454 cbox.confd[0] = cbox.confd[1] = -1;
455
456 cliAddCmd(".", cmdDot);
457 cliAddCmd("9p", cmd9p);
458 cliAddCmd("dflag", cmdDflag);
459 cliAddCmd("echo", cmdEcho);
460 cliAddCmd("bind", cmdBind);
461
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;
469
470 }
471 cbox.con->isconsole = 1;
472
473 return 1;
474 }