xref: /freebsd/usr.sbin/ypserv/yp_main.c (revision 952d112864d8008aa87278a30a539d888a8493cd)
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.14 1997/02/22 16:15:12 peter 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
69 static const char rcsid[] = "$Id: yp_main.c,v 1.14 1997/02/22 16:15:12 peter Exp $";
70 #endif /* not lint */
71 int _rpcpmstart;		/* Started by a port monitor ? */
72 static 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 
80 extern void ypprog_1 __P((struct svc_req *, register SVCXPRT *));
81 extern void ypprog_2 __P((struct svc_req *, register SVCXPRT *));
82 extern int _rpc_dtablesize __P((void));
83 extern int _rpcsvcstate;	 /* Set when a request is serviced */
84 char *progname = "ypserv";
85 char *yp_dir = _PATH_YP;
86 int debug = 0;
87 int do_dns = 0;
88 int resfd;
89 
90 static
91 void _msgout(char* msg)
92 {
93 	if (debug) {
94 		if (_rpcpmstart)
95 			syslog(LOG_ERR, msg);
96 		else
97 			(void) fprintf(stderr, "%s\n", msg);
98 	} else
99 		syslog(LOG_ERR, msg);
100 }
101 
102 static void
103 yp_svc_run()
104 {
105 #ifdef FD_SETSIZE
106 	fd_set readfds;
107 #else
108 	int readfds;
109 #endif /* def FD_SETSIZE */
110 	extern int forked;
111 	int pid;
112 	int fd_setsize = _rpc_dtablesize();
113 	struct timeval timeout;
114 
115 	/* Establish the identity of the parent ypserv process. */
116 	pid = getpid();
117 
118 	for (;;) {
119 #ifdef FD_SETSIZE
120 		readfds = svc_fdset;
121 #else
122 		readfds = svc_fds;
123 #endif /* def FD_SETSIZE */
124 
125 		FD_SET(resfd, &readfds);
126 
127 		timeout.tv_sec = RESOLVER_TIMEOUT;
128 		timeout.tv_usec = 0;
129 		switch (select(fd_setsize, &readfds, NULL, NULL,
130 			       &timeout)) {
131 		case -1:
132 			if (errno == EINTR) {
133 				continue;
134 			}
135 			perror("svc_run: - select failed");
136 			return;
137 		case 0:
138 			yp_prune_dnsq();
139 			break;
140 		default:
141 			if (FD_ISSET(resfd, &readfds)) {
142 				yp_run_dnsq();
143 				FD_CLR(resfd, &readfds);
144 			}
145 			svc_getreqset(&readfds);
146 			if (forked && pid != getpid())
147 				exit(0);
148 		}
149 	}
150 }
151 
152 static void unregister()
153 {
154 	(void) pmap_unset(YPPROG, YPVERS);
155 	(void) pmap_unset(YPPROG, YPOLDVERS);
156 }
157 
158 static void reaper(sig)
159 	int sig;
160 {
161 	int status;
162 
163 	if (sig == SIGHUP) {
164 		load_securenets();
165 #ifdef DB_CACHE
166 		yp_flush_all();
167 #endif
168 		return;
169 	}
170 
171 	if (sig == SIGCHLD) {
172 		while (wait3(&status, WNOHANG, NULL) > 0)
173 			children--;
174 	} else {
175 		unregister();
176 		exit(0);
177 	}
178 }
179 
180 static void usage()
181 {
182 	fprintf(stderr, "Usage: %s [-h] [-d] [-n] [-p path]\n", progname);
183 	exit(1);
184 }
185 
186 static void
187 closedown(int sig)
188 {
189 	if (_rpcsvcstate == _IDLE) {
190 		extern fd_set svc_fdset;
191 		static int size;
192 		int i, openfd;
193 
194 		if (_rpcfdtype == SOCK_DGRAM) {
195 			unregister();
196 			exit(0);
197 		}
198 		if (size == 0) {
199 			size = getdtablesize();
200 		}
201 		for (i = 0, openfd = 0; i < size && openfd < 2; i++)
202 			if (FD_ISSET(i, &svc_fdset))
203 				openfd++;
204 		if (openfd <= 1) {
205 			unregister();
206 			exit(0);
207 		}
208 	}
209 	if (_rpcsvcstate == _SERVED)
210 		_rpcsvcstate = _IDLE;
211 
212 	(void) signal(SIGALRM, (SIG_PF) closedown);
213 	(void) alarm(_RPCSVC_CLOSEDOWN/2);
214 }
215 
216 main(argc, argv)
217 	int argc;
218 	char *argv[];
219 {
220 	register SVCXPRT *transp = NULL;
221 	int sock;
222 	int proto = 0;
223 	struct sockaddr_in saddr;
224 	int asize = sizeof (saddr);
225 	int ch;
226 
227 	while ((ch = getopt(argc, argv, "hdnp:")) != -1) {
228 		switch(ch) {
229 		case 'd':
230 			debug = ypdb_debug = 1;
231 			break;
232 		case 'n':
233 			do_dns = 1;
234 			break;
235 		case 'p':
236 			yp_dir = optarg;
237 			break;
238 		case 'h':
239 		default:
240 			usage();
241 		}
242 	}
243 
244 	load_securenets();
245 	yp_init_resolver();
246 #ifdef DB_CACHE
247 	yp_init_dbs();
248 #endif
249 	if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
250 		int ssize = sizeof (int);
251 
252 		if (saddr.sin_family != AF_INET)
253 			exit(1);
254 		if (getsockopt(0, SOL_SOCKET, SO_TYPE,
255 				(char *)&_rpcfdtype, &ssize) == -1)
256 			exit(1);
257 		sock = 0;
258 		_rpcpmstart = 1;
259 		proto = 0;
260 		openlog(progname, LOG_PID, LOG_DAEMON);
261 	} else {
262 		if (!debug) {
263 			if (daemon(0,0)) {
264 				err(1,"cannot fork");
265 			}
266 			openlog(progname, LOG_PID, LOG_DAEMON);
267 		}
268 		sock = RPC_ANYSOCK;
269 		(void) pmap_unset(YPPROG, YPVERS);
270 		(void) pmap_unset(YPPROG, 1);
271 	}
272 
273 	if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
274 		transp = svcudp_create(sock);
275 		if (transp == NULL) {
276 			_msgout("cannot create udp service.");
277 			exit(1);
278 		}
279 		if (!_rpcpmstart)
280 			proto = IPPROTO_UDP;
281 		if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) {
282 			_msgout("unable to register (YPPROG, YPOLDVERS, udp).");
283 			exit(1);
284 		}
285 		if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
286 			_msgout("unable to register (YPPROG, YPVERS, udp).");
287 			exit(1);
288 		}
289 	}
290 
291 	if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
292 		transp = svctcp_create(sock, 0, 0);
293 		if (transp == NULL) {
294 			_msgout("cannot create tcp service.");
295 			exit(1);
296 		}
297 		if (!_rpcpmstart)
298 			proto = IPPROTO_TCP;
299 		if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) {
300 			_msgout("unable to register (YPPROG, YPOLDVERS, tcp).");
301 			exit(1);
302 		}
303 		if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) {
304 			_msgout("unable to register (YPPROG, YPVERS, tcp).");
305 			exit(1);
306 		}
307 	}
308 
309 	if (transp == (SVCXPRT *)NULL) {
310 		_msgout("could not create a handle");
311 		exit(1);
312 	}
313 	if (_rpcpmstart) {
314 		(void) signal(SIGALRM, (SIG_PF) closedown);
315 		(void) alarm(_RPCSVC_CLOSEDOWN/2);
316 	}
317 /*
318  * Make sure SIGPIPE doesn't blow us away while servicing TCP
319  * connections.
320  */
321 	(void) signal(SIGPIPE, SIG_IGN);
322 	(void) signal(SIGCHLD, (SIG_PF) reaper);
323 	(void) signal(SIGTERM, (SIG_PF) reaper);
324 	(void) signal(SIGINT, (SIG_PF) reaper);
325 	(void) signal(SIGHUP, (SIG_PF) reaper);
326 	yp_svc_run();
327 	_msgout("svc_run returned");
328 	exit(1);
329 	/* NOTREACHED */
330 }
331