xref: /titanic_41/usr/src/cmd/rpcsvc/rpc.rusersd.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  *
22*7c478bd9Sstevel@tonic-gate  * Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
23*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24*7c478bd9Sstevel@tonic-gate  */
25*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
26*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
29*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
30*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
33*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
34*7c478bd9Sstevel@tonic-gate  * contributors.
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #include <stdio.h>
40*7c478bd9Sstevel@tonic-gate #include <signal.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
42*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
43*7c478bd9Sstevel@tonic-gate #include <memory.h>
44*7c478bd9Sstevel@tonic-gate #include <netconfig.h>
45*7c478bd9Sstevel@tonic-gate #include <stropts.h>
46*7c478bd9Sstevel@tonic-gate #include <syslog.h>
47*7c478bd9Sstevel@tonic-gate #include <utmpx.h>
48*7c478bd9Sstevel@tonic-gate #include <rpcsvc/rusers.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/resource.h>
50*7c478bd9Sstevel@tonic-gate #include <limits.h>
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
53*7c478bd9Sstevel@tonic-gate #define	RPC_SVC_FG
54*7c478bd9Sstevel@tonic-gate #endif
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate #define	_RPCSVC_CLOSEDOWN 120
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate static void rusers_service();
59*7c478bd9Sstevel@tonic-gate static void closedown();
60*7c478bd9Sstevel@tonic-gate static void msgout();
61*7c478bd9Sstevel@tonic-gate static unsigned min();
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate static int _rpcpmstart;		/* Started by a port monitor ? */
64*7c478bd9Sstevel@tonic-gate static int _rpcfdtype;		/* Whether Stream or Datagram ? */
65*7c478bd9Sstevel@tonic-gate static int _rpcsvcdirty;	/* Still serving ? */
66*7c478bd9Sstevel@tonic-gate static int _rpcsvcrecent;	/* set when we serivce a request; tested */
67*7c478bd9Sstevel@tonic-gate 				/* and cleared by closedown() routine */
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate #define	DIV60(t)	((t+30)/60)	/* x/60 rounded */
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate #define	ALL_ENTRIES	1
72*7c478bd9Sstevel@tonic-gate #define	REAL_USERS	0
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate utmp_array utmp_array_res;
75*7c478bd9Sstevel@tonic-gate int used_array_len = 0;
76*7c478bd9Sstevel@tonic-gate struct utmpidlearr utmpidlearr;
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate main()
79*7c478bd9Sstevel@tonic-gate {
80*7c478bd9Sstevel@tonic-gate 	pid_t pid;
81*7c478bd9Sstevel@tonic-gate 	int i;
82*7c478bd9Sstevel@tonic-gate 	int connmaxrec = RPC_MAXDATASIZE;
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate 	/*
85*7c478bd9Sstevel@tonic-gate 	 * Set non-blocking mode and maximum record size for
86*7c478bd9Sstevel@tonic-gate 	 * connection oriented RPC transports.
87*7c478bd9Sstevel@tonic-gate 	 */
88*7c478bd9Sstevel@tonic-gate 	if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
89*7c478bd9Sstevel@tonic-gate 		msgout("unable to set maximum RPC record size");
90*7c478bd9Sstevel@tonic-gate 	}
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate 	/*
93*7c478bd9Sstevel@tonic-gate 	 * If stdin looks like a TLI endpoint, we assume
94*7c478bd9Sstevel@tonic-gate 	 * that we were started by a port monitor. If
95*7c478bd9Sstevel@tonic-gate 	 * t_getstate fails with TBADF, this is not a
96*7c478bd9Sstevel@tonic-gate 	 * TLI endpoint.
97*7c478bd9Sstevel@tonic-gate 	 */
98*7c478bd9Sstevel@tonic-gate 	if (t_getstate(0) != -1 || t_errno != TBADF) {
99*7c478bd9Sstevel@tonic-gate 		char *netid;
100*7c478bd9Sstevel@tonic-gate 		struct netconfig *nconf = NULL;
101*7c478bd9Sstevel@tonic-gate 		SVCXPRT *transp;
102*7c478bd9Sstevel@tonic-gate 		int pmclose;
103*7c478bd9Sstevel@tonic-gate 		extern char *getenv();
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 		_rpcpmstart = 1;
106*7c478bd9Sstevel@tonic-gate 		openlog("rusers", LOG_PID, LOG_DAEMON);
107*7c478bd9Sstevel@tonic-gate 		if ((netid = getenv("NLSPROVIDER")) == NULL) {
108*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
109*7c478bd9Sstevel@tonic-gate 			msgout("cannot get transport name");
110*7c478bd9Sstevel@tonic-gate #endif
111*7c478bd9Sstevel@tonic-gate 		} else if ((nconf = getnetconfigent(netid)) == NULL) {
112*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
113*7c478bd9Sstevel@tonic-gate 			msgout("cannot get transport info");
114*7c478bd9Sstevel@tonic-gate #endif
115*7c478bd9Sstevel@tonic-gate 		}
116*7c478bd9Sstevel@tonic-gate 		if ((transp = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {
117*7c478bd9Sstevel@tonic-gate 			msgout("cannot create server handle");
118*7c478bd9Sstevel@tonic-gate 			exit(1);
119*7c478bd9Sstevel@tonic-gate 		}
120*7c478bd9Sstevel@tonic-gate 		if (nconf)
121*7c478bd9Sstevel@tonic-gate 			freenetconfigent(nconf);
122*7c478bd9Sstevel@tonic-gate 		if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_3, rusers_service,
123*7c478bd9Sstevel@tonic-gate 				0)) {
124*7c478bd9Sstevel@tonic-gate 	msgout("unable to register (RUSERSPROG, RUSERSVERS_3).");
125*7c478bd9Sstevel@tonic-gate 			exit(1);
126*7c478bd9Sstevel@tonic-gate 		}
127*7c478bd9Sstevel@tonic-gate 		if (!svc_reg(transp, RUSERSPROG, RUSERSVERS_IDLE,
128*7c478bd9Sstevel@tonic-gate 				rusers_service, 0)) {
129*7c478bd9Sstevel@tonic-gate 	msgout("unable to register (RUSERSPROG, RUSERSVERS_IDLE).");
130*7c478bd9Sstevel@tonic-gate 			exit(1);
131*7c478bd9Sstevel@tonic-gate 		}
132*7c478bd9Sstevel@tonic-gate 		(void) signal(SIGALRM, closedown);
133*7c478bd9Sstevel@tonic-gate 		(void) alarm(_RPCSVC_CLOSEDOWN);
134*7c478bd9Sstevel@tonic-gate 		svc_run();
135*7c478bd9Sstevel@tonic-gate 		msgout("svc_run returned");
136*7c478bd9Sstevel@tonic-gate 		exit(1);
137*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
138*7c478bd9Sstevel@tonic-gate 	}
139*7c478bd9Sstevel@tonic-gate #ifndef RPC_SVC_FG
140*7c478bd9Sstevel@tonic-gate 	pid = fork();
141*7c478bd9Sstevel@tonic-gate 	if (pid < 0) {
142*7c478bd9Sstevel@tonic-gate 		perror("rpc.rusersd: cannot fork");
143*7c478bd9Sstevel@tonic-gate 		exit(1);
144*7c478bd9Sstevel@tonic-gate 	}
145*7c478bd9Sstevel@tonic-gate 	if (pid)
146*7c478bd9Sstevel@tonic-gate 		exit(0);
147*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 20; i++)
148*7c478bd9Sstevel@tonic-gate 		(void) close(i);
149*7c478bd9Sstevel@tonic-gate 	setsid();
150*7c478bd9Sstevel@tonic-gate 	openlog("rusers", LOG_PID, LOG_DAEMON);
151*7c478bd9Sstevel@tonic-gate #endif
152*7c478bd9Sstevel@tonic-gate 	if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_3, "netpath")) {
153*7c478bd9Sstevel@tonic-gate 	    msgout("unable to create (RUSERSPROG, RUSERSVERS_3) for netpath");
154*7c478bd9Sstevel@tonic-gate 		exit(1);
155*7c478bd9Sstevel@tonic-gate 	}
156*7c478bd9Sstevel@tonic-gate 	if (!svc_create(rusers_service, RUSERSPROG, RUSERSVERS_IDLE,
157*7c478bd9Sstevel@tonic-gate 			"netpath")) {
158*7c478bd9Sstevel@tonic-gate 	    msgout(
159*7c478bd9Sstevel@tonic-gate 		"unable to create (RUSERSPROG, RUSERSVERS_IDLE) for netpath");
160*7c478bd9Sstevel@tonic-gate 		exit(1);
161*7c478bd9Sstevel@tonic-gate 	}
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate 	svc_run();
164*7c478bd9Sstevel@tonic-gate 	msgout("svc_run returned");
165*7c478bd9Sstevel@tonic-gate 	exit(1);
166*7c478bd9Sstevel@tonic-gate 	/* NOTREACHED */
167*7c478bd9Sstevel@tonic-gate }
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate /*
171*7c478bd9Sstevel@tonic-gate  * This routine gets the user information.
172*7c478bd9Sstevel@tonic-gate  * "all" specifies whether all listings should be counted, or only those of
173*7c478bd9Sstevel@tonic-gate  *	type "USER_PROCESS".
174*7c478bd9Sstevel@tonic-gate  * "version" is either RUSERSVERS_IDLE or RUSERSVERS_3.  If anything else,
175*7c478bd9Sstevel@tonic-gate  *	just a count is returned.
176*7c478bd9Sstevel@tonic-gate  * "limit" specifies the maximum number of entries to be processed.
177*7c478bd9Sstevel@tonic-gate  *
178*7c478bd9Sstevel@tonic-gate  * For both versions, the results are placed into an external variable.
179*7c478bd9Sstevel@tonic-gate  * For RUSERSVERS_IDLE, this routine mallocs entries in a vector as it
180*7c478bd9Sstevel@tonic-gate  * processed each utmpx entry.  These malloc'd entries must be freed after the
181*7c478bd9Sstevel@tonic-gate  * results are returned.
182*7c478bd9Sstevel@tonic-gate  * For RUSERSVERS_3, this routine uses array entries that are malloc'd prior
183*7c478bd9Sstevel@tonic-gate  * to this routine being called. "limit" is the number of elements available.
184*7c478bd9Sstevel@tonic-gate  */
185*7c478bd9Sstevel@tonic-gate int
186*7c478bd9Sstevel@tonic-gate getutmpx_3(all, version, limit)
187*7c478bd9Sstevel@tonic-gate 	int all;		/* give all listings? */
188*7c478bd9Sstevel@tonic-gate 	int version;		/* version 2 or 3 */
189*7c478bd9Sstevel@tonic-gate 	int limit;		/* limits users returned, 0 means no limit */
190*7c478bd9Sstevel@tonic-gate {
191*7c478bd9Sstevel@tonic-gate 	struct utmpx *utent;
192*7c478bd9Sstevel@tonic-gate 	struct utmpidle **q = utmpidlearr.uia_arr;
193*7c478bd9Sstevel@tonic-gate 	int minidle;
194*7c478bd9Sstevel@tonic-gate 	int cnt = 0;
195*7c478bd9Sstevel@tonic-gate 	time_t now;
196*7c478bd9Sstevel@tonic-gate 	extern char *s_malodup();
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 	time(&now);		/* only one call to time() for this rpc call */
199*7c478bd9Sstevel@tonic-gate 	setutxent();		/* reset the utmpx file */
200*7c478bd9Sstevel@tonic-gate 	while ((utent = getutxent()) != NULL && (limit == 0 || cnt < limit)) {
201*7c478bd9Sstevel@tonic-gate 		if (utent->ut_line[0] == '\0' || utent->ut_user[0] == '\0')
202*7c478bd9Sstevel@tonic-gate 			continue;
203*7c478bd9Sstevel@tonic-gate 		/*
204*7c478bd9Sstevel@tonic-gate 		 * List only user processes.
205*7c478bd9Sstevel@tonic-gate 		 * XXX modified to exclude cmdtool style window entries.
206*7c478bd9Sstevel@tonic-gate 		 */
207*7c478bd9Sstevel@tonic-gate 		if ((all == REAL_USERS) && ((utent->ut_type != USER_PROCESS) ||
208*7c478bd9Sstevel@tonic-gate 		    nonuserx(*utent)))
209*7c478bd9Sstevel@tonic-gate 			continue;
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 		if (version == RUSERSVERS_IDLE) {
212*7c478bd9Sstevel@tonic-gate 			/*
213*7c478bd9Sstevel@tonic-gate 			 * need to free this; done after svc_sendreply.
214*7c478bd9Sstevel@tonic-gate 			 */
215*7c478bd9Sstevel@tonic-gate 			*q = (struct utmpidle *)
216*7c478bd9Sstevel@tonic-gate 				malloc(sizeof (struct utmpidle));
217*7c478bd9Sstevel@tonic-gate 			(*q)->ui_idle = findidle(utent->ut_line,
218*7c478bd9Sstevel@tonic-gate 						sizeof (utent->ut_line), now);
219*7c478bd9Sstevel@tonic-gate 			if (strncmp(utent->ut_line, "console",
220*7c478bd9Sstevel@tonic-gate 				strlen("console")) == 0) {
221*7c478bd9Sstevel@tonic-gate 				(*q)->ui_idle = min((*q)->ui_idle,
222*7c478bd9Sstevel@tonic-gate 					console_idle(now));
223*7c478bd9Sstevel@tonic-gate 			}
224*7c478bd9Sstevel@tonic-gate 			usys5to_ru(utent, &((*q)->ui_utmp));
225*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
226*7c478bd9Sstevel@tonic-gate 			printf("%-*s %-*s  %s; idle %d",
227*7c478bd9Sstevel@tonic-gate 			    sizeof (utent->ut_line),
228*7c478bd9Sstevel@tonic-gate 			    utent->ut_line,
229*7c478bd9Sstevel@tonic-gate 			    sizeof (utent->ut_name),
230*7c478bd9Sstevel@tonic-gate 			    utent->ut_name,
231*7c478bd9Sstevel@tonic-gate 			    ctime(&utent->ut_xtime),
232*7c478bd9Sstevel@tonic-gate 			    (*q)->ui_idle);
233*7c478bd9Sstevel@tonic-gate #endif
234*7c478bd9Sstevel@tonic-gate 			q++;
235*7c478bd9Sstevel@tonic-gate 		} else if (version == RUSERSVERS_3) {
236*7c478bd9Sstevel@tonic-gate #define	uav	utmp_array_res.utmp_array_val
237*7c478bd9Sstevel@tonic-gate 
238*7c478bd9Sstevel@tonic-gate 			uav[cnt].ut_host =
239*7c478bd9Sstevel@tonic-gate 				s_malodup(utent->ut_host, utent->ut_syslen);
240*7c478bd9Sstevel@tonic-gate 			uav[cnt].ut_user = s_malodup(utent->ut_user,
241*7c478bd9Sstevel@tonic-gate 				sizeof (utent->ut_user));
242*7c478bd9Sstevel@tonic-gate 			uav[cnt].ut_line = s_malodup(utent->ut_line,
243*7c478bd9Sstevel@tonic-gate 				sizeof (utent->ut_line));
244*7c478bd9Sstevel@tonic-gate 			uav[cnt].ut_type = utent->ut_type;
245*7c478bd9Sstevel@tonic-gate 			uav[cnt].ut_time = utent->ut_xtime;
246*7c478bd9Sstevel@tonic-gate 			uav[cnt].ut_idle = findidle(utent->ut_line,
247*7c478bd9Sstevel@tonic-gate 						sizeof (utent->ut_line), now);
248*7c478bd9Sstevel@tonic-gate 			if (strncmp(utent->ut_line, "console",
249*7c478bd9Sstevel@tonic-gate 				strlen("console")) == 0) {
250*7c478bd9Sstevel@tonic-gate 				uav[cnt].ut_idle =
251*7c478bd9Sstevel@tonic-gate 					min(uav[cnt].ut_idle,
252*7c478bd9Sstevel@tonic-gate 							console_idle(now));
253*7c478bd9Sstevel@tonic-gate 			}
254*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
255*7c478bd9Sstevel@tonic-gate 			printf("user: %-10s line: %-10s  %s; idle %d (%s)\n",
256*7c478bd9Sstevel@tonic-gate 					uav[cnt].ut_line, uav[cnt].ut_user,
257*7c478bd9Sstevel@tonic-gate 					ctime((time_t *)&uav[cnt].ut_time),
258*7c478bd9Sstevel@tonic-gate 					uav[cnt].ut_idle, uav[cnt].ut_host);
259*7c478bd9Sstevel@tonic-gate #endif
260*7c478bd9Sstevel@tonic-gate #undef	uav
261*7c478bd9Sstevel@tonic-gate 		}
262*7c478bd9Sstevel@tonic-gate 		cnt++;
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 	return (cnt);
265*7c478bd9Sstevel@tonic-gate }
266*7c478bd9Sstevel@tonic-gate 
267*7c478bd9Sstevel@tonic-gate /*
268*7c478bd9Sstevel@tonic-gate  * "string" is a character array with maximum size "size".  Return a
269*7c478bd9Sstevel@tonic-gate  * malloc'd string that's a duplicate of the string.
270*7c478bd9Sstevel@tonic-gate  */
271*7c478bd9Sstevel@tonic-gate char *
272*7c478bd9Sstevel@tonic-gate s_malodup(string, size)
273*7c478bd9Sstevel@tonic-gate char *string;
274*7c478bd9Sstevel@tonic-gate int size;
275*7c478bd9Sstevel@tonic-gate {
276*7c478bd9Sstevel@tonic-gate 	char *tmp;
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	tmp = (char *)malloc(size+1);
279*7c478bd9Sstevel@tonic-gate 	if (tmp == NULL) {
280*7c478bd9Sstevel@tonic-gate 		msgout("rpc.rusersd: malloc failed (2)");
281*7c478bd9Sstevel@tonic-gate 		return (NULL);
282*7c478bd9Sstevel@tonic-gate 	}
283*7c478bd9Sstevel@tonic-gate 	strncpy(tmp, string, size);
284*7c478bd9Sstevel@tonic-gate 	tmp[size] = '\0';
285*7c478bd9Sstevel@tonic-gate 	return (tmp);
286*7c478bd9Sstevel@tonic-gate }
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate int
290*7c478bd9Sstevel@tonic-gate console_idle(now)
291*7c478bd9Sstevel@tonic-gate 	time_t now;
292*7c478bd9Sstevel@tonic-gate {
293*7c478bd9Sstevel@tonic-gate 	/*
294*7c478bd9Sstevel@tonic-gate 	 * On the console, the user may be running a window system; if so,
295*7c478bd9Sstevel@tonic-gate 	 * their activity will show up in the last-access times of
296*7c478bd9Sstevel@tonic-gate 	 * "/dev/kbd" and "/dev/mouse", so take the minimum of the idle
297*7c478bd9Sstevel@tonic-gate 	 * times on those two devices and "/dev/console" and treat that as
298*7c478bd9Sstevel@tonic-gate 	 * the idle time.
299*7c478bd9Sstevel@tonic-gate 	 */
300*7c478bd9Sstevel@tonic-gate 	return (min((unsigned)findidle("kbd", strlen("kbd"), now),
301*7c478bd9Sstevel@tonic-gate 		(unsigned)findidle("mouse", strlen("mouse"), now)));
302*7c478bd9Sstevel@tonic-gate }
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate static void
305*7c478bd9Sstevel@tonic-gate rusers_service(rqstp, transp)
306*7c478bd9Sstevel@tonic-gate 	register struct svc_req *rqstp;
307*7c478bd9Sstevel@tonic-gate 	register SVCXPRT *transp;
308*7c478bd9Sstevel@tonic-gate {
309*7c478bd9Sstevel@tonic-gate 	int i;
310*7c478bd9Sstevel@tonic-gate 	int cnt;
311*7c478bd9Sstevel@tonic-gate 	char *replyerr = "rpc.rusersd: error replying to request";
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	_rpcsvcrecent = _rpcsvcdirty = 1;
314*7c478bd9Sstevel@tonic-gate 	switch (rqstp->rq_proc) {
315*7c478bd9Sstevel@tonic-gate 	case 0:
316*7c478bd9Sstevel@tonic-gate 		if (svc_sendreply(transp, xdr_void, 0) == FALSE) {
317*7c478bd9Sstevel@tonic-gate 			msgout(replyerr);
318*7c478bd9Sstevel@tonic-gate 		}
319*7c478bd9Sstevel@tonic-gate 		break;
320*7c478bd9Sstevel@tonic-gate 	case RUSERSPROC_NUM:
321*7c478bd9Sstevel@tonic-gate 		cnt = getutmpx_3(REAL_USERS, 0, 0);
322*7c478bd9Sstevel@tonic-gate 		if (!svc_sendreply(transp, xdr_u_long, (caddr_t)&cnt))
323*7c478bd9Sstevel@tonic-gate 			msgout(replyerr);
324*7c478bd9Sstevel@tonic-gate 		break;
325*7c478bd9Sstevel@tonic-gate 	case RUSERSPROC_NAMES:
326*7c478bd9Sstevel@tonic-gate 	case RUSERSPROC_ALLNAMES:
327*7c478bd9Sstevel@tonic-gate 		if (rqstp->rq_vers == RUSERSVERS_IDLE) {
328*7c478bd9Sstevel@tonic-gate 			utmpidlearr.uia_arr = (struct utmpidle **)
329*7c478bd9Sstevel@tonic-gate 				malloc(MAXUSERS*sizeof (struct utmpidle *));
330*7c478bd9Sstevel@tonic-gate 			utmpidlearr.uia_cnt = getutmpx_3(rqstp->rq_proc ==
331*7c478bd9Sstevel@tonic-gate 				RUSERSPROC_ALLNAMES,
332*7c478bd9Sstevel@tonic-gate 				RUSERSVERS_IDLE, MAXUSERS);
333*7c478bd9Sstevel@tonic-gate 			if (!svc_sendreply(transp, xdr_utmpidlearr,
334*7c478bd9Sstevel@tonic-gate 					(caddr_t)&utmpidlearr))
335*7c478bd9Sstevel@tonic-gate 				msgout(replyerr);
336*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < utmpidlearr.uia_cnt; i++) {
337*7c478bd9Sstevel@tonic-gate 				free(utmpidlearr.uia_arr[i]);
338*7c478bd9Sstevel@tonic-gate 			}
339*7c478bd9Sstevel@tonic-gate 			free(utmpidlearr.uia_arr);
340*7c478bd9Sstevel@tonic-gate 		} else if (rqstp->rq_vers == RUSERSVERS_3) {
341*7c478bd9Sstevel@tonic-gate 			int entries, alloc_array_len;
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 			/*
344*7c478bd9Sstevel@tonic-gate 			 * Always free strings from previous results array
345*7c478bd9Sstevel@tonic-gate 			 */
346*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < used_array_len; i++) {
347*7c478bd9Sstevel@tonic-gate 			free_ua_entry(&utmp_array_res.utmp_array_val[i]);
348*7c478bd9Sstevel@tonic-gate 			}
349*7c478bd9Sstevel@tonic-gate 			entries = (rqstp->rq_proc == RUSERSPROC_ALLNAMES);
350*7c478bd9Sstevel@tonic-gate 			cnt = getutmpx_3(entries, 0, 0);	/* get cnt */
351*7c478bd9Sstevel@tonic-gate 			if (cnt > utmp_array_res.utmp_array_len) {
352*7c478bd9Sstevel@tonic-gate 				free(utmp_array_res.utmp_array_val);
353*7c478bd9Sstevel@tonic-gate 				utmp_array_res.utmp_array_len = 0;
354*7c478bd9Sstevel@tonic-gate 				utmp_array_res.utmp_array_val = (rusers_utmp *)
355*7c478bd9Sstevel@tonic-gate 					malloc(cnt * sizeof (rusers_utmp));
356*7c478bd9Sstevel@tonic-gate 				if (utmp_array_res.utmp_array_val == NULL) {
357*7c478bd9Sstevel@tonic-gate 				    msgout("rpc.rusersd: malloc failed (1)");
358*7c478bd9Sstevel@tonic-gate 				    break;
359*7c478bd9Sstevel@tonic-gate 				}
360*7c478bd9Sstevel@tonic-gate 				alloc_array_len = cnt;
361*7c478bd9Sstevel@tonic-gate 			} else {
362*7c478bd9Sstevel@tonic-gate 				alloc_array_len = utmp_array_res.utmp_array_len;
363*7c478bd9Sstevel@tonic-gate 			}
364*7c478bd9Sstevel@tonic-gate 			cnt = getutmpx_3(entries, RUSERSVERS_3, cnt);
365*7c478bd9Sstevel@tonic-gate 			utmp_array_res.utmp_array_len = used_array_len = cnt;
366*7c478bd9Sstevel@tonic-gate 			if (!svc_sendreply(transp, xdr_utmp_array,
367*7c478bd9Sstevel@tonic-gate 					(caddr_t)&utmp_array_res))
368*7c478bd9Sstevel@tonic-gate 				msgout(replyerr);
369*7c478bd9Sstevel@tonic-gate 			utmp_array_res.utmp_array_len = alloc_array_len;
370*7c478bd9Sstevel@tonic-gate 		}
371*7c478bd9Sstevel@tonic-gate 		break;
372*7c478bd9Sstevel@tonic-gate 	default:
373*7c478bd9Sstevel@tonic-gate 		svcerr_noproc(transp);
374*7c478bd9Sstevel@tonic-gate 		break;
375*7c478bd9Sstevel@tonic-gate 	}
376*7c478bd9Sstevel@tonic-gate 	_rpcsvcdirty = 0;
377*7c478bd9Sstevel@tonic-gate 
378*7c478bd9Sstevel@tonic-gate }
379*7c478bd9Sstevel@tonic-gate 
380*7c478bd9Sstevel@tonic-gate free_ua_entry(uap)
381*7c478bd9Sstevel@tonic-gate rusers_utmp *uap;
382*7c478bd9Sstevel@tonic-gate {
383*7c478bd9Sstevel@tonic-gate 	if (uap == NULL)
384*7c478bd9Sstevel@tonic-gate 		return;
385*7c478bd9Sstevel@tonic-gate 	if (uap->ut_user)
386*7c478bd9Sstevel@tonic-gate 		free(uap->ut_user);
387*7c478bd9Sstevel@tonic-gate 	if (uap->ut_line)
388*7c478bd9Sstevel@tonic-gate 		free(uap->ut_line);
389*7c478bd9Sstevel@tonic-gate 	if (uap->ut_host)
390*7c478bd9Sstevel@tonic-gate 		free(uap->ut_host);
391*7c478bd9Sstevel@tonic-gate }
392*7c478bd9Sstevel@tonic-gate 
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate /* find & return number of minutes current tty has been idle */
396*7c478bd9Sstevel@tonic-gate findidle(name, ln, now)
397*7c478bd9Sstevel@tonic-gate 	char *name;
398*7c478bd9Sstevel@tonic-gate 	int ln;
399*7c478bd9Sstevel@tonic-gate 	time_t	now;
400*7c478bd9Sstevel@tonic-gate {
401*7c478bd9Sstevel@tonic-gate 	struct stat stbuf;
402*7c478bd9Sstevel@tonic-gate 	long lastaction, diff;
403*7c478bd9Sstevel@tonic-gate 	char ttyname[32];
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 	strcpy(ttyname, "/dev/");
406*7c478bd9Sstevel@tonic-gate 	strncat(ttyname, name, ln);
407*7c478bd9Sstevel@tonic-gate 	if (stat(ttyname, &stbuf) < 0)
408*7c478bd9Sstevel@tonic-gate 		return (INT_MAX);
409*7c478bd9Sstevel@tonic-gate 	lastaction = stbuf.st_atime;
410*7c478bd9Sstevel@tonic-gate 	diff = now - lastaction;
411*7c478bd9Sstevel@tonic-gate 	diff = DIV60(diff);
412*7c478bd9Sstevel@tonic-gate 	if (diff < 0) diff = 0;
413*7c478bd9Sstevel@tonic-gate 	return (diff);
414*7c478bd9Sstevel@tonic-gate }
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate static
417*7c478bd9Sstevel@tonic-gate usys5to_ru(s5, bss)
418*7c478bd9Sstevel@tonic-gate 	struct utmpx *s5;
419*7c478bd9Sstevel@tonic-gate 	struct ru_utmp *bss;
420*7c478bd9Sstevel@tonic-gate {
421*7c478bd9Sstevel@tonic-gate 	int i;
422*7c478bd9Sstevel@tonic-gate 
423*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
424*7c478bd9Sstevel@tonic-gate 	printf("sizeof (bss->ut_host) == %d\n", sizeof (bss->ut_host));
425*7c478bd9Sstevel@tonic-gate #endif
426*7c478bd9Sstevel@tonic-gate 	strncpy(bss->ut_name, s5->ut_name, sizeof (bss->ut_name));
427*7c478bd9Sstevel@tonic-gate 	strncpy(bss->ut_line, s5->ut_line, sizeof (bss->ut_line));
428*7c478bd9Sstevel@tonic-gate 	strncpy(bss->ut_host, s5->ut_host, sizeof (bss->ut_host));
429*7c478bd9Sstevel@tonic-gate 	bss->ut_time = s5->ut_xtime;
430*7c478bd9Sstevel@tonic-gate }
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate static void
433*7c478bd9Sstevel@tonic-gate msgout(msg)
434*7c478bd9Sstevel@tonic-gate 	char *msg;
435*7c478bd9Sstevel@tonic-gate {
436*7c478bd9Sstevel@tonic-gate #ifdef RPC_SVC_FG
437*7c478bd9Sstevel@tonic-gate 	if (_rpcpmstart)
438*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, msg);
439*7c478bd9Sstevel@tonic-gate 	else
440*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s\n", msg);
441*7c478bd9Sstevel@tonic-gate #else
442*7c478bd9Sstevel@tonic-gate 	syslog(LOG_ERR, msg);
443*7c478bd9Sstevel@tonic-gate #endif
444*7c478bd9Sstevel@tonic-gate }
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate static void
447*7c478bd9Sstevel@tonic-gate closedown(sig)
448*7c478bd9Sstevel@tonic-gate int sig;
449*7c478bd9Sstevel@tonic-gate {
450*7c478bd9Sstevel@tonic-gate 	if (_rpcsvcrecent) {
451*7c478bd9Sstevel@tonic-gate 		_rpcsvcrecent = 0;
452*7c478bd9Sstevel@tonic-gate 	} else {
453*7c478bd9Sstevel@tonic-gate 		if (_rpcsvcdirty == 0) {
454*7c478bd9Sstevel@tonic-gate 			int i, openfd;
455*7c478bd9Sstevel@tonic-gate 			struct t_info tinfo;
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 			if (t_getinfo(0, &tinfo) || (tinfo.servtype == T_CLTS))
458*7c478bd9Sstevel@tonic-gate 				exit(0);
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate 			for (i = 0, openfd = 0;
461*7c478bd9Sstevel@tonic-gate 					i < svc_max_pollfd && openfd < 2;
462*7c478bd9Sstevel@tonic-gate 					i++) {
463*7c478bd9Sstevel@tonic-gate 				if (svc_pollfd[i].fd >= 0)
464*7c478bd9Sstevel@tonic-gate 					openfd++;
465*7c478bd9Sstevel@tonic-gate 			}
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 			if (openfd <= 1)
468*7c478bd9Sstevel@tonic-gate 				exit(0);
469*7c478bd9Sstevel@tonic-gate 		}
470*7c478bd9Sstevel@tonic-gate 	}
471*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGALRM, closedown);
472*7c478bd9Sstevel@tonic-gate 	(void) alarm(_RPCSVC_CLOSEDOWN);
473*7c478bd9Sstevel@tonic-gate }
474*7c478bd9Sstevel@tonic-gate 
475*7c478bd9Sstevel@tonic-gate unsigned
476*7c478bd9Sstevel@tonic-gate min(a, b)
477*7c478bd9Sstevel@tonic-gate unsigned a;
478*7c478bd9Sstevel@tonic-gate unsigned b;
479*7c478bd9Sstevel@tonic-gate {
480*7c478bd9Sstevel@tonic-gate 	if (a < b)
481*7c478bd9Sstevel@tonic-gate 		return (a);
482*7c478bd9Sstevel@tonic-gate 	else
483*7c478bd9Sstevel@tonic-gate 		return (b);
484*7c478bd9Sstevel@tonic-gate }
485