yp*(8): Fix building with -fno-common.
[dragonfly.git] / usr.sbin / rpc.ypxfrd / ypxfrd_main.c
CommitLineData
984263bc
MD
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.
1de703da
MD
31 *
32 * $FreeBSD: src/usr.sbin/rpc.ypxfrd/ypxfrd_main.c,v 1.8.2.3 2002/02/15 00:46:58 des Exp $
984263bc
MD
33 */
34
984263bc
MD
35#include "ypxfrd.h"
36#include <err.h>
37#include <fcntl.h>
38#include <paths.h>
39#include <stdio.h>
40#include <stdlib.h> /* getenv, exit */
41#include <unistd.h>
42#include <rpc/pmap_clnt.h> /* for pmap_unset */
74457d3f 43#include <rpc/rpc_com.h>
984263bc
MD
44#include <string.h> /* strcmp */
45#include <signal.h>
46#include <sys/ttycom.h> /* TIOCNOTTY */
47#ifdef __cplusplus
48#include <sysent.h> /* getdtablesize, open */
49#endif /* __cplusplus */
50#include <memory.h>
51#include <sys/socket.h>
52#include <netinet/in.h>
53#include <syslog.h>
54#include "ypxfrd_extern.h"
55#include <sys/wait.h>
56#include <errno.h>
57
58#ifndef SIG_PF
59#define SIG_PF void(*)(int)
60#endif
61
62#ifdef DEBUG
63#define RPC_SVC_FG
64#endif
65
66#define _RPCSVC_CLOSEDOWN 120
67int _rpcpmstart; /* Started by a port monitor ? */
68static int _rpcfdtype;
69 /* Whether Stream or Datagram ? */
70 /* States a server can be in wrt request */
71
72#define _IDLE 0
73#define _SERVED 1
74#define _SERVING 2
75
76extern int _rpcsvcstate; /* Set when a request is serviced */
77
04277bb2
SW
78int debug;
79
984263bc
MD
80char *progname = "rpc.ypxfrd";
81char *yp_dir = "/var/yp/";
82
2e3ed54d
SW
83static void
84_msgout(char *msg)
984263bc
MD
85{
86#ifdef RPC_SVC_FG
87 if (_rpcpmstart)
88 syslog(LOG_ERR, "%s", msg);
89 else
90 warnx("%s", msg);
91#else
92 syslog(LOG_ERR, "%s", msg);
93#endif
94}
95
96static void
97closedown(int sig)
98{
99 if (_rpcsvcstate == _IDLE) {
100 extern fd_set svc_fdset;
101 static int size;
102 int i, openfd;
103
104 if (_rpcfdtype == SOCK_DGRAM)
105 exit(0);
106 if (size == 0) {
107 size = getdtablesize();
108 }
109 for (i = 0, openfd = 0; i < size && openfd < 2; i++)
110 if (FD_ISSET(i, &svc_fdset))
111 openfd++;
112 if (openfd <= 1)
113 exit(0);
114 }
115 if (_rpcsvcstate == _SERVED)
116 _rpcsvcstate = _IDLE;
117
71126e33
SW
118 signal(SIGALRM, (SIG_PF) closedown);
119 alarm(_RPCSVC_CLOSEDOWN/2);
984263bc
MD
120}
121
122
123static void
2e3ed54d 124ypxfrd_svc_run(void)
984263bc
MD
125{
126#ifdef FD_SETSIZE
127 fd_set readfds;
128#else
129 int readfds;
130#endif /* def FD_SETSIZE */
131 extern int forked;
132 int pid;
133 int fd_setsize = _rpc_dtablesize();
134
135 /* Establish the identity of the parent ypserv process. */
136 pid = getpid();
137
138 for (;;) {
139#ifdef FD_SETSIZE
140 readfds = svc_fdset;
141#else
142 readfds = svc_fds;
143#endif /* def FD_SETSIZE */
60233e58 144 switch (select(fd_setsize, &readfds, NULL, NULL, NULL)) {
984263bc
MD
145 case -1:
146 if (errno == EINTR) {
147 continue;
148 }
149 warn("svc_run: - select failed");
150 return;
151 case 0:
152 continue;
153 default:
154 svc_getreqset(&readfds);
155 if (forked && pid != getpid())
156 exit(0);
157 }
158 }
159}
160
2e3ed54d
SW
161static void
162reaper(int sig)
984263bc
MD
163{
164 int status;
165 int saved_errno;
166
167 saved_errno = errno;
168
169 if (sig == SIGHUP) {
170 load_securenets();
171 errno = saved_errno;
172 return;
173 }
174
175 if (sig == SIGCHLD) {
176 while (wait3(&status, WNOHANG, NULL) > 0)
177 children--;
178 } else {
71126e33 179 pmap_unset(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS);
984263bc
MD
180 exit(0);
181 }
182
183 errno = saved_errno;
184 return;
185}
186
fe08e20d 187__dead2 void
2e3ed54d 188usage(void)
984263bc
MD
189{
190 fprintf(stderr, "usage: rpc.ypxfrd [-p path]\n");
191 exit(0);
192}
193
194int
2e3ed54d 195main(int argc, char *argv[])
984263bc 196{
1ab20d67 197 SVCXPRT *transp = NULL;
984263bc
MD
198 int sock;
199 int proto = 0;
200 struct sockaddr_in saddr;
201 int asize = sizeof (saddr);
202 int ch;
203
204 while ((ch = getopt(argc, argv, "p:h")) != -1) {
205 switch (ch) {
206 case 'p':
207 yp_dir = optarg;
208 break;
209 default:
210 usage();
211 break;
212 }
213 }
214
215 load_securenets();
216
217 if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
218 int ssize = sizeof (int);
219
220 if (saddr.sin_family != AF_INET)
221 exit(1);
222 if (getsockopt(0, SOL_SOCKET, SO_TYPE,
223 (char *)&_rpcfdtype, &ssize) == -1)
224 exit(1);
225 sock = 0;
226 _rpcpmstart = 1;
227 proto = 0;
228 openlog("rpc.ypxfrd", LOG_PID, LOG_DAEMON);
229 } else {
230#ifndef RPC_SVC_FG
231 int size;
232 int pid, i;
233
234 pid = fork();
235 if (pid < 0)
236 err(1, "fork");
237 if (pid)
238 exit(0);
239 size = getdtablesize();
240 for (i = 0; i < size; i++)
71126e33 241 close(i);
984263bc 242 i = open(_PATH_CONSOLE, 2);
71126e33
SW
243 dup2(i, 1);
244 dup2(i, 2);
984263bc
MD
245 i = open(_PATH_TTY, 2);
246 if (i >= 0) {
2038fb68 247 ioctl(i, TIOCNOTTY, NULL);
71126e33 248 close(i);
984263bc
MD
249 }
250 openlog("rpc.ypxfrd", LOG_PID, LOG_DAEMON);
251#endif
252 sock = RPC_ANYSOCK;
71126e33 253 pmap_unset(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS);
984263bc
MD
254 }
255
256 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
257 transp = svcudp_create(sock);
258 if (transp == NULL) {
259 _msgout("cannot create udp service.");
260 exit(1);
261 }
262 if (!_rpcpmstart)
263 proto = IPPROTO_UDP;
264 if (!svc_register(transp, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, ypxfrd_freebsd_prog_1, proto)) {
265 _msgout("unable to register (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, udp).");
266 exit(1);
267 }
268 }
269
270 if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
271 transp = svctcp_create(sock, 0, 0);
272 if (transp == NULL) {
273 _msgout("cannot create tcp service.");
274 exit(1);
275 }
276 if (!_rpcpmstart)
277 proto = IPPROTO_TCP;
278 if (!svc_register(transp, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, ypxfrd_freebsd_prog_1, proto)) {
279 _msgout("unable to register (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, tcp).");
280 exit(1);
281 }
282 }
283
2038fb68 284 if (transp == NULL) {
984263bc
MD
285 _msgout("could not create a handle");
286 exit(1);
287 }
288 if (_rpcpmstart) {
71126e33
SW
289 signal(SIGALRM, (SIG_PF) closedown);
290 alarm(_RPCSVC_CLOSEDOWN/2);
984263bc
MD
291 }
292
71126e33
SW
293 signal(SIGPIPE, SIG_IGN);
294 signal(SIGCHLD, (SIG_PF) reaper);
295 signal(SIGTERM, (SIG_PF) reaper);
296 signal(SIGINT, (SIG_PF) reaper);
297 signal(SIGHUP, (SIG_PF) reaper);
984263bc
MD
298
299 ypxfrd_svc_run();
300 _msgout("svc_run returned");
301 exit(1);
302 /* NOTREACHED */
303}