xref: /netbsd-src/usr.bin/rump_allserver/rump_allserver.c (revision 4817a0b0b8fe9612e8ebe21a9bf2d97b95038a97)
1 /*	$NetBSD: rump_allserver.c,v 1.11 2010/12/15 19:07:43 pooka Exp $	*/
2 
3 /*-
4  * Copyright (c) 2010 Antti Kantee.  All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include <sys/cdefs.h>
29 #ifndef lint
30 __RCSID("$NetBSD: rump_allserver.c,v 1.11 2010/12/15 19:07:43 pooka Exp $");
31 #endif /* !lint */
32 
33 #include <sys/types.h>
34 #include <sys/signal.h>
35 #include <sys/module.h>
36 
37 #include <rump/rump.h>
38 #include <rump/rump_syscalls.h>
39 
40 #include <dlfcn.h>
41 #include <err.h>
42 #include <errno.h>
43 #include <fcntl.h>
44 #include <semaphore.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 
50 static void
51 usage(void)
52 {
53 
54 	fprintf(stderr, "usage: %s [-s] [-d drivespec] [-l libs] [-m modules] "
55 	    "bindurl\n", getprogname());
56 	exit(1);
57 }
58 
59 static void
60 die(int sflag, int error, const char *reason)
61 {
62 
63 	warnx("%s: %s", reason, strerror(error));
64 	if (!sflag)
65 		rump_daemonize_done(error);
66 	exit(1);
67 }
68 
69 static sem_t sigsem;
70 static void
71 sigreboot(int sig)
72 {
73 
74 	sem_post(&sigsem);
75 }
76 
77 static const char *const disktokens[] = {
78 #define DKEY 0
79 	"key",
80 #define DFILE 1
81 	"hostpath",
82 #define DSIZE 2
83 	"size",
84 	NULL
85 };
86 
87 struct etfsreg {
88 	const char *key;
89 	const char *hostpath;
90 	off_t flen;
91 	enum rump_etfs_type type;
92 };
93 
94 int
95 main(int argc, char *argv[])
96 {
97 	const char *serverurl;
98 	char **modarray = NULL;
99 	unsigned nmods = 0, curmod = 0, i;
100 	struct etfsreg *etfs = NULL;
101 	unsigned netfs = 0, curetfs = 0;
102 	int error;
103 	int ch, sflag;
104 
105 	setprogname(argv[0]);
106 
107 	sflag = 0;
108 	while ((ch = getopt(argc, argv, "d:l:m:s")) != -1) {
109 		switch (ch) {
110 		case 'd': {
111 			char *options, *value;
112 			char *key, *hostpath;
113 			long long flen;
114 
115 			flen = 0;
116 			key = hostpath = NULL;
117 			options = optarg;
118 			while (*options) {
119 				switch (getsubopt(&options,
120 				    __UNCONST(disktokens), &value)) {
121 				case DKEY:
122 					if (key != NULL) {
123 						fprintf(stderr,
124 						    "key already given\n");
125 						usage();
126 					}
127 					key = value;
128 					break;
129 				case DFILE:
130 					if (hostpath != NULL) {
131 						fprintf(stderr,
132 						    "hostpath already given\n");
133 						usage();
134 					}
135 					hostpath = value;
136 					break;
137 				case DSIZE:
138 					if (flen != 0) {
139 						fprintf(stderr,
140 						    "size already given\n");
141 						usage();
142 					}
143 					/* XXX: off_t max? */
144 					flen = strsuftoll("-d size", value,
145 					    0, LLONG_MAX);
146 					break;
147 				default:
148 					fprintf(stderr, "invalid dtoken\n");
149 					usage();
150 					break;
151 				}
152 			}
153 
154 			if (key == NULL || hostpath == NULL || flen == 0) {
155 				fprintf(stderr, "incomplete drivespec\n");
156 				usage();
157 			}
158 
159 			if (netfs - curetfs == 0) {
160 				etfs = realloc(etfs, (netfs+16)*sizeof(*etfs));
161 				if (etfs == NULL)
162 					err(1, "realloc etfs");
163 				netfs += 16;
164 			}
165 
166 			etfs[curetfs].key = key;
167 			etfs[curetfs].hostpath = hostpath;
168 			etfs[curetfs].flen = flen;
169 			etfs[curetfs].type = RUMP_ETFS_BLK;
170 			curetfs++;
171 
172 			break;
173 		}
174 		case 'l':
175 			if (dlopen(optarg, RTLD_LAZY|RTLD_GLOBAL) == NULL) {
176 				char pb[MAXPATHLEN];
177 				/* try to mimic linker -l syntax */
178 
179 				snprintf(pb, sizeof(pb), "lib%s.so", optarg);
180 				if (dlopen(pb, RTLD_LAZY|RTLD_GLOBAL) == NULL) {
181 					errx(1, "dlopen %s failed: %s",
182 					    pb, dlerror());
183 				}
184 			}
185 			break;
186 		case 'm':
187 			if (nmods - curmod == 0) {
188 				modarray = realloc(modarray,
189 				    (nmods+16) * sizeof(char *));
190 				if (modarray == NULL)
191 					err(1, "realloc");
192 				nmods += 16;
193 			}
194 			modarray[curmod++] = optarg;
195 			break;
196 		case 's':
197 			sflag = 1;
198 			break;
199 		default:
200 			usage();
201 			/*NOTREACHED*/
202 		}
203 	}
204 
205 	argc -= optind;
206 	argv += optind;
207 
208 	if (argc != 1)
209 		usage();
210 
211 	serverurl = argv[0];
212 
213 	if (!sflag) {
214 		error = rump_daemonize_begin();
215 		if (error)
216 			errx(1, "rump daemonize: %s", strerror(error));
217 	}
218 
219 	error = rump_init();
220 	if (error)
221 		die(sflag, error, "rump init failed");
222 
223 	/* load modules */
224 	for (i = 0; i < curmod; i++) {
225 		struct modctl_load ml;
226 
227 #define ETFSKEY "/module.mod"
228 		if ((error = rump_pub_etfs_register(ETFSKEY,
229 		    modarray[0], RUMP_ETFS_REG)) != 0)
230 			die(sflag, error, "module etfs register failed");
231 		memset(&ml, 0, sizeof(ml));
232 		ml.ml_filename = ETFSKEY;
233 		if (rump_sys_modctl(MODCTL_LOAD, &ml) == -1)
234 			die(sflag, errno, "module load failed");
235 		rump_pub_etfs_remove(ETFSKEY);
236 #undef ETFSKEY
237 	}
238 
239 	/* register host drives */
240 	for (i = 0; i < curetfs; i++) {
241 		int fd;
242 
243 		fd = open(etfs[i].hostpath, O_RDWR | O_CREAT, 0755);
244 		if (fd == -1)
245 			die(sflag, error, "etfs hostpath create");
246 		if (ftruncate(fd, etfs[i].flen) == -1)
247 			die(sflag, error, "truncate");
248 		close(fd);
249 
250 		if ((error = rump_pub_etfs_register(etfs[i].key,
251 		    etfs[i].hostpath, etfs[i].type)) != 0)
252 			die(sflag, error, "etfs register");
253 	}
254 
255 	error = rump_init_server(serverurl);
256 	if (error)
257 		die(sflag, error, "rump server init failed");
258 
259 	if (!sflag)
260 		rump_daemonize_done(RUMP_DAEMONIZE_SUCCESS);
261 
262 	sem_init(&sigsem, 0, 0);
263 	signal(SIGTERM, sigreboot);
264 	signal(SIGINT, sigreboot);
265 	sem_wait(&sigsem);
266 
267 	rump_sys_reboot(0, NULL);
268 	/*NOTREACHED*/
269 
270 	return 0;
271 }
272