summaryrefslogtreecommitdiff
path: root/sys/src/cmd/aux/9pcon.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/aux/9pcon.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/aux/9pcon.c')
-rwxr-xr-xsys/src/cmd/aux/9pcon.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/9pcon.c b/sys/src/cmd/aux/9pcon.c
new file mode 100755
index 000000000..60fbc206f
--- /dev/null
+++ b/sys/src/cmd/aux/9pcon.c
@@ -0,0 +1,367 @@
+#include <u.h>
+#include <libc.h>
+#include <auth.h>
+#include <fcall.h>
+#include <bio.h>
+
+uint messagesize = 65536; /* just a buffer size */
+
+void
+usage(void)
+{
+ fprint(2, "usage: aux/9pcon [-m messagesize] /srv/service | -c command | -n networkaddress\n");
+ exits("usage");
+}
+
+int
+connectcmd(char *cmd)
+{
+ int p[2];
+
+ if(pipe(p) < 0)
+ return -1;
+ switch(fork()){
+ case -1:
+ fprint(2, "fork failed: %r\n");
+ _exits("exec");
+ case 0:
+ dup(p[0], 0);
+ dup(p[0], 1);
+ close(p[1]);
+ execl("/bin/rc", "rc", "-c", cmd, nil);
+ fprint(2, "exec failed: %r\n");
+ _exits("exec");
+ default:
+ close(p[0]);
+ return p[1];
+ }
+}
+
+void
+watch(int fd)
+{
+ int n;
+ uchar *buf;
+ Fcall f;
+
+ buf = malloc(messagesize);
+ if(buf == nil)
+ sysfatal("out of memory");
+
+ while((n = read9pmsg(fd, buf, messagesize)) > 0){
+ if(convM2S(buf, n, &f) == 0){
+ print("convM2S: %r\n");
+ continue;
+ }
+ print("\t<- %F\n", &f);
+ }
+ if(n == 0)
+ print("server eof\n");
+ else
+ print("read9pmsg from server: %r\n");
+}
+
+char*
+tversion(Fcall *f, int, char **argv)
+{
+ f->msize = atoi(argv[0]);
+ if(f->msize > messagesize)
+ return "message size too big; use -m option on command line";
+ f->version = argv[1];
+ return nil;
+}
+
+char*
+tauth(Fcall *f, int, char **argv)
+{
+ f->afid = atoi(argv[0]);
+ f->uname = argv[1];
+ f->aname = argv[2];
+ return nil;
+}
+
+char*
+tflush(Fcall *f, int, char **argv)
+{
+ f->oldtag = atoi(argv[0]);
+ return nil;
+}
+
+char*
+tattach(Fcall *f, int, char **argv)
+{
+ f->fid = atoi(argv[0]);
+ f->afid = atoi(argv[1]);
+ f->uname = argv[2];
+ f->aname = argv[3];
+ return nil;
+}
+
+char*
+twalk(Fcall *f, int argc, char **argv)
+{
+ int i;
+
+ if(argc < 2)
+ return "usage: Twalk tag fid newfid [name...]";
+ f->fid = atoi(argv[0]);
+ f->newfid = atoi(argv[1]);
+ f->nwname = argc-2;
+ if(f->nwname > MAXWELEM)
+ return "too many names";
+ for(i=0; i<argc-2; i++)
+ f->wname[i] = argv[2+i];
+ return nil;
+}
+
+char*
+topen(Fcall *f, int, char **argv)
+{
+ f->fid = atoi(argv[0]);
+ f->mode = atoi(argv[1]);
+ return nil;
+}
+
+char*
+tcreate(Fcall *f, int, char **argv)
+{
+ f->fid = atoi(argv[0]);
+ f->name = argv[1];
+ f->perm = strtoul(argv[2], 0, 8);
+ f->mode = atoi(argv[3]);
+ return nil;
+}
+
+char*
+tread(Fcall *f, int, char **argv)
+{
+ f->fid = atoi(argv[0]);
+ f->offset = strtoll(argv[1], 0, 0);
+ f->count = strtol(argv[2], 0, 0);
+ return nil;
+}
+
+char*
+twrite(Fcall *f, int, char **argv)
+{
+ f->fid = atoi(argv[0]);
+ f->offset = strtoll(argv[1], 0, 0);
+ f->data = argv[2];
+ f->count = strlen(argv[2]);
+ return nil;
+}
+
+char*
+tclunk(Fcall *f, int, char **argv)
+{
+ f->fid = atoi(argv[0]);
+ return nil;
+}
+
+char*
+tremove(Fcall *f, int, char **argv)
+{
+ f->fid = atoi(argv[0]);
+ return nil;
+}
+
+char*
+tstat(Fcall *f, int, char **argv)
+{
+ f->fid = atoi(argv[0]);
+ return nil;
+}
+
+ulong
+xstrtoul(char *s)
+{
+ if(strcmp(s, "~0") == 0)
+ return ~0UL;
+ return strtoul(s, 0, 0);
+}
+
+uvlong
+xstrtoull(char *s)
+{
+ if(strcmp(s, "~0") == 0)
+ return ~0ULL;
+ return strtoull(s, 0, 0);
+}
+
+char*
+twstat(Fcall *f, int, char **argv)
+{
+ static uchar buf[DIRMAX];
+ Dir d;
+
+ memset(&d, 0, sizeof d);
+ nulldir(&d);
+ d.name = argv[1];
+ d.uid = argv[2];
+ d.gid = argv[3];
+ d.mode = xstrtoul(argv[4]);
+ d.mtime = xstrtoul(argv[5]);
+ d.length = xstrtoull(argv[6]);
+
+ f->fid = atoi(argv[0]);
+ f->stat = buf;
+ f->nstat = convD2M(&d, buf, sizeof buf);
+ if(f->nstat < BIT16SZ)
+ return "convD2M failed (internal error)";
+
+ return nil;
+}
+
+int taggen;
+
+char*
+settag(Fcall*, int, char **argv)
+{
+ static char buf[120];
+
+ taggen = atoi(argv[0])-1;
+ snprint(buf, sizeof buf, "next tag is %d", taggen+1);
+ return buf;
+}
+
+typedef struct Cmd Cmd;
+struct Cmd {
+ char *name;
+ int type;
+ int argc;
+ char *usage;
+ char *(*fn)(Fcall *f, int, char**);
+};
+
+Cmd msg9p[] = {
+ "Tversion", Tversion, 2, "messagesize version", tversion,
+ "Tauth", Tauth, 3, "afid uname aname", tauth,
+ "Tflush", Tflush, 1, "oldtag", tflush,
+ "Tattach", Tattach, 4, "fid afid uname aname", tattach,
+ "Twalk", Twalk, 0, "fid newfid [name...]", twalk,
+ "Topen", Topen, 2, "fid mode", topen,
+ "Tcreate", Tcreate, 4, "fid name perm mode", tcreate,
+ "Tread", Tread, 3, "fid offset count", tread,
+ "Twrite", Twrite, 3, "fid offset data", twrite,
+ "Tclunk", Tclunk, 1, "fid", tclunk,
+ "Tremove", Tremove, 1, "fid", tremove,
+ "Tstat", Tstat, 1, "fid", tstat,
+ "Twstat", Twstat, 7, "fid name uid gid mode mtime length", twstat,
+ "nexttag", 0, 0, "", settag,
+};
+
+void
+shell9p(int fd)
+{
+ char *e, *f[10], *p;
+ uchar *buf;
+ int i, n, nf;
+ Biobuf b;
+ Fcall t;
+
+ buf = malloc(messagesize);
+ if(buf == nil){
+ fprint(2, "out of memory\n");
+ return;
+ }
+
+ taggen = 0;
+ Binit(&b, 0, OREAD);
+ while(p = Brdline(&b, '\n')){
+ p[Blinelen(&b)-1] = '\0';
+ if(p[0] == '#')
+ continue;
+ if((nf = tokenize(p, f, nelem(f))) == 0)
+ continue;
+ for(i=0; i<nelem(msg9p); i++)
+ if(strcmp(f[0], msg9p[i].name) == 0)
+ break;
+ if(i == nelem(msg9p)){
+ fprint(2, "?unknown message\n");
+ continue;
+ }
+ memset(&t, 0, sizeof t);
+ t.type = msg9p[i].type;
+ if(t.type == Tversion)
+ t.tag = NOTAG;
+ else
+ t.tag = ++taggen;
+ if(nf < 1 || (msg9p[i].argc && nf != 1+msg9p[i].argc)){
+ fprint(2, "?usage: %s %s\n", msg9p[i].name, msg9p[i].usage);
+ continue;
+ }
+ if(e = msg9p[i].fn(&t, nf-1, f+1)){
+ fprint(2, "?%s\n", e);
+ continue;
+ }
+ n = convS2M(&t, buf, messagesize);
+ if(n <= BIT16SZ){
+ fprint(2, "?message too large for buffer\n");
+ continue;
+ }
+ if(write(fd, buf, n) != n){
+ fprint(2, "?write fails: %r\n");
+ break;
+ }
+ print("\t-> %F\n", &t);
+ }
+}
+
+void
+main(int argc, char **argv)
+{
+ int fd, pid, cmd, net;
+
+ cmd = 0;
+ net = 0;
+ ARGBEGIN{
+ case 'c':
+ cmd = 1;
+ break;
+ case 'm':
+ messagesize = atoi(EARGF(usage()));
+ break;
+ case 'n':
+ net = 1;
+ break;
+ default:
+ usage();
+ }ARGEND
+
+ fmtinstall('F', fcallfmt);
+ fmtinstall('D', dirfmt);
+ fmtinstall('M', dirmodefmt);
+
+ if(argc != 1)
+ usage();
+
+ if(cmd && net)
+ usage();
+
+ if(cmd)
+ fd = connectcmd(argv[0]);
+ else if(net){
+ fd = dial(netmkaddr(argv[0], "net", "9fs"), 0, 0, 0);
+ if(fd < 0)
+ sysfatal("dial: %r");
+ }else{
+ fd = open(argv[0], ORDWR);
+ if(fd < 0)
+ sysfatal("open: %r");
+ }
+
+ switch(pid = rfork(RFPROC|RFMEM)){
+ case -1:
+ sysfatal("rfork: %r");
+ break;
+ case 0:
+ watch(fd);
+ postnote(PNPROC, getppid(), "kill");
+ break;
+ default:
+ shell9p(fd);
+ postnote(PNPROC, pid, "kill");
+ break;
+ }
+ exits(nil);
+}