This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / libexec / rpc.rusersd / rusers_proc.c
CommitLineData
69582008
C
1/*-
2 * Copyright (c) 1993, John Brezak
3 * 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 the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
79a14d86 35static char rcsid[] = "$Id: rusers_proc.c,v 1.1 1993/09/16 00:34:46 jtc Exp $";
69582008
C
36#endif /* not lint */
37
38#include <signal.h>
39#include <sys/types.h>
40#include <sys/time.h>
41#include <utmp.h>
42#include <stdio.h>
43#include <syslog.h>
44#include <rpc/rpc.h>
45#include <sys/socket.h>
46#include <sys/param.h>
47#include <sys/stat.h>
48#ifdef XIDLE
49#include <setjmp.h>
50#include <X11/Xlib.h>
51#include <X11/extensions/xidle.h>
52#endif
53#define utmp rutmp
54#include <rpcsvc/rnusers.h>
55#undef utmp
56
57#define IGNOREUSER "sleeper"
58
59#ifdef OSF
60#define _PATH_UTMP UTMP_FILE
61#endif
62
63#ifndef _PATH_UTMP
64#define _PATH_UTMP "/etc/utmp"
65#endif
66
67#ifndef _PATH_DEV
68#define _PATH_DEV "/dev"
69#endif
70
71#ifndef UT_LINESIZE
72#define UT_LINESIZE sizeof(((struct utmp *)0)->ut_line)
73#endif
74#ifndef UT_NAMESIZE
75#define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name)
76#endif
77#ifndef UT_HOSTSIZE
78#define UT_HOSTSIZE sizeof(((struct utmp *)0)->ut_host)
79#endif
80
79a14d86
JH
81typedef char ut_line_t[UT_LINESIZE+1];
82typedef char ut_name_t[UT_NAMESIZE+1];
83typedef char ut_host_t[UT_HOSTSIZE+1];
69582008
C
84
85utmpidle utmp_idle[MAXUSERS];
86rutmp old_utmp[MAXUSERS];
87ut_line_t line[MAXUSERS];
88ut_name_t name[MAXUSERS];
89ut_host_t host[MAXUSERS];
90
91extern int from_inetd;
92
93FILE *ufp;
94
95#ifdef XIDLE
96Display *dpy;
97
98static jmp_buf openAbort;
99
100static void
101abortOpen ()
102{
103 longjmp (openAbort, 1);
104}
105
106XqueryIdle(char *display)
107{
108 int first_event, first_error;
109 Time IdleTime;
110
111 (void) signal (SIGALRM, abortOpen);
112 (void) alarm ((unsigned) 10);
113 if (!setjmp (openAbort)) {
114 if (!(dpy= XOpenDisplay(display))) {
115 syslog(LOG_ERR, "Cannot open display %s", display);
116 return(-1);
117 }
118 if (XidleQueryExtension(dpy, &first_event, &first_error)) {
119 if (!XGetIdleTime(dpy, &IdleTime)) {
120 syslog(LOG_ERR, "%s: Unable to get idle time.", display);
121 return(-1);
122 }
123 }
124 else {
125 syslog(LOG_ERR, "%s: Xidle extension not loaded.", display);
126 return(-1);
127 }
128 XCloseDisplay(dpy);
129 }
130 else {
131 syslog(LOG_ERR, "%s: Server grabbed for over 10 seconds.", display);
132 return(-1);
133 }
134 (void) signal (SIGALRM, SIG_DFL);
135 (void) alarm ((unsigned) 0);
136
137 IdleTime /= 1000;
138 return((IdleTime + 30) / 60);
139}
140#endif
141
142static u_int
143getidle(char *tty, char *display)
144{
145 struct stat st;
146 char devname[PATH_MAX];
147 time_t now;
148 u_long idle;
149
150 /*
151 * If this is an X terminal or console, then try the
152 * XIdle extension
153 */
154#ifdef XIDLE
155 if (display && *display && (idle = XqueryIdle(display)) >= 0)
156 return(idle);
157#endif
158 idle = 0;
159 if (*tty == 'X') {
160 u_long kbd_idle, mouse_idle;
161#if !defined(__386BSD__)
162 kbd_idle = getidle("kbd", NULL);
163#else
164 kbd_idle = getidle("vga", NULL);
165#endif
166 mouse_idle = getidle("mouse", NULL);
167 idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle;
168 }
169 else {
170 sprintf(devname, "%s/%s", _PATH_DEV, tty);
171 if (stat(devname, &st) < 0) {
172#ifdef DEBUG
173 printf("%s: %s\n", devname, strerror(errno));
174#endif
175 return(-1);
176 }
177 time(&now);
178#ifdef DEBUG
179 printf("%s: now=%d atime=%d\n", devname, now,
180 st.st_atime);
181#endif
182 idle = now - st.st_atime;
183 idle = (idle + 30) / 60; /* secs->mins */
184 }
185 if (idle < 0) idle = 0;
186
187 return(idle);
188}
189
190static utmpidlearr *
191do_names_2(int all)
192{
193 static utmpidlearr ut;
194 struct utmp usr;
195 int nusers = 0;
196
197 bzero((char *)&ut, sizeof(ut));
198 ut.utmpidlearr_val = &utmp_idle[0];
199
200 ufp = fopen(_PATH_UTMP, "r");
201 if (!ufp) {
202 syslog(LOG_ERR, "%m");
203 return(&ut);
204 }
205
206 /* only entries with both name and line fields */
207 while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1 &&
208 nusers < MAXUSERS)
209 if (*usr.ut_name && *usr.ut_line &&
210 strncmp(usr.ut_name, IGNOREUSER,
211 sizeof(usr.ut_name))
212#ifdef OSF
213 && usr.ut_type == USER_PROCESS
214#endif
215 ) {
216 utmp_idle[nusers].ui_utmp.ut_time =
217 usr.ut_time;
218 utmp_idle[nusers].ui_idle =
219 getidle(usr.ut_line, usr.ut_host);
220 utmp_idle[nusers].ui_utmp.ut_line = line[nusers];
79a14d86 221 strncpy(line[nusers], usr.ut_line, UT_LINESIZE);
69582008 222 utmp_idle[nusers].ui_utmp.ut_name = name[nusers];
79a14d86 223 strncpy(name[nusers], usr.ut_name, UT_NAMESIZE);
69582008 224 utmp_idle[nusers].ui_utmp.ut_host = host[nusers];
79a14d86
JH
225 strncpy(host[nusers], usr.ut_host, UT_HOSTSIZE);
226
227 /* Make sure entries are NUL terminated */
228 line[nusers][UT_LINESIZE] =
229 name[nusers][UT_NAMESIZE] =
230 host[nusers][UT_HOSTSIZE] = '\0';
69582008
C
231 nusers++;
232 }
233
234 ut.utmpidlearr_len = nusers;
235 fclose(ufp);
236 return(&ut);
237}
238
239int *
240rusers_num()
241{
242 int num_users = 0;
243 struct utmp usr;
244
245 ufp = fopen(_PATH_UTMP, "r");
246 if (!ufp) {
247 syslog(LOG_ERR, "%m");
248 return(0);
249 }
250
251 /* only entries with both name and line fields */
252 while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
253 if (*usr.ut_name && *usr.ut_line &&
254 strncmp(usr.ut_name, IGNOREUSER,
255 sizeof(usr.ut_name))
256#ifdef OSF
257 && usr.ut_type == USER_PROCESS
258#endif
259 ) {
260 num_users++;
261 }
262
263 fclose(ufp);
264 return(&num_users);
265}
266
267static utmparr *
268do_names_1(int all)
269{
270 utmpidlearr *utidle;
271 utmparr ut;
272 int i;
273
274 bzero((char *)&ut, sizeof(ut));
275
276 utidle = do_names_2(all);
277 if (utidle) {
278 ut.utmparr_len = utidle->utmpidlearr_len;
279 ut.utmparr_val = &old_utmp[0];
280 for (i = 0; i < ut.utmparr_len; i++)
281 bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i],
282 sizeof(old_utmp[0]));
283
284 }
285
286 return(&ut);
287}
288
289utmpidlearr *
290rusersproc_names_2()
291{
292 return(do_names_2(0));
293}
294
295utmpidlearr *
296rusersproc_allnames_2()
297{
298 return(do_names_2(1));
299}
300
301utmparr *
302rusersproc_names_1()
303{
304 return(do_names_1(0));
305}
306
307utmparr *
308rusersproc_allnames_1()
309{
310 return(do_names_1(1));
311}
312
313void
314rusers_service(rqstp, transp)
315 struct svc_req *rqstp;
316 SVCXPRT *transp;
317{
318 union {
319 int fill;
320 } argument;
321 char *result;
322 bool_t (*xdr_argument)(), (*xdr_result)();
323 char *(*local)();
324
325 switch (rqstp->rq_proc) {
326 case NULLPROC:
327 (void)svc_sendreply(transp, xdr_void, (char *)NULL);
328 goto leave;
329
330 case RUSERSPROC_NUM:
331 xdr_argument = xdr_void;
332 xdr_result = xdr_int;
333 local = (char *(*)()) rusers_num;
334 break;
335
336 case RUSERSPROC_NAMES:
337 xdr_argument = xdr_void;
338 xdr_result = xdr_utmpidlearr;
339 switch (rqstp->rq_vers) {
340 case RUSERSVERS_ORIG:
341 local = (char *(*)()) rusersproc_names_1;
342 break;
343 case RUSERSVERS_IDLE:
344 local = (char *(*)()) rusersproc_names_2;
345 break;
346 default:
347 svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
348 goto leave;
349 /*NOTREACHED*/
350 }
351 break;
352
353 case RUSERSPROC_ALLNAMES:
354 xdr_argument = xdr_void;
355 xdr_result = xdr_utmpidlearr;
356 switch (rqstp->rq_vers) {
357 case RUSERSVERS_ORIG:
358 local = (char *(*)()) rusersproc_allnames_1;
359 break;
360 case RUSERSVERS_IDLE:
361 local = (char *(*)()) rusersproc_allnames_2;
362 break;
363 default:
364 svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
365 goto leave;
366 /*NOTREACHED*/
367 }
368 break;
369
370 default:
371 svcerr_noproc(transp);
372 goto leave;
373 }
374 bzero((char *)&argument, sizeof(argument));
375 if (!svc_getargs(transp, xdr_argument, &argument)) {
376 svcerr_decode(transp);
377 goto leave;
378 }
379 result = (*local)(&argument, rqstp);
380 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
381 svcerr_systemerr(transp);
382 }
383 if (!svc_freeargs(transp, xdr_argument, &argument)) {
384 (void)fprintf(stderr, "unable to free arguments\n");
385 exit(1);
386 }
387leave:
388 if (from_inetd)
389 exit(0);
390}