2 * Copyright (c) 1993, John Brezak
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
35 static const char rcsid[] =
36 "$FreeBSD: src/libexec/rpc.rusersd/rusers_proc.c,v 1.10 1999/08/28 00:09:56 peter Exp $";
44 #include <sys/param.h>
51 #include <X11/extensions/xidle.h>
54 #include <rpcsvc/rnusers.h>
57 #define IGNOREUSER "sleeper"
60 #define _PATH_UTMP UTMP_FILE
64 #define _PATH_UTMP "/etc/utmp"
68 #define _PATH_DEV "/dev"
72 #define UT_LINESIZE sizeof(((struct utmp *)0)->ut_line)
75 #define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name)
78 #define UT_HOSTSIZE sizeof(((struct utmp *)0)->ut_host)
81 typedef char ut_line_t[UT_LINESIZE+1];
82 typedef char ut_name_t[UT_NAMESIZE+1];
83 typedef char ut_host_t[UT_HOSTSIZE+1];
85 utmpidle utmp_idle[MAXUSERS];
86 rutmp old_utmp[MAXUSERS];
87 ut_line_t line[MAXUSERS];
88 ut_name_t name[MAXUSERS];
89 ut_host_t host[MAXUSERS];
91 extern int from_inetd;
98 static jmp_buf openAbort;
103 longjmp (openAbort, 1);
106 XqueryIdle(char *display)
108 int first_event, first_error;
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);
118 if (XidleQueryExtension(dpy, &first_event, &first_error)) {
119 if (!XGetIdleTime(dpy, &IdleTime)) {
120 syslog(LOG_ERR, "%s: unable to get idle time", display);
125 syslog(LOG_ERR, "%s: Xidle extension not loaded", display);
131 syslog(LOG_ERR, "%s: server grabbed for over 10 seconds", display);
134 (void) signal (SIGALRM, SIG_DFL);
135 (void) alarm ((unsigned) 0);
138 return((IdleTime + 30) / 60);
143 getidle(char *tty, char *display)
146 char devname[PATH_MAX];
151 * If this is an X terminal or console, then try the
155 if (display && *display && (idle = XqueryIdle(display)) >= 0)
160 u_long kbd_idle, mouse_idle;
161 #if !defined(__FreeBSD__)
162 kbd_idle = getidle("kbd", NULL);
164 kbd_idle = getidle("vga", NULL);
166 mouse_idle = getidle("mouse", NULL);
167 idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle;
170 sprintf(devname, "%s/%s", _PATH_DEV, tty);
171 if (stat(devname, &st) < 0) {
173 printf("%s: %s\n", devname, strerror(errno));
179 printf("%s: now=%d atime=%d\n", devname, now,
182 idle = now - st.st_atime;
183 idle = (idle + 30) / 60; /* secs->mins */
185 if (idle < 0) idle = 0;
193 static utmpidlearr ut;
197 bzero((char *)&ut, sizeof(ut));
198 ut.utmpidlearr_val = &utmp_idle[0];
200 ufp = fopen(_PATH_UTMP, "r");
202 syslog(LOG_ERR, "%m");
206 /* only entries with both name and line fields */
207 while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1 &&
209 if (*usr.ut_name && *usr.ut_line &&
210 strncmp(usr.ut_name, IGNOREUSER,
213 && usr.ut_type == USER_PROCESS
216 utmp_idle[nusers].ui_utmp.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];
221 strncpy(line[nusers], usr.ut_line, UT_LINESIZE);
222 utmp_idle[nusers].ui_utmp.ut_name = name[nusers];
223 strncpy(name[nusers], usr.ut_name, UT_NAMESIZE);
224 utmp_idle[nusers].ui_utmp.ut_host = host[nusers];
225 strncpy(host[nusers], usr.ut_host, UT_HOSTSIZE);
227 /* Make sure entries are NUL terminated */
228 line[nusers][UT_LINESIZE] =
229 name[nusers][UT_NAMESIZE] =
230 host[nusers][UT_HOSTSIZE] = '\0';
234 ut.utmpidlearr_len = nusers;
242 static int num_users = 0;
245 ufp = fopen(_PATH_UTMP, "r");
247 syslog(LOG_ERR, "%m");
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,
257 && usr.ut_type == USER_PROCESS
274 bzero((char *)&ut, sizeof(ut));
276 utidle = do_names_2(all);
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]));
290 rusersproc_names_2_svc(argp, rqstp)
292 struct svc_req *rqstp;
294 return(do_names_2(0));
298 rusersproc_allnames_2_svc(argp, rqstp)
300 struct svc_req *rqstp;
302 return(do_names_2(1));
306 rusersproc_names_1_svc(argp, rqstp)
308 struct svc_req *rqstp;
310 return(do_names_1(0));
314 rusersproc_allnames_1_svc(argp, rqstp)
316 struct svc_req *rqstp;
318 return(do_names_1(1));
322 rusers_service(rqstp, transp)
323 struct svc_req *rqstp;
330 bool_t (*xdr_argument)(), (*xdr_result)();
333 switch (rqstp->rq_proc) {
335 (void)svc_sendreply(transp, xdr_void, (char *)NULL);
339 xdr_argument = xdr_void;
340 xdr_result = xdr_int;
341 local = (char *(*)()) rusers_num;
344 case RUSERSPROC_NAMES:
345 xdr_argument = xdr_void;
346 xdr_result = xdr_utmpidlearr;
347 switch (rqstp->rq_vers) {
348 case RUSERSVERS_ORIG:
349 local = (char *(*)()) rusersproc_names_1_svc;
351 case RUSERSVERS_IDLE:
352 local = (char *(*)()) rusersproc_names_2_svc;
355 svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
361 case RUSERSPROC_ALLNAMES:
362 xdr_argument = xdr_void;
363 xdr_result = xdr_utmpidlearr;
364 switch (rqstp->rq_vers) {
365 case RUSERSVERS_ORIG:
366 local = (char *(*)()) rusersproc_allnames_1_svc;
368 case RUSERSVERS_IDLE:
369 local = (char *(*)()) rusersproc_allnames_2_svc;
372 svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
379 svcerr_noproc(transp);
382 bzero((char *)&argument, sizeof(argument));
383 if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
384 svcerr_decode(transp);
387 result = (*local)(&argument, rqstp);
388 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
389 svcerr_systemerr(transp);
391 if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) {
392 syslog(LOG_ERR, "unable to free arguments");