ypwhich(1) totally rewritten by Chuck Cranor <chuck@ccrc.wustl.edu>.

fixes various nits in the behaviour of the '-m' option, amongst
other things. update the docco to suit.
This commit is contained in:
lukem 1997-11-04 11:36:26 +00:00
parent 1140eceb13
commit 3eff4309d8
2 changed files with 377 additions and 233 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: ypwhich.1,v 1.4 1997/10/20 03:44:39 lukem Exp $
.\" $NetBSD: ypwhich.1,v 1.5 1997/11/04 11:36:26 lukem Exp $
.\"
.\" Copyright (c) 1994 Christopher G. Demetriou
.\" All rights reserved.
@ -28,7 +28,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd February 23, 1994
.Dd November 4, 1997
.Dt YPWHICH 1
.Os
.Sh NAME
@ -38,12 +38,16 @@
.Nm
.Op Fl d Ar domain
.Oo
.Op Fl t
.Fl m Op Ar mname
|
.Op Fl h
.Ar host
.Oc
.Nm ""
.Op Fl d Ar domain
.Op Fl h Ar host
.Op Fl f
.Op Fl t
.Fl m Op Ar mname
.Nm ""
.Fl x
.Sh DESCRIPTION
.Nm
@ -63,21 +67,28 @@ which
server it is using.
.Pp
The options are as follows:
.Bl -tag -width indent
.Bl -tag -width Fl
.It Fl d Ar domain
Specify a domain other than the default domain.
.It Fl h Ar host
Specify a host other than localhost to query for information.
.It Fl f
When used in conjunction with
.Fl m ,
force
.Nm
to query
.Ar host
directly, without using the local copy of
.Xr ypbind 8 .
.It Fl t
Inhibit translation of map nicknames
to their corresponding map names.
.It Fl m Op Ar mname
Find the master
.Tn YP
server for the named map. No
.Ar host
may be specified with the
.Fl m
option.
.Ar Mname
server for the named map.
.Ar mname
can be a map name or nickname. If
.Ar mname
is ommitted,
@ -88,13 +99,11 @@ Display the map nickname table.
.El
.Sh SEE ALSO
.Xr domainname 1 ,
.Xr ypbind 8 ,
.Xr ypcat 1 ,
.Xr ypmatch 1 ,
.Xr yp 8 ,
.Xr ypbind 8 ,
.Xr yppoll 8 ,
.Xr ypset 8 ,
.Xr yp 8
.Xr ypset 8
.Sh AUTHOR
Theo De Raadt
Charles D. Cranor

View File

