9import.c (4391B)
1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 #include <thread.h> 5 6 enum { 7 Encnone, 8 Encssl, 9 Enctls, 10 }; 11 12 static char *encprotos[] = { 13 [Encnone] = "clear", 14 [Encssl] = "ssl", 15 [Enctls] = "tls", 16 nil, 17 }; 18 19 char *keyspec = ""; 20 char *filterp; 21 char *ealgs = "rc4_256 sha1"; 22 int encproto = Encnone; 23 AuthInfo *ai; 24 int debug; 25 int doauth = 1; 26 int timedout; 27 28 int connectez(char*, char*); 29 void sysfatal(char*, ...); 30 void usage(void); 31 int filter(int, char *, char *); 32 33 int 34 catcher(void *v, char *msg) 35 { 36 timedout = 1; 37 if(strcmp(msg, "alarm") == 0) 38 return 1; 39 return 0; 40 } 41 42 static int 43 lookup(char *s, char *l[]) 44 { 45 int i; 46 47 for (i = 0; l[i] != 0; i++) 48 if (strcmp(l[i], s) == 0) 49 return i; 50 return -1; 51 } 52 53 static char* 54 srvname(char *addr) 55 { 56 int i; 57 58 for(i=0; i<strlen(addr); i++){ 59 if(addr[i] == '!') 60 addr[i] = ':'; 61 } 62 return addr; 63 } 64 65 void 66 threadmain(int argc, char **argv) 67 { 68 char *mntpt, *srvpost, srvfile[64]; 69 int fd; 70 71 quotefmtinstall(); 72 srvpost = nil; 73 ARGBEGIN{ 74 case 'A': 75 doauth = 0; 76 break; 77 case 'd': 78 debug++; 79 break; 80 case 'E': 81 if ((encproto = lookup(EARGF(usage()), encprotos)) < 0) 82 usage(); 83 break; 84 case 'e': 85 ealgs = EARGF(usage()); 86 if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) 87 ealgs = nil; 88 break; 89 case 'k': 90 keyspec = EARGF(usage()); 91 break; 92 case 'p': 93 filterp = unsharp("#9/bin/aan"); 94 break; 95 case 's': 96 srvpost = EARGF(usage()); 97 break; 98 default: 99 usage(); 100 }ARGEND; 101 102 mntpt = 0; /* to shut up compiler */ 103 switch(argc) { 104 case 2: 105 mntpt = argv[1]; 106 break; 107 case 3: 108 mntpt = argv[2]; 109 break; 110 default: 111 usage(); 112 } 113 114 if(encproto != Encnone) 115 sysfatal("%s: tls and ssl have not yet been implemented", argv[0]); 116 117 threadnotify(catcher, 1); 118 alarm(60*1000); 119 120 fd = connectez(argv[0], argv[1]); 121 122 fprint(fd, "impo %s %s\n", filterp? "aan": "nofilter", 123 encprotos[encproto]); 124 125 if (filterp) 126 fd = filter(fd, filterp, argv[0]); 127 128 if(srvpost == nil) 129 srvpost = srvname(argv[0]); 130 sprint(srvfile, "%s", srvpost); 131 132 if(post9pservice(fd, srvfile, mntpt) < 0) 133 sysfatal("can't post %s: %r", argv[1]); 134 alarm(0); 135 136 threadexitsall(0); 137 } 138 139 /* the name "connect" is special */ 140 int 141 connectez(char *system, char *tree) 142 { 143 char buf[ERRMAX], *na; 144 int fd, n; 145 char *authp; 146 147 na = netmkaddr(system, "tcp", "exportfs"); 148 threadsetname("dial %s", na); 149 if((fd = dial(na, nil, nil, nil)) < 0) 150 sysfatal("can't dial %s: %r", system); 151 152 if(doauth){ 153 authp = "p9any"; 154 threadsetname("auth_proxy auth_getkey proto=%q role=client %s", 155 authp, keyspec); 156 ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", 157 authp, keyspec); 158 if(ai == nil) 159 sysfatal("%r: %s", system); 160 } 161 162 threadsetname("writing tree name %s", tree); 163 n = write(fd, tree, strlen(tree)); 164 if(n < 0) 165 sysfatal("can't write tree: %r"); 166 167 strcpy(buf, "can't read tree"); 168 169 threadsetname("awaiting OK for %s", tree); 170 n = read(fd, buf, sizeof buf - 1); 171 if(n!=2 || buf[0]!='O' || buf[1]!='K'){ 172 if (timedout) 173 sysfatal("timed out connecting to %s", na); 174 buf[sizeof buf - 1] = '\0'; 175 sysfatal("bad remote tree: %s", buf); 176 } 177 178 return fd; 179 } 180 181 void 182 usage(void) 183 { 184 fprint(2, "usage: 9import [-A] [-E clear|ssl|tls] " 185 "[-e 'crypt auth'|clear] [-k keypattern] [-p] [-s srv] host remotefs [mountpoint]\n"); 186 threadexitsall("usage"); 187 } 188 189 /* Network on fd1, mount driver on fd0 */ 190 int 191 filter(int fd, char *cmd, char *host) 192 { 193 int p[2], len, argc; 194 char newport[256], buf[256], *s; 195 char *argv[16], *file, *pbuf; 196 197 if ((len = read(fd, newport, sizeof newport - 1)) < 0) 198 sysfatal("filter: cannot write port; %r"); 199 newport[len] = '\0'; 200 201 if ((s = strchr(newport, '!')) == nil) 202 sysfatal("filter: illegally formatted port %s", newport); 203 204 strecpy(buf, buf+sizeof buf, netmkaddr(host, "tcp", "0")); 205 pbuf = strrchr(buf, '!'); 206 strecpy(pbuf, buf+sizeof buf, s); 207 208 if(debug) 209 fprint(2, "filter: remote port %s\n", newport); 210 211 argc = tokenize(cmd, argv, nelem(argv)-2); 212 if (argc == 0) 213 sysfatal("filter: empty command"); 214 argv[argc++] = "-c"; 215 argv[argc++] = buf; 216 argv[argc] = nil; 217 file = argv[0]; 218 if (s = strrchr(argv[0], '/')) 219 argv[0] = s+1; 220 221 if(pipe(p) < 0) 222 sysfatal("pipe: %r"); 223 224 switch(rfork(RFNOWAIT|RFPROC|RFFDG)) { 225 case -1: 226 sysfatal("rfork record module: %r"); 227 case 0: 228 dup(p[0], 1); 229 dup(p[0], 0); 230 close(p[0]); 231 close(p[1]); 232 exec(file, argv); 233 sysfatal("exec record module: %r"); 234 default: 235 close(fd); 236 close(p[0]); 237 } 238 return p[1]; 239 }