1 /* $NetBSD: rusers_proc.c,v 1.25 2005/08/01 21:08:34 christos Exp $ */
4 * Copyright (c) 1993 John Brezak
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: rusers_proc.c,v 1.25 2005/08/01 21:08:34 christos Exp $");
36 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <sys/param.h>
53 #include "rusers_proc.h"
54 #include "utmpentry.h"
59 #include <X11/extensions/xidle.h>
62 #include <rpcsvc/rusers.h> /* New version */
63 static size_t maxusers3
= 0;
64 static struct rusers_utmp
*utmps
;
66 #include <rpcsvc/rnusers.h> /* Old version */
67 static size_t maxusers2
= 0;
68 static struct utmpidle
**utmp_idlep
;
69 static struct utmpidle
*utmp_idle
;
71 typedef char *(*rusersproc
)(void *, struct svc_req
*);
74 #define _PATH_DEV "/dev"
78 extern int from_inetd
;
80 static int getarrays2(int);
81 static int getarrays3(int);
82 static int getidle(const char *, char *);
83 static int *rusers_num_svc(void *, struct svc_req
*);
84 static utmp_array
*do_names_3(int);
85 static struct utmpidlearr
*do_names_2(int);
88 struct utmpidlearr
*rusersproc_names_2_svc(void *, struct svc_req
*);
89 struct utmpidlearr
*rusersproc_allnames_2_svc(void *, struct svc_req
*);
94 static sigjmp_buf openAbort
;
96 static int XqueryIdle(char *);
97 static void abortOpen(int);
102 siglongjmp(openAbort
, 1);
106 XqueryIdle(char *display
)
108 int first_event
, first_error
;
111 (void)signal(SIGALRM
, abortOpen
);
113 if (!sigsetjmp(openAbort
, 0)) {
114 if ((dpy
= XOpenDisplay(display
)) == NULL
) {
115 syslog(LOG_DEBUG
, "cannot open display %s", display
);
118 if (XidleQueryExtension(dpy
, &first_event
, &first_error
)) {
119 if (!XGetIdleTime(dpy
, &IdleTime
)) {
121 "%s: unable to get idle time", display
);
125 syslog(LOG_DEBUG
, "%s: Xidle extension not loaded",
131 syslog(LOG_DEBUG
, "%s: server grabbed for over 10 seconds",
136 (void)signal(SIGALRM
, SIG_DFL
);
139 return (IdleTime
+ 30) / 60;
146 struct utmpidle
**nutmp_idlep
;
147 struct utmpidle
*nutmp_idle
;
149 /* Limit to MAXUSERS for version 2 */
153 if (maxusers2
== 0) {
154 nutmp_idlep
= malloc(sizeof(*nutmp_idlep
) * ne
);
155 nutmp_idle
= malloc(sizeof(*nutmp_idle
) * ne
);
157 nutmp_idlep
= realloc(utmp_idlep
, sizeof(*nutmp_idlep
) * ne
);
158 nutmp_idle
= realloc(utmp_idle
, sizeof(*nutmp_idle
) * ne
);
161 if (nutmp_idlep
== NULL
|| nutmp_idle
== NULL
) {
162 syslog(LOG_WARNING
, "Cannot allocate data for %u users (%m)",
169 utmp_idlep
= nutmp_idlep
;
170 utmp_idle
= nutmp_idle
;
171 return maxusers2
= ne
;
177 struct rusers_utmp
*nutmps
;
179 if (maxusers3
== 0) {
180 nutmps
= malloc(sizeof(*nutmps
) * ne
);
182 nutmps
= realloc(utmps
, sizeof(*nutmps
) * ne
);
185 if (nutmps
== NULL
) {
186 syslog(LOG_WARNING
, "Cannot allocate data for %u users (%m)",
192 return maxusers3
= ne
;
197 getidle(const char *tty
, char *display
)
200 char dev_name
[PATH_MAX
];
205 * If this is an X terminal or console, then try the
209 if (display
&& *display
&& strchr(display
, ':') != NULL
&&
210 (idle
= XqueryIdle(display
)) >= 0)
215 long kbd_idle
, mouse_idle
;
217 kbd_idle
= getidle("kbd", NULL
);
220 * XXX Icky i386 console hack.
222 kbd_idle
= getidle("vga", NULL
);
224 mouse_idle
= getidle("mouse", NULL
);
225 idle
= (kbd_idle
< mouse_idle
) ? kbd_idle
: mouse_idle
;
227 snprintf(dev_name
, sizeof dev_name
, "%s/%s", _PATH_DEV
, tty
);
228 if (stat(dev_name
, &st
) == -1) {
229 syslog(LOG_WARNING
, "Cannot stat %s (%m)", dev_name
);
234 printf("%s: now=%ld atime=%ld\n", dev_name
,
235 (long)now
, (long)st
.st_atime
);
237 idle
= now
- st
.st_atime
;
238 idle
= (idle
+ 30) / 60; /* secs->mins */
246 static struct utmpentry
*ue
= NULL
;
247 static int nusers
= 0;
251 rusers_num_svc(void *arg
, struct svc_req
*rqstp
)
253 nusers
= getutentries(NULL
, &ue
);
260 static utmp_array ut
;
265 nusers
= getutentries(NULL
, &ue
);
266 nusers
= getarrays3(nusers
);
268 (void)memset(&ut
, 0, sizeof(ut
));
269 ut
.utmp_array_val
= utmps
;
271 for (nu
= 0, e
= ue
; e
!= NULL
&& nu
< (size_t)nusers
; e
= e
->next
) {
272 if ((idle
= getidle(e
->line
, e
->host
)) > 0 && !all
)
274 utmps
[nu
].ut_type
= RUSERS_USER_PROCESS
;
275 utmps
[nu
].ut_time
= e
->tv
.tv_sec
;
276 utmps
[nu
].ut_idle
= idle
;
277 utmps
[nu
].ut_line
= e
->line
;
278 utmps
[nu
].ut_user
= e
->name
;
279 utmps
[nu
].ut_host
= e
->host
;
283 ut
.utmp_array_len
= nu
;
290 rusersproc_names_3_svc(void *arg
, struct svc_req
*rqstp
)
293 return do_names_3(0);
298 rusersproc_allnames_3_svc(void *arg
, struct svc_req
*rqstp
)
301 return do_names_3(1);
304 static struct utmpidlearr
*
307 static struct utmpidlearr ut
;
312 nusers
= getutentries(NULL
, &ue
);
313 nusers
= getarrays2(nusers
);
314 (void)memset(&ut
, 0, sizeof(ut
));
315 ut
.uia_arr
= utmp_idlep
;
318 for (nu
= 0, e
= ue
; e
!= NULL
&& nu
< (size_t)nusers
; e
= e
->next
) {
319 if ((idle
= getidle(e
->line
, e
->host
)) > 0 && !all
)
321 utmp_idlep
[nu
] = &utmp_idle
[nu
];
322 utmp_idle
[nu
].ui_utmp
.ut_time
= e
->tv
.tv_sec
;
323 utmp_idle
[nu
].ui_idle
= idle
;
324 (void)strncpy(utmp_idle
[nu
].ui_utmp
.ut_line
, e
->line
,
325 sizeof(utmp_idle
[nu
].ui_utmp
.ut_line
));
326 (void)strncpy(utmp_idle
[nu
].ui_utmp
.ut_name
, e
->name
,
327 sizeof(utmp_idle
[nu
].ui_utmp
.ut_name
));
328 (void)strncpy(utmp_idle
[nu
].ui_utmp
.ut_host
, e
->host
,
329 sizeof(utmp_idle
[nu
].ui_utmp
.ut_host
));
339 rusersproc_names_2_svc(void *arg
, struct svc_req
*rqstp
)
341 return do_names_2(0);
346 rusersproc_allnames_2_svc(void *arg
, struct svc_req
*rqstp
)
348 return do_names_2(1);
352 rusers_service(struct svc_req
*rqstp
, SVCXPRT
*transp
)
358 xdrproc_t xdr_argument
, xdr_result
;
361 switch (rqstp
->rq_proc
) {
363 (void)svc_sendreply(transp
, xdr_void
, NULL
);
367 xdr_argument
= (xdrproc_t
)xdr_void
;
368 xdr_result
= (xdrproc_t
)xdr_int
;
369 switch (rqstp
->rq_vers
) {
371 case RUSERSVERS_IDLE
:
372 local
= (char *(*)(void *, struct svc_req
*))
376 svcerr_progvers(transp
, RUSERSVERS_IDLE
, RUSERSVERS_3
);
382 case RUSERSPROC_NAMES
:
383 xdr_argument
= (xdrproc_t
)xdr_void
;
384 xdr_result
= (xdrproc_t
)xdr_utmp_array
;
385 switch (rqstp
->rq_vers
) {
387 local
= (rusersproc
)rusersproc_names_3_svc
;
390 case RUSERSVERS_IDLE
:
391 xdr_result
= (xdrproc_t
)xdr_utmpidlearr
;
392 local
= (rusersproc
)rusersproc_names_2_svc
;
396 svcerr_progvers(transp
, RUSERSVERS_IDLE
, RUSERSVERS_3
);
402 case RUSERSPROC_ALLNAMES
:
403 xdr_argument
= (xdrproc_t
)xdr_void
;
404 xdr_result
= (xdrproc_t
)xdr_utmp_array
;
405 switch (rqstp
->rq_vers
) {
407 local
= (rusersproc
)rusersproc_allnames_3_svc
;
410 case RUSERSVERS_IDLE
:
411 xdr_result
= (xdrproc_t
)xdr_utmpidlearr
;
412 local
= (rusersproc
)rusersproc_allnames_2_svc
;
416 svcerr_progvers(transp
, RUSERSVERS_IDLE
, RUSERSVERS_3
);
423 svcerr_noproc(transp
);
426 (void)memset(&argument
, 0, sizeof(argument
));
427 if (!svc_getargs(transp
, xdr_argument
, (caddr_t
)(void *)&argument
)) {
428 svcerr_decode(transp
);
431 result
= (*local
)(&argument
, rqstp
);
432 if (result
!= NULL
&& !svc_sendreply(transp
, xdr_result
, result
)) {
433 svcerr_systemerr(transp
);
435 if (!svc_freeargs(transp
, xdr_argument
, (caddr_t
)(void *)&argument
)) {
436 syslog(LOG_ERR
, "unable to free arguments");