rusers.c revision 121545
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: head/usr.bin/rusers/rusers.c 121545 2003-10-26 04:57:32Z peter $");
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>
5227976Scharnier#include <unistd.h>
532345Scsgr
5478455Smikeh#define MAX_INT		0x7fffffff
5578455Smikeh#define HOST_WIDTH	20
5678455Smikeh#define LINE_WIDTH	15
572345Scsgr
582345Scsgrint longopt;
592345Scsgrint allopt;
602345Scsgr
612345Scsgrstruct host_list {
6278455Smikeh	struct	host_list *next;
6378455Smikeh	struct	in_addr addr;
642345Scsgr} *hosts;
652345Scsgr
6695619Smarkmstatic int
6727976Scharniersearch_host(struct in_addr addr)
682345Scsgr{
692345Scsgr	struct host_list *hp;
708874Srgrimes
7178455Smikeh	if (hosts == NULL)
7278455Smikeh		return (0);
732345Scsgr
742345Scsgr	for (hp = hosts; hp != NULL; hp = hp->next) {
752345Scsgr		if (hp->addr.s_addr == addr.s_addr)
7678455Smikeh			return (1);
772345Scsgr	}
7878455Smikeh	return (0);
792345Scsgr}
802345Scsgr
8195619Smarkmstatic void
8227976Scharnierremember_host(struct in_addr addr)
832345Scsgr{
842345Scsgr	struct host_list *hp;
852345Scsgr
8678455Smikeh	if ((hp = (struct host_list *)malloc(sizeof(struct host_list))) == NULL)
8727976Scharnier		errx(1, "no memory");
882345Scsgr	hp->addr.s_addr = addr.s_addr;
892345Scsgr	hp->next = hosts;
902345Scsgr	hosts = hp;
912345Scsgr}
922345Scsgr
9395619Smarkmstatic int
9474462Salfredrusers_reply(caddr_t replyp, struct sockaddr_in *raddrp)
952345Scsgr{
9695619Smarkm	u_int x;
9795619Smarkm	int idle;
9878455Smikeh	char date[32], idle_time[64], remote[64];
9978455Smikeh	struct hostent *hp;
10078455Smikeh	utmpidlearr *up = (utmpidlearr *)replyp;
10178455Smikeh	char *host;
10278455Smikeh	int days, hours, minutes, seconds;
1038874Srgrimes
1042345Scsgr	if (search_host(raddrp->sin_addr))
10578455Smikeh		return (0);
1062345Scsgr
10778455Smikeh	if (!allopt && up->utmpidlearr_len == 0)
10878455Smikeh		return (0);
1098874Srgrimes
11078455Smikeh	hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
11178455Smikeh	    sizeof(struct in_addr), AF_INET);
11278455Smikeh	if (hp != NULL)
11378455Smikeh		host = hp->h_name;
11478455Smikeh	else
11578455Smikeh		host = inet_ntoa(raddrp->sin_addr);
1168874Srgrimes
11778455Smikeh	if (!longopt)
11878455Smikeh		printf("%-*s ", HOST_WIDTH, host);
1198874Srgrimes
12078455Smikeh	for (x = 0; x < up->utmpidlearr_len; x++) {
12189572Sdillon		time_t t = _int_to_time(up->utmpidlearr_val[x].ui_utmp.ut_time);
12285638Sdillon		strncpy(date, &(ctime(&t)[4]), sizeof(date) - 1);
1232345Scsgr
12478455Smikeh		idle = up->utmpidlearr_val[x].ui_idle;
12578455Smikeh		sprintf(idle_time, "  :%02d", idle);
12678455Smikeh		if (idle == MAX_INT)
12778455Smikeh			strcpy(idle_time, "??");
12878455Smikeh		else if (idle == 0)
12978455Smikeh			strcpy(idle_time, "");
13078455Smikeh		else {
13178455Smikeh			seconds = idle;
13278455Smikeh			days = seconds / (60 * 60 * 24);
13378455Smikeh			seconds %= (60 * 60 * 24);
13478455Smikeh			hours = seconds / (60 * 60);
13578455Smikeh			seconds %= (60 * 60);
13678455Smikeh			minutes = seconds / 60;
13778455Smikeh			seconds %= 60;
13878455Smikeh			if (idle > 60)
13978455Smikeh				sprintf(idle_time, "%d:%02d", minutes, seconds);
14078455Smikeh			if (idle >= (60 * 60))
14178455Smikeh				sprintf(idle_time, "%d:%02d:%02d",
14278455Smikeh				    hours, minutes, seconds);
14378455Smikeh			if (idle >= (24 * 60 * 60))
14478455Smikeh				sprintf(idle_time, "%d days, %d:%02d:%02d",
14578455Smikeh				    days, hours, minutes, seconds);
14678455Smikeh		}
1472345Scsgr
14878455Smikeh		strncpy(remote, up->utmpidlearr_val[x].ui_utmp.ut_host,
14978455Smikeh		    sizeof(remote) - 1);
15078455Smikeh		if (strlen(remote) != 0)
15178455Smikeh			sprintf(remote, "(%.16s)",
15278455Smikeh			    up->utmpidlearr_val[x].ui_utmp.ut_host);
1532345Scsgr
15478455Smikeh		if (longopt)
15578455Smikeh			printf("%-8.8s %*s:%-*.*s %-12.12s  %6s %.18s\n",
15678455Smikeh			    up->utmpidlearr_val[x].ui_utmp.ut_name,
15778455Smikeh			    HOST_WIDTH, host, LINE_WIDTH, LINE_WIDTH,
15878455Smikeh			    up->utmpidlearr_val[x].ui_utmp.ut_line, date,
15978455Smikeh			    idle_time, remote );
16078455Smikeh		else
16178455Smikeh			printf("%s ",
16278455Smikeh			    up->utmpidlearr_val[x].ui_utmp.ut_name);
16378455Smikeh	}
16478455Smikeh	if (!longopt)
16578455Smikeh		putchar('\n');
1668874Srgrimes
1672345Scsgr	remember_host(raddrp->sin_addr);
16878455Smikeh	return (0);
1692345Scsgr}
1702345Scsgr
17195619Smarkmstatic void
1722345Scsgronehost(char *host)
1732345Scsgr{
17478455Smikeh	utmpidlearr up;
17578455Smikeh	CLIENT *rusers_clnt;
17678455Smikeh	struct sockaddr_in addr;
17778455Smikeh	struct hostent *hp;
17878455Smikeh	struct timeval tv;
1798874Srgrimes
18078455Smikeh	hp = gethostbyname(host);
18178455Smikeh	if (hp == NULL)
18278455Smikeh		errx(1, "unknown host \"%s\"", host);
1832345Scsgr
18478455Smikeh	rusers_clnt = clnt_create(host, RUSERSPROG, RUSERSVERS_IDLE, "udp");
18578455Smikeh	if (rusers_clnt == NULL)
18678455Smikeh		errx(1, "%s", clnt_spcreateerror(""));
1872345Scsgr
1882345Scsgr	bzero((char *)&up, sizeof(up));
18978455Smikeh	tv.tv_sec = 15;	/* XXX ?? */
19021094Speter	tv.tv_usec = 0;
191121545Speter	if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL,
192121545Speter	    (xdrproc_t)xdr_utmpidlearr, &up, tv) != RPC_SUCCESS)
19378455Smikeh		errx(1, "%s", clnt_sperror(rusers_clnt, ""));
19478455Smikeh	addr.sin_addr.s_addr = *(int *)hp->h_addr;
19578455Smikeh	rusers_reply((caddr_t)&up, &addr);
19678456Smikeh	clnt_destroy(rusers_clnt);
1972345Scsgr}
1982345Scsgr
19995619Smarkmstatic void
20095619Smarkmallhosts(void)
2012345Scsgr{
20227976Scharnier	utmpidlearr up;
2032345Scsgr	enum clnt_stat clnt_stat;
2042345Scsgr
2052345Scsgr	bzero((char *)&up, sizeof(up));
20678455Smikeh	clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE,
207121545Speter	    RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL,
208121545Speter	    (xdrproc_t)xdr_utmpidlearr, (char *)&up,
209121545Speter	    (resultproc_t)rusers_reply);
21027976Scharnier	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
21127976Scharnier		errx(1, "%s", clnt_sperrno(clnt_stat));
2122345Scsgr}
2132345Scsgr
21427976Scharnierstatic void
21595619Smarkmusage(void)
2162345Scsgr{
21778455Smikeh
21878455Smikeh	fprintf(stderr, "usage: rusers [-la] [hosts ...]\n");
21978455Smikeh	exit(1);
2202345Scsgr}
2212345Scsgr
22227976Scharnierint
2232345Scsgrmain(int argc, char *argv[])
2242345Scsgr{
22578455Smikeh	int ch;
2268874Srgrimes
22778455Smikeh	while ((ch = getopt(argc, argv, "al")) != -1)
22878455Smikeh		switch (ch) {
22978455Smikeh		case 'a':
23078455Smikeh			allopt++;
23178455Smikeh			break;
23278455Smikeh		case 'l':
23378455Smikeh			longopt++;
23478455Smikeh			break;
23578455Smikeh		default:
23678455Smikeh			usage();
23778455Smikeh			/* NOTREACHED */
23878455Smikeh		}
2392345Scsgr
24078455Smikeh	setlinebuf(stdout);
2412345Scsgr	if (argc == optind)
2422345Scsgr		allhosts();
2432345Scsgr	else {
2442345Scsgr		for (; optind < argc; optind++)
24578455Smikeh			(void)onehost(argv[optind]);
2462345Scsgr	}
24778455Smikeh	exit(0);
2482345Scsgr}
249