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