rusers_proc.c revision 241777
12337Scsgr/*- 22337Scsgr * Copyright (c) 1993, John Brezak 32337Scsgr * All rights reserved. 42337Scsgr * 52337Scsgr * Redistribution and use in source and binary forms, with or without 62337Scsgr * modification, are permitted provided that the following conditions 72337Scsgr * are met: 82337Scsgr * 1. Redistributions of source code must retain the above copyright 92337Scsgr * notice, this list of conditions and the following disclaimer. 102337Scsgr * 2. Redistributions in binary form must reproduce the above copyright 112337Scsgr * notice, this list of conditions and the following disclaimer in the 122337Scsgr * documentation and/or other materials provided with the distribution. 132337Scsgr * 3. All advertising materials mentioning features or use of this software 142337Scsgr * must display the following acknowledgement: 152337Scsgr * This product includes software developed by the University of 162337Scsgr * California, Berkeley and its contributors. 172337Scsgr * 4. Neither the name of the University nor the names of its contributors 182337Scsgr * may be used to endorse or promote products derived from this software 192337Scsgr * without specific prior written permission. 202337Scsgr * 212337Scsgr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 222337Scsgr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 232337Scsgr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 242337Scsgr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 252337Scsgr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 262337Scsgr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 272337Scsgr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 282337Scsgr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 292337Scsgr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 302337Scsgr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 312337Scsgr * SUCH DAMAGE. 322337Scsgr */ 332337Scsgr 342337Scsgr#ifndef lint 3531422Scharnierstatic const char rcsid[] = 3650476Speter "$FreeBSD: head/libexec/rpc.rusersd/rusers_proc.c 241777 2012-10-20 10:33:15Z ed $"; 372337Scsgr#endif /* not lint */ 382337Scsgr 3932312Scharnier#ifdef DEBUG 4032312Scharnier#include <errno.h> 4132312Scharnier#endif 422337Scsgr#include <stdio.h> 4331422Scharnier#include <string.h> 4431422Scharnier#include <sys/param.h> 452337Scsgr#include <sys/stat.h> 46115668Sobrien#include <stdlib.h> 4731422Scharnier#include <syslog.h> 48202210Sed#include <utmpx.h> 492337Scsgr#ifdef XIDLE 502337Scsgr#include <setjmp.h> 512337Scsgr#include <X11/Xlib.h> 522337Scsgr#include <X11/extensions/xidle.h> 532337Scsgr#endif 542337Scsgr#include <rpcsvc/rnusers.h> 552337Scsgr 56241777Sed#include "extern.h" 57241777Sed 582337Scsgr#ifndef _PATH_DEV 592337Scsgr#define _PATH_DEV "/dev" 602337Scsgr#endif 612337Scsgr 62201146Sedstatic utmpidle utmp_idle[MAXUSERS]; 63201192Sedstatic utmp old_utmp[MAXUSERS]; 64201192Sedstatic struct utmpx utmp_list[MAXUSERS]; 652337Scsgr 662337Scsgr#ifdef XIDLE 67201146Sedstatic Display *dpy; 682337Scsgr 692337Scsgrstatic jmp_buf openAbort; 702337Scsgr 712337Scsgrstatic void 7290336SimpabortOpen(void) 732337Scsgr{ 742337Scsgr longjmp (openAbort, 1); 752337Scsgr} 762337Scsgr 772337ScsgrXqueryIdle(char *display) 782337Scsgr{ 79201146Sed int first_event, first_error; 80201146Sed Time IdleTime; 812337Scsgr 82201146Sed (void) signal (SIGALRM, abortOpen); 83201146Sed (void) alarm ((unsigned) 10); 84201146Sed if (!setjmp (openAbort)) { 85201146Sed if (!(dpy= XOpenDisplay(display))) { 86201146Sed syslog(LOG_ERR, "Cannot open display %s", display); 87201146Sed return(-1); 88201146Sed } 89201146Sed if (XidleQueryExtension(dpy, &first_event, &first_error)) { 90201146Sed if (!XGetIdleTime(dpy, &IdleTime)) { 91201146Sed syslog(LOG_ERR, "%s: unable to get idle time", display); 92201146Sed return(-1); 93201146Sed } 94201146Sed } else { 95201146Sed syslog(LOG_ERR, "%s: Xidle extension not loaded", display); 96201146Sed return(-1); 97201146Sed } 98201146Sed XCloseDisplay(dpy); 99201146Sed } else { 100201146Sed syslog(LOG_ERR, "%s: server grabbed for over 10 seconds", display); 101201146Sed return(-1); 102201146Sed } 103201146Sed (void) signal (SIGALRM, SIG_DFL); 104201146Sed (void) alarm ((unsigned) 0); 1052337Scsgr 106201146Sed IdleTime /= 1000; 107201146Sed return((IdleTime + 30) / 60); 1082337Scsgr} 1092337Scsgr#endif 1102337Scsgr 1112337Scsgrstatic u_int 112201146Sedgetidle(const char *tty, const char *display __unused) 1132337Scsgr{ 114201146Sed struct stat st; 115201146Sed char ttyname[PATH_MAX]; 116201146Sed time_t now; 117201146Sed u_long idle; 1188870Srgrimes 119201146Sed /* 120201146Sed * If this is an X terminal or console, then try the 121201146Sed * XIdle extension 122201146Sed */ 1232337Scsgr#ifdef XIDLE 124201146Sed if (display && *display && (idle = XqueryIdle(display)) >= 0) 125201146Sed return(idle); 1262337Scsgr#endif 127201146Sed idle = 0; 128201146Sed if (*tty == 'X') { 129201146Sed u_long kbd_idle, mouse_idle; 1304131Sjkh#if !defined(__FreeBSD__) 131201146Sed kbd_idle = getidle("kbd", NULL); 1322337Scsgr#else 133201146Sed kbd_idle = getidle("vga", NULL); 1342337Scsgr#endif 135201146Sed mouse_idle = getidle("mouse", NULL); 136201146Sed idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle; 137201146Sed } else { 138201146Sed sprintf(ttyname, "%s/%s", _PATH_DEV, tty); 139201146Sed if (stat(ttyname, &st) < 0) { 1402337Scsgr#ifdef DEBUG 141201146Sed printf("%s: %s\n", ttyname, strerror(errno)); 1422337Scsgr#endif 143201146Sed return(-1); 144201146Sed } 145201146Sed time(&now); 1462337Scsgr#ifdef DEBUG 147201146Sed printf("%s: now=%d atime=%d\n", ttyname, now, 148201146Sed st.st_atime); 1492337Scsgr#endif 150201146Sed idle = now - st.st_atime; 151201146Sed idle = (idle + 30) / 60; /* secs->mins */ 152201146Sed } 1532337Scsgr 154201146Sed return(idle); 1552337Scsgr} 1568870Srgrimes 1572337Scsgrstatic utmpidlearr * 158201146Seddo_names_2(void) 1592337Scsgr{ 160201146Sed static utmpidlearr ut; 161201192Sed struct utmpx *usr; 162201146Sed int nusers = 0; 1638870Srgrimes 164201192Sed memset(&ut, 0, sizeof(ut)); 165201146Sed ut.utmpidlearr_val = &utmp_idle[0]; 1668870Srgrimes 167201192Sed setutxent(); 168201192Sed while ((usr = getutxent()) != NULL && nusers < MAXUSERS) { 169201192Sed if (usr->ut_type != USER_PROCESS) 170201192Sed continue; 1712337Scsgr 172201192Sed memcpy(&utmp_list[nusers], usr, sizeof(*usr)); 173201192Sed utmp_idle[nusers].ui_utmp.ut_time = usr->ut_tv.tv_sec; 174201192Sed utmp_idle[nusers].ui_idle = 175201192Sed getidle(usr->ut_line, usr->ut_host); 176201192Sed utmp_idle[nusers].ui_utmp.ut_line = 177201192Sed utmp_list[nusers].ut_line; 178201192Sed utmp_idle[nusers].ui_utmp.ut_name = 179201192Sed utmp_list[nusers].ut_user; 180201192Sed utmp_idle[nusers].ui_utmp.ut_host = 181201192Sed utmp_list[nusers].ut_host; 1828870Srgrimes 183201192Sed nusers++; 184201192Sed } 185201192Sed endutxent(); 1862337Scsgr 187201146Sed ut.utmpidlearr_len = nusers; 188201146Sed return(&ut); 1892337Scsgr} 1902337Scsgr 191201146Sedstatic int * 192201146Sedrusers_num(void *argp __unused, struct svc_req *rqstp __unused) 1932337Scsgr{ 194201146Sed static int num_users = 0; 195201192Sed struct utmpx *usr; 196201192Sed 197201192Sed setutxent(); 198201192Sed while ((usr = getutxent()) != NULL) { 199201192Sed if (usr->ut_type != USER_PROCESS) 200201192Sed continue; 201201192Sed num_users++; 202201146Sed } 203201192Sed endutxent(); 204201192Sed 205201146Sed return(&num_users); 2062337Scsgr} 2072337Scsgr 2082337Scsgrstatic utmparr * 209201146Seddo_names_1(void) 2102337Scsgr{ 211201146Sed utmpidlearr *utidle; 212201146Sed static utmparr ut; 213201146Sed unsigned int i; 2148870Srgrimes 215201146Sed bzero((char *)&ut, sizeof(ut)); 2168870Srgrimes 217201146Sed utidle = do_names_2(); 218201146Sed if (utidle) { 219201146Sed ut.utmparr_len = utidle->utmpidlearr_len; 220201146Sed ut.utmparr_val = &old_utmp[0]; 221201146Sed for (i = 0; i < ut.utmparr_len; i++) 222201146Sed bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i], 223201146Sed sizeof(old_utmp[0])); 2248870Srgrimes 225201146Sed } 2268870Srgrimes 227201146Sed return(&ut); 2282337Scsgr} 2292337Scsgr 2302337Scsgrutmpidlearr * 231201146Sedrusersproc_names_2_svc(void *argp __unused, struct svc_req *rqstp __unused) 2322337Scsgr{ 233201146Sed 234201146Sed return (do_names_2()); 2352337Scsgr} 2362337Scsgr 2372337Scsgrutmpidlearr * 238201146Sedrusersproc_allnames_2_svc(void *argp __unused, struct svc_req *rqstp __unused) 2392337Scsgr{ 240201146Sed 241201146Sed return (do_names_2()); 2422337Scsgr} 2432337Scsgr 2442337Scsgrutmparr * 245201146Sedrusersproc_names_1_svc(void *argp __unused, struct svc_req *rqstp __unused) 2462337Scsgr{ 247201146Sed 248201146Sed return (do_names_1()); 2492337Scsgr} 2502337Scsgr 2512337Scsgrutmparr * 252201146Sedrusersproc_allnames_1_svc(void *argp __unused, struct svc_req *rqstp __unused) 2532337Scsgr{ 254201146Sed 255201146Sed return (do_names_1()); 2562337Scsgr} 2572337Scsgr 258201146Sedtypedef void *(*rusersproc_t)(void *, struct svc_req *); 259201146Sed 2602337Scsgrvoid 26190336Simprusers_service(struct svc_req *rqstp, SVCXPRT *transp) 2622337Scsgr{ 2632337Scsgr union { 2642337Scsgr int fill; 2652337Scsgr } argument; 2662337Scsgr char *result; 267201146Sed xdrproc_t xdr_argument, xdr_result; 268201146Sed rusersproc_t local; 2692337Scsgr 2702337Scsgr switch (rqstp->rq_proc) { 2712337Scsgr case NULLPROC: 27295658Sdes (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); 2732337Scsgr goto leave; 2742337Scsgr 2752337Scsgr case RUSERSPROC_NUM: 276201146Sed xdr_argument = (xdrproc_t)xdr_void; 277201146Sed xdr_result = (xdrproc_t)xdr_int; 278201146Sed local = (rusersproc_t)rusers_num; 2792337Scsgr break; 2802337Scsgr 2812337Scsgr case RUSERSPROC_NAMES: 282201146Sed xdr_argument = (xdrproc_t)xdr_void; 283201146Sed xdr_result = (xdrproc_t)xdr_utmpidlearr; 284201146Sed switch (rqstp->rq_vers) { 285201146Sed case RUSERSVERS_ORIG: 286201146Sed local = (rusersproc_t)rusersproc_names_1_svc; 287201146Sed break; 288201146Sed case RUSERSVERS_IDLE: 289201146Sed local = (rusersproc_t)rusersproc_names_2_svc; 290201146Sed break; 291201146Sed default: 292201146Sed svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); 293201146Sed goto leave; 294201146Sed /*NOTREACHED*/ 295201146Sed } 2962337Scsgr break; 2972337Scsgr 2982337Scsgr case RUSERSPROC_ALLNAMES: 299201146Sed xdr_argument = (xdrproc_t)xdr_void; 300201146Sed xdr_result = (xdrproc_t)xdr_utmpidlearr; 301201146Sed switch (rqstp->rq_vers) { 302201146Sed case RUSERSVERS_ORIG: 303201146Sed local = (rusersproc_t)rusersproc_allnames_1_svc; 304201146Sed break; 305201146Sed case RUSERSVERS_IDLE: 306201146Sed local = (rusersproc_t)rusersproc_allnames_2_svc; 307201146Sed break; 308201146Sed default: 309201146Sed svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); 310201146Sed goto leave; 311201146Sed /*NOTREACHED*/ 312201146Sed } 3132337Scsgr break; 3142337Scsgr 3152337Scsgr default: 3162337Scsgr svcerr_noproc(transp); 3172337Scsgr goto leave; 3182337Scsgr } 31995658Sdes bzero(&argument, sizeof(argument)); 32095658Sdes if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) { 3212337Scsgr svcerr_decode(transp); 3222337Scsgr goto leave; 3232337Scsgr } 3242337Scsgr result = (*local)(&argument, rqstp); 32595658Sdes if (result != NULL && 32695658Sdes !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { 3272337Scsgr svcerr_systemerr(transp); 3282337Scsgr } 32995658Sdes if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, &argument)) { 33032312Scharnier syslog(LOG_ERR, "unable to free arguments"); 33132312Scharnier exit(1); 33232312Scharnier } 3332337Scsgrleave: 334201146Sed if (from_inetd) 335201146Sed exit(0); 3362337Scsgr} 337