Path: blob/main/libexec/rpc.rusersd/rusers_proc.c
105170 views
/*-1* SPDX-License-Identifier: BSD-3-Clause2*3* Copyright (c) 1993, John Brezak4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14* 3. Neither the name of the University nor the names of its contributors15* may be used to endorse or promote products derived from this software16* without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND19* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE22* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL23* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS24* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT26* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY27* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF28* SUCH DAMAGE.29*/3031#ifdef DEBUG32#include <errno.h>33#endif34#include <stdio.h>35#include <string.h>36#include <sys/param.h>37#include <sys/stat.h>38#include <stdlib.h>39#include <syslog.h>40#include <utmpx.h>41#ifdef XIDLE42#include <setjmp.h>43#include <X11/Xlib.h>44#include <X11/extensions/xidle.h>45#endif46#include <rpcsvc/rnusers.h>4748#include "extern.h"4950#ifndef _PATH_DEV51#define _PATH_DEV "/dev"52#endif5354static utmpidle utmp_idle[MAXUSERS];55static utmp old_utmp[MAXUSERS];56static struct utmpx utmp_list[MAXUSERS];5758#ifdef XIDLE59static Display *dpy;6061static jmp_buf openAbort;6263static void64abortOpen(void)65{66longjmp (openAbort, 1);67}6869XqueryIdle(char *display)70{71int first_event, first_error;72Time IdleTime;7374(void) signal (SIGALRM, abortOpen);75(void) alarm ((unsigned) 10);76if (!setjmp (openAbort)) {77if (!(dpy= XOpenDisplay(display))) {78syslog(LOG_ERR, "Cannot open display %s", display);79return(-1);80}81if (XidleQueryExtension(dpy, &first_event, &first_error)) {82if (!XGetIdleTime(dpy, &IdleTime)) {83syslog(LOG_ERR, "%s: unable to get idle time", display);84return(-1);85}86} else {87syslog(LOG_ERR, "%s: Xidle extension not loaded", display);88return(-1);89}90XCloseDisplay(dpy);91} else {92syslog(LOG_ERR, "%s: server grabbed for over 10 seconds", display);93return(-1);94}95(void) signal (SIGALRM, SIG_DFL);96(void) alarm ((unsigned) 0);9798IdleTime /= 1000;99return((IdleTime + 30) / 60);100}101#endif102103static u_int104getidle(const char *tty, const char *display __unused)105{106struct stat st;107char ttyname[PATH_MAX];108time_t now;109u_long idle;110111/*112* If this is an X terminal or console, then try the113* XIdle extension114*/115#ifdef XIDLE116if (display && *display && (idle = XqueryIdle(display)) >= 0)117return(idle);118#endif119idle = 0;120if (*tty == 'X') {121u_long kbd_idle, mouse_idle;122#if !defined(__FreeBSD__)123kbd_idle = getidle("kbd", NULL);124#else125kbd_idle = getidle("vga", NULL);126#endif127mouse_idle = getidle("mouse", NULL);128idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle;129} else {130sprintf(ttyname, "%s/%s", _PATH_DEV, tty);131if (stat(ttyname, &st) < 0) {132#ifdef DEBUG133printf("%s: %s\n", ttyname, strerror(errno));134#endif135return(-1);136}137time(&now);138#ifdef DEBUG139printf("%s: now=%d atime=%d\n", ttyname, now,140st.st_atime);141#endif142idle = now - st.st_atime;143idle = (idle + 30) / 60; /* secs->mins */144}145146return(idle);147}148149static utmpidlearr *150do_names_2(void)151{152static utmpidlearr ut;153struct utmpx *usr;154int nusers = 0;155156memset(&ut, 0, sizeof(ut));157ut.utmpidlearr_val = &utmp_idle[0];158159setutxent();160while ((usr = getutxent()) != NULL && nusers < MAXUSERS) {161if (usr->ut_type != USER_PROCESS)162continue;163164memcpy(&utmp_list[nusers], usr, sizeof(*usr));165utmp_idle[nusers].ui_utmp.ut_time = usr->ut_tv.tv_sec;166utmp_idle[nusers].ui_idle =167getidle(usr->ut_line, usr->ut_host);168utmp_idle[nusers].ui_utmp.ut_line =169utmp_list[nusers].ut_line;170utmp_idle[nusers].ui_utmp.ut_name =171utmp_list[nusers].ut_user;172utmp_idle[nusers].ui_utmp.ut_host =173utmp_list[nusers].ut_host;174175nusers++;176}177endutxent();178179ut.utmpidlearr_len = nusers;180return(&ut);181}182183static int *184rusers_num(void *argp __unused, struct svc_req *rqstp __unused)185{186static int num_users = 0;187struct utmpx *usr;188189setutxent();190while ((usr = getutxent()) != NULL) {191if (usr->ut_type != USER_PROCESS)192continue;193num_users++;194}195endutxent();196197return(&num_users);198}199200static utmparr *201do_names_1(void)202{203utmpidlearr *utidle;204static utmparr ut;205unsigned int i;206207bzero((char *)&ut, sizeof(ut));208209utidle = do_names_2();210if (utidle) {211ut.utmparr_len = utidle->utmpidlearr_len;212ut.utmparr_val = &old_utmp[0];213for (i = 0; i < ut.utmparr_len; i++)214bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i],215sizeof(old_utmp[0]));216217}218219return(&ut);220}221222utmpidlearr *223rusersproc_names_2_svc(void *argp __unused, struct svc_req *rqstp __unused)224{225226return (do_names_2());227}228229utmpidlearr *230rusersproc_allnames_2_svc(void *argp __unused, struct svc_req *rqstp __unused)231{232233return (do_names_2());234}235236utmparr *237rusersproc_names_1_svc(void *argp __unused, struct svc_req *rqstp __unused)238{239240return (do_names_1());241}242243utmparr *244rusersproc_allnames_1_svc(void *argp __unused, struct svc_req *rqstp __unused)245{246247return (do_names_1());248}249250typedef void *(*rusersproc_t)(void *, struct svc_req *);251252void253rusers_service(struct svc_req *rqstp, SVCXPRT *transp)254{255union {256int fill;257} argument;258char *result;259xdrproc_t xdr_argument, xdr_result;260rusersproc_t local;261262switch (rqstp->rq_proc) {263case NULLPROC:264(void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);265goto leave;266267case RUSERSPROC_NUM:268xdr_argument = (xdrproc_t)xdr_void;269xdr_result = (xdrproc_t)xdr_int;270local = (rusersproc_t)rusers_num;271break;272273case RUSERSPROC_NAMES:274xdr_argument = (xdrproc_t)xdr_void;275xdr_result = (xdrproc_t)xdr_utmpidlearr;276switch (rqstp->rq_vers) {277case RUSERSVERS_ORIG:278local = (rusersproc_t)rusersproc_names_1_svc;279break;280case RUSERSVERS_IDLE:281local = (rusersproc_t)rusersproc_names_2_svc;282break;283default:284svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);285goto leave;286/*NOTREACHED*/287}288break;289290case RUSERSPROC_ALLNAMES:291xdr_argument = (xdrproc_t)xdr_void;292xdr_result = (xdrproc_t)xdr_utmpidlearr;293switch (rqstp->rq_vers) {294case RUSERSVERS_ORIG:295local = (rusersproc_t)rusersproc_allnames_1_svc;296break;297case RUSERSVERS_IDLE:298local = (rusersproc_t)rusersproc_allnames_2_svc;299break;300default:301svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE);302goto leave;303/*NOTREACHED*/304}305break;306307default:308svcerr_noproc(transp);309goto leave;310}311bzero(&argument, sizeof(argument));312if (!svc_getargs(transp, (xdrproc_t)xdr_argument, &argument)) {313svcerr_decode(transp);314goto leave;315}316result = (*local)(&argument, rqstp);317if (result != NULL &&318!svc_sendreply(transp, (xdrproc_t)xdr_result, result)) {319svcerr_systemerr(transp);320}321if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, &argument)) {322syslog(LOG_ERR, "unable to free arguments");323exit(1);324}325leave:326if (from_inetd)327exit(0);328}329330331