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 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 char copyright[] = 13 "@(#) Copyright (c) 1992, 1993, 1994\n\ 14 The Regents of the University of California. All rights reserved.\n"; 15 #endif /* not lint */ 16 17 #ifndef lint 18 static char sccsid[] = "@(#)mount_portal.c 8.4 (Berkeley) 03/27/94"; 19 #endif /* not lint */ 20 21 #include <sys/param.h> 22 #include <sys/wait.h> 23 #include <sys/socket.h> 24 #include <sys/un.h> 25 #include <sys/syslog.h> 26 #include <sys/mount.h> 27 28 #include <err.h> 29 #include <errno.h> 30 #include <signal.h> 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <unistd.h> 35 36 #include "mntopts.h" 37 #include "pathnames.h" 38 #include "portald.h" 39 40 struct mntopt mopts[] = { 41 MOPT_STDOPTS, 42 { NULL } 43 }; 44 45 static void usage __P((void)); 46 47 static sig_atomic_t readcf; /* Set when SIGHUP received */ 48 49 static void sigchld(sig) 50 int sig; 51 { 52 pid_t pid; 53 54 while ((pid = waitpid((pid_t) -1, (int *) 0, WNOHANG)) > 0) 55 ; 56 if (pid < 0) 57 syslog(LOG_WARNING, "waitpid: %s", strerror(errno)); 58 } 59 60 int 61 main(argc, argv) 62 int argc; 63 char *argv[]; 64 { 65 struct portal_args args; 66 struct sockaddr_un un; 67 char *conf; 68 char *mountpt; 69 int mntflags = 0; 70 char tag[32]; 71 72 qelem q; 73 int rc; 74 int so; 75 int error = 0; 76 77 /* 78 * Crack command line args 79 */ 80 int ch; 81 82 while ((ch = getopt(argc, argv, "o:")) != EOF) { 83 switch (ch) { 84 case 'o': 85 getmntopts(optarg, mopts, &mntflags); 86 break; 87 default: 88 error = 1; 89 break; 90 } 91 } 92 93 if (optind != (argc - 2)) 94 error = 1; 95 96 if (error) 97 usage(); 98 99 /* 100 * Get config file and mount point 101 */ 102 conf = argv[optind]; 103 mountpt = argv[optind+1]; 104 105 /* 106 * Construct the listening socket 107 */ 108 un.sun_family = AF_UNIX; 109 if (sizeof(_PATH_TMPPORTAL) >= sizeof(un.sun_path)) { 110 fprintf(stderr, "mount_portal: portal socket name too long\n"); 111 exit(1); 112 } 113 strcpy(un.sun_path, _PATH_TMPPORTAL); 114 mktemp(un.sun_path); 115 un.sun_len = strlen(un.sun_path); 116 117 so = socket(AF_UNIX, SOCK_STREAM, 0); 118 if (so < 0) { 119 fprintf(stderr, "mount_portal: socket: %s\n", strerror(errno)); 120 exit(1); 121 } 122 (void) unlink(un.sun_path); 123 if (bind(so, (struct sockaddr *) &un, sizeof(un)) < 0) 124 err(1, NULL); 125 (void) unlink(un.sun_path); 126 127 (void) listen(so, 5); 128 129 args.pa_socket = so; 130 sprintf(tag, "portal:%d", getpid()); 131 args.pa_config = tag; 132 133 rc = mount(MOUNT_PORTAL, mountpt, mntflags, &args); 134 if (rc < 0) 135 err(1, NULL); 136 137 #ifdef notdef 138 /* 139 * Everything is ready to go - now is a good time to fork 140 */ 141 daemon(0, 0); 142 #endif 143 144 /* 145 * Start logging (and change name) 146 */ 147 openlog("portald", LOG_CONS|LOG_PID, LOG_DAEMON); 148 149 q.q_forw = q.q_back = &q; 150 readcf = 1; 151 152 signal(SIGCHLD, sigchld); 153 154 /* 155 * Just loop waiting for new connections and activating them 156 */ 157 for (;;) { 158 struct sockaddr_un un2; 159 int len2 = sizeof(un2); 160 int so2; 161 pid_t pid; 162 fd_set fdset; 163 int rc; 164 165 /* 166 * Check whether we need to re-read the configuration file 167 */ 168 if (readcf) { 169 readcf = 0; 170 conf_read(&q, conf); 171 continue; 172 } 173 174 /* 175 * Accept a new connection 176 * Will get EINTR if a signal has arrived, so just 177 * ignore that error code 178 */ 179 FD_SET(so, &fdset); 180 rc = select(so+1, &fdset, (void *) 0, (void *) 0, (void *) 0); 181 if (rc < 0) { 182 if (errno == EINTR) 183 continue; 184 syslog(LOG_ERR, "select: %s", strerror(errno)); 185 exit(1); 186 } 187 if (rc == 0) 188 break; 189 so2 = accept(so, (struct sockaddr *) &un2, &len2); 190 if (so2 < 0) { 191 /* 192 * The unmount function does a shutdown on the socket 193 * which will generated ECONNABORTED on the accept. 194 */ 195 if (errno == ECONNABORTED) 196 break; 197 if (errno != EINTR) { 198 syslog(LOG_ERR, "accept: %s", strerror(errno)); 199 exit(1); 200 } 201 continue; 202 } 203 204 /* 205 * Now fork a new child to deal with the connection 206 */ 207 eagain:; 208 switch (pid = fork()) { 209 case -1: 210 if (errno == EAGAIN) { 211 sleep(1); 212 goto eagain; 213 } 214 syslog(LOG_ERR, "fork: %s", strerror(errno)); 215 break; 216 case 0: 217 (void) close(so); 218 activate(&q, so2); 219 break; 220 default: 221 (void) close(so2); 222 break; 223 } 224 } 225 syslog(LOG_INFO, "%s unmounted", mountpt); 226 exit(0); 227 } 228 229 static void 230 usage() 231 { 232 (void)fprintf(stderr, 233 "usage: mount_portal [-o options] config mount-point\n"); 234 exit(1); 235 } 236