1 /* $NetBSD: rusers.c,v 1.22 2004/01/05 23:23:36 jmmv Exp $ */
4 * Copyright (c) 1993 John Brezak
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: rusers.c,v 1.22 2004/01/05 23:23:36 jmmv Exp $");
36 #include <sys/types.h>
37 #include <sys/socket.h>
40 #include <arpa/inet.h>
52 * For now we only try version 2 of the protocol. The current
53 * version is 3 (rusers.h), but only Solaris and NetBSD seem
54 * to support it currently.
56 #include <rpcsvc/rnusers.h> /* Old version */
59 #define MAX_INT 0x7fffffff
61 struct timeval timeout
= { 25, 0 };
66 int main(int, char *[]);
68 void remember_host(struct sockaddr
*);
69 int rusers_reply(char *, struct netbuf
*, struct netconfig
*);
70 int search_host(struct sockaddr
*);
74 struct host_list
*next
;
77 struct in6_addr _addr6
;
78 struct in_addr _addr4
;
82 #define addr6 addr._addr6
83 #define addr4 addr._addr4
86 search_host(struct sockaddr
*sa
)
93 for (hp
= hosts
; hp
!= NULL
; hp
= hp
->next
) {
96 if (!memcmp(&hp
->addr6
,
97 &((struct sockaddr_in6
*)sa
)->sin6_addr
,
98 sizeof (struct in6_addr
)))
102 if (!memcmp(&hp
->addr4
,
103 &((struct sockaddr_in
*)sa
)->sin_addr
,
104 sizeof (struct in_addr
)))
115 remember_host(struct sockaddr
*sa
)
117 struct host_list
*hp
;
119 if (!(hp
= (struct host_list
*)malloc(sizeof(struct host_list
)))) {
123 hp
->family
= sa
->sa_family
;
125 switch (sa
->sa_family
) {
127 memcpy(&hp
->addr6
, &((struct sockaddr_in6
*)sa
)->sin6_addr
,
128 sizeof (struct in6_addr
));
131 memcpy(&hp
->addr4
, &((struct sockaddr_in
*)sa
)->sin_addr
,
132 sizeof (struct in_addr
));
135 err(1, "unknown address family");
142 rusers_reply(char *replyp
, struct netbuf
*raddrp
, struct netconfig
*nconf
)
144 char host
[NI_MAXHOST
];
146 struct utmpidlearr
*up
= (struct utmpidlearr
*)replyp
;
147 struct sockaddr
*sa
= raddrp
->buf
;
152 if (!allopt
&& !up
->uia_cnt
)
155 if (getnameinfo(sa
, sa
->sa_len
, host
, sizeof host
, NULL
, 0, 0))
158 #define HOSTWID (int)sizeof(up->uia_arr[0]->ui_utmp.ut_host)
159 #define LINEWID (int)sizeof(up->uia_arr[0]->ui_utmp.ut_line)
160 #define NAMEWID (int)sizeof(up->uia_arr[0]->ui_utmp.ut_name)
163 printf("%-*.*s ", HOSTWID
, HOSTWID
, host
);
165 for (x
= 0; x
< up
->uia_cnt
; x
++) {
166 unsigned int minutes
;
167 char date
[26], idle
[8];
168 char remote
[HOSTWID
+ 3]; /* "(" host ")" \0 */
169 char local
[HOSTWID
+ LINEWID
+ 2]; /* host ":" line \0 */
173 printf("%.*s ", NAMEWID
,
174 up
->uia_arr
[x
]->ui_utmp
.ut_name
);
178 snprintf(local
, sizeof(local
), "%.*s:%s",
180 up
->uia_arr
[x
]->ui_utmp
.ut_line
);
182 uttime
= up
->uia_arr
[x
]->ui_utmp
.ut_time
;
183 snprintf(date
, sizeof(date
), "%s",
184 &(ctime(&uttime
))[4]);
186 minutes
= up
->uia_arr
[x
]->ui_idle
;
187 if (minutes
== MAX_INT
)
189 else if (minutes
== 0)
192 unsigned int days
, hours
;
194 days
= minutes
/ (24 * 60);
195 minutes
%= (24 * 60);
196 hours
= minutes
/ 60;
200 snprintf(idle
, sizeof(idle
), "%d d ", days
);
202 snprintf(idle
, sizeof(idle
), "%2d:%02d",
205 snprintf(idle
, sizeof(idle
), ":%02d", minutes
);
208 if (up
->uia_arr
[x
]->ui_utmp
.ut_host
[0] != '\0')
209 snprintf(remote
, sizeof(remote
), "(%.*s)",
210 HOSTWID
, up
->uia_arr
[x
]->ui_utmp
.ut_host
);
214 printf("%-*.*s %-*.*s %-12.12s %8.8s %s\n",
215 NAMEWID
, NAMEWID
, up
->uia_arr
[x
]->ui_utmp
.ut_name
,
216 HOSTWID
+LINEWID
+1, HOSTWID
+LINEWID
+1, local
,
229 struct utmpidlearr up
;
231 enum clnt_stat clnt_stat
;
236 rusers_clnt
= clnt_create(host
, RUSERSPROG
, RUSERSVERS_IDLE
, "udp");
237 if (rusers_clnt
== NULL
) {
238 clnt_pcreateerror(getprogname());
242 ecode
= getaddrinfo(host
, NULL
, NULL
, &ai
);
244 err(1, "%s", gai_strerror(ecode
));
246 memset((char *)&up
, 0, sizeof(up
));
247 clnt_stat
= clnt_call(rusers_clnt
, RUSERSPROC_NAMES
, xdr_void
, NULL
,
248 xdr_utmpidlearr
, &up
, timeout
);
249 if (clnt_stat
!= RPC_SUCCESS
)
250 errx(1, "%s", clnt_sperrno(clnt_stat
));
251 nb
.buf
= ai
->ai_addr
;
252 nb
.len
= nb
.maxlen
= ai
->ai_addrlen
;
253 rusers_reply((char *)&up
, &nb
, NULL
);
260 struct utmpidlearr up
;
261 enum clnt_stat clnt_stat
;
263 memset((char *)&up
, 0, sizeof(up
));
264 clnt_stat
= rpc_broadcast(RUSERSPROG
, RUSERSVERS_IDLE
,
265 RUSERSPROC_NAMES
, xdr_void
, NULL
, xdr_utmpidlearr
,
266 (char *)&up
, (resultproc_t
)rusers_reply
, "udp");
267 if (clnt_stat
!= RPC_SUCCESS
&& clnt_stat
!= RPC_TIMEDOUT
)
268 errx(1, "%s", clnt_sperrno(clnt_stat
));
274 fprintf(stderr
, "usage: %s [-la] [hosts ...]\n", getprogname());
279 main(int argc
, char *argv
[])
283 while ((ch
= getopt(argc
, argv
, "al")) != -1)
300 for (; optind
< argc
; optind
++)
301 (void) onehost(argv
[optind
]);