xref: /plan9/sys/src/cmd/aux/9pcon.c (revision ab3dc52f122c98aa4bc2bd64bd2292bb7b80fba2)
19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <auth.h>
49a747e4fSDavid du Colombier #include <fcall.h>
59a747e4fSDavid du Colombier #include <bio.h>
69a747e4fSDavid du Colombier 
79a747e4fSDavid du Colombier uint messagesize = 65536;	/* just a buffer size */
89a747e4fSDavid du Colombier 
99a747e4fSDavid du Colombier void
usage(void)109a747e4fSDavid du Colombier usage(void)
119a747e4fSDavid du Colombier {
129a747e4fSDavid du Colombier 	fprint(2, "usage: aux/9pcon [-m messagesize] /srv/service | -c command | -n networkaddress\n");
139a747e4fSDavid du Colombier 	exits("usage");
149a747e4fSDavid du Colombier }
159a747e4fSDavid du Colombier 
169a747e4fSDavid du Colombier int
connectcmd(char * cmd)179a747e4fSDavid du Colombier connectcmd(char *cmd)
189a747e4fSDavid du Colombier {
199a747e4fSDavid du Colombier 	int p[2];
209a747e4fSDavid du Colombier 
219a747e4fSDavid du Colombier 	if(pipe(p) < 0)
229a747e4fSDavid du Colombier 		return -1;
239a747e4fSDavid du Colombier 	switch(fork()){
249a747e4fSDavid du Colombier 	case -1:
259a747e4fSDavid du Colombier 		fprint(2, "fork failed: %r\n");
269a747e4fSDavid du Colombier 		_exits("exec");
279a747e4fSDavid du Colombier 	case 0:
289a747e4fSDavid du Colombier 		dup(p[0], 0);
299a747e4fSDavid du Colombier 		dup(p[0], 1);
309a747e4fSDavid du Colombier 		close(p[1]);
319a747e4fSDavid du Colombier 		execl("/bin/rc", "rc", "-c", cmd, nil);
329a747e4fSDavid du Colombier 		fprint(2, "exec failed: %r\n");
339a747e4fSDavid du Colombier 		_exits("exec");
349a747e4fSDavid du Colombier 	default:
359a747e4fSDavid du Colombier 		close(p[0]);
369a747e4fSDavid du Colombier 		return p[1];
379a747e4fSDavid du Colombier 	}
389a747e4fSDavid du Colombier }
399a747e4fSDavid du Colombier 
409a747e4fSDavid du Colombier void
watch(int fd)419a747e4fSDavid du Colombier watch(int fd)
429a747e4fSDavid du Colombier {
439a747e4fSDavid du Colombier 	int n;
449a747e4fSDavid du Colombier 	uchar *buf;
459a747e4fSDavid du Colombier 	Fcall f;
469a747e4fSDavid du Colombier 
479a747e4fSDavid du Colombier 	buf = malloc(messagesize);
489a747e4fSDavid du Colombier 	if(buf == nil)
499a747e4fSDavid du Colombier 		sysfatal("out of memory");
509a747e4fSDavid du Colombier 
519a747e4fSDavid du Colombier 	while((n = read9pmsg(fd, buf, messagesize)) > 0){
529a747e4fSDavid du Colombier 		if(convM2S(buf, n, &f) == 0){
539a747e4fSDavid du Colombier 			print("convM2S: %r\n");
549a747e4fSDavid du Colombier 			continue;
559a747e4fSDavid du Colombier 		}
569a747e4fSDavid du Colombier 		print("\t<- %F\n", &f);
579a747e4fSDavid du Colombier 	}
589a747e4fSDavid du Colombier 	if(n == 0)
599a747e4fSDavid du Colombier 		print("server eof\n");
609a747e4fSDavid du Colombier 	else
619a747e4fSDavid du Colombier 		print("read9pmsg from server: %r\n");
629a747e4fSDavid du Colombier }
639a747e4fSDavid du Colombier 
649a747e4fSDavid du Colombier char*
tversion(Fcall * f,int,char ** argv)659a747e4fSDavid du Colombier tversion(Fcall *f, int, char **argv)
669a747e4fSDavid du Colombier {
679a747e4fSDavid du Colombier 	f->msize = atoi(argv[0]);
689a747e4fSDavid du Colombier 	if(f->msize > messagesize)
699a747e4fSDavid du Colombier 		return "message size too big; use -m option on command line";
709a747e4fSDavid du Colombier 	f->version = argv[1];
719a747e4fSDavid du Colombier 	return nil;
729a747e4fSDavid du Colombier }
739a747e4fSDavid du Colombier 
749a747e4fSDavid du Colombier char*
tauth(Fcall * f,int,char ** argv)759a747e4fSDavid du Colombier tauth(Fcall *f, int, char **argv)
769a747e4fSDavid du Colombier {
779a747e4fSDavid du Colombier 	f->afid = atoi(argv[0]);
789a747e4fSDavid du Colombier 	f->uname = argv[1];
799a747e4fSDavid du Colombier 	f->aname = argv[2];
809a747e4fSDavid du Colombier 	return nil;
819a747e4fSDavid du Colombier }
829a747e4fSDavid du Colombier 
839a747e4fSDavid du Colombier char*
tflush(Fcall * f,int,char ** argv)849a747e4fSDavid du Colombier tflush(Fcall *f, int, char **argv)
859a747e4fSDavid du Colombier {
869a747e4fSDavid du Colombier 	f->oldtag = atoi(argv[0]);
879a747e4fSDavid du Colombier 	return nil;
889a747e4fSDavid du Colombier }
899a747e4fSDavid du Colombier 
909a747e4fSDavid du Colombier char*
tattach(Fcall * f,int,char ** argv)919a747e4fSDavid du Colombier tattach(Fcall *f, int, char **argv)
929a747e4fSDavid du Colombier {
939a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
949a747e4fSDavid du Colombier 	f->afid = atoi(argv[1]);
959a747e4fSDavid du Colombier 	f->uname = argv[2];
969a747e4fSDavid du Colombier 	f->aname = argv[3];
979a747e4fSDavid du Colombier 	return nil;
989a747e4fSDavid du Colombier }
999a747e4fSDavid du Colombier 
1009a747e4fSDavid du Colombier char*
twalk(Fcall * f,int argc,char ** argv)1019a747e4fSDavid du Colombier twalk(Fcall *f, int argc, char **argv)
1029a747e4fSDavid du Colombier {
1039a747e4fSDavid du Colombier 	int i;
1049a747e4fSDavid du Colombier 
1059a747e4fSDavid du Colombier 	if(argc < 2)
1069a747e4fSDavid du Colombier 		return "usage: Twalk tag fid newfid [name...]";
1079a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
1089a747e4fSDavid du Colombier 	f->newfid = atoi(argv[1]);
1099a747e4fSDavid du Colombier 	f->nwname = argc-2;
1109a747e4fSDavid du Colombier 	if(f->nwname > MAXWELEM)
1119a747e4fSDavid du Colombier 		return "too many names";
1129a747e4fSDavid du Colombier 	for(i=0; i<argc-2; i++)
1139a747e4fSDavid du Colombier 		f->wname[i] = argv[2+i];
1149a747e4fSDavid du Colombier 	return nil;
1159a747e4fSDavid du Colombier }
1169a747e4fSDavid du Colombier 
1179a747e4fSDavid du Colombier char*
topen(Fcall * f,int,char ** argv)1189a747e4fSDavid du Colombier topen(Fcall *f, int, char **argv)
1199a747e4fSDavid du Colombier {
1209a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
1219a747e4fSDavid du Colombier 	f->mode = atoi(argv[1]);
1229a747e4fSDavid du Colombier 	return nil;
1239a747e4fSDavid du Colombier }
1249a747e4fSDavid du Colombier 
1259a747e4fSDavid du Colombier char*
tcreate(Fcall * f,int,char ** argv)1269a747e4fSDavid du Colombier tcreate(Fcall *f, int, char **argv)
1279a747e4fSDavid du Colombier {
1289a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
1299a747e4fSDavid du Colombier 	f->name = argv[1];
130*ab3dc52fSDavid du Colombier 	f->perm = strtoul(argv[2], 0, 8);
1319a747e4fSDavid du Colombier 	f->mode = atoi(argv[3]);
1329a747e4fSDavid du Colombier 	return nil;
1339a747e4fSDavid du Colombier }
1349a747e4fSDavid du Colombier 
1359a747e4fSDavid du Colombier char*
tread(Fcall * f,int,char ** argv)1369a747e4fSDavid du Colombier tread(Fcall *f, int, char **argv)
1379a747e4fSDavid du Colombier {
1389a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
1399a747e4fSDavid du Colombier 	f->offset = strtoll(argv[1], 0, 0);
1409a747e4fSDavid du Colombier 	f->count = strtol(argv[2], 0, 0);
1419a747e4fSDavid du Colombier 	return nil;
1429a747e4fSDavid du Colombier }
1439a747e4fSDavid du Colombier 
1449a747e4fSDavid du Colombier char*
twrite(Fcall * f,int,char ** argv)1459a747e4fSDavid du Colombier twrite(Fcall *f, int, char **argv)
1469a747e4fSDavid du Colombier {
1479a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
1489a747e4fSDavid du Colombier 	f->offset = strtoll(argv[1], 0, 0);
1499a747e4fSDavid du Colombier 	f->data = argv[2];
1509a747e4fSDavid du Colombier 	f->count = strlen(argv[2]);
1519a747e4fSDavid du Colombier 	return nil;
1529a747e4fSDavid du Colombier }
1539a747e4fSDavid du Colombier 
1549a747e4fSDavid du Colombier char*
tclunk(Fcall * f,int,char ** argv)1559a747e4fSDavid du Colombier tclunk(Fcall *f, int, char **argv)
1569a747e4fSDavid du Colombier {
1579a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
1589a747e4fSDavid du Colombier 	return nil;
1599a747e4fSDavid du Colombier }
1609a747e4fSDavid du Colombier 
1619a747e4fSDavid du Colombier char*
tremove(Fcall * f,int,char ** argv)1629a747e4fSDavid du Colombier tremove(Fcall *f, int, char **argv)
1639a747e4fSDavid du Colombier {
1649a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
1659a747e4fSDavid du Colombier 	return nil;
1669a747e4fSDavid du Colombier }
1679a747e4fSDavid du Colombier 
1689a747e4fSDavid du Colombier char*
tstat(Fcall * f,int,char ** argv)1699a747e4fSDavid du Colombier tstat(Fcall *f, int, char **argv)
1709a747e4fSDavid du Colombier {
1719a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
1729a747e4fSDavid du Colombier 	return nil;
1739a747e4fSDavid du Colombier }
1749a747e4fSDavid du Colombier 
1759a747e4fSDavid du Colombier ulong
xstrtoul(char * s)1769a747e4fSDavid du Colombier xstrtoul(char *s)
1779a747e4fSDavid du Colombier {
1789a747e4fSDavid du Colombier 	if(strcmp(s, "~0") == 0)
1799a747e4fSDavid du Colombier 		return ~0UL;
1809a747e4fSDavid du Colombier 	return strtoul(s, 0, 0);
1819a747e4fSDavid du Colombier }
1829a747e4fSDavid du Colombier 
1839a747e4fSDavid du Colombier uvlong
xstrtoull(char * s)1849a747e4fSDavid du Colombier xstrtoull(char *s)
1859a747e4fSDavid du Colombier {
1869a747e4fSDavid du Colombier 	if(strcmp(s, "~0") == 0)
1879a747e4fSDavid du Colombier 		return ~0ULL;
1889a747e4fSDavid du Colombier 	return strtoull(s, 0, 0);
1899a747e4fSDavid du Colombier }
1909a747e4fSDavid du Colombier 
1919a747e4fSDavid du Colombier char*
twstat(Fcall * f,int,char ** argv)1929a747e4fSDavid du Colombier twstat(Fcall *f, int, char **argv)
1939a747e4fSDavid du Colombier {
1949a747e4fSDavid du Colombier 	static uchar buf[DIRMAX];
1959a747e4fSDavid du Colombier 	Dir d;
1969a747e4fSDavid du Colombier 
1979a747e4fSDavid du Colombier 	memset(&d, 0, sizeof d);
1989a747e4fSDavid du Colombier 	nulldir(&d);
1999a747e4fSDavid du Colombier 	d.name = argv[1];
2009a747e4fSDavid du Colombier 	d.uid = argv[2];
2019a747e4fSDavid du Colombier 	d.gid = argv[3];
2029a747e4fSDavid du Colombier 	d.mode = xstrtoul(argv[4]);
2039a747e4fSDavid du Colombier 	d.mtime = xstrtoul(argv[5]);
2049a747e4fSDavid du Colombier 	d.length = xstrtoull(argv[6]);
2059a747e4fSDavid du Colombier 
2069a747e4fSDavid du Colombier 	f->fid = atoi(argv[0]);
2079a747e4fSDavid du Colombier 	f->stat = buf;
2089a747e4fSDavid du Colombier 	f->nstat = convD2M(&d, buf, sizeof buf);
2099a747e4fSDavid du Colombier 	if(f->nstat < BIT16SZ)
2109a747e4fSDavid du Colombier 		return "convD2M failed (internal error)";
2119a747e4fSDavid du Colombier 
2129a747e4fSDavid du Colombier 	return nil;
2139a747e4fSDavid du Colombier }
2149a747e4fSDavid du Colombier 
2159a747e4fSDavid du Colombier int taggen;
2169a747e4fSDavid du Colombier 
2179a747e4fSDavid du Colombier char*
settag(Fcall *,int,char ** argv)2189a747e4fSDavid du Colombier settag(Fcall*, int, char **argv)
2199a747e4fSDavid du Colombier {
2209a747e4fSDavid du Colombier 	static char buf[120];
2219a747e4fSDavid du Colombier 
2229a747e4fSDavid du Colombier 	taggen = atoi(argv[0])-1;
2239a747e4fSDavid du Colombier 	snprint(buf, sizeof buf, "next tag is %d", taggen+1);
2249a747e4fSDavid du Colombier 	return buf;
2259a747e4fSDavid du Colombier }
2269a747e4fSDavid du Colombier 
2279a747e4fSDavid du Colombier typedef struct Cmd Cmd;
2289a747e4fSDavid du Colombier struct Cmd {
2299a747e4fSDavid du Colombier 	char *name;
2309a747e4fSDavid du Colombier 	int type;
2319a747e4fSDavid du Colombier 	int argc;
2329a747e4fSDavid du Colombier 	char *usage;
2339a747e4fSDavid du Colombier 	char *(*fn)(Fcall *f, int, char**);
2349a747e4fSDavid du Colombier };
2359a747e4fSDavid du Colombier 
2369a747e4fSDavid du Colombier Cmd msg9p[] = {
2379a747e4fSDavid du Colombier 	"Tversion", Tversion, 2, "messagesize version", tversion,
2389a747e4fSDavid du Colombier 	"Tauth", Tauth, 3, "afid uname aname", tauth,
2399a747e4fSDavid du Colombier 	"Tflush", Tflush, 1, "oldtag", tflush,
2409a747e4fSDavid du Colombier 	"Tattach", Tattach, 4, "fid afid uname aname", tattach,
2419a747e4fSDavid du Colombier 	"Twalk", Twalk, 0, "fid newfid [name...]", twalk,
2429a747e4fSDavid du Colombier 	"Topen", Topen, 2, "fid mode", topen,
2439a747e4fSDavid du Colombier 	"Tcreate", Tcreate, 4, "fid name perm mode", tcreate,
2449a747e4fSDavid du Colombier 	"Tread", Tread, 3, "fid offset count", tread,
2459a747e4fSDavid du Colombier 	"Twrite", Twrite, 3, "fid offset data", twrite,
2469a747e4fSDavid du Colombier 	"Tclunk", Tclunk, 1, "fid", tclunk,
2479a747e4fSDavid du Colombier 	"Tremove", Tremove, 1, "fid", tremove,
2489a747e4fSDavid du Colombier 	"Tstat", Tstat, 1, "fid", tstat,
2499a747e4fSDavid du Colombier 	"Twstat", Twstat, 7, "fid name uid gid mode mtime length", twstat,
2509a747e4fSDavid du Colombier 	"nexttag", 0, 0, "", settag,
2519a747e4fSDavid du Colombier };
2529a747e4fSDavid du Colombier 
2539a747e4fSDavid du Colombier void
shell9p(int fd)2549a747e4fSDavid du Colombier shell9p(int fd)
2559a747e4fSDavid du Colombier {
2569a747e4fSDavid du Colombier 	char *e, *f[10], *p;
2579a747e4fSDavid du Colombier 	uchar *buf;
2589a747e4fSDavid du Colombier 	int i, n, nf;
2599a747e4fSDavid du Colombier 	Biobuf b;
2609a747e4fSDavid du Colombier 	Fcall t;
2619a747e4fSDavid du Colombier 
2629a747e4fSDavid du Colombier 	buf = malloc(messagesize);
2639a747e4fSDavid du Colombier 	if(buf == nil){
2649a747e4fSDavid du Colombier 		fprint(2, "out of memory\n");
2659a747e4fSDavid du Colombier 		return;
2669a747e4fSDavid du Colombier 	}
2679a747e4fSDavid du Colombier 
2689a747e4fSDavid du Colombier 	taggen = 0;
2699a747e4fSDavid du Colombier 	Binit(&b, 0, OREAD);
2709a747e4fSDavid du Colombier 	while(p = Brdline(&b, '\n')){
2719a747e4fSDavid du Colombier 		p[Blinelen(&b)-1] = '\0';
2729a747e4fSDavid du Colombier 		if(p[0] == '#')
2739a747e4fSDavid du Colombier 			continue;
2749a747e4fSDavid du Colombier 		if((nf = tokenize(p, f, nelem(f))) == 0)
2759a747e4fSDavid du Colombier 			continue;
2769a747e4fSDavid du Colombier 		for(i=0; i<nelem(msg9p); i++)
2779a747e4fSDavid du Colombier 			if(strcmp(f[0], msg9p[i].name) == 0)
2789a747e4fSDavid du Colombier 				break;
2799a747e4fSDavid du Colombier 		if(i == nelem(msg9p)){
2809a747e4fSDavid du Colombier 			fprint(2, "?unknown message\n");
2819a747e4fSDavid du Colombier 			continue;
2829a747e4fSDavid du Colombier 		}
2839a747e4fSDavid du Colombier 		memset(&t, 0, sizeof t);
2849a747e4fSDavid du Colombier 		t.type = msg9p[i].type;
2853ff48bf5SDavid du Colombier 		if(t.type == Tversion)
2863ff48bf5SDavid du Colombier 			t.tag = NOTAG;
2873ff48bf5SDavid du Colombier 		else
2889a747e4fSDavid du Colombier 			t.tag = ++taggen;
2899a747e4fSDavid du Colombier 		if(nf < 1 || (msg9p[i].argc && nf != 1+msg9p[i].argc)){
2909a747e4fSDavid du Colombier 			fprint(2, "?usage: %s %s\n", msg9p[i].name, msg9p[i].usage);
2919a747e4fSDavid du Colombier 			continue;
2929a747e4fSDavid du Colombier 		}
2939a747e4fSDavid du Colombier 		if(e = msg9p[i].fn(&t, nf-1, f+1)){
2949a747e4fSDavid du Colombier 			fprint(2, "?%s\n", e);
2959a747e4fSDavid du Colombier 			continue;
2969a747e4fSDavid du Colombier 		}
2979a747e4fSDavid du Colombier 		n = convS2M(&t, buf, messagesize);
2989a747e4fSDavid du Colombier 		if(n <= BIT16SZ){
2999a747e4fSDavid du Colombier 			fprint(2, "?message too large for buffer\n");
3009a747e4fSDavid du Colombier 			continue;
3019a747e4fSDavid du Colombier 		}
3029a747e4fSDavid du Colombier 		if(write(fd, buf, n) != n){
3039a747e4fSDavid du Colombier 			fprint(2, "?write fails: %r\n");
3049a747e4fSDavid du Colombier 			break;
3059a747e4fSDavid du Colombier 		}
3069a747e4fSDavid du Colombier 		print("\t-> %F\n", &t);
3079a747e4fSDavid du Colombier 	}
3089a747e4fSDavid du Colombier }
3099a747e4fSDavid du Colombier 
3109a747e4fSDavid du Colombier void
main(int argc,char ** argv)3119a747e4fSDavid du Colombier main(int argc, char **argv)
3129a747e4fSDavid du Colombier {
3139a747e4fSDavid du Colombier 	int fd, pid, cmd, net;
3149a747e4fSDavid du Colombier 
3159a747e4fSDavid du Colombier 	cmd = 0;
3169a747e4fSDavid du Colombier 	net = 0;
3179a747e4fSDavid du Colombier 	ARGBEGIN{
3189a747e4fSDavid du Colombier 	case 'c':
3199a747e4fSDavid du Colombier 		cmd = 1;
3209a747e4fSDavid du Colombier 		break;
3219a747e4fSDavid du Colombier 	case 'm':
3229a747e4fSDavid du Colombier 		messagesize = atoi(EARGF(usage()));
3239a747e4fSDavid du Colombier 		break;
3249a747e4fSDavid du Colombier 	case 'n':
3259a747e4fSDavid du Colombier 		net = 1;
3269a747e4fSDavid du Colombier 		break;
3279a747e4fSDavid du Colombier 	default:
3289a747e4fSDavid du Colombier 		usage();
3299a747e4fSDavid du Colombier 	}ARGEND
3309a747e4fSDavid du Colombier 
3319a747e4fSDavid du Colombier 	fmtinstall('F', fcallfmt);
3329a747e4fSDavid du Colombier 	fmtinstall('D', dirfmt);
3339a747e4fSDavid du Colombier 	fmtinstall('M', dirmodefmt);
3349a747e4fSDavid du Colombier 
3359a747e4fSDavid du Colombier 	if(argc != 1)
3369a747e4fSDavid du Colombier 		usage();
3379a747e4fSDavid du Colombier 
3389a747e4fSDavid du Colombier 	if(cmd && net)
3399a747e4fSDavid du Colombier 		usage();
3409a747e4fSDavid du Colombier 
3419a747e4fSDavid du Colombier 	if(cmd)
3429a747e4fSDavid du Colombier 		fd = connectcmd(argv[0]);
3439a747e4fSDavid du Colombier 	else if(net){
3449a747e4fSDavid du Colombier 		fd = dial(netmkaddr(argv[0], "net", "9fs"), 0, 0, 0);
3459a747e4fSDavid du Colombier 		if(fd < 0)
3469a747e4fSDavid du Colombier 			sysfatal("dial: %r");
3479a747e4fSDavid du Colombier 	}else{
3489a747e4fSDavid du Colombier 		fd = open(argv[0], ORDWR);
3499a747e4fSDavid du Colombier 		if(fd < 0)
3509a747e4fSDavid du Colombier 			sysfatal("open: %r");
3519a747e4fSDavid du Colombier 	}
3529a747e4fSDavid du Colombier 
3539a747e4fSDavid du Colombier 	switch(pid = rfork(RFPROC|RFMEM)){
3549a747e4fSDavid du Colombier 	case -1:
3559a747e4fSDavid du Colombier 		sysfatal("rfork: %r");
3569a747e4fSDavid du Colombier 		break;
3579a747e4fSDavid du Colombier 	case 0:
3589a747e4fSDavid du Colombier 		watch(fd);
3599a747e4fSDavid du Colombier 		postnote(PNPROC, getppid(), "kill");
3609a747e4fSDavid du Colombier 		break;
3619a747e4fSDavid du Colombier 	default:
3629a747e4fSDavid du Colombier 		shell9p(fd);
3639a747e4fSDavid du Colombier 		postnote(PNPROC, pid, "kill");
3649a747e4fSDavid du Colombier 		break;
3659a747e4fSDavid du Colombier 	}
3669a747e4fSDavid du Colombier 	exits(nil);
3679a747e4fSDavid du Colombier }
368