rusers_proc.c revision 201192
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 201192 2009-12-29 10:28:20Z 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> 48201192Sed#define _ULOG_POSIX_NAMES 49201192Sed#include <ulog.h> 502337Scsgr#ifdef XIDLE 512337Scsgr#include <setjmp.h> 522337Scsgr#include <X11/Xlib.h> 532337Scsgr#include <X11/extensions/xidle.h> 542337Scsgr#endif 552337Scsgr#include <rpcsvc/rnusers.h> 562337Scsgr 572337Scsgr#ifndef _PATH_DEV 582337Scsgr#define _PATH_DEV "/dev" 592337Scsgr#endif 602337Scsgr 61201146Sedstatic utmpidle utmp_idle[MAXUSERS]; 62201192Sedstatic utmp old_utmp[MAXUSERS]; 63201192Sedstatic struct utmpx utmp_list[MAXUSERS]; 642337Scsgr 652337Scsgrextern int from_inetd; 662337Scsgr 67201146Sedvoid rusers_service(struct svc_req *, SVCXPRT *); 682337Scsgr 692337Scsgr#ifdef XIDLE 70201146Sedstatic Display *dpy; 712337Scsgr 722337Scsgrstatic jmp_buf openAbort; 732337Scsgr 742337Scsgrstatic void 7590336SimpabortOpen(void) 762337Scsgr{ 772337Scsgr longjmp (openAbort, 1); 782337Scsgr} 792337Scsgr 802337ScsgrXqueryIdle(char *display) 812337Scsgr{ 82201146Sed int first_event, first_error; 83201146Sed Time IdleTime; 842337Scsgr 85201146Sed (void) signal (SIGALRM, abortOpen); 86201146Sed (void) alarm ((unsigned) 10); 87201146Sed if (!setjmp (openAbort)) { 88201146Sed if (!(dpy= XOpenDisplay(display))) { 89201146Sed syslog(LOG_ERR, "Cannot open display %s", display); 90201146Sed return(-1); 91201146Sed } 92201146Sed if (XidleQueryExtension(dpy, &first_event, &first_error)) { 93201146Sed if (!XGetIdleTime(dpy, &IdleTime)) { 94201146Sed syslog(LOG_ERR, "%s: unable to get idle time", display); 95201146Sed return(-1); 96201146Sed } 97201146Sed } else { 98201146Sed syslog(LOG_ERR, "%s: Xidle extension not loaded", display); 99201146Sed return(-1); 100201146Sed } 101201146Sed XCloseDisplay(dpy); 102201146Sed } else { 103201146Sed syslog(LOG_ERR, "%s: server grabbed for over 10 seconds", display); 104201146Sed return(-1); 105201146Sed } 106201146Sed (void) signal (SIGALRM, SIG_DFL); 107201146Sed (void) alarm ((unsigned) 0); 1082337Scsgr 109201146Sed IdleTime /= 1000; 110201146Sed return((IdleTime + 30) / 60); 1112337Scsgr} 1122337Scsgr#endif 1132337Scsgr 1142337Scsgrstatic u_int 115201146Sedgetidle(const char *tty, const char *display __unused) 1162337Scsgr{ 117201146Sed struct stat st; 118201146Sed char ttyname[PATH_MAX]; 119201146Sed time_t now; 120201146Sed u_long idle; 1218870Srgrimes 122201146Sed /* 123201146Sed * If this is an X terminal or console, then try the 124201146Sed * XIdle extension 125201146Sed */ 1262337Scsgr#ifdef XIDLE 127201146Sed if (display && *display && (idle = XqueryIdle(display)) >= 0) 128201146Sed return(idle); 1292337Scsgr#endif 130201146Sed idle = 0; 131201146Sed if (*tty == 'X') { 132201146Sed u_long kbd_idle, mouse_idle; 1334131Sjkh#if !defined(__FreeBSD__) 134201146Sed kbd_idle = getidle("kbd", NULL); 1352337Scsgr#else 136201146Sed kbd_idle = getidle("vga", NULL); 1372337Scsgr#endif 138201146Sed mouse_idle = getidle("mouse", NULL); 139201146Sed idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle; 140201146Sed } else { 141201146Sed sprintf(ttyname, "%s/%s", _PATH_DEV, tty); 142201146Sed if (stat(ttyname, &st) < 0) { 1432337Scsgr#ifdef DEBUG 144201146Sed printf("%s: %s\n", ttyname, strerror(errno)); 1452337Scsgr#endif 146201146Sed return(-1); 147201146Sed } 148201146Sed time(&now); 1492337Scsgr#ifdef DEBUG 150201146Sed printf("%s: now=%d atime=%d\n", ttyname, now, 151201146Sed st.st_atime); 1522337Scsgr#endif 153201146Sed idle = now - st.st_atime; 154201146Sed idle = (idle + 30) / 60; /* secs->mins */ 155201146Sed } 1562337Scsgr 157201146Sed return(idle); 1582337Scsgr} 1598870Srgrimes 1602337Scsgrstatic utmpidlearr * 161201146Seddo_names_2(void) 1622337Scsgr{ 163201146Sed static utmpidlearr ut; 164201192Sed struct utmpx *usr; 165201146Sed int nusers = 0; 1668870Srgrimes 167201192Sed memset(&ut, 0, sizeof(ut)); 168201146Sed ut.utmpidlearr_val = &utmp_idle[0]; 1698870Srgrimes 170201192Sed setutxent(); 171201192Sed while ((usr = getutxent()) != NULL && nusers < MAXUSERS) { 172201192Sed if (usr->ut_type != USER_PROCESS) 173201192Sed continue; 1742337Scsgr 175201192Sed memcpy(&utmp_list[nusers], usr, sizeof(*usr)); 176201192Sed utmp_idle[nusers].ui_utmp.ut_time = usr->ut_tv.tv_sec; 177201192Sed utmp_idle[nusers].ui_idle = 178201192Sed getidle(usr->ut_line, usr->ut_host); 179201192Sed utmp_idle[nusers].ui_utmp.ut_line = 180201192Sed utmp_list[nusers].ut_line; 181201192Sed utmp_idle[nusers].ui_utmp.ut_name = 182201192Sed utmp_list[nusers].ut_user; 183201192Sed utmp_idle[nusers].ui_utmp.ut_host = 184201192Sed utmp_list[nusers].ut_host; 1858870Srgrimes 186201192Sed nusers++; 187201192Sed } 188201192Sed endutxent(); 1892337Scsgr 190201146Sed ut.utmpidlearr_len = nusers; 191201146Sed return(&ut); 1922337Scsgr} 1932337Scsgr 194201146Sedstatic int * 195201146Sedrusers_num(void *argp __unused, struct svc_req *rqstp __unused) 1962337Scsgr{ 197201146Sed static int num_users = 0; 198201192Sed struct utmpx *usr; 199201192Sed 200201192Sed setutxent(); 201201192Sed while ((usr = getutxent()) != NULL) { 202201192Sed if (usr->ut_type != USER_PROCESS) 203201192Sed continue; 204201192Sed num_users++; 205201146Sed } 206201192Sed endutxent(); 207201192Sed 208201146Sed return(&num_users); 2092337Scsgr} 2102337Scsgr 2112337Scsgrstatic utmparr * 212201146Seddo_names_1(void) 2132337Scsgr{ 214201146Sed utmpidlearr *utidle; 215201146Sed static utmparr ut; 216201146Sed unsigned int i; 2178870Srgrimes 218201146Sed bzero((char *)&ut, sizeof(ut)); 2198870Srgrimes 220201146Sed utidle = do_names_2(); 221201146Sed if (utidle) { 222201146Sed ut.utmparr_len = utidle->utmpidlearr_len; 223201146Sed ut.utmparr_val = &old_utmp[0]; 224201146Sed for (i = 0; i < ut.utmparr_len; i++) 225201146Sed bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i], 226201146Sed sizeof(old_utmp[0])); 2278870Srgrimes 228201146Sed } 2298870Srgrimes 230201146Sed return(&ut); 2312337Scsgr} 2322337Scsgr 2332337Scsgrutmpidlearr * 234201146Sedrusersproc_names_2_svc(void *argp __unused, struct svc_req *rqstp __unused) 2352337Scsgr{ 236201146Sed 237201146Sed return (do_names_2()); 2382337Scsgr} 2392337Scsgr 2402337Scsgrutmpidlearr * 241201146Sedrusersproc_allnames_2_svc(void *argp __unused, struct svc_req *rqstp __unused) 2422337Scsgr{ 243201146Sed 244201146Sed return (do_names_2()); 2452337Scsgr} 2462337Scsgr 2472337Scsgrutmparr * 248201146Sedrusersproc_names_1_svc(void *argp __unused, struct svc_req *rqstp __unused) 2492337Scsgr{ 250201146Sed 251201146Sed return (do_names_1()); 2522337Scsgr} 2532337Scsgr 2542337Scsgrutmparr * 255201146Sedrusersproc_allnames_1_svc(void *argp __unused, struct svc_req *rqstp __unused) 2562337Scsgr{ 257201146Sed 258201146Sed return (do_names_1()); 2592337Scsgr} 2602337Scsgr 261201146Sedtypedef void *(*rusersproc_t)(void *, struct svc_req *); 262201146Sed 2632337Scsgrvoid 26490336Simprusers_service(struct svc_req *rqstp, SVCXPRT *transp) 2652337Scsgr{ 2662337Scsgr union { 2672337Scsgr int fill; 2682337Scsgr } argument; 2692337Scsgr char *result; 270201146Sed xdrproc_t xdr_argument, xdr_result; 271201146Sed rusersproc_t local; 2722337Scsgr 2732337Scsgr switch (rqstp->rq_proc) { 2742337Scsgr case NULLPROC: 27595658Sdes (void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL); 2762337Scsgr goto leave; 2772337Scsgr 2782337Scsgr case RUSERSPROC_NUM: 279201146Sed xdr_argument = (xdrproc_t)xdr_void; 280201146Sed xdr_result = (xdrproc_t)xdr_int; 281201146Sed local = (rusersproc_t)rusers_num; 2822337Scsgr break; 2832337Scsgr 2842337Scsgr case RUSERSPROC_NAMES: 285201146Sed xdr_argument = (xdrproc_t)xdr_void; 286201146Sed xdr_result = (xdrproc_t)xdr_utmpidlearr; 287201146Sed switch (rqstp->rq_vers) { 288201146Sed case RUSERSVERS_ORIG: 289201146Sed local = (rusersproc_t)rusersproc_names_1_svc; 290201146Sed break; 291201146Sed case RUSERSVERS_IDLE: 292201146Sed local = (rusersproc_t)rusersproc_names_2_svc; 293201146Sed break; 294201146Sed default: 295201146Sed svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); 296201146Sed goto leave; 297201146Sed /*NOTREACHED*/ 298201146Sed } 2992337Scsgr break; 3002337Scsgr 3012337Scsgr case RUSERSPROC_ALLNAMES: 302201146Sed xdr_argument = (xdrproc_t)xdr_void; 303201146Sed xdr_result = (xdrproc_t)xdr_utmpidlearr; 304201146Sed switch (rqstp->rq_vers) { 305201146Sed case RUSERSVERS_ORIG: 306201146Sed local = (rusersproc_t)rusersproc_allnames_1_svc; 307201146Sed break; 308201146Sed case RUSERSVERS_IDLE: 309201146Sed local = (rusersproc_t)rusersproc_allnames_2_svc; 310201146Sed break; 311201146Sed default: 312201146Sed svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); 313201146Sed goto leave; 314201146Sed /*NOTREACHED*/ 315201146Sed } 3162337Scsgr break; 3172337Scsgr 3182337Scsgr default: 3192337Scsgr svcerr_noproc(transp); 3202337Scsgr goto leave; 3212337Scsgr } 32295658Sdes bzero(&argument, sizeof(argument)); 32395658Sdes if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) { 3242337Scsgr svcerr_decode(transp); 3252337Scsgr goto leave; 3262337Scsgr } 3272337Scsgr result = (*local)(&argument, rqstp); 32895658Sdes if (result != NULL && 32995658Sdes !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) { 3302337Scsgr svcerr_systemerr(transp); 3312337Scsgr } 33295658Sdes if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, &argument)) { 33332312Scharnier syslog(LOG_ERR, "unable to free arguments"); 33432312Scharnier exit(1); 33532312Scharnier } 3362337Scsgrleave: 337201146Sed if (from_inetd) 338201146Sed exit(0); 3392337Scsgr} 340