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