12345Scsgr/*- 22345Scsgr * Copyright (c) 1993, John Brezak 32345Scsgr * All rights reserved. 42345Scsgr * 52345Scsgr * Redistribution and use in source and binary forms, with or without 62345Scsgr * modification, are permitted provided that the following conditions 72345Scsgr * are met: 82345Scsgr * 1. Redistributions of source code must retain the above copyright 92345Scsgr * notice, this list of conditions and the following disclaimer. 102345Scsgr * 2. Redistributions in binary form must reproduce the above copyright 112345Scsgr * notice, this list of conditions and the following disclaimer in the 122345Scsgr * documentation and/or other materials provided with the distribution. 132345Scsgr * 3. All advertising materials mentioning features or use of this software 142345Scsgr * must display the following acknowledgement: 152345Scsgr * This product includes software developed by the University of 162345Scsgr * California, Berkeley and its contributors. 172345Scsgr * 4. Neither the name of the University nor the names of its contributors 182345Scsgr * may be used to endorse or promote products derived from this software 192345Scsgr * without specific prior written permission. 202345Scsgr * 212345Scsgr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 222345Scsgr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 232345Scsgr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 242345Scsgr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 252345Scsgr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 262345Scsgr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 272345Scsgr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 282345Scsgr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 292345Scsgr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 302345Scsgr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 312345Scsgr * SUCH DAMAGE. 322345Scsgr */ 332345Scsgr 3495619Smarkm#include <sys/cdefs.h> 352345Scsgr 3695619Smarkm__FBSDID("$FreeBSD$"); 3795619Smarkm 382345Scsgr#include <sys/types.h> 392345Scsgr#include <sys/socket.h> 4095619Smarkm 4178455Smikeh#include <rpc/rpc.h> 4278455Smikeh#include <rpc/pmap_clnt.h> 4378455Smikeh#include <rpcsvc/rnusers.h> 4495619Smarkm 4578455Smikeh#include <arpa/inet.h> 4695619Smarkm 4727976Scharnier#include <err.h> 482345Scsgr#include <netdb.h> 492345Scsgr#include <stdio.h> 5027976Scharnier#include <stdlib.h> 5195619Smarkm#include <string.h> 52129459Sdwmalone#include <timeconv.h> 5327976Scharnier#include <unistd.h> 542345Scsgr 5578455Smikeh#define MAX_INT 0x7fffffff 5678455Smikeh#define HOST_WIDTH 20 5778455Smikeh#define LINE_WIDTH 15 582345Scsgr 59227179Sedstatic int longopt; 60227179Sedstatic int allopt; 612345Scsgr 62227179Sedstatic struct host_list { 6378455Smikeh struct host_list *next; 6478455Smikeh struct in_addr addr; 652345Scsgr} *hosts; 662345Scsgr 6795619Smarkmstatic int 6827976Scharniersearch_host(struct in_addr addr) 692345Scsgr{ 702345Scsgr struct host_list *hp; 718874Srgrimes 7278455Smikeh if (hosts == NULL) 7378455Smikeh return (0); 742345Scsgr 752345Scsgr for (hp = hosts; hp != NULL; hp = hp->next) { 762345Scsgr if (hp->addr.s_addr == addr.s_addr) 7778455Smikeh return (1); 782345Scsgr } 7978455Smikeh return (0); 802345Scsgr} 812345Scsgr 8295619Smarkmstatic void 8327976Scharnierremember_host(struct in_addr addr) 842345Scsgr{ 852345Scsgr struct host_list *hp; 862345Scsgr 8778455Smikeh if ((hp = (struct host_list *)malloc(sizeof(struct host_list))) == NULL) 8827976Scharnier errx(1, "no memory"); 892345Scsgr hp->addr.s_addr = addr.s_addr; 902345Scsgr hp->next = hosts; 912345Scsgr hosts = hp; 922345Scsgr} 932345Scsgr 9495619Smarkmstatic int 9574462Salfredrusers_reply(caddr_t replyp, struct sockaddr_in *raddrp) 962345Scsgr{ 9795619Smarkm u_int x; 9895619Smarkm int idle; 9978455Smikeh char date[32], idle_time[64], remote[64]; 10078455Smikeh struct hostent *hp; 101129459Sdwmalone utmpidlearr *up, u; 10278455Smikeh char *host; 10378455Smikeh int days, hours, minutes, seconds; 1048874Srgrimes 105129459Sdwmalone up = &u; 106129459Sdwmalone memcpy(up, replyp, sizeof(*up)); 1072345Scsgr if (search_host(raddrp->sin_addr)) 10878455Smikeh return (0); 1092345Scsgr 11078455Smikeh if (!allopt && up->utmpidlearr_len == 0) 11178455Smikeh return (0); 1128874Srgrimes 11378455Smikeh hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr, 11478455Smikeh sizeof(struct in_addr), AF_INET); 11578455Smikeh if (hp != NULL) 11678455Smikeh host = hp->h_name; 11778455Smikeh else 11878455Smikeh host = inet_ntoa(raddrp->sin_addr); 1198874Srgrimes 12078455Smikeh if (!longopt) 12178455Smikeh printf("%-*s ", HOST_WIDTH, host); 1228874Srgrimes 12378455Smikeh for (x = 0; x < up->utmpidlearr_len; x++) { 12489572Sdillon time_t t = _int_to_time(up->utmpidlearr_val[x].ui_utmp.ut_time); 12585638Sdillon strncpy(date, &(ctime(&t)[4]), sizeof(date) - 1); 1262345Scsgr 12778455Smikeh idle = up->utmpidlearr_val[x].ui_idle; 12878455Smikeh sprintf(idle_time, " :%02d", idle); 12978455Smikeh if (idle == MAX_INT) 13078455Smikeh strcpy(idle_time, "??"); 13178455Smikeh else if (idle == 0) 13278455Smikeh strcpy(idle_time, ""); 13378455Smikeh else { 13478455Smikeh seconds = idle; 13578455Smikeh days = seconds / (60 * 60 * 24); 13678455Smikeh seconds %= (60 * 60 * 24); 13778455Smikeh hours = seconds / (60 * 60); 13878455Smikeh seconds %= (60 * 60); 13978455Smikeh minutes = seconds / 60; 14078455Smikeh seconds %= 60; 14178455Smikeh if (idle > 60) 14278455Smikeh sprintf(idle_time, "%d:%02d", minutes, seconds); 14378455Smikeh if (idle >= (60 * 60)) 14478455Smikeh sprintf(idle_time, "%d:%02d:%02d", 14578455Smikeh hours, minutes, seconds); 14678455Smikeh if (idle >= (24 * 60 * 60)) 14778455Smikeh sprintf(idle_time, "%d days, %d:%02d:%02d", 14878455Smikeh days, hours, minutes, seconds); 14978455Smikeh } 1502345Scsgr 15178455Smikeh strncpy(remote, up->utmpidlearr_val[x].ui_utmp.ut_host, 15278455Smikeh sizeof(remote) - 1); 15378455Smikeh if (strlen(remote) != 0) 15478455Smikeh sprintf(remote, "(%.16s)", 15578455Smikeh up->utmpidlearr_val[x].ui_utmp.ut_host); 1562345Scsgr 15778455Smikeh if (longopt) 15878455Smikeh printf("%-8.8s %*s:%-*.*s %-12.12s %6s %.18s\n", 15978455Smikeh up->utmpidlearr_val[x].ui_utmp.ut_name, 16078455Smikeh HOST_WIDTH, host, LINE_WIDTH, LINE_WIDTH, 16178455Smikeh up->utmpidlearr_val[x].ui_utmp.ut_line, date, 16278455Smikeh idle_time, remote ); 16378455Smikeh else 16478455Smikeh printf("%s ", 16578455Smikeh up->utmpidlearr_val[x].ui_utmp.ut_name); 16678455Smikeh } 16778455Smikeh if (!longopt) 16878455Smikeh putchar('\n'); 1698874Srgrimes 1702345Scsgr remember_host(raddrp->sin_addr); 17178455Smikeh return (0); 1722345Scsgr} 1732345Scsgr 17495619Smarkmstatic void 1752345Scsgronehost(char *host) 1762345Scsgr{ 17778455Smikeh utmpidlearr up; 17878455Smikeh CLIENT *rusers_clnt; 17978455Smikeh struct sockaddr_in addr; 18078455Smikeh struct hostent *hp; 18178455Smikeh struct timeval tv; 1828874Srgrimes 18378455Smikeh hp = gethostbyname(host); 18478455Smikeh if (hp == NULL) 18578455Smikeh errx(1, "unknown host \"%s\"", host); 1862345Scsgr 18778455Smikeh rusers_clnt = clnt_create(host, RUSERSPROG, RUSERSVERS_IDLE, "udp"); 18878455Smikeh if (rusers_clnt == NULL) 18978455Smikeh errx(1, "%s", clnt_spcreateerror("")); 1902345Scsgr 1912345Scsgr bzero((char *)&up, sizeof(up)); 19278455Smikeh tv.tv_sec = 15; /* XXX ?? */ 19321094Speter tv.tv_usec = 0; 194121545Speter if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL, 195121545Speter (xdrproc_t)xdr_utmpidlearr, &up, tv) != RPC_SUCCESS) 19678455Smikeh errx(1, "%s", clnt_sperror(rusers_clnt, "")); 197129459Sdwmalone memcpy(&addr.sin_addr.s_addr, hp->h_addr, sizeof(addr.sin_addr.s_addr)); 19878455Smikeh rusers_reply((caddr_t)&up, &addr); 19978456Smikeh clnt_destroy(rusers_clnt); 2002345Scsgr} 2012345Scsgr 20295619Smarkmstatic void 20395619Smarkmallhosts(void) 2042345Scsgr{ 20527976Scharnier utmpidlearr up; 2062345Scsgr enum clnt_stat clnt_stat; 2072345Scsgr 2082345Scsgr bzero((char *)&up, sizeof(up)); 20978455Smikeh clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE, 210121545Speter RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL, 211121545Speter (xdrproc_t)xdr_utmpidlearr, (char *)&up, 212121545Speter (resultproc_t)rusers_reply); 21327976Scharnier if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) 21427976Scharnier errx(1, "%s", clnt_sperrno(clnt_stat)); 2152345Scsgr} 2162345Scsgr 21727976Scharnierstatic void 21895619Smarkmusage(void) 2192345Scsgr{ 22078455Smikeh 221146466Sru fprintf(stderr, "usage: rusers [-al] [host ...]\n"); 22278455Smikeh exit(1); 2232345Scsgr} 2242345Scsgr 22527976Scharnierint 2262345Scsgrmain(int argc, char *argv[]) 2272345Scsgr{ 22878455Smikeh int ch; 2298874Srgrimes 23078455Smikeh while ((ch = getopt(argc, argv, "al")) != -1) 23178455Smikeh switch (ch) { 23278455Smikeh case 'a': 23378455Smikeh allopt++; 23478455Smikeh break; 23578455Smikeh case 'l': 23678455Smikeh longopt++; 23778455Smikeh break; 23878455Smikeh default: 23978455Smikeh usage(); 24078455Smikeh /* NOTREACHED */ 24178455Smikeh } 2422345Scsgr 24378455Smikeh setlinebuf(stdout); 2442345Scsgr if (argc == optind) 2452345Scsgr allhosts(); 2462345Scsgr else { 2472345Scsgr for (; optind < argc; optind++) 24878455Smikeh (void)onehost(argv[optind]); 2492345Scsgr } 25078455Smikeh exit(0); 2512345Scsgr} 252