Home | History | Annotate | Line # | Download | only in rpcinfo
rpcinfo.c revision 1.1
      1 /* @(#)rpcinfo.c	2.2 88/08/11 4.0 RPCSRC */
      2 #ifndef lint
      3 static	char sccsid[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI";
      4 #endif
      5 
      6 /*
      7  * Copyright (C) 1986, Sun Microsystems, Inc.
      8  */
      9 
     10 /*
     11  * rpcinfo: ping a particular rpc program
     12  *     or dump the portmapper
     13  */
     14 
     15 /*
     16  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
     17  * unrestricted use provided that this legend is included on all tape
     18  * media and as a part of the software program in whole or part.  Users
     19  * may copy or modify Sun RPC without charge, but are not authorized
     20  * to license or distribute it to anyone else except as part of a product or
     21  * program developed by the user.
     22  *
     23  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
     24  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
     25  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
     26  *
     27  * Sun RPC is provided with no support and without any obligation on the
     28  * part of Sun Microsystems, Inc. to assist in its use, correction,
     29  * modification or enhancement.
     30  *
     31  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
     32  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
     33  * OR ANY PART THEREOF.
     34  *
     35  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
     36  * or profits or other special, indirect and consequential damages, even if
     37  * Sun has been advised of the possibility of such damages.
     38  *
     39  * Sun Microsystems, Inc.
     40  * 2550 Garcia Avenue
     41  * Mountain View, California  94043
     42  */
     43 
     44 #include <rpc/rpc.h>
     45 #include <stdio.h>
     46 #include <sys/socket.h>
     47 #include <netdb.h>
     48 #include <rpc/pmap_prot.h>
     49 #include <rpc/pmap_clnt.h>
     50 #include <signal.h>
     51 #include <ctype.h>
     52 
     53 #define MAXHOSTLEN 256
     54 
     55 #define	MIN_VERS	((u_long) 0)
     56 #define	MAX_VERS	((u_long) 4294967295L)
     57 
     58 static void	udpping(/*u_short portflag, int argc, char **argv*/);
     59 static void	tcpping(/*u_short portflag, int argc, char **argv*/);
     60 static int	pstatus(/*CLIENT *client, u_long prognum, u_long vers*/);
     61 static void	pmapdump(/*int argc, char **argv*/);
     62 static bool_t	reply_proc(/*void *res, struct sockaddr_in *who*/);
     63 static void	brdcst(/*int argc, char **argv*/);
     64 static void	deletereg(/* int argc, char **argv */) ;
     65 static void	usage(/*void*/);
     66 static u_long	getprognum(/*char *arg*/);
     67 static u_long	getvers(/*char *arg*/);
     68 static void	get_inet_address(/*struct sockaddr_in *addr, char *host*/);
     69 extern u_long inet_addr();  /* in 4.2BSD, arpa/inet.h called that a in_addr */
     70 extern char *inet_ntoa();
     71 
     72 /*
     73  * Functions to be performed.
     74  */
     75 #define	NONE		0	/* no function */
     76 #define	PMAPDUMP	1	/* dump portmapper registrations */
     77 #define	TCPPING		2	/* ping TCP service */
     78 #define	UDPPING		3	/* ping UDP service */
     79 #define	BRDCST		4	/* ping broadcast UDP service */
     80 #define DELETES		5	/* delete registration for the service */
     81 
     82 int
     83 main(argc, argv)
     84 	int argc;
     85 	char **argv;
     86 {
     87 	register int c;
     88 	extern char *optarg;
     89 	extern int optind;
     90 	int errflg;
     91 	int function;
     92 	u_short portnum;
     93 
     94 	function = NONE;
     95 	portnum = 0;
     96 	errflg = 0;
     97 	while ((c = getopt(argc, argv, "ptubdn:")) != EOF) {
     98 		switch (c) {
     99 
    100 		case 'p':
    101 			if (function != NONE)
    102 				errflg = 1;
    103 			else
    104 				function = PMAPDUMP;
    105 			break;
    106 
    107 		case 't':
    108 			if (function != NONE)
    109 				errflg = 1;
    110 			else
    111 				function = TCPPING;
    112 			break;
    113 
    114 		case 'u':
    115 			if (function != NONE)
    116 				errflg = 1;
    117 			else
    118 				function = UDPPING;
    119 			break;
    120 
    121 		case 'b':
    122 			if (function != NONE)
    123 				errflg = 1;
    124 			else
    125 				function = BRDCST;
    126 			break;
    127 
    128 		case 'n':
    129 			portnum = (u_short) atoi(optarg);   /* hope we don't get bogus # */
    130 			break;
    131 
    132 		case 'd':
    133 			if (function != NONE)
    134 				errflg = 1;
    135 			else
    136 				function = DELETES;
    137 			break;
    138 
    139 		case '?':
    140 			errflg = 1;
    141 		}
    142 	}
    143 
    144 	if (errflg || function == NONE) {
    145 		usage();
    146 		return (1);
    147 	}
    148 
    149 	switch (function) {
    150 
    151 	case PMAPDUMP:
    152 		if (portnum != 0) {
    153 			usage();
    154 			return (1);
    155 		}
    156 		pmapdump(argc - optind, argv + optind);
    157 		break;
    158 
    159 	case UDPPING:
    160 		udpping(portnum, argc - optind, argv + optind);
    161 		break;
    162 
    163 	case TCPPING:
    164 		tcpping(portnum, argc - optind, argv + optind);
    165 		break;
    166 
    167 	case BRDCST:
    168 		if (portnum != 0) {
    169 			usage();
    170 			return (1);
    171 		}
    172 		brdcst(argc - optind, argv + optind);
    173 		break;
    174 
    175 	case DELETES:
    176 		deletereg(argc - optind, argv + optind);
    177 		break;
    178 	}
    179 
    180 	return (0);
    181 }
    182 
    183 static void
    184 udpping(portnum, argc, argv)
    185 	u_short portnum;
    186 	int argc;
    187 	char **argv;
    188 {
    189 	struct timeval to;
    190 	struct sockaddr_in addr;
    191 	enum clnt_stat rpc_stat;
    192 	CLIENT *client;
    193 	u_long prognum, vers, minvers, maxvers;
    194 	int sock = RPC_ANYSOCK;
    195 	struct rpc_err rpcerr;
    196 	int failure;
    197 
    198 	if (argc < 2 || argc > 3) {
    199 		usage();
    200 		exit(1);
    201 	}
    202 	prognum = getprognum(argv[1]);
    203 	get_inet_address(&addr, argv[0]);
    204 	/* Open the socket here so it will survive calls to clnt_destroy */
    205 	sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    206 	if (sock < 0) {
    207 		perror("rpcinfo: socket");
    208 		exit(1);
    209 	}
    210 	failure = 0;
    211 	if (argc == 2) {
    212 		/*
    213 		 * A call to version 0 should fail with a program/version
    214 		 * mismatch, and give us the range of versions supported.
    215 		 */
    216 		addr.sin_port = htons(portnum);
    217 		to.tv_sec = 5;
    218 		to.tv_usec = 0;
    219 		if ((client = clntudp_create(&addr, prognum, (u_long)0,
    220 		    to, &sock)) == NULL) {
    221 			clnt_pcreateerror("rpcinfo");
    222 			printf("program %lu is not available\n",
    223 			    prognum);
    224 			exit(1);
    225 		}
    226 		to.tv_sec = 10;
    227 		to.tv_usec = 0;
    228 		rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
    229 		    xdr_void, (char *)NULL, to);
    230 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
    231 			clnt_geterr(client, &rpcerr);
    232 			minvers = rpcerr.re_vers.low;
    233 			maxvers = rpcerr.re_vers.high;
    234 		} else if (rpc_stat == RPC_SUCCESS) {
    235 			/*
    236 			 * Oh dear, it DOES support version 0.
    237 			 * Let's try version MAX_VERS.
    238 			 */
    239 			addr.sin_port = htons(portnum);
    240 			to.tv_sec = 5;
    241 			to.tv_usec = 0;
    242 			if ((client = clntudp_create(&addr, prognum, MAX_VERS,
    243 			    to, &sock)) == NULL) {
    244 				clnt_pcreateerror("rpcinfo");
    245 				printf("program %lu version %lu is not available\n",
    246 				    prognum, MAX_VERS);
    247 				exit(1);
    248 			}
    249 			to.tv_sec = 10;
    250 			to.tv_usec = 0;
    251 			rpc_stat = clnt_call(client, NULLPROC, xdr_void,
    252 			    (char *)NULL, xdr_void, (char *)NULL, to);
    253 			if (rpc_stat == RPC_PROGVERSMISMATCH) {
    254 				clnt_geterr(client, &rpcerr);
    255 				minvers = rpcerr.re_vers.low;
    256 				maxvers = rpcerr.re_vers.high;
    257 			} else if (rpc_stat == RPC_SUCCESS) {
    258 				/*
    259 				 * It also supports version MAX_VERS.
    260 				 * Looks like we have a wise guy.
    261 				 * OK, we give them information on all
    262 				 * 4 billion versions they support...
    263 				 */
    264 				minvers = 0;
    265 				maxvers = MAX_VERS;
    266 			} else {
    267 				(void) pstatus(client, prognum, MAX_VERS);
    268 				exit(1);
    269 			}
    270 		} else {
    271 			(void) pstatus(client, prognum, (u_long)0);
    272 			exit(1);
    273 		}
    274 		clnt_destroy(client);
    275 		for (vers = minvers; vers <= maxvers; vers++) {
    276 			addr.sin_port = htons(portnum);
    277 			to.tv_sec = 5;
    278 			to.tv_usec = 0;
    279 			if ((client = clntudp_create(&addr, prognum, vers,
    280 			    to, &sock)) == NULL) {
    281 				clnt_pcreateerror("rpcinfo");
    282 				printf("program %lu version %lu is not available\n",
    283 				    prognum, vers);
    284 				exit(1);
    285 			}
    286 			to.tv_sec = 10;
    287 			to.tv_usec = 0;
    288 			rpc_stat = clnt_call(client, NULLPROC, xdr_void,
    289 			    (char *)NULL, xdr_void, (char *)NULL, to);
    290 			if (pstatus(client, prognum, vers) < 0)
    291 				failure = 1;
    292 			clnt_destroy(client);
    293 		}
    294 	}
    295 	else {
    296 		vers = getvers(argv[2]);
    297 		addr.sin_port = htons(portnum);
    298 		to.tv_sec = 5;
    299 		to.tv_usec = 0;
    300 		if ((client = clntudp_create(&addr, prognum, vers,
    301 		    to, &sock)) == NULL) {
    302 			clnt_pcreateerror("rpcinfo");
    303 			printf("program %lu version %lu is not available\n",
    304 			    prognum, vers);
    305 			exit(1);
    306 		}
    307 		to.tv_sec = 10;
    308 		to.tv_usec = 0;
    309 		rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
    310 		    xdr_void, (char *)NULL, to);
    311 		if (pstatus(client, prognum, vers) < 0)
    312 			failure = 1;
    313 	}
    314 	(void) close(sock); /* Close it up again */
    315 	if (failure)
    316 		exit(1);
    317 }
    318 
    319 static void
    320 tcpping(portnum, argc, argv)
    321 	u_short portnum;
    322 	int argc;
    323 	char **argv;
    324 {
    325 	struct timeval to;
    326 	struct sockaddr_in addr;
    327 	enum clnt_stat rpc_stat;
    328 	CLIENT *client;
    329 	u_long prognum, vers, minvers, maxvers;
    330 	int sock = RPC_ANYSOCK;
    331 	struct rpc_err rpcerr;
    332 	int failure;
    333 
    334 	if (argc < 2 || argc > 3) {
    335 		usage();
    336 		exit(1);
    337 	}
    338 	prognum = getprognum(argv[1]);
    339 	get_inet_address(&addr, argv[0]);
    340 	failure = 0;
    341 	if (argc == 2) {
    342 		/*
    343 		 * A call to version 0 should fail with a program/version
    344 		 * mismatch, and give us the range of versions supported.
    345 		 */
    346 		addr.sin_port = htons(portnum);
    347 		if ((client = clnttcp_create(&addr, prognum, MIN_VERS,
    348 		    &sock, 0, 0)) == NULL) {
    349 			clnt_pcreateerror("rpcinfo");
    350 			printf("program %lu is not available\n",
    351 			    prognum);
    352 			exit(1);
    353 		}
    354 		to.tv_sec = 10;
    355 		to.tv_usec = 0;
    356 		rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL,
    357 		    xdr_void, (char *)NULL, to);
    358 		if (rpc_stat == RPC_PROGVERSMISMATCH) {
    359 			clnt_geterr(client, &rpcerr);
    360 			minvers = rpcerr.re_vers.low;
    361 			maxvers = rpcerr.re_vers.high;
    362 		} else if (rpc_stat == RPC_SUCCESS) {
    363 			/*
    364 			 * Oh dear, it DOES support version 0.
    365 			 * Let's try version MAX_VERS.
    366 			 */
    367 			addr.sin_port = htons(portnum);
    368 			if ((client = clnttcp_create(&addr, prognum, MAX_VERS,
    369 			    &sock, 0, 0)) == NULL) {
    370 				clnt_pcreateerror("rpcinfo");
    371 				printf("program %lu version %lu is not available\n",
    372 				    prognum, MAX_VERS);
    373 				exit(1);
    374 			}
    375 			to.tv_sec = 10;
    376 			to.tv_usec = 0;
    377 			rpc_stat = clnt_call(client, NULLPROC, xdr_void,
    378 			    (char *)NULL, xdr_void, (char *)NULL, to);
    379 			if (rpc_stat == RPC_PROGVERSMISMATCH) {
    380 				clnt_geterr(client, &rpcerr);
    381 				minvers = rpcerr.re_vers.low;
    382 				maxvers = rpcerr.re_vers.high;
    383 			} else if (rpc_stat == RPC_SUCCESS) {
    384 				/*
    385 				 * It also supports version MAX_VERS.
    386 				 * Looks like we have a wise guy.
    387 				 * OK, we give them information on all
    388 				 * 4 billion versions they support...
    389 				 */
    390 				minvers = 0;
    391 				maxvers = MAX_VERS;
    392 			} else {
    393 				(void) pstatus(client, prognum, MAX_VERS);
    394 				exit(1);
    395 			}
    396 		} else {
    397 			(void) pstatus(client, prognum, MIN_VERS);
    398 			exit(1);
    399 		}
    400 		clnt_destroy(client);
    401 		(void) close(sock);
    402 		sock = RPC_ANYSOCK; /* Re-initialize it for later */
    403 		for (vers = minvers; vers <= maxvers; vers++) {
    404 			addr.sin_port = htons(portnum);
    405 			if ((client = clnttcp_create(&addr, prognum, vers,
    406 			    &sock, 0, 0)) == NULL) {
    407 				clnt_pcreateerror("rpcinfo");
    408 				printf("program %lu version %lu is not available\n",
    409 				    prognum, vers);
    410 				exit(1);
    411 			}
    412 			to.tv_usec = 0;
    413 			to.tv_sec = 10;
    414 			rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
    415 			    xdr_void, (char *)NULL, to);
    416 			if (pstatus(client, prognum, vers) < 0)
    417 				failure = 1;
    418 			clnt_destroy(client);
    419 			(void) close(sock);
    420 			sock = RPC_ANYSOCK;
    421 		}
    422 	}
    423 	else {
    424 		vers = getvers(argv[2]);
    425 		addr.sin_port = htons(portnum);
    426 		if ((client = clnttcp_create(&addr, prognum, vers, &sock,
    427 		    0, 0)) == NULL) {
    428 			clnt_pcreateerror("rpcinfo");
    429 			printf("program %lu version %lu is not available\n",
    430 			    prognum, vers);
    431 			exit(1);
    432 		}
    433 		to.tv_usec = 0;
    434 		to.tv_sec = 10;
    435 		rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL,
    436 		    xdr_void, (char *)NULL, to);
    437 		if (pstatus(client, prognum, vers) < 0)
    438 			failure = 1;
    439 	}
    440 	if (failure)
    441 		exit(1);
    442 }
    443 
    444 /*
    445  * This routine should take a pointer to an "rpc_err" structure, rather than
    446  * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
    447  * a CLIENT structure rather than a pointer to an "rpc_err" structure.
    448  * As such, we have to keep the CLIENT structure around in order to print
    449  * a good error message.
    450  */
    451 static int
    452 pstatus(client, prognum, vers)
    453 	register CLIENT *client;
    454 	u_long prognum;
    455 	u_long vers;
    456 {
    457 	struct rpc_err rpcerr;
    458 
    459 	clnt_geterr(client, &rpcerr);
    460 	if (rpcerr.re_status != RPC_SUCCESS) {
    461 		clnt_perror(client, "rpcinfo");
    462 		printf("program %lu version %lu is not available\n",
    463 		    prognum, vers);
    464 		return (-1);
    465 	} else {
    466 		printf("program %lu version %lu ready and waiting\n",
    467 		    prognum, vers);
    468 		return (0);
    469 	}
    470 }
    471 
    472 static void
    473 pmapdump(argc, argv)
    474 	int argc;
    475 	char **argv;
    476 {
    477 	struct sockaddr_in server_addr;
    478 	register struct hostent *hp;
    479 	struct pmaplist *head = NULL;
    480 	int socket = RPC_ANYSOCK;
    481 	struct timeval minutetimeout;
    482 	register CLIENT *client;
    483 	struct rpcent *rpc;
    484 
    485 	if (argc > 1) {
    486 		usage();
    487 		exit(1);
    488 	}
    489 	if (argc == 1)
    490 		get_inet_address(&server_addr, argv[0]);
    491 	else {
    492 		bzero((char *)&server_addr, sizeof server_addr);
    493 		server_addr.sin_family = AF_INET;
    494 		if ((hp = gethostbyname("localhost")) != NULL)
    495 			bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr,
    496 			    hp->h_length);
    497 		else
    498 			server_addr.sin_addr.s_addr = inet_addr("0.0.0.0");
    499 	}
    500 	minutetimeout.tv_sec = 60;
    501 	minutetimeout.tv_usec = 0;
    502 	server_addr.sin_port = htons(PMAPPORT);
    503 	if ((client = clnttcp_create(&server_addr, PMAPPROG,
    504 	    PMAPVERS, &socket, 50, 500)) == NULL) {
    505 		clnt_pcreateerror("rpcinfo: can't contact portmapper");
    506 		exit(1);
    507 	}
    508 	if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL,
    509 	    xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) {
    510 		fprintf(stderr, "rpcinfo: can't contact portmapper: ");
    511 		clnt_perror(client, "rpcinfo");
    512 		exit(1);
    513 	}
    514 	if (head == NULL) {
    515 		printf("No remote programs registered.\n");
    516 	} else {
    517 		printf("   program vers proto   port\n");
    518 		for (; head != NULL; head = head->pml_next) {
    519 			printf("%10ld%5ld",
    520 			    head->pml_map.pm_prog,
    521 			    head->pml_map.pm_vers);
    522 			if (head->pml_map.pm_prot == IPPROTO_UDP)
    523 				printf("%6s",  "udp");
    524 			else if (head->pml_map.pm_prot == IPPROTO_TCP)
    525 				printf("%6s", "tcp");
    526 			else
    527 				printf("%6ld",  head->pml_map.pm_prot);
    528 			printf("%7ld",  head->pml_map.pm_port);
    529 			rpc = getrpcbynumber(head->pml_map.pm_prog);
    530 			if (rpc)
    531 				printf("  %s\n", rpc->r_name);
    532 			else
    533 				printf("\n");
    534 		}
    535 	}
    536 }
    537 
    538 /*
    539  * reply_proc collects replies from the broadcast.
    540  * to get a unique list of responses the output of rpcinfo should
    541  * be piped through sort(1) and then uniq(1).
    542  */
    543 
    544 /*ARGSUSED*/
    545 static bool_t
    546 reply_proc(res, who)
    547 	void *res;		/* Nothing comes back */
    548 	struct sockaddr_in *who; /* Who sent us the reply */
    549 {
    550 	register struct hostent *hp;
    551 
    552 	hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr,
    553 	    AF_INET);
    554 	printf("%s %s\n", inet_ntoa(who->sin_addr),
    555 	    (hp == NULL) ? "(unknown)" : hp->h_name);
    556 	return(FALSE);
    557 }
    558 
    559 static void
    560 brdcst(argc, argv)
    561 	int argc;
    562 	char **argv;
    563 {
    564 	enum clnt_stat rpc_stat;
    565 	u_long prognum, vers;
    566 
    567 	if (argc != 2) {
    568 		usage();
    569 		exit(1);
    570 	}
    571 	prognum = getprognum(argv[0]);
    572 	vers = getvers(argv[1]);
    573 	rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void,
    574 	    (char *)NULL, xdr_void, (char *)NULL, reply_proc);
    575 	if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) {
    576 		fprintf(stderr, "rpcinfo: broadcast failed: %s\n",
    577 		    clnt_sperrno(rpc_stat));
    578 		exit(1);
    579 	}
    580 	exit(0);
    581 }
    582 
    583 static void
    584 deletereg(argc, argv)
    585 	int argc;
    586 	char **argv;
    587 {	u_long prog_num, version_num ;
    588 
    589 	if (argc != 2) {
    590 		usage() ;
    591 		exit(1) ;
    592 	}
    593 	if (getuid()) { /* This command allowed only to root */
    594 		fprintf(stderr, "Sorry. You are not root\n") ;
    595 		exit(1) ;
    596 	}
    597 	prog_num = getprognum(argv[0]);
    598 	version_num = getvers(argv[1]);
    599 	if ((pmap_unset(prog_num, version_num)) == 0) {
    600 		fprintf(stderr, "rpcinfo: Could not delete registration for prog %s version %s\n",
    601 			argv[0], argv[1]) ;
    602 		exit(1) ;
    603 	}
    604 }
    605 
    606 static void
    607 usage()
    608 {
    609 	fprintf(stderr, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n");
    610 	fprintf(stderr, "       rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n");
    611 	fprintf(stderr, "       rpcinfo -p [ host ]\n");
    612 	fprintf(stderr, "       rpcinfo -b prognum versnum\n");
    613 	fprintf(stderr, "       rpcinfo -d prognum versnum\n") ;
    614 }
    615 
    616 static u_long
    617 getprognum(arg)
    618 	char *arg;
    619 {
    620 	register struct rpcent *rpc;
    621 	register u_long prognum;
    622 
    623 	if (isalpha(*arg)) {
    624 		rpc = getrpcbyname(arg);
    625 		if (rpc == NULL) {
    626 			fprintf(stderr, "rpcinfo: %s is unknown service\n",
    627 			    arg);
    628 			exit(1);
    629 		}
    630 		prognum = rpc->r_number;
    631 	} else {
    632 		prognum = (u_long) atoi(arg);
    633 	}
    634 
    635 	return (prognum);
    636 }
    637 
    638 static u_long
    639 getvers(arg)
    640 	char *arg;
    641 {
    642 	register u_long vers;
    643 
    644 	vers = (int) atoi(arg);
    645 	return (vers);
    646 }
    647 
    648 static void
    649 get_inet_address(addr, host)
    650 	struct sockaddr_in *addr;
    651 	char *host;
    652 {
    653 	register struct hostent *hp;
    654 
    655 	bzero((char *)addr, sizeof *addr);
    656 	addr->sin_addr.s_addr = (u_long) inet_addr(host);
    657 	if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) {
    658 		if ((hp = gethostbyname(host)) == NULL) {
    659 			fprintf(stderr, "rpcinfo: %s is unknown host\n", host);
    660 			exit(1);
    661 		}
    662 		bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length);
    663 	}
    664 	addr->sin_family = AF_INET;
    665 }
    666