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