xref: /plan9/sys/src/cmd/ns.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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
30 usage(void)
31 {
32 	fprint(2, "usage: ns [-r] [pid]\n");
33 	exits("usage");
34 }
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 
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 < 0) {
72 			fprint(2, "ns: read %r\n");
73 			exits("read ns");
74 		}
75 		if(n == 0)
76 			break;
77 		buf[n] = '\0';
78 
79 		m = mallocz(sizeof(Mount), 1);
80 		if(m == nil) {
81 			fprint(2, "ns: no memory: %r\n");
82 			exits("no memory");
83 		}
84 
85 		n = tokenize(buf, av, 5);
86 		switch(n){
87 		case 2:
88 			if(strcmp(av[0], "cd") == 0){
89 				Bprint(&stdout, "%s %s\n", av[0], av[1]);
90 				continue;
91 			}
92 			/* fall through */
93 		default:
94 			fprint(2, "ns: unrecognized format of ns file: %d elements on line %d\n", n, line);
95 			exits("format");
96 		case 5:
97 			m->cmd = strdup(av[0]);
98 			m->flag = strdup(av[1]);
99 			m->new = strdup(av[2]);
100 			m->old = strdup(av[3]);
101 			m->spec = strdup(av[4]);
102 			break;
103 		case 4:
104 			if(av[1][0] == '-'){
105 				m->cmd = strdup(av[0]);
106 				m->flag = strdup(av[1]);
107 				m->new = strdup(av[2]);
108 				m->old = strdup(av[3]);
109 				m->spec = strdup("");
110 			}else{
111 				m->cmd = strdup(av[0]);
112 				m->flag = strdup("");
113 				m->new = strdup(av[1]);
114 				m->old = strdup(av[2]);
115 				m->spec = strdup(av[3]);
116 			}
117 			break;
118 		case 3:
119 			m->cmd = strdup(av[0]);
120 			m->flag = strdup("");
121 			m->new = strdup(av[1]);
122 			m->old = strdup(av[2]);
123 			m->spec = strdup("");
124 			break;
125 		}
126 
127 		if(!rflag && strcmp(m->cmd, "mount")==0)
128 			xlatemnt(m);
129 
130 		Bprint(&stdout, "%s %s %s %s %s\n", m->cmd, m->flag,
131 			quote(m->new), quote(m->old), quote(m->spec));
132 
133 		free(m->cmd);
134 		free(m->flag);
135 		free(m->new);
136 		free(m->old);
137 		free(m->spec);
138 		free(m);
139 	}
140 
141 	exits(nil);
142 }
143 
144 void
145 xlatemnt(Mount *m)
146 {
147 	int n, fd;
148 	char *s, *t, *net, *port;
149 	char buf[256];
150 
151 	if(strncmp(m->new, "/net/", 5) != 0)
152 		return;
153 
154 	s = strdup(m->new);
155 	net = s+5;
156 	for(t=net; *t!='/'; t++)
157 		if(*t == '\0')
158 			goto Return;
159 	*t = '\0';
160 	port = t+1;
161 	for(t=port; *t!='/'; t++)
162 		if(*t == '\0')
163 			goto Return;
164 	*t = '\0';
165 	if(strcmp(t+1, "data") != 0)
166 		goto Return;
167 	snprint(buf, sizeof buf, "/net/%s/%s/remote", net, port);
168 	fd = open(buf, OREAD);
169 	if(fd < 0)
170 		goto Return;
171 	n = read(fd, buf, sizeof buf);
172 	close(fd);
173 	if(n<=1 || n>sizeof buf)
174 		goto Return;
175 	if(buf[n-1] == '\n')
176 		--n;
177 	buf[n] = '\0';
178 	t = malloc(strlen(net)+1+n+1);
179 	if(t == nil)
180 		goto Return;
181 	sprint(t, "%s!%s", net, buf);
182 	free(m->new);
183 	m->new = t;
184 
185 Return:
186 	free(s);
187 }
188 
189 char*
190 quote(char *s)
191 {
192 	static char buf[3][1024];
193 	static int i;
194 	char *p, *ep;
195 
196 	if(strpbrk(s, " '\\\t#$") == nil)
197 		return s;
198 	i = (i+1)%3;
199 	p = &buf[i][0];
200 	ep = &buf[i][1024];
201 	*p++ = '\'';
202 	while(p < ep-5){
203 		switch(*s){
204 		case '\0':
205 			goto out;
206 		case '\'':
207 			*p++ = '\'';
208 			break;
209 		}
210 		*p++ = *s++;
211 	}
212     out:
213 	*p++ = '\'';
214 	*p = '\0';
215 	return buf[i];
216 }
217