Update.
[glibc.git] / nis / ypclnt.c
blobab28e6002ba674ce93a63a796a9da9c52b4e8c14
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, 1) == -1)
78 perror ("fcntl: F_SETFD");
82 #if USE_BINDINGDIR
83 static void
84 yp_bind_file (const char *domain, dom_binding *ysd)
86 struct ypbind_resp ypbr;
87 char path[sizeof (BINDINGDIR) + strlen (domain) + 10];
88 struct iovec vec[2];
89 unsigned short port;
90 int fd;
92 sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
93 fd = open (path, O_RDONLY);
94 if (fd >= 0)
96 /* We have a binding file and could save a RPC call */
97 vec[0].iov_base = &port;
98 vec[0].iov_len = sizeof (port);
99 vec[1].iov_base = &ypbr;
100 vec[1].iov_len = sizeof (ypbr);
102 if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
103 yp_bind_client_create (domain, ysd, &ypbr);
105 close (fd);
108 #endif
110 static int
111 yp_bind_ypbindprog (const char *domain, dom_binding *ysd)
113 struct sockaddr_in clnt_saddr;
114 struct ypbind_resp ypbr;
115 int clnt_sock;
116 CLIENT *client;
118 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
119 clnt_saddr.sin_family = AF_INET;
120 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
121 clnt_sock = RPC_ANYSOCK;
122 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
123 &clnt_sock, 0, 0);
124 if (client == NULL)
125 return YPERR_YPBIND;
127 /* Check the port number -- should be < IPPORT_RESERVED.
128 If not, it's possible someone has registered a bogus
129 ypbind with the portmapper and is trying to trick us. */
130 if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
132 clnt_destroy (client);
133 return YPERR_YPBIND;
136 if (clnt_call (client, YPBINDPROC_DOMAIN,
137 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
138 (xdrproc_t) xdr_ypbind_resp,
139 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
141 clnt_destroy (client);
142 return YPERR_YPBIND;
145 clnt_destroy (client);
147 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
149 fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
150 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
151 return YPERR_DOMAIN;
153 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
155 yp_bind_client_create (domain, ysd, &ypbr);
157 return YPERR_SUCCESS;
160 static int
161 __yp_bind (const char *domain, dom_binding **ypdb)
163 dom_binding *ysd = NULL;
164 int is_new = 0;
166 if (domain == NULL || domain[0] == '\0')
167 return YPERR_BADARGS;
169 ysd = *ypdb;
170 while (ysd != NULL)
172 if (strcmp (domain, ysd->dom_domain) == 0)
173 break;
174 ysd = ysd->dom_pnext;
177 if (ysd == NULL)
179 is_new = 1;
180 ysd = (dom_binding *) calloc (1, sizeof *ysd);
181 if (__builtin_expect (ysd == NULL, 0))
182 return YPERR_RESRC;
185 #if USE_BINDINGDIR
186 /* Try binding dir at first if we have no binding */
187 if (ysd->dom_client == NULL)
188 yp_bind_file (domain, ysd);
189 #endif /* USE_BINDINGDIR */
191 if (ysd->dom_client == NULL)
193 int retval = yp_bind_ypbindprog (domain, ysd);
194 if (retval != YPERR_SUCCESS)
196 if (is_new)
197 free (ysd);
198 return retval;
202 if (ysd->dom_client == NULL)
204 if (is_new)
205 free (ysd);
206 return YPERR_YPSERV;
209 if (is_new)
211 ysd->dom_pnext = *ypdb;
212 *ypdb = ysd;
215 return YPERR_SUCCESS;
218 static void
219 __yp_unbind (dom_binding *ydb)
221 clnt_destroy (ydb->dom_client);
222 free (ydb);
226 yp_bind (const char *indomain)
228 int status;
230 __libc_lock_lock (ypbindlist_lock);
232 status = __yp_bind (indomain, &__ypbindlist);
234 __libc_lock_unlock (ypbindlist_lock);
236 return status;
239 static void
240 yp_unbind_locked (const char *indomain)
242 dom_binding *ydbptr, *ydbptr2;
244 ydbptr2 = NULL;
245 ydbptr = __ypbindlist;
247 while (ydbptr != NULL)
249 if (strcmp (ydbptr->dom_domain, indomain) == 0)
251 dom_binding *work;
253 work = ydbptr;
254 if (ydbptr2 == NULL)
255 __ypbindlist = __ypbindlist->dom_pnext;
256 else
257 ydbptr2 = ydbptr->dom_pnext;
258 __yp_unbind (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 __ypclnt_call (const char *domain, u_long prog, xdrproc_t xargs,
280 caddr_t req, xdrproc_t xres, caddr_t resp, dom_binding **ydb,
281 int print_error)
283 enum clnt_stat result;
285 result = clnt_call ((*ydb)->dom_client, prog,
286 xargs, req, xres, resp, RPCTIMEOUT);
288 if (result != RPC_SUCCESS)
290 /* We don't print an error message, if we try our old,
291 cached data. Only print this for data, which should work. */
292 if (print_error)
293 clnt_perror ((*ydb)->dom_client, "do_ypcall: clnt_call");
295 return YPERR_RPC;
298 return YPERR_SUCCESS;
301 static int
302 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
303 caddr_t req, xdrproc_t xres, caddr_t resp)
305 dom_binding *ydb;
306 int status;
307 int saved_errno = errno;
309 status = YPERR_YPERR;
311 __libc_lock_lock (ypbindlist_lock);
312 if (__ypbindlist != NULL)
314 ydb = __ypbindlist;
315 while (ydb != NULL)
317 if (strcmp (domain, ydb->dom_domain) == 0)
318 break;
319 ydb = ydb->dom_pnext;
321 if (ydb != NULL)
323 if (__yp_bind (domain, &ydb) == 0)
325 /* Call server, print no error message, do not unbind. */
326 status = __ypclnt_call (domain, prog, xargs, req, xres,
327 resp, &ydb, 0);
328 if (status == YPERR_SUCCESS)
330 __set_errno (saved_errno);
331 return status;
334 /* We use ypbindlist, and the old cached data is
335 invalid. unbind now and create a new binding */
336 yp_unbind_locked (domain);
339 __libc_lock_unlock (ypbindlist_lock);
341 /* First try with cached data failed. Now try to get
342 current data from the system. */
343 ydb = NULL;
344 if (__yp_bind (domain, &ydb) == 0)
346 status = __ypclnt_call (domain, prog, xargs, req, xres,
347 resp, &ydb, 1);
348 __yp_unbind (ydb);
351 #if USE_BINDINGDIR
352 /* If we support binding dir data, we have a third chance:
353 Ask ypbind. */
354 if (status != YPERR_SUCCESS)
356 ydb = calloc (1, sizeof (dom_binding));
357 if (yp_bind_ypbindprog (domain, ydb) == YPERR_SUCCESS)
359 status = __ypclnt_call (domain, prog, xargs, req, xres,
360 resp, &ydb, 1);
361 __yp_unbind (ydb);
363 else
364 free (ydb);
366 #endif
368 __set_errno (saved_errno);
370 return status;
374 __libc_lock_define_initialized (static, domainname_lock)
377 yp_get_default_domain (char **outdomain)
379 int result = YPERR_SUCCESS;;
380 *outdomain = NULL;
382 __libc_lock_lock (domainname_lock);
384 if (__ypdomainname[0] == '\0')
386 if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
387 result = YPERR_NODOM;
388 else if (strcmp (__ypdomainname, "(none)") == 0)
390 /* If domainname is not set, some systems will return "(none)" */
391 __ypdomainname[0] = '\0';
392 result = YPERR_NODOM;
394 else
395 *outdomain = __ypdomainname;
397 else
398 *outdomain = __ypdomainname;
400 __libc_lock_unlock (domainname_lock);
402 return result;
406 __yp_check (char **domain)
408 char *unused;
410 if (__ypdomainname[0] == '\0')
411 if (yp_get_default_domain (&unused))
412 return 0;
414 if (domain)
415 *domain = __ypdomainname;
417 if (yp_bind (__ypdomainname) == 0)
418 return 1;
419 return 0;
423 yp_match (const char *indomain, const char *inmap, const char *inkey,
424 const int inkeylen, char **outval, int *outvallen)
426 ypreq_key req;
427 ypresp_val resp;
428 enum clnt_stat result;
430 if (indomain == NULL || indomain[0] == '\0' ||
431 inmap == NULL || inmap[0] == '\0' ||
432 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
433 return YPERR_BADARGS;
435 req.domain = (char *) indomain;
436 req.map = (char *) inmap;
437 req.key.keydat_val = (char *) inkey;
438 req.key.keydat_len = inkeylen;
440 *outval = NULL;
441 *outvallen = 0;
442 memset (&resp, '\0', sizeof (resp));
444 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
445 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
446 (caddr_t) & resp);
448 if (result != YPERR_SUCCESS)
449 return result;
450 if (resp.stat != YP_TRUE)
451 return ypprot_err (resp.stat);
453 *outvallen = resp.val.valdat_len;
454 *outval = malloc (*outvallen + 1);
455 if (__builtin_expect (*outval == NULL, 0))
456 return YPERR_RESRC;
457 memcpy (*outval, resp.val.valdat_val, *outvallen);
458 (*outval)[*outvallen] = '\0';
460 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
462 return YPERR_SUCCESS;
466 yp_first (const char *indomain, const char *inmap, char **outkey,
467 int *outkeylen, char **outval, int *outvallen)
469 ypreq_nokey req;
470 ypresp_key_val resp;
471 enum clnt_stat result;
473 if (indomain == NULL || indomain[0] == '\0' ||
474 inmap == NULL || inmap[0] == '\0')
475 return YPERR_BADARGS;
477 req.domain = (char *) indomain;
478 req.map = (char *) inmap;
480 *outkey = *outval = NULL;
481 *outkeylen = *outvallen = 0;
482 memset (&resp, '\0', sizeof (resp));
484 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
485 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
486 (caddr_t) & resp);
488 if (result != RPC_SUCCESS)
489 return YPERR_RPC;
490 if (resp.stat != YP_TRUE)
491 return ypprot_err (resp.stat);
493 *outkeylen = resp.key.keydat_len;
494 *outkey = malloc (*outkeylen + 1);
495 if (__builtin_expect (*outkey == NULL, 0))
496 return YPERR_RESRC;
497 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
498 (*outkey)[*outkeylen] = '\0';
499 *outvallen = resp.val.valdat_len;
500 *outval = malloc (*outvallen + 1);
501 if (__builtin_expect (*outval == NULL, 0))
502 return YPERR_RESRC;
503 memcpy (*outval, resp.val.valdat_val, *outvallen);
504 (*outval)[*outvallen] = '\0';
506 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
508 return YPERR_SUCCESS;
512 yp_next (const char *indomain, const char *inmap, const char *inkey,
513 const int inkeylen, char **outkey, int *outkeylen, char **outval,
514 int *outvallen)
516 ypreq_key req;
517 ypresp_key_val resp;
518 enum clnt_stat result;
520 if (indomain == NULL || indomain[0] == '\0' ||
521 inmap == NULL || inmap[0] == '\0' ||
522 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
523 return YPERR_BADARGS;
525 req.domain = (char *) indomain;
526 req.map = (char *) inmap;
527 req.key.keydat_val = (char *) inkey;
528 req.key.keydat_len = inkeylen;
530 *outkey = *outval = NULL;
531 *outkeylen = *outvallen = 0;
532 memset (&resp, '\0', sizeof (resp));
534 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
535 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
536 (caddr_t) & resp);
538 if (result != YPERR_SUCCESS)
539 return result;
540 if (resp.stat != YP_TRUE)
541 return ypprot_err (resp.stat);
543 *outkeylen = resp.key.keydat_len;
544 *outkey = malloc (*outkeylen + 1);
545 if (__builtin_expect (*outkey == NULL, 0))
546 return YPERR_RESRC;
547 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
548 (*outkey)[*outkeylen] = '\0';
549 *outvallen = resp.val.valdat_len;
550 *outval = malloc (*outvallen + 1);
551 if (__builtin_expect (*outval == NULL, 0))
552 return YPERR_RESRC;
553 memcpy (*outval, resp.val.valdat_val, *outvallen);
554 (*outval)[*outvallen] = '\0';
556 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
558 return YPERR_SUCCESS;
562 yp_master (const char *indomain, const char *inmap, char **outname)
564 ypreq_nokey req;
565 ypresp_master resp;
566 enum clnt_stat result;
568 if (indomain == NULL || indomain[0] == '\0' ||
569 inmap == NULL || inmap[0] == '\0')
570 return YPERR_BADARGS;
572 req.domain = (char *) indomain;
573 req.map = (char *) inmap;
575 memset (&resp, '\0', sizeof (ypresp_master));
577 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
578 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
580 if (result != YPERR_SUCCESS)
581 return result;
582 if (resp.stat != YP_TRUE)
583 return ypprot_err (resp.stat);
585 *outname = strdup (resp.peer);
586 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
588 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
592 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
594 struct ypreq_nokey req;
595 struct ypresp_order resp;
596 enum clnt_stat result;
598 if (indomain == NULL || indomain[0] == '\0' ||
599 inmap == NULL || inmap == '\0')
600 return YPERR_BADARGS;
602 req.domain = (char *) indomain;
603 req.map = (char *) inmap;
605 memset (&resp, '\0', sizeof (resp));
607 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
608 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
610 if (result != YPERR_SUCCESS)
611 return result;
612 if (resp.stat != YP_TRUE)
613 return ypprot_err (resp.stat);
615 *outorder = resp.ordernum;
616 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
618 return YPERR_SUCCESS;
621 struct ypresp_all_data
623 unsigned long status;
624 void *data;
625 int (*foreach) (int status, char *key, int keylen,
626 char *val, int vallen, char *data);
629 static bool_t
630 __xdr_ypresp_all (XDR *xdrs, struct ypresp_all_data *objp)
632 while (1)
634 struct ypresp_all resp;
636 memset (&resp, '\0', sizeof (struct ypresp_all));
637 if (!xdr_ypresp_all (xdrs, &resp))
639 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
640 objp->status = YP_YPERR;
641 return FALSE;
643 if (resp.more == 0)
645 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
646 objp->status = YP_NOMORE;
647 return TRUE;
650 switch (resp.ypresp_all_u.val.stat)
652 case YP_TRUE:
654 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
655 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
656 int keylen = resp.ypresp_all_u.val.key.keydat_len;
657 int vallen = resp.ypresp_all_u.val.val.valdat_len;
659 /* We are not allowed to modify the key and val data.
660 But we are allowed to add data behind the buffer,
661 if we don't modify the length. So add an extra NUL
662 character to avoid trouble with broken code. */
663 objp->status = YP_TRUE;
664 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
665 key[keylen] = '\0';
666 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
667 val[vallen] = '\0';
668 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
669 if ((*objp->foreach) (objp->status, key, keylen,
670 val, vallen, objp->data))
671 return TRUE;
673 break;
674 default:
675 objp->status = resp.ypresp_all_u.val.stat;
676 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
677 /* Sun says we don't need to make this call, but must return
678 immediatly. Since Solaris makes this call, we will call
679 the callback function, too. */
680 (*objp->foreach) (objp->status, NULL, 0, NULL, 0, objp->data);
681 return TRUE;
687 yp_all (const char *indomain, const char *inmap,
688 const struct ypall_callback *incallback)
690 struct ypreq_nokey req;
691 dom_binding *ydb = NULL;
692 int try, res;
693 enum clnt_stat result;
694 struct sockaddr_in clnt_sin;
695 CLIENT *clnt;
696 struct ypresp_all_data data;
697 int clnt_sock;
698 int saved_errno = errno;
700 if (indomain == NULL || indomain[0] == '\0' ||
701 inmap == NULL || inmap == '\0')
702 return YPERR_BADARGS;
704 try = 0;
705 res = YPERR_YPERR;
707 while (try < MAXTRIES && res != YPERR_SUCCESS)
709 if (__yp_bind (indomain, &ydb) != 0)
711 __set_errno (saved_errno);
712 return YPERR_DOMAIN;
715 clnt_sock = RPC_ANYSOCK;
716 clnt_sin = ydb->dom_server_addr;
717 clnt_sin.sin_port = 0;
719 /* We don't need the UDP connection anymore. */
720 __yp_unbind (ydb);
721 ydb = NULL;
723 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
724 if (clnt == NULL)
726 __set_errno (saved_errno);
727 return YPERR_PMAP;
729 req.domain = (char *) indomain;
730 req.map = (char *) inmap;
732 data.foreach = incallback->foreach;
733 data.data = (void *) incallback->data;
735 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
736 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
737 (caddr_t) &data, RPCTIMEOUT);
739 if (result != RPC_SUCCESS)
741 /* Print the error message only on the last try */
742 if (try == MAXTRIES - 1)
743 clnt_perror (clnt, "yp_all: clnt_call");
744 res = YPERR_RPC;
746 else
747 res = YPERR_SUCCESS;
749 clnt_destroy (clnt);
751 if (res == YPERR_SUCCESS && data.status != YP_NOMORE)
753 __set_errno (saved_errno);
754 return ypprot_err (data.status);
756 ++try;
759 __set_errno (saved_errno);
761 return res;
765 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
767 struct ypresp_maplist resp;
768 enum clnt_stat result;
770 if (indomain == NULL || indomain[0] == '\0')
771 return YPERR_BADARGS;
773 memset (&resp, '\0', sizeof (resp));
775 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
776 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
778 if (result != YPERR_SUCCESS)
779 return result;
780 if (resp.stat != YP_TRUE)
781 return ypprot_err (resp.stat);
783 *outmaplist = resp.maps;
784 /* We give the list not free, this will be done by ypserv
785 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
787 return YPERR_SUCCESS;
790 const char *
791 yperr_string (const int error)
793 switch (error)
795 case YPERR_SUCCESS:
796 return _("Success");
797 case YPERR_BADARGS:
798 return _("Request arguments bad");
799 case YPERR_RPC:
800 return _("RPC failure on NIS operation");
801 case YPERR_DOMAIN:
802 return _("Can't bind to server which serves this domain");
803 case YPERR_MAP:
804 return _("No such map in server's domain");
805 case YPERR_KEY:
806 return _("No such key in map");
807 case YPERR_YPERR:
808 return _("Internal NIS error");
809 case YPERR_RESRC:
810 return _("Local resource allocation failure");
811 case YPERR_NOMORE:
812 return _("No more records in map database");
813 case YPERR_PMAP:
814 return _("Can't communicate with portmapper");
815 case YPERR_YPBIND:
816 return _("Can't communicate with ypbind");
817 case YPERR_YPSERV:
818 return _("Can't communicate with ypserv");
819 case YPERR_NODOM:
820 return _("Local domain name not set");
821 case YPERR_BADDB:
822 return _("NIS map database is bad");
823 case YPERR_VERS:
824 return _("NIS client/server version mismatch - can't supply service");
825 case YPERR_ACCESS:
826 return _("Permission denied");
827 case YPERR_BUSY:
828 return _("Database is busy");
830 return _("Unknown NIS error code");
834 ypprot_err (const int code)
836 switch (code)
838 case YP_TRUE:
839 return YPERR_SUCCESS;
840 case YP_NOMORE:
841 return YPERR_NOMORE;
842 case YP_FALSE:
843 return YPERR_YPERR;
844 case YP_NOMAP:
845 return YPERR_MAP;
846 case YP_NODOM:
847 return YPERR_DOMAIN;
848 case YP_NOKEY:
849 return YPERR_KEY;
850 case YP_BADOP:
851 return YPERR_YPERR;
852 case YP_BADDB:
853 return YPERR_BADDB;
854 case YP_YPERR:
855 return YPERR_YPERR;
856 case YP_BADARGS:
857 return YPERR_BADARGS;
858 case YP_VERS:
859 return YPERR_VERS;
861 return YPERR_YPERR;
864 const char *
865 ypbinderr_string (const int error)
867 switch (error)
869 case 0:
870 return _("Success");
871 case YPBIND_ERR_ERR:
872 return _("Internal ypbind error");
873 case YPBIND_ERR_NOSERV:
874 return _("Domain not bound");
875 case YPBIND_ERR_RESC:
876 return _("System resource allocation failure");
877 default:
878 return _("Unknown ypbind error");
883 #define WINDOW 60
886 yp_update (char *domain, char *map, unsigned ypop,
887 char *key, int keylen, char *data, int datalen)
889 union
891 ypupdate_args update_args;
892 ypdelete_args delete_args;
894 args;
895 xdrproc_t xdr_argument;
896 unsigned res = 0;
897 CLIENT *clnt;
898 char *master;
899 struct sockaddr saddr;
900 char servername[MAXNETNAMELEN + 1];
901 int r;
903 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
904 return YPERR_BADARGS;
906 args.update_args.mapname = map;
907 args.update_args.key.yp_buf_len = keylen;
908 args.update_args.key.yp_buf_val = key;
909 args.update_args.datum.yp_buf_len = datalen;
910 args.update_args.datum.yp_buf_val = data;
912 if ((r = yp_master (domain, map, &master)) != 0)
913 return r;
915 if (!host2netname (servername, master, domain))
917 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
918 return YPERR_YPERR;
921 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
923 clnt_pcreateerror ("yp_update: clnt_create");
924 return YPERR_RPC;
927 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
929 fputs (_("yp_update: cannot get server address\n"), stderr);
930 return YPERR_RPC;
933 switch (ypop)
935 case YPOP_CHANGE:
936 case YPOP_INSERT:
937 case YPOP_STORE:
938 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
939 break;
940 case YPOP_DELETE:
941 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
942 break;
943 default:
944 return YPERR_BADARGS;
945 break;
948 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
950 if (clnt->cl_auth == NULL)
951 clnt->cl_auth = authunix_create_default ();
953 again:
954 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
955 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
957 if (r == RPC_AUTHERROR)
959 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
961 clnt->cl_auth = authunix_create_default ();
962 goto again;
964 else
965 return YPERR_ACCESS;
967 if (r != RPC_SUCCESS)
969 clnt_perror (clnt, "yp_update: clnt_call");
970 return YPERR_RPC;
972 return res;