Home | History | Annotate | Line # | Download | only in rusers
rusers.c revision 1.11
      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.11 1996/03/21 18:00:35 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
    228 usage(void)
    229 {
    230 	fprintf(stderr, "Usage: %s [-la] [hosts ...]\n", argv0);
    231 	exit(1);
    232 }
    233 
    234 int
    235 main(int argc, char *argv[])
    236 {
    237 	int ch;
    238 	extern int optind;
    239 
    240 	if (!(argv0 = rindex(argv[0], '/')))
    241 		argv0 = argv[0];
    242 	else
    243 		argv0++;
    244 
    245 
    246 	while ((ch = getopt(argc, argv, "al")) != -1)
    247 		switch (ch) {
    248 		case 'a':
    249 			allopt++;
    250 			break;
    251 		case 'l':
    252 			longopt++;
    253 			break;
    254 		default:
    255 			usage();
    256 			/*NOTREACHED*/
    257 		}
    258 
    259 	setlinebuf(stdout);
    260 	if (argc == optind)
    261 		allhosts();
    262 	else {
    263 		for (; optind < argc; optind++)
    264 			(void) onehost(argv[optind]);
    265 	}
    266 	exit(0);
    267 }
    268