rusers.c revision 27976
1/*-
2 * Copyright (c) 1993, John Brezak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by the University of
16 *	California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static const char rcsid[] =
36	"$Id: rusers.c,v 1.5 1997/02/22 19:56:52 peter Exp $";
37#endif /* not lint */
38
39#include <sys/types.h>
40#include <sys/param.h>
41#include <sys/socket.h>
42#include <err.h>
43#include <netdb.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <strings.h>
47#include <unistd.h>
48#include <rpc/rpc.h>
49#include <rpc/pmap_clnt.h>
50#include <arpa/inet.h>
51#include <rpcsvc/rnusers.h>
52
53#define MAX_INT 0x7fffffff
54#define HOST_WIDTH 20
55#define LINE_WIDTH 15
56
57int longopt;
58int allopt;
59
60struct host_list {
61	struct host_list *next;
62	struct in_addr addr;
63} *hosts;
64
65int
66search_host(struct in_addr addr)
67{
68	struct host_list *hp;
69
70	if (!hosts)
71		return(0);
72
73	for (hp = hosts; hp != NULL; hp = hp->next) {
74		if (hp->addr.s_addr == addr.s_addr)
75			return(1);
76	}
77	return(0);
78}
79
80void
81remember_host(struct in_addr addr)
82{
83	struct host_list *hp;
84
85	if (!(hp = (struct host_list *)malloc(sizeof(struct host_list))))
86		errx(1, "no memory");
87	hp->addr.s_addr = addr.s_addr;
88	hp->next = hosts;
89	hosts = hp;
90}
91
92int
93rusers_reply(char *replyp, struct sockaddr_in *raddrp)
94{
95        int x, idle;
96        char date[32], idle_time[64], remote[64];
97        struct hostent *hp;
98        utmpidlearr *up = (utmpidlearr *)replyp;
99        char *host;
100        int days, hours, minutes, seconds;
101
102	if (search_host(raddrp->sin_addr))
103		return(0);
104
105        if (!allopt && !up->utmpidlearr_len)
106                return(0);
107
108        hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
109                           sizeof(struct in_addr), AF_INET);
110        if (hp)
111                host = hp->h_name;
112        else
113                host = inet_ntoa(raddrp->sin_addr);
114
115        if (!longopt)
116                printf("%-*s ", HOST_WIDTH, host);
117
118        for (x = 0; x < up->utmpidlearr_len; x++) {
119                strncpy(date,
120                        &(ctime((time_t *)&(up->utmpidlearr_val[x].ui_utmp.ut_time))[4]),
121                        sizeof(date)-1);
122
123                idle = up->utmpidlearr_val[x].ui_idle;
124                sprintf(idle_time, "  :%02d", idle);
125                if (idle == MAX_INT)
126                        strcpy(idle_time, "??");
127                else if (idle == 0)
128                        strcpy(idle_time, "");
129                else {
130                        seconds = idle;
131                        days = seconds/(60*60*24);
132                        seconds %= (60*60*24);
133                        hours = seconds/(60*60);
134                        seconds %= (60*60);
135                        minutes = seconds/60;
136                        seconds %= 60;
137                        if (idle > 60)
138                                sprintf(idle_time, "%d:%02d",
139                                        minutes, seconds);
140                        if (idle >= (60*60))
141                                sprintf(idle_time, "%d:%02d:%02d",
142                                        hours, minutes, seconds);
143                        if (idle >= (24*60*60))
144                                sprintf(idle_time, "%d days, %d:%02d:%02d",
145                                        days, hours, minutes, seconds);
146                }
147
148                strncpy(remote, up->utmpidlearr_val[x].ui_utmp.ut_host, sizeof(remote)-1);
149                if (strlen(remote) != 0)
150                        sprintf(remote, "(%.16s)", up->utmpidlearr_val[x].ui_utmp.ut_host);
151
152                if (longopt)
153                        printf("%-8.8s %*s:%-*.*s %-12.12s  %6s %.18s\n",
154                               up->utmpidlearr_val[x].ui_utmp.ut_name,
155                               HOST_WIDTH, host,
156                               LINE_WIDTH, LINE_WIDTH, up->utmpidlearr_val[x].ui_utmp.ut_line,
157                               date,
158                               idle_time,
159                               remote
160                               );
161                else
162                        printf("%s ",
163                               up->utmpidlearr_val[x].ui_utmp.ut_name);
164        }
165        if (!longopt)
166                putchar('\n');
167
168	remember_host(raddrp->sin_addr);
169	return(0);
170}
171
172void
173onehost(char *host)
174{
175        utmpidlearr up;
176        CLIENT *rusers_clnt;
177        struct sockaddr_in addr;
178        struct hostent *hp;
179		struct timeval tv;
180
181        hp = gethostbyname(host);
182        if (hp == NULL)
183                errx(1, "unknown host \"%s\"", host);
184
185        rusers_clnt = clnt_create(host, RUSERSPROG, RUSERSVERS_IDLE, "udp");
186        if (rusers_clnt == NULL)
187                errx(1, "%s", clnt_spcreateerror(""));
188
189	bzero((char *)&up, sizeof(up));
190	tv.tv_sec = 15;		/* XXX ?? */
191	tv.tv_usec = 0;
192	if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, xdr_void, NULL, xdr_utmpidlearr, &up, tv) != RPC_SUCCESS)
193                errx(1, "%s", clnt_sperror(rusers_clnt, ""));
194        addr.sin_addr.s_addr = *(int *)hp->h_addr;
195        rusers_reply((char *)&up, &addr);
196}
197
198void
199allhosts()
200{
201	utmpidlearr up;
202	enum clnt_stat clnt_stat;
203
204	bzero((char *)&up, sizeof(up));
205	clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE, RUSERSPROC_NAMES,
206				   xdr_void, NULL,
207				   xdr_utmpidlearr, &up, rusers_reply);
208	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
209		errx(1, "%s", clnt_sperrno(clnt_stat));
210}
211
212static void
213usage()
214{
215        fprintf(stderr, "usage: rusers [-la] [hosts ...]\n");
216        exit(1);
217}
218
219int
220main(int argc, char *argv[])
221{
222        int ch;
223
224        while ((ch = getopt(argc, argv, "al")) != -1)
225	        switch (ch) {
226                case 'a':
227                        allopt++;
228                        break;
229                case 'l':
230                        longopt++;
231                        break;
232                default:
233                        usage();
234                        /*NOTREACHED*/
235                }
236
237        setlinebuf(stdout);
238	if (argc == optind)
239		allhosts();
240	else {
241		for (; optind < argc; optind++)
242			(void) onehost(argv[optind]);
243	}
244        exit(0);
245}
246