]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - libexec/rpc.rusersd/rusers_proc.c
ifconfig(8): wordsmith -G and -g descriptions
[FreeBSD/FreeBSD.git] / libexec / rpc.rusersd / rusers_proc.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1993, John Brezak
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 #ifdef DEBUG
33 #include <errno.h>
34 #endif
35 #include <stdio.h>
36 #include <string.h>
37 #include <sys/param.h>
38 #include <sys/stat.h>
39 #include <stdlib.h>
40 #include <syslog.h>
41 #include <utmpx.h>
42 #ifdef XIDLE
43 #include <setjmp.h>
44 #include <X11/Xlib.h>
45 #include <X11/extensions/xidle.h>
46 #endif
47 #include <rpcsvc/rnusers.h>
48
49 #include "extern.h"
50
51 #ifndef _PATH_DEV
52 #define _PATH_DEV "/dev"
53 #endif
54
55 static utmpidle utmp_idle[MAXUSERS];
56 static utmp old_utmp[MAXUSERS];
57 static struct utmpx utmp_list[MAXUSERS];
58
59 #ifdef XIDLE
60 static Display *dpy;
61
62 static jmp_buf openAbort;
63
64 static void
65 abortOpen(void)
66 {
67     longjmp (openAbort, 1);
68 }
69
70 XqueryIdle(char *display)
71 {
72         int first_event, first_error;
73         Time IdleTime;
74
75         (void) signal (SIGALRM, abortOpen);
76         (void) alarm ((unsigned) 10);
77         if (!setjmp (openAbort)) {
78                 if (!(dpy= XOpenDisplay(display))) {
79                         syslog(LOG_ERR, "Cannot open display %s", display);
80                         return(-1);
81                 }
82                 if (XidleQueryExtension(dpy, &first_event, &first_error)) {
83                         if (!XGetIdleTime(dpy, &IdleTime)) {
84                                 syslog(LOG_ERR, "%s: unable to get idle time", display);
85                                 return(-1);
86                         }
87                 } else {
88                         syslog(LOG_ERR, "%s: Xidle extension not loaded", display);
89                         return(-1);
90                 }
91                 XCloseDisplay(dpy);
92         } else {
93                 syslog(LOG_ERR, "%s: server grabbed for over 10 seconds", display);
94                 return(-1);
95         }
96         (void) signal (SIGALRM, SIG_DFL);
97         (void) alarm ((unsigned) 0);
98
99         IdleTime /= 1000;
100         return((IdleTime + 30) / 60);
101 }
102 #endif
103
104 static u_int
105 getidle(const char *tty, const char *display __unused)
106 {
107         struct stat st;
108         char ttyname[PATH_MAX];
109         time_t now;
110         u_long idle;
111
112         /*
113          * If this is an X terminal or console, then try the
114          * XIdle extension
115          */
116 #ifdef XIDLE
117         if (display && *display && (idle = XqueryIdle(display)) >= 0)
118                 return(idle);
119 #endif
120         idle = 0;
121         if (*tty == 'X') {
122                 u_long kbd_idle, mouse_idle;
123 #if     !defined(__FreeBSD__)
124                 kbd_idle = getidle("kbd", NULL);
125 #else
126                 kbd_idle = getidle("vga", NULL);
127 #endif
128                 mouse_idle = getidle("mouse", NULL);
129                 idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle;
130         } else {
131                 sprintf(ttyname, "%s/%s", _PATH_DEV, tty);
132                 if (stat(ttyname, &st) < 0) {
133 #ifdef DEBUG
134                         printf("%s: %s\n", ttyname, strerror(errno));
135 #endif
136                         return(-1);
137                 }
138                 time(&now);
139 #ifdef DEBUG
140                 printf("%s: now=%d atime=%d\n", ttyname, now,
141                        st.st_atime);
142 #endif
143                 idle = now - st.st_atime;
144                 idle = (idle + 30) / 60; /* secs->mins */
145         }
146
147         return(idle);
148 }
149
150 static utmpidlearr *
151 do_names_2(void)
152 {
153         static utmpidlearr ut;
154         struct utmpx *usr;
155         int nusers = 0;
156
157         memset(&ut, 0, sizeof(ut));
158         ut.utmpidlearr_val = &utmp_idle[0];
159
160         setutxent();
161         while ((usr = getutxent()) != NULL && nusers < MAXUSERS) {
162                 if (usr->ut_type != USER_PROCESS)
163                         continue;
164
165                 memcpy(&utmp_list[nusers], usr, sizeof(*usr));
166                 utmp_idle[nusers].ui_utmp.ut_time = usr->ut_tv.tv_sec;
167                 utmp_idle[nusers].ui_idle =
168                     getidle(usr->ut_line, usr->ut_host);
169                 utmp_idle[nusers].ui_utmp.ut_line =
170                     utmp_list[nusers].ut_line;
171                 utmp_idle[nusers].ui_utmp.ut_name =
172                     utmp_list[nusers].ut_user;
173                 utmp_idle[nusers].ui_utmp.ut_host =
174                     utmp_list[nusers].ut_host;
175
176                 nusers++;
177         }
178         endutxent();
179
180         ut.utmpidlearr_len = nusers;
181         return(&ut);
182 }
183
184 static int *
185 rusers_num(void *argp __unused, struct svc_req *rqstp __unused)
186 {
187         static int num_users = 0;
188         struct utmpx *usr;
189  
190         setutxent();
191         while ((usr = getutxent()) != NULL) {
192                 if (usr->ut_type != USER_PROCESS)
193                         continue;
194                 num_users++;
195         }
196         endutxent();
197  
198         return(&num_users);
199 }
200
201 static utmparr *
202 do_names_1(void)
203 {
204         utmpidlearr *utidle;
205         static utmparr ut;
206         unsigned int i;
207
208         bzero((char *)&ut, sizeof(ut));
209
210         utidle = do_names_2();
211         if (utidle) {
212                 ut.utmparr_len = utidle->utmpidlearr_len;
213                 ut.utmparr_val = &old_utmp[0];
214                 for (i = 0; i < ut.utmparr_len; i++)
215                         bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i],
216                               sizeof(old_utmp[0]));
217
218         }
219
220         return(&ut);
221 }
222
223 utmpidlearr *
224 rusersproc_names_2_svc(void *argp __unused, struct svc_req *rqstp __unused)
225 {
226
227         return (do_names_2());
228 }
229
230 utmpidlearr *
231 rusersproc_allnames_2_svc(void *argp __unused, struct svc_req *rqstp __unused)
232 {
233
234         return (do_names_2());
235 }
236
237 utmparr *
238 rusersproc_names_1_svc(void *argp __unused, struct svc_req *rqstp __unused)
239 {
240
241         return (do_names_1());
242 }
243
244 utmparr *
245 rusersproc_allnames_1_svc(void *argp __unused, struct svc_req *rqstp __unused)
246 {
247
248         return (do_names_1());
249 }
250
251 typedef void *(*rusersproc_t)(void *, struct svc_req *);
252
253 void
254 rusers_service(struct svc_req *rqstp, SVCXPRT *transp)
255 {
256         union {
257                 int fill;
258         } argument;
259         char *result;
260         xdrproc_t xdr_argument, xdr_result;
261         rusersproc_t local;
262
263         switch (rqstp->rq_proc) {
264         case NULLPROC:
265                 (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
266                 goto leave;
267
268         case RUSERSPROC_NUM:
269                 xdr_argument = (xdrproc_t)xdr_void;
270                 xdr_result = (xdrproc_t)xdr_int;
271                 local = (rusersproc_t)rusers_num;
272                 break;
273
274         case RUSERSPROC_NAMES:
275                 xdr_argument = (xdrproc_t)xdr_void;
276                 xdr_result = (xdrproc_t)xdr_utmpidlearr;
277                 switch (rqstp->rq_vers) {
278                 case RUSERSVERS_ORIG:
279                         local = (rusersproc_t)rusersproc_names_1_svc;
280                         break;
281                 case RUSERSVERS_IDLE:
282                         local = (rusersproc_t)rusersproc_names_2_svc;
283                         break;
284                 default:
285                         svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
286                         goto leave;
287                         /*NOTREACHED*/
288                 }
289                 break;
290
291         case RUSERSPROC_ALLNAMES:
292                 xdr_argument = (xdrproc_t)xdr_void;
293                 xdr_result = (xdrproc_t)xdr_utmpidlearr;
294                 switch (rqstp->rq_vers) {
295                 case RUSERSVERS_ORIG:
296                         local = (rusersproc_t)rusersproc_allnames_1_svc;
297                         break;
298                 case RUSERSVERS_IDLE:
299                         local = (rusersproc_t)rusersproc_allnames_2_svc;
300                         break;
301                 default:
302                         svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
303                         goto leave;
304                         /*NOTREACHED*/
305                 }
306                 break;
307
308         default:
309                 svcerr_noproc(transp);
310                 goto leave;
311         }
312         bzero(&argument, sizeof(argument));
313         if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) {
314                 svcerr_decode(transp);
315                 goto leave;
316         }
317         result = (*local)(&argument, rqstp);
318         if (result != NULL &&
319             !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) {
320                 svcerr_systemerr(transp);
321         }
322         if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, &argument)) {
323                 syslog(LOG_ERR, "unable to free arguments");
324                 exit(1);
325         }
326 leave:
327         if (from_inetd)
328                 exit(0);
329 }