mount_portal(8): Raise WARNS to 6.
[dragonfly.git] / sbin / mount_portal / mount_portal.c
CommitLineData
984263bc
MD
1/*
2 * Copyright (c) 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software donated to Berkeley by
6 * Jan-Simon Pendry.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
1de703da
MD
35 *
36 * @(#) Copyright (c) 1992, 1993, 1994 The Regents of the University of California. All rights reserved.
37 * @(#)mount_portal.c 8.6 (Berkeley) 4/26/95
38 * $FreeBSD: src/sbin/mount_portal/mount_portal.c,v 1.16 1999/10/09 11:54:11 phk Exp $
e929265d 39 * $DragonFly: src/sbin/mount_portal/mount_portal.c,v 1.6 2005/11/06 12:36:40 swildner Exp $
984263bc
MD
40 */
41
984263bc
MD
42#include <sys/param.h>
43#include <sys/wait.h>
44#include <sys/socket.h>
45#include <sys/un.h>
46#include <sys/stat.h>
47#include <sys/syslog.h>
48#include <sys/mount.h>
49
50#include <err.h>
51#include <errno.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55#include <sysexits.h>
56#include <unistd.h>
57
58#include "mntopts.h"
59#include "pathnames.h"
60#include "portald.h"
61
62struct mntopt mopts[] = {
63 MOPT_STDOPTS,
92f258c4 64 { NULL, 0, 0, 0 }
984263bc
MD
65};
66
9a76cd75 67static void usage(void) __dead2;
984263bc
MD
68
69static sig_atomic_t readcf; /* Set when SIGHUP received */
70
e929265d 71static void
92f258c4 72sighup(int sig __unused)
984263bc
MD
73{
74 readcf ++;
75}
76
e929265d 77static void
92f258c4 78sigchld(int sig __unused)
984263bc
MD
79{
80 pid_t pid;
81
902ec341 82 while ((pid = waitpid((pid_t) -1, NULL, WNOHANG)) > 0)
984263bc
MD
83 ;
84 /* wrtp - waitpid _doesn't_ return 0 when no children! */
85#ifdef notdef
86 if (pid < 0 && errno != ECHILD)
87 syslog(LOG_WARNING, "waitpid: %s", strerror(errno));
88#endif
89}
90
91int
b5744197 92main(int argc, char **argv)
984263bc
MD
93{
94 struct portal_args args;
95 struct sockaddr_un un;
96 char *conf;
97 char mountpt[MAXPATHLEN];
98 int mntflags = 0;
99 char tag[32];
100 struct vfsconf vfc;
101 mode_t um;
102
103 qelem q;
104 int rc;
105 int so;
106 int error = 0;
107
108 /*
109 * Crack command line args
110 */
111 int ch;
112
113 while ((ch = getopt(argc, argv, "o:")) != -1) {
114 switch (ch) {
115 case 'o':
116 getmntopts(optarg, mopts, &mntflags, 0);
117 break;
118 default:
119 error = 1;
120 break;
121 }
122 }
123
124 if (optind != (argc - 2))
125 error = 1;
126
127 if (error)
128 usage();
129
130 /*
131 * Get config file and mount point
132 */
133 conf = argv[optind];
134
135 /* resolve the mountpoint with realpath(3) */
7cee7052 136 checkpath(argv[optind+1], mountpt);
984263bc
MD
137
138 /*
139 * Construct the listening socket
140 */
141 un.sun_family = AF_UNIX;
142 if (sizeof(_PATH_TMPPORTAL) >= sizeof(un.sun_path)) {
143 errx(EX_SOFTWARE, "portal socket name too long");
144 }
145 strcpy(un.sun_path, _PATH_TMPPORTAL);
146 mktemp(un.sun_path);
147 un.sun_len = strlen(un.sun_path);
148
149 so = socket(AF_UNIX, SOCK_STREAM, 0);
150 if (so < 0) {
151 err(EX_OSERR, "socket");
152 }
153 um = umask(077);
7cee7052 154 unlink(un.sun_path);
984263bc
MD
155 if (bind(so, (struct sockaddr *) &un, sizeof(un)) < 0)
156 err(1, NULL);
157
7cee7052
SW
158 unlink(un.sun_path);
159 umask(um);
984263bc 160
7cee7052 161 listen(so, 5);
984263bc
MD
162
163 args.pa_socket = so;
164 sprintf(tag, "portal:%d", getpid());
165 args.pa_config = tag;
166
167 error = getvfsbyname("portal", &vfc);
168 if (error && vfsisloadable("portal")) {
169 if (vfsload("portal"))
170 err(EX_OSERR, "vfsload(portal)");
171 endvfsent();
172 error = getvfsbyname("portal", &vfc);
173 }
174 if (error)
175 errx(EX_OSERR, "portal filesystem is not available");
176
177 rc = mount(vfc.vfc_name, mountpt, mntflags, &args);
178 if (rc < 0)
179 err(1, NULL);
180
181 /*
182 * Everything is ready to go - now is a good time to fork
183 */
184#ifndef DEBUG
185 daemon(0, 0);
186#endif
187
188 /*
189 * Start logging (and change name)
190 */
191 openlog("portald", LOG_CONS|LOG_PID, LOG_DAEMON);
192
193 q.q_forw = q.q_back = &q;
194 readcf = 1;
195
196 signal(SIGCHLD, sigchld);
197 signal(SIGHUP, sighup);
198
199 /*
200 * Just loop waiting for new connections and activating them
201 */
202 for (;;) {
203 struct sockaddr_un un2;
204 int len2 = sizeof(un2);
205 int so2;
206 pid_t pid;
207 fd_set fdset;
984263bc
MD
208
209 /*
210 * Check whether we need to re-read the configuration file
211 */
212 if (readcf) {
213#ifdef DEBUG
214 printf ("re-reading configuration file\n");
215#endif
216 readcf = 0;
217 conf_read(&q, conf);
218 continue;
219 }
220
221 /*
222 * Accept a new connection
223 * Will get EINTR if a signal has arrived, so just
224 * ignore that error code
225 */
226 FD_ZERO(&fdset);
227 FD_SET(so, &fdset);
902ec341 228 rc = select(so+1, &fdset, NULL, NULL, NULL);
984263bc
MD
229 if (rc < 0) {
230 if (errno == EINTR)
231 continue;
232 syslog(LOG_ERR, "select: %s", strerror(errno));
233 exit(EX_OSERR);
234 }
235 if (rc == 0)
236 break;
237 so2 = accept(so, (struct sockaddr *) &un2, &len2);
238 if (so2 < 0) {
239 /*
240 * The unmount function does a shutdown on the socket
241 * which will generated ECONNABORTED on the accept.
242 */
243 if (errno == ECONNABORTED)
244 break;
245 if (errno != EINTR) {
246 syslog(LOG_ERR, "accept: %s", strerror(errno));
247 exit(EX_OSERR);
248 }
249 continue;
250 }
251
252 /*
253 * Now fork a new child to deal with the connection
254 */
255 eagain:;
256 switch (pid = fork()) {
257 case -1:
258 if (errno == EAGAIN) {
259 sleep(1);
260 goto eagain;
261 }
262 syslog(LOG_ERR, "fork: %s", strerror(errno));
263 break;
264 case 0:
7cee7052 265 close(so);
984263bc
MD
266 activate(&q, so2);
267 exit(0);
268 default:
7cee7052 269 close(so2);
984263bc
MD
270 break;
271 }
272 }
273 syslog(LOG_INFO, "%s unmounted", mountpt);
274 exit(0);
275}
276
277static void
b5744197 278usage(void)
984263bc 279{
7cee7052
SW
280 fprintf(stderr,
281 "usage: mount_portal [-o options] config mount-point\n");
984263bc
MD
282 exit(EX_USAGE);
283}