dial.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * old single-process version of dial that libthread can cope with
  11. */
  12. #include <u.h>
  13. #include <libc.h>
  14. typedef struct DS DS;
  15. static int call(char*, char*, DS*);
  16. static int csdial(DS*);
  17. static void _dial_string_parse(char*, DS*);
  18. enum
  19. {
  20. Maxstring = 128,
  21. Maxpath = 256,
  22. };
  23. struct DS {
  24. /* dist string */
  25. char buf[Maxstring];
  26. char *netdir;
  27. char *proto;
  28. char *rem;
  29. /* other args */
  30. char *local;
  31. char *dir;
  32. int *cfdp;
  33. };
  34. /*
  35. * the dialstring is of the form '[/net/]proto!dest'
  36. */
  37. int
  38. _threaddial(char *dest, char *local, char *dir, int *cfdp)
  39. {
  40. DS ds;
  41. int rv;
  42. char err[ERRMAX], alterr[ERRMAX];
  43. ds.local = local;
  44. ds.dir = dir;
  45. ds.cfdp = cfdp;
  46. _dial_string_parse(dest, &ds);
  47. if(ds.netdir)
  48. return csdial(&ds);
  49. ds.netdir = "/net";
  50. rv = csdial(&ds);
  51. if(rv >= 0)
  52. return rv;
  53. err[0] = '\0';
  54. errstr(err, sizeof err);
  55. if(strstr(err, "refused") != 0){
  56. werrstr("%s", err);
  57. return rv;
  58. }
  59. ds.netdir = "/net.alt";
  60. rv = csdial(&ds);
  61. if(rv >= 0)
  62. return rv;
  63. alterr[0] = 0;
  64. errstr(alterr, sizeof alterr);
  65. if(strstr(alterr, "translate") || strstr(alterr, "does not exist"))
  66. werrstr("%s", err);
  67. else
  68. werrstr("%s", alterr);
  69. return rv;
  70. }
  71. static int
  72. csdial(DS *ds)
  73. {
  74. int n, fd, rv;
  75. char *p, buf[Maxstring], clone[Maxpath], err[ERRMAX], besterr[ERRMAX];
  76. /*
  77. * open connection server
  78. */
  79. snprint(buf, sizeof(buf), "%s/cs", ds->netdir);
  80. fd = open(buf, ORDWR);
  81. if(fd < 0){
  82. /* no connection server, don't translate */
  83. snprint(clone, sizeof(clone), "%s/%s/clone", ds->netdir, ds->proto);
  84. return call(clone, ds->rem, ds);
  85. }
  86. /*
  87. * ask connection server to translate
  88. */
  89. snprint(buf, sizeof(buf), "%s!%s", ds->proto, ds->rem);
  90. if(write(fd, buf, strlen(buf)) < 0){
  91. close(fd);
  92. return -1;
  93. }
  94. /*
  95. * loop through each address from the connection server till
  96. * we get one that works.
  97. */
  98. *besterr = 0;
  99. rv = -1;
  100. seek(fd, 0, 0);
  101. while((n = read(fd, buf, sizeof(buf) - 1)) > 0){
  102. buf[n] = 0;
  103. p = strchr(buf, ' ');
  104. if(p == 0)
  105. continue;
  106. *p++ = 0;
  107. rv = call(buf, p, ds);
  108. if(rv >= 0)
  109. break;
  110. err[0] = '\0';
  111. errstr(err, sizeof err);
  112. if(strstr(err, "does not exist") == 0)
  113. strcpy(besterr, err);
  114. }
  115. close(fd);
  116. if(rv < 0 && *besterr)
  117. werrstr("%s", besterr);
  118. else
  119. werrstr("%s", err);
  120. return rv;
  121. }
  122. static int
  123. call(char *clone, char *dest, DS *ds)
  124. {
  125. int fd, cfd, n;
  126. char cname[Maxpath], name[Maxpath], data[Maxpath], *p;
  127. /* because cs is in a different name space, replace the mount point */
  128. if(*clone == '/'){
  129. p = strchr(clone+1, '/');
  130. if(p == nil)
  131. p = clone;
  132. else
  133. p++;
  134. } else
  135. p = clone;
  136. snprint(cname, sizeof cname, "%s/%s", ds->netdir, p);
  137. cfd = open(cname, ORDWR);
  138. if(cfd < 0)
  139. return -1;
  140. /* get directory name */
  141. n = read(cfd, name, sizeof(name)-1);
  142. if(n < 0){
  143. close(cfd);
  144. return -1;
  145. }
  146. name[n] = 0;
  147. for(p = name; *p == ' '; p++)
  148. ;
  149. snprint(name, sizeof(name), "%ld", strtoul(p, 0, 0));
  150. p = strrchr(cname, '/');
  151. *p = 0;
  152. if(ds->dir)
  153. snprint(ds->dir, NETPATHLEN, "%s/%s", cname, name);
  154. snprint(data, sizeof(data), "%s/%s/data", cname, name);
  155. /* connect */
  156. if(ds->local)
  157. snprint(name, sizeof(name), "connect %s %s", dest, ds->local);
  158. else
  159. snprint(name, sizeof(name), "connect %s", dest);
  160. if(write(cfd, name, strlen(name)) < 0){
  161. close(cfd);
  162. return -1;
  163. }
  164. /* open data connection */
  165. fd = open(data, ORDWR);
  166. if(fd < 0){
  167. close(cfd);
  168. return -1;
  169. }
  170. if(ds->cfdp)
  171. *ds->cfdp = cfd;
  172. else
  173. close(cfd);
  174. return fd;
  175. }
  176. /*
  177. * parse a dial string
  178. */
  179. static void
  180. _dial_string_parse(char *str, DS *ds)
  181. {
  182. char *p, *p2;
  183. strncpy(ds->buf, str, Maxstring);
  184. ds->buf[Maxstring-1] = 0;
  185. p = strchr(ds->buf, '!');
  186. if(p == 0) {
  187. ds->netdir = 0;
  188. ds->proto = "net";
  189. ds->rem = ds->buf;
  190. } else {
  191. if(*ds->buf != '/' && *ds->buf != '#'){
  192. ds->netdir = 0;
  193. ds->proto = ds->buf;
  194. } else {
  195. for(p2 = p; *p2 != '/'; p2--)
  196. ;
  197. *p2++ = 0;
  198. ds->netdir = ds->buf;
  199. ds->proto = p2;
  200. }
  201. *p = 0;
  202. ds->rem = p + 1;
  203. }
  204. }