yp_main.c revision 30827
129088Smarkm/* 229088Smarkm * Copyright (c) 1995 329088Smarkm * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 1329088Smarkm * 3. All advertising materials mentioning features or use of this software 1429088Smarkm * must display the following acknowledgement: 1529088Smarkm * This product includes software developed by Bill Paul. 1629088Smarkm * 4. Neither the name of the author nor the names of any co-contributors 1729088Smarkm * may be used to endorse or promote products derived from this software 1829088Smarkm * without specific prior written permission. 1929088Smarkm * 2029088Smarkm * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2129088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2229088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2329088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 2429088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2529088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2629088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2729088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2829088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2929088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3029088Smarkm * SUCH DAMAGE. 3129088Smarkm */ 3229088Smarkm 3329088Smarkm#ifndef lint 34114630Sobrienstatic const char rcsid[] = 3529088Smarkm "$Id$"; 3629181Smarkm#endif /* not lint */ 3731622Scharnier 38114630Sobrien/* 39114630Sobrien * ypserv startup function. 40114630Sobrien * We need out own main() since we have to do some additional work 4129088Smarkm * that rpcgen won't do for us. Most of this file was generated using 4279981Sru * rpcgen.new, and later modified. 4329088Smarkm */ 4487139Smarkm 4529088Smarkm#include "yp.h" 4629088Smarkm#include <err.h> 4787139Smarkm#include <errno.h> 4829181Smarkm#include <memory.h> 4929181Smarkm#include <stdio.h> 5029088Smarkm#include <signal.h> 5129088Smarkm#include <stdlib.h> /* getenv, exit */ 5229088Smarkm#include <string.h> /* strcmp */ 5329088Smarkm#include <syslog.h> 5429088Smarkm#include <unistd.h> 5529088Smarkm#include <rpc/pmap_clnt.h> /* for pmap_unset */ 5629088Smarkm#include <sys/ttycom.h> /* TIOCNOTTY */ 5729088Smarkm#ifdef __cplusplus 5829088Smarkm#include <sysent.h> /* getdtablesize, open */ 5929088Smarkm#endif /* __cplusplus */ 6029088Smarkm#include <sys/socket.h> 6129088Smarkm#include <netinet/in.h> 6229088Smarkm#include <sys/wait.h> 6329088Smarkm#include "yp_extern.h" 6429088Smarkm#include <rpc/rpc.h> 6529088Smarkm 6629088Smarkm#ifndef SIG_PF 6729088Smarkm#define SIG_PF void(*)(int) 6829088Smarkm#endif 6929088Smarkm 7029088Smarkm#define _RPCSVC_CLOSEDOWN 120 7129088Smarkmint _rpcpmstart; /* Started by a port monitor ? */ 7229088Smarkmstatic int _rpcfdtype; 7329088Smarkm /* Whether Stream or Datagram ? */ 7429088Smarkm /* States a server can be in wrt request */ 7529088Smarkm 7629088Smarkm#define _IDLE 0 7729088Smarkm#define _SERVED 1 7829088Smarkm#define _SERVING 2 7929088Smarkm 8029088Smarkmextern void ypprog_1 __P((struct svc_req *, register SVCXPRT *)); 8129088Smarkmextern void ypprog_2 __P((struct svc_req *, register SVCXPRT *)); 8229088Smarkmextern int _rpc_dtablesize __P((void)); 8329088Smarkmextern int _rpcsvcstate; /* Set when a request is serviced */ 8429088Smarkmchar *progname = "ypserv"; 8529088Smarkmchar *yp_dir = _PATH_YP; 8629088Smarkmint debug = 0; 8729088Smarkmint do_dns = 0; 8829088Smarkmint resfd; 8929088Smarkm 9029088Smarkmstatic 9129088Smarkmvoid _msgout(char* msg) 9287139Smarkm{ 9387139Smarkm if (debug) { 9487139Smarkm if (_rpcpmstart) 9587139Smarkm syslog(LOG_ERR, msg); 9629088Smarkm else 9787139Smarkm warnx("%s", msg); 9829088Smarkm } else 9929088Smarkm syslog(LOG_ERR, msg); 10029088Smarkm} 10129088Smarkm 10229088Smarkmstatic void 10329088Smarkmyp_svc_run() 10429088Smarkm{ 10529088Smarkm#ifdef FD_SETSIZE 10629088Smarkm fd_set readfds; 10729088Smarkm#else 10829088Smarkm int readfds; 10929088Smarkm#endif /* def FD_SETSIZE */ 11029088Smarkm extern int forked; 11129088Smarkm int pid; 11229088Smarkm int fd_setsize = _rpc_dtablesize(); 11329088Smarkm struct timeval timeout; 11429088Smarkm 11529088Smarkm /* Establish the identity of the parent ypserv process. */ 116103956Smarkm pid = getpid(); 11729088Smarkm 11829088Smarkm for (;;) { 11929088Smarkm#ifdef FD_SETSIZE 12029088Smarkm readfds = svc_fdset; 12129088Smarkm#else 12229088Smarkm readfds = svc_fds; 12329088Smarkm#endif /* def FD_SETSIZE */ 12429088Smarkm 12529088Smarkm FD_SET(resfd, &readfds); 12629088Smarkm 12729088Smarkm timeout.tv_sec = RESOLVER_TIMEOUT; 12829088Smarkm timeout.tv_usec = 0; 12929088Smarkm switch (select(fd_setsize, &readfds, NULL, NULL, 13029088Smarkm &timeout)) { 13129088Smarkm case -1: 13229088Smarkm if (errno == EINTR) { 13329088Smarkm continue; 13429088Smarkm } 13529088Smarkm warn("svc_run: - select failed"); 13629088Smarkm return; 13729088Smarkm case 0: 13829088Smarkm yp_prune_dnsq(); 13929088Smarkm break; 14029088Smarkm default: 14129088Smarkm if (FD_ISSET(resfd, &readfds)) { 14229088Smarkm yp_run_dnsq(); 14329088Smarkm FD_CLR(resfd, &readfds); 14429088Smarkm } 14529088Smarkm svc_getreqset(&readfds); 14629088Smarkm if (forked && pid != getpid()) 14729088Smarkm exit(0); 14829088Smarkm } 14929088Smarkm } 15029088Smarkm} 15129088Smarkm 15229088Smarkmstatic void unregister() 15329088Smarkm{ 15429088Smarkm (void) pmap_unset(YPPROG, YPVERS); 15529088Smarkm (void) pmap_unset(YPPROG, YPOLDVERS); 15629088Smarkm} 15729088Smarkm 15829088Smarkmstatic void reaper(sig) 15929088Smarkm int sig; 16029088Smarkm{ 16129088Smarkm int status; 16229088Smarkm 16329088Smarkm if (sig == SIGHUP) { 16429088Smarkm load_securenets(); 16529088Smarkm#ifdef DB_CACHE 16629088Smarkm yp_flush_all(); 16729088Smarkm#endif 16829088Smarkm return; 16929088Smarkm } 17029088Smarkm 17129088Smarkm if (sig == SIGCHLD) { 17229088Smarkm while (wait3(&status, WNOHANG, NULL) > 0) 17329088Smarkm children--; 17429088Smarkm } else { 17529088Smarkm unregister(); 17629088Smarkm exit(0); 17729088Smarkm } 17829088Smarkm} 17929088Smarkm 18029088Smarkmstatic void usage() 18129088Smarkm{ 18229088Smarkm fprintf(stderr, "usage: ypserv [-h] [-d] [-n] [-p path]\n"); 18329088Smarkm exit(1); 18429088Smarkm} 18529088Smarkm 18629088Smarkmstatic void 18729088Smarkmclosedown(int sig) 18829088Smarkm{ 18929088Smarkm if (_rpcsvcstate == _IDLE) { 19029088Smarkm extern fd_set svc_fdset; 19129088Smarkm static int size; 19229088Smarkm int i, openfd; 19329088Smarkm 19429088Smarkm if (_rpcfdtype == SOCK_DGRAM) { 19529088Smarkm unregister(); 19629088Smarkm exit(0); 19729088Smarkm } 19829088Smarkm if (size == 0) { 19929088Smarkm size = getdtablesize(); 20029088Smarkm } 20129088Smarkm for (i = 0, openfd = 0; i < size && openfd < 2; i++) 20229088Smarkm if (FD_ISSET(i, &svc_fdset)) 20329088Smarkm openfd++; 20429088Smarkm if (openfd <= 1) { 20529088Smarkm unregister(); 20629088Smarkm exit(0); 20729088Smarkm } 20879981Sru } 20929088Smarkm if (_rpcsvcstate == _SERVED) 21029088Smarkm _rpcsvcstate = _IDLE; 21129088Smarkm 21229088Smarkm (void) signal(SIGALRM, (SIG_PF) closedown); 21329088Smarkm (void) alarm(_RPCSVC_CLOSEDOWN/2); 21429088Smarkm} 21529088Smarkm 21629088Smarkmint 21729088Smarkmmain(argc, argv) 21829088Smarkm int argc; 21929088Smarkm char *argv[]; 22029088Smarkm{ 22129088Smarkm register SVCXPRT *transp = NULL; 22229088Smarkm int sock; 22329088Smarkm int proto = 0; 22429088Smarkm struct sockaddr_in saddr; 22529088Smarkm int asize = sizeof (saddr); 22629088Smarkm int ch; 22729088Smarkm 22829088Smarkm while ((ch = getopt(argc, argv, "hdnp:")) != -1) { 22929088Smarkm switch(ch) { 23029088Smarkm case 'd': 23129088Smarkm debug = ypdb_debug = 1; 23229088Smarkm break; 23329088Smarkm case 'n': 23429088Smarkm do_dns = 1; 23529088Smarkm break; 23629088Smarkm case 'p': 23729088Smarkm yp_dir = optarg; 23829088Smarkm break; 23929088Smarkm case 'h': 24029088Smarkm default: 24129088Smarkm usage(); 24229088Smarkm } 24329088Smarkm } 24429088Smarkm 24529088Smarkm load_securenets(); 24629088Smarkm yp_init_resolver(); 24729088Smarkm#ifdef DB_CACHE 24829088Smarkm yp_init_dbs(); 24929088Smarkm#endif 25029088Smarkm if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 25129088Smarkm int ssize = sizeof (int); 25229088Smarkm 25329088Smarkm if (saddr.sin_family != AF_INET) 25429088Smarkm exit(1); 25529088Smarkm if (getsockopt(0, SOL_SOCKET, SO_TYPE, 25629088Smarkm (char *)&_rpcfdtype, &ssize) == -1) 25729088Smarkm exit(1); 25829088Smarkm sock = 0; 25929088Smarkm _rpcpmstart = 1; 26029088Smarkm proto = 0; 26129088Smarkm openlog("ypserv", LOG_PID, LOG_DAEMON); 26229088Smarkm } else { 26329088Smarkm if (!debug) { 26429088Smarkm if (daemon(0,0)) { 26529088Smarkm err(1,"cannot fork"); 26629088Smarkm } 26729088Smarkm openlog("ypserv", LOG_PID, LOG_DAEMON); 26829088Smarkm } 26929088Smarkm sock = RPC_ANYSOCK; 27029088Smarkm (void) pmap_unset(YPPROG, YPVERS); 27129088Smarkm (void) pmap_unset(YPPROG, 1); 27229088Smarkm } 27329088Smarkm 27429088Smarkm if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 27529088Smarkm transp = svcudp_create(sock); 27629088Smarkm if (transp == NULL) { 27729088Smarkm _msgout("cannot create udp service"); 27829088Smarkm exit(1); 27929088Smarkm } 28029088Smarkm if (!_rpcpmstart) 28129088Smarkm proto = IPPROTO_UDP; 28229088Smarkm if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { 28329088Smarkm _msgout("unable to register (YPPROG, YPOLDVERS, udp)"); 28429088Smarkm exit(1); 28529088Smarkm } 28629088Smarkm if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { 28729088Smarkm _msgout("unable to register (YPPROG, YPVERS, udp)"); 28829088Smarkm exit(1); 28929088Smarkm } 29029088Smarkm } 29129088Smarkm 29229088Smarkm if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 29329088Smarkm transp = svctcp_create(sock, 0, 0); 29429088Smarkm if (transp == NULL) { 29529088Smarkm _msgout("cannot create tcp service"); 29629088Smarkm exit(1); 29729088Smarkm } 29829088Smarkm if (!_rpcpmstart) 29929088Smarkm proto = IPPROTO_TCP; 30029088Smarkm if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { 30129088Smarkm _msgout("unable to register (YPPROG, YPOLDVERS, tcp)"); 30229088Smarkm exit(1); 30329088Smarkm } 30429088Smarkm if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { 30529088Smarkm _msgout("unable to register (YPPROG, YPVERS, tcp)"); 30629088Smarkm exit(1); 30729088Smarkm } 30829088Smarkm } 30929088Smarkm 31029088Smarkm if (transp == (SVCXPRT *)NULL) { 31129088Smarkm _msgout("could not create a handle"); 31229088Smarkm exit(1); 31329088Smarkm } 31429088Smarkm if (_rpcpmstart) { 31529088Smarkm (void) signal(SIGALRM, (SIG_PF) closedown); 31629088Smarkm (void) alarm(_RPCSVC_CLOSEDOWN/2); 31729088Smarkm } 31829088Smarkm/* 31929088Smarkm * Make sure SIGPIPE doesn't blow us away while servicing TCP 32029088Smarkm * connections. 32129088Smarkm */ 32229088Smarkm (void) signal(SIGPIPE, SIG_IGN); 32329088Smarkm (void) signal(SIGCHLD, (SIG_PF) reaper); 32429088Smarkm (void) signal(SIGTERM, (SIG_PF) reaper); 32529088Smarkm (void) signal(SIGINT, (SIG_PF) reaper); 32629088Smarkm (void) signal(SIGHUP, (SIG_PF) reaper); 32729088Smarkm yp_svc_run(); 32829088Smarkm _msgout("svc_run returned"); 32929088Smarkm exit(1); 33029088Smarkm /* NOTREACHED */ 33129088Smarkm} 33229088Smarkm