(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / nis / ypclnt.c
blob85292b62d9acf853c9b15cf1d81267c9b3687bfa
1 /* Copyright (C) 1996-2001, 2002, 2003, 2004 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 Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 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 void
57 yp_bind_client_create (const char *domain, dom_binding *ysd,
58 struct ypbind_resp *ypbr)
60 ysd->dom_server_addr.sin_family = AF_INET;
61 memcpy (&ysd->dom_server_addr.sin_port,
62 ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
63 sizeof (ysd->dom_server_addr.sin_port));
64 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
65 ypbr->ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
66 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
67 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
68 ysd->dom_domain[YPMAXDOMAIN] = '\0';
70 ysd->dom_socket = RPC_ANYSOCK;
71 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
72 UDPTIMEOUT, &ysd->dom_socket);
74 if (ysd->dom_client != NULL)
76 /* If the program exits, close the socket */
77 if (fcntl (ysd->dom_socket, F_SETFD, FD_CLOEXEC) == -1)
78 perror ("fcntl: F_SETFD");
82 #if USE_BINDINGDIR
83 static void
84 yp_bind_file (const char *domain, dom_binding *ysd)
86 char path[sizeof (BINDINGDIR) + strlen (domain) + 3 * sizeof (unsigned) + 3];
88 snprintf (path, sizeof (path), "%s/%s.%u", BINDINGDIR, domain, YPBINDVERS);
89 int fd = open (path, O_RDONLY);
90 if (fd >= 0)
92 /* We have a binding file and could save a RPC call. The file
93 contains a port number and the YPBIND_RESP record. The port
94 number (16 bits) can be ignored. */
95 struct ypbind_resp ypbr;
97 if (pread (fd, &ypbr, sizeof (ypbr), 2) == sizeof (ypbr))
98 yp_bind_client_create (domain, ysd, &ypbr);
100 close (fd);
103 #endif
105 static int
106 yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
108 struct sockaddr_in clnt_saddr;
109 struct ypbind_resp ypbr;
110 int clnt_sock;
111 CLIENT *client;
113 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
114 clnt_saddr.sin_family = AF_INET;
115 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
116 clnt_sock = RPC_ANYSOCK;
117 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
118 &clnt_sock, 0, 0);
119 if (client == NULL)
120 return YPERR_YPBIND;
122 /* Check the port number -- should be < IPPORT_RESERVED.
123 If not, it's possible someone has registered a bogus
124 ypbind with the portmapper and is trying to trick us. */
125 if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
127 clnt_destroy (client);
128 return YPERR_YPBIND;
131 if (clnt_call (client, YPBINDPROC_DOMAIN,
132 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
133 (xdrproc_t) xdr_ypbind_resp,
134 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
136 clnt_destroy (client);
137 return YPERR_YPBIND;
140 clnt_destroy (client);
142 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
144 fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
145 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
146 return YPERR_DOMAIN;
148 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
150 yp_bind_client_create (domain, ysd, &ypbr);
152 return YPERR_SUCCESS;
155 static int
156 __yp_bind (const char *domain, dom_binding **ypdb)
158 dom_binding *ysd = NULL;
159 int is_new = 0;
161 if (domain == NULL || domain[0] == '\0')
162 return YPERR_BADARGS;
164 ysd = *ypdb;
165 while (ysd != NULL)
167 if (strcmp (domain, ysd->dom_domain) == 0)
168 break;
169 ysd = ysd->dom_pnext;
172 if (ysd == NULL)
174 is_new = 1;
175 ysd = (dom_binding *) calloc (1, sizeof *ysd);
176 if (__builtin_expect (ysd == NULL, 0))
177 return YPERR_RESRC;
180 #if USE_BINDINGDIR
181 /* Try binding dir at first if we have no binding */
182 if (ysd->dom_client == NULL)
183 yp_bind_file (domain, ysd);
184 #endif /* USE_BINDINGDIR */
186 if (ysd->dom_client == NULL)
188 int retval = yp_bind_ypbindprog (domain, ysd);
189 if (retval != YPERR_SUCCESS)
191 if (is_new)
192 free (ysd);
193 return retval;
197 if (ysd->dom_client == NULL)
199 if (is_new)
200 free (ysd);
201 return YPERR_YPSERV;
204 if (is_new)
206 ysd->dom_pnext = *ypdb;
207 *ypdb = ysd;
210 return YPERR_SUCCESS;
213 static void
214 __yp_unbind (dom_binding *ydb)
216 clnt_destroy (ydb->dom_client);
217 free (ydb);
221 yp_bind (const char *indomain)
223 int status;
225 __libc_lock_lock (ypbindlist_lock);
227 status = __yp_bind (indomain, &__ypbindlist);
229 __libc_lock_unlock (ypbindlist_lock);
231 return status;
233 libnsl_hidden_def (yp_bind)
235 static void
236 yp_unbind_locked (const char *indomain)
238 dom_binding *ydbptr, *ydbptr2;
240 ydbptr2 = NULL;
241 ydbptr = __ypbindlist;
243 while (ydbptr != NULL)
245 if (strcmp (ydbptr->dom_domain, indomain) == 0)
247 dom_binding *work;
249 work = ydbptr;
250 if (ydbptr2 == NULL)
251 __ypbindlist = __ypbindlist->dom_pnext;
252 else
253 ydbptr2 = ydbptr->dom_pnext;
254 __yp_unbind (work);
255 break;
257 ydbptr2 = ydbptr;
258 ydbptr = ydbptr->dom_pnext;
262 void
263 yp_unbind (const char *indomain)
265 __libc_lock_lock (ypbindlist_lock);
267 yp_unbind_locked (indomain);
269 __libc_lock_unlock (ypbindlist_lock);
271 return;
274 static int
275 __ypclnt_call (const char *domain, u_long prog, xdrproc_t xargs,
276 caddr_t req, xdrproc_t xres, caddr_t resp, dom_binding **ydb,
277 int print_error)
279 enum clnt_stat result;
281 result = clnt_call ((*ydb)->dom_client, prog,
282 xargs, req, xres, resp, RPCTIMEOUT);
284 if (result != RPC_SUCCESS)
286 /* We don't print an error message, if we try our old,
287 cached data. Only print this for data, which should work. */
288 if (print_error)
289 clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
291 return YPERR_RPC;
294 return YPERR_SUCCESS;
297 static int
298 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
299 caddr_t req, xdrproc_t xres, caddr_t resp)
301 dom_binding *ydb;
302 int status;
303 int saved_errno = errno;
305 status = YPERR_YPERR;
307 __libc_lock_lock (ypbindlist_lock);
308 ydb = __ypbindlist;
309 while (ydb != NULL)
311 if (strcmp (domain, ydb->dom_domain) == 0)
313 if (__yp_bind (domain, &ydb) == 0)
315 /* Call server, print no error message, do not unbind. */
316 status = __ypclnt_call (domain, prog, xargs, req, xres,
317 resp, &ydb, 0);
318 if (status == YPERR_SUCCESS)
320 __libc_lock_unlock (ypbindlist_lock);
321 __set_errno (saved_errno);
322 return status;
325 /* We use ypbindlist, and the old cached data is
326 invalid. unbind now and create a new binding */
327 yp_unbind_locked (domain);
329 break;
331 ydb = ydb->dom_pnext;
333 __libc_lock_unlock (ypbindlist_lock);
335 /* First try with cached data failed. Now try to get
336 current data from the system. */
337 ydb = NULL;
338 if (__yp_bind (domain, &ydb) == 0)
340 status = __ypclnt_call (domain, prog, xargs, req, xres,
341 resp, &ydb, 1);
342 __yp_unbind (ydb);
345 #if USE_BINDINGDIR
346 /* If we support binding dir data, we have a third chance:
347 Ask ypbind. */
348 if (status != YPERR_SUCCESS)
350 ydb = calloc (1, sizeof (dom_binding));
351 if (yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
353 status = __ypclnt_call (domain, prog, xargs, req, xres,
354 resp, &ydb, 1);
355 __yp_unbind (ydb);
357 else
358 free (ydb);
360 #endif
362 __set_errno (saved_errno);
364 return status;
368 __libc_lock_define_initialized (static, domainname_lock)
371 yp_get_default_domain (char **outdomain)
373 int result = YPERR_SUCCESS;;
374 *outdomain = NULL;
376 __libc_lock_lock (domainname_lock);
378 if (__ypdomainname[0] == '\0')
380 if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
381 result = YPERR_NODOM;
382 else if (strcmp (__ypdomainname, "(none)") == 0)
384 /* If domainname is not set, some systems will return "(none)" */
385 __ypdomainname[0] = '\0';
386 result = YPERR_NODOM;
388 else
389 *outdomain = __ypdomainname;
391 else
392 *outdomain = __ypdomainname;
394 __libc_lock_unlock (domainname_lock);
396 return result;
398 libnsl_hidden_def (yp_get_default_domain)
401 __yp_check (char **domain)
403 char *unused;
405 if (__ypdomainname[0] == '\0')
406 if (yp_get_default_domain (&unused))
407 return 0;
409 if (domain)
410 *domain = __ypdomainname;
412 if (yp_bind (__ypdomainname) == 0)
413 return 1;
414 return 0;
418 yp_match (const char *indomain, const char *inmap, const char *inkey,
419 const int inkeylen, char **outval, int *outvallen)
421 ypreq_key req;
422 ypresp_val resp;
423 enum clnt_stat result;
425 if (indomain == NULL || indomain[0] == '\0' ||
426 inmap == NULL || inmap[0] == '\0' ||
427 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
428 return YPERR_BADARGS;
430 req.domain = (char *) indomain;
431 req.map = (char *) inmap;
432 req.key.keydat_val = (char *) inkey;
433 req.key.keydat_len = inkeylen;
435 *outval = NULL;
436 *outvallen = 0;
437 memset (&resp, '\0', sizeof (resp));
439 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
440 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
441 (caddr_t) & resp);
443 if (result != YPERR_SUCCESS)
444 return result;
445 if (resp.stat != YP_TRUE)
446 return ypprot_err (resp.stat);
448 *outvallen = resp.val.valdat_len;
449 *outval = malloc (*outvallen + 1);
450 if (__builtin_expect (*outval == NULL, 0))
451 return YPERR_RESRC;
452 memcpy (*outval, resp.val.valdat_val, *outvallen);
453 (*outval)[*outvallen] = '\0';
455 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
457 return YPERR_SUCCESS;
461 yp_first (const char *indomain, const char *inmap, char **outkey,
462 int *outkeylen, char **outval, int *outvallen)
464 ypreq_nokey req;
465 ypresp_key_val resp;
466 enum clnt_stat result;
468 if (indomain == NULL || indomain[0] == '\0' ||
469 inmap == NULL || inmap[0] == '\0')
470 return YPERR_BADARGS;
472 req.domain = (char *) indomain;
473 req.map = (char *) inmap;
475 *outkey = *outval = NULL;
476 *outkeylen = *outvallen = 0;
477 memset (&resp, '\0', sizeof (resp));
479 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
480 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
481 (caddr_t) & resp);
483 if (result != RPC_SUCCESS)
484 return YPERR_RPC;
485 if (resp.stat != YP_TRUE)
486 return ypprot_err (resp.stat);
488 *outkeylen = resp.key.keydat_len;
489 *outkey = malloc (*outkeylen + 1);
490 if (__builtin_expect (*outkey == NULL, 0))
491 return YPERR_RESRC;
492 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
493 (*outkey)[*outkeylen] = '\0';
494 *outvallen = resp.val.valdat_len;
495 *outval = malloc (*outvallen + 1);
496 if (__builtin_expect (*outval == NULL, 0))
497 return YPERR_RESRC;
498 memcpy (*outval, resp.val.valdat_val, *outvallen);
499 (*outval)[*outvallen] = '\0';
501 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
503 return YPERR_SUCCESS;
507 yp_next (const char *indomain, const char *inmap, const char *inkey,
508 const int inkeylen, char **outkey, int *outkeylen, char **outval,
509 int *outvallen)
511 ypreq_key req;
512 ypresp_key_val resp;
513 enum clnt_stat result;
515 if (indomain == NULL || indomain[0] == '\0' ||
516 inmap == NULL || inmap[0] == '\0' ||
517 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
518 return YPERR_BADARGS;
520 req.domain = (char *) indomain;
521 req.map = (char *) inmap;
522 req.key.keydat_val = (char *) inkey;
523 req.key.keydat_len = inkeylen;
525 *outkey = *outval = NULL;
526 *outkeylen = *outvallen = 0;
527 memset (&resp, '\0', sizeof (resp));
529 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
530 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
531 (caddr_t) & resp);
533 if (result != YPERR_SUCCESS)
534 return result;
535 if (resp.stat != YP_TRUE)
536 return ypprot_err (resp.stat);
538 *outkeylen = resp.key.keydat_len;
539 *outkey = malloc (*outkeylen + 1);
540 if (__builtin_expect (*outkey == NULL, 0))
541 return YPERR_RESRC;
542 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
543 (*outkey)[*outkeylen] = '\0';
544 *outvallen = resp.val.valdat_len;
545 *outval = malloc (*outvallen + 1);
546 if (__builtin_expect (*outval == NULL, 0))
547 return YPERR_RESRC;
548 memcpy (*outval, resp.val.valdat_val, *outvallen);
549 (*outval)[*outvallen] = '\0';
551 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
553 return YPERR_SUCCESS;
557 yp_master (const char *indomain, const char *inmap, char **outname)
559 ypreq_nokey req;
560 ypresp_master resp;
561 enum clnt_stat result;
563 if (indomain == NULL || indomain[0] == '\0' ||
564 inmap == NULL || inmap[0] == '\0')
565 return YPERR_BADARGS;
567 req.domain = (char *) indomain;
568 req.map = (char *) inmap;
570 memset (&resp, '\0', sizeof (ypresp_master));
572 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
573 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
575 if (result != YPERR_SUCCESS)
576 return result;
577 if (resp.stat != YP_TRUE)
578 return ypprot_err (resp.stat);
580 *outname = strdup (resp.peer);
581 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
583 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
585 libnsl_hidden_def (yp_master)
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 struct ypresp_all_data
619 unsigned long status;
620 void *data;
621 int (*foreach) (int status, char *key, int keylen,
622 char *val, int vallen, char *data);
625 static bool_t
626 __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
628 while (1)
630 struct ypresp_all resp;
632 memset (&resp, '\0', sizeof (struct ypresp_all));
633 if (!xdr_ypresp_all (xdrs, &resp))
635 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
636 objp->status = YP_YPERR;
637 return FALSE;
639 if (resp.more == 0)
641 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
642 objp->status = YP_NOMORE;
643 return TRUE;
646 switch (resp.ypresp_all_u.val.stat)
648 case YP_TRUE:
650 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
651 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
652 int keylen = resp.ypresp_all_u.val.key.keydat_len;
653 int vallen = resp.ypresp_all_u.val.val.valdat_len;
655 /* We are not allowed to modify the key and val data.
656 But we are allowed to add data behind the buffer,
657 if we don't modify the length. So add an extra NUL
658 character to avoid trouble with broken code. */
659 objp->status = YP_TRUE;
660 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
661 key[keylen] = '\0';
662 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
663 val[vallen] = '\0';
664 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
665 if ((*objp->foreach) (objp->status, key, keylen,
666 val, vallen, objp->data))
667 return TRUE;
669 break;
670 default:
671 objp->status = resp.ypresp_all_u.val.stat;
672 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
673 /* Sun says we don't need to make this call, but must return
674 immediatly. Since Solaris makes this call, we will call
675 the callback function, too. */
676 (*objp->foreach) (objp->status, NULL, 0, NULL, 0, objp->data);
677 return TRUE;
683 yp_all (const char *indomain, const char *inmap,
684 const struct ypall_callback *incallback)
686 struct ypreq_nokey req;
687 dom_binding *ydb = NULL;
688 int try, res;
689 enum clnt_stat result;
690 struct sockaddr_in clnt_sin;
691 CLIENT *clnt;
692 struct ypresp_all_data data;
693 int clnt_sock;
694 int saved_errno = errno;
696 if (indomain == NULL || indomain[0] == '\0' ||
697 inmap == NULL || inmap == '\0')
698 return YPERR_BADARGS;
700 try = 0;
701 res = YPERR_YPERR;
703 while (try < MAXTRIES && res != YPERR_SUCCESS)
705 if (__yp_bind (indomain, &ydb) != 0)
707 __set_errno (saved_errno);
708 return YPERR_DOMAIN;
711 clnt_sock = RPC_ANYSOCK;
712 clnt_sin = ydb->dom_server_addr;
713 clnt_sin.sin_port = 0;
715 /* We don't need the UDP connection anymore. */
716 __yp_unbind (ydb);
717 ydb = NULL;
719 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
720 if (clnt == NULL)
722 __set_errno (saved_errno);
723 return YPERR_PMAP;
725 req.domain = (char *) indomain;
726 req.map = (char *) inmap;
728 data.foreach = incallback->foreach;
729 data.data = (void *) incallback->data;
731 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
732 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
733 (caddr_t) &data, RPCTIMEOUT);
735 if (result != RPC_SUCCESS)
737 /* Print the error message only on the last try */
738 if (try == MAXTRIES - 1)
739 clnt_perror (clnt, "yp_all: clnt_call");
740 res = YPERR_RPC;
742 else
743 res = YPERR_SUCCESS;
745 clnt_destroy (clnt);
747 if (res == YPERR_SUCCESS && data.status != YP_NOMORE)
749 __set_errno (saved_errno);
750 return ypprot_err (data.status);
752 ++try;
755 __set_errno (saved_errno);
757 return res;
761 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
763 struct ypresp_maplist resp;
764 enum clnt_stat result;
766 if (indomain == NULL || indomain[0] == '\0')
767 return YPERR_BADARGS;
769 memset (&resp, '\0', sizeof (resp));
771 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
772 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
774 if (result != YPERR_SUCCESS)
775 return result;
776 if (resp.stat != YP_TRUE)
777 return ypprot_err (resp.stat);
779 *outmaplist = resp.maps;
780 /* We give the list not free, this will be done by ypserv
781 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
783 return YPERR_SUCCESS;
786 const char *
787 yperr_string (const int error)
789 switch (error)
791 case YPERR_SUCCESS:
792 return _("Success");
793 case YPERR_BADARGS:
794 return _("Request arguments bad");
795 case YPERR_RPC:
796 return _("RPC failure on NIS operation");
797 case YPERR_DOMAIN:
798 return _("Can't bind to server which serves this domain");
799 case YPERR_MAP:
800 return _("No such map in server's domain");
801 case YPERR_KEY:
802 return _("No such key in map");
803 case YPERR_YPERR:
804 return _("Internal NIS error");
805 case YPERR_RESRC:
806 return _("Local resource allocation failure");
807 case YPERR_NOMORE:
808 return _("No more records in map database");
809 case YPERR_PMAP:
810 return _("Can't communicate with portmapper");
811 case YPERR_YPBIND:
812 return _("Can't communicate with ypbind");
813 case YPERR_YPSERV:
814 return _("Can't communicate with ypserv");
815 case YPERR_NODOM:
816 return _("Local domain name not set");
817 case YPERR_BADDB:
818 return _("NIS map database is bad");
819 case YPERR_VERS:
820 return _("NIS client/server version mismatch - can't supply service");
821 case YPERR_ACCESS:
822 return _("Permission denied");
823 case YPERR_BUSY:
824 return _("Database is busy");
826 return _("Unknown NIS error code");
829 static const int8_t yp_2_yperr[] =
831 #define YP2YPERR(yp, yperr) [YP_##yp - YP_VERS] = YPERR_##yperr
832 YP2YPERR (NOKEY, KEY),
833 YP2YPERR (BADOP, YPERR),
834 YP2YPERR (BADDB, BADDB),
835 YP2YPERR (YPERR, YPERR),
836 YP2YPERR (BADARGS, BADARGS),
837 YP2YPERR (VERS, VERS)
840 ypprot_err (const int code)
842 if (code < YP_VERS || code > YP_NOKEY)
843 return YPERR_YPERR;
844 return yp_2_yperr[code - YP_VERS];
846 libnsl_hidden_def (ypprot_err)
848 const char *
849 ypbinderr_string (const int error)
851 switch (error)
853 case 0:
854 return _("Success");
855 case YPBIND_ERR_ERR:
856 return _("Internal ypbind error");
857 case YPBIND_ERR_NOSERV:
858 return _("Domain not bound");
859 case YPBIND_ERR_RESC:
860 return _("System resource allocation failure");
861 default:
862 return _("Unknown ypbind error");
865 libnsl_hidden_def (ypbinderr_string)
867 #define WINDOW 60
870 yp_update (char *domain, char *map, unsigned ypop,
871 char *key, int keylen, char *data, int datalen)
873 union
875 ypupdate_args update_args;
876 ypdelete_args delete_args;
878 args;
879 xdrproc_t xdr_argument;
880 unsigned res = 0;
881 CLIENT *clnt;
882 char *master;
883 struct sockaddr saddr;
884 char servername[MAXNETNAMELEN + 1];
885 int r;
887 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
888 return YPERR_BADARGS;
890 args.update_args.mapname = map;
891 args.update_args.key.yp_buf_len = keylen;
892 args.update_args.key.yp_buf_val = key;
893 args.update_args.datum.yp_buf_len = datalen;
894 args.update_args.datum.yp_buf_val = data;
896 if ((r = yp_master (domain, map, &master)) != 0)
897 return r;
899 if (!host2netname (servername, master, domain))
901 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
902 return YPERR_YPERR;
905 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
907 clnt_pcreateerror ("yp_update: clnt_create");
908 return YPERR_RPC;
911 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
913 fputs (_("yp_update: cannot get server address\n"), stderr);
914 return YPERR_RPC;
917 switch (ypop)
919 case YPOP_CHANGE:
920 case YPOP_INSERT:
921 case YPOP_STORE:
922 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
923 break;
924 case YPOP_DELETE:
925 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
926 break;
927 default:
928 return YPERR_BADARGS;
929 break;
932 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
934 if (clnt->cl_auth == NULL)
935 clnt->cl_auth = authunix_create_default ();
937 again:
938 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
939 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
941 if (r == RPC_AUTHERROR)
943 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
945 clnt->cl_auth = authunix_create_default ();
946 goto again;
948 else
949 return YPERR_ACCESS;
951 if (r != RPC_SUCCESS)
953 clnt_perror (clnt, "yp_update: clnt_call");
954 return YPERR_RPC;
956 return res;