rusers_proc.c revision 201146
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 201146 2009-12-28 23:01:24Z 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> 4831422Scharnier#include <utmp.h> 492337Scsgr#ifdef XIDLE 502337Scsgr#include <setjmp.h> 512337Scsgr#include <X11/Xlib.h> 522337Scsgr#include <X11/extensions/xidle.h> 532337Scsgr#endif 542337Scsgr#define utmp rutmp 552337Scsgr#include <rpcsvc/rnusers.h> 562337Scsgr#undef utmp 572337Scsgr 582337Scsgr#define IGNOREUSER "sleeper" 592337Scsgr 602337Scsgr#ifdef OSF 612337Scsgr#define _PATH_UTMP UTMP_FILE 622337Scsgr#endif 632337Scsgr 642337Scsgr#ifndef _PATH_UTMP 652337Scsgr#define _PATH_UTMP "/etc/utmp" 662337Scsgr#endif 672337Scsgr 682337Scsgr#ifndef _PATH_DEV 692337Scsgr#define _PATH_DEV "/dev" 702337Scsgr#endif 712337Scsgr 722337Scsgr#ifndef UT_LINESIZE 732337Scsgr#define UT_LINESIZE sizeof(((struct utmp *)0)->ut_line) 742337Scsgr#endif 752337Scsgr#ifndef UT_NAMESIZE 762337Scsgr#define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name) 772337Scsgr#endif 782337Scsgr#ifndef UT_HOSTSIZE 792337Scsgr#define UT_HOSTSIZE sizeof(((struct utmp *)0)->ut_host) 802337Scsgr#endif 812337Scsgr 822337Scsgrtypedef char ut_line_t[UT_LINESIZE+1]; 832337Scsgrtypedef char ut_name_t[UT_NAMESIZE+1]; 842337Scsgrtypedef char ut_host_t[UT_HOSTSIZE+1]; 852337Scsgr 86201146Sedstatic utmpidle utmp_idle[MAXUSERS]; 87201146Sedstatic rutmp old_utmp[MAXUSERS]; 88201146Sedstatic ut_line_t line[MAXUSERS]; 89201146Sedstatic ut_name_t name[MAXUSERS]; 90201146Sedstatic ut_host_t host[MAXUSERS]; 912337Scsgr 922337Scsgrextern int from_inetd; 932337Scsgr 94201146Sedvoid rusers_service(struct svc_req *, SVCXPRT *); 952337Scsgr 96201146Sedstatic FILE *ufp; 97201146Sed 982337Scsgr#ifdef XIDLE 99201146Sedstatic Display *dpy; 1002337Scsgr 1012337Scsgrstatic jmp_buf openAbort; 1022337Scsgr 1032337Scsgrstatic void 10490336SimpabortOpen(void) 1052337Scsgr{ 1062337Scsgr longjmp (openAbort, 1); 1072337Scsgr} 1082337Scsgr 1092337ScsgrXqueryIdle(char *display) 1102337Scsgr{ 111201146Sed int first_event, first_error; 112201146Sed Time IdleTime; 1132337Scsgr 114201146Sed (void) signal (SIGALRM, abortOpen); 115201146Sed (void) alarm ((unsigned) 10); 116201146Sed if (!setjmp (openAbort)) { 117201146Sed if (!(dpy= XOpenDisplay(display))) { 118201146Sed syslog(LOG_ERR, "Cannot open display %s", display); 119201146Sed return(-1); 120201146Sed } 121201146Sed if (XidleQueryExtension(dpy, &first_event, &first_error)) { 122201146Sed if (!XGetIdleTime(dpy, &IdleTime)) { 123201146Sed syslog(LOG_ERR, "%s: unable to get idle time", display); 124201146Sed return(-1); 125201146Sed } 126201146Sed } else { 127201146Sed syslog(LOG_ERR, "%s: Xidle extension not loaded", display); 128201146Sed return(-1); 129201146Sed } 130201146Sed XCloseDisplay(dpy); 131201146Sed } else { 132201146Sed syslog(LOG_ERR, "%s: server grabbed for over 10 seconds", display); 133201146Sed return(-1); 134201146Sed } 135201146Sed (void) signal (SIGALRM, SIG_DFL); 136201146Sed (void) alarm ((unsigned) 0); 1372337Scsgr 138201146Sed IdleTime /= 1000; 139201146Sed return((IdleTime + 30) / 60); 1402337Scsgr} 1412337Scsgr#endif 1422337Scsgr 1432337Scsgrstatic u_int 144201146Sedgetidle(const char *tty, const char *display __unused) 1452337Scsgr{ 146201146Sed struct stat st; 147201146Sed char ttyname[PATH_MAX]; 148201146Sed time_t now; 149201146Sed u_long idle; 1508870Srgrimes 151201146Sed /* 152201146Sed * If this is an X terminal or console, then try the 153201146Sed * XIdle extension 154201146Sed */ 1552337Scsgr#ifdef XIDLE 156201146Sed if (display && *display && (idle = XqueryIdle(display)) >= 0) 157201146Sed return(idle); 1582337Scsgr#endif 159201146Sed idle = 0; 160201146Sed if (*tty == 'X') { 161201146Sed u_long kbd_idle, mouse_idle; 1624131Sjkh#if !defined(__FreeBSD__) 163201146Sed kbd_idle = getidle("kbd", NULL); 1642337Scsgr#else 165201146Sed kbd_idle = getidle("vga", NULL); 1662337Scsgr#endif 167201146Sed mouse_idle = getidle("mouse", NULL); 168201146Sed idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle; 169201146Sed } else { 170201146Sed sprintf(ttyname, "%s/%s", _PATH_DEV, tty); 171201146Sed if (stat(ttyname, &st) < 0) { 1722337Scsgr#ifdef DEBUG 173201146Sed printf("%s: %s\n", ttyname, strerror(errno)); 1742337Scsgr#endif 175201146Sed return(-1); 176201146Sed } 177201146Sed time(&now); 1782337Scsgr#ifdef DEBUG 179201146Sed printf("%s: now=%d atime=%d\n", ttyname, now, 180201146Sed st.st_atime); 1812337Scsgr#endif 182201146Sed idle = now - st.st_atime; 183201146Sed idle = (idle + 30) / 60; /* secs->mins */ 184201146Sed } 1852337Scsgr 186201146Sed return(idle); 1872337Scsgr} 1888870Srgrimes 1892337Scsgrstatic utmpidlearr * 190201146Seddo_names_2(void) 1912337Scsgr{ 192201146Sed static utmpidlearr ut; 1932337Scsgr struct utmp usr; 194201146Sed int nusers = 0; 1958870Srgrimes 196201146Sed bzero((char *)&ut, sizeof(ut)); 197201146Sed ut.utmpidlearr_val = &utmp_idle[0]; 1988870Srgrimes 1992337Scsgr ufp = fopen(_PATH_UTMP, "r"); 200201146Sed if (!ufp) { 201201146Sed syslog(LOG_ERR, "%m"); 202201146Sed return(&ut); 203201146Sed } 2042337Scsgr 205201146Sed /* only entries with both name and line fields */ 206201146Sed while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1 && 207201146Sed nusers < MAXUSERS) 208201146Sed if (*usr.ut_name && *usr.ut_line && 2092337Scsgr strncmp(usr.ut_name, IGNOREUSER, 210201146Sed sizeof(usr.ut_name)) 2112337Scsgr#ifdef OSF 212201146Sed && usr.ut_type == USER_PROCESS 2132337Scsgr#endif 214201146Sed ) { 215201146Sed utmp_idle[nusers].ui_utmp.ut_time = 216201146Sed usr.ut_time; 217201146Sed utmp_idle[nusers].ui_idle = 218201146Sed getidle(usr.ut_line, usr.ut_host); 219201146Sed utmp_idle[nusers].ui_utmp.ut_line = line[nusers]; 220201146Sed strncpy(line[nusers], usr.ut_line, UT_LINESIZE); 221201146Sed utmp_idle[nusers].ui_utmp.ut_name = name[nusers]; 222201146Sed strncpy(name[nusers], usr.ut_name, UT_NAMESIZE); 223201146Sed utmp_idle[nusers].ui_utmp.ut_host = host[nusers]; 224201146Sed strncpy(host[nusers], usr.ut_host, UT_HOSTSIZE); 2258870Srgrimes 2262337Scsgr /* Make sure entries are NUL terminated */ 2278870Srgrimes line[nusers][UT_LINESIZE] = 2288870Srgrimes name[nusers][UT_NAMESIZE] = 2292337Scsgr host[nusers][UT_HOSTSIZE] = '\0'; 230201146Sed nusers++; 231201146Sed } 2322337Scsgr 233201146Sed ut.utmpidlearr_len = nusers; 234201146Sed fclose(ufp); 235201146Sed return(&ut); 2362337Scsgr} 2372337Scsgr 238201146Sedstatic int * 239201146Sedrusers_num(void *argp __unused, struct svc_req *rqstp __unused) 2402337Scsgr{ 241201146Sed static int num_users = 0; 2422337Scsgr struct utmp usr; 2432337Scsgr 244201146Sed ufp = fopen(_PATH_UTMP, "r"); 245201146Sed if (!ufp) { 246201146Sed syslog(LOG_ERR, "%m"); 247201146Sed return(NULL); 248201146Sed } 2492337Scsgr 250201146Sed /* only entries with both name and line fields */ 251201146Sed while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1) 252201146Sed if (*usr.ut_name && *usr.ut_line && 2532337Scsgr strncmp(usr.ut_name, IGNOREUSER, 254201146Sed sizeof(usr.ut_name)) 2552337Scsgr#ifdef OSF 256201146Sed && usr.ut_type == USER_PROCESS 2572337Scsgr#endif 258201146Sed ) { 259201146Sed num_users++; 260201146Sed } 2612337Scsgr 262201146Sed fclose(ufp); 263201146Sed return(&num_users); 2642337Scsgr} 2652337Scsgr 2662337Scsgrstatic utmparr * 267201146Seddo_names_1(void) 2682337Scsgr{ 269201146Sed utmpidlearr *utidle; 270201146Sed static utmparr ut; 271201146Sed unsigned int i; 2728870Srgrimes 273201146Sed bzero((char *)&ut, sizeof(ut)); 2748870Srgrimes 275201146Sed utidle = do_names_2(); 276201146Sed if (utidle) { 277201146Sed ut.utmparr_len = utidle->utmpidlearr_len; 278201146Sed ut.utmparr_val = &old_utmp[0]; 279201146Sed for (i = 0; i < ut.utmparr_len; i++) 280201146Sed bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i], 281201146Sed sizeof(old_utmp[0])); 2828870Srgrimes 283201146Sed } 2848870Srgrimes 285201146Sed return(&ut); 2862337Scsgr} 2872337Scsgr 2882337Scsgrutmpidlearr * 289201146Sedrusersproc_names_2_svc(void *argp __unused, struct svc_req *rqstp __unused) 2902337Scsgr{ 291201146Sed 292201146Sed return (do_names_2()); 2932337Scsgr} 2942337Scsgr 2952337Scsgrutmpidlearr * 296201146Sedrusersproc_allnames_2_svc(void *argp __unused, struct svc_req *rqstp __unused) 2972337Scsgr{ 298201146Sed 299201146Sed return (do_names_2()); 3002337Scsgr} 3012337Scsgr 3022337Scsgrutmparr * 303201146Sedrusersproc_names_1_svc(void *argp __unused, struct svc_req *rqstp __unused) 3042337Scsgr{ 305201146Sed 306201146Sed return (do_names_1()); 3072337Scsgr} 3082337Scsgr 3092337Scsgrutmparr * 310201146Sedrusersproc_allnames_1_svc(void *argp __unused, struct svc_req *rqstp __unused) 3112337Scsgr{ 312201146Sed 313201146Sed return (do_names_1()); 3142337Scsgr} 3152337Scsgr 316201146Sedtypedef void *(*rusersproc_t)(void *, struct svc_req *); 317201146Sed 3182337Scsgrvoid 31990336Simprusers_service(struct svc_req *rqstp, SVCXPRT *transp) 3202337Scsgr{ 3212337Scsgr union { 3222337Scsgr int fill; 3232337Scsgr } argument; 3242337Scsgr char *result; 325201146Sed xdrproc_t xdr_argument, xdr_result; 326201146Sed rusersproc_t local; 3272337Scsgr 3282337Scsgr switch (rqstp->rq_proc) { 3292337Scsgr case NULLPROC: 33095658Sdes (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); 3312337Scsgr goto leave; 3322337Scsgr 3332337Scsgr case RUSERSPROC_NUM: 334201146Sed xdr_argument = (xdrproc_t)xdr_void; 335201146Sed xdr_result = (xdrproc_t)xdr_int; 336201146Sed local = (rusersproc_t)rusers_num; 3372337Scsgr break; 3382337Scsgr 3392337Scsgr case RUSERSPROC_NAMES: 340201146Sed xdr_argument = (xdrproc_t)xdr_void; 341201146Sed xdr_result = (xdrproc_t)xdr_utmpidlearr; 342201146Sed switch (rqstp->rq_vers) { 343201146Sed case RUSERSVERS_ORIG: 344201146Sed local = (rusersproc_t)rusersproc_names_1_svc; 345201146Sed break; 346201146Sed case RUSERSVERS_IDLE: 347201146Sed local = (rusersproc_t)rusersproc_names_2_svc; 348201146Sed break; 349201146Sed default: 350201146Sed svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); 351201146Sed goto leave; 352201146Sed /*NOTREACHED*/ 353201146Sed } 3542337Scsgr break; 3552337Scsgr 3562337Scsgr case RUSERSPROC_ALLNAMES: 357201146Sed xdr_argument = (xdrproc_t)xdr_void; 358201146Sed xdr_result = (xdrproc_t)xdr_utmpidlearr; 359201146Sed switch (rqstp->rq_vers) { 360201146Sed case RUSERSVERS_ORIG: 361201146Sed local = (rusersproc_t)rusersproc_allnames_1_svc; 362201146Sed break; 363201146Sed case RUSERSVERS_IDLE: 364201146Sed local = (rusersproc_t)rusersproc_allnames_2_svc; 365201146Sed break; 366201146Sed default: 367201146Sed svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); 368201146Sed goto leave; 369201146Sed /*NOTREACHED*/ 370201146Sed } 3712337Scsgr break; 3722337Scsgr 3732337Scsgr default: 3742337Scsgr svcerr_noproc(transp); 3752337Scsgr goto leave; 3762337Scsgr } 37795658Sdes bzero(&argument, sizeof(argument)); 37895658Sdes if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) { 3792337Scsgr svcerr_decode(transp); 3802337Scsgr goto leave; 3812337Scsgr } 3822337Scsgr result = (*local)(&argument, rqstp); 38395658Sdes if (result != NULL && 38495658Sdes !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { 3852337Scsgr svcerr_systemerr(transp); 3862337Scsgr } 38795658Sdes if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, &argument)) { 38832312Scharnier syslog(LOG_ERR, "unable to free arguments"); 38932312Scharnier exit(1); 39032312Scharnier } 3912337Scsgrleave: 392201146Sed if (from_inetd) 393201146Sed exit(0); 3942337Scsgr} 395