1 /* 2 * Copyright (c) 1995, 1996 3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-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 Bill Paul 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 Bill Paul 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 * $Id: ypxfrd_main.c,v 1.4 1996/06/04 04:27:47 wpaul Exp $ 33 */ 34 35 #include "ypxfrd.h" 36 #include <stdio.h> 37 #include <stdlib.h> /* getenv, exit */ 38 #include <rpc/pmap_clnt.h> /* for pmap_unset */ 39 #include <string.h> /* strcmp */ 40 #include <signal.h> 41 #include <sys/ttycom.h> /* TIOCNOTTY */ 42 #ifdef __cplusplus 43 #include <sysent.h> /* getdtablesize, open */ 44 #endif /* __cplusplus */ 45 #include <memory.h> 46 #include <sys/socket.h> 47 #include <netinet/in.h> 48 #include <syslog.h> 49 #include "ypxfrd_extern.h" 50 #include <sys/wait.h> 51 #include <errno.h> 52 53 #ifndef SIG_PF 54 #define SIG_PF void(*)(int) 55 #endif 56 57 #ifdef DEBUG 58 #define RPC_SVC_FG 59 #endif 60 61 #define _RPCSVC_CLOSEDOWN 120 62 #ifndef lint 63 static const char rcsid[] = "$Id: ypxfrd_main.c,v 1.4 1996/06/04 04:27:47 wpaul Exp $"; 64 #endif /* not lint */ 65 int _rpcpmstart; /* Started by a port monitor ? */ 66 static int _rpcfdtype; 67 /* Whether Stream or Datagram ? */ 68 /* States a server can be in wrt request */ 69 70 #define _IDLE 0 71 #define _SERVED 1 72 #define _SERVING 2 73 74 extern int _rpcsvcstate; /* Set when a request is serviced */ 75 76 char *progname = "rpc.ypxfrd"; 77 char *yp_dir = "/var/yp/"; 78 79 static 80 void _msgout(char* msg) 81 { 82 #ifdef RPC_SVC_FG 83 if (_rpcpmstart) 84 syslog(LOG_ERR, msg); 85 else 86 (void) fprintf(stderr, "%s\n", msg); 87 #else 88 syslog(LOG_ERR, msg); 89 #endif 90 } 91 92 static void 93 closedown(int sig) 94 { 95 if (_rpcsvcstate == _IDLE) { 96 extern fd_set svc_fdset; 97 static int size; 98 int i, openfd; 99 100 if (_rpcfdtype == SOCK_DGRAM) 101 exit(0); 102 if (size == 0) { 103 size = getdtablesize(); 104 } 105 for (i = 0, openfd = 0; i < size && openfd < 2; i++) 106 if (FD_ISSET(i, &svc_fdset)) 107 openfd++; 108 if (openfd <= 1) 109 exit(0); 110 } 111 if (_rpcsvcstate == _SERVED) 112 _rpcsvcstate = _IDLE; 113 114 (void) signal(SIGALRM, (SIG_PF) closedown); 115 (void) alarm(_RPCSVC_CLOSEDOWN/2); 116 } 117 118 119 static void 120 ypxfrd_svc_run() 121 { 122 #ifdef FD_SETSIZE 123 fd_set readfds; 124 #else 125 int readfds; 126 #endif /* def FD_SETSIZE */ 127 extern int forked; 128 int pid; 129 int fd_setsize = _rpc_dtablesize(); 130 131 /* Establish the identity of the parent ypserv process. */ 132 pid = getpid(); 133 134 for (;;) { 135 #ifdef FD_SETSIZE 136 readfds = svc_fdset; 137 #else 138 readfds = svc_fds; 139 #endif /* def FD_SETSIZE */ 140 switch (select(fd_setsize, &readfds, NULL, NULL, 141 (struct timeval *)0)) { 142 case -1: 143 if (errno == EINTR) { 144 continue; 145 } 146 perror("svc_run: - select failed"); 147 return; 148 case 0: 149 continue; 150 default: 151 svc_getreqset(&readfds); 152 if (forked && pid != getpid()) 153 exit(0); 154 } 155 } 156 } 157 158 static void reaper(sig) 159 int sig; 160 { 161 int status; 162 163 if (sig == SIGHUP) { 164 load_securenets(); 165 return; 166 } 167 168 if (sig == SIGCHLD) { 169 while (wait3(&status, WNOHANG, NULL) > 0) 170 children--; 171 } else { 172 (void) pmap_unset(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS); 173 exit(0); 174 } 175 } 176 177 void usage() 178 { 179 fprintf(stderr, "%s [-p path]\n", progname); 180 exit(0); 181 } 182 183 main(argc, argv) 184 int argc; 185 char *argv[]; 186 { 187 register SVCXPRT *transp; 188 int sock; 189 int proto; 190 struct sockaddr_in saddr; 191 int asize = sizeof (saddr); 192 int ch; 193 194 while ((ch = getopt(argc, argv, "p:h")) != EOF) { 195 switch(ch) { 196 case 'p': 197 yp_dir = optarg; 198 break; 199 default: 200 usage(); 201 break; 202 } 203 } 204 205 load_securenets(); 206 207 if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 208 int ssize = sizeof (int); 209 210 if (saddr.sin_family != AF_INET) 211 exit(1); 212 if (getsockopt(0, SOL_SOCKET, SO_TYPE, 213 (char *)&_rpcfdtype, &ssize) == -1) 214 exit(1); 215 sock = 0; 216 _rpcpmstart = 1; 217 proto = 0; 218 openlog("rpc.ypxfrd", LOG_PID, LOG_DAEMON); 219 } else { 220 #ifndef RPC_SVC_FG 221 int size; 222 int pid, i; 223 224 pid = fork(); 225 if (pid < 0) { 226 perror("cannot fork"); 227 exit(1); 228 } 229 if (pid) 230 exit(0); 231 size = getdtablesize(); 232 for (i = 0; i < size; i++) 233 (void) close(i); 234 i = open("/dev/console", 2); 235 (void) dup2(i, 1); 236 (void) dup2(i, 2); 237 i = open("/dev/tty", 2); 238 if (i >= 0) { 239 (void) ioctl(i, TIOCNOTTY, (char *)NULL); 240 (void) close(i); 241 } 242 openlog("rpc.ypxfrd", LOG_PID, LOG_DAEMON); 243 #endif 244 sock = RPC_ANYSOCK; 245 (void) pmap_unset(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS); 246 } 247 248 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 249 transp = svcudp_create(sock); 250 if (transp == NULL) { 251 _msgout("cannot create udp service."); 252 exit(1); 253 } 254 if (!_rpcpmstart) 255 proto = IPPROTO_UDP; 256 if (!svc_register(transp, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, ypxfrd_freebsd_prog_1, proto)) { 257 _msgout("unable to register (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, udp)."); 258 exit(1); 259 } 260 } 261 262 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 263 transp = svctcp_create(sock, 0, 0); 264 if (transp == NULL) { 265 _msgout("cannot create tcp service."); 266 exit(1); 267 } 268 if (!_rpcpmstart) 269 proto = IPPROTO_TCP; 270 if (!svc_register(transp, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, ypxfrd_freebsd_prog_1, proto)) { 271 _msgout("unable to register (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, tcp)."); 272 exit(1); 273 } 274 } 275 276 if (transp == (SVCXPRT *)NULL) { 277 _msgout("could not create a handle"); 278 exit(1); 279 } 280 if (_rpcpmstart) { 281 (void) signal(SIGALRM, (SIG_PF) closedown); 282 (void) alarm(_RPCSVC_CLOSEDOWN/2); 283 } 284 285 (void) signal(SIGPIPE, SIG_IGN); 286 (void) signal(SIGCHLD, (SIG_PF) reaper); 287 (void) signal(SIGTERM, (SIG_PF) reaper); 288 (void) signal(SIGINT, (SIG_PF) reaper); 289 (void) signal(SIGHUP, (SIG_PF) reaper); 290 291 ypxfrd_svc_run(); 292 _msgout("svc_run returned"); 293 exit(1); 294 /* NOTREACHED */ 295 } 296