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