]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.bin/rusers/rusers.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.bin / rusers / rusers.c
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 #include <sys/cdefs.h>
35
36 __FBSDID("$FreeBSD$");
37
38 #include <sys/types.h>
39 #include <sys/socket.h>
40
41 #include <rpc/rpc.h>
42 #include <rpc/pmap_clnt.h>
43 #include <rpcsvc/rnusers.h>
44
45 #include <arpa/inet.h>
46
47 #include <err.h>
48 #include <netdb.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <timeconv.h>
53 #include <unistd.h>
54
55 #define MAX_INT         0x7fffffff
56 #define HOST_WIDTH      20
57 #define LINE_WIDTH      15
58
59 int longopt;
60 int allopt;
61
62 struct host_list {
63         struct  host_list *next;
64         struct  in_addr addr;
65 } *hosts;
66
67 static int
68 search_host(struct in_addr addr)
69 {
70         struct host_list *hp;
71
72         if (hosts == NULL)
73                 return (0);
74
75         for (hp = hosts; hp != NULL; hp = hp->next) {
76                 if (hp->addr.s_addr == addr.s_addr)
77                         return (1);
78         }
79         return (0);
80 }
81
82 static void
83 remember_host(struct in_addr addr)
84 {
85         struct host_list *hp;
86
87         if ((hp = (struct host_list *)malloc(sizeof(struct host_list))) == NULL)
88                 errx(1, "no memory");
89         hp->addr.s_addr = addr.s_addr;
90         hp->next = hosts;
91         hosts = hp;
92 }
93
94 static int
95 rusers_reply(caddr_t replyp, struct sockaddr_in *raddrp)
96 {
97         u_int x;
98         int idle;
99         char date[32], idle_time[64], remote[64];
100         struct hostent *hp;
101         utmpidlearr *up, u;
102         char *host;
103         int days, hours, minutes, seconds;
104
105         up = &u;
106         memcpy(up, replyp, sizeof(*up));
107         if (search_host(raddrp->sin_addr))
108                 return (0);
109
110         if (!allopt && up->utmpidlearr_len == 0)
111                 return (0);
112
113         hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
114             sizeof(struct in_addr), AF_INET);
115         if (hp != NULL)
116                 host = hp->h_name;
117         else
118                 host = inet_ntoa(raddrp->sin_addr);
119
120         if (!longopt)
121                 printf("%-*s ", HOST_WIDTH, host);
122
123         for (x = 0; x < up->utmpidlearr_len; x++) {
124                 time_t t = _int_to_time(up->utmpidlearr_val[x].ui_utmp.ut_time);
125                 strncpy(date, &(ctime(&t)[4]), sizeof(date) - 1);
126
127                 idle = up->utmpidlearr_val[x].ui_idle;
128                 sprintf(idle_time, "  :%02d", idle);
129                 if (idle == MAX_INT)
130                         strcpy(idle_time, "??");
131                 else if (idle == 0)
132                         strcpy(idle_time, "");
133                 else {
134                         seconds = idle;
135                         days = seconds / (60 * 60 * 24);
136                         seconds %= (60 * 60 * 24);
137                         hours = seconds / (60 * 60);
138                         seconds %= (60 * 60);
139                         minutes = seconds / 60;
140                         seconds %= 60;
141                         if (idle > 60)
142                                 sprintf(idle_time, "%d:%02d", minutes, seconds);
143                         if (idle >= (60 * 60))
144                                 sprintf(idle_time, "%d:%02d:%02d",
145                                     hours, minutes, seconds);
146                         if (idle >= (24 * 60 * 60))
147                                 sprintf(idle_time, "%d days, %d:%02d:%02d",
148                                     days, hours, minutes, seconds);
149                 }
150
151                 strncpy(remote, up->utmpidlearr_val[x].ui_utmp.ut_host,
152                     sizeof(remote) - 1);
153                 if (strlen(remote) != 0)
154                         sprintf(remote, "(%.16s)",
155                             up->utmpidlearr_val[x].ui_utmp.ut_host);
156
157                 if (longopt)
158                         printf("%-8.8s %*s:%-*.*s %-12.12s  %6s %.18s\n",
159                             up->utmpidlearr_val[x].ui_utmp.ut_name,
160                             HOST_WIDTH, host, LINE_WIDTH, LINE_WIDTH,
161                             up->utmpidlearr_val[x].ui_utmp.ut_line, date,
162                             idle_time, remote );
163                 else
164                         printf("%s ",
165                             up->utmpidlearr_val[x].ui_utmp.ut_name);
166         }
167         if (!longopt)
168                 putchar('\n');
169
170         remember_host(raddrp->sin_addr);
171         return (0);
172 }
173
174 static void
175 onehost(char *host)
176 {
177         utmpidlearr up;
178         CLIENT *rusers_clnt;
179         struct sockaddr_in addr;
180         struct hostent *hp;
181         struct timeval tv;
182
183         hp = gethostbyname(host);
184         if (hp == NULL)
185                 errx(1, "unknown host \"%s\"", host);
186
187         rusers_clnt = clnt_create(host, RUSERSPROG, RUSERSVERS_IDLE, "udp");
188         if (rusers_clnt == NULL)
189                 errx(1, "%s", clnt_spcreateerror(""));
190
191         bzero((char *)&up, sizeof(up));
192         tv.tv_sec = 15; /* XXX ?? */
193         tv.tv_usec = 0;
194         if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL,
195             (xdrproc_t)xdr_utmpidlearr, &up, tv) != RPC_SUCCESS)
196                 errx(1, "%s", clnt_sperror(rusers_clnt, ""));
197         memcpy(&addr.sin_addr.s_addr, hp->h_addr, sizeof(addr.sin_addr.s_addr));
198         rusers_reply((caddr_t)&up, &addr);
199         clnt_destroy(rusers_clnt);
200 }
201
202 static void
203 allhosts(void)
204 {
205         utmpidlearr up;
206         enum clnt_stat clnt_stat;
207
208         bzero((char *)&up, sizeof(up));
209         clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE,
210             RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL,
211             (xdrproc_t)xdr_utmpidlearr, (char *)&up,
212             (resultproc_t)rusers_reply);
213         if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
214                 errx(1, "%s", clnt_sperrno(clnt_stat));
215 }
216
217 static void
218 usage(void)
219 {
220
221         fprintf(stderr, "usage: rusers [-al] [host ...]\n");
222         exit(1);
223 }
224
225 int
226 main(int argc, char *argv[])
227 {
228         int ch;
229
230         while ((ch = getopt(argc, argv, "al")) != -1)
231                 switch (ch) {
232                 case 'a':
233                         allopt++;
234                         break;
235                 case 'l':
236                         longopt++;
237                         break;
238                 default:
239                         usage();
240                         /* NOTREACHED */
241                 }
242
243         setlinebuf(stdout);
244         if (argc == optind)
245                 allhosts();
246         else {
247                 for (; optind < argc; optind++)
248                         (void)onehost(argv[optind]);
249         }
250         exit(0);
251 }