]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - libexec/rpc.rusersd/rusers_proc.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / libexec / rpc.rusersd / rusers_proc.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
35 static const char rcsid[] =
36   "$FreeBSD$";
37 #endif /* not lint */
38
39 #ifdef DEBUG
40 #include <errno.h>
41 #endif
42 #include <stdio.h>
43 #include <string.h>
44 #include <sys/param.h>
45 #include <sys/stat.h>
46 #include <stdlib.h>
47 #include <syslog.h>
48 #include <utmpx.h>
49 #ifdef XIDLE
50 #include <setjmp.h>
51 #include <X11/Xlib.h>
52 #include <X11/extensions/xidle.h>
53 #endif
54 #include <rpcsvc/rnusers.h>
55
56 #include "extern.h"
57
58 #ifndef _PATH_DEV
59 #define _PATH_DEV "/dev"
60 #endif
61
62 static utmpidle utmp_idle[MAXUSERS];
63 static utmp old_utmp[MAXUSERS];
64 static struct utmpx utmp_list[MAXUSERS];
65
66 #ifdef XIDLE
67 static Display *dpy;
68
69 static jmp_buf openAbort;
70
71 static void
72 abortOpen(void)
73 {
74     longjmp (openAbort, 1);
75 }
76
77 XqueryIdle(char *display)
78 {
79         int first_event, first_error;
80         Time IdleTime;
81
82         (void) signal (SIGALRM, abortOpen);
83         (void) alarm ((unsigned) 10);
84         if (!setjmp (openAbort)) {
85                 if (!(dpy= XOpenDisplay(display))) {
86                         syslog(LOG_ERR, "Cannot open display %s", display);
87                         return(-1);
88                 }
89                 if (XidleQueryExtension(dpy, &first_event, &first_error)) {
90                         if (!XGetIdleTime(dpy, &IdleTime)) {
91                                 syslog(LOG_ERR, "%s: unable to get idle time", display);
92                                 return(-1);
93                         }
94                 } else {
95                         syslog(LOG_ERR, "%s: Xidle extension not loaded", display);
96                         return(-1);
97                 }
98                 XCloseDisplay(dpy);
99         } else {
100                 syslog(LOG_ERR, "%s: server grabbed for over 10 seconds", display);
101                 return(-1);
102         }
103         (void) signal (SIGALRM, SIG_DFL);
104         (void) alarm ((unsigned) 0);
105
106         IdleTime /= 1000;
107         return((IdleTime + 30) / 60);
108 }
109 #endif
110
111 static u_int
112 getidle(const char *tty, const char *display __unused)
113 {
114         struct stat st;
115         char ttyname[PATH_MAX];
116         time_t now;
117         u_long idle;
118
119         /*
120          * If this is an X terminal or console, then try the
121          * XIdle extension
122          */
123 #ifdef XIDLE
124         if (display && *display && (idle = XqueryIdle(display)) >= 0)
125                 return(idle);
126 #endif
127         idle = 0;
128         if (*tty == 'X') {
129                 u_long kbd_idle, mouse_idle;
130 #if     !defined(__FreeBSD__)
131                 kbd_idle = getidle("kbd", NULL);
132 #else
133                 kbd_idle = getidle("vga", NULL);
134 #endif
135                 mouse_idle = getidle("mouse", NULL);
136                 idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle;
137         } else {
138                 sprintf(ttyname, "%s/%s", _PATH_DEV, tty);
139                 if (stat(ttyname, &st) < 0) {
140 #ifdef DEBUG
141                         printf("%s: %s\n", ttyname, strerror(errno));
142 #endif
143                         return(-1);
144                 }
145                 time(&now);
146 #ifdef DEBUG
147                 printf("%s: now=%d atime=%d\n", ttyname, now,
148                        st.st_atime);
149 #endif
150                 idle = now - st.st_atime;
151                 idle = (idle + 30) / 60; /* secs->mins */
152         }
153
154         return(idle);
155 }
156
157 static utmpidlearr *
158 do_names_2(void)
159 {
160         static utmpidlearr ut;
161         struct utmpx *usr;
162         int nusers = 0;
163
164         memset(&ut, 0, sizeof(ut));
165         ut.utmpidlearr_val = &utmp_idle[0];
166
167         setutxent();
168         while ((usr = getutxent()) != NULL && nusers < MAXUSERS) {
169                 if (usr->ut_type != USER_PROCESS)
170                         continue;
171
172                 memcpy(&utmp_list[nusers], usr, sizeof(*usr));
173                 utmp_idle[nusers].ui_utmp.ut_time = usr->ut_tv.tv_sec;
174                 utmp_idle[nusers].ui_idle =
175                     getidle(usr->ut_line, usr->ut_host);
176                 utmp_idle[nusers].ui_utmp.ut_line =
177                     utmp_list[nusers].ut_line;
178                 utmp_idle[nusers].ui_utmp.ut_name =
179                     utmp_list[nusers].ut_user;
180                 utmp_idle[nusers].ui_utmp.ut_host =
181                     utmp_list[nusers].ut_host;
182
183                 nusers++;
184         }
185         endutxent();
186
187         ut.utmpidlearr_len = nusers;
188         return(&ut);
189 }
190
191 static int *
192 rusers_num(void *argp __unused, struct svc_req *rqstp __unused)
193 {
194         static int num_users = 0;
195         struct utmpx *usr;
196  
197         setutxent();
198         while ((usr = getutxent()) != NULL) {
199                 if (usr->ut_type != USER_PROCESS)
200                         continue;
201                 num_users++;
202         }
203         endutxent();
204  
205         return(&num_users);
206 }
207
208 static utmparr *
209 do_names_1(void)
210 {
211         utmpidlearr *utidle;
212         static utmparr ut;
213         unsigned int i;
214
215         bzero((char *)&ut, sizeof(ut));
216
217         utidle = do_names_2();
218         if (utidle) {
219                 ut.utmparr_len = utidle->utmpidlearr_len;
220                 ut.utmparr_val = &old_utmp[0];
221                 for (i = 0; i < ut.utmparr_len; i++)
222                         bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i],
223                               sizeof(old_utmp[0]));
224
225         }
226
227         return(&ut);
228 }
229
230 utmpidlearr *
231 rusersproc_names_2_svc(void *argp __unused, struct svc_req *rqstp __unused)
232 {
233
234         return (do_names_2());
235 }
236
237 utmpidlearr *
238 rusersproc_allnames_2_svc(void *argp __unused, struct svc_req *rqstp __unused)
239 {
240
241         return (do_names_2());
242 }
243
244 utmparr *
245 rusersproc_names_1_svc(void *argp __unused, struct svc_req *rqstp __unused)
246 {
247
248         return (do_names_1());
249 }
250
251 utmparr *
252 rusersproc_allnames_1_svc(void *argp __unused, struct svc_req *rqstp __unused)
253 {
254
255         return (do_names_1());
256 }
257
258 typedef void *(*rusersproc_t)(void *, struct svc_req *);
259
260 void
261 rusers_service(struct svc_req *rqstp, SVCXPRT *transp)
262 {
263         union {
264                 int fill;
265         } argument;
266         char *result;
267         xdrproc_t xdr_argument, xdr_result;
268         rusersproc_t local;
269
270         switch (rqstp->rq_proc) {
271         case NULLPROC:
272                 (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
273                 goto leave;
274
275         case RUSERSPROC_NUM:
276                 xdr_argument = (xdrproc_t)xdr_void;
277                 xdr_result = (xdrproc_t)xdr_int;
278                 local = (rusersproc_t)rusers_num;
279                 break;
280
281         case RUSERSPROC_NAMES:
282                 xdr_argument = (xdrproc_t)xdr_void;
283                 xdr_result = (xdrproc_t)xdr_utmpidlearr;
284                 switch (rqstp->rq_vers) {
285                 case RUSERSVERS_ORIG:
286                         local = (rusersproc_t)rusersproc_names_1_svc;
287                         break;
288                 case RUSERSVERS_IDLE:
289                         local = (rusersproc_t)rusersproc_names_2_svc;
290                         break;
291                 default:
292                         svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
293                         goto leave;
294                         /*NOTREACHED*/
295                 }
296                 break;
297
298         case RUSERSPROC_ALLNAMES:
299                 xdr_argument = (xdrproc_t)xdr_void;
300                 xdr_result = (xdrproc_t)xdr_utmpidlearr;
301                 switch (rqstp->rq_vers) {
302                 case RUSERSVERS_ORIG:
303                         local = (rusersproc_t)rusersproc_allnames_1_svc;
304                         break;
305                 case RUSERSVERS_IDLE:
306                         local = (rusersproc_t)rusersproc_allnames_2_svc;
307                         break;
308                 default:
309                         svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
310                         goto leave;
311                         /*NOTREACHED*/
312                 }
313                 break;
314
315         default:
316                 svcerr_noproc(transp);
317                 goto leave;
318         }
319         bzero(&argument, sizeof(argument));
320         if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) {
321                 svcerr_decode(transp);
322                 goto leave;
323         }
324         result = (*local)(&argument, rqstp);
325         if (result != NULL &&
326             !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) {
327                 svcerr_systemerr(transp);
328         }
329         if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, &argument)) {
330                 syslog(LOG_ERR, "unable to free arguments");
331                 exit(1);
332         }
333 leave:
334         if (from_inetd)
335                 exit(0);
336 }