From 825be05ec41b2eb1c5f88b495d1be6b6d87f8e14 Mon Sep 17 00:00:00 2001 From: Geoff Rehmet Date: Sun, 28 Aug 1994 14:53:45 +0000 Subject: [PATCH] rusersd from FreeBSD 1.1.5.1 Reviewed by: geoff. Submitted by: John Brezak --- libexec/rpc.rusersd/Makefile | 16 ++ libexec/rpc.rusersd/rpc.rusersd.8 | 64 +++++ libexec/rpc.rusersd/rusers_proc.c | 390 ++++++++++++++++++++++++++++++ libexec/rpc.rusersd/rusersd.c | 108 +++++++++ 4 files changed, 578 insertions(+) create mode 100644 libexec/rpc.rusersd/Makefile create mode 100644 libexec/rpc.rusersd/rpc.rusersd.8 create mode 100644 libexec/rpc.rusersd/rusers_proc.c create mode 100644 libexec/rpc.rusersd/rusersd.c diff --git a/libexec/rpc.rusersd/Makefile b/libexec/rpc.rusersd/Makefile new file mode 100644 index 000000000000..1c689397232d --- /dev/null +++ b/libexec/rpc.rusersd/Makefile @@ -0,0 +1,16 @@ +# $Id: Makefile,v 1.2 1993/11/10 03:46:04 smace Exp $ + +PROG = rpc.rusersd +SRCS = rusersd.c rusers_proc.c +MAN8 = rpc.rusersd.8 + +DPADD= ${LIBRPCSVC} ${LIBUTIL} +LDADD= -lrpcsvc -lutil + +.if exists(/usr/include/X11/extensions/xidle.h) +CFLAGS+= -DXIDLE +LDADD+= -L/usr/X386/lib -lXext -lX11 +.endif + + +.include diff --git a/libexec/rpc.rusersd/rpc.rusersd.8 b/libexec/rpc.rusersd/rpc.rusersd.8 new file mode 100644 index 000000000000..15947ac8bfbb --- /dev/null +++ b/libexec/rpc.rusersd/rpc.rusersd.8 @@ -0,0 +1,64 @@ +.\" -*- nroff -*- +.\" +.\" Copyright (c) 1985, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: rpc.rusersd.8,v 1.1 1993/09/16 00:34:43 jtc Exp $ +.\" +.Dd June 7, 1993 +.Dt RPC.RUSERSD 8 +.Os BSD 4.3 +.Sh NAME +.Nm rpc.rusersd +.Nd logged in users server +.Sh SYNOPSIS +.Nm /usr/libexec/rpc.rusersd +.Sh DESCRIPTION +.Nm rpc.rusersd +is a server which returns information about users +currently logged in to the system. +.Pp +The currently logged in users are queried using the +.Xr rusers 1 +command. +The +.Nm rpc.rusersd +daemon is normally invoked by +.Xr inetd 8 . +.Pp +.Nm rpc.rusersd +uses an RPC protocol defined in +.Pa /usr/include/rpcsvc/rnusers.x . +.Sh SEE ALSO +.Xr rusers 1 , +.Xr who 1 , +.Xr w 1 , +.Xr inetd 8 diff --git a/libexec/rpc.rusersd/rusers_proc.c b/libexec/rpc.rusersd/rusers_proc.c new file mode 100644 index 000000000000..ab9d6a0c53f3 --- /dev/null +++ b/libexec/rpc.rusersd/rusers_proc.c @@ -0,0 +1,390 @@ +/*- + * Copyright (c) 1993, John Brezak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$Id: rusers_proc.c,v 1.2 1994/03/06 02:07:58 jkh Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef XIDLE +#include +#include +#include +#endif +#define utmp rutmp +#include +#undef utmp + +#define IGNOREUSER "sleeper" + +#ifdef OSF +#define _PATH_UTMP UTMP_FILE +#endif + +#ifndef _PATH_UTMP +#define _PATH_UTMP "/etc/utmp" +#endif + +#ifndef _PATH_DEV +#define _PATH_DEV "/dev" +#endif + +#ifndef UT_LINESIZE +#define UT_LINESIZE sizeof(((struct utmp *)0)->ut_line) +#endif +#ifndef UT_NAMESIZE +#define UT_NAMESIZE sizeof(((struct utmp *)0)->ut_name) +#endif +#ifndef UT_HOSTSIZE +#define UT_HOSTSIZE sizeof(((struct utmp *)0)->ut_host) +#endif + +typedef char ut_line_t[UT_LINESIZE+1]; +typedef char ut_name_t[UT_NAMESIZE+1]; +typedef char ut_host_t[UT_HOSTSIZE+1]; + +utmpidle utmp_idle[MAXUSERS]; +rutmp old_utmp[MAXUSERS]; +ut_line_t line[MAXUSERS]; +ut_name_t name[MAXUSERS]; +ut_host_t host[MAXUSERS]; + +extern int from_inetd; + +FILE *ufp; + +#ifdef XIDLE +Display *dpy; + +static jmp_buf openAbort; + +static void +abortOpen () +{ + longjmp (openAbort, 1); +} + +XqueryIdle(char *display) +{ + int first_event, first_error; + Time IdleTime; + + (void) signal (SIGALRM, abortOpen); + (void) alarm ((unsigned) 10); + if (!setjmp (openAbort)) { + if (!(dpy= XOpenDisplay(display))) { + syslog(LOG_ERR, "Cannot open display %s", display); + return(-1); + } + if (XidleQueryExtension(dpy, &first_event, &first_error)) { + if (!XGetIdleTime(dpy, &IdleTime)) { + syslog(LOG_ERR, "%s: Unable to get idle time.", display); + return(-1); + } + } + else { + syslog(LOG_ERR, "%s: Xidle extension not loaded.", display); + return(-1); + } + XCloseDisplay(dpy); + } + else { + syslog(LOG_ERR, "%s: Server grabbed for over 10 seconds.", display); + return(-1); + } + (void) signal (SIGALRM, SIG_DFL); + (void) alarm ((unsigned) 0); + + IdleTime /= 1000; + return((IdleTime + 30) / 60); +} +#endif + +static u_int +getidle(char *tty, char *display) +{ + struct stat st; + char devname[PATH_MAX]; + time_t now; + u_long idle; + + /* + * If this is an X terminal or console, then try the + * XIdle extension + */ +#ifdef XIDLE + if (display && *display && (idle = XqueryIdle(display)) >= 0) + return(idle); +#endif + idle = 0; + if (*tty == 'X') { + u_long kbd_idle, mouse_idle; +#if !defined(__386BSD__) + kbd_idle = getidle("kbd", NULL); +#else + kbd_idle = getidle("vga", NULL); +#endif + mouse_idle = getidle("mouse", NULL); + idle = (kbd_idle < mouse_idle)?kbd_idle:mouse_idle; + } + else { + sprintf(devname, "%s/%s", _PATH_DEV, tty); + if (stat(devname, &st) < 0) { +#ifdef DEBUG + printf("%s: %s\n", devname, strerror(errno)); +#endif + return(-1); + } + time(&now); +#ifdef DEBUG + printf("%s: now=%d atime=%d\n", devname, now, + st.st_atime); +#endif + idle = now - st.st_atime; + idle = (idle + 30) / 60; /* secs->mins */ + } + if (idle < 0) idle = 0; + + return(idle); +} + +static utmpidlearr * +do_names_2(int all) +{ + static utmpidlearr ut; + struct utmp usr; + int nusers = 0; + + bzero((char *)&ut, sizeof(ut)); + ut.utmpidlearr_val = &utmp_idle[0]; + + ufp = fopen(_PATH_UTMP, "r"); + if (!ufp) { + syslog(LOG_ERR, "%m"); + return(&ut); + } + + /* only entries with both name and line fields */ + while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1 && + nusers < MAXUSERS) + if (*usr.ut_name && *usr.ut_line && + strncmp(usr.ut_name, IGNOREUSER, + sizeof(usr.ut_name)) +#ifdef OSF + && usr.ut_type == USER_PROCESS +#endif + ) { + utmp_idle[nusers].ui_utmp.ut_time = + usr.ut_time; + utmp_idle[nusers].ui_idle = + getidle(usr.ut_line, usr.ut_host); + utmp_idle[nusers].ui_utmp.ut_line = line[nusers]; + strncpy(line[nusers], usr.ut_line, UT_LINESIZE); + utmp_idle[nusers].ui_utmp.ut_name = name[nusers]; + strncpy(name[nusers], usr.ut_name, UT_NAMESIZE); + utmp_idle[nusers].ui_utmp.ut_host = host[nusers]; + strncpy(host[nusers], usr.ut_host, UT_HOSTSIZE); + + /* Make sure entries are NUL terminated */ + line[nusers][UT_LINESIZE] = + name[nusers][UT_NAMESIZE] = + host[nusers][UT_HOSTSIZE] = '\0'; + nusers++; + } + + ut.utmpidlearr_len = nusers; + fclose(ufp); + return(&ut); +} + +int * +rusers_num() +{ + int num_users = 0; + struct utmp usr; + + ufp = fopen(_PATH_UTMP, "r"); + if (!ufp) { + syslog(LOG_ERR, "%m"); + return(0); + } + + /* only entries with both name and line fields */ + while (fread((char *)&usr, sizeof(usr), 1, ufp) == 1) + if (*usr.ut_name && *usr.ut_line && + strncmp(usr.ut_name, IGNOREUSER, + sizeof(usr.ut_name)) +#ifdef OSF + && usr.ut_type == USER_PROCESS +#endif + ) { + num_users++; + } + + fclose(ufp); + return(&num_users); +} + +static utmparr * +do_names_1(int all) +{ + utmpidlearr *utidle; + utmparr ut; + int i; + + bzero((char *)&ut, sizeof(ut)); + + utidle = do_names_2(all); + if (utidle) { + ut.utmparr_len = utidle->utmpidlearr_len; + ut.utmparr_val = &old_utmp[0]; + for (i = 0; i < ut.utmparr_len; i++) + bcopy(&utmp_idle[i].ui_utmp, &old_utmp[i], + sizeof(old_utmp[0])); + + } + + return(&ut); +} + +utmpidlearr * +rusersproc_names_2() +{ + return(do_names_2(0)); +} + +utmpidlearr * +rusersproc_allnames_2() +{ + return(do_names_2(1)); +} + +utmparr * +rusersproc_names_1() +{ + return(do_names_1(0)); +} + +utmparr * +rusersproc_allnames_1() +{ + return(do_names_1(1)); +} + +void +rusers_service(rqstp, transp) + struct svc_req *rqstp; + SVCXPRT *transp; +{ + union { + int fill; + } argument; + char *result; + bool_t (*xdr_argument)(), (*xdr_result)(); + char *(*local)(); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void)svc_sendreply(transp, xdr_void, (char *)NULL); + goto leave; + + case RUSERSPROC_NUM: + xdr_argument = xdr_void; + xdr_result = xdr_int; + local = (char *(*)()) rusers_num; + break; + + case RUSERSPROC_NAMES: + xdr_argument = xdr_void; + xdr_result = xdr_utmpidlearr; + switch (rqstp->rq_vers) { + case RUSERSVERS_ORIG: + local = (char *(*)()) rusersproc_names_1; + break; + case RUSERSVERS_IDLE: + local = (char *(*)()) rusersproc_names_2; + break; + default: + svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); + goto leave; + /*NOTREACHED*/ + } + break; + + case RUSERSPROC_ALLNAMES: + xdr_argument = xdr_void; + xdr_result = xdr_utmpidlearr; + switch (rqstp->rq_vers) { + case RUSERSVERS_ORIG: + local = (char *(*)()) rusersproc_allnames_1; + break; + case RUSERSVERS_IDLE: + local = (char *(*)()) rusersproc_allnames_2; + break; + default: + svcerr_progvers(transp, RUSERSVERS_ORIG, RUSERSVERS_IDLE); + goto leave; + /*NOTREACHED*/ + } + break; + + default: + svcerr_noproc(transp); + goto leave; + } + bzero((char *)&argument, sizeof(argument)); + if (!svc_getargs(transp, xdr_argument, &argument)) { + svcerr_decode(transp); + goto leave; + } + result = (*local)(&argument, rqstp); + if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, xdr_argument, &argument)) { + (void)fprintf(stderr, "unable to free arguments\n"); + exit(1); + } +leave: + if (from_inetd) + exit(0); +} diff --git a/libexec/rpc.rusersd/rusersd.c b/libexec/rpc.rusersd/rusersd.c new file mode 100644 index 000000000000..525a57525d07 --- /dev/null +++ b/libexec/rpc.rusersd/rusersd.c @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 1993, John Brezak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$Id: rusersd.c,v 1.1 1993/09/16 00:34:49 jtc Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#define utmp rutmp +#include +#undef utmp + +extern void rusers_service(); + +int from_inetd = 1; + +void +cleanup() +{ + (void) pmap_unset(RUSERSPROG, RUSERSVERS_IDLE); + (void) pmap_unset(RUSERSPROG, RUSERSVERS_ORIG); + exit(0); +} + +main(argc, argv) + int argc; + char *argv[]; +{ + SVCXPRT *transp; + int sock = 0; + int proto = 0; + struct sockaddr_in from; + int fromlen; + + /* + * See if inetd started us + */ + if (getsockname(0, (struct sockaddr *)&from, &fromlen) < 0) { + from_inetd = 0; + sock = RPC_ANYSOCK; + proto = IPPROTO_UDP; + } + + if (!from_inetd) { + daemon(0, 0); + + (void) pmap_unset(RUSERSPROG, RUSERSVERS_IDLE); + (void) pmap_unset(RUSERSPROG, RUSERSVERS_ORIG); + + (void) signal(SIGINT, cleanup); + (void) signal(SIGTERM, cleanup); + (void) signal(SIGHUP, cleanup); + } + + openlog("rpc.rusersd", LOG_CONS|LOG_PID, LOG_DAEMON); + + transp = svcudp_create(sock); + if (transp == NULL) { + syslog(LOG_ERR, "cannot create udp service."); + exit(1); + } + if (!svc_register(transp, RUSERSPROG, RUSERSVERS_IDLE, rusers_service, proto)) { + syslog(LOG_ERR, "unable to register (RUSERSPROG, RUSERSVERS_IDLE, %s).", proto?"udp":"(inetd)"); + exit(1); + } + + if (!svc_register(transp, RUSERSPROG, RUSERSVERS_ORIG, rusers_service, proto)) { + syslog(LOG_ERR, "unable to register (RUSERSPROG, RUSERSVERS_ORIG, %s).", proto?"udp":"(inetd)"); + exit(1); + } + + svc_run(); + syslog(LOG_ERR, "svc_run returned"); + exit(1); +}