1 /*
2  * Please do not edit this file.
3  * It was generated using rpcgen.
4  */
5 
6 #include "rwall.h"
7 #include <stdio.h>
8 #include <stdlib.h> /* getenv, exit */
9 #include <signal.h>
10 #include <sys/types.h>
11 #include <memory.h>
12 #include <stropts.h>
13 #include <netconfig.h>
14 #include <sys/resource.h> /* rlimit */
15 #include <syslog.h>
16 
17 #ifdef DEBUG
18 #define	RPC_SVC_FG
19 #endif
20 
21 #define	_RPCSVC_CLOSEDOWN 120
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * CDDL HEADER START
27  *
28  * The contents of this file are subject to the terms of the
29  * Common Development and Distribution License, Version 1.0 only
30  * (the "License").  You may not use this file except in compliance
31  * with the License.
32  *
33  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
34  * or http://www.opensolaris.org/os/licensing.
35  * See the License for the specific language governing permissions
36  * and limitations under the License.
37  *
38  * When distributing Covered Code, include this CDDL HEADER in each
39  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
40  * If applicable, add the following below this CDDL HEADER, with the
41  * fields enclosed by brackets "[]" replaced with your own identifying
42  * information: Portions Copyright [yyyy] [name of copyright owner]
43  *
44  * CDDL HEADER END
45  */
46 /* from rwall.x */
47 
48 /*
49  * Remote write-all ONC service
50  */
51 
52 /*
53  *  Server side stub routines for the rpc.rwalld daemon
54  */
55 
56 static int _rpcpmstart;		/* Started by a port monitor ? */
57 
58 /* States a server can be in wrt request */
59 
60 #define	_IDLE 0
61 #define	_SERVED 1
62 
63 static int _rpcsvcstate = _IDLE;	/* Set when a request is serviced */
64 static int _rpcsvccount = 0;		/* Number of requests being serviced */
65 mutex_t _svcstate_lock;		/* lock for _rpcsvcstate, _rpcsvccount */
66 
67 #if	defined(RPC_MSGOUT)
68 extern void RPC_MSGOUT();
69 #else	/* defined(RPC_MSGOUT) */
70 static void
71 RPC_MSGOUT(fmt, msg)
72 	char *fmt;
73 	char *msg;
74 {
75 #ifdef RPC_SVC_FG
76 	if (_rpcpmstart)
77 		syslog(LOG_ERR, fmt, msg);
78 	else {
79 		(void) fprintf(stderr, fmt, msg);
80 		(void) putc('\n', stderr);
81 	}
82 #else
83 	syslog(LOG_ERR, fmt, msg);
84 #endif
85 }
86 #endif	/* defined(RPC_MSGOUT) */
87 
88 /*ARGSUSED*/
89 static void *
90 closedown(arg)
91 	void *arg;
92 {
93 	/*CONSTCOND*/
94 	while (1) {
95 		(void) sleep(_RPCSVC_CLOSEDOWN/2);
96 
97 		if (mutex_trylock(&_svcstate_lock) != 0)
98 			continue;
99 
100 		if (_rpcsvcstate == _IDLE && _rpcsvccount == 0) {
101 			int size;
102 			int i, openfd = 0;
103 
104 			size = svc_max_pollfd;
105 			for (i = 0; i < size && openfd < 2; i++)
106 				if (svc_pollfd[i].fd >= 0)
107 					openfd++;
108 			if (openfd <= 1)
109 				exit(0);
110 		} else
111 			_rpcsvcstate = _IDLE;
112 
113 		(void) mutex_unlock(&_svcstate_lock);
114 	}
115 }
116 
117 static void
118 wallprog_1(rqstp, transp)
119 	struct svc_req *rqstp;
120 	register SVCXPRT *transp;
121 {
122 	union {
123 		wrapstring wallproc_wall_1_arg;
124 	} argument;
125 	union {
126 		int fill;
127 	} result;
128 	bool_t retval;
129 	bool_t (*_xdr_argument)(), (*_xdr_result)();
130 	bool_t (*local)();
131 
132 	(void) mutex_lock(&_svcstate_lock);
133 	_rpcsvccount++;
134 	(void) mutex_unlock(&_svcstate_lock);
135 	switch (rqstp->rq_proc) {
136 	case NULLPROC:
137 		(void) svc_sendreply(transp, xdr_void,
138 			NULL);
139 		(void) mutex_lock(&_svcstate_lock);
140 		_rpcsvccount--;
141 		_rpcsvcstate = _SERVED;
142 		(void) mutex_unlock(&_svcstate_lock);
143 		return; /* CSTYLED */
144 
145 	case WALLPROC_WALL:
146 		_xdr_argument = xdr_wrapstring;
147 		_xdr_result = xdr_void;
148 		local = (bool_t (*)())
149 		    wallproc_wall_1_svc;
150 		break;
151 
152 	default:
153 		svcerr_noproc(transp);
154 		(void) mutex_lock(&_svcstate_lock);
155 		_rpcsvccount--;
156 		_rpcsvcstate = _SERVED;
157 		(void) mutex_unlock(&_svcstate_lock);
158 		return; /* CSTYLED */
159 	}
160 	(void) memset((char *)&argument, 0, sizeof (argument));
161 	if (!svc_getargs(transp, _xdr_argument, (caddr_t)&argument)) {
162 		svcerr_decode(transp);
163 		(void) mutex_lock(&_svcstate_lock);
164 		_rpcsvccount--;
165 		_rpcsvcstate = _SERVED;
166 		(void) mutex_unlock(&_svcstate_lock);
167 		return; /* CSTYLED */
168 	}
169 	retval = (bool_t)(*local)(&argument, &result, rqstp);
170 	if (_xdr_result && retval > 0 &&
171 	    !svc_sendreply(transp, _xdr_result, (char *)&result)) {
172 		svcerr_systemerr(transp);
173 	}
174 	if (!svc_freeargs(transp, _xdr_argument, (caddr_t)&argument)) {
175 		RPC_MSGOUT("%s",
176 		    "unable to free arguments");
177 		exit(1);
178 	}
179 	if (_xdr_result != NULL) {
180 		if (!wallprog_1_freeresult(transp, _xdr_result,
181 		    (caddr_t)&result))
182 			RPC_MSGOUT("%s",
183 			    "unable to free results");
184 
185 	}
186 	(void) mutex_lock(&_svcstate_lock);
187 	_rpcsvccount--;
188 	_rpcsvcstate = _SERVED;
189 	(void) mutex_unlock(&_svcstate_lock);
190 	return; /* CSTYLED */
191 }
192 
193 int
194 main()
195 {
196 	pid_t pid;
197 	int i;
198 	int mode = RPC_SVC_MT_AUTO;
199 
200 	if (!rpc_control(RPC_SVC_MTMODE_SET, &mode)) {
201 		RPC_MSGOUT("%s",
202 		    "unable to set automatic MT mode.");
203 		exit(1);
204 	}
205 	mutex_init(&_svcstate_lock, USYNC_THREAD, NULL);
206 	(void) sigset(SIGPIPE, SIG_IGN);
207 
208 	/*
209 	 * If stdin looks like a TLI endpoint, we assume
210 	 * that we were started by a port monitor. If
211 	 * t_getstate fails with TBADF, this is not a
212 	 * TLI endpoint.
213 	 */
214 	if (t_getstate(0) != -1 || t_errno != TBADF) {
215 		char *netid;
216 		struct netconfig *nconf = NULL;
217 		SVCXPRT *transp;
218 		int pmclose;
219 
220 		_rpcpmstart = 1;
221 		openlog("rwall", LOG_PID, LOG_DAEMON);
222 
223 		if ((netid = getenv("NLSPROVIDER")) == NULL) {
224 		/* started from inetd */
225 			pmclose = 1;
226 		} else {
227 			if ((nconf = getnetconfigent(netid)) == NULL)
228 				RPC_MSGOUT("%s",
229 				    "cannot get transport info");
230 
231 			pmclose = (t_getstate(0) != T_DATAXFER);
232 		}
233 		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
234 			RPC_MSGOUT("%s",
235 			    "cannot create server handle");
236 			exit(1);
237 		}
238 		if (nconf)
239 			freenetconfigent(nconf);
240 		if (!svc_reg(transp, WALLPROG, WALLVERS,
241 		    wallprog_1, 0)) {
242 			RPC_MSGOUT("%s",
243 			    "unable to register (WALLPROG, WALLVERS).");
244 			exit(1);
245 		}
246 		if (pmclose) {
247 			if (thr_create(NULL, 0, closedown, NULL,
248 			    0, NULL) != 0) {
249 				RPC_MSGOUT("%s",
250 				    "cannot create closedown thread");
251 				exit(1);
252 			}
253 		}
254 		svc_run();
255 		exit(1);
256 		/* NOTREACHED */
257 	}	else {
258 #ifndef RPC_SVC_FG
259 #pragma weak closefrom
260 		extern void closefrom();
261 		int size;
262 		struct rlimit rl;
263 		pid = fork();
264 		if (pid < 0) {
265 			perror("cannot fork");
266 			exit(1);
267 		}
268 		if (pid)
269 			exit(0);
270 		if (closefrom != NULL)
271 			closefrom(0);
272 		else {
273 			rl.rlim_max = 0;
274 			getrlimit(RLIMIT_NOFILE, &rl);
275 			if ((size = rl.rlim_max) == 0)
276 				exit(1);
277 			for (i = 0; i < size; i++)
278 				(void) close(i);
279 		}
280 		i = open("/dev/null", 2);
281 		(void) dup2(i, 1);
282 		(void) dup2(i, 2);
283 		setsid();
284 		openlog("rwall", LOG_PID, LOG_DAEMON);
285 #endif
286 	}
287 	if (!svc_create(
288 	    wallprog_1, WALLPROG, WALLVERS,
289 	    "datagram_v")) {
290 		RPC_MSGOUT("%s",
291 		    "unable to create (WALLPROG, WALLVERS) for datagram_v.");
292 		exit(1);
293 	}
294 
295 	svc_run();
296 	RPC_MSGOUT("%s",
297 	    "svc_run returned");
298 	exit(1);
299 	/* NOTREACHED */
300 }
301