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