home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / rpcinfo / rpcinfo.c < prev   
Encoding:
C/C++ Source or Header  |  1994-05-23  |  16.4 KB  |  673 lines

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