mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-11-03 20:53:13 +03:00 
			
		
		
		
	1997-12-14 21:33 Ulrich Drepper <drepper@cygnus.com> * version.h (VERSION): Bump to 2.0.91. * db2/makedb.c (process_input): Fix typo in message. * sunrpc/rpcinfo.c (pmapdump): Unify messages. * elf/dynamic-link.h: Pretty print. * elf/rtld.c: Allow multiple preloading of a shared object. * include/limits.h: Prevent multiple inclusion. * malloc/Makefile (headers): Add mcheck.h. (distribute): Remove it here. * malloc/mcheck.h: Pretty print. * malloc/mtrace.c (mallenv): Make `const'. * malloc/mtrace.pl: Don't print table head for memory leaks if there are none. * manual/memory.texi: Update descriptor of malloc hooks. * posix/Makefile (routines): Add waitid. * posix/sys/types.h [__USE_SVID || __USE_POSIX]: Define id_t based on __id_t. * posix/sys/wait.h: Define idtype_t type. Add prototype for waitid. * signal/signal.h: Move definition of sigval_t to <bits/siginfo.h>. * sysdeps/generic/waitid.c: Stub for waitid. * sysdeps/generic/bits/siginfo.h: Define sigval_t. Arrange to work the __need_siginfo_t defined. * sysdeps/unix/sysv/linux/bits/siginfo: Likewise. * sysdeps/generic/bits/types.h: Define __id_t. Correct definition of __FDMASK. * sysdeps/unix/sysv/linux/alpha/bits/types.h: Likewise. * sysdeps/unix/sysv/linux/bits/types.h: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/bits/types.h: Likewise. * sysdeps/posix/waitid.c: New file. Provided by Zack Weinberg. * rt/aio_misc.c: Rename __aio_free_req to __aio_free_request. * sysdeps/alpha/dl-machine.h (ELF_MACHINE_RUNTIME_TRAMPOLINE): Add missing parameters. * sysdeps/generic/dl-sysdep.c: Don't call __libc_init_secure. * sysdeps/generic/enbl-secure.c: Don't define __libc_uid. * sysdeps/unix/sysv/linux/init-first.c: Define __libc_uid. * sysdeps/unix/sysv/linux/sigqueue.c: Make sure __libc_uid is initialized. * sysdeps/i386/dl-machine.h: Little cleanup. * sysdeps/i386/fpu/bits/mathinline.h: Use __signbit* inline functions. (__finite): Mark function as const. Add inline code for __ieee754_atan2. * sysdeps/libm-ieee754/s_cacoshf.c: Add alternate implementation (but don't use it now). * sysdeps/libm-ieee754/s_catan.c: Use __ieee754_atan2 instead of __atan. * sysdeps/libm-ieee754/s_catanf.c: Likewise. * sysdeps/libm-ieee754/s_catanl.c: Likewise. * sysdeps/libm-ieee754/s_catanh.c: Likewise. Correct sign of real part. * sysdeps/libm-ieee754/s_catanhf.c: Likewise. * sysdeps/libm-ieee754/s_catanhl.c: Likewise. * sysdeps/libm-ieee754/s_clog10.c: Use factor to correct __ieee754_atan2 to base 10. * sysdeps/libm-ieee754/s_clog10f.c: Likewise. * sysdeps/libm-ieee754/s_clog10l.c: Likewise. * sysdeps/unix/sysv/linux/alpha/kernel_sigaction.h: Define as old_kernel_sigaction. * sysdeps/unix/sysv/linux/net/if_slip.h: Pretty print. * wctype/Makefile (routines): Add wctype_l. * wctype/wctype.h: Add declaration of __wctype_l. * wctype/wctype_l.c: New file. 1997-12-10 00:38 Ulrich Drepper <drepper@cygnus.com> * locale/C-ctype.c: Correct data for isw* functions. * locale/programs/ld-ctype.c: Write 32bit char classes in correct byte order. * wctype/test_wctype.c: Add test for isw* functions. * wctype/wctype.c: Return value with expected byte order. * sysdeps/generic/_G_config.h: Define _G_HAVE_IO_FILE_OPEN. * sysdeps/unix/sysv/linux/_G_config.h: Likewise.
		
			
				
	
	
		
			740 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			740 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
 | 
						|
/* @(#)rpcinfo.c        2.2 88/08/11 4.0 RPCSRC */
 | 
						|
#if !defined(lint) && defined (SCCSID)
 | 
						|
static char sccsid[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI";
 | 
						|
#endif
 | 
						|
 | 
						|
/*
 | 
						|
 * Copyright (C) 1986, Sun Microsystems, Inc.
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * rpcinfo: ping a particular rpc program
 | 
						|
 *     or dump the portmapper
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
 | 
						|
 * unrestricted use provided that this legend is included on all tape
 | 
						|
 * media and as a part of the software program in whole or part.  Users
 | 
						|
 * may copy or modify Sun RPC without charge, but are not authorized
 | 
						|
 * to license or distribute it to anyone else except as part of a product or
 | 
						|
 * program developed by the user.
 | 
						|
 *
 | 
						|
 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
 | 
						|
 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 | 
						|
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 | 
						|
 *
 | 
						|
 * Sun RPC is provided with no support and without any obligation on the
 | 
						|
 * part of Sun Microsystems, Inc. to assist in its use, correction,
 | 
						|
 * modification or enhancement.
 | 
						|
 *
 | 
						|
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 | 
						|
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
 | 
						|
 * OR ANY PART THEREOF.
 | 
						|
 *
 | 
						|
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 | 
						|
 * or profits or other special, indirect and consequential damages, even if
 | 
						|
 * Sun has been advised of the possibility of such damages.
 | 
						|
 *
 | 
						|
 * Sun Microsystems, Inc.
 | 
						|
 * 2550 Garcia Avenue
 | 
						|
 * Mountain View, California  94043
 | 
						|
 */
 | 
						|
 | 
						|
#include <getopt.h>
 | 
						|
#include <string.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <rpc/rpc.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <sys/socket.h>
 | 
						|
#include <netinet/in.h>
 | 
						|
#include <arpa/inet.h>
 | 
						|
#include <netdb.h>
 | 
						|
#include <rpc/pmap_prot.h>
 | 
						|
#include <rpc/pmap_clnt.h>
 | 
						|
#include <signal.h>
 | 
						|
#include <ctype.h>
 | 
						|
#include <locale.h>
 | 
						|
#include <libintl.h>
 | 
						|
 | 
						|
#define MAXHOSTLEN 256
 | 
						|
 | 
						|
#define	MIN_VERS	((u_long) 0)
 | 
						|
#define	MAX_VERS	((u_long) 4294967295UL)
 | 
						|
 | 
						|
static void udpping (u_short portflag, int argc, char **argv);
 | 
						|
static void tcpping (u_short portflag, int argc, char **argv);
 | 
						|
static int pstatus (CLIENT *client, u_long prognum, u_long vers);
 | 
						|
static void pmapdump (int argc, char **argv);
 | 
						|
static bool_t reply_proc (void *res, struct sockaddr_in *who);
 | 
						|
static void brdcst (int argc, char **argv);
 | 
						|
static void deletereg (int argc, char **argv);
 | 
						|
static void usage (void);
 | 
						|
static u_long getprognum (char *arg);
 | 
						|
static u_long getvers (char *arg);
 | 
						|
static void get_inet_address (struct sockaddr_in *addr, char *host);
 | 
						|
 | 
						|
/*
 | 
						|
 * Functions to be performed.
 | 
						|
 */
 | 
						|
#define	NONE		0	/* no function */
 | 
						|
#define	PMAPDUMP	1	/* dump portmapper registrations */
 | 
						|
#define	TCPPING		2	/* ping TCP service */
 | 
						|
#define	UDPPING		3	/* ping UDP service */
 | 
						|
#define	BRDCST		4	/* ping broadcast UDP service */
 | 
						|
#define DELETES		5	/* delete registration for the service */
 | 
						|
 | 
						|
int
 | 
						|
main (int argc, char **argv)
 | 
						|
{
 | 
						|
  register int c;
 | 
						|
  int errflg;
 | 
						|
  int function;
 | 
						|
  u_short portnum;
 | 
						|
 | 
						|
  setlocale (LC_ALL, "");
 | 
						|
  textdomain (_libc_intl_domainname);
 | 
						|
 | 
						|
  function = NONE;
 | 
						|
  portnum = 0;
 | 
						|
  errflg = 0;
 | 
						|
  while ((c = getopt (argc, argv, "ptubdn:")) != -1)
 | 
						|
    {
 | 
						|
      switch (c)
 | 
						|
	{
 | 
						|
 | 
						|
	case 'p':
 | 
						|
	  if (function != NONE)
 | 
						|
	    errflg = 1;
 | 
						|
	  else
 | 
						|
	    function = PMAPDUMP;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 't':
 | 
						|
	  if (function != NONE)
 | 
						|
	    errflg = 1;
 | 
						|
	  else
 | 
						|
	    function = TCPPING;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'u':
 | 
						|
	  if (function != NONE)
 | 
						|
	    errflg = 1;
 | 
						|
	  else
 | 
						|
	    function = UDPPING;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'b':
 | 
						|
	  if (function != NONE)
 | 
						|
	    errflg = 1;
 | 
						|
	  else
 | 
						|
	    function = BRDCST;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'n':
 | 
						|
	  portnum = (u_short) atoi (optarg);	/* hope we don't get bogus # */
 | 
						|
	  break;
 | 
						|
 | 
						|
	case 'd':
 | 
						|
	  if (function != NONE)
 | 
						|
	    errflg = 1;
 | 
						|
	  else
 | 
						|
	    function = DELETES;
 | 
						|
	  break;
 | 
						|
 | 
						|
	case '?':
 | 
						|
	  errflg = 1;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  if (errflg || function == NONE)
 | 
						|
    {
 | 
						|
      usage ();
 | 
						|
      return 1;
 | 
						|
    }
 | 
						|
 | 
						|
  switch (function)
 | 
						|
    {
 | 
						|
 | 
						|
    case PMAPDUMP:
 | 
						|
      if (portnum != 0)
 | 
						|
	{
 | 
						|
	  usage ();
 | 
						|
	  return 1;
 | 
						|
	}
 | 
						|
      pmapdump (argc - optind, argv + optind);
 | 
						|
      break;
 | 
						|
 | 
						|
    case UDPPING:
 | 
						|
      udpping (portnum, argc - optind, argv + optind);
 | 
						|
      break;
 | 
						|
 | 
						|
    case TCPPING:
 | 
						|
      tcpping (portnum, argc - optind, argv + optind);
 | 
						|
      break;
 | 
						|
 | 
						|
    case BRDCST:
 | 
						|
      if (portnum != 0)
 | 
						|
	{
 | 
						|
	  usage ();
 | 
						|
	  return 1;
 | 
						|
	}
 | 
						|
      brdcst (argc - optind, argv + optind);
 | 
						|
      break;
 | 
						|
 | 
						|
    case DELETES:
 | 
						|
      deletereg (argc - optind, argv + optind);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
udpping (portnum, argc, argv)
 | 
						|
     u_short portnum;
 | 
						|
     int argc;
 | 
						|
     char **argv;
 | 
						|
{
 | 
						|
  struct timeval to;
 | 
						|
  struct sockaddr_in addr;
 | 
						|
  enum clnt_stat rpc_stat;
 | 
						|
  CLIENT *client;
 | 
						|
  u_long prognum, vers, minvers, maxvers;
 | 
						|
  int sock = RPC_ANYSOCK;
 | 
						|
  struct rpc_err rpcerr;
 | 
						|
  int failure;
 | 
						|
 | 
						|
  if (argc < 2 || argc > 3)
 | 
						|
    {
 | 
						|
      usage ();
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  prognum = getprognum (argv[1]);
 | 
						|
  get_inet_address (&addr, argv[0]);
 | 
						|
  /* Open the socket here so it will survive calls to clnt_destroy */
 | 
						|
  sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
 | 
						|
  if (sock < 0)
 | 
						|
    {
 | 
						|
      perror ("rpcinfo: socket");
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  failure = 0;
 | 
						|
  if (argc == 2)
 | 
						|
    {
 | 
						|
      /*
 | 
						|
       * A call to version 0 should fail with a program/version
 | 
						|
       * mismatch, and give us the range of versions supported.
 | 
						|
       */
 | 
						|
      addr.sin_port = htons (portnum);
 | 
						|
      to.tv_sec = 5;
 | 
						|
      to.tv_usec = 0;
 | 
						|
      if ((client = clntudp_create (&addr, prognum, (u_long) 0,
 | 
						|
				    to, &sock)) == NULL)
 | 
						|
	{
 | 
						|
	  clnt_pcreateerror ("rpcinfo");
 | 
						|
	  printf (_("program %lu is not available\n"), prognum);
 | 
						|
	  exit (1);
 | 
						|
	}
 | 
						|
      to.tv_sec = 10;
 | 
						|
      to.tv_usec = 0;
 | 
						|
      rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
 | 
						|
			    (char *) NULL, (xdrproc_t) xdr_void,
 | 
						|
			    (char *) NULL, to);
 | 
						|
      if (rpc_stat == RPC_PROGVERSMISMATCH)
 | 
						|
	{
 | 
						|
	  clnt_geterr (client, &rpcerr);
 | 
						|
	  minvers = rpcerr.re_vers.low;
 | 
						|
	  maxvers = rpcerr.re_vers.high;
 | 
						|
	}
 | 
						|
      else if (rpc_stat == RPC_SUCCESS)
 | 
						|
	{
 | 
						|
	  /*
 | 
						|
	   * Oh dear, it DOES support version 0.
 | 
						|
	   * Let's try version MAX_VERS.
 | 
						|
	   */
 | 
						|
	  addr.sin_port = htons (portnum);
 | 
						|
	  to.tv_sec = 5;
 | 
						|
	  to.tv_usec = 0;
 | 
						|
	  if ((client = clntudp_create (&addr, prognum, MAX_VERS,
 | 
						|
					to, &sock)) == NULL)
 | 
						|
	    {
 | 
						|
	      clnt_pcreateerror ("rpcinfo");
 | 
						|
	      printf (_("program %lu version %lu is not available\n"),
 | 
						|
		      prognum, MAX_VERS);
 | 
						|
	      exit (1);
 | 
						|
	    }
 | 
						|
	  to.tv_sec = 10;
 | 
						|
	  to.tv_usec = 0;
 | 
						|
	  rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
 | 
						|
				NULL, (xdrproc_t) xdr_void, NULL, to);
 | 
						|
	  if (rpc_stat == RPC_PROGVERSMISMATCH)
 | 
						|
	    {
 | 
						|
	      clnt_geterr (client, &rpcerr);
 | 
						|
	      minvers = rpcerr.re_vers.low;
 | 
						|
	      maxvers = rpcerr.re_vers.high;
 | 
						|
	    }
 | 
						|
	  else if (rpc_stat == RPC_SUCCESS)
 | 
						|
	    {
 | 
						|
	      /*
 | 
						|
	       * It also supports version MAX_VERS.
 | 
						|
	       * Looks like we have a wise guy.
 | 
						|
	       * OK, we give them information on all
 | 
						|
	       * 4 billion versions they support...
 | 
						|
	       */
 | 
						|
	      minvers = 0;
 | 
						|
	      maxvers = MAX_VERS;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      (void) pstatus (client, prognum, MAX_VERS);
 | 
						|
	      exit (1);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  (void) pstatus (client, prognum, (u_long) 0);
 | 
						|
	  exit (1);
 | 
						|
	}
 | 
						|
      clnt_destroy (client);
 | 
						|
      for (vers = minvers; vers <= maxvers; vers++)
 | 
						|
	{
 | 
						|
	  addr.sin_port = htons (portnum);
 | 
						|
	  to.tv_sec = 5;
 | 
						|
	  to.tv_usec = 0;
 | 
						|
	  if ((client = clntudp_create (&addr, prognum, vers,
 | 
						|
					to, &sock)) == NULL)
 | 
						|
	    {
 | 
						|
	      clnt_pcreateerror ("rpcinfo");
 | 
						|
	      printf (_("program %lu version %lu is not available\n"),
 | 
						|
		      prognum, vers);
 | 
						|
	      exit (1);
 | 
						|
	    }
 | 
						|
	  to.tv_sec = 10;
 | 
						|
	  to.tv_usec = 0;
 | 
						|
	  rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
 | 
						|
				NULL, (xdrproc_t) xdr_void, NULL, to);
 | 
						|
	  if (pstatus (client, prognum, vers) < 0)
 | 
						|
	    failure = 1;
 | 
						|
	  clnt_destroy (client);
 | 
						|
	}
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      vers = getvers (argv[2]);
 | 
						|
      addr.sin_port = htons (portnum);
 | 
						|
      to.tv_sec = 5;
 | 
						|
      to.tv_usec = 0;
 | 
						|
      if ((client = clntudp_create (&addr, prognum, vers,
 | 
						|
				    to, &sock)) == NULL)
 | 
						|
	{
 | 
						|
	  clnt_pcreateerror ("rpcinfo");
 | 
						|
	  printf (_("program %lu version %lu is not available\n"),
 | 
						|
		  prognum, vers);
 | 
						|
	  exit (1);
 | 
						|
	}
 | 
						|
      to.tv_sec = 10;
 | 
						|
      to.tv_usec = 0;
 | 
						|
      rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
 | 
						|
			    (xdrproc_t) xdr_void, NULL, to);
 | 
						|
      if (pstatus (client, prognum, vers) < 0)
 | 
						|
	failure = 1;
 | 
						|
    }
 | 
						|
  (void) close (sock);		/* Close it up again */
 | 
						|
  if (failure)
 | 
						|
    exit (1);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
tcpping (portnum, argc, argv)
 | 
						|
     u_short portnum;
 | 
						|
     int argc;
 | 
						|
     char **argv;
 | 
						|
{
 | 
						|
  struct timeval to;
 | 
						|
  struct sockaddr_in addr;
 | 
						|
  enum clnt_stat rpc_stat;
 | 
						|
  CLIENT *client;
 | 
						|
  u_long prognum, vers, minvers, maxvers;
 | 
						|
  int sock = RPC_ANYSOCK;
 | 
						|
  struct rpc_err rpcerr;
 | 
						|
  int failure;
 | 
						|
 | 
						|
  if (argc < 2 || argc > 3)
 | 
						|
    {
 | 
						|
      usage ();
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  prognum = getprognum (argv[1]);
 | 
						|
  get_inet_address (&addr, argv[0]);
 | 
						|
  failure = 0;
 | 
						|
  if (argc == 2)
 | 
						|
    {
 | 
						|
      /*
 | 
						|
       * A call to version 0 should fail with a program/version
 | 
						|
       * mismatch, and give us the range of versions supported.
 | 
						|
       */
 | 
						|
      addr.sin_port = htons (portnum);
 | 
						|
      if ((client = clnttcp_create (&addr, prognum, MIN_VERS,
 | 
						|
				    &sock, 0, 0)) == NULL)
 | 
						|
	{
 | 
						|
	  clnt_pcreateerror ("rpcinfo");
 | 
						|
	  printf (_("program %lu is not available\n"), prognum);
 | 
						|
	  exit (1);
 | 
						|
	}
 | 
						|
      to.tv_sec = 10;
 | 
						|
      to.tv_usec = 0;
 | 
						|
      rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void, NULL,
 | 
						|
			    (xdrproc_t) xdr_void, NULL, to);
 | 
						|
      if (rpc_stat == RPC_PROGVERSMISMATCH)
 | 
						|
	{
 | 
						|
	  clnt_geterr (client, &rpcerr);
 | 
						|
	  minvers = rpcerr.re_vers.low;
 | 
						|
	  maxvers = rpcerr.re_vers.high;
 | 
						|
	}
 | 
						|
      else if (rpc_stat == RPC_SUCCESS)
 | 
						|
	{
 | 
						|
	  /*
 | 
						|
	   * Oh dear, it DOES support version 0.
 | 
						|
	   * Let's try version MAX_VERS.
 | 
						|
	   */
 | 
						|
	  addr.sin_port = htons (portnum);
 | 
						|
	  if ((client = clnttcp_create (&addr, prognum, MAX_VERS,
 | 
						|
					&sock, 0, 0)) == NULL)
 | 
						|
	    {
 | 
						|
	      clnt_pcreateerror ("rpcinfo");
 | 
						|
	      printf (_("program %lu version %lu is not available\n"),
 | 
						|
		      prognum, MAX_VERS);
 | 
						|
	      exit (1);
 | 
						|
	    }
 | 
						|
	  to.tv_sec = 10;
 | 
						|
	  to.tv_usec = 0;
 | 
						|
	  rpc_stat = clnt_call (client, NULLPROC, (xdrproc_t) xdr_void,
 | 
						|
				NULL, (xdrproc_t) xdr_void, NULL, to);
 | 
						|
	  if (rpc_stat == RPC_PROGVERSMISMATCH)
 | 
						|
	    {
 | 
						|
	      clnt_geterr (client, &rpcerr);
 | 
						|
	      minvers = rpcerr.re_vers.low;
 | 
						|
	      maxvers = rpcerr.re_vers.high;
 | 
						|
	    }
 | 
						|
	  else if (rpc_stat == RPC_SUCCESS)
 | 
						|
	    {
 | 
						|
	      /*
 | 
						|
	       * It also supports version MAX_VERS.
 | 
						|
	       * Looks like we have a wise guy.
 | 
						|
	       * OK, we give them information on all
 | 
						|
	       * 4 billion versions they support...
 | 
						|
	       */
 | 
						|
	      minvers = 0;
 | 
						|
	      maxvers = MAX_VERS;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      (void) pstatus (client, prognum, MAX_VERS);
 | 
						|
	      exit (1);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  (void) pstatus (client, prognum, MIN_VERS);
 | 
						|
	  exit (1);
 | 
						|
	}
 | 
						|
      clnt_destroy (client);
 | 
						|
      (void) close (sock);
 | 
						|
      sock = RPC_ANYSOCK;	/* Re-initialize it for later */
 | 
						|
      for (vers = minvers; vers <= maxvers; vers++)
 | 
						|
	{
 | 
						|
	  addr.sin_port = htons (portnum);
 | 
						|
	  if ((client = clnttcp_create (&addr, prognum, vers,
 | 
						|
					&sock, 0, 0)) == NULL)
 | 
						|
	    {
 | 
						|
	      clnt_pcreateerror ("rpcinfo");
 | 
						|
	      printf (_("program %lu version %lu is not available\n"),
 | 
						|
		      prognum, vers);
 | 
						|
	      exit (1);
 | 
						|
	    }
 | 
						|
	  to.tv_usec = 0;
 | 
						|
	  to.tv_sec = 10;
 | 
						|
	  rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
 | 
						|
				(xdrproc_t) xdr_void, NULL, to);
 | 
						|
	  if (pstatus (client, prognum, vers) < 0)
 | 
						|
	    failure = 1;
 | 
						|
	  clnt_destroy (client);
 | 
						|
	  (void) close (sock);
 | 
						|
	  sock = RPC_ANYSOCK;
 | 
						|
	}
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      vers = getvers (argv[2]);
 | 
						|
      addr.sin_port = htons (portnum);
 | 
						|
      if ((client = clnttcp_create (&addr, prognum, vers, &sock,
 | 
						|
				    0, 0)) == NULL)
 | 
						|
	{
 | 
						|
	  clnt_pcreateerror ("rpcinfo");
 | 
						|
	  printf (_("program %lu version %lu is not available\n"),
 | 
						|
		  prognum, vers);
 | 
						|
	  exit (1);
 | 
						|
	}
 | 
						|
      to.tv_usec = 0;
 | 
						|
      to.tv_sec = 10;
 | 
						|
      rpc_stat = clnt_call (client, 0, (xdrproc_t) xdr_void, NULL,
 | 
						|
			    (xdrproc_t) xdr_void, NULL, to);
 | 
						|
      if (pstatus (client, prognum, vers) < 0)
 | 
						|
	failure = 1;
 | 
						|
    }
 | 
						|
  if (failure)
 | 
						|
    exit (1);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * This routine should take a pointer to an "rpc_err" structure, rather than
 | 
						|
 * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
 | 
						|
 * a CLIENT structure rather than a pointer to an "rpc_err" structure.
 | 
						|
 * As such, we have to keep the CLIENT structure around in order to print
 | 
						|
 * a good error message.
 | 
						|
 */
 | 
						|
static int
 | 
						|
pstatus (client, prognum, vers)
 | 
						|
     register CLIENT *client;
 | 
						|
     u_long prognum;
 | 
						|
     u_long vers;
 | 
						|
{
 | 
						|
  struct rpc_err rpcerr;
 | 
						|
 | 
						|
  clnt_geterr (client, &rpcerr);
 | 
						|
  if (rpcerr.re_status != RPC_SUCCESS)
 | 
						|
    {
 | 
						|
      clnt_perror (client, "rpcinfo");
 | 
						|
      printf (_("program %lu version %lu is not available\n"), prognum, vers);
 | 
						|
      return -1;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      printf (_("program %lu version %lu ready and waiting\n"), prognum, vers);
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
pmapdump (argc, argv)
 | 
						|
     int argc;
 | 
						|
     char **argv;
 | 
						|
{
 | 
						|
  struct sockaddr_in server_addr;
 | 
						|
  register struct hostent *hp;
 | 
						|
  struct pmaplist *head = NULL;
 | 
						|
  int socket = RPC_ANYSOCK;
 | 
						|
  struct timeval minutetimeout;
 | 
						|
  register CLIENT *client;
 | 
						|
  struct rpcent *rpc;
 | 
						|
 | 
						|
  if (argc > 1)
 | 
						|
    {
 | 
						|
      usage ();
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  if (argc == 1)
 | 
						|
    get_inet_address (&server_addr, argv[0]);
 | 
						|
  else
 | 
						|
    {
 | 
						|
      bzero ((char *) &server_addr, sizeof server_addr);
 | 
						|
      server_addr.sin_family = AF_INET;
 | 
						|
      if ((hp = gethostbyname ("localhost")) != NULL)
 | 
						|
	bcopy (hp->h_addr, (caddr_t) & server_addr.sin_addr,
 | 
						|
	       hp->h_length);
 | 
						|
      else
 | 
						|
	server_addr.sin_addr.s_addr = inet_addr ("0.0.0.0");
 | 
						|
    }
 | 
						|
  minutetimeout.tv_sec = 60;
 | 
						|
  minutetimeout.tv_usec = 0;
 | 
						|
  server_addr.sin_port = htons (PMAPPORT);
 | 
						|
  if ((client = clnttcp_create (&server_addr, PMAPPROG,
 | 
						|
				PMAPVERS, &socket, 50, 500)) == NULL)
 | 
						|
    {
 | 
						|
      clnt_pcreateerror (_("rpcinfo: can't contact portmapper"));
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  if (clnt_call (client, PMAPPROC_DUMP, (xdrproc_t) xdr_void, NULL,
 | 
						|
		 (xdrproc_t) xdr_pmaplist, (caddr_t) &head,
 | 
						|
		 minutetimeout) != RPC_SUCCESS)
 | 
						|
    {
 | 
						|
      fputs (_("rpcinfo: can't contact portmapper"), stderr);
 | 
						|
      fputs (": ", stderr);
 | 
						|
      clnt_perror (client, "rpcinfo");
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  if (head == NULL)
 | 
						|
    {
 | 
						|
      fputs (_("No remote programs registered.\n"), stdout);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      fputs (_("   program vers proto   port\n"), stdout);
 | 
						|
      for (; head != NULL; head = head->pml_next)
 | 
						|
	{
 | 
						|
	  printf ("%10ld%5ld",
 | 
						|
		  head->pml_map.pm_prog,
 | 
						|
		  head->pml_map.pm_vers);
 | 
						|
	  if (head->pml_map.pm_prot == IPPROTO_UDP)
 | 
						|
	    printf ("%6s", "udp");
 | 
						|
	  else if (head->pml_map.pm_prot == IPPROTO_TCP)
 | 
						|
	    printf ("%6s", "tcp");
 | 
						|
	  else
 | 
						|
	    printf ("%6ld", head->pml_map.pm_prot);
 | 
						|
	  printf ("%7ld", head->pml_map.pm_port);
 | 
						|
	  rpc = getrpcbynumber (head->pml_map.pm_prog);
 | 
						|
	  if (rpc)
 | 
						|
	    printf ("  %s\n", rpc->r_name);
 | 
						|
	  else
 | 
						|
	    printf ("\n");
 | 
						|
	}
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * reply_proc collects replies from the broadcast.
 | 
						|
 * to get a unique list of responses the output of rpcinfo should
 | 
						|
 * be piped through sort(1) and then uniq(1).
 | 
						|
 */
 | 
						|
 | 
						|
/*ARGSUSED */
 | 
						|
static bool_t
 | 
						|
reply_proc (res, who)
 | 
						|
     void *res;			/* Nothing comes back */
 | 
						|
     struct sockaddr_in *who;	/* Who sent us the reply */
 | 
						|
{
 | 
						|
  register struct hostent *hp;
 | 
						|
 | 
						|
  hp = gethostbyaddr ((char *) &who->sin_addr, sizeof who->sin_addr,
 | 
						|
		      AF_INET);
 | 
						|
  printf ("%s %s\n", inet_ntoa (who->sin_addr),
 | 
						|
	  (hp == NULL) ? _("(unknown)") : hp->h_name);
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
brdcst (argc, argv)
 | 
						|
     int argc;
 | 
						|
     char **argv;
 | 
						|
{
 | 
						|
  enum clnt_stat rpc_stat;
 | 
						|
  u_long prognum, vers;
 | 
						|
 | 
						|
  if (argc != 2)
 | 
						|
    {
 | 
						|
      usage ();
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  prognum = getprognum (argv[0]);
 | 
						|
  vers = getvers (argv[1]);
 | 
						|
  rpc_stat = clnt_broadcast (prognum, vers, NULLPROC, (xdrproc_t) xdr_void,
 | 
						|
			     NULL, (xdrproc_t) xdr_void, NULL,
 | 
						|
			     (resultproc_t) reply_proc);
 | 
						|
  if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT))
 | 
						|
    {
 | 
						|
      fprintf (stderr, _("rpcinfo: broadcast failed: %s\n"),
 | 
						|
	       clnt_sperrno (rpc_stat));
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  exit (0);
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
deletereg (argc, argv)
 | 
						|
     int argc;
 | 
						|
     char **argv;
 | 
						|
{
 | 
						|
  u_long prog_num, version_num;
 | 
						|
 | 
						|
  if (argc != 2)
 | 
						|
    {
 | 
						|
      usage ();
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  if (getuid ())
 | 
						|
    {				/* This command allowed only to root */
 | 
						|
      fputs (_("Sorry. You are not root\n"), stderr);
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
  prog_num = getprognum (argv[0]);
 | 
						|
  version_num = getvers (argv[1]);
 | 
						|
  if ((pmap_unset (prog_num, version_num)) == 0)
 | 
						|
    {
 | 
						|
      fprintf (stderr, _("rpcinfo: Could not delete registration for prog %s version %s\n"),
 | 
						|
	       argv[0], argv[1]);
 | 
						|
      exit (1);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
usage ()
 | 
						|
{
 | 
						|
  fputs (_("Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"),
 | 
						|
	 stderr);
 | 
						|
  fputs (_("       rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"),
 | 
						|
	 stderr);
 | 
						|
  fputs (_("       rpcinfo -p [ host ]\n"), stderr);
 | 
						|
  fputs (_("       rpcinfo -b prognum versnum\n"), stderr);
 | 
						|
  fputs (_("       rpcinfo -d prognum versnum\n"), stderr);
 | 
						|
}
 | 
						|
 | 
						|
static u_long
 | 
						|
getprognum (arg)
 | 
						|
     char *arg;
 | 
						|
{
 | 
						|
  register struct rpcent *rpc;
 | 
						|
  register u_long prognum;
 | 
						|
 | 
						|
  if (isalpha (*arg))
 | 
						|
    {
 | 
						|
      rpc = getrpcbyname (arg);
 | 
						|
      if (rpc == NULL)
 | 
						|
	{
 | 
						|
	  fprintf (stderr, _("rpcinfo: %s is unknown service\n"), arg);
 | 
						|
	  exit (1);
 | 
						|
	}
 | 
						|
      prognum = rpc->r_number;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
      prognum = (u_long) atoi (arg);
 | 
						|
    }
 | 
						|
 | 
						|
  return prognum;
 | 
						|
}
 | 
						|
 | 
						|
static u_long
 | 
						|
getvers (arg)
 | 
						|
     char *arg;
 | 
						|
{
 | 
						|
  register u_long vers;
 | 
						|
 | 
						|
  vers = (int) atoi (arg);
 | 
						|
  return vers;
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
get_inet_address (addr, host)
 | 
						|
     struct sockaddr_in *addr;
 | 
						|
     char *host;
 | 
						|
{
 | 
						|
  register struct hostent *hp;
 | 
						|
 | 
						|
  bzero ((char *) addr, sizeof *addr);
 | 
						|
  addr->sin_addr.s_addr = (u_long) inet_addr (host);
 | 
						|
  if (addr->sin_addr.s_addr == INADDR_NONE
 | 
						|
      || addr->sin_addr.s_addr == INADDR_ANY)
 | 
						|
    {
 | 
						|
      if ((hp = gethostbyname (host)) == NULL)
 | 
						|
	{
 | 
						|
	  fprintf (stderr, _("rpcinfo: %s is unknown host\n"),
 | 
						|
		   host);
 | 
						|
	  exit (1);
 | 
						|
	}
 | 
						|
      bcopy (hp->h_addr, (char *) &addr->sin_addr, hp->h_length);
 | 
						|
    }
 | 
						|
  addr->sin_family = AF_INET;
 | 
						|
}
 |