ns.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 <libc.h>
  11. #include <bio.h>
  12. #include <auth.h>
  13. #include <fcall.h>
  14. #pragma varargck type "P" char*
  15. int nsrv;
  16. Dir *srv;
  17. Biobuf stdout;
  18. typedef struct Mount Mount;
  19. struct Mount
  20. {
  21. char *cmd;
  22. char *flag;
  23. char *new;
  24. char *old;
  25. char *spec;
  26. };
  27. void xlatemnt(Mount*);
  28. char *quote(char*);
  29. int rflag;
  30. void
  31. usage(void)
  32. {
  33. fprint(2, "usage: ns [-r] [pid]\n");
  34. exits("usage");
  35. }
  36. void
  37. main(int argc, char **argv)
  38. {
  39. Mount *m;
  40. int line, fd, n, pid;
  41. char buf[1024], *av[5];
  42. ARGBEGIN{
  43. case 'r':
  44. rflag++;
  45. break;
  46. default:
  47. usage();
  48. }ARGEND
  49. if(argc > 1)
  50. usage();
  51. if(argc == 1){
  52. pid = atoi(argv[0]);
  53. if(pid == 0)
  54. usage();
  55. }else
  56. pid = getpid();
  57. Binit(&stdout, 1, OWRITE);
  58. sprint(buf, "/proc/%d/ns", pid);
  59. fd = open(buf, OREAD);
  60. if(fd < 0) {
  61. fprint(2, "ns: open %s: %r\n", buf);
  62. exits("open ns");
  63. }
  64. for(line=1; ; line++) {
  65. n = read(fd, buf, sizeof(buf));
  66. if(n == sizeof(buf)) {
  67. fprint(2, "ns: ns string too long\n");
  68. exits("read ns");
  69. }
  70. if(n < 0) {
  71. fprint(2, "ns: read %r\n");
  72. exits("read ns");
  73. }
  74. if(n == 0)
  75. break;
  76. buf[n] = '\0';
  77. m = mallocz(sizeof(Mount), 1);
  78. if(m == nil) {
  79. fprint(2, "ns: no memory: %r\n");
  80. exits("no memory");
  81. }
  82. n = tokenize(buf, av, 5);
  83. switch(n){
  84. case 2:
  85. if(strcmp(av[0], "cd") == 0){
  86. Bprint(&stdout, "%s %s\n", av[0], av[1]);
  87. continue;
  88. }
  89. /* fall through */
  90. default:
  91. fprint(2, "ns: unrecognized format of ns file: %d elements on line %d\n", n, line);
  92. exits("format");
  93. case 5:
  94. m->cmd = strdup(av[0]);
  95. m->flag = strdup(av[1]);
  96. m->new = strdup(av[2]);
  97. m->old = strdup(av[3]);
  98. m->spec = strdup(av[4]);
  99. break;
  100. case 4:
  101. if(av[1][0] == '-'){
  102. m->cmd = strdup(av[0]);
  103. m->flag = strdup(av[1]);
  104. m->new = strdup(av[2]);
  105. m->old = strdup(av[3]);
  106. m->spec = strdup("");
  107. }else{
  108. m->cmd = strdup(av[0]);
  109. m->flag = strdup("");
  110. m->new = strdup(av[1]);
  111. m->old = strdup(av[2]);
  112. m->spec = strdup(av[3]);
  113. }
  114. break;
  115. case 3:
  116. m->cmd = strdup(av[0]);
  117. m->flag = strdup("");
  118. m->new = strdup(av[1]);
  119. m->old = strdup(av[2]);
  120. m->spec = strdup("");
  121. break;
  122. }
  123. if(!rflag && strcmp(m->cmd, "mount")==0)
  124. xlatemnt(m);
  125. Bprint(&stdout, "%s %s %s %s %s\n", m->cmd, m->flag,
  126. quote(m->new), quote(m->old), quote(m->spec));
  127. free(m->cmd);
  128. free(m->flag);
  129. free(m->new);
  130. free(m->old);
  131. free(m->spec);
  132. free(m);
  133. }
  134. exits(nil);
  135. }
  136. void
  137. xlatemnt(Mount *m)
  138. {
  139. int n, fd;
  140. char *s, *t, *net, *port;
  141. char buf[256];
  142. if(strncmp(m->new, "/net/", 5) != 0)
  143. return;
  144. s = strdup(m->new);
  145. net = s+5;
  146. for(t=net; *t!='/'; t++)
  147. if(*t == '\0')
  148. goto Return;
  149. *t = '\0';
  150. port = t+1;
  151. for(t=port; *t!='/'; t++)
  152. if(*t == '\0')
  153. goto Return;
  154. *t = '\0';
  155. if(strcmp(t+1, "data") != 0)
  156. goto Return;
  157. snprint(buf, sizeof buf, "/net/%s/%s/remote", net, port);
  158. fd = open(buf, OREAD);
  159. if(fd < 0)
  160. goto Return;
  161. n = read(fd, buf, sizeof buf);
  162. close(fd);
  163. if(n<=1 || n>sizeof buf)
  164. goto Return;
  165. if(buf[n-1] == '\n')
  166. --n;
  167. buf[n] = '\0';
  168. t = malloc(strlen(net)+1+n+1);
  169. if(t == nil)
  170. goto Return;
  171. sprint(t, "%s!%s", net, buf);
  172. free(m->new);
  173. m->new = t;
  174. Return:
  175. free(s);
  176. }
  177. char*
  178. quote(char *s)
  179. {
  180. static char buf[3][1024];
  181. static int i;
  182. char *p, *ep;
  183. if(strpbrk(s, " '\\\t#$") == nil)
  184. return s;
  185. i = (i+1)%3;
  186. p = &buf[i][0];
  187. ep = &buf[i][1024];
  188. *p++ = '\'';
  189. while(p < ep-5){
  190. switch(*s){
  191. case '\0':
  192. goto out;
  193. case '\'':
  194. *p++ = '\'';
  195. break;
  196. }
  197. *p++ = *s++;
  198. }
  199. out:
  200. *p++ = '\'';
  201. *p = '\0';
  202. return buf[i];
  203. }