Update.
[glibc.git] / nis / ypclnt.c
bloba62e356912e796be2405e293fa33d89b95012479
1 /* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <libintl.h>
25 #include <rpc/rpc.h>
26 #include <rpcsvc/nis.h>
27 #include <rpcsvc/yp.h>
28 #include <rpcsvc/ypclnt.h>
29 #include <rpcsvc/ypupd.h>
30 #include <sys/uio.h>
31 #include <bits/libc-lock.h>
33 /* This should only be defined on systems with a BSD compatible ypbind */
34 #ifndef BINDINGDIR
35 # define BINDINGDIR "/var/yp/binding"
36 #endif
38 struct dom_binding
40 struct dom_binding *dom_pnext;
41 char dom_domain[YPMAXDOMAIN + 1];
42 struct sockaddr_in dom_server_addr;
43 int dom_socket;
44 CLIENT *dom_client;
46 typedef struct dom_binding dom_binding;
48 static struct timeval RPCTIMEOUT = {25, 0};
49 static struct timeval UDPTIMEOUT = {5, 0};
50 static int const MAXTRIES = 2;
51 static char __ypdomainname[NIS_MAXNAMELEN + 1] = "\0";
52 __libc_lock_define_initialized (static, ypbindlist_lock)
53 static dom_binding *__ypbindlist = NULL;
56 static int
57 __yp_bind (const char *domain, dom_binding **ypdb)
59 struct sockaddr_in clnt_saddr;
60 struct ypbind_resp ypbr;
61 dom_binding *ysd = NULL;
62 int clnt_sock;
63 CLIENT *client;
64 int is_new = 0;
66 if (domain == NULL || domain[0] == '\0')
67 return YPERR_BADARGS;
69 if (ypdb != NULL)
71 ysd = *ypdb;
72 while (ysd != NULL)
74 if (strcmp (domain, ysd->dom_domain) == 0)
75 break;
76 ysd = ysd->dom_pnext;
80 if (ysd == NULL)
82 is_new = 1;
83 ysd = (dom_binding *) calloc (1, sizeof *ysd);
84 if (__builtin_expect (ysd == NULL, 0))
85 return YPERR_RESRC;
88 #if USE_BINDINGDIR
89 if (ysd->dom_client == NULL)
91 /* Try binding dir at first if we have no binding */
92 char path[sizeof (BINDINGDIR) + strlen (domain) + 10];
93 struct iovec vec[2];
94 unsigned short port;
95 int fd;
97 sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
98 fd = open (path, O_RDONLY);
99 if (fd >= 0)
101 /* We have a binding file and could save a RPC call */
102 vec[0].iov_base = &port;
103 vec[0].iov_len = sizeof (port);
104 vec[1].iov_base = &ypbr;
105 vec[1].iov_len = sizeof (ypbr);
107 if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
109 ysd->dom_server_addr.sin_family = AF_INET;
110 memcpy (&ysd->dom_server_addr.sin_port,
111 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
112 sizeof (ysd->dom_server_addr.sin_port));
113 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
114 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
115 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
116 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
117 ysd->dom_domain[YPMAXDOMAIN] = '\0';
119 ysd->dom_socket = RPC_ANYSOCK;
120 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG,
121 YPVERS, UDPTIMEOUT,
122 &ysd->dom_socket);
124 if (ysd->dom_client != NULL)
125 /* If the program exits, close the socket */
126 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
127 perror ("fcntl: F_SETFD");
129 close (fd);
132 #endif /* USE_BINDINGDIR */
134 if (ysd->dom_client == NULL)
136 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
137 clnt_saddr.sin_family = AF_INET;
138 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
139 clnt_sock = RPC_ANYSOCK;
140 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
141 &clnt_sock, 0, 0);
142 if (client == NULL)
144 if (is_new)
145 free (ysd);
146 return YPERR_YPBIND;
148 /* Check the port number -- should be < IPPORT_RESERVED.
149 If not, it's possible someone has registered a bogus
150 ypbind with the portmapper and is trying to trick us. */
151 if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
153 clnt_destroy (client);
154 if (is_new)
155 free (ysd);
156 return YPERR_YPBIND;
159 if (clnt_call (client, YPBINDPROC_DOMAIN,
160 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
161 (xdrproc_t) xdr_ypbind_resp,
162 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
164 clnt_destroy (client);
165 if (is_new)
166 free (ysd);
167 return YPERR_YPBIND;
170 clnt_destroy (client);
172 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
174 fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
175 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
176 if (is_new)
177 free (ysd);
178 return YPERR_DOMAIN;
180 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
181 ysd->dom_server_addr.sin_family = AF_INET;
182 memcpy (&ysd->dom_server_addr.sin_port,
183 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
184 sizeof (ysd->dom_server_addr.sin_port));
185 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
186 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
187 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
188 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
189 ysd->dom_domain[YPMAXDOMAIN] = '\0';
191 ysd->dom_socket = RPC_ANYSOCK;
192 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
193 UDPTIMEOUT, &ysd->dom_socket);
195 if (ysd->dom_client != NULL)
196 /* If the program exits, close the socket */
197 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
198 perror ("fcntl: F_SETFD");
201 if (ysd->dom_client == NULL)
203 if (is_new)
204 free (ysd);
205 return YPERR_YPSERV;
208 if (is_new && ypdb != NULL)
210 ysd->dom_pnext = *ypdb;
211 *ypdb = ysd;
214 return YPERR_SUCCESS;
217 static void
218 __yp_unbind (dom_binding *ydb)
220 clnt_destroy (ydb->dom_client);
221 ydb->dom_client = NULL;
225 yp_bind (const char *indomain)
227 int status;
229 __libc_lock_lock (ypbindlist_lock);
231 status = __yp_bind (indomain, &__ypbindlist);
233 __libc_lock_unlock (ypbindlist_lock);
235 return status;
238 static void
239 yp_unbind_locked (const char *indomain)
241 dom_binding *ydbptr, *ydbptr2;
243 ydbptr2 = NULL;
244 ydbptr = __ypbindlist;
246 while (ydbptr != NULL)
248 if (strcmp (ydbptr->dom_domain, indomain) == 0)
250 dom_binding *work;
252 work = ydbptr;
253 if (ydbptr2 == NULL)
254 __ypbindlist = __ypbindlist->dom_pnext;
255 else
256 ydbptr2 = ydbptr->dom_pnext;
257 __yp_unbind (work);
258 free (work);
259 break;
261 ydbptr2 = ydbptr;
262 ydbptr = ydbptr->dom_pnext;
266 void
267 yp_unbind (const char *indomain)
269 __libc_lock_lock (ypbindlist_lock);
271 yp_unbind_locked (indomain);
273 __libc_lock_unlock (ypbindlist_lock);
275 return;
278 static int
279 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
280 caddr_t req, xdrproc_t xres, caddr_t resp)
282 dom_binding *ydb = NULL;
283 bool_t use_ypbindlist = FALSE;
284 int try, status;
285 enum clnt_stat result;
286 int saved_errno = errno;
288 try = 0;
289 status = YPERR_YPERR;
291 __libc_lock_lock (ypbindlist_lock);
292 if (__ypbindlist != NULL)
294 ydb = __ypbindlist;
295 while (ydb != NULL)
297 if (strcmp (domain, ydb->dom_domain) == 0)
298 break;
299 ydb = ydb->dom_pnext;
301 if (ydb != NULL)
302 use_ypbindlist = TRUE;
303 else
304 __libc_lock_unlock (ypbindlist_lock);
306 else
307 __libc_lock_unlock (ypbindlist_lock);
309 while (try < MAXTRIES && status != YPERR_SUCCESS)
311 if (__yp_bind (domain, &ydb) != 0)
313 if (use_ypbindlist)
314 __libc_lock_unlock (ypbindlist_lock);
315 __set_errno (saved_errno);
316 return YPERR_DOMAIN;
319 result = clnt_call (ydb->dom_client, prog,
320 xargs, req, xres, resp, RPCTIMEOUT);
322 if (result != RPC_SUCCESS)
324 /* Don't print the error message on the first try. It
325 could be that we use cached data which is now invalid. */
326 if (try != 0)
327 clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
329 if (use_ypbindlist)
331 /* We use ypbindlist, and the old cached data is
332 invalid. unbind now and create a new binding */
333 yp_unbind_locked (domain);
334 __libc_lock_unlock (ypbindlist_lock);
335 use_ypbindlist = FALSE;
337 else
339 __yp_unbind (ydb);
340 free (ydb);
343 ydb = NULL;
344 status = YPERR_RPC;
346 else
347 status = YPERR_SUCCESS;
349 try++;
351 if (use_ypbindlist)
353 __libc_lock_unlock (ypbindlist_lock);
354 use_ypbindlist = FALSE;
356 else
357 if (ydb != NULL)
359 __yp_unbind (ydb);
360 free (ydb);
361 ydb = NULL;
364 __set_errno (saved_errno);
366 return status;
370 __libc_lock_define_initialized (static, domainname_lock)
373 yp_get_default_domain (char **outdomain)
375 int result = YPERR_SUCCESS;;
376 *outdomain = NULL;
378 __libc_lock_lock (domainname_lock);
380 if (__ypdomainname[0] == '\0')
382 if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
383 result = YPERR_NODOM;
384 else if (strcmp (__ypdomainname, "(none)") == 0)
386 /* If domainname is not set, some systems will return "(none)" */
387 __ypdomainname[0] = '\0';
388 result = YPERR_NODOM;
390 else
391 *outdomain = __ypdomainname;
393 else
394 *outdomain = __ypdomainname;
396 __libc_lock_unlock (domainname_lock);
398 return result;
402 __yp_check (char **domain)
404 char *unused;
406 if (__ypdomainname[0] == '\0')
407 if (yp_get_default_domain (&unused))
408 return 0;
410 if (domain)
411 *domain = __ypdomainname;
413 if (yp_bind (__ypdomainname) == 0)
414 return 1;
415 return 0;
419 yp_match (const char *indomain, const char *inmap, const char *inkey,
420 const int inkeylen, char **outval, int *outvallen)
422 ypreq_key req;
423 ypresp_val resp;
424 enum clnt_stat result;
426 if (indomain == NULL || indomain[0] == '\0' ||
427 inmap == NULL || inmap[0] == '\0' ||
428 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
429 return YPERR_BADARGS;
431 req.domain = (char *) indomain;
432 req.map = (char *) inmap;
433 req.key.keydat_val = (char *) inkey;
434 req.key.keydat_len = inkeylen;
436 *outval = NULL;
437 *outvallen = 0;
438 memset (&resp, '\0', sizeof (resp));
440 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
441 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
442 (caddr_t) & resp);
444 if (result != YPERR_SUCCESS)
445 return result;
446 if (resp.stat != YP_TRUE)
447 return ypprot_err (resp.stat);
449 *outvallen = resp.val.valdat_len;
450 *outval = malloc (*outvallen + 1);
451 if (__builtin_expect (*outval == NULL, 0))
452 return YPERR_RESRC;
453 memcpy (*outval, resp.val.valdat_val, *outvallen);
454 (*outval)[*outvallen] = '\0';
456 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
458 return YPERR_SUCCESS;
462 yp_first (const char *indomain, const char *inmap, char **outkey,
463 int *outkeylen, char **outval, int *outvallen)
465 ypreq_nokey req;
466 ypresp_key_val resp;
467 enum clnt_stat result;
469 if (indomain == NULL || indomain[0] == '\0' ||
470 inmap == NULL || inmap[0] == '\0')
471 return YPERR_BADARGS;
473 req.domain = (char *) indomain;
474 req.map = (char *) inmap;
476 *outkey = *outval = NULL;
477 *outkeylen = *outvallen = 0;
478 memset (&resp, '\0', sizeof (resp));
480 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
481 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
482 (caddr_t) & resp);
484 if (result != RPC_SUCCESS)
485 return YPERR_RPC;
486 if (resp.stat != YP_TRUE)
487 return ypprot_err (resp.stat);
489 *outkeylen = resp.key.keydat_len;
490 *outkey = malloc (*outkeylen + 1);
491 if (__builtin_expect (*outkey == NULL, 0))
492 return YPERR_RESRC;
493 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
494 (*outkey)[*outkeylen] = '\0';
495 *outvallen = resp.val.valdat_len;
496 *outval = malloc (*outvallen + 1);
497 if (__builtin_expect (*outval == NULL, 0))
498 return YPERR_RESRC;
499 memcpy (*outval, resp.val.valdat_val, *outvallen);
500 (*outval)[*outvallen] = '\0';
502 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
504 return YPERR_SUCCESS;
508 yp_next (const char *indomain, const char *inmap, const char *inkey,
509 const int inkeylen, char **outkey, int *outkeylen, char **outval,
510 int *outvallen)
512 ypreq_key req;
513 ypresp_key_val resp;
514 enum clnt_stat result;
516 if (indomain == NULL || indomain[0] == '\0' ||
517 inmap == NULL || inmap[0] == '\0' ||
518 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
519 return YPERR_BADARGS;
521 req.domain = (char *) indomain;
522 req.map = (char *) inmap;
523 req.key.keydat_val = (char *) inkey;
524 req.key.keydat_len = inkeylen;
526 *outkey = *outval = NULL;
527 *outkeylen = *outvallen = 0;
528 memset (&resp, '\0', sizeof (resp));
530 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
531 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
532 (caddr_t) & resp);
534 if (result != YPERR_SUCCESS)
535 return result;
536 if (resp.stat != YP_TRUE)
537 return ypprot_err (resp.stat);
539 *outkeylen = resp.key.keydat_len;
540 *outkey = malloc (*outkeylen + 1);
541 if (__builtin_expect (*outkey == NULL, 0))
542 return YPERR_RESRC;
543 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
544 (*outkey)[*outkeylen] = '\0';
545 *outvallen = resp.val.valdat_len;
546 *outval = malloc (*outvallen + 1);
547 if (__builtin_expect (*outval == NULL, 0))
548 return YPERR_RESRC;
549 memcpy (*outval, resp.val.valdat_val, *outvallen);
550 (*outval)[*outvallen] = '\0';
552 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
554 return YPERR_SUCCESS;
558 yp_master (const char *indomain, const char *inmap, char **outname)
560 ypreq_nokey req;
561 ypresp_master resp;
562 enum clnt_stat result;
564 if (indomain == NULL || indomain[0] == '\0' ||
565 inmap == NULL || inmap[0] == '\0')
566 return YPERR_BADARGS;
568 req.domain = (char *) indomain;
569 req.map = (char *) inmap;
571 memset (&resp, '\0', sizeof (ypresp_master));
573 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
574 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
576 if (result != YPERR_SUCCESS)
577 return result;
578 if (resp.stat != YP_TRUE)
579 return ypprot_err (resp.stat);
581 *outname = strdup (resp.peer);
582 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
584 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
588 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
590 struct ypreq_nokey req;
591 struct ypresp_order resp;
592 enum clnt_stat result;
594 if (indomain == NULL || indomain[0] == '\0' ||
595 inmap == NULL || inmap == '\0')
596 return YPERR_BADARGS;
598 req.domain = (char *) indomain;
599 req.map = (char *) inmap;
601 memset (&resp, '\0', sizeof (resp));
603 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
604 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
606 if (result != YPERR_SUCCESS)
607 return result;
608 if (resp.stat != YP_TRUE)
609 return ypprot_err (resp.stat);
611 *outorder = resp.ordernum;
612 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
614 return YPERR_SUCCESS;
617 static void *ypall_data;
618 static int (*ypall_foreach) (int status, char *key, int keylen,
619 char *val, int vallen, char *data);
621 static bool_t
622 __xdr_ypresp_all (XDR *xdrs, u_long *objp)
624 while (1)
626 struct ypresp_all resp;
628 memset (&resp, '\0', sizeof (struct ypresp_all));
629 if (!xdr_ypresp_all (xdrs, &resp))
631 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
632 *objp = YP_YPERR;
633 return FALSE;
635 if (resp.more == 0)
637 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
638 *objp = YP_NOMORE;
639 return TRUE;
642 switch (resp.ypresp_all_u.val.stat)
644 case YP_TRUE:
646 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
647 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
648 int keylen = resp.ypresp_all_u.val.key.keydat_len;
649 int vallen = resp.ypresp_all_u.val.val.valdat_len;
651 /* We are not allowed to modify the key and val data.
652 But we are allowed to add data behind the buffer,
653 if we don't modify the length. So add an extra NUL
654 character to avoid trouble with broken code. */
655 *objp = YP_TRUE;
656 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
657 key[keylen] = '\0';
658 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
659 val[vallen] = '\0';
660 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
661 if ((*ypall_foreach) (*objp, key, keylen,
662 val, vallen, ypall_data))
663 return TRUE;
665 break;
666 default:
667 *objp = resp.ypresp_all_u.val.stat;
668 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
669 /* Sun says we don't need to make this call, but must return
670 immediatly. Since Solaris makes this call, we will call
671 the callback function, too. */
672 (*ypall_foreach) (*objp, NULL, 0, NULL, 0, ypall_data);
673 return TRUE;
679 yp_all (const char *indomain, const char *inmap,
680 const struct ypall_callback *incallback)
682 struct ypreq_nokey req;
683 dom_binding *ydb = NULL;
684 int try, res;
685 enum clnt_stat result;
686 struct sockaddr_in clnt_sin;
687 CLIENT *clnt;
688 unsigned long status;
689 int clnt_sock;
690 int saved_errno = errno;
692 if (indomain == NULL || indomain[0] == '\0' ||
693 inmap == NULL || inmap == '\0')
694 return YPERR_BADARGS;
696 try = 0;
697 res = YPERR_YPERR;
699 while (try < MAXTRIES && res != YPERR_SUCCESS)
701 if (__yp_bind (indomain, &ydb) != 0)
703 __set_errno (saved_errno);
704 return YPERR_DOMAIN;
707 /* YPPROC_ALL get its own TCP channel to ypserv. Therefore we
708 close the socket opened by the __yp_bind call. */
709 close (ydb->dom_socket);
710 clnt_sock = RPC_ANYSOCK;
711 clnt_sin = ydb->dom_server_addr;
712 clnt_sin.sin_port = 0;
713 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
714 if (clnt == NULL)
716 __yp_unbind (ydb);
717 __set_errno (saved_errno);
718 return YPERR_PMAP;
720 req.domain = (char *) indomain;
721 req.map = (char *) inmap;
723 ypall_foreach = incallback->foreach;
724 ypall_data = (void *) incallback->data;
726 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
727 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
728 (caddr_t) &status, RPCTIMEOUT);
730 if (result != RPC_SUCCESS)
732 clnt_perror (clnt, "yp_all: clnt_call");
733 res = YPERR_RPC;
735 else
736 res = YPERR_SUCCESS;
738 __yp_unbind (ydb);
739 clnt_destroy (clnt);
741 if (status != YP_NOMORE)
743 __set_errno (saved_errno);
744 return ypprot_err (status);
746 ++try;
749 __set_errno (saved_errno);
751 return res;
755 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
757 struct ypresp_maplist resp;
758 enum clnt_stat result;
760 if (indomain == NULL || indomain[0] == '\0')
761 return YPERR_BADARGS;
763 memset (&resp, '\0', sizeof (resp));
765 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
766 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
768 if (result != YPERR_SUCCESS)
769 return result;
770 if (resp.stat != YP_TRUE)
771 return ypprot_err (resp.stat);
773 *outmaplist = resp.maps;
774 /* We give the list not free, this will be done by ypserv
775 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
777 return YPERR_SUCCESS;
780 const char *
781 yperr_string (const int error)
783 switch (error)
785 case YPERR_SUCCESS:
786 return _("Success");
787 case YPERR_BADARGS:
788 return _("Request arguments bad");
789 case YPERR_RPC:
790 return _("RPC failure on NIS operation");
791 case YPERR_DOMAIN:
792 return _("Can't bind to server which serves this domain");
793 case YPERR_MAP:
794 return _("No such map in server's domain");
795 case YPERR_KEY:
796 return _("No such key in map");
797 case YPERR_YPERR:
798 return _("Internal NIS error");
799 case YPERR_RESRC:
800 return _("Local resource allocation failure");
801 case YPERR_NOMORE:
802 return _("No more records in map database");
803 case YPERR_PMAP:
804 return _("Can't communicate with portmapper");
805 case YPERR_YPBIND:
806 return _("Can't communicate with ypbind");
807 case YPERR_YPSERV:
808 return _("Can't communicate with ypserv");
809 case YPERR_NODOM:
810 return _("Local domain name not set");
811 case YPERR_BADDB:
812 return _("NIS map database is bad");
813 case YPERR_VERS:
814 return _("NIS client/server version mismatch - can't supply service");
815 case YPERR_ACCESS:
816 return _("Permission denied");
817 case YPERR_BUSY:
818 return _("Database is busy");
820 return _("Unknown NIS error code");
824 ypprot_err (const int code)
826 switch (code)
828 case YP_TRUE:
829 return YPERR_SUCCESS;
830 case YP_NOMORE:
831 return YPERR_NOMORE;
832 case YP_FALSE:
833 return YPERR_YPERR;
834 case YP_NOMAP:
835 return YPERR_MAP;
836 case YP_NODOM:
837 return YPERR_DOMAIN;
838 case YP_NOKEY:
839 return YPERR_KEY;
840 case YP_BADOP:
841 return YPERR_YPERR;
842 case YP_BADDB:
843 return YPERR_BADDB;
844 case YP_YPERR:
845 return YPERR_YPERR;
846 case YP_BADARGS:
847 return YPERR_BADARGS;
848 case YP_VERS:
849 return YPERR_VERS;
851 return YPERR_YPERR;
854 const char *
855 ypbinderr_string (const int error)
857 switch (error)
859 case 0:
860 return _("Success");
861 case YPBIND_ERR_ERR:
862 return _("Internal ypbind error");
863 case YPBIND_ERR_NOSERV:
864 return _("Domain not bound");
865 case YPBIND_ERR_RESC:
866 return _("System resource allocation failure");
867 default:
868 return _("Unknown ypbind error");
873 #define WINDOW 60
876 yp_update (char *domain, char *map, unsigned ypop,
877 char *key, int keylen, char *data, int datalen)
879 union
881 ypupdate_args update_args;
882 ypdelete_args delete_args;
884 args;
885 xdrproc_t xdr_argument;
886 unsigned res = 0;
887 CLIENT *clnt;
888 char *master;
889 struct sockaddr saddr;
890 char servername[MAXNETNAMELEN + 1];
891 int r;
893 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
894 return YPERR_BADARGS;
896 args.update_args.mapname = map;
897 args.update_args.key.yp_buf_len = keylen;
898 args.update_args.key.yp_buf_val = key;
899 args.update_args.datum.yp_buf_len = datalen;
900 args.update_args.datum.yp_buf_val = data;
902 if ((r = yp_master (domain, map, &master)) != 0)
903 return r;
905 if (!host2netname (servername, master, domain))
907 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
908 return YPERR_YPERR;
911 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
913 clnt_pcreateerror ("yp_update: clnt_create");
914 return YPERR_RPC;
917 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
919 fputs (_("yp_update: cannot get server address\n"), stderr);
920 return YPERR_RPC;
923 switch (ypop)
925 case YPOP_CHANGE:
926 case YPOP_INSERT:
927 case YPOP_STORE:
928 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
929 break;
930 case YPOP_DELETE:
931 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
932 break;
933 default:
934 return YPERR_BADARGS;
935 break;
938 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
940 if (clnt->cl_auth == NULL)
941 clnt->cl_auth = authunix_create_default ();
943 again:
944 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
945 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
947 if (r == RPC_AUTHERROR)
949 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
951 clnt->cl_auth = authunix_create_default ();
952 goto again;
954 else
955 return YPERR_ACCESS;
957 if (r != RPC_SUCCESS)
959 clnt_perror (clnt, "yp_update: clnt_call");
960 return YPERR_RPC;
962 return res;