rusers.c revision 74462
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
342345Scsgr#ifndef lint
3527976Scharnierstatic const char rcsid[] =
3650477Speter  "$FreeBSD: head/usr.bin/rusers/rusers.c 74462 2001-03-19 12:50:13Z alfred $";
372345Scsgr#endif /* not lint */
382345Scsgr
392345Scsgr#include <sys/types.h>
402345Scsgr#include <sys/param.h>
412345Scsgr#include <sys/socket.h>
4227976Scharnier#include <err.h>
432345Scsgr#include <netdb.h>
442345Scsgr#include <stdio.h>
4527976Scharnier#include <stdlib.h>
462345Scsgr#include <strings.h>
4727976Scharnier#include <unistd.h>
482345Scsgr#include <rpc/rpc.h>
4927976Scharnier#include <rpc/pmap_clnt.h>
502345Scsgr#include <arpa/inet.h>
512345Scsgr#include <rpcsvc/rnusers.h>
522345Scsgr
532345Scsgr#define MAX_INT 0x7fffffff
542345Scsgr#define HOST_WIDTH 20
552345Scsgr#define LINE_WIDTH 15
562345Scsgr
572345Scsgrint longopt;
582345Scsgrint allopt;
592345Scsgr
602345Scsgrstruct host_list {
612345Scsgr	struct host_list *next;
622345Scsgr	struct in_addr addr;
632345Scsgr} *hosts;
642345Scsgr
6527976Scharnierint
6627976Scharniersearch_host(struct in_addr addr)
672345Scsgr{
682345Scsgr	struct host_list *hp;
698874Srgrimes
702345Scsgr	if (!hosts)
712345Scsgr		return(0);
722345Scsgr
732345Scsgr	for (hp = hosts; hp != NULL; hp = hp->next) {
742345Scsgr		if (hp->addr.s_addr == addr.s_addr)
752345Scsgr			return(1);
762345Scsgr	}
772345Scsgr	return(0);
782345Scsgr}
792345Scsgr
8027976Scharniervoid
8127976Scharnierremember_host(struct in_addr addr)
822345Scsgr{
832345Scsgr	struct host_list *hp;
842345Scsgr
8527976Scharnier	if (!(hp = (struct host_list *)malloc(sizeof(struct host_list))))
8627976Scharnier		errx(1, "no memory");
872345Scsgr	hp->addr.s_addr = addr.s_addr;
882345Scsgr	hp->next = hosts;
892345Scsgr	hosts = hp;
902345Scsgr}
912345Scsgr
9227976Scharnierint
9374462Salfredrusers_reply(caddr_t replyp, struct sockaddr_in *raddrp)
942345Scsgr{
952345Scsgr        int x, idle;
962345Scsgr        char date[32], idle_time[64], remote[64];
972345Scsgr        struct hostent *hp;
982345Scsgr        utmpidlearr *up = (utmpidlearr *)replyp;
992345Scsgr        char *host;
1002345Scsgr        int days, hours, minutes, seconds;
1018874Srgrimes
1022345Scsgr	if (search_host(raddrp->sin_addr))
1032345Scsgr		return(0);
1042345Scsgr
1052345Scsgr        if (!allopt && !up->utmpidlearr_len)
1062345Scsgr                return(0);
1078874Srgrimes
1082345Scsgr        hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
1092345Scsgr                           sizeof(struct in_addr), AF_INET);
1102345Scsgr        if (hp)
1112345Scsgr                host = hp->h_name;
1122345Scsgr        else
1132345Scsgr                host = inet_ntoa(raddrp->sin_addr);
1148874Srgrimes
1152345Scsgr        if (!longopt)
1162345Scsgr                printf("%-*s ", HOST_WIDTH, host);
1178874Srgrimes
1182345Scsgr        for (x = 0; x < up->utmpidlearr_len; x++) {
1192345Scsgr                strncpy(date,
1202345Scsgr                        &(ctime((time_t *)&(up->utmpidlearr_val[x].ui_utmp.ut_time))[4]),
1212345Scsgr                        sizeof(date)-1);
1222345Scsgr
1232345Scsgr                idle = up->utmpidlearr_val[x].ui_idle;
1242345Scsgr                sprintf(idle_time, "  :%02d", idle);
1252345Scsgr                if (idle == MAX_INT)
1262345Scsgr                        strcpy(idle_time, "??");
1272345Scsgr                else if (idle == 0)
1282345Scsgr                        strcpy(idle_time, "");
1292345Scsgr                else {
1302345Scsgr                        seconds = idle;
1312345Scsgr                        days = seconds/(60*60*24);
1322345Scsgr                        seconds %= (60*60*24);
1332345Scsgr                        hours = seconds/(60*60);
1342345Scsgr                        seconds %= (60*60);
1352345Scsgr                        minutes = seconds/60;
1362345Scsgr                        seconds %= 60;
1372345Scsgr                        if (idle > 60)
1382345Scsgr                                sprintf(idle_time, "%d:%02d",
1392345Scsgr                                        minutes, seconds);
1402345Scsgr                        if (idle >= (60*60))
1412345Scsgr                                sprintf(idle_time, "%d:%02d:%02d",
1422345Scsgr                                        hours, minutes, seconds);
1432345Scsgr                        if (idle >= (24*60*60))
1442345Scsgr                                sprintf(idle_time, "%d days, %d:%02d:%02d",
1452345Scsgr                                        days, hours, minutes, seconds);
1462345Scsgr                }
1472345Scsgr
1482345Scsgr                strncpy(remote, up->utmpidlearr_val[x].ui_utmp.ut_host, sizeof(remote)-1);
1492345Scsgr                if (strlen(remote) != 0)
1502345Scsgr                        sprintf(remote, "(%.16s)", up->utmpidlearr_val[x].ui_utmp.ut_host);
1512345Scsgr
1522345Scsgr                if (longopt)
1532345Scsgr                        printf("%-8.8s %*s:%-*.*s %-12.12s  %6s %.18s\n",
1542345Scsgr                               up->utmpidlearr_val[x].ui_utmp.ut_name,
1552345Scsgr                               HOST_WIDTH, host,
1562345Scsgr                               LINE_WIDTH, LINE_WIDTH, up->utmpidlearr_val[x].ui_utmp.ut_line,
1572345Scsgr                               date,
1582345Scsgr                               idle_time,
1592345Scsgr                               remote
1602345Scsgr                               );
1612345Scsgr                else
1622345Scsgr                        printf("%s ",
1632345Scsgr                               up->utmpidlearr_val[x].ui_utmp.ut_name);
1642345Scsgr        }
1652345Scsgr        if (!longopt)
1662345Scsgr                putchar('\n');
1678874Srgrimes
1682345Scsgr	remember_host(raddrp->sin_addr);
1692345Scsgr	return(0);
1702345Scsgr}
1712345Scsgr
17227976Scharniervoid
1732345Scsgronehost(char *host)
1742345Scsgr{
1752345Scsgr        utmpidlearr up;
1762345Scsgr        CLIENT *rusers_clnt;
1772345Scsgr        struct sockaddr_in addr;
1782345Scsgr        struct hostent *hp;
17927976Scharnier		struct timeval tv;
1808874Srgrimes
1812345Scsgr        hp = gethostbyname(host);
18227976Scharnier        if (hp == NULL)
18327976Scharnier                errx(1, "unknown host \"%s\"", host);
1842345Scsgr
1852345Scsgr        rusers_clnt = clnt_create(host, RUSERSPROG, RUSERSVERS_IDLE, "udp");
18627976Scharnier        if (rusers_clnt == NULL)
18727976Scharnier                errx(1, "%s", clnt_spcreateerror(""));
1882345Scsgr
1892345Scsgr	bzero((char *)&up, sizeof(up));
19021094Speter	tv.tv_sec = 15;		/* XXX ?? */
19121094Speter	tv.tv_usec = 0;
19227976Scharnier	if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, xdr_void, NULL, xdr_utmpidlearr, &up, tv) != RPC_SUCCESS)
19327976Scharnier                errx(1, "%s", clnt_sperror(rusers_clnt, ""));
1942345Scsgr        addr.sin_addr.s_addr = *(int *)hp->h_addr;
19574462Salfred        rusers_reply((caddr_t)&up, &addr);
1962345Scsgr}
1972345Scsgr
19827976Scharniervoid
1992345Scsgrallhosts()
2002345Scsgr{
20127976Scharnier	utmpidlearr up;
2022345Scsgr	enum clnt_stat clnt_stat;
2032345Scsgr
2042345Scsgr	bzero((char *)&up, sizeof(up));
2052345Scsgr	clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE, RUSERSPROC_NAMES,
2062345Scsgr				   xdr_void, NULL,
20729469Sjkh				   xdr_utmpidlearr, (char *)&up, rusers_reply);
20827976Scharnier	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
20927976Scharnier		errx(1, "%s", clnt_sperrno(clnt_stat));
2102345Scsgr}
2112345Scsgr
21227976Scharnierstatic void
2132345Scsgrusage()
2142345Scsgr{
21527976Scharnier        fprintf(stderr, "usage: rusers [-la] [hosts ...]\n");
2162345Scsgr        exit(1);
2172345Scsgr}
2182345Scsgr
21927976Scharnierint
2202345Scsgrmain(int argc, char *argv[])
2212345Scsgr{
2222345Scsgr        int ch;
2238874Srgrimes
2242345Scsgr        while ((ch = getopt(argc, argv, "al")) != -1)
2252345Scsgr	        switch (ch) {
2262345Scsgr                case 'a':
2272345Scsgr                        allopt++;
2282345Scsgr                        break;
2292345Scsgr                case 'l':
2302345Scsgr                        longopt++;
2312345Scsgr                        break;
2322345Scsgr                default:
2332345Scsgr                        usage();
2342345Scsgr                        /*NOTREACHED*/
2352345Scsgr                }
2362345Scsgr
2372345Scsgr        setlinebuf(stdout);
2382345Scsgr	if (argc == optind)
2392345Scsgr		allhosts();
2402345Scsgr	else {
2412345Scsgr		for (; optind < argc; optind++)
2422345Scsgr			(void) onehost(argv[optind]);
2432345Scsgr	}
2442345Scsgr        exit(0);
2452345Scsgr}
246