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