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