| #include <u.h> |
| #include <libc.h> |
| #include <auth.h> |
| #include <thread.h> |
| |
| enum { |
| Encnone, |
| Encssl, |
| Enctls, |
| }; |
| |
| static char *encprotos[] = { |
| [Encnone] = "clear", |
| [Encssl] = "ssl", |
| [Enctls] = "tls", |
| nil, |
| }; |
| |
| char *keyspec = ""; |
| char *filterp; |
| char *ealgs = "rc4_256 sha1"; |
| int encproto = Encnone; |
| AuthInfo *ai; |
| int debug; |
| int doauth = 1; |
| int timedout; |
| |
| int connectez(char*, char*); |
| void sysfatal(char*, ...); |
| void usage(void); |
| int filter(int, char *, char *); |
| |
| int |
| catcher(void *v, char *msg) |
| { |
| timedout = 1; |
| if(strcmp(msg, "alarm") == 0) |
| return 1; |
| return 0; |
| } |
| |
| static int |
| lookup(char *s, char *l[]) |
| { |
| int i; |
| |
| for (i = 0; l[i] != 0; i++) |
| if (strcmp(l[i], s) == 0) |
| return i; |
| return -1; |
| } |
| |
| static char* |
| srvname(char *addr) |
| { |
| int i; |
| |
| for(i=0; i<strlen(addr); i++){ |
| if(addr[i] == '!') |
| addr[i] = ':'; |
| } |
| return addr; |
| } |
| |
| void |
| threadmain(int argc, char **argv) |
| { |
| char *mntpt, *srvpost, srvfile[64]; |
| int fd; |
| |
| quotefmtinstall(); |
| srvpost = nil; |
| ARGBEGIN{ |
| case 'A': |
| doauth = 0; |
| break; |
| case 'd': |
| debug++; |
| break; |
| case 'E': |
| if ((encproto = lookup(EARGF(usage()), encprotos)) < 0) |
| usage(); |
| break; |
| case 'e': |
| ealgs = EARGF(usage()); |
| if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) |
| ealgs = nil; |
| break; |
| case 'k': |
| keyspec = EARGF(usage()); |
| break; |
| case 'p': |
| filterp = unsharp("#9/bin/aan"); |
| break; |
| case 's': |
| srvpost = EARGF(usage()); |
| break; |
| default: |
| usage(); |
| }ARGEND; |
| |
| mntpt = 0; /* to shut up compiler */ |
| switch(argc) { |
| case 2: |
| mntpt = argv[1]; |
| break; |
| case 3: |
| mntpt = argv[2]; |
| break; |
| default: |
| usage(); |
| } |
| |
| if(encproto != Encnone) |
| sysfatal("%s: tls and ssl have not yet been implemented", argv[0]); |
| |
| threadnotify(catcher, 1); |
| alarm(60*1000); |
| |
| fd = connectez(argv[0], argv[1]); |
| |
| fprint(fd, "impo %s %s\n", filterp? "aan": "nofilter", |
| encprotos[encproto]); |
| |
| if (filterp) |
| fd = filter(fd, filterp, argv[0]); |
| |
| if(srvpost == nil) |
| srvpost = srvname(argv[0]); |
| sprint(srvfile, "%s", srvpost); |
| |
| if(post9pservice(fd, srvfile, mntpt) < 0) |
| sysfatal("can't post %s: %r", argv[1]); |
| alarm(0); |
| |
| threadexitsall(0); |
| } |
| |
| /* the name "connect" is special */ |
| int |
| connectez(char *system, char *tree) |
| { |
| char buf[ERRMAX], *na; |
| int fd, n; |
| char *authp; |
| |
| na = netmkaddr(system, "tcp", "exportfs"); |
| threadsetname("dial %s", na); |
| if((fd = dial(na, nil, nil, nil)) < 0) |
| sysfatal("can't dial %s: %r", system); |
| |
| if(doauth){ |
| authp = "p9any"; |
| threadsetname("auth_proxy auth_getkey proto=%q role=client %s", |
| authp, keyspec); |
| ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", |
| authp, keyspec); |
| if(ai == nil) |
| sysfatal("%r: %s", system); |
| } |
| |
| threadsetname("writing tree name %s", tree); |
| n = write(fd, tree, strlen(tree)); |
| if(n < 0) |
| sysfatal("can't write tree: %r"); |
| |
| strcpy(buf, "can't read tree"); |
| |
| threadsetname("awaiting OK for %s", tree); |
| n = read(fd, buf, sizeof buf - 1); |
| if(n!=2 || buf[0]!='O' || buf[1]!='K'){ |
| if (timedout) |
| sysfatal("timed out connecting to %s", na); |
| buf[sizeof buf - 1] = '\0'; |
| sysfatal("bad remote tree: %s", buf); |
| } |
| |
| return fd; |
| } |
| |
| void |
| usage(void) |
| { |
| fprint(2, "usage: 9import [-A] [-E clear|ssl|tls] " |
| "[-e 'crypt auth'|clear] [-k keypattern] [-p] [-s srv] host remotefs [mountpoint]\n"); |
| threadexitsall("usage"); |
| } |
| |
| /* Network on fd1, mount driver on fd0 */ |
| int |
| filter(int fd, char *cmd, char *host) |
| { |
| int p[2], len, argc; |
| char newport[256], buf[256], *s; |
| char *argv[16], *file, *pbuf; |
| |
| if ((len = read(fd, newport, sizeof newport - 1)) < 0) |
| sysfatal("filter: cannot write port; %r"); |
| newport[len] = '\0'; |
| |
| if ((s = strchr(newport, '!')) == nil) |
| sysfatal("filter: illegally formatted port %s", newport); |
| |
| strecpy(buf, buf+sizeof buf, netmkaddr(host, "tcp", "0")); |
| pbuf = strrchr(buf, '!'); |
| strecpy(pbuf, buf+sizeof buf, s); |
| |
| if(debug) |
| fprint(2, "filter: remote port %s\n", newport); |
| |
| argc = tokenize(cmd, argv, nelem(argv)-2); |
| if (argc == 0) |
| sysfatal("filter: empty command"); |
| argv[argc++] = "-c"; |
| argv[argc++] = buf; |
| argv[argc] = nil; |
| file = argv[0]; |
| if (s = strrchr(argv[0], '/')) |
| argv[0] = s+1; |
| |
| if(pipe(p) < 0) |
| sysfatal("pipe: %r"); |
| |
| switch(rfork(RFNOWAIT|RFPROC|RFFDG)) { |
| case -1: |
| sysfatal("rfork record module: %r"); |
| case 0: |
| dup(p[0], 1); |
| dup(p[0], 0); |
| close(p[0]); |
| close(p[1]); |
| exec(file, argv); |
| sysfatal("exec record module: %r"); |
| default: |
| close(fd); |
| close(p[0]); |
| } |
| return p[1]; |
| } |