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