xref: /plan9/sys/src/cmd/ns.c (revision 80ee5cbfe36716af62da8896207e9763b8e3d760)
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