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