xref: /plan9-contrib/sys/src/cmd/srv.c (revision 0b459c2cb92b7c9d88818e9a2f72e678e5bc4553)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <auth.h>
5 
6 char	*dest = "system";
7 int	mountflag = MREPL;
8 
9 void	error(char *);
10 void	rpc(int, int);
11 void	post(char*, int);
12 void	mountfs(char*, int);
13 
14 void
15 usage(void)
16 {
17 	fprint(2, "usage: %s [-abcCm] [net!]host [srvname [mtpt]]\n", argv0);
18 	fprint(2, "    or %s -e [-abcCm] command [srvname [mtpt]]\n", argv0);
19 
20 	exits("usage");
21 }
22 
23 void
24 ignore(void *a, char *c)
25 {
26 	USED(a);
27 fprint(2, "%s\n", c);
28 	if(strcmp(c, "alarm") == 0){
29 		fprint(2, "srv: timeout establishing connection to %s\n", dest);
30 		exits("timeout");
31 	}
32 	if(strstr(c, "write on closed pipe") == 0){
33 		fprint(2, "write on closed pipe\n");
34 		noted(NCONT);
35 	}
36 	noted(NDFLT);
37 }
38 
39 int
40 connectcmd(char *cmd)
41 {
42 	int p[2];
43 
44 	if(pipe(p) < 0)
45 		return -1;
46 	switch(fork()){
47 	case -1:
48 		fprint(2, "fork failed: %r\n");
49 		_exits("exec");
50 	case 0:
51 		rfork(RFNOTEG);
52 		dup(p[0], 0);
53 		dup(p[0], 1);
54 		close(p[1]);
55 		execl("/bin/rc", "rc", "-c", cmd, nil);
56 		fprint(2, "exec failed: %r\n");
57 		_exits("exec");
58 	default:
59 		close(p[0]);
60 		return p[1];
61 	}
62 }
63 
64 void
65 main(int argc, char *argv[])
66 {
67 	int fd, doexec;
68 	char srv[64], mtpt[64];
69 	char dir[1024];
70 	char err[ERRMAX];
71 	char *p, *p2;
72 	int domount, reallymount, try, sleeptime;
73 
74 	notify(ignore);
75 
76 	domount = 0;
77 	reallymount = 0;
78 	doexec = 0;
79 	sleeptime = 0;
80 
81 	ARGBEGIN{
82 	case 'a':
83 		mountflag |= MAFTER;
84 		domount = 1;
85 		reallymount = 1;
86 		break;
87 	case 'b':
88 		mountflag |= MBEFORE;
89 		domount = 1;
90 		reallymount = 1;
91 		break;
92 	case 'c':
93 		mountflag |= MCREATE;
94 		domount = 1;
95 		reallymount = 1;
96 		break;
97 	case 'C':
98 		mountflag |= MCACHE;
99 		domount = 1;
100 		reallymount = 1;
101 		break;
102 	case 'e':
103 		doexec = 1;
104 		break;
105 	case 'm':
106 		domount = 1;
107 		reallymount = 1;
108 		break;
109 	case 'q':
110 		domount = 1;
111 		reallymount = 0;
112 		break;
113 	case 'r':
114 		/* deprecated -r flag; ignored for compatibility */
115 		break;
116 	case 's':
117 		sleeptime = atoi(EARGF(usage()));
118 		break;
119 	default:
120 		usage();
121 		break;
122 	}ARGEND
123 
124 	if((mountflag&MAFTER)&&(mountflag&MBEFORE))
125 		usage();
126 
127 	switch(argc){
128 	case 1:	/* calculate srv and mtpt from address */
129 		p = strrchr(argv[0], '/');
130 		p = p ? p+1 : argv[0];
131 		snprint(srv, sizeof(srv), "/srv/%.28s", p);
132 		p2 = strchr(p, '!');
133 		p2 = p2 ? p2+1 : p;
134 		snprint(mtpt, sizeof(mtpt), "/n/%.28s", p2);
135 		break;
136 	case 2:	/* calculate mtpt from address, srv given */
137 		snprint(srv, sizeof(srv), "/srv/%.28s", argv[1]);
138 		p = strrchr(argv[0], '/');
139 		p = p ? p+1 : argv[0];
140 		p2 = strchr(p, '!');
141 		p2 = p2 ? p2+1 : p;
142 		snprint(mtpt, sizeof(mtpt), "/n/%.28s", p2);
143 		break;
144 	case 3:	/* srv and mtpt given */
145 		domount = 1;
146 		reallymount = 1;
147 		snprint(srv, sizeof(srv), "/srv/%.28s", argv[1]);
148 		snprint(mtpt, sizeof(mtpt), "%.28s", argv[2]);
149 		break;
150 	default:
151 		usage();
152 	}
153 
154 	try = 0;
155 	dest = *argv;
156 Again:
157 	try++;
158 
159 	if(access(srv, 0) == 0){
160 		if(domount){
161 			fd = open(srv, ORDWR);
162 			if(fd >= 0)
163 				goto Mount;
164 			remove(srv);
165 		}
166 		else{
167 			fprint(2, "srv: %s already exists\n", srv);
168 			exits(0);
169 		}
170 	}
171 
172 	alarm(10000);
173 	if(doexec)
174 		fd = connectcmd(dest);
175 	else{
176 		dest = netmkaddr(dest, 0, "9fs");
177 		fd = dial(dest, 0, dir, 0);
178 	}
179 	if(fd < 0) {
180 		fprint(2, "srv: dial %s: %r\n", dest);
181 		exits("dial");
182 	}
183 	alarm(0);
184 
185 	if(sleeptime){
186 		fprint(2, "sleep...");
187 		sleep(sleeptime*1000);
188 	}
189 
190 	post(srv, fd);
191 
192 Mount:
193 	if(domount == 0 || reallymount == 0)
194 		exits(0);
195 
196 	if(amount(fd, mtpt, mountflag, "") < 0){
197 		err[0] = 0;
198 		errstr(err, sizeof err);
199 		if(strstr(err, "Hangup") || strstr(err, "hungup") || strstr(err, "timed out")){
200 			remove(srv);
201 			if(try == 1)
202 				goto Again;
203 		}
204 		fprint(2, "srv %s: mount failed: %s\n", dest, err);
205 		exits("mount");
206 	}
207 	exits(0);
208 }
209 
210 void
211 post(char *srv, int fd)
212 {
213 	int f;
214 	char buf[128];
215 
216 	fprint(2, "post...\n");
217 	f = create(srv, OWRITE, 0666);
218 	if(f < 0){
219 		sprint(buf, "create(%s)", srv);
220 		error(buf);
221 	}
222 	sprint(buf, "%d", fd);
223 	if(write(f, buf, strlen(buf)) != strlen(buf))
224 		error("write");
225 }
226 
227 void
228 error(char *s)
229 {
230 	fprint(2, "srv %s: %s: %r\n", dest, s);
231 	exits("srv: error");
232 }
233