rusers.c revision 89572
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 89572 2002-01-19 23:20:02Z dillon $";
372345Scsgr#endif /* not lint */
382345Scsgr
392345Scsgr#include <sys/types.h>
402345Scsgr#include <sys/socket.h>
4178455Smikeh#include <rpc/rpc.h>
4278455Smikeh#include <rpc/pmap_clnt.h>
4378455Smikeh#include <rpcsvc/rnusers.h>
4478455Smikeh#include <arpa/inet.h>
4527976Scharnier#include <err.h>
462345Scsgr#include <netdb.h>
472345Scsgr#include <stdio.h>
4827976Scharnier#include <stdlib.h>
492345Scsgr#include <strings.h>
5027976Scharnier#include <unistd.h>
512345Scsgr
5278455Smikeh#define MAX_INT		0x7fffffff
5378455Smikeh#define HOST_WIDTH	20
5478455Smikeh#define LINE_WIDTH	15
552345Scsgr
562345Scsgrint longopt;
572345Scsgrint allopt;
582345Scsgr
592345Scsgrstruct host_list {
6078455Smikeh	struct	host_list *next;
6178455Smikeh	struct	in_addr addr;
622345Scsgr} *hosts;
632345Scsgr
6427976Scharnierint
6527976Scharniersearch_host(struct in_addr addr)
662345Scsgr{
672345Scsgr	struct host_list *hp;
688874Srgrimes
6978455Smikeh	if (hosts == NULL)
7078455Smikeh		return (0);
712345Scsgr
722345Scsgr	for (hp = hosts; hp != NULL; hp = hp->next) {
732345Scsgr		if (hp->addr.s_addr == addr.s_addr)
7478455Smikeh			return (1);
752345Scsgr	}
7678455Smikeh	return (0);
772345Scsgr}
782345Scsgr
7927976Scharniervoid
8027976Scharnierremember_host(struct in_addr addr)
812345Scsgr{
822345Scsgr	struct host_list *hp;
832345Scsgr
8478455Smikeh	if ((hp = (struct host_list *)malloc(sizeof(struct host_list))) == NULL)
8527976Scharnier		errx(1, "no memory");
862345Scsgr	hp->addr.s_addr = addr.s_addr;
872345Scsgr	hp->next = hosts;
882345Scsgr	hosts = hp;
892345Scsgr}
902345Scsgr
9127976Scharnierint
9274462Salfredrusers_reply(caddr_t replyp, struct sockaddr_in *raddrp)
932345Scsgr{
9478455Smikeh	int x, idle;
9578455Smikeh	char date[32], idle_time[64], remote[64];
9678455Smikeh	struct hostent *hp;
9778455Smikeh	utmpidlearr *up = (utmpidlearr *)replyp;
9878455Smikeh	char *host;
9978455Smikeh	int days, hours, minutes, seconds;
1008874Srgrimes
1012345Scsgr	if (search_host(raddrp->sin_addr))
10278455Smikeh		return (0);
1032345Scsgr
10478455Smikeh	if (!allopt && up->utmpidlearr_len == 0)
10578455Smikeh		return (0);
1068874Srgrimes
10778455Smikeh	hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
10878455Smikeh	    sizeof(struct in_addr), AF_INET);
10978455Smikeh	if (hp != NULL)
11078455Smikeh		host = hp->h_name;
11178455Smikeh	else
11278455Smikeh		host = inet_ntoa(raddrp->sin_addr);
1138874Srgrimes
11478455Smikeh	if (!longopt)
11578455Smikeh		printf("%-*s ", HOST_WIDTH, host);
1168874Srgrimes
11778455Smikeh	for (x = 0; x < up->utmpidlearr_len; x++) {
11889572Sdillon		time_t t = _int_to_time(up->utmpidlearr_val[x].ui_utmp.ut_time);
11985638Sdillon		strncpy(date, &(ctime(&t)[4]), sizeof(date) - 1);
1202345Scsgr
12178455Smikeh		idle = up->utmpidlearr_val[x].ui_idle;
12278455Smikeh		sprintf(idle_time, "  :%02d", idle);
12378455Smikeh		if (idle == MAX_INT)
12478455Smikeh			strcpy(idle_time, "??");
12578455Smikeh		else if (idle == 0)
12678455Smikeh			strcpy(idle_time, "");
12778455Smikeh		else {
12878455Smikeh			seconds = idle;
12978455Smikeh			days = seconds / (60 * 60 * 24);
13078455Smikeh			seconds %= (60 * 60 * 24);
13178455Smikeh			hours = seconds / (60 * 60);
13278455Smikeh			seconds %= (60 * 60);
13378455Smikeh			minutes = seconds / 60;
13478455Smikeh			seconds %= 60;
13578455Smikeh			if (idle > 60)
13678455Smikeh				sprintf(idle_time, "%d:%02d", minutes, seconds);
13778455Smikeh			if (idle >= (60 * 60))
13878455Smikeh				sprintf(idle_time, "%d:%02d:%02d",
13978455Smikeh				    hours, minutes, seconds);
14078455Smikeh			if (idle >= (24 * 60 * 60))
14178455Smikeh				sprintf(idle_time, "%d days, %d:%02d:%02d",
14278455Smikeh				    days, hours, minutes, seconds);
14378455Smikeh		}
1442345Scsgr
14578455Smikeh		strncpy(remote, up->utmpidlearr_val[x].ui_utmp.ut_host,
14678455Smikeh		    sizeof(remote) - 1);
14778455Smikeh		if (strlen(remote) != 0)
14878455Smikeh			sprintf(remote, "(%.16s)",
14978455Smikeh			    up->utmpidlearr_val[x].ui_utmp.ut_host);
1502345Scsgr
15178455Smikeh		if (longopt)
15278455Smikeh			printf("%-8.8s %*s:%-*.*s %-12.12s  %6s %.18s\n",
15378455Smikeh			    up->utmpidlearr_val[x].ui_utmp.ut_name,
15478455Smikeh			    HOST_WIDTH, host, LINE_WIDTH, LINE_WIDTH,
15578455Smikeh			    up->utmpidlearr_val[x].ui_utmp.ut_line, date,
15678455Smikeh			    idle_time, remote );
15778455Smikeh		else
15878455Smikeh			printf("%s ",
15978455Smikeh			    up->utmpidlearr_val[x].ui_utmp.ut_name);
16078455Smikeh	}
16178455Smikeh	if (!longopt)
16278455Smikeh		putchar('\n');
1638874Srgrimes
1642345Scsgr	remember_host(raddrp->sin_addr);
16578455Smikeh	return (0);
1662345Scsgr}
1672345Scsgr
16827976Scharniervoid
1692345Scsgronehost(char *host)
1702345Scsgr{
17178455Smikeh	utmpidlearr up;
17278455Smikeh	CLIENT *rusers_clnt;
17378455Smikeh	struct sockaddr_in addr;
17478455Smikeh	struct hostent *hp;
17578455Smikeh	struct timeval tv;
1768874Srgrimes
17778455Smikeh	hp = gethostbyname(host);
17878455Smikeh	if (hp == NULL)
17978455Smikeh		errx(1, "unknown host \"%s\"", host);
1802345Scsgr
18178455Smikeh	rusers_clnt = clnt_create(host, RUSERSPROG, RUSERSVERS_IDLE, "udp");
18278455Smikeh	if (rusers_clnt == NULL)
18378455Smikeh		errx(1, "%s", clnt_spcreateerror(""));
1842345Scsgr
1852345Scsgr	bzero((char *)&up, sizeof(up));
18678455Smikeh	tv.tv_sec = 15;	/* XXX ?? */
18721094Speter	tv.tv_usec = 0;
18878455Smikeh	if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, xdr_void, NULL,
18978455Smikeh	    xdr_utmpidlearr, &up, tv) != RPC_SUCCESS)
19078455Smikeh		errx(1, "%s", clnt_sperror(rusers_clnt, ""));
19178455Smikeh	addr.sin_addr.s_addr = *(int *)hp->h_addr;
19278455Smikeh	rusers_reply((caddr_t)&up, &addr);
19378456Smikeh	clnt_destroy(rusers_clnt);
1942345Scsgr}
1952345Scsgr
19627976Scharniervoid
1972345Scsgrallhosts()
1982345Scsgr{
19927976Scharnier	utmpidlearr up;
2002345Scsgr	enum clnt_stat clnt_stat;
2012345Scsgr
2022345Scsgr	bzero((char *)&up, sizeof(up));
20378455Smikeh	clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE,
20478455Smikeh	    RUSERSPROC_NAMES, xdr_void, NULL, xdr_utmpidlearr, (char *)&up,
20578455Smikeh	    rusers_reply);
20627976Scharnier	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
20727976Scharnier		errx(1, "%s", clnt_sperrno(clnt_stat));
2082345Scsgr}
2092345Scsgr
21027976Scharnierstatic void
2112345Scsgrusage()
2122345Scsgr{
21378455Smikeh
21478455Smikeh	fprintf(stderr, "usage: rusers [-la] [hosts ...]\n");
21578455Smikeh	exit(1);
2162345Scsgr}
2172345Scsgr
21827976Scharnierint
2192345Scsgrmain(int argc, char *argv[])
2202345Scsgr{
22178455Smikeh	int ch;
2228874Srgrimes
22378455Smikeh	while ((ch = getopt(argc, argv, "al")) != -1)
22478455Smikeh		switch (ch) {
22578455Smikeh		case 'a':
22678455Smikeh			allopt++;
22778455Smikeh			break;
22878455Smikeh		case 'l':
22978455Smikeh			longopt++;
23078455Smikeh			break;
23178455Smikeh		default:
23278455Smikeh			usage();
23378455Smikeh			/* NOTREACHED */
23478455Smikeh		}
2352345Scsgr
23678455Smikeh	setlinebuf(stdout);
2372345Scsgr	if (argc == optind)
2382345Scsgr		allhosts();
2392345Scsgr	else {
2402345Scsgr		for (; optind < argc; optind++)
24178455Smikeh			(void)onehost(argv[optind]);
2422345Scsgr	}
24378455Smikeh	exit(0);
2442345Scsgr}
245