rusers.c revision 1.15 1 1.15 kleink /* $NetBSD: rusers.c,v 1.15 1998/04/02 10:59:14 kleink 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.15 kleink __RCSID("$NetBSD: rusers.c,v 1.15 1998/04/02 10:59:14 kleink 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/socket.h>
38 1.15 kleink
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.15 kleink #include <time.h>
48 1.14 perry #include <unistd.h>
49 1.6 brezak #include <utmp.h>
50 1.6 brezak
51 1.6 brezak /*
52 1.6 brezak * For now we only try version 2 of the protocol. The current
53 1.9 deraadt * version is 3 (rusers.h), but only Solaris and NetBSD seem
54 1.6 brezak * to support it currently.
55 1.6 brezak */
56 1.6 brezak #include <rpcsvc/rnusers.h> /* Old version */
57 1.1 brezak
58 1.13 lukem
59 1.1 brezak #define MAX_INT 0x7fffffff
60 1.13 lukem extern char *__progname; /* from crt0.o */
61 1.1 brezak
62 1.10 jtc struct timeval timeout = { 25, 0 };
63 1.1 brezak int longopt;
64 1.1 brezak int allopt;
65 1.1 brezak
66 1.13 lukem void allhosts __P((void));
67 1.13 lukem int main __P((int, char *[]));
68 1.13 lukem void onehost __P((char *));
69 1.13 lukem void remember_host __P((struct in_addr));
70 1.13 lukem int rusers_reply __P((char *, struct sockaddr_in *));
71 1.13 lukem int search_host __P((struct in_addr));
72 1.13 lukem void usage __P((void));
73 1.13 lukem
74 1.1 brezak struct host_list {
75 1.1 brezak struct host_list *next;
76 1.1 brezak struct in_addr addr;
77 1.1 brezak } *hosts;
78 1.1 brezak
79 1.5 deraadt int
80 1.6 brezak search_host(struct in_addr addr)
81 1.1 brezak {
82 1.1 brezak struct host_list *hp;
83 1.1 brezak
84 1.1 brezak if (!hosts)
85 1.1 brezak return(0);
86 1.1 brezak
87 1.1 brezak for (hp = hosts; hp != NULL; hp = hp->next) {
88 1.1 brezak if (hp->addr.s_addr == addr.s_addr)
89 1.1 brezak return(1);
90 1.1 brezak }
91 1.1 brezak return(0);
92 1.1 brezak }
93 1.1 brezak
94 1.5 deraadt void
95 1.6 brezak remember_host(struct in_addr addr)
96 1.1 brezak {
97 1.1 brezak struct host_list *hp;
98 1.1 brezak
99 1.13 lukem if (!(hp = (struct host_list *)malloc(sizeof(struct host_list))))
100 1.13 lukem errx(1, "no memory");
101 1.1 brezak hp->addr.s_addr = addr.s_addr;
102 1.1 brezak hp->next = hosts;
103 1.1 brezak hosts = hp;
104 1.1 brezak }
105 1.1 brezak
106 1.6 brezak int
107 1.6 brezak rusers_reply(char *replyp, struct sockaddr_in *raddrp)
108 1.5 deraadt {
109 1.13 lukem int x;
110 1.5 deraadt struct hostent *hp;
111 1.6 brezak struct utmpidlearr *up = (struct utmpidlearr *)replyp;
112 1.5 deraadt char *host;
113 1.5 deraadt
114 1.1 brezak if (search_host(raddrp->sin_addr))
115 1.1 brezak return(0);
116 1.1 brezak
117 1.6 brezak if (!allopt && !up->uia_cnt)
118 1.5 deraadt return(0);
119 1.5 deraadt
120 1.5 deraadt hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
121 1.5 deraadt sizeof(struct in_addr), AF_INET);
122 1.5 deraadt if (hp)
123 1.5 deraadt host = hp->h_name;
124 1.5 deraadt else
125 1.5 deraadt host = inet_ntoa(raddrp->sin_addr);
126 1.5 deraadt
127 1.13 lukem #define HOSTWID (int)sizeof(up->uia_arr[0]->ui_utmp.ut_host)
128 1.13 lukem #define LINEWID (int)sizeof(up->uia_arr[0]->ui_utmp.ut_line)
129 1.13 lukem #define NAMEWID (int)sizeof(up->uia_arr[0]->ui_utmp.ut_name)
130 1.13 lukem
131 1.5 deraadt if (!longopt)
132 1.13 lukem printf("%-*.*s ", HOSTWID, HOSTWID, host);
133 1.5 deraadt
134 1.6 brezak for (x = 0; x < up->uia_cnt; x++) {
135 1.13 lukem unsigned int minutes;
136 1.13 lukem char date[26], idle[8];
137 1.13 lukem char remote[HOSTWID + 3]; /* "(" host ")" \0 */
138 1.13 lukem char local[HOSTWID + LINEWID + 2]; /* host ":" line \0 */
139 1.13 lukem
140 1.13 lukem if (!longopt) {
141 1.13 lukem printf("%.*s ", NAMEWID,
142 1.13 lukem up->uia_arr[x]->ui_utmp.ut_name);
143 1.13 lukem continue;
144 1.13 lukem }
145 1.13 lukem
146 1.13 lukem snprintf(local, sizeof(local), "%.*s:%s",
147 1.13 lukem HOSTWID, host,
148 1.13 lukem up->uia_arr[x]->ui_utmp.ut_line);
149 1.13 lukem
150 1.13 lukem snprintf(date, sizeof(date), "%s",
151 1.13 lukem &(ctime((time_t *)&(up->uia_arr[x]->ui_utmp.ut_time)))[4]);
152 1.13 lukem
153 1.13 lukem minutes = up->uia_arr[x]->ui_idle;
154 1.13 lukem if (minutes == MAX_INT)
155 1.13 lukem strcpy(idle, "??");
156 1.13 lukem else if (minutes == 0)
157 1.13 lukem strcpy(idle, "");
158 1.5 deraadt else {
159 1.13 lukem unsigned int days, hours;
160 1.13 lukem
161 1.13 lukem days = minutes / (24 * 60);
162 1.13 lukem minutes %= (24 * 60);
163 1.13 lukem hours = minutes / 24;
164 1.13 lukem minutes %= 24;
165 1.13 lukem
166 1.13 lukem if (days > 0)
167 1.13 lukem snprintf(idle, sizeof(idle), "%d d ", days);
168 1.13 lukem else if (hours > 0)
169 1.13 lukem snprintf(idle, sizeof(idle), "%2d:%02d",
170 1.13 lukem hours, minutes);
171 1.13 lukem else
172 1.13 lukem snprintf(idle, sizeof(idle), ":%02d", minutes);
173 1.5 deraadt }
174 1.5 deraadt
175 1.13 lukem if (up->uia_arr[x]->ui_utmp.ut_host[0] != '\0')
176 1.13 lukem snprintf(remote, sizeof(remote), "(%.*s)",
177 1.13 lukem HOSTWID, up->uia_arr[x]->ui_utmp.ut_host);
178 1.13 lukem else
179 1.13 lukem remote[0] = '\0';
180 1.13 lukem
181 1.13 lukem printf("%-*.*s %-*.*s %-12.12s %8.8s %s\n",
182 1.13 lukem NAMEWID, NAMEWID, up->uia_arr[x]->ui_utmp.ut_name,
183 1.13 lukem HOSTWID+LINEWID+1, HOSTWID+LINEWID+1, local,
184 1.13 lukem date, idle, remote);
185 1.5 deraadt }
186 1.5 deraadt if (!longopt)
187 1.5 deraadt putchar('\n');
188 1.5 deraadt
189 1.1 brezak remember_host(raddrp->sin_addr);
190 1.1 brezak return(0);
191 1.1 brezak }
192 1.1 brezak
193 1.6 brezak void
194 1.6 brezak onehost(char *host)
195 1.1 brezak {
196 1.6 brezak struct utmpidlearr up;
197 1.5 deraadt CLIENT *rusers_clnt;
198 1.13 lukem enum clnt_stat clnt_stat;
199 1.5 deraadt struct sockaddr_in addr;
200 1.5 deraadt struct hostent *hp;
201 1.5 deraadt
202 1.5 deraadt hp = gethostbyname(host);
203 1.13 lukem if (hp == NULL)
204 1.13 lukem errx(1, "unknown host \"%s\"", host);
205 1.5 deraadt
206 1.5 deraadt rusers_clnt = clnt_create(host, RUSERSPROG, RUSERSVERS_IDLE, "udp");
207 1.5 deraadt if (rusers_clnt == NULL) {
208 1.13 lukem clnt_pcreateerror(__progname);
209 1.5 deraadt exit(1);
210 1.5 deraadt }
211 1.1 brezak
212 1.13 lukem memset((char *)&up, 0, sizeof(up));
213 1.13 lukem clnt_stat = clnt_call(rusers_clnt, RUSERSPROC_NAMES, xdr_void, NULL,
214 1.13 lukem xdr_utmpidlearr, &up, timeout);
215 1.13 lukem if (clnt_stat != RPC_SUCCESS)
216 1.13 lukem errx(1, "%s", clnt_sperrno(clnt_stat));
217 1.5 deraadt addr.sin_addr.s_addr = *(int *)hp->h_addr;
218 1.5 deraadt rusers_reply((char *)&up, &addr);
219 1.1 brezak }
220 1.1 brezak
221 1.6 brezak void
222 1.6 brezak allhosts(void)
223 1.1 brezak {
224 1.6 brezak struct utmpidlearr up;
225 1.1 brezak enum clnt_stat clnt_stat;
226 1.1 brezak
227 1.13 lukem memset((char *)&up, 0, sizeof(up));
228 1.5 deraadt clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE,
229 1.5 deraadt RUSERSPROC_NAMES, xdr_void, NULL, xdr_utmpidlearr,
230 1.13 lukem (char *)&up, rusers_reply);
231 1.13 lukem if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
232 1.13 lukem errx(1, "%s", clnt_sperrno(clnt_stat));
233 1.1 brezak }
234 1.1 brezak
235 1.11 jtc void
236 1.11 jtc usage(void)
237 1.1 brezak {
238 1.13 lukem fprintf(stderr, "Usage: %s [-la] [hosts ...]\n", __progname);
239 1.5 deraadt exit(1);
240 1.1 brezak }
241 1.1 brezak
242 1.11 jtc int
243 1.11 jtc main(int argc, char *argv[])
244 1.1 brezak {
245 1.5 deraadt int ch;
246 1.5 deraadt extern int optind;
247 1.5 deraadt
248 1.5 deraadt while ((ch = getopt(argc, argv, "al")) != -1)
249 1.5 deraadt switch (ch) {
250 1.5 deraadt case 'a':
251 1.5 deraadt allopt++;
252 1.5 deraadt break;
253 1.5 deraadt case 'l':
254 1.5 deraadt longopt++;
255 1.5 deraadt break;
256 1.5 deraadt default:
257 1.5 deraadt usage();
258 1.5 deraadt /*NOTREACHED*/
259 1.5 deraadt }
260 1.3 brezak
261 1.5 deraadt setlinebuf(stdout);
262 1.1 brezak if (argc == optind)
263 1.1 brezak allhosts();
264 1.1 brezak else {
265 1.1 brezak for (; optind < argc; optind++)
266 1.1 brezak (void) onehost(argv[optind]);
267 1.1 brezak }
268 1.5 deraadt exit(0);
269 1.1 brezak }
270