plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }