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