Update.
[glibc.git] / nis / ypclnt.c
blobd6e2205fd9e72cc80d54aecf8d83f67508c1c993
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 static void *ypall_data;
622 static int (*ypall_foreach) (int status, char *key, int keylen,
623 char *val, int vallen, char *data);
625 static bool_t
626 __xdr_ypresp_all (XDR *xdrs, u_long *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 = YP_YPERR;
637 return FALSE;
639 if (resp.more == 0)
641 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
642 *objp = 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 = 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 ((*ypall_foreach) (*objp, key, keylen,
666 val, vallen, ypall_data))
667 return TRUE;
669 break;
670 default:
671 *objp = 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 (*ypall_foreach) (*objp, NULL, 0, NULL, 0, ypall_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 unsigned long status;
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 ypall_foreach = incallback->foreach;
729 ypall_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) &status, 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 && status != YP_NOMORE)
749 __set_errno (saved_errno);
750 return ypprot_err (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");
830 ypprot_err (const int code)
832 switch (code)
834 case YP_TRUE:
835 return YPERR_SUCCESS;
836 case YP_NOMORE:
837 return YPERR_NOMORE;
838 case YP_FALSE:
839 return YPERR_YPERR;
840 case YP_NOMAP:
841 return YPERR_MAP;
842 case YP_NODOM:
843 return YPERR_DOMAIN;
844 case YP_NOKEY:
845 return YPERR_KEY;
846 case YP_BADOP:
847 return YPERR_YPERR;
848 case YP_BADDB:
849 return YPERR_BADDB;
850 case YP_YPERR:
851 return YPERR_YPERR;
852 case YP_BADARGS:
853 return YPERR_BADARGS;
854 case YP_VERS:
855 return YPERR_VERS;
857 return YPERR_YPERR;
860 const char *
861 ypbinderr_string (const int error)
863 switch (error)
865 case 0:
866 return _("Success");
867 case YPBIND_ERR_ERR:
868 return _("Internal ypbind error");
869 case YPBIND_ERR_NOSERV:
870 return _("Domain not bound");
871 case YPBIND_ERR_RESC:
872 return _("System resource allocation failure");
873 default:
874 return _("Unknown ypbind error");
879 #define WINDOW 60
882 yp_update (char *domain, char *map, unsigned ypop,
883 char *key, int keylen, char *data, int datalen)
885 union
887 ypupdate_args update_args;
888 ypdelete_args delete_args;
890 args;
891 xdrproc_t xdr_argument;
892 unsigned res = 0;
893 CLIENT *clnt;
894 char *master;
895 struct sockaddr saddr;
896 char servername[MAXNETNAMELEN + 1];
897 int r;
899 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
900 return YPERR_BADARGS;
902 args.update_args.mapname = map;
903 args.update_args.key.yp_buf_len = keylen;
904 args.update_args.key.yp_buf_val = key;
905 args.update_args.datum.yp_buf_len = datalen;
906 args.update_args.datum.yp_buf_val = data;
908 if ((r = yp_master (domain, map, &master)) != 0)
909 return r;
911 if (!host2netname (servername, master, domain))
913 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
914 return YPERR_YPERR;
917 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
919 clnt_pcreateerror ("yp_update: clnt_create");
920 return YPERR_RPC;
923 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
925 fputs (_("yp_update: cannot get server address\n"), stderr);
926 return YPERR_RPC;
929 switch (ypop)
931 case YPOP_CHANGE:
932 case YPOP_INSERT:
933 case YPOP_STORE:
934 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
935 break;
936 case YPOP_DELETE:
937 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
938 break;
939 default:
940 return YPERR_BADARGS;
941 break;
944 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
946 if (clnt->cl_auth == NULL)
947 clnt->cl_auth = authunix_create_default ();
949 again:
950 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
951 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
953 if (r == RPC_AUTHERROR)
955 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
957 clnt->cl_auth = authunix_create_default ();
958 goto again;
960 else
961 return YPERR_ACCESS;
963 if (r != RPC_SUCCESS)
965 clnt_perror (clnt, "yp_update: clnt_call");
966 return YPERR_RPC;
968 return res;