This commit was generated by cvs2svn to track changes on a CVS vendor
[unix-history] / libexec / rpc.rusersd / rusers_proc.c
CommitLineData
69582008
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
35static char rcsid[] = "$Id: rusers_proc.c,v 1.5 1993/08/02 17:50:46 mycroft Exp $";
36#endif /* not lint */
37
38#include <signal.h>
39#include <sys/types.h>
40#include <sys/time.h>
41#include <utmp.h>
42#include <stdio.h>
43#include <syslog.h>
44#include <rpc/rpc.h>
45#include <sys/socket.h>
46#include <sys/param.h>
47#include <sys/stat.h>
48#ifdef XIDLE
49#include <setjmp.h>
50#include <X11/Xlib.h>
51#include <X11/extensions/xidle.h>
52#endif
53#define utmp rutmp
54#include <rpcsvc/rnusers.h>
55#undef utmp
56
57#define IGNOREUSER "sleeper"
58
59#ifdef OSF
60#define _PATH_UTMP UTMP_FILE
61#endif
62
63#ifndef _PATH_UTMP
64#define _PATH_UTMP "/etc/utmp"
65#endif
66
67#ifndef _PATH_DEV
68#define _PATH_DEV "/dev"
69#endif
70
71#ifndef UT_LINESIZE
72#define UT_LINESIZE sizeof(((struct utmp *)0)->ut_line)
73#endif
74#ifndef UT_NAMESIZE
75#define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name)
76#endif
77#ifndef UT_HOSTSIZE
78#define UT_HOSTSIZE sizeof(((struct utmp *)0)->ut_host)
79#endif
80
81typedef char ut_line_t[UT_LINESIZE];
82typedef char ut_name_t[UT_NAMESIZE];
83typedef char ut_host_t[UT_HOSTSIZE];
84
85utmpidle utmp_idle[MAXUSERS];
86rutmp old_utmp[MAXUSERS];
87ut_line_t line[MAXUSERS];
88ut_name_t name[MAXUSERS];
89ut_host_t host[MAXUSERS];
90
91extern int from_inetd;
92
93FILE *ufp;
94
95#ifdef XIDLE
96Display *dpy;
97
98static jmp_buf openAbort;
99
100static void
101abortOpen ()
102{
103 longjmp (openAbort, 1);
104}
105
106XqueryIdle(char *display)
107{
108 int first_event, first_error;
109 Time IdleTime;
110
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);
116 return(-1);
117 }
118 if (XidleQueryExtension(dpy, &first_event, &first_error)) {
119 if (!XGetIdleTime(dpy, &IdleTime)) {
120 syslog(LOG_ERR, "%s: Unable to get idle time.", display);
121 return(-1);
122 }
123 }
124 else {
125 syslog(LOG_ERR, "%s: Xidle extension not loaded.", display);
126 return(-1);
127 }
128 XCloseDisplay(dpy);
129 }
130 else {
131 syslog(LOG_ERR, "%s: Server grabbed for over 10 seconds.", display);
132 return(-1);
133 }
134 (void) signal (SIGALRM, SIG_DFL);
135 (void) alarm ((unsigned) 0);
136
137 IdleTime /= 1000;
138 return((IdleTime + 30) / 60);
139}
140#endif
141
142static u_int
143getidle(char *tty, char *display)
144{
145 struct stat st;
146 char devname[PATH_MAX];
147 time_t now;
148 u_long idle;
149
150 /*
151 * If this is an X terminal or console, then try the
152 * XIdle extension
153 */
154#ifdef XIDLE
155 if (display && *display && (idle = XqueryIdle(display)) >= 0)
156 return(idle);
157#endif
158 idle = 0;
159 if (*tty == 'X') {
160 u_long kbd_idle, mouse_idle;
161#if !defined(__386BSD__)
162 kbd_idle = getidle("kbd", NULL);
163#else
164 kbd_idle = getidle("vga", NULL);
165#endif
166 mouse_idle = getidle("mouse", NULL);
167 idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle;
168 }
169 else {
170 sprintf(devname, "%s/%s", _PATH_DEV, tty);
171 if (stat(devname, &st) < 0) {
172#ifdef DEBUG
173 printf("%s: %s\n", devname, strerror(errno));
174#endif
175 return(-1);
176 }
177 time(&now);
178#ifdef DEBUG
179 printf("%s: now=%d atime=%d\n", devname, now,
180 st.st_atime);
181#endif
182 idle = now - st.st_atime;
183 idle = (idle + 30) / 60; /* secs->mins */
184 }
185 if (idle < 0) idle = 0;
186
187 return(idle);
188}
189
190static utmpidlearr *
191do_names_2(int all)
192{
193 static utmpidlearr ut;
194 struct utmp usr;
195 int nusers = 0;
196
197 bzero((char *)&ut, sizeof(ut));
198 ut.utmpidlearr_val = &utmp_idle[0];
199
200 ufp = fopen(_PATH_UTMP, "r");
201 if (!ufp) {
202 syslog(LOG_ERR, "%m");
203 return(&ut);
204 }
205
206 /* only entries with both name and line fields */
207 while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1 &&
208 nusers < MAXUSERS)
209 if (*usr.ut_name && *usr.ut_line &&
210 strncmp(usr.ut_name, IGNOREUSER,
211 sizeof(usr.ut_name))
212#ifdef OSF
213 && usr.ut_type == USER_PROCESS
214#endif
215 ) {
216 utmp_idle[nusers].ui_utmp.ut_time =
217 usr.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, sizeof(line[nusers]));
222 utmp_idle[nusers].ui_utmp.ut_name = name[nusers];
223 strncpy(name[nusers], usr.ut_name, sizeof(name[nusers]));
224 utmp_idle[nusers].ui_utmp.ut_host = host[nusers];
225 strncpy(host[nusers], usr.ut_host, sizeof(host[nusers]));
226 nusers++;
227 }
228
229 ut.utmpidlearr_len = nusers;
230 fclose(ufp);
231 return(&ut);
232}
233
234int *
235rusers_num()
236{
237 int num_users = 0;
238 struct utmp usr;
239
240 ufp = fopen(_PATH_UTMP, "r");
241 if (!ufp) {
242 syslog(LOG_ERR, "%m");
243 return(0);
244 }
245
246 /* only entries with both name and line fields */
247 while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1)
248 if (*usr.ut_name && *usr.ut_line &&
249 strncmp(usr.ut_name, IGNOREUSER,
250 sizeof(usr.ut_name))
251#ifdef OSF
252 && usr.ut_type == USER_PROCESS
253#endif
254 ) {
255 num_users++;
256 }
257
258 fclose(ufp);
259 return(&num_users);
260}
261
262static utmparr *
263do_names_1(int all)
264{
265 utmpidlearr *utidle;
266 utmparr ut;
267 int i;
268
269 bzero((char *)&ut, sizeof(ut));
270
271 utidle = do_names_2(all);
272 if (utidle) {
273 ut.utmparr_len = utidle->utmpidlearr_len;
274 ut.utmparr_val = &old_utmp[0];
275 for (i = 0; i < ut.utmparr_len; i++)
276 bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i],
277 sizeof(old_utmp[0]));
278
279 }
280
281 return(&ut);
282}
283
284utmpidlearr *
285rusersproc_names_2()
286{
287 return(do_names_2(0));
288}
289
290utmpidlearr *
291rusersproc_allnames_2()
292{
293 return(do_names_2(1));
294}
295
296utmparr *
297rusersproc_names_1()
298{
299 return(do_names_1(0));
300}
301
302utmparr *
303rusersproc_allnames_1()
304{
305 return(do_names_1(1));
306}
307
308void
309rusers_service(rqstp, transp)
310 struct svc_req *rqstp;
311 SVCXPRT *transp;
312{
313 union {
314 int fill;
315 } argument;
316 char *result;
317 bool_t (*xdr_argument)(), (*xdr_result)();
318 char *(*local)();
319
320 switch (rqstp->rq_proc) {
321 case NULLPROC:
322 (void)svc_sendreply(transp, xdr_void, (char *)NULL);
323 goto leave;
324
325 case RUSERSPROC_NUM:
326 xdr_argument = xdr_void;
327 xdr_result = xdr_int;
328 local = (char *(*)()) rusers_num;
329 break;
330
331 case RUSERSPROC_NAMES:
332 xdr_argument = xdr_void;
333 xdr_result = xdr_utmpidlearr;
334 switch (rqstp->rq_vers) {
335 case RUSERSVERS_ORIG:
336 local = (char *(*)()) rusersproc_names_1;
337 break;
338 case RUSERSVERS_IDLE:
339 local = (char *(*)()) rusersproc_names_2;
340 break;
341 default:
342 svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
343 goto leave;
344 /*NOTREACHED*/
345 }
346 break;
347
348 case RUSERSPROC_ALLNAMES:
349 xdr_argument = xdr_void;
350 xdr_result = xdr_utmpidlearr;
351 switch (rqstp->rq_vers) {
352 case RUSERSVERS_ORIG:
353 local = (char *(*)()) rusersproc_allnames_1;
354 break;
355 case RUSERSVERS_IDLE:
356 local = (char *(*)()) rusersproc_allnames_2;
357 break;
358 default:
359 svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);
360 goto leave;
361 /*NOTREACHED*/
362 }
363 break;
364
365 default:
366 svcerr_noproc(transp);
367 goto leave;
368 }
369 bzero((char *)&argument, sizeof(argument));
370 if (!svc_getargs(transp, xdr_argument, &argument)) {
371 svcerr_decode(transp);
372 goto leave;
373 }
374 result = (*local)(&argument, rqstp);
375 if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
376 svcerr_systemerr(transp);
377 }
378 if (!svc_freeargs(transp, xdr_argument, &argument)) {
379 (void)fprintf(stderr, "unable to free arguments\n");
380 exit(1);
381 }
382leave:
383 if (from_inetd)
384 exit(0);
385}