1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 *
26 */
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * This source was formally rpcgen generated, but has been
31 * checked in.
32 */
33
34#include "ypxfrd.h"
35#include <stdio.h>
36#include <stdlib.h> /* getenv, exit */
37#include <signal.h>
38#include <rpc/pmap_clnt.h> /* for pmap_unset */
39#include <string.h> /* strcmp */
40#include <unistd.h> /* setsid */
41#include <sys/types.h>
42#include <memory.h>
43#include <stropts.h>
44#include <netconfig.h>
45#include <sys/resource.h> /* rlimit */
46#include <syslog.h>
47#include <ndbm.h>
48#include "shim.h"
49#include "yptol.h"
50
51#ifndef SIG_PF
52#define	SIG_PF void(*)(int)
53#endif
54
55#ifdef DEBUG
56#define	RPC_SVC_FG
57#endif
58
59#define	_RPCSVC_CLOSEDOWN 120
60
61/*
62 * Copyr 1989 Sun Micro
63 * #ident	"@(#)ypxfrd.x	1.2	00/05/01 SMI"
64 * This is NOT source code!
65 * DO NOT EDIT THIS FILE!
66 */
67static int _rpcpmstart;		/* Started by a port monitor ? */
68
69/* States a server can be in wrt request */
70
71#define	_IDLE 0
72#define	_SERVED 1
73
74static int _rpcsvcstate = _IDLE;	/* Set when a request is serviced */
75static int _rpcsvccount = 0;		/* Number of requests being serviced */
76
77static void
78_msgout(char *msg)
79{
80#ifdef RPC_SVC_FG
81	if (_rpcpmstart)
82		syslog(LOG_ERR, "%s", msg);
83	else
84		(void) fprintf(stderr, "%s\n", msg);
85#else
86	syslog(LOG_ERR, "%s", msg);
87#endif
88}
89
90static void
91closedown(int sig)
92{
93	if (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {
94		int size;
95		int i, openfd = 0;
96
97		size = svc_max_pollfd;
98		for (i = 0; i < size && openfd < 2; i++)
99			if (svc_pollfd[i].fd >= 0)
100				openfd++;
101		if (openfd <= 1)
102			exit(0);
103	} else
104		_rpcsvcstate = _IDLE;
105
106	(void) signal(SIGALRM, (SIG_PF) closedown);
107	(void) alarm(_RPCSVC_CLOSEDOWN/2);
108}
109
110static void
111ypxfrd_1(struct svc_req *rqstp, register SVCXPRT *transp)
112{
113	union {
114		hosereq getdbm_1_arg;
115	} argument;
116	char *result;
117	xdrproc_t _xdr_argument, _xdr_result;
118	char *(*local)(char *, struct svc_req *);
119
120	_rpcsvccount++;
121	switch (rqstp->rq_proc) {
122	case NULLPROC:
123		(void) svc_sendreply(transp,
124			(xdrproc_t)xdr_void, (char *)NULL);
125		_rpcsvccount--;
126		_rpcsvcstate = _SERVED;
127		return;
128
129	case getdbm:
130		_xdr_argument = (xdrproc_t)xdr_hosereq;
131		_xdr_result = (xdrproc_t)xdr_dbmfyl;
132		local = (char *(*)(char *, struct svc_req *)) getdbm_1_svc;
133		break;
134
135	default:
136		svcerr_noproc(transp);
137		_rpcsvccount--;
138		_rpcsvcstate = _SERVED;
139		return;
140	}
141	(void) memset((char *)&argument, 0, sizeof (argument));
142	if (!svc_getargs(transp, _xdr_argument, (caddr_t)&argument)) {
143		svcerr_decode(transp);
144		_rpcsvccount--;
145		_rpcsvcstate = _SERVED;
146		return;
147	}
148	result = (*local)((char *)&argument, rqstp);
149	if (_xdr_result && result != NULL &&
150		!svc_sendreply(transp, _xdr_result, result)) {
151		svcerr_systemerr(transp);
152	}
153	if (!svc_freeargs(transp, _xdr_argument, (caddr_t)&argument)) {
154		_msgout("unable to free arguments");
155		exit(1);
156	}
157	_rpcsvccount--;
158	_rpcsvcstate = _SERVED;
159}
160
161int
162main()
163{
164	pid_t pid;
165	int i;
166	int stat;
167
168	(void) sigset(SIGPIPE, SIG_IGN);
169
170	/*
171	 * If stdin looks like a TLI endpoint, we assume
172	 * that we were started by a port monitor. If
173	 * t_getstate fails with TBADF, this is not a
174	 * TLI endpoint.
175	 */
176	if (t_getstate(0) != -1 || t_errno != TBADF) {
177		char *netid;
178		struct netconfig *nconf = NULL;
179		SVCXPRT *transp;
180		int pmclose;
181
182		_rpcpmstart = 1;
183		openlog("ypxfrd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
184
185		if ((netid = getenv("NLSPROVIDER")) == NULL) {
186		/* started from inetd */
187			pmclose = 1;
188		} else {
189			if ((nconf = getnetconfigent(netid)) == NULL)
190				_msgout("cannot get transport info");
191
192			pmclose = (t_getstate(0) != T_DATAXFER);
193		}
194		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
195			_msgout("cannot create server handle");
196			exit(1);
197		}
198		if (nconf)
199			freenetconfigent(nconf);
200		if (!svc_reg(transp, YPXFRD, V1, ypxfrd_1, 0)) {
201			_msgout("unable to register (YPXFRD, V1).");
202			exit(1);
203		}
204		if (pmclose) {
205			(void) signal(SIGALRM, (SIG_PF) closedown);
206			(void) alarm(_RPCSVC_CLOSEDOWN/2);
207		}
208
209		if (yptol_mode) {
210			stat = parseConfig(NULL, NTOL_MAP_FILE);
211			if (stat == 1) {
212				_msgout("NIS to LDAP mapping inactive.");
213			} else if (stat != 0) {
214				_msgout("Aborting after NIS to LDAP "
215					"mapping error.");
216				exit(1);
217			}
218		}
219
220		svc_run();
221		exit(1);
222		/* NOTREACHED */
223	}	else {
224#ifndef RPC_SVC_FG
225#pragma weak closefrom
226		extern void closefrom();
227		int size;
228		struct rlimit rl;
229		pid = fork();
230		if (pid < 0) {
231			perror("cannot fork");
232			exit(1);
233		}
234		if (pid)
235			exit(0);
236		closelog();
237		if (closefrom != NULL)
238			closefrom(0);
239		else {
240			rl.rlim_max = 0;
241			getrlimit(RLIMIT_NOFILE, &rl);
242			if ((size = rl.rlim_max) == 0)
243				exit(1);
244			for (i = 0; i < size; i++)
245				(void) close(i);
246		}
247		i = open("/dev/null", 2);
248		(void) dup2(i, 1);
249		(void) dup2(i, 2);
250		openlog("ypxfrd", LOG_NDELAY|LOG_PID, LOG_DAEMON);
251		setsid();
252#endif
253	}
254
255	if (yptol_mode) {
256		stat = parseConfig(NULL, NTOL_MAP_FILE);
257		if (stat == 1) {
258			_msgout("NIS to LDAP mapping inactive.");
259		} else if (stat != 0) {
260			_msgout("Aborting after NIS to LDAP mapping error.");
261			exit(1);
262		}
263	}
264
265	if (!svc_create(ypxfrd_1, YPXFRD, V1, "visible")) {
266		_msgout("unable to create (YPXFRD, V1) for visible.");
267		exit(1);
268	}
269
270	svc_run();
271	_msgout("svc_run returned");
272	exit(1);
273	/* NOTREACHED */
274}
275