ypxfrd_main.c revision 22997
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$ 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 63static const char rcsid[] = "$Id$"; 64#endif /* not lint */ 65int _rpcpmstart; /* Started by a port monitor ? */ 66static 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 74extern int _rpcsvcstate; /* Set when a request is serviced */ 75 76char *progname = "rpc.ypxfrd"; 77char *yp_dir = "/var/yp/"; 78 79static 80void _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 92static void 93closedown(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 119static void 120ypxfrd_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 158static 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 177void usage() 178{ 179 fprintf(stderr, "%s [-p path]\n", progname); 180 exit(0); 181} 182 183main(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