glibc/sunrpc/rpcinfo.c
Ulrich Drepper bd355af04f Update.
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.
1997-12-14 22:24:57 +00:00

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;
}