Update.
[glibc.git] / nis / ypclnt.c
blobf25c7c710bc2a3ae16cebfa1ee68aa21c7e1421e
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;
234 static void
235 yp_unbind_locked (const char *indomain)
237 dom_binding *ydbptr, *ydbptr2;
239 ydbptr2 = NULL;
240 ydbptr = __ypbindlist;
242 while (ydbptr != NULL)
244 if (strcmp (ydbptr->dom_domain, indomain) == 0)
246 dom_binding *work;
248 work = ydbptr;
249 if (ydbptr2 == NULL)
250 __ypbindlist = __ypbindlist->dom_pnext;
251 else
252 ydbptr2 = ydbptr->dom_pnext;
253 __yp_unbind (work);
254 break;
256 ydbptr2 = ydbptr;
257 ydbptr = ydbptr->dom_pnext;
261 void
262 yp_unbind (const char *indomain)
264 __libc_lock_lock (ypbindlist_lock);
266 yp_unbind_locked (indomain);
268 __libc_lock_unlock (ypbindlist_lock);
270 return;
273 static int
274 __ypclnt_call (const char *domain, u_long prog, xdrproc_t xargs,
275 caddr_t req, xdrproc_t xres, caddr_t resp, dom_binding **ydb,
276 int print_error)
278 enum clnt_stat result;
280 result = clnt_call ((*ydb)->dom_client, prog,
281 xargs, req, xres, resp, RPCTIMEOUT);
283 if (result != RPC_SUCCESS)
285 /* We don't print an error message, if we try our old,
286 cached data. Only print this for data, which should work. */
287 if (print_error)
288 clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
290 return YPERR_RPC;
293 return YPERR_SUCCESS;
296 static int
297 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
298 caddr_t req, xdrproc_t xres, caddr_t resp)
300 dom_binding *ydb;
301 int status;
302 int saved_errno = errno;
304 status = YPERR_YPERR;
306 __libc_lock_lock (ypbindlist_lock);
307 ydb = __ypbindlist;
308 while (ydb != NULL)
310 if (strcmp (domain, ydb->dom_domain) == 0)
312 if (__yp_bind (domain, &ydb) == 0)
314 /* Call server, print no error message, do not unbind. */
315 status = __ypclnt_call (domain, prog, xargs, req, xres,
316 resp, &ydb, 0);
317 if (status == YPERR_SUCCESS)
319 __libc_lock_unlock (ypbindlist_lock);
320 __set_errno (saved_errno);
321 return status;
324 /* We use ypbindlist, and the old cached data is
325 invalid. unbind now and create a new binding */
326 yp_unbind_locked (domain);
328 break;
330 ydb = ydb->dom_pnext;
332 __libc_lock_unlock (ypbindlist_lock);
334 /* First try with cached data failed. Now try to get
335 current data from the system. */
336 ydb = NULL;
337 if (__yp_bind (domain, &ydb) == 0)
339 status = __ypclnt_call (domain, prog, xargs, req, xres,
340 resp, &ydb, 1);
341 __yp_unbind (ydb);
344 #if USE_BINDINGDIR
345 /* If we support binding dir data, we have a third chance:
346 Ask ypbind. */
347 if (status != YPERR_SUCCESS)
349 ydb = calloc (1, sizeof (dom_binding));
350 if (yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
352 status = __ypclnt_call (domain, prog, xargs, req, xres,
353 resp, &ydb, 1);
354 __yp_unbind (ydb);
356 else
357 free (ydb);
359 #endif
361 __set_errno (saved_errno);
363 return status;
367 __libc_lock_define_initialized (static, domainname_lock)
370 yp_get_default_domain (char **outdomain)
372 int result = YPERR_SUCCESS;;
373 *outdomain = NULL;
375 __libc_lock_lock (domainname_lock);
377 if (__ypdomainname[0] == '\0')
379 if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
380 result = YPERR_NODOM;
381 else if (strcmp (__ypdomainname, "(none)") == 0)
383 /* If domainname is not set, some systems will return "(none)" */
384 __ypdomainname[0] = '\0';
385 result = YPERR_NODOM;
387 else
388 *outdomain = __ypdomainname;
390 else
391 *outdomain = __ypdomainname;
393 __libc_lock_unlock (domainname_lock);
395 return result;
399 __yp_check (char **domain)
401 char *unused;
403 if (__ypdomainname[0] == '\0')
404 if (yp_get_default_domain (&unused))
405 return 0;
407 if (domain)
408 *domain = __ypdomainname;
410 if (yp_bind (__ypdomainname) == 0)
411 return 1;
412 return 0;
416 yp_match (const char *indomain, const char *inmap, const char *inkey,
417 const int inkeylen, char **outval, int *outvallen)
419 ypreq_key req;
420 ypresp_val resp;
421 enum clnt_stat result;
423 if (indomain == NULL || indomain[0] == '\0' ||
424 inmap == NULL || inmap[0] == '\0' ||
425 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
426 return YPERR_BADARGS;
428 req.domain = (char *) indomain;
429 req.map = (char *) inmap;
430 req.key.keydat_val = (char *) inkey;
431 req.key.keydat_len = inkeylen;
433 *outval = NULL;
434 *outvallen = 0;
435 memset (&resp, '\0', sizeof (resp));
437 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
438 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
439 (caddr_t) & resp);
441 if (result != YPERR_SUCCESS)
442 return result;
443 if (resp.stat != YP_TRUE)
444 return ypprot_err (resp.stat);
446 *outvallen = resp.val.valdat_len;
447 *outval = malloc (*outvallen + 1);
448 if (__builtin_expect (*outval == NULL, 0))
449 return YPERR_RESRC;
450 memcpy (*outval, resp.val.valdat_val, *outvallen);
451 (*outval)[*outvallen] = '\0';
453 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
455 return YPERR_SUCCESS;
459 yp_first (const char *indomain, const char *inmap, char **outkey,
460 int *outkeylen, char **outval, int *outvallen)
462 ypreq_nokey req;
463 ypresp_key_val resp;
464 enum clnt_stat result;
466 if (indomain == NULL || indomain[0] == '\0' ||
467 inmap == NULL || inmap[0] == '\0')
468 return YPERR_BADARGS;
470 req.domain = (char *) indomain;
471 req.map = (char *) inmap;
473 *outkey = *outval = NULL;
474 *outkeylen = *outvallen = 0;
475 memset (&resp, '\0', sizeof (resp));
477 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
478 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
479 (caddr_t) & resp);
481 if (result != RPC_SUCCESS)
482 return YPERR_RPC;
483 if (resp.stat != YP_TRUE)
484 return ypprot_err (resp.stat);
486 *outkeylen = resp.key.keydat_len;
487 *outkey = malloc (*outkeylen + 1);
488 if (__builtin_expect (*outkey == NULL, 0))
489 return YPERR_RESRC;
490 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
491 (*outkey)[*outkeylen] = '\0';
492 *outvallen = resp.val.valdat_len;
493 *outval = malloc (*outvallen + 1);
494 if (__builtin_expect (*outval == NULL, 0))
495 return YPERR_RESRC;
496 memcpy (*outval, resp.val.valdat_val, *outvallen);
497 (*outval)[*outvallen] = '\0';
499 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
501 return YPERR_SUCCESS;
505 yp_next (const char *indomain, const char *inmap, const char *inkey,
506 const int inkeylen, char **outkey, int *outkeylen, char **outval,
507 int *outvallen)
509 ypreq_key req;
510 ypresp_key_val resp;
511 enum clnt_stat result;
513 if (indomain == NULL || indomain[0] == '\0' ||
514 inmap == NULL || inmap[0] == '\0' ||
515 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
516 return YPERR_BADARGS;
518 req.domain = (char *) indomain;
519 req.map = (char *) inmap;
520 req.key.keydat_val = (char *) inkey;
521 req.key.keydat_len = inkeylen;
523 *outkey = *outval = NULL;
524 *outkeylen = *outvallen = 0;
525 memset (&resp, '\0', sizeof (resp));
527 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
528 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
529 (caddr_t) & resp);
531 if (result != YPERR_SUCCESS)
532 return result;
533 if (resp.stat != YP_TRUE)
534 return ypprot_err (resp.stat);
536 *outkeylen = resp.key.keydat_len;
537 *outkey = malloc (*outkeylen + 1);
538 if (__builtin_expect (*outkey == NULL, 0))
539 return YPERR_RESRC;
540 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
541 (*outkey)[*outkeylen] = '\0';
542 *outvallen = resp.val.valdat_len;
543 *outval = malloc (*outvallen + 1);
544 if (__builtin_expect (*outval == NULL, 0))
545 return YPERR_RESRC;
546 memcpy (*outval, resp.val.valdat_val, *outvallen);
547 (*outval)[*outvallen] = '\0';
549 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
551 return YPERR_SUCCESS;
555 yp_master (const char *indomain, const char *inmap, char **outname)
557 ypreq_nokey req;
558 ypresp_master resp;
559 enum clnt_stat result;
561 if (indomain == NULL || indomain[0] == '\0' ||
562 inmap == NULL || inmap[0] == '\0')
563 return YPERR_BADARGS;
565 req.domain = (char *) indomain;
566 req.map = (char *) inmap;
568 memset (&resp, '\0', sizeof (ypresp_master));
570 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
571 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
573 if (result != YPERR_SUCCESS)
574 return result;
575 if (resp.stat != YP_TRUE)
576 return ypprot_err (resp.stat);
578 *outname = strdup (resp.peer);
579 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
581 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
585 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
587 struct ypreq_nokey req;
588 struct ypresp_order resp;
589 enum clnt_stat result;
591 if (indomain == NULL || indomain[0] == '\0' ||
592 inmap == NULL || inmap == '\0')
593 return YPERR_BADARGS;
595 req.domain = (char *) indomain;
596 req.map = (char *) inmap;
598 memset (&resp, '\0', sizeof (resp));
600 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
601 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
603 if (result != YPERR_SUCCESS)
604 return result;
605 if (resp.stat != YP_TRUE)
606 return ypprot_err (resp.stat);
608 *outorder = resp.ordernum;
609 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
611 return YPERR_SUCCESS;
614 struct ypresp_all_data
616 unsigned long status;
617 void *data;
618 int (*foreach) (int status, char *key, int keylen,
619 char *val, int vallen, char *data);
622 static bool_t
623 __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
625 while (1)
627 struct ypresp_all resp;
629 memset (&resp, '\0', sizeof (struct ypresp_all));
630 if (!xdr_ypresp_all (xdrs, &resp))
632 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
633 objp->status = YP_YPERR;
634 return FALSE;
636 if (resp.more == 0)
638 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
639 objp->status = YP_NOMORE;
640 return TRUE;
643 switch (resp.ypresp_all_u.val.stat)
645 case YP_TRUE:
647 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
648 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
649 int keylen = resp.ypresp_all_u.val.key.keydat_len;
650 int vallen = resp.ypresp_all_u.val.val.valdat_len;
652 /* We are not allowed to modify the key and val data.
653 But we are allowed to add data behind the buffer,
654 if we don't modify the length. So add an extra NUL
655 character to avoid trouble with broken code. */
656 objp->status = YP_TRUE;
657 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
658 key[keylen] = '\0';
659 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
660 val[vallen] = '\0';
661 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
662 if ((*objp->foreach) (objp->status, key, keylen,
663 val, vallen, objp->data))
664 return TRUE;
666 break;
667 default:
668 objp->status = resp.ypresp_all_u.val.stat;
669 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
670 /* Sun says we don't need to make this call, but must return
671 immediatly. Since Solaris makes this call, we will call
672 the callback function, too. */
673 (*objp->foreach) (objp->status, NULL, 0, NULL, 0, objp->data);
674 return TRUE;
680 yp_all (const char *indomain, const char *inmap,
681 const struct ypall_callback *incallback)
683 struct ypreq_nokey req;
684 dom_binding *ydb = NULL;
685 int try, res;
686 enum clnt_stat result;
687 struct sockaddr_in clnt_sin;
688 CLIENT *clnt;
689 struct ypresp_all_data data;
690 int clnt_sock;
691 int saved_errno = errno;
693 if (indomain == NULL || indomain[0] == '\0' ||
694 inmap == NULL || inmap == '\0')
695 return YPERR_BADARGS;
697 try = 0;
698 res = YPERR_YPERR;
700 while (try < MAXTRIES && res != YPERR_SUCCESS)
702 if (__yp_bind (indomain, &ydb) != 0)
704 __set_errno (saved_errno);
705 return YPERR_DOMAIN;
708 clnt_sock = RPC_ANYSOCK;
709 clnt_sin = ydb->dom_server_addr;
710 clnt_sin.sin_port = 0;
712 /* We don't need the UDP connection anymore. */
713 __yp_unbind (ydb);
714 ydb = NULL;
716 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
717 if (clnt == NULL)
719 __set_errno (saved_errno);
720 return YPERR_PMAP;
722 req.domain = (char *) indomain;
723 req.map = (char *) inmap;
725 data.foreach = incallback->foreach;
726 data.data = (void *) incallback->data;
728 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
729 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
730 (caddr_t) &data, RPCTIMEOUT);
732 if (result != RPC_SUCCESS)
734 /* Print the error message only on the last try */
735 if (try == MAXTRIES - 1)
736 clnt_perror (clnt, "yp_all: clnt_call");
737 res = YPERR_RPC;
739 else
740 res = YPERR_SUCCESS;
742 clnt_destroy (clnt);
744 if (res == YPERR_SUCCESS && data.status != YP_NOMORE)
746 __set_errno (saved_errno);
747 return ypprot_err (data.status);
749 ++try;
752 __set_errno (saved_errno);
754 return res;
758 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
760 struct ypresp_maplist resp;
761 enum clnt_stat result;
763 if (indomain == NULL || indomain[0] == '\0')
764 return YPERR_BADARGS;
766 memset (&resp, '\0', sizeof (resp));
768 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
769 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
771 if (result != YPERR_SUCCESS)
772 return result;
773 if (resp.stat != YP_TRUE)
774 return ypprot_err (resp.stat);
776 *outmaplist = resp.maps;
777 /* We give the list not free, this will be done by ypserv
778 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
780 return YPERR_SUCCESS;
783 const char *
784 yperr_string (const int error)
786 switch (error)
788 case YPERR_SUCCESS:
789 return _("Success");
790 case YPERR_BADARGS:
791 return _("Request arguments bad");
792 case YPERR_RPC:
793 return _("RPC failure on NIS operation");
794 case YPERR_DOMAIN:
795 return _("Can't bind to server which serves this domain");
796 case YPERR_MAP:
797 return _("No such map in server's domain");
798 case YPERR_KEY:
799 return _("No such key in map");
800 case YPERR_YPERR:
801 return _("Internal NIS error");
802 case YPERR_RESRC:
803 return _("Local resource allocation failure");
804 case YPERR_NOMORE:
805 return _("No more records in map database");
806 case YPERR_PMAP:
807 return _("Can't communicate with portmapper");
808 case YPERR_YPBIND:
809 return _("Can't communicate with ypbind");
810 case YPERR_YPSERV:
811 return _("Can't communicate with ypserv");
812 case YPERR_NODOM:
813 return _("Local domain name not set");
814 case YPERR_BADDB:
815 return _("NIS map database is bad");
816 case YPERR_VERS:
817 return _("NIS client/server version mismatch - can't supply service");
818 case YPERR_ACCESS:
819 return _("Permission denied");
820 case YPERR_BUSY:
821 return _("Database is busy");
823 return _("Unknown NIS error code");
827 ypprot_err (const int code)
829 switch (code)
831 case YP_TRUE:
832 return YPERR_SUCCESS;
833 case YP_NOMORE:
834 return YPERR_NOMORE;
835 case YP_FALSE:
836 return YPERR_YPERR;
837 case YP_NOMAP:
838 return YPERR_MAP;
839 case YP_NODOM:
840 return YPERR_DOMAIN;
841 case YP_NOKEY:
842 return YPERR_KEY;
843 case YP_BADOP:
844 return YPERR_YPERR;
845 case YP_BADDB:
846 return YPERR_BADDB;
847 case YP_YPERR:
848 return YPERR_YPERR;
849 case YP_BADARGS:
850 return YPERR_BADARGS;
851 case YP_VERS:
852 return YPERR_VERS;
854 return YPERR_YPERR;
857 const char *
858 ypbinderr_string (const int error)
860 switch (error)
862 case 0:
863 return _("Success");
864 case YPBIND_ERR_ERR:
865 return _("Internal ypbind error");
866 case YPBIND_ERR_NOSERV:
867 return _("Domain not bound");
868 case YPBIND_ERR_RESC:
869 return _("System resource allocation failure");
870 default:
871 return _("Unknown ypbind error");
876 #define WINDOW 60
879 yp_update (char *domain, char *map, unsigned ypop,
880 char *key, int keylen, char *data, int datalen)
882 union
884 ypupdate_args update_args;
885 ypdelete_args delete_args;
887 args;
888 xdrproc_t xdr_argument;
889 unsigned res = 0;
890 CLIENT *clnt;
891 char *master;
892 struct sockaddr saddr;
893 char servername[MAXNETNAMELEN + 1];
894 int r;
896 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
897 return YPERR_BADARGS;
899 args.update_args.mapname = map;
900 args.update_args.key.yp_buf_len = keylen;
901 args.update_args.key.yp_buf_val = key;
902 args.update_args.datum.yp_buf_len = datalen;
903 args.update_args.datum.yp_buf_val = data;
905 if ((r = yp_master (domain, map, &master)) != 0)
906 return r;
908 if (!host2netname (servername, master, domain))
910 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
911 return YPERR_YPERR;
914 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
916 clnt_pcreateerror ("yp_update: clnt_create");
917 return YPERR_RPC;
920 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
922 fputs (_("yp_update: cannot get server address\n"), stderr);
923 return YPERR_RPC;
926 switch (ypop)
928 case YPOP_CHANGE:
929 case YPOP_INSERT:
930 case YPOP_STORE:
931 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
932 break;
933 case YPOP_DELETE:
934 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
935 break;
936 default:
937 return YPERR_BADARGS;
938 break;
941 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
943 if (clnt->cl_auth == NULL)
944 clnt->cl_auth = authunix_create_default ();
946 again:
947 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
948 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
950 if (r == RPC_AUTHERROR)
952 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
954 clnt->cl_auth = authunix_create_default ();
955 goto again;
957 else
958 return YPERR_ACCESS;
960 if (r != RPC_SUCCESS)
962 clnt_perror (clnt, "yp_update: clnt_call");
963 return YPERR_RPC;
965 return res;