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