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