yp_main.c revision 20053
1/* 2 * Copyright (c) 1995 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: yp_main.c,v 1.6 1996/05/31 16:01:50 wpaul Exp $ 33 */ 34 35/* 36 * ypserv startup function. 37 * We need out own main() since we have to do some additional work 38 * that rpcgen won't do for us. Most of this file was generated using 39 * rpcgen.new, and later modified. 40 */ 41 42#include "yp.h" 43#include <stdio.h> 44#include <stdlib.h> /* getenv, exit */ 45#include <rpc/pmap_clnt.h> /* for pmap_unset */ 46#include <string.h> /* strcmp */ 47#include <signal.h> 48#include <sys/ttycom.h> /* TIOCNOTTY */ 49#ifdef __cplusplus 50#include <sysent.h> /* getdtablesize, open */ 51#endif /* __cplusplus */ 52#include <memory.h> 53#include <sys/socket.h> 54#include <netinet/in.h> 55#include <syslog.h> 56#include <sys/wait.h> 57#include "yp_extern.h" 58#include <unistd.h> 59#include <rpc/rpc.h> 60#include <errno.h> 61#include <err.h> 62 63#ifndef SIG_PF 64#define SIG_PF void(*)(int) 65#endif 66 67#define _RPCSVC_CLOSEDOWN 120 68#ifndef lint 69static const char rcsid[] = "$Id: yp_main.c,v 1.6 1996/05/31 16:01:50 wpaul Exp $"; 70#endif /* not lint */ 71int _rpcpmstart; /* Started by a port monitor ? */ 72static int _rpcfdtype; 73 /* Whether Stream or Datagram ? */ 74 /* States a server can be in wrt request */ 75 76#define _IDLE 0 77#define _SERVED 1 78#define _SERVING 2 79 80extern void ypprog_1 __P((struct svc_req, register SVCXPRT)); 81extern void ypprog_2 __P((struct svc_req, register SVCXPRT)); 82extern int _rpcsvcstate; /* Set when a request is serviced */ 83char *progname = "ypserv"; 84char *yp_dir = _PATH_YP; 85int debug = 0; 86int do_dns = 0; 87 88static 89void _msgout(char* msg) 90{ 91 if (debug) { 92 if (_rpcpmstart) 93 syslog(LOG_ERR, msg); 94 else 95 (void) fprintf(stderr, "%s\n", msg); 96 } else 97 syslog(LOG_ERR, msg); 98} 99 100static void unregister() 101{ 102 (void) pmap_unset(YPPROG, YPVERS); 103 (void) pmap_unset(YPPROG, YPOLDVERS); 104} 105 106static void reaper(sig) 107 int sig; 108{ 109 int status; 110 111 if (sig == SIGHUP) { 112 load_securenets(); 113#ifdef DB_CACHE 114 yp_flush_all(); 115#endif 116 return; 117 } 118 119 if (sig == SIGCHLD) { 120 while (wait3(&status, WNOHANG, NULL) > 0) 121 children--; 122 } else { 123 unregister(); 124 exit(0); 125 } 126} 127 128static void usage() 129{ 130 fprintf(stderr, "Usage: %s [-h] [-d] [-n] [-p path]\n", progname); 131 exit(1); 132} 133 134static void 135closedown(int sig) 136{ 137 if (_rpcsvcstate == _IDLE) { 138 extern fd_set svc_fdset; 139 static int size; 140 int i, openfd; 141 142 if (_rpcfdtype == SOCK_DGRAM) { 143 unregister(); 144 exit(0); 145 } 146 if (size == 0) { 147 size = getdtablesize(); 148 } 149 for (i = 0, openfd = 0; i < size && openfd < 2; i++) 150 if (FD_ISSET(i, &svc_fdset)) 151 openfd++; 152 if (openfd <= 1) { 153 unregister(); 154 exit(0); 155 } 156 } 157 if (_rpcsvcstate == _SERVED) 158 _rpcsvcstate = _IDLE; 159 160 (void) signal(SIGALRM, (SIG_PF) closedown); 161 (void) alarm(_RPCSVC_CLOSEDOWN/2); 162} 163 164main(argc, argv) 165 int argc; 166 char *argv[]; 167{ 168 register SVCXPRT *transp = NULL; 169 int sock; 170 int proto = 0; 171 struct sockaddr_in saddr; 172 int asize = sizeof (saddr); 173 int ch; 174 175 while ((ch = getopt(argc, argv, "hdnp:")) != EOF) { 176 switch(ch) { 177 case 'd': 178 debug = ypdb_debug = 1; 179 break; 180 case 'n': 181 do_dns = 1; 182 break; 183 case 'p': 184 yp_dir = optarg; 185 break; 186 case 'h': 187 default: 188 usage(); 189 } 190 } 191 192 load_securenets(); 193 yp_init_async(); 194#ifdef DB_CACHE 195 yp_init_dbs(); 196#endif 197 if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 198 int ssize = sizeof (int); 199 200 if (saddr.sin_family != AF_INET) 201 exit(1); 202 if (getsockopt(0, SOL_SOCKET, SO_TYPE, 203 (char *)&_rpcfdtype, &ssize) == -1) 204 exit(1); 205 sock = 0; 206 _rpcpmstart = 1; 207 proto = 0; 208 openlog(progname, LOG_PID, LOG_DAEMON); 209 } else { 210 if (!debug) { 211 if (daemon(0,0)) { 212 err(1,"cannot fork"); 213 } 214 openlog(progname, LOG_PID, LOG_DAEMON); 215 } 216 sock = RPC_ANYSOCK; 217 (void) pmap_unset(YPPROG, YPVERS); 218 (void) pmap_unset(YPPROG, 1); 219 } 220 221 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 222 transp = svcudp_create(sock); 223 if (transp == NULL) { 224 _msgout("cannot create udp service."); 225 exit(1); 226 } 227 if (!_rpcpmstart) 228 proto = IPPROTO_UDP; 229 if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { 230 _msgout("unable to register (YPPROG, YPOLDVERS, udp)."); 231 exit(1); 232 } 233 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { 234 _msgout("unable to register (YPPROG, YPVERS, udp)."); 235 exit(1); 236 } 237 } 238 239 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 240 transp = svctcp_create(sock, 0, 0); 241 if (transp == NULL) { 242 _msgout("cannot create tcp service."); 243 exit(1); 244 } 245 if (!_rpcpmstart) 246 proto = IPPROTO_TCP; 247 if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { 248 _msgout("unable to register (YPPROG, YPOLDVERS, tcp)."); 249 exit(1); 250 } 251 if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { 252 _msgout("unable to register (YPPROG, YPVERS, tcp)."); 253 exit(1); 254 } 255 } 256 257 if (transp == (SVCXPRT *)NULL) { 258 _msgout("could not create a handle"); 259 exit(1); 260 } 261 if (_rpcpmstart) { 262 (void) signal(SIGALRM, (SIG_PF) closedown); 263 (void) alarm(_RPCSVC_CLOSEDOWN/2); 264 } 265/* 266 * Make sure SIGPIPE doesn't blow us away while servicing TCP 267 * connections. 268 */ 269 (void) signal(SIGPIPE, SIG_IGN); 270 (void) signal(SIGCHLD, (SIG_PF) reaper); 271 (void) signal(SIGTERM, (SIG_PF) reaper); 272 (void) signal(SIGINT, (SIG_PF) reaper); 273 (void) signal(SIGHUP, (SIG_PF) reaper); 274 yp_svc_run(); 275 _msgout("svc_run returned"); 276 exit(1); 277 /* NOTREACHED */ 278} 279