announce.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include <stdlib.h>
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <ctype.h>
  8. #include <libnet.h>
  9. #define NAMELEN 28
  10. static int nettrans(char*, char*, int na, char*, int);
  11. /*
  12. * announce a network service.
  13. */
  14. int
  15. announce(char *addr, char *dir)
  16. {
  17. int ctl, n, m;
  18. char buf[3*NAMELEN];
  19. char buf2[3*NAMELEN];
  20. char netdir[2*NAMELEN];
  21. char naddr[3*NAMELEN];
  22. char *cp;
  23. /*
  24. * translate the address
  25. */
  26. if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0)
  27. return -1;
  28. /*
  29. * get a control channel
  30. */
  31. ctl = open(netdir, O_RDWR);
  32. if(ctl<0)
  33. return -1;
  34. cp = strrchr(netdir, '/');
  35. *cp = 0;
  36. /*
  37. * find out which line we have
  38. */
  39. n = sprintf(buf, "%.*s/", 2*NAMELEN+1, netdir);
  40. m = read(ctl, &buf[n], sizeof(buf)-n-1);
  41. if(n<=0){
  42. close(ctl);
  43. return -1;
  44. }
  45. buf[n+m] = 0;
  46. /*
  47. * make the call
  48. */
  49. n = sprintf(buf2, "announce %.*s", 2*NAMELEN, naddr);
  50. if(write(ctl, buf2, n)!=n){
  51. close(ctl);
  52. return -1;
  53. }
  54. /*
  55. * return directory etc.
  56. */
  57. if(dir)
  58. strcpy(dir, buf);
  59. return ctl;
  60. }
  61. /*
  62. * listen for an incoming call
  63. */
  64. int
  65. listen(char *dir, char *newdir)
  66. {
  67. int ctl, n, m;
  68. char buf[3*NAMELEN];
  69. char *cp;
  70. /*
  71. * open listen, wait for a call
  72. */
  73. sprintf(buf, "%.*s/listen", 2*NAMELEN+1, dir);
  74. ctl = open(buf, O_RDWR);
  75. if(ctl < 0)
  76. return -1;
  77. /*
  78. * find out which line we have
  79. */
  80. strcpy(buf, dir);
  81. cp = strrchr(buf, '/');
  82. *++cp = 0;
  83. n = cp-buf;
  84. m = read(ctl, cp, sizeof(buf) - n - 1);
  85. if(n<=0){
  86. close(ctl);
  87. return -1;
  88. }
  89. buf[n+m] = 0;
  90. /*
  91. * return directory etc.
  92. */
  93. if(newdir)
  94. strcpy(newdir, buf);
  95. return ctl;
  96. }
  97. /*
  98. * accept a call, return an fd to the open data file
  99. */
  100. int
  101. accept(int ctl, char *dir)
  102. {
  103. char buf[128];
  104. char *num;
  105. long n;
  106. num = strrchr(dir, '/');
  107. if(num == 0)
  108. num = dir;
  109. else
  110. num++;
  111. sprintf(buf, "accept %s", num);
  112. n = strlen(buf);
  113. write(ctl, buf, n); /* ignore return value, netowrk might not need accepts */
  114. sprintf(buf, "%s/data", dir);
  115. return open(buf, O_RDWR);
  116. }
  117. /*
  118. * reject a call, tell device the reason for the rejection
  119. */
  120. int
  121. reject(int ctl, char *dir, char *cause)
  122. {
  123. char buf[128];
  124. char *num;
  125. long n;
  126. num = strrchr(dir, '/');
  127. if(num == 0)
  128. num = dir;
  129. else
  130. num++;
  131. sprintf(buf, "reject %s %s", num, cause);
  132. n = strlen(buf);
  133. if(write(ctl, buf, n) != n)
  134. return -1;
  135. return 0;
  136. }
  137. /*
  138. * perform the identity translation (in case we can't reach cs)
  139. */
  140. static int
  141. identtrans(char *addr, char *naddr, int na, char *file, int nf)
  142. {
  143. char reply[4*NAMELEN];
  144. char *p;
  145. USED(nf);
  146. /* parse the network */
  147. strncpy(reply, addr, sizeof(reply));
  148. reply[sizeof(reply)-1] = 0;
  149. p = strchr(addr, '!');
  150. if(p)
  151. *p++ = 0;
  152. sprintf(file, "/net/%.*s/clone", na - sizeof("/net//clone"), reply);
  153. strncpy(naddr, p, na);
  154. naddr[na-1] = 0;
  155. return 1;
  156. }
  157. /*
  158. * call up the connection server and get a translation
  159. */
  160. static int
  161. nettrans(char *addr, char *naddr, int na, char *file, int nf)
  162. {
  163. int fd;
  164. char reply[4*NAMELEN];
  165. char *cp;
  166. long n;
  167. /*
  168. * ask the connection server
  169. */
  170. fd = open("/net/cs", O_RDWR);
  171. if(fd < 0)
  172. return identtrans(addr, naddr, na, file, nf);
  173. if(write(fd, addr, strlen(addr)) < 0){
  174. close(fd);
  175. return -1;
  176. }
  177. lseek(fd, 0, 0);
  178. n = read(fd, reply, sizeof(reply)-1);
  179. close(fd);
  180. if(n <= 0)
  181. return -1;
  182. reply[n] = 0;
  183. /*
  184. * parse the reply
  185. */
  186. cp = strchr(reply, ' ');
  187. if(cp == 0)
  188. return -1;
  189. *cp++ = 0;
  190. strncpy(naddr, cp, na);
  191. naddr[na-1] = 0;
  192. strncpy(file, reply, nf);
  193. file[nf-1] = 0;
  194. return 0;
  195. }