xref: /freebsd/lib/libc/yp/yplib.c (revision d201fe46e355212750b727061e6a7ac005267852)
14415cd19SGarrett Wollman /*
24415cd19SGarrett Wollman  * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
34e6ace08SBill Paul  * Copyright (c) 1998 Bill Paul <wpaul@ctr.columbia.edu>
44415cd19SGarrett Wollman  * All rights reserved.
54415cd19SGarrett Wollman  *
64415cd19SGarrett Wollman  * Redistribution and use in source and binary forms, with or without
74415cd19SGarrett Wollman  * modification, are permitted provided that the following conditions
84415cd19SGarrett Wollman  * are met:
94415cd19SGarrett Wollman  * 1. Redistributions of source code must retain the above copyright
104415cd19SGarrett Wollman  *    notice, this list of conditions and the following disclaimer.
114415cd19SGarrett Wollman  * 2. Redistributions in binary form must reproduce the above copyright
124415cd19SGarrett Wollman  *    notice, this list of conditions and the following disclaimer in the
134415cd19SGarrett Wollman  *    documentation and/or other materials provided with the distribution.
144415cd19SGarrett Wollman  * 3. The name of the author may not be used to endorse or promote
154415cd19SGarrett Wollman  *    products derived from this software without specific prior written
164415cd19SGarrett Wollman  *    permission.
174415cd19SGarrett Wollman  *
184415cd19SGarrett Wollman  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
194415cd19SGarrett Wollman  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
204415cd19SGarrett Wollman  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
214415cd19SGarrett Wollman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
224415cd19SGarrett Wollman  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
234415cd19SGarrett Wollman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
244415cd19SGarrett Wollman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
254415cd19SGarrett Wollman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
264415cd19SGarrett Wollman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
274415cd19SGarrett Wollman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
284415cd19SGarrett Wollman  * SUCH DAMAGE.
294415cd19SGarrett Wollman  */
304415cd19SGarrett Wollman 
314415cd19SGarrett Wollman #ifndef LINT
327f3dea24SPeter Wemm static char *rcsid = "$FreeBSD$";
334415cd19SGarrett Wollman #endif
344415cd19SGarrett Wollman 
35d201fe46SDaniel Eischen #include "namespace.h"
364415cd19SGarrett Wollman #include <sys/param.h>
374415cd19SGarrett Wollman #include <sys/types.h>
384415cd19SGarrett Wollman #include <sys/socket.h>
394415cd19SGarrett Wollman #include <sys/file.h>
404415cd19SGarrett Wollman #include <sys/uio.h>
414415cd19SGarrett Wollman #include <errno.h>
424415cd19SGarrett Wollman #include <stdio.h>
434415cd19SGarrett Wollman #include <string.h>
44b9729ac2SBill Paul #include <stdlib.h>
45b9729ac2SBill Paul #include <unistd.h>
464415cd19SGarrett Wollman #include <rpc/rpc.h>
474415cd19SGarrett Wollman #include <rpc/xdr.h>
480e276383SBill Paul #include <rpcsvc/yp.h>
49d201fe46SDaniel Eischen #include "un-namespace.h"
50d201fe46SDaniel Eischen #include "libc_private.h"
510e276383SBill Paul 
520e276383SBill Paul /*
530e276383SBill Paul  * We have to define these here due to clashes between yp_prot.h and
540e276383SBill Paul  * yp.h.
550e276383SBill Paul  */
560e276383SBill Paul 
574e6ace08SBill Paul #define YPMATCHCACHE
584e6ace08SBill Paul 
594e6ace08SBill Paul #ifdef YPMATCHCACHE
604e6ace08SBill Paul struct ypmatch_ent {
614e6ace08SBill Paul         char			*ypc_map;
624e6ace08SBill Paul 	keydat			ypc_key;
634e6ace08SBill Paul 	valdat			ypc_val;
644e6ace08SBill Paul         time_t			ypc_expire_t;
654e6ace08SBill Paul         struct ypmatch_ent	*ypc_next;
664e6ace08SBill Paul };
674e6ace08SBill Paul #define YPLIB_MAXCACHE	5	/* At most 5 entries */
684e6ace08SBill Paul #define YPLIB_EXPIRE	5	/* Expire after 5 seconds */
694e6ace08SBill Paul #endif
704e6ace08SBill Paul 
710e276383SBill Paul struct dom_binding {
720e276383SBill Paul         struct dom_binding *dom_pnext;
730e276383SBill Paul         char dom_domain[YPMAXDOMAIN + 1];
740e276383SBill Paul         struct sockaddr_in dom_server_addr;
750e276383SBill Paul         u_short dom_server_port;
760e276383SBill Paul         int dom_socket;
770e276383SBill Paul         CLIENT *dom_client;
78a2308772SBill Paul         u_short dom_local_port; /* now I finally know what this is for. */
790e276383SBill Paul         long dom_vers;
804e6ace08SBill Paul #ifdef YPMATCHCACHE
814e6ace08SBill Paul 	struct ypmatch_ent *cache;
824e6ace08SBill Paul 	int ypmatch_cachecnt;
834e6ace08SBill Paul #endif
840e276383SBill Paul };
850e276383SBill Paul 
864415cd19SGarrett Wollman #include <rpcsvc/ypclnt.h>
874415cd19SGarrett Wollman 
884415cd19SGarrett Wollman #ifndef BINDINGDIR
894415cd19SGarrett Wollman #define BINDINGDIR "/var/yp/binding"
904415cd19SGarrett Wollman #endif
91456ebbf8SBill Paul #define MAX_RETRIES 20
924415cd19SGarrett Wollman 
934415cd19SGarrett Wollman extern bool_t xdr_domainname(), xdr_ypbind_resp();
944415cd19SGarrett Wollman extern bool_t xdr_ypreq_key(), xdr_ypresp_val();
954415cd19SGarrett Wollman extern bool_t xdr_ypreq_nokey(), xdr_ypresp_key_val();
964415cd19SGarrett Wollman extern bool_t xdr_ypresp_all(), xdr_ypresp_all_seq();
974415cd19SGarrett Wollman extern bool_t xdr_ypresp_master();
984415cd19SGarrett Wollman 
994415cd19SGarrett Wollman int (*ypresp_allfn)();
1004415cd19SGarrett Wollman void *ypresp_data;
1014415cd19SGarrett Wollman 
102cc64a2bfSBill Paul static void _yp_unbind __P(( struct dom_binding * ));
1034415cd19SGarrett Wollman struct dom_binding *_ypbindlist;
1044415cd19SGarrett Wollman static char _yp_domain[MAXHOSTNAMELEN];
1054415cd19SGarrett Wollman int _yplib_timeout = 10;
1064415cd19SGarrett Wollman 
1074415cd19SGarrett Wollman #ifdef YPMATCHCACHE
1084e6ace08SBill Paul static void ypmatch_cache_delete(ypdb, prev, cur)
1094e6ace08SBill Paul 	struct dom_binding	*ypdb;
1104e6ace08SBill Paul 	struct ypmatch_ent	*prev;
1114e6ace08SBill Paul 	struct ypmatch_ent	*cur;
1124415cd19SGarrett Wollman {
1134e6ace08SBill Paul 	if (prev == NULL)
1144e6ace08SBill Paul 		ypdb->cache = cur->ypc_next;
1154e6ace08SBill Paul 	else
1164e6ace08SBill Paul 		prev->ypc_next = cur->ypc_next;
1174e6ace08SBill Paul 
1184e6ace08SBill Paul 	free(cur->ypc_map);
1194e6ace08SBill Paul 	free(cur->ypc_key.keydat_val);
1204e6ace08SBill Paul 	free(cur->ypc_val.valdat_val);
1214e6ace08SBill Paul 	free(cur);
1224e6ace08SBill Paul 
1234e6ace08SBill Paul 	ypdb->ypmatch_cachecnt--;
1244e6ace08SBill Paul 
1254e6ace08SBill Paul 	return;
1264e6ace08SBill Paul }
1274e6ace08SBill Paul 
1284e6ace08SBill Paul static void ypmatch_cache_flush(ypdb)
1294e6ace08SBill Paul 	struct dom_binding	*ypdb;
1304e6ace08SBill Paul {
1314e6ace08SBill Paul 	struct ypmatch_ent	*n, *c = ypdb->cache;
1324e6ace08SBill Paul 
1334e6ace08SBill Paul 	while (c != NULL) {
1344e6ace08SBill Paul 		n = c->ypc_next;
1354e6ace08SBill Paul 		ypmatch_cache_delete(ypdb, NULL, c);
1364e6ace08SBill Paul 		c = n;
1374e6ace08SBill Paul 	}
1384e6ace08SBill Paul 
1394e6ace08SBill Paul 	return;
1404e6ace08SBill Paul }
1414e6ace08SBill Paul 
1424e6ace08SBill Paul static void ypmatch_cache_expire(ypdb)
1434e6ace08SBill Paul 	struct dom_binding	*ypdb;
1444e6ace08SBill Paul {
1454e6ace08SBill Paul 	struct ypmatch_ent	*c = ypdb->cache;
1464e6ace08SBill Paul 	struct ypmatch_ent	*n, *p = NULL;
1474415cd19SGarrett Wollman 	time_t			t;
1484415cd19SGarrett Wollman 
1494415cd19SGarrett Wollman 	time(&t);
1504415cd19SGarrett Wollman 
1514e6ace08SBill Paul 	while (c != NULL) {
1524e6ace08SBill Paul 		if (t >= c->ypc_expire_t) {
1534e6ace08SBill Paul 			n = c->ypc_next;
1544e6ace08SBill Paul 			ypmatch_cache_delete(ypdb, p, c);
1554e6ace08SBill Paul 			c = n;
1564415cd19SGarrett Wollman 		} else {
1574e6ace08SBill Paul 			p = c;
1584e6ace08SBill Paul 			c = c->ypc_next;
1594e6ace08SBill Paul 		}
1604415cd19SGarrett Wollman 	}
1614415cd19SGarrett Wollman 
1624e6ace08SBill Paul 	return;
1634415cd19SGarrett Wollman }
1644415cd19SGarrett Wollman 
1654e6ace08SBill Paul static void ypmatch_cache_insert(ypdb, map, key, val)
1664e6ace08SBill Paul 	struct dom_binding	*ypdb;
1674415cd19SGarrett Wollman 	char			*map;
1684e6ace08SBill Paul 	keydat			*key;
1694e6ace08SBill Paul 	valdat			*val;
1704415cd19SGarrett Wollman {
1714e6ace08SBill Paul 	struct ypmatch_ent	*new;
1724415cd19SGarrett Wollman 
1734e6ace08SBill Paul 	/* Do an expire run to maybe open up a slot. */
1744e6ace08SBill Paul 	if (ypdb->ypmatch_cachecnt)
1754e6ace08SBill Paul 		ypmatch_cache_expire(ypdb);
1764415cd19SGarrett Wollman 
1774e6ace08SBill Paul 	/*
1784e6ace08SBill Paul 	 * If there are no slots free, then force an expire of
1794e6ace08SBill Paul 	 * the least recently used entry.
1804e6ace08SBill Paul  	 */
1814e6ace08SBill Paul 	if (ypdb->ypmatch_cachecnt >= YPLIB_MAXCACHE) {
1824e6ace08SBill Paul 		struct ypmatch_ent	*o = NULL, *c = ypdb->cache;
1834e6ace08SBill Paul 		time_t			oldest = 0;
1844415cd19SGarrett Wollman 
1854e6ace08SBill Paul 		oldest = ~oldest;
1864415cd19SGarrett Wollman 
1874e6ace08SBill Paul 		while(c != NULL) {
1884e6ace08SBill Paul 			if (c->ypc_expire_t < oldest) {
1894e6ace08SBill Paul 				oldest = c->ypc_expire_t;
1904e6ace08SBill Paul 				o = c;
1914415cd19SGarrett Wollman 			}
1924e6ace08SBill Paul 			c = c->ypc_next;
1934e6ace08SBill Paul 		}
1944e6ace08SBill Paul 
1954e6ace08SBill Paul 		if (o == NULL)
1964e6ace08SBill Paul 			return;
1974e6ace08SBill Paul 		o->ypc_expire_t = 0;
1984e6ace08SBill Paul 		ypmatch_cache_expire(ypdb);
1994e6ace08SBill Paul 	}
2004e6ace08SBill Paul 
2014e6ace08SBill Paul 	new = malloc(sizeof(struct ypmatch_ent));
2024e6ace08SBill Paul 	if (new == NULL)
2034e6ace08SBill Paul 		return;
2044e6ace08SBill Paul 
2054e6ace08SBill Paul 	new->ypc_map = strdup(map);
2064e6ace08SBill Paul 	if (new->ypc_map == NULL) {
2074e6ace08SBill Paul 		free(new);
2084e6ace08SBill Paul 		return;
2094e6ace08SBill Paul 	}
2104e6ace08SBill Paul 	new->ypc_key.keydat_val = malloc(key->keydat_len);
2114e6ace08SBill Paul 	if (new->ypc_key.keydat_val == NULL) {
2124e6ace08SBill Paul 		free(new->ypc_map);
2134e6ace08SBill Paul 		free(new);
2144e6ace08SBill Paul 		return;
2154e6ace08SBill Paul 	}
2164e6ace08SBill Paul 	new->ypc_val.valdat_val = malloc(val->valdat_len);
2174e6ace08SBill Paul 	if (new->ypc_val.valdat_val == NULL) {
2184e6ace08SBill Paul 		free(new->ypc_val.valdat_val);
2194e6ace08SBill Paul 		free(new->ypc_map);
2204e6ace08SBill Paul 		free(new);
2214e6ace08SBill Paul 		return;
2224e6ace08SBill Paul 	}
2234e6ace08SBill Paul 
2244e6ace08SBill Paul 	new->ypc_expire_t = time(NULL) + YPLIB_EXPIRE;
2254e6ace08SBill Paul 	new->ypc_key.keydat_len = key->keydat_len;
2264e6ace08SBill Paul 	new->ypc_val.valdat_len = val->valdat_len;
2274e6ace08SBill Paul 	bcopy(key->keydat_val, new->ypc_key.keydat_val, key->keydat_len);
2284e6ace08SBill Paul 	bcopy(val->valdat_val, new->ypc_val.valdat_val, val->valdat_len);
2294e6ace08SBill Paul 
2304e6ace08SBill Paul 	new->ypc_next = ypdb->cache;
2314e6ace08SBill Paul 	ypdb->cache = new;
2324e6ace08SBill Paul 
2334e6ace08SBill Paul 	ypdb->ypmatch_cachecnt++;
2344e6ace08SBill Paul 
2354e6ace08SBill Paul 	return;
2364e6ace08SBill Paul }
2374e6ace08SBill Paul 
2384e6ace08SBill Paul static bool_t ypmatch_cache_lookup(ypdb, map, key, val)
2394e6ace08SBill Paul 	struct dom_binding	*ypdb;
2404e6ace08SBill Paul 	char			*map;
2414e6ace08SBill Paul 	keydat			*key;
2424e6ace08SBill Paul 	valdat			*val;
2434e6ace08SBill Paul {
2444e6ace08SBill Paul 	struct ypmatch_ent	*c = ypdb->cache;
2454e6ace08SBill Paul 
2464e6ace08SBill Paul 	ypmatch_cache_expire(ypdb);
2474e6ace08SBill Paul 
2484e6ace08SBill Paul 	for (c = ypdb->cache; c != NULL; c = c->ypc_next) {
2494e6ace08SBill Paul 		if (strcmp(map, c->ypc_map))
2504e6ace08SBill Paul 			continue;
2514e6ace08SBill Paul 		if (key->keydat_len != c->ypc_key.keydat_len)
2524e6ace08SBill Paul 			continue;
2534e6ace08SBill Paul 		if (bcmp(key->keydat_val, c->ypc_key.keydat_val,
2544e6ace08SBill Paul 				key->keydat_len))
2554e6ace08SBill Paul 			continue;
2564e6ace08SBill Paul 	}
2574e6ace08SBill Paul 
2584e6ace08SBill Paul 	if (c == NULL)
2594e6ace08SBill Paul 		return(FALSE);
2604e6ace08SBill Paul 
2614e6ace08SBill Paul 	val->valdat_len = c->ypc_val.valdat_len;
2624e6ace08SBill Paul 	val->valdat_val = c->ypc_val.valdat_val;
2634e6ace08SBill Paul 
2644e6ace08SBill Paul 	return(TRUE);
2654415cd19SGarrett Wollman }
2664415cd19SGarrett Wollman #endif
2674415cd19SGarrett Wollman 
26864416168SBill Paul char *
26964416168SBill Paul ypbinderr_string(incode)
27064416168SBill Paul 	int incode;
27164416168SBill Paul {
27264416168SBill Paul 	static char err[80];
27364416168SBill Paul 	switch(incode) {
27464416168SBill Paul 	case 0:
27564416168SBill Paul 		return "Success";
27662967ca2SBill Paul 	case YPBIND_ERR_ERR:
27764416168SBill Paul 		return "Internal ypbind error";
27862967ca2SBill Paul 	case YPBIND_ERR_NOSERV:
27964416168SBill Paul 		return "Domain not bound";
28062967ca2SBill Paul 	case YPBIND_ERR_RESC:
28164416168SBill Paul 		return "System resource allocation failure";
28264416168SBill Paul 	}
28362967ca2SBill Paul 	sprintf(err, "Unknown ypbind error: #%d\n", incode);
28464416168SBill Paul 	return err;
28564416168SBill Paul }
28664416168SBill Paul 
2874415cd19SGarrett Wollman int
2884415cd19SGarrett Wollman _yp_dobind(dom, ypdb)
2894415cd19SGarrett Wollman 	char *dom;
2904415cd19SGarrett Wollman 	struct dom_binding **ypdb;
2914415cd19SGarrett Wollman {
292e75ad74aSJames Raynard 	static pid_t pid = -1;
2934415cd19SGarrett Wollman 	char path[MAXPATHLEN];
2944415cd19SGarrett Wollman 	struct dom_binding *ysd, *ysd2;
2959d80b1ddSBill Paul 	struct ypbind_resp ypbr;
2964415cd19SGarrett Wollman 	struct timeval tv;
2974415cd19SGarrett Wollman 	struct sockaddr_in clnt_sin;
29851295a4dSJordan K. Hubbard 	int clnt_sock, fd;
299ccbcef60SJames Raynard 	pid_t gpid;
3004415cd19SGarrett Wollman 	CLIENT *client;
3014415cd19SGarrett Wollman 	int new = 0, r;
302456ebbf8SBill Paul 	int retries = 0;
303a2308772SBill Paul 	struct sockaddr_in check;
304a2308772SBill Paul 	int checklen = sizeof(struct sockaddr_in);
3054415cd19SGarrett Wollman 
3066e8caff7SBill Paul 	/* Not allowed; bad doggie. Bad. */
3076e8caff7SBill Paul 	if (strchr(dom, '/') != NULL)
3086e8caff7SBill Paul 		return(YPERR_BADARGS);
3096e8caff7SBill Paul 
3104415cd19SGarrett Wollman 	gpid = getpid();
3114415cd19SGarrett Wollman 	if( !(pid==-1 || pid==gpid) ) {
3124415cd19SGarrett Wollman 		ysd = _ypbindlist;
3134415cd19SGarrett Wollman 		while(ysd) {
3149fa75c15SBill Paul 			if(ysd->dom_client != NULL)
315cc64a2bfSBill Paul 				_yp_unbind(ysd);
3164415cd19SGarrett Wollman 			ysd2 = ysd->dom_pnext;
3174415cd19SGarrett Wollman 			free(ysd);
3184415cd19SGarrett Wollman 			ysd = ysd2;
3194415cd19SGarrett Wollman 		}
3204415cd19SGarrett Wollman 		_ypbindlist = NULL;
3214415cd19SGarrett Wollman 	}
3224415cd19SGarrett Wollman 	pid = gpid;
3234415cd19SGarrett Wollman 
3244415cd19SGarrett Wollman 	if(ypdb!=NULL)
3254415cd19SGarrett Wollman 		*ypdb = NULL;
3264415cd19SGarrett Wollman 
3274415cd19SGarrett Wollman 	if(dom==NULL || strlen(dom)==0)
3284415cd19SGarrett Wollman 		return YPERR_BADARGS;
3294415cd19SGarrett Wollman 
3304415cd19SGarrett Wollman 	for(ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext)
3314415cd19SGarrett Wollman 		if( strcmp(dom, ysd->dom_domain) == 0)
3324415cd19SGarrett Wollman 			break;
333a169c9b1SBill Paul 
334a2308772SBill Paul 
3354415cd19SGarrett Wollman 	if(ysd==NULL) {
3364415cd19SGarrett Wollman 		ysd = (struct dom_binding *)malloc(sizeof *ysd);
3374415cd19SGarrett Wollman 		bzero((char *)ysd, sizeof *ysd);
3384415cd19SGarrett Wollman 		ysd->dom_socket = -1;
3394415cd19SGarrett Wollman 		ysd->dom_vers = 0;
3404415cd19SGarrett Wollman 		new = 1;
341a2308772SBill Paul 	} else {
342a2308772SBill Paul 	/* Check the socket -- may have been hosed by the caller. */
343d201fe46SDaniel Eischen 		if (_getsockname(ysd->dom_socket, (struct sockaddr *)&check,
344a2308772SBill Paul 		    &checklen) == -1 || check.sin_family != AF_INET ||
345a2308772SBill Paul 		    check.sin_port != ysd->dom_local_port) {
346a2308772SBill Paul 		/* Socket became bogus somehow... need to rebind. */
347a2308772SBill Paul 			int save, sock;
348a2308772SBill Paul 
349a2308772SBill Paul 			sock = ysd->dom_socket;
350d201fe46SDaniel Eischen 			save = _dup(ysd->dom_socket);
3519fa75c15SBill Paul 			if (ysd->dom_client != NULL)
352a2308772SBill Paul 				clnt_destroy(ysd->dom_client);
353a2308772SBill Paul 			ysd->dom_vers = 0;
354a2308772SBill Paul 			ysd->dom_client = NULL;
355d201fe46SDaniel Eischen 			sock = _dup2(save, sock);
3569233c4d9SJason Evans 			_close(save);
357a2308772SBill Paul 		}
3584415cd19SGarrett Wollman 	}
3590f98415eSBill Paul 
3604415cd19SGarrett Wollman again:
361456ebbf8SBill Paul 	retries++;
362456ebbf8SBill Paul 	if (retries > MAX_RETRIES) {
363456ebbf8SBill Paul 		if (new)
364456ebbf8SBill Paul 			free(ysd);
365456ebbf8SBill Paul 		return(YPERR_YPBIND);
366456ebbf8SBill Paul 	}
3674415cd19SGarrett Wollman #ifdef BINDINGDIR
3684415cd19SGarrett Wollman 	if(ysd->dom_vers==0) {
369a169c9b1SBill Paul 		/*
370a169c9b1SBill Paul 		 * We're trying to make a new binding: zorch the
371a169c9b1SBill Paul 		 * existing handle now (if any).
372a169c9b1SBill Paul 		 */
3739fa75c15SBill Paul 		if(ysd->dom_client != NULL) {
374a169c9b1SBill Paul 			clnt_destroy(ysd->dom_client);
375a169c9b1SBill Paul 			ysd->dom_client = NULL;
376a2308772SBill Paul 			ysd->dom_socket = -1;
377a169c9b1SBill Paul 		}
37883ac6cdcSKris Kennaway 		snprintf(path, sizeof(path), "%s/%s.%d", BINDINGDIR, dom, 2);
3799233c4d9SJason Evans 		if((fd = _open(path, O_RDONLY)) == -1) {
3804415cd19SGarrett Wollman 			/* no binding file, YP is dead. */
381456ebbf8SBill Paul 			/* Try to bring it back to life. */
3829233c4d9SJason Evans 			_close(fd);
383b9729ac2SBill Paul 			goto skipit;
3844415cd19SGarrett Wollman 		}
385d201fe46SDaniel Eischen 		if(_flock(fd, LOCK_EX|LOCK_NB) == -1 && errno==EWOULDBLOCK) {
3864415cd19SGarrett Wollman 			struct iovec iov[2];
3879d80b1ddSBill Paul 			struct ypbind_resp ybr;
3884415cd19SGarrett Wollman 			u_short	ypb_port;
3894415cd19SGarrett Wollman 
3904415cd19SGarrett Wollman 			iov[0].iov_base = (caddr_t)&ypb_port;
3914415cd19SGarrett Wollman 			iov[0].iov_len = sizeof ypb_port;
3924415cd19SGarrett Wollman 			iov[1].iov_base = (caddr_t)&ybr;
3934415cd19SGarrett Wollman 			iov[1].iov_len = sizeof ybr;
3944415cd19SGarrett Wollman 
395d201fe46SDaniel Eischen 			r = _readv(fd, iov, 2);
3964415cd19SGarrett Wollman 			if(r != iov[0].iov_len + iov[1].iov_len) {
3979233c4d9SJason Evans 				_close(fd);
3984415cd19SGarrett Wollman 				ysd->dom_vers = -1;
3994415cd19SGarrett Wollman 				goto again;
4004415cd19SGarrett Wollman 			}
4014415cd19SGarrett Wollman 
4024415cd19SGarrett Wollman 			bzero(&ysd->dom_server_addr, sizeof ysd->dom_server_addr);
4034415cd19SGarrett Wollman 			ysd->dom_server_addr.sin_family = AF_INET;
4044415cd19SGarrett Wollman 			ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in);
4059d80b1ddSBill Paul 			ysd->dom_server_addr.sin_addr.s_addr =
4069d80b1ddSBill Paul 			    *(u_long *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr;
4074415cd19SGarrett Wollman 			ysd->dom_server_addr.sin_port =
4089d80b1ddSBill Paul 			    *(u_short *)&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port;
4094415cd19SGarrett Wollman 
4104415cd19SGarrett Wollman 			ysd->dom_server_port = ysd->dom_server_addr.sin_port;
4119233c4d9SJason Evans 			_close(fd);
4124415cd19SGarrett Wollman 			goto gotit;
4134415cd19SGarrett Wollman 		} else {
4144415cd19SGarrett Wollman 			/* no lock on binding file, YP is dead. */
415456ebbf8SBill Paul 			/* Try to bring it back to life. */
4169233c4d9SJason Evans 			_close(fd);
417456ebbf8SBill Paul 			goto skipit;
418f067dfeaSBill Paul 		}
419f067dfeaSBill Paul 	}
420b9729ac2SBill Paul skipit:
4214415cd19SGarrett Wollman #endif
4224415cd19SGarrett Wollman 	if(ysd->dom_vers==-1 || ysd->dom_vers==0) {
423a169c9b1SBill Paul 		/*
424a169c9b1SBill Paul 		 * We're trying to make a new binding: zorch the
425a169c9b1SBill Paul 		 * existing handle now (if any).
426a169c9b1SBill Paul 		 */
4279fa75c15SBill Paul 		if(ysd->dom_client != NULL) {
428a169c9b1SBill Paul 			clnt_destroy(ysd->dom_client);
429a169c9b1SBill Paul 			ysd->dom_client = NULL;
430a2308772SBill Paul 			ysd->dom_socket = -1;
431a169c9b1SBill Paul 		}
4324415cd19SGarrett Wollman 		bzero((char *)&clnt_sin, sizeof clnt_sin);
4334415cd19SGarrett Wollman 		clnt_sin.sin_family = AF_INET;
4344415cd19SGarrett Wollman 		clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
4354415cd19SGarrett Wollman 
4364415cd19SGarrett Wollman 		clnt_sock = RPC_ANYSOCK;
4374415cd19SGarrett Wollman 		client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, &clnt_sock,
4384415cd19SGarrett Wollman 			0, 0);
4394415cd19SGarrett Wollman 		if(client==NULL) {
44020e4b00aSBill Paul 			/*
44120e4b00aSBill Paul 			 * These conditions indicate ypbind just isn't
44220e4b00aSBill Paul 			 * alive -- we probably don't want to shoot our
443a169c9b1SBill Paul 			 * mouth off in this case; instead generate error
44420e4b00aSBill Paul 			 * messages only for really exotic problems.
44520e4b00aSBill Paul 			 */
44620e4b00aSBill Paul 			if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED &&
44720e4b00aSBill Paul 			   (rpc_createerr.cf_stat != RPC_SYSTEMERROR &&
44820e4b00aSBill Paul 			   rpc_createerr.cf_error.re_errno == ECONNREFUSED))
4494415cd19SGarrett Wollman 				clnt_pcreateerror("clnttcp_create");
4504415cd19SGarrett Wollman 			if(new)
4514415cd19SGarrett Wollman 				free(ysd);
452456ebbf8SBill Paul 			return (YPERR_YPBIND);
4534415cd19SGarrett Wollman 		}
4544415cd19SGarrett Wollman 
45556d18edaSBill Paul 		/*
45656d18edaSBill Paul 		 * Check the port number -- should be < IPPORT_RESERVED.
45756d18edaSBill Paul 		 * If not, it's possible someone has registered a bogus
45856d18edaSBill Paul 		 * ypbind with the portmapper and is trying to trick us.
45956d18edaSBill Paul 		 */
46056d18edaSBill Paul 		if (ntohs(clnt_sin.sin_port) >= IPPORT_RESERVED) {
4619fa75c15SBill Paul 			if (client != NULL)
46256d18edaSBill Paul 				clnt_destroy(client);
46356d18edaSBill Paul 			if (new)
46456d18edaSBill Paul 				free(ysd);
46556d18edaSBill Paul 			return(YPERR_YPBIND);
46656d18edaSBill Paul 		}
467456ebbf8SBill Paul 		tv.tv_sec = _yplib_timeout/2;
4684415cd19SGarrett Wollman 		tv.tv_usec = 0;
4694415cd19SGarrett Wollman 		r = clnt_call(client, YPBINDPROC_DOMAIN,
4709d80b1ddSBill Paul 			xdr_domainname, (char *)&dom, xdr_ypbind_resp, &ypbr, tv);
4714415cd19SGarrett Wollman 		if(r != RPC_SUCCESS) {
4724415cd19SGarrett Wollman 			clnt_destroy(client);
4734415cd19SGarrett Wollman 			ysd->dom_vers = -1;
474a2308772SBill Paul 			if (r == RPC_PROGUNAVAIL || r == RPC_PROCUNAVAIL) {
475a2308772SBill Paul 				if (new)
476a2308772SBill Paul 					free(ysd);
47720e4b00aSBill Paul 				return(YPERR_YPBIND);
478a2308772SBill Paul 			}
47920e4b00aSBill Paul 			fprintf(stderr,
48020e4b00aSBill Paul 			"YP: server for domain %s not responding, retrying\n", dom);
4814415cd19SGarrett Wollman 			goto again;
48264416168SBill Paul 		} else {
48364416168SBill Paul 			if (ypbr.ypbind_status != YPBIND_SUCC_VAL) {
4849233c4d9SJason Evans 				struct timespec time_to_sleep, time_remaining;
4859233c4d9SJason Evans 
486456ebbf8SBill Paul 				clnt_destroy(client);
487456ebbf8SBill Paul 				ysd->dom_vers = -1;
4889233c4d9SJason Evans 
4899233c4d9SJason Evans 				time_to_sleep.tv_sec = _yplib_timeout/2;
4909233c4d9SJason Evans 				time_to_sleep.tv_nsec = 0;
4919233c4d9SJason Evans 				_nanosleep(&time_to_sleep,
4929233c4d9SJason Evans 				    &time_remaining);
493456ebbf8SBill Paul 				goto again;
49464416168SBill Paul 			}
4954415cd19SGarrett Wollman 		}
4964415cd19SGarrett Wollman 		clnt_destroy(client);
4974415cd19SGarrett Wollman 
4984415cd19SGarrett Wollman 		bzero((char *)&ysd->dom_server_addr, sizeof ysd->dom_server_addr);
4994415cd19SGarrett Wollman 		ysd->dom_server_addr.sin_family = AF_INET;
5004415cd19SGarrett Wollman 		ysd->dom_server_addr.sin_port =
5019d80b1ddSBill Paul 			*(u_short *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port;
5024415cd19SGarrett Wollman 		ysd->dom_server_addr.sin_addr.s_addr =
5039d80b1ddSBill Paul 			*(u_long *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr;
50456d18edaSBill Paul 
50556d18edaSBill Paul 		/*
50656d18edaSBill Paul 		 * We could do a reserved port check here too, but this
50756d18edaSBill Paul 		 * could pose compatibility problems. The local ypbind is
50856d18edaSBill Paul 		 * supposed to decide whether or not to trust yp servers
50956d18edaSBill Paul 		 * on insecure ports. For now, we trust its judgement.
51056d18edaSBill Paul 		 */
5114415cd19SGarrett Wollman 		ysd->dom_server_port =
5129d80b1ddSBill Paul 			*(u_short *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port;
5134415cd19SGarrett Wollman gotit:
5144415cd19SGarrett Wollman 		ysd->dom_vers = YPVERS;
51583ac6cdcSKris Kennaway 		strlcpy(ysd->dom_domain, dom, sizeof(ysd->dom_domain));
5164415cd19SGarrett Wollman 	}
5174415cd19SGarrett Wollman 
518a169c9b1SBill Paul 	/* Don't rebuild the connection to the server unless we have to. */
519a169c9b1SBill Paul 	if (ysd->dom_client == NULL) {
5204415cd19SGarrett Wollman 		tv.tv_sec = _yplib_timeout/2;
5214415cd19SGarrett Wollman 		tv.tv_usec = 0;
5224415cd19SGarrett Wollman 		ysd->dom_socket = RPC_ANYSOCK;
5234e6ace08SBill Paul 		ysd->dom_client = clntudp_bufcreate(&ysd->dom_server_addr,
5244e6ace08SBill Paul 			YPPROG, YPVERS, tv, &ysd->dom_socket, 1280, 2304);
5254415cd19SGarrett Wollman 		if(ysd->dom_client==NULL) {
5264415cd19SGarrett Wollman 			clnt_pcreateerror("clntudp_create");
5274415cd19SGarrett Wollman 			ysd->dom_vers = -1;
5284415cd19SGarrett Wollman 			goto again;
5294415cd19SGarrett Wollman 		}
5309233c4d9SJason Evans 		if(_fcntl(ysd->dom_socket, F_SETFD, 1) == -1)
5314415cd19SGarrett Wollman 			perror("fcntl: F_SETFD");
532a2308772SBill Paul 		/*
533a2308772SBill Paul 		 * We want a port number associated with this socket
534a2308772SBill Paul 		 * so that we can check its authenticity later.
535a2308772SBill Paul 		 */
536a2308772SBill Paul 		checklen = sizeof(struct sockaddr_in);
537a2308772SBill Paul 		bzero((char *)&check, checklen);
538d201fe46SDaniel Eischen 		_bind(ysd->dom_socket, (struct sockaddr *)&check, checklen);
539a2308772SBill Paul 		check.sin_family = AF_INET;
540d201fe46SDaniel Eischen 		if (!_getsockname(ysd->dom_socket,
541a2308772SBill Paul 		    (struct sockaddr *)&check, &checklen)) {
542a2308772SBill Paul 			ysd->dom_local_port = check.sin_port;
543a2308772SBill Paul 		} else {
544a2308772SBill Paul 			clnt_destroy(ysd->dom_client);
545a2308772SBill Paul 			if (new)
546a2308772SBill Paul 				free(ysd);
547a2308772SBill Paul 			return(YPERR_YPBIND);
548a2308772SBill Paul 		}
549a169c9b1SBill Paul 	}
5504415cd19SGarrett Wollman 
5514415cd19SGarrett Wollman 	if(new) {
5524415cd19SGarrett Wollman 		ysd->dom_pnext = _ypbindlist;
5534415cd19SGarrett Wollman 		_ypbindlist = ysd;
5544415cd19SGarrett Wollman 	}
5554415cd19SGarrett Wollman 
5564415cd19SGarrett Wollman 	if(ypdb!=NULL)
5574415cd19SGarrett Wollman 		*ypdb = ysd;
5584415cd19SGarrett Wollman 	return 0;
5594415cd19SGarrett Wollman }
5604415cd19SGarrett Wollman 
5614415cd19SGarrett Wollman static void
5624415cd19SGarrett Wollman _yp_unbind(ypb)
5634415cd19SGarrett Wollman 	struct dom_binding *ypb;
5644415cd19SGarrett Wollman {
5659fa75c15SBill Paul 	struct sockaddr_in check;
5669fa75c15SBill Paul 	int checklen = sizeof(struct sockaddr_in);
5679fa75c15SBill Paul 
5689fa75c15SBill Paul 	if (ypb->dom_client != NULL) {
5699fa75c15SBill Paul 		/* Check the socket -- may have been hosed by the caller. */
570d201fe46SDaniel Eischen 		if (_getsockname(ypb->dom_socket, (struct sockaddr *)&check,
5719fa75c15SBill Paul 	    	&checklen) == -1 || check.sin_family != AF_INET ||
5729fa75c15SBill Paul 	    	check.sin_port != ypb->dom_local_port) {
5739fa75c15SBill Paul 			int save, sock;
5749fa75c15SBill Paul 
5759fa75c15SBill Paul 			sock = ypb->dom_socket;
576d201fe46SDaniel Eischen 			save = _dup(ypb->dom_socket);
5774415cd19SGarrett Wollman 			clnt_destroy(ypb->dom_client);
578d201fe46SDaniel Eischen 			sock = _dup2(save, sock);
5799233c4d9SJason Evans 			_close(save);
5809fa75c15SBill Paul 		} else
5819fa75c15SBill Paul 			clnt_destroy(ypb->dom_client);
5829fa75c15SBill Paul 	}
5839fa75c15SBill Paul 
5844415cd19SGarrett Wollman 	ypb->dom_client = NULL;
5854415cd19SGarrett Wollman 	ypb->dom_socket = -1;
5862694f9b9SBill Paul 	ypb->dom_vers = -1;
5874e6ace08SBill Paul #ifdef YPMATCHCACHE
5884e6ace08SBill Paul 	ypmatch_cache_flush(ypb);
5894e6ace08SBill Paul #endif
5904415cd19SGarrett Wollman }
5914415cd19SGarrett Wollman 
5924415cd19SGarrett Wollman int
5934415cd19SGarrett Wollman yp_bind(dom)
5944415cd19SGarrett Wollman 	char *dom;
5954415cd19SGarrett Wollman {
5964415cd19SGarrett Wollman 	return _yp_dobind(dom, NULL);
5974415cd19SGarrett Wollman }
5984415cd19SGarrett Wollman 
5994415cd19SGarrett Wollman void
6004415cd19SGarrett Wollman yp_unbind(dom)
6014415cd19SGarrett Wollman 	char *dom;
6024415cd19SGarrett Wollman {
6034415cd19SGarrett Wollman 	struct dom_binding *ypb, *ypbp;
6044415cd19SGarrett Wollman 
6054415cd19SGarrett Wollman 	ypbp = NULL;
6064415cd19SGarrett Wollman 	for(ypb=_ypbindlist; ypb; ypb=ypb->dom_pnext) {
6074415cd19SGarrett Wollman 		if( strcmp(dom, ypb->dom_domain) == 0) {
6082694f9b9SBill Paul 			_yp_unbind(ypb);
6094415cd19SGarrett Wollman 			if(ypbp)
6104415cd19SGarrett Wollman 				ypbp->dom_pnext = ypb->dom_pnext;
6114415cd19SGarrett Wollman 			else
6124415cd19SGarrett Wollman 				_ypbindlist = ypb->dom_pnext;
6134415cd19SGarrett Wollman 			free(ypb);
6144415cd19SGarrett Wollman 			return;
6154415cd19SGarrett Wollman 		}
6164415cd19SGarrett Wollman 		ypbp = ypb;
6174415cd19SGarrett Wollman 	}
6184415cd19SGarrett Wollman 	return;
6194415cd19SGarrett Wollman }
6204415cd19SGarrett Wollman 
6214415cd19SGarrett Wollman int
6224415cd19SGarrett Wollman yp_match(indomain, inmap, inkey, inkeylen, outval, outvallen)
6234415cd19SGarrett Wollman 	char *indomain;
6244415cd19SGarrett Wollman 	char *inmap;
6254415cd19SGarrett Wollman 	const char *inkey;
6264415cd19SGarrett Wollman 	int inkeylen;
6274415cd19SGarrett Wollman 	char **outval;
6284415cd19SGarrett Wollman 	int *outvallen;
6294415cd19SGarrett Wollman {
6304415cd19SGarrett Wollman 	struct dom_binding *ysd;
6314415cd19SGarrett Wollman 	struct ypresp_val yprv;
6324415cd19SGarrett Wollman 	struct timeval tv;
6334415cd19SGarrett Wollman 	struct ypreq_key yprk;
6344415cd19SGarrett Wollman 	int r;
6354415cd19SGarrett Wollman 
6364415cd19SGarrett Wollman 	*outval = NULL;
6374415cd19SGarrett Wollman 	*outvallen = 0;
6384415cd19SGarrett Wollman 
63906643071SBill Paul 	/* Sanity check */
640e17334c3SBill Paul 
64106643071SBill Paul 	if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 ||
64206643071SBill Paul 	    inmap == NULL || !strlen(inmap) ||
64306643071SBill Paul 	    indomain == NULL || !strlen(indomain))
64406643071SBill Paul 		return YPERR_BADARGS;
645e17334c3SBill Paul 
6464e6ace08SBill Paul 	if (_yp_dobind(indomain, &ysd) != 0)
6474e6ace08SBill Paul 		return(YPERR_DOMAIN);
6484e6ace08SBill Paul 
6494e6ace08SBill Paul 	yprk.domain = indomain;
6504e6ace08SBill Paul 	yprk.map = inmap;
6514e6ace08SBill Paul 	yprk.key.keydat_val = (char *)inkey;
6524e6ace08SBill Paul 	yprk.key.keydat_len = inkeylen;
6534e6ace08SBill Paul 
6544415cd19SGarrett Wollman #ifdef YPMATCHCACHE
6554e6ace08SBill Paul 	if (ypmatch_cache_lookup(ysd, yprk.map, &yprk.key, &yprv.val) == TRUE) {
6564e6ace08SBill Paul /*
6574415cd19SGarrett Wollman 	if( !strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey,
6580e276383SBill Paul 	    inkeylen, &yprv.val.valdat_val, &yprv.val.valdat_len)) {
6594e6ace08SBill Paul */
6600e276383SBill Paul 		*outvallen = yprv.val.valdat_len;
6614415cd19SGarrett Wollman 		*outval = (char *)malloc(*outvallen+1);
6620e276383SBill Paul 		bcopy(yprv.val.valdat_val, *outval, *outvallen);
6634415cd19SGarrett Wollman 		(*outval)[*outvallen] = '\0';
6644415cd19SGarrett Wollman 		return 0;
6654415cd19SGarrett Wollman 	}
6664415cd19SGarrett Wollman #endif
6674415cd19SGarrett Wollman 
6684cc738f7SBill Paul again:
6694cc738f7SBill Paul 	if( _yp_dobind(indomain, &ysd) != 0)
6704cc738f7SBill Paul 		return YPERR_DOMAIN;
6714cc738f7SBill Paul 
6724415cd19SGarrett Wollman 	tv.tv_sec = _yplib_timeout;
6734415cd19SGarrett Wollman 	tv.tv_usec = 0;
6744415cd19SGarrett Wollman 
6754415cd19SGarrett Wollman 	bzero((char *)&yprv, sizeof yprv);
6764415cd19SGarrett Wollman 
6774415cd19SGarrett Wollman 	r = clnt_call(ysd->dom_client, YPPROC_MATCH,
6784415cd19SGarrett Wollman 		xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv);
6794415cd19SGarrett Wollman 	if(r != RPC_SUCCESS) {
6804415cd19SGarrett Wollman 		clnt_perror(ysd->dom_client, "yp_match: clnt_call");
6812694f9b9SBill Paul 		_yp_unbind(ysd);
6824415cd19SGarrett Wollman 		goto again;
6834415cd19SGarrett Wollman 	}
684a169c9b1SBill Paul 
6850e276383SBill Paul 	if( !(r=ypprot_err(yprv.stat)) ) {
6860e276383SBill Paul 		*outvallen = yprv.val.valdat_len;
6874415cd19SGarrett Wollman 		*outval = (char *)malloc(*outvallen+1);
6880e276383SBill Paul 		bcopy(yprv.val.valdat_val, *outval, *outvallen);
6894415cd19SGarrett Wollman 		(*outval)[*outvallen] = '\0';
6904415cd19SGarrett Wollman #ifdef YPMATCHCACHE
6914e6ace08SBill Paul 		ypmatch_cache_insert(ysd, yprk.map, &yprk.key, &yprv.val);
6924415cd19SGarrett Wollman #endif
6932694f9b9SBill Paul 	}
694a169c9b1SBill Paul 
695a169c9b1SBill Paul 	xdr_free(xdr_ypresp_val, (char *)&yprv);
6964415cd19SGarrett Wollman 	return r;
6974415cd19SGarrett Wollman }
6984415cd19SGarrett Wollman 
6994415cd19SGarrett Wollman int
7004415cd19SGarrett Wollman yp_get_default_domain(domp)
7014415cd19SGarrett Wollman char **domp;
7024415cd19SGarrett Wollman {
7034415cd19SGarrett Wollman 	*domp = NULL;
7044415cd19SGarrett Wollman 	if(_yp_domain[0] == '\0')
7054415cd19SGarrett Wollman 		if( getdomainname(_yp_domain, sizeof _yp_domain))
7064415cd19SGarrett Wollman 			return YPERR_NODOM;
7074415cd19SGarrett Wollman 	*domp = _yp_domain;
7084415cd19SGarrett Wollman 	return 0;
7094415cd19SGarrett Wollman }
7104415cd19SGarrett Wollman 
7114415cd19SGarrett Wollman int
7124415cd19SGarrett Wollman yp_first(indomain, inmap, outkey, outkeylen, outval, outvallen)
7134415cd19SGarrett Wollman 	char *indomain;
7144415cd19SGarrett Wollman 	char *inmap;
7154415cd19SGarrett Wollman 	char **outkey;
7164415cd19SGarrett Wollman 	int *outkeylen;
7174415cd19SGarrett Wollman 	char **outval;
7184415cd19SGarrett Wollman 	int *outvallen;
7194415cd19SGarrett Wollman {
7204415cd19SGarrett Wollman 	struct ypresp_key_val yprkv;
7214415cd19SGarrett Wollman 	struct ypreq_nokey yprnk;
7224415cd19SGarrett Wollman 	struct dom_binding *ysd;
7234415cd19SGarrett Wollman 	struct timeval tv;
7244415cd19SGarrett Wollman 	int r;
7254415cd19SGarrett Wollman 
72606643071SBill Paul 	/* Sanity check */
72706643071SBill Paul 
72806643071SBill Paul 	if (indomain == NULL || !strlen(indomain) ||
72906643071SBill Paul 	    inmap == NULL || !strlen(inmap))
73006643071SBill Paul 		return YPERR_BADARGS;
73106643071SBill Paul 
7324415cd19SGarrett Wollman 	*outkey = *outval = NULL;
7334415cd19SGarrett Wollman 	*outkeylen = *outvallen = 0;
7344415cd19SGarrett Wollman 
7354415cd19SGarrett Wollman again:
7364415cd19SGarrett Wollman 	if( _yp_dobind(indomain, &ysd) != 0)
7374415cd19SGarrett Wollman 		return YPERR_DOMAIN;
7384415cd19SGarrett Wollman 
7394415cd19SGarrett Wollman 	tv.tv_sec = _yplib_timeout;
7404415cd19SGarrett Wollman 	tv.tv_usec = 0;
7414415cd19SGarrett Wollman 
7424415cd19SGarrett Wollman 	yprnk.domain = indomain;
7434415cd19SGarrett Wollman 	yprnk.map = inmap;
7444415cd19SGarrett Wollman 	bzero((char *)&yprkv, sizeof yprkv);
7454415cd19SGarrett Wollman 
7464415cd19SGarrett Wollman 	r = clnt_call(ysd->dom_client, YPPROC_FIRST,
7474415cd19SGarrett Wollman 		xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv);
7484415cd19SGarrett Wollman 	if(r != RPC_SUCCESS) {
7494415cd19SGarrett Wollman 		clnt_perror(ysd->dom_client, "yp_first: clnt_call");
7502694f9b9SBill Paul 		_yp_unbind(ysd);
7514415cd19SGarrett Wollman 		goto again;
7524415cd19SGarrett Wollman 	}
7530e276383SBill Paul 	if( !(r=ypprot_err(yprkv.stat)) ) {
7540e276383SBill Paul 		*outkeylen = yprkv.key.keydat_len;
7554415cd19SGarrett Wollman 		*outkey = (char *)malloc(*outkeylen+1);
7560e276383SBill Paul 		bcopy(yprkv.key.keydat_val, *outkey, *outkeylen);
7574415cd19SGarrett Wollman 		(*outkey)[*outkeylen] = '\0';
7580e276383SBill Paul 		*outvallen = yprkv.val.valdat_len;
7594415cd19SGarrett Wollman 		*outval = (char *)malloc(*outvallen+1);
7600e276383SBill Paul 		bcopy(yprkv.val.valdat_val, *outval, *outvallen);
7614415cd19SGarrett Wollman 		(*outval)[*outvallen] = '\0';
7622694f9b9SBill Paul 	}
763a169c9b1SBill Paul 
764a169c9b1SBill Paul 	xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
7654415cd19SGarrett Wollman 	return r;
7664415cd19SGarrett Wollman }
7674415cd19SGarrett Wollman 
7684415cd19SGarrett Wollman int
7694415cd19SGarrett Wollman yp_next(indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen)
7704415cd19SGarrett Wollman 	char *indomain;
7714415cd19SGarrett Wollman 	char *inmap;
7724415cd19SGarrett Wollman 	char *inkey;
7734415cd19SGarrett Wollman 	int inkeylen;
7744415cd19SGarrett Wollman 	char **outkey;
7754415cd19SGarrett Wollman 	int *outkeylen;
7764415cd19SGarrett Wollman 	char **outval;
7774415cd19SGarrett Wollman 	int *outvallen;
7784415cd19SGarrett Wollman {
7794415cd19SGarrett Wollman 	struct ypresp_key_val yprkv;
7804415cd19SGarrett Wollman 	struct ypreq_key yprk;
7814415cd19SGarrett Wollman 	struct dom_binding *ysd;
7824415cd19SGarrett Wollman 	struct timeval tv;
7834415cd19SGarrett Wollman 	int r;
7844415cd19SGarrett Wollman 
78506643071SBill Paul 	/* Sanity check */
78606643071SBill Paul 
78706643071SBill Paul 	if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 ||
78806643071SBill Paul 	    inmap == NULL || !strlen(inmap) ||
78906643071SBill Paul 	    indomain == NULL || !strlen(indomain))
79006643071SBill Paul 		return YPERR_BADARGS;
79106643071SBill Paul 
7924415cd19SGarrett Wollman 	*outkey = *outval = NULL;
7934415cd19SGarrett Wollman 	*outkeylen = *outvallen = 0;
7944415cd19SGarrett Wollman 
7954415cd19SGarrett Wollman again:
7964415cd19SGarrett Wollman 	if( _yp_dobind(indomain, &ysd) != 0)
7974415cd19SGarrett Wollman 		return YPERR_DOMAIN;
7984415cd19SGarrett Wollman 
7994415cd19SGarrett Wollman 	tv.tv_sec = _yplib_timeout;
8004415cd19SGarrett Wollman 	tv.tv_usec = 0;
8014415cd19SGarrett Wollman 
8024415cd19SGarrett Wollman 	yprk.domain = indomain;
8034415cd19SGarrett Wollman 	yprk.map = inmap;
8040e276383SBill Paul 	yprk.key.keydat_val = inkey;
8050e276383SBill Paul 	yprk.key.keydat_len = inkeylen;
8064415cd19SGarrett Wollman 	bzero((char *)&yprkv, sizeof yprkv);
8074415cd19SGarrett Wollman 
8084415cd19SGarrett Wollman 	r = clnt_call(ysd->dom_client, YPPROC_NEXT,
8094415cd19SGarrett Wollman 		xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv);
8104415cd19SGarrett Wollman 	if(r != RPC_SUCCESS) {
8114415cd19SGarrett Wollman 		clnt_perror(ysd->dom_client, "yp_next: clnt_call");
8122694f9b9SBill Paul 		_yp_unbind(ysd);
8134415cd19SGarrett Wollman 		goto again;
8144415cd19SGarrett Wollman 	}
8150e276383SBill Paul 	if( !(r=ypprot_err(yprkv.stat)) ) {
8160e276383SBill Paul 		*outkeylen = yprkv.key.keydat_len;
8174415cd19SGarrett Wollman 		*outkey = (char *)malloc(*outkeylen+1);
8180e276383SBill Paul 		bcopy(yprkv.key.keydat_val, *outkey, *outkeylen);
8194415cd19SGarrett Wollman 		(*outkey)[*outkeylen] = '\0';
8200e276383SBill Paul 		*outvallen = yprkv.val.valdat_len;
8214415cd19SGarrett Wollman 		*outval = (char *)malloc(*outvallen+1);
8220e276383SBill Paul 		bcopy(yprkv.val.valdat_val, *outval, *outvallen);
8234415cd19SGarrett Wollman 		(*outval)[*outvallen] = '\0';
8242694f9b9SBill Paul 	}
825a169c9b1SBill Paul 
826a169c9b1SBill Paul 	xdr_free(xdr_ypresp_key_val, (char *)&yprkv);
8274415cd19SGarrett Wollman 	return r;
8284415cd19SGarrett Wollman }
8294415cd19SGarrett Wollman 
8304415cd19SGarrett Wollman int
8314415cd19SGarrett Wollman yp_all(indomain, inmap, incallback)
8324415cd19SGarrett Wollman 	char *indomain;
8334415cd19SGarrett Wollman 	char *inmap;
8344415cd19SGarrett Wollman 	struct ypall_callback *incallback;
8354415cd19SGarrett Wollman {
8364415cd19SGarrett Wollman 	struct ypreq_nokey yprnk;
8374415cd19SGarrett Wollman 	struct dom_binding *ysd;
8384415cd19SGarrett Wollman 	struct timeval tv;
8394415cd19SGarrett Wollman 	struct sockaddr_in clnt_sin;
8404415cd19SGarrett Wollman 	CLIENT *clnt;
84108aff01bSBill Paul 	u_long status, savstat;
8424415cd19SGarrett Wollman 	int clnt_sock;
8434415cd19SGarrett Wollman 
84406643071SBill Paul 	/* Sanity check */
84506643071SBill Paul 
84606643071SBill Paul 	if (indomain == NULL || !strlen(indomain) ||
84706643071SBill Paul 	    inmap == NULL || !strlen(inmap))
84806643071SBill Paul 		return YPERR_BADARGS;
84906643071SBill Paul 
8502694f9b9SBill Paul again:
8512694f9b9SBill Paul 
8524415cd19SGarrett Wollman 	if( _yp_dobind(indomain, &ysd) != 0)
8534415cd19SGarrett Wollman 		return YPERR_DOMAIN;
8544415cd19SGarrett Wollman 
8554415cd19SGarrett Wollman 	tv.tv_sec = _yplib_timeout;
8564415cd19SGarrett Wollman 	tv.tv_usec = 0;
8572694f9b9SBill Paul 
8582694f9b9SBill Paul 	/* YPPROC_ALL manufactures its own channel to ypserv using TCP */
8592694f9b9SBill Paul 
8604415cd19SGarrett Wollman 	clnt_sock = RPC_ANYSOCK;
8614415cd19SGarrett Wollman 	clnt_sin = ysd->dom_server_addr;
8624415cd19SGarrett Wollman 	clnt_sin.sin_port = 0;
8634415cd19SGarrett Wollman 	clnt = clnttcp_create(&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
8644415cd19SGarrett Wollman 	if(clnt==NULL) {
8654415cd19SGarrett Wollman 		printf("clnttcp_create failed\n");
8664415cd19SGarrett Wollman 		return YPERR_PMAP;
8674415cd19SGarrett Wollman 	}
8684415cd19SGarrett Wollman 
8694415cd19SGarrett Wollman 	yprnk.domain = indomain;
8704415cd19SGarrett Wollman 	yprnk.map = inmap;
8714415cd19SGarrett Wollman 	ypresp_allfn = incallback->foreach;
8724415cd19SGarrett Wollman 	ypresp_data = (void *)incallback->data;
8734415cd19SGarrett Wollman 
8742694f9b9SBill Paul 	if (clnt_call(clnt, YPPROC_ALL,
8752694f9b9SBill Paul 		xdr_ypreq_nokey, &yprnk,
8762694f9b9SBill Paul 		xdr_ypresp_all_seq, &status, tv) != RPC_SUCCESS) {
8772694f9b9SBill Paul 			clnt_perror(ysd->dom_client, "yp_next: clnt_call");
8782694f9b9SBill Paul 			clnt_destroy(clnt);
8792694f9b9SBill Paul 			_yp_unbind(ysd);
8802694f9b9SBill Paul 			goto again;
8812694f9b9SBill Paul 	}
8822694f9b9SBill Paul 
8834415cd19SGarrett Wollman 	clnt_destroy(clnt);
88408aff01bSBill Paul 	savstat = status;
8854415cd19SGarrett Wollman 	xdr_free(xdr_ypresp_all_seq, (char *)&status);	/* not really needed... */
88608aff01bSBill Paul 	if(savstat != YP_NOMORE)
88708aff01bSBill Paul 		return ypprot_err(savstat);
8884415cd19SGarrett Wollman 	return 0;
8894415cd19SGarrett Wollman }
8904415cd19SGarrett Wollman 
8914415cd19SGarrett Wollman int
8924415cd19SGarrett Wollman yp_order(indomain, inmap, outorder)
8934415cd19SGarrett Wollman 	char *indomain;
8944415cd19SGarrett Wollman 	char *inmap;
8954415cd19SGarrett Wollman 	int *outorder;
8964415cd19SGarrett Wollman {
8974415cd19SGarrett Wollman  	struct dom_binding *ysd;
8984415cd19SGarrett Wollman 	struct ypresp_order ypro;
8994415cd19SGarrett Wollman 	struct ypreq_nokey yprnk;
9004415cd19SGarrett Wollman 	struct timeval tv;
9014415cd19SGarrett Wollman 	int r;
9024415cd19SGarrett Wollman 
90306643071SBill Paul 	/* Sanity check */
90406643071SBill Paul 
90506643071SBill Paul 	if (indomain == NULL || !strlen(indomain) ||
90606643071SBill Paul 	    inmap == NULL || !strlen(inmap))
90706643071SBill Paul 		return YPERR_BADARGS;
90806643071SBill Paul 
9094415cd19SGarrett Wollman again:
9104415cd19SGarrett Wollman 	if( _yp_dobind(indomain, &ysd) != 0)
9114415cd19SGarrett Wollman 		return YPERR_DOMAIN;
9124415cd19SGarrett Wollman 
9134415cd19SGarrett Wollman 	tv.tv_sec = _yplib_timeout;
9144415cd19SGarrett Wollman 	tv.tv_usec = 0;
9154415cd19SGarrett Wollman 
9164415cd19SGarrett Wollman 	yprnk.domain = indomain;
9174415cd19SGarrett Wollman 	yprnk.map = inmap;
9184415cd19SGarrett Wollman 
9194415cd19SGarrett Wollman 	bzero((char *)(char *)&ypro, sizeof ypro);
9204415cd19SGarrett Wollman 
9214415cd19SGarrett Wollman 	r = clnt_call(ysd->dom_client, YPPROC_ORDER,
9224415cd19SGarrett Wollman 		xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv);
9239fa75c15SBill Paul 
9249fa75c15SBill Paul 	/*
9259fa75c15SBill Paul 	 * NIS+ in YP compat mode doesn't support the YPPROC_ORDER
9269fa75c15SBill Paul 	 * procedure.
9279fa75c15SBill Paul 	 */
9289fa75c15SBill Paul 	if (r == RPC_PROCUNAVAIL) {
9299fa75c15SBill Paul 		return(YPERR_YPERR);
9309fa75c15SBill Paul 	}
9319fa75c15SBill Paul 
9324415cd19SGarrett Wollman 	if(r != RPC_SUCCESS) {
9334415cd19SGarrett Wollman 		clnt_perror(ysd->dom_client, "yp_order: clnt_call");
9342694f9b9SBill Paul 		_yp_unbind(ysd);
9354415cd19SGarrett Wollman 		goto again;
9364415cd19SGarrett Wollman 	}
9374415cd19SGarrett Wollman 
938a169c9b1SBill Paul 	if( !(r=ypprot_err(ypro.stat)) ) {
9394415cd19SGarrett Wollman 		*outorder = ypro.ordernum;
9402694f9b9SBill Paul 	}
941a169c9b1SBill Paul 
9424415cd19SGarrett Wollman 	xdr_free(xdr_ypresp_order, (char *)&ypro);
9432694f9b9SBill Paul 	return (r);
9444415cd19SGarrett Wollman }
9454415cd19SGarrett Wollman 
9464415cd19SGarrett Wollman int
9474415cd19SGarrett Wollman yp_master(indomain, inmap, outname)
9484415cd19SGarrett Wollman 	char *indomain;
9494415cd19SGarrett Wollman 	char *inmap;
9504415cd19SGarrett Wollman 	char **outname;
9514415cd19SGarrett Wollman {
9524415cd19SGarrett Wollman 	struct dom_binding *ysd;
9534415cd19SGarrett Wollman 	struct ypresp_master yprm;
9544415cd19SGarrett Wollman 	struct ypreq_nokey yprnk;
9554415cd19SGarrett Wollman 	struct timeval tv;
9564415cd19SGarrett Wollman 	int r;
9574415cd19SGarrett Wollman 
95806643071SBill Paul 	/* Sanity check */
95906643071SBill Paul 
96006643071SBill Paul 	if (indomain == NULL || !strlen(indomain) ||
96106643071SBill Paul 	    inmap == NULL || !strlen(inmap))
96206643071SBill Paul 		return YPERR_BADARGS;
9634415cd19SGarrett Wollman again:
9644415cd19SGarrett Wollman 	if( _yp_dobind(indomain, &ysd) != 0)
9654415cd19SGarrett Wollman 		return YPERR_DOMAIN;
9664415cd19SGarrett Wollman 
9674415cd19SGarrett Wollman 	tv.tv_sec = _yplib_timeout;
9684415cd19SGarrett Wollman 	tv.tv_usec = 0;
9694415cd19SGarrett Wollman 
9704415cd19SGarrett Wollman 	yprnk.domain = indomain;
9714415cd19SGarrett Wollman 	yprnk.map = inmap;
9724415cd19SGarrett Wollman 
9734415cd19SGarrett Wollman 	bzero((char *)&yprm, sizeof yprm);
9744415cd19SGarrett Wollman 
9754415cd19SGarrett Wollman 	r = clnt_call(ysd->dom_client, YPPROC_MASTER,
9764415cd19SGarrett Wollman 		xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv);
9774415cd19SGarrett Wollman 	if(r != RPC_SUCCESS) {
9784415cd19SGarrett Wollman 		clnt_perror(ysd->dom_client, "yp_master: clnt_call");
9792694f9b9SBill Paul 		_yp_unbind(ysd);
9804415cd19SGarrett Wollman 		goto again;
9814415cd19SGarrett Wollman 	}
9822694f9b9SBill Paul 
9830e276383SBill Paul 	if( !(r=ypprot_err(yprm.stat)) ) {
9840e276383SBill Paul 		*outname = (char *)strdup(yprm.peer);
9852694f9b9SBill Paul 	}
986a169c9b1SBill Paul 
987a169c9b1SBill Paul 	xdr_free(xdr_ypresp_master, (char *)&yprm);
9882694f9b9SBill Paul 	return (r);
9894415cd19SGarrett Wollman }
990b9729ac2SBill Paul int
9914415cd19SGarrett Wollman yp_maplist(indomain, outmaplist)
9924415cd19SGarrett Wollman 	char *indomain;
9934415cd19SGarrett Wollman 	struct ypmaplist **outmaplist;
9944415cd19SGarrett Wollman {
9954415cd19SGarrett Wollman 	struct dom_binding *ysd;
9964415cd19SGarrett Wollman 	struct ypresp_maplist ypml;
9974415cd19SGarrett Wollman 	struct timeval tv;
9984415cd19SGarrett Wollman 	int r;
9994415cd19SGarrett Wollman 
100006643071SBill Paul 	/* Sanity check */
100106643071SBill Paul 
100206643071SBill Paul 	if (indomain == NULL || !strlen(indomain))
100306643071SBill Paul 		return YPERR_BADARGS;
100406643071SBill Paul 
10054415cd19SGarrett Wollman again:
10064415cd19SGarrett Wollman 	if( _yp_dobind(indomain, &ysd) != 0)
10074415cd19SGarrett Wollman 		return YPERR_DOMAIN;
10084415cd19SGarrett Wollman 
10094415cd19SGarrett Wollman 	tv.tv_sec = _yplib_timeout;
10104415cd19SGarrett Wollman 	tv.tv_usec = 0;
10114415cd19SGarrett Wollman 
10124415cd19SGarrett Wollman 	bzero((char *)&ypml, sizeof ypml);
10134415cd19SGarrett Wollman 
10144415cd19SGarrett Wollman 	r = clnt_call(ysd->dom_client, YPPROC_MAPLIST,
10159d80b1ddSBill Paul 		xdr_domainname,(char *)&indomain,xdr_ypresp_maplist,&ypml,tv);
10164415cd19SGarrett Wollman 	if (r != RPC_SUCCESS) {
10174415cd19SGarrett Wollman 		clnt_perror(ysd->dom_client, "yp_maplist: clnt_call");
10182694f9b9SBill Paul 		_yp_unbind(ysd);
10194415cd19SGarrett Wollman 		goto again;
10204415cd19SGarrett Wollman 	}
1021a169c9b1SBill Paul 	if( !(r=ypprot_err(ypml.stat)) ) {
10220e276383SBill Paul 		*outmaplist = ypml.maps;
10232694f9b9SBill Paul 	}
10242694f9b9SBill Paul 
1025a169c9b1SBill Paul 	/* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/
10262694f9b9SBill Paul 	return (r);
10274415cd19SGarrett Wollman }
10284415cd19SGarrett Wollman 
10294415cd19SGarrett Wollman char *
10304415cd19SGarrett Wollman yperr_string(incode)
10314415cd19SGarrett Wollman 	int incode;
10324415cd19SGarrett Wollman {
10334415cd19SGarrett Wollman 	static char err[80];
10344415cd19SGarrett Wollman 
10354415cd19SGarrett Wollman 	switch(incode) {
10364415cd19SGarrett Wollman 	case 0:
10374415cd19SGarrett Wollman 		return "Success";
10384415cd19SGarrett Wollman 	case YPERR_BADARGS:
10394415cd19SGarrett Wollman 		return "Request arguments bad";
10404415cd19SGarrett Wollman 	case YPERR_RPC:
10414415cd19SGarrett Wollman 		return "RPC failure";
10424415cd19SGarrett Wollman 	case YPERR_DOMAIN:
10434415cd19SGarrett Wollman 		return "Can't bind to server which serves this domain";
10444415cd19SGarrett Wollman 	case YPERR_MAP:
10454415cd19SGarrett Wollman 		return "No such map in server's domain";
10464415cd19SGarrett Wollman 	case YPERR_KEY:
10474415cd19SGarrett Wollman 		return "No such key in map";
10484415cd19SGarrett Wollman 	case YPERR_YPERR:
10494415cd19SGarrett Wollman 		return "YP server error";
10504415cd19SGarrett Wollman 	case YPERR_RESRC:
10514415cd19SGarrett Wollman 		return "Local resource allocation failure";
10524415cd19SGarrett Wollman 	case YPERR_NOMORE:
10534415cd19SGarrett Wollman 		return "No more records in map database";
10544415cd19SGarrett Wollman 	case YPERR_PMAP:
10554415cd19SGarrett Wollman 		return "Can't communicate with portmapper";
10564415cd19SGarrett Wollman 	case YPERR_YPBIND:
10574415cd19SGarrett Wollman 		return "Can't communicate with ypbind";
10584415cd19SGarrett Wollman 	case YPERR_YPSERV:
10594415cd19SGarrett Wollman 		return "Can't communicate with ypserv";
10604415cd19SGarrett Wollman 	case YPERR_NODOM:
10614415cd19SGarrett Wollman 		return "Local domain name not set";
10624415cd19SGarrett Wollman 	case YPERR_BADDB:
10634415cd19SGarrett Wollman 		return "Server data base is bad";
10644415cd19SGarrett Wollman 	case YPERR_VERS:
10654415cd19SGarrett Wollman 		return "YP server version mismatch - server can't supply service.";
10664415cd19SGarrett Wollman 	case YPERR_ACCESS:
10674415cd19SGarrett Wollman 		return "Access violation";
10684415cd19SGarrett Wollman 	case YPERR_BUSY:
10694415cd19SGarrett Wollman 		return "Database is busy";
10704415cd19SGarrett Wollman 	}
10714415cd19SGarrett Wollman 	sprintf(err, "YP unknown error %d\n", incode);
10724415cd19SGarrett Wollman 	return err;
10734415cd19SGarrett Wollman }
10744415cd19SGarrett Wollman 
10754415cd19SGarrett Wollman int
10764415cd19SGarrett Wollman ypprot_err(incode)
10774415cd19SGarrett Wollman 	unsigned int incode;
10784415cd19SGarrett Wollman {
10794415cd19SGarrett Wollman 	switch(incode) {
10804415cd19SGarrett Wollman 	case YP_TRUE:
10814415cd19SGarrett Wollman 		return 0;
10824415cd19SGarrett Wollman 	case YP_FALSE:
10834415cd19SGarrett Wollman 		return YPERR_YPBIND;
10844415cd19SGarrett Wollman 	case YP_NOMORE:
10854415cd19SGarrett Wollman 		return YPERR_NOMORE;
10864415cd19SGarrett Wollman 	case YP_NOMAP:
10874415cd19SGarrett Wollman 		return YPERR_MAP;
10884415cd19SGarrett Wollman 	case YP_NODOM:
1089bc8e373cSBill Paul 		return YPERR_DOMAIN;
10904415cd19SGarrett Wollman 	case YP_NOKEY:
10914415cd19SGarrett Wollman 		return YPERR_KEY;
10924415cd19SGarrett Wollman 	case YP_BADOP:
10934415cd19SGarrett Wollman 		return YPERR_YPERR;
10944415cd19SGarrett Wollman 	case YP_BADDB:
10954415cd19SGarrett Wollman 		return YPERR_BADDB;
10964415cd19SGarrett Wollman 	case YP_YPERR:
10974415cd19SGarrett Wollman 		return YPERR_YPERR;
10984415cd19SGarrett Wollman 	case YP_BADARGS:
10994415cd19SGarrett Wollman 		return YPERR_BADARGS;
11004415cd19SGarrett Wollman 	case YP_VERS:
11014415cd19SGarrett Wollman 		return YPERR_VERS;
11024415cd19SGarrett Wollman 	}
11034415cd19SGarrett Wollman 	return YPERR_YPERR;
11044415cd19SGarrett Wollman }
11054415cd19SGarrett Wollman 
11064415cd19SGarrett Wollman int
11074415cd19SGarrett Wollman _yp_check(dom)
11084415cd19SGarrett Wollman 	char **dom;
11094415cd19SGarrett Wollman {
11104415cd19SGarrett Wollman 	char *unused;
11114415cd19SGarrett Wollman 
11124415cd19SGarrett Wollman 	if( _yp_domain[0]=='\0' )
11134415cd19SGarrett Wollman 		if( yp_get_default_domain(&unused) )
11144415cd19SGarrett Wollman 			return 0;
11154415cd19SGarrett Wollman 
11164415cd19SGarrett Wollman 	if(dom)
11174415cd19SGarrett Wollman 		*dom = _yp_domain;
11184415cd19SGarrett Wollman 
11190f98415eSBill Paul 	if( yp_bind(_yp_domain)==0 ) {
11200f98415eSBill Paul 		yp_unbind(_yp_domain);
11214415cd19SGarrett Wollman 		return 1;
11220f98415eSBill Paul 	}
11234415cd19SGarrett Wollman 	return 0;
11244415cd19SGarrett Wollman }
1125