@ -1,7 +1,8 @@
/* $NetBSD: ypwhich.c,v 1.8 1997/07/18 07:40:43 thorpej Exp $ */
/* $NetBSD: ypwhich.c,v 1.9 1997/11/04 11:36:28 lukem Exp $ */
/*
* Copyright (c) 1992, 1993 Theo de Raadt <deraadt@fsa.ca>
*
* Copyright (c) 1997 Charles D. Cranor
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -12,267 +13,401 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Theo de Raadt.
* 4. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ypwhich.c,v 1.8 1997/07/18 07:40:43 thorpej Exp $");
#endif
/*
* ypwhich
* author: Chuck Cranor <chuck@ccrc.wustl.edu>
* date: 31-Oct-97
*
* notes: this is a full rewrite of Theo de Raadt's ypwhich.
* this version allows you full control of which ypserv you
* talk to for the "-m" command.
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <rpc/rpc.h>
#include <rpc/xdr.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
const struct ypalias {
char *alias, *name;
} ypaliases[] = {
{ "passwd", "passwd.byname" },
{ "group", "group.byname" },
{ "networks", "networks.byaddr" },
{ "hosts", "hosts.byaddr" },
{ "protocols", "protocols.bynumber" },
{ "services", "services.byname" },
{ "aliases", "mail.aliases" },
{ "ethers", "ethers.byname" },
/*
* ypwhich: query a host about its yp service
*
* usage:
* ypwhich [-d domain] [[-h] host]
* (who is host's ypserv?)
* ypwhich [-h host] [-d domain] [-f] [-t] -m [mapname]
* (who is the master of a map?)
* ypwhich -x
* (what nicknames do you use?)
*
* -d: the domainname to ask about
* -f: for -m, force us to talk directly to ypserv on the specified host
* without going through ypbind.
* -h: specify a host to ask [default = localhost]
* -m: find master server for a specific map (no map means 'all maps')
* -t: inhibit nickname translation
* -x: print list of yp map aliases and exit
*/
static char *ypnicknames[] = {
"aliases", "mail.aliases",
"ethers", "ethers.byname",
"group", "group.byname",
"hosts", "hosts.byaddr",
"networks", "networks.byaddr",
"passwd", "passwd.byname",
"protocols", "protocols.bynumber",
"services", "services.byname",
0, 0,
};
int main __P((int, char *[]));
int bind_host __P((char *dom, struct sockaddr_in *));
void usage __P((void));
extern char *__progname;
extern char *__progname;
/*
* prototypes
*/
void find_mapmaster __P((const char *, const char *, const char *,
int, int));
struct in_addr *find_server __P((const char *, const char *));
int main __P((int, char *[]));
void usage __P((void));
/*
* main
*/
int
main(argc, argv)
int argc;
char *argv[];
int argc;
char **argv;
{
char *domainname, *master, *map;
struct ypmaplist *ypml, *y;
struct hostent *hent;
struct sockaddr_in sin;
int notrans, mode, getmap;
int c, r, i;
char *targhost = "localhost";
char *ourdomain;
int inhibit = 0, force = 0;
char *targmap = NULL;
int ch, saw_m, lcv;
struct in_addr *inaddr;
struct hostent *he;
yp_get_default_domain(&domainname);
map = NULL;
getmap = notrans = mode = 0;
while((c = getopt(argc, argv, "xd:mt")) != -1) {
switch (c) {
case 'x':
for(i = 0;
i < sizeof(ypaliases)/sizeof(ypaliases[0]); i++)
printf("Use \"%s\" for \"%s\"\n",
ypaliases[i].alias,
ypaliases[i].name);
exit(0);
/*
* get default domainname and parse options
*/
yp_get_default_domain(&ourdomain);
saw_m = 0;
while ((ch = getopt(argc, argv, "h:d:xtfm")) != -1) {
switch (ch) {
case 'h':
targhost = optarg;
break;
case 'd':
domainname = optarg;
ourdomain = optarg;
break;
case 'x':
for (lcv = 0; ypnicknames[lcv]; lcv += 2)
printf("Use \"%s\" for map \"%s\"\n",
ypnicknames[lcv], ypnicknames[lcv + 1]);
exit(0);
case 'f':
force = 1;
break;
case 't':
notrans++;
inhibit = 1;
break;
case 'm':
mode++;
if (optind < argc && argv[optind][0] != '-')
targmap = argv[optind++];
saw_m = 1;
break;
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (domainname == NULL)
errx(1, "YP domain name not set");
if (mode == 0) {
switch (argc) {
case 0:
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (bind_host(domainname, &sin))
exit(1);
break;
case 1:
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
if (inet_aton(argv[0], &sin.sin_addr) == 0) {
hent = gethostbyname(argv[0]);
if (hent == NULL)
errx(1, "host %s unknown", argv[0]);
memcpy(&sin.sin_addr, hent->h_addr,
sizeof(sin.sin_addr));
}
if (bind_host(domainname, &sin))
exit(1);
break;
default:
if (argc) {
if (argc > 1)
usage();
}
exit(0);
targhost = argv[0];
}
#ifdef DEBUG
printf("target_host=%s, domain=%s, inhibit=%d, saw_m=%d, map=%s, force=%d\n",
targhost, ourdomain, inhibit, saw_m, targmap, force);
#endif
if (argc > 1)
usage();
/*
* need a valid domain
*/
if (argc == 1) {
map = argv[0];
for (i = 0; (notrans == 0) &&
i < sizeof(ypaliases)/sizeof(ypaliases[0]); i++)
if (strcmp(map, ypaliases[i].alias) == 0)
map = ypaliases[i].name;
r = yp_master(domainname, map, &master);
switch (r) {
case 0:
printf("%s\n", master);
free(master);
break;
if (ourdomain == NULL)
errx(1, "the domain hasn't been set on this machine.");
case YPERR_YPBIND:
errx(1, "not running upbind");
default:
errx(1, "can't find master for map %s. Reason: %s",
map, yperr_string(r));
}
exit(0);
}
ypml = NULL;
r = yp_maplist(domainname, &ypml);
switch (r) {
case 0:
for (y = ypml; y != NULL; ) {
ypml = y;
r = yp_master(domainname, ypml->ypml_name, &master);
switch (r) {
case 0:
printf("%s %s\n", ypml->ypml_name, master);
free(master);
break;
default:
warnx("can't find master for map %s. "
"Reason: %s", ypml->ypml_name,
yperr_string(r));
break;
}
y = ypml->ypml_next;
free(ypml);
}
break;
case YPERR_YPBIND:
errx(1, "not running ypbind");
default:
errx(1, "can't get map list for domain %s. Reason: %s",
domainname, yperr_string(r));
/*
* now do it
*/
if (saw_m)
find_mapmaster(targhost, ourdomain, targmap, inhibit, force);
else {
inaddr = find_server(targhost, ourdomain);
he = gethostbyaddr((char *) &inaddr->s_addr,
sizeof(inaddr->s_addr), AF_INET);
if (he)
printf("%s\n", he->h_name);
else
printf("%s\n", inet_ntoa(*inaddr));
}
exit(0);
}
/*
* Like yp_bind except can query a specific host
* usage: print usage and exit
*/
int
bind_host(dom, sin)
char *dom;
struct sockaddr_in *sin;
{
struct hostent *hent = NULL;
struct ypbind_resp ypbr;
struct timeval tv;
CLIENT *client;
int sock, r;
struct in_addr ina;
sock = RPC_ANYSOCK;
tv.tv_sec = 15;
tv.tv_usec = 0;
client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock);
if (client == NULL) {
warnx("can't clntudp_create: %s", yperr_string(YPERR_YPBIND));
return YPERR_YPBIND;
}
tv.tv_sec = 5;
tv.tv_usec = 0;
r = clnt_call(client, YPBINDPROC_DOMAIN, xdr_ypdomain_wrap_string,
&dom, xdr_ypbind_resp, &ypbr, tv);
if (r != RPC_SUCCESS) {
warnx("can't cnlt_call: %s", yperr_string(YPERR_YPBIND));
clnt_destroy(client);
return YPERR_YPBIND;
} else {
if (ypbr.ypbind_status != YPBIND_SUCC_VAL) {
warnx("can't bind. Reason: %s\n",
yperr_string(ypbr.ypbind_status));
clnt_destroy(client);
return r;
}
}
clnt_destroy(client);
ina.s_addr =
ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr.s_addr;
hent = gethostbyaddr((const char *)&ina.s_addr, sizeof(ina.s_addr),
AF_INET);
if (hent != NULL)
printf("%s\n", hent->h_name);
else
printf("%s\n", inet_ntoa(ina));
return 0;
}
void
usage()
{
fprintf(stderr, "usage: %s [-d domain] [[-t] -m [mapname] | host]\n",
fprintf(stderr, "usage:\n");
fprintf(stderr, "\t%s [-d domain] [[-h] host]\n", __progname);
fprintf(stderr, "\t%s [-h host] [-d domain] [-f] [-t] -m [mapname]\n",
__progname);
fprintf(stderr, " %s -x\n", __progname);
fprintf(stderr, "\t%s -x\n", __progname);
exit(1);
}
/*
* find_server: ask a host's ypbind who its current ypserver is
*/
struct in_addr *
find_server(host, domain)
const char *host, *domain;
{
static struct in_addr result;
struct sockaddr_in sin;
CLIENT *ypbind;
int ypbind_fd;
struct timeval tv;
enum clnt_stat retval;
struct ypbind_resp ypbind_resp;
/*
* get address of host
*/
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
if (inet_aton(host, &sin.sin_addr) == 0) {
struct hostent *he;
he = gethostbyname(host);
if (he == NULL)
errx(1, "%s: %s", host, hstrerror(h_errno));
memmove(&sin.sin_addr, he->h_addr, sizeof(sin.sin_addr));
}
/*
* establish connection to ypbind
*/
tv.tv_sec = 15;
tv.tv_usec = 0;
ypbind_fd = RPC_ANYSOCK;
ypbind = clntudp_create(&sin, YPBINDPROG, YPBINDVERS, tv, &ypbind_fd);
if (ypbind == NULL)
errx(1, "clntudp_create: %s: %s", host,
yperr_string(YPERR_YPBIND));
/*
* now call ypbind's "DOMAIN" procedure to get the server name
*/
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = clnt_call(ypbind, YPBINDPROC_DOMAIN, xdr_ypdomain_wrap_string,
&domain, xdr_ypbind_resp, &ypbind_resp, tv);
clnt_destroy(ypbind);
if (retval != RPC_SUCCESS)
errx(1, "clnt_call: %s: %s", host, clnt_sperrno(retval));
if (ypbind_resp.ypbind_status != YPBIND_SUCC_VAL)
errx(1, "ypbind on %s for domain %s failed: %s\n", host, domain,
yperr_string(ypbind_resp.ypbind_status));
/*
* got it!
*/
result.s_addr = ypbind_resp.ypbind_respbody.
ypbind_bindinfo.ypbind_binding_addr.s_addr; /* love that name! */
return (&result);
}
/*
* find_mapmaster: ask a host's ypserver who its map's master is
*/
void
find_mapmaster(host, domain, map, inhibit, force)
const char *host, *domain, *map;
int inhibit, force;
{
struct in_addr *inaddr, faddr;
struct hostent *he;
int lcv;
struct sockaddr_in sin;
CLIENT *ypserv;
int ypserv_fd, yperr;
struct timeval tv;
enum clnt_stat retval;
struct ypresp_maplist yprespmlist;
struct ypmaplist fakelist, *ypml;
struct ypresp_master yprespmaster;
struct ypreq_nokey ypreqkey;
/*
* we can either ask the hosts ypbind where it's ypserv is located,
* or we can be forced to assume that ypserv is running on the host.
*/
if (force) {
if (inet_aton(host, &faddr) == 0) {
he = gethostbyname(host);
if (he == NULL)
errx(1, "%s: %s", host, hstrerror(h_errno));
memmove(&faddr, he->h_addr, sizeof(faddr));
}
inaddr = &faddr;
} else {
/* ask host "host" who is currently serving its maps */
inaddr = find_server(host, domain);
}
/*
* now translate nicknames [unless inhibited]
*/
if (map && !inhibit) {
for (lcv = 0; ypnicknames[lcv]; lcv += 2) {
if (strcmp(map, ypnicknames[lcv]) == 0) {
map = ypnicknames[lcv + 1];
break;
}
}
#ifdef DEBUG
printf("translated map name = %s\n", map);
#endif
}
/*
* now we try and connect to host's ypserv
*/
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inaddr->s_addr;
tv.tv_sec = 15;
tv.tv_usec = 0;
ypserv_fd = RPC_ANYSOCK;
ypserv = clntudp_create(&sin, YPPROG, YPVERS, tv, &ypserv_fd);
if (ypserv == NULL) {
warnx("clntudp_create: %s: %s", host,
yperr_string(YPERR_YPSERV));
goto error;
}
/*
* did the user specify a map?
*/
if (map == NULL) {
/*
* if no map specified, we ask ypserv for a list of all maps
*/
memset(&yprespmlist, 0, sizeof(yprespmlist));
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = clnt_call(ypserv, YPPROC_MAPLIST,
xdr_ypdomain_wrap_string, &domain, xdr_ypresp_maplist,
&yprespmlist, tv);
if (retval != RPC_SUCCESS) {
warnx("clnt_call MAPLIST: %s: %s", host,
clnt_sperrno(retval));
goto error;
}
yperr = ypprot_err(yprespmlist.status);
if (yperr) {
warnx("clnt_call: %s: %s", host, yperr_string(yperr));
goto error;
}
ypml = yprespmlist.list;
} else {
/*
* build a fake "list" of maps containing only the list the user
* asked about in it.
*/
memset(&fakelist, 0, sizeof(fakelist));
strncpy(fakelist.ypml_name, map, YPMAXMAP);
fakelist.ypml_next = NULL;
ypml = &fakelist;
}
/*
* we now have a list of maps. ask ypserv who is the master for
* each map...
*/
for ( /* null */ ; ypml != NULL; ypml = ypml->ypml_next) {
ypreqkey.domain = domain;
ypreqkey.map = ypml->ypml_name;
memset(&yprespmaster, 0, sizeof(yprespmaster));
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = clnt_call(ypserv, YPPROC_MASTER, xdr_ypreq_nokey,
&ypreqkey, xdr_ypresp_master, &yprespmaster, tv);
if (retval != RPC_SUCCESS) {
warnx("clnt_call MASTER: %s: %s", host,
clnt_sperrno(retval));
goto error;
}
yperr = ypprot_err(yprespmaster.status);
if (yperr) {
warnx("clnt_call: %s: %s: %s", host, ypml->ypml_name,
yperr_string(yperr));
} else {
printf("%s %s\n", ypml->ypml_name, yprespmaster.master);
}
xdr_free(xdr_ypresp_master, (char *) &yprespmaster);
}
clnt_destroy(ypserv);
/*
* done
*/
return;
error:
/* print host's ypserv's IP address to prevent confusion */
if (ypserv)
clnt_destroy(ypserv);
if (!force)
fprintf(stderr, "\t[note %s's ypserv running on host %s]\n",
host, inet_ntoa(*inaddr));
exit(1);
}