Ccmd.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 }