home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / internet / amitcp3.0b / src.lha / src / util / rpcinfo / rpcinfo.c next >
Encoding:
C/C++ Source or Header  |  1996-09-08  |  17.9 KB  |  708 lines

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