chandial.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include "../ip/ip.h"
  16. typedef struct DS DS;
  17. static Chan* call(char*, char*, DS*);
  18. static void _dial_string_parse(char*, DS*);
  19. enum
  20. {
  21. Maxstring= 128,
  22. };
  23. struct DS
  24. {
  25. char buf[Maxstring]; /* dist string */
  26. char *netdir;
  27. char *proto;
  28. char *rem;
  29. char *local; /* other args */
  30. char *dir;
  31. Chan **ctlp;
  32. };
  33. /*
  34. * the dialstring is of the form '[/net/]proto!dest'
  35. */
  36. Chan*
  37. chandial(char *dest, char *local, char *dir, Chan **ctlp)
  38. {
  39. DS ds;
  40. char clone[Maxpath];
  41. ds.local = local;
  42. ds.dir = dir;
  43. ds.ctlp = ctlp;
  44. _dial_string_parse(dest, &ds);
  45. if(ds.netdir == 0)
  46. ds.netdir = "/net";
  47. /* no connection server, don't translate */
  48. snprint(clone, sizeof(clone), "%s/%s/clone", ds.netdir, ds.proto);
  49. return call(clone, ds.rem, &ds);
  50. }
  51. static Chan*
  52. call(char *clone, char *dest, DS *ds)
  53. {
  54. Mach *m = machp();
  55. int n;
  56. Chan *dchan, *cchan;
  57. char name[Maxpath], data[Maxpath], *p;
  58. cchan = namec(clone, Aopen, ORDWR, 0);
  59. /* get directory name */
  60. if(waserror()){
  61. cclose(cchan);
  62. nexterror();
  63. }
  64. n = cchan->dev->read(cchan, name, sizeof(name)-1, 0);
  65. name[n] = 0;
  66. for(p = name; *p == ' '; p++)
  67. ;
  68. snprint(name, sizeof name, "%lud", strtoul(p, 0, 0));
  69. p = strrchr(clone, '/');
  70. *p = 0;
  71. if(ds->dir)
  72. snprint(ds->dir, Maxpath, "%s/%s", clone, name);
  73. snprint(data, sizeof(data), "%s/%s/data", clone, name);
  74. /* connect */
  75. if(ds->local)
  76. snprint(name, sizeof(name), "connect %s %s", dest, ds->local);
  77. else
  78. snprint(name, sizeof(name), "connect %s", dest);
  79. cchan->dev->write(cchan, name, strlen(name), 0);
  80. /* open data connection */
  81. dchan = namec(data, Aopen, ORDWR, 0);
  82. if(ds->ctlp)
  83. *ds->ctlp = cchan;
  84. else
  85. cclose(cchan);
  86. poperror();
  87. return dchan;
  88. }
  89. /*
  90. * parse a dial string
  91. */
  92. static void
  93. _dial_string_parse(char *str, DS *ds)
  94. {
  95. char *p, *p2;
  96. strncpy(ds->buf, str, Maxstring);
  97. ds->buf[Maxstring-1] = 0;
  98. p = strchr(ds->buf, '!');
  99. if(p == 0) {
  100. ds->netdir = 0;
  101. ds->proto = "net";
  102. ds->rem = ds->buf;
  103. } else {
  104. if(*ds->buf != '/' && *ds->buf != '#'){
  105. ds->netdir = 0;
  106. ds->proto = ds->buf;
  107. } else {
  108. for(p2 = p; *p2 != '/'; p2--)
  109. ;
  110. *p2++ = 0;
  111. ds->netdir = ds->buf;
  112. ds->proto = p2;
  113. }
  114. *p = 0;
  115. ds->rem = p + 1;
  116. }
  117. }