Update.
[glibc.git] / nis / ypclnt.c
blobef0f385a1e57f23459293efcb4d656c51748f3a1
1 /* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <rpc/rpc.h>
25 #include <rpcsvc/nis.h>
26 #include <rpcsvc/yp.h>
27 #include <rpcsvc/ypclnt.h>
28 #include <rpcsvc/ypupd.h>
29 #include <sys/uio.h>
30 #include <bits/libc-lock.h>
32 /* This should only be defined on systems with a BSD compatible ypbind */
33 #ifndef BINDINGDIR
34 # define BINDINGDIR "/var/yp/binding"
35 #endif
37 struct dom_binding
39 struct dom_binding *dom_pnext;
40 char dom_domain[YPMAXDOMAIN + 1];
41 struct sockaddr_in dom_server_addr;
42 int dom_socket;
43 CLIENT *dom_client;
44 long int dom_vers;
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 = 5;
51 static char __ypdomainname[NIS_MAXNAMELEN + 1] = "\0";
52 __libc_lock_define_initialized (static, ypbindlist_lock)
53 static dom_binding *__ypbindlist = NULL;
56 static int
57 __yp_bind (const char *domain, dom_binding **ypdb)
59 struct sockaddr_in clnt_saddr;
60 struct ypbind_resp ypbr;
61 dom_binding *ysd = NULL;
62 int clnt_sock;
63 CLIENT *client;
64 int is_new = 0;
65 int try;
67 if (domain == NULL || domain[0] == '\0')
68 return YPERR_BADARGS;
70 if (ypdb != NULL)
72 ysd = *ypdb;
73 while (ysd != NULL)
75 if (strcmp (domain, ysd->dom_domain) == 0)
76 break;
77 ysd = ysd->dom_pnext;
81 if (ysd == NULL)
83 is_new = 1;
84 ysd = (dom_binding *) calloc (1, sizeof *ysd);
85 ysd->dom_socket = -1;
86 ysd->dom_vers = -1;
89 try = 0;
93 ++try;
94 if (try > MAXTRIES)
96 if (is_new)
97 free (ysd);
98 return YPERR_YPBIND;
101 #if USE_BINDINGDIR
102 if (ysd->dom_vers < 1 && try == 1) /* Try binding dir only first time */
104 char path[sizeof (BINDINGDIR) - 1 + strlen (domain) + 10];
105 struct iovec vec[2];
106 unsigned short port;
107 int fd;
109 sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
110 fd = open (path, O_RDONLY);
111 if (fd >= 0)
113 /* We have a binding file and could save a RPC call */
114 vec[0].iov_base = &port;
115 vec[0].iov_len = sizeof (port);
116 vec[1].iov_base = &ypbr;
117 vec[1].iov_len = sizeof (ypbr);
119 if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
121 ysd->dom_server_addr.sin_family = AF_INET;
122 memcpy (&ysd->dom_server_addr.sin_port,
123 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
124 sizeof (ysd->dom_server_addr.sin_port));
125 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
126 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
127 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
128 ysd->dom_vers = YPVERS;
129 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
130 ysd->dom_domain[YPMAXDOMAIN] = '\0';
132 close (fd);
135 #endif /* USE_BINDINGDIR */
137 if (ysd->dom_vers == -1)
139 if (ysd->dom_client)
141 clnt_destroy (ysd->dom_client);
142 ysd->dom_client = NULL;
143 ysd->dom_socket = -1;
145 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
146 clnt_saddr.sin_family = AF_INET;
147 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
148 clnt_sock = RPC_ANYSOCK;
149 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
150 &clnt_sock, 0, 0);
151 if (client == NULL)
153 if (is_new)
154 free (ysd);
155 return YPERR_YPBIND;
158 ** Check the port number -- should be < IPPORT_RESERVED.
159 ** If not, it's possible someone has registered a bogus
160 ** ypbind with the portmapper and is trying to trick us.
162 if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
164 clnt_destroy (client);
165 if (is_new)
166 free (ysd);
167 return YPERR_YPBIND;
170 if (clnt_call (client, YPBINDPROC_DOMAIN,
171 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
172 (xdrproc_t) xdr_ypbind_resp,
173 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
175 clnt_destroy (client);
176 if (is_new)
177 free (ysd);
178 return YPERR_YPBIND;
181 clnt_destroy (client);
183 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
185 fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
186 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
187 if (is_new)
188 free (ysd);
189 return YPERR_DOMAIN;
191 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
192 ysd->dom_server_addr.sin_family = AF_INET;
193 memcpy (&ysd->dom_server_addr.sin_port,
194 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
195 sizeof (ysd->dom_server_addr.sin_port));
196 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
197 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
198 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
199 ysd->dom_vers = YPVERS;
200 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
201 ysd->dom_domain[YPMAXDOMAIN] = '\0';
204 ysd->dom_socket = RPC_ANYSOCK;
205 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
206 UDPTIMEOUT, &ysd->dom_socket);
207 if (ysd->dom_client == NULL)
208 ysd->dom_vers = -1;
211 while (ysd->dom_client == NULL);
213 /* If the program exists, close the socket */
214 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
215 perror ("fcntl: F_SETFD");
217 if (is_new && ypdb != NULL)
219 ysd->dom_pnext = *ypdb;
220 *ypdb = ysd;
223 return YPERR_SUCCESS;
226 static void
227 __yp_unbind (dom_binding *ydb)
229 clnt_destroy (ydb->dom_client);
230 ydb->dom_client = NULL;
231 ydb->dom_socket = -1;
234 static int
235 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
236 caddr_t req, xdrproc_t xres, caddr_t resp)
238 dom_binding *ydb = NULL;
239 bool_t use_ypbindlist = FALSE;
240 int try, status;
241 enum clnt_stat result;
242 int saved_errno = errno;
244 try = 0;
245 status = YPERR_YPERR;
247 __libc_lock_lock (ypbindlist_lock);
248 if (__ypbindlist != NULL)
250 ydb = __ypbindlist;
251 while (ydb != NULL)
253 if (strcmp (domain, ydb->dom_domain) == 0)
254 break;
255 ydb = ydb->dom_pnext;
257 if (ydb != NULL)
258 use_ypbindlist = TRUE;
259 else
260 __libc_lock_unlock (ypbindlist_lock);
262 else
263 __libc_lock_unlock (ypbindlist_lock);
265 while (try < MAXTRIES && status != YPERR_SUCCESS)
267 if (__yp_bind (domain, &ydb) != 0)
269 if (use_ypbindlist)
270 __libc_lock_unlock (ypbindlist_lock);
271 __set_errno (saved_errno);
272 return YPERR_DOMAIN;
275 result = clnt_call (ydb->dom_client, prog,
276 xargs, req, xres, resp, RPCTIMEOUT);
278 if (result != RPC_SUCCESS)
280 clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
281 ydb->dom_vers = -1;
282 if (!use_ypbindlist)
284 __yp_unbind (ydb);
285 free (ydb);
286 ydb = NULL;
288 status = YPERR_RPC;;
290 else
291 status = YPERR_SUCCESS;
293 try++;
295 if (use_ypbindlist)
297 __libc_lock_unlock (ypbindlist_lock);
298 use_ypbindlist = FALSE;
300 else
301 if (ydb != NULL)
303 __yp_unbind (ydb);
304 free (ydb);
305 ydb = NULL;
308 __set_errno (saved_errno);
310 return status;
314 yp_bind (const char *indomain)
316 int status;
318 __libc_lock_lock (ypbindlist_lock);
320 status = __yp_bind (indomain, &__ypbindlist);
322 __libc_lock_unlock (ypbindlist_lock);
324 return status;
327 void
328 yp_unbind (const char *indomain)
330 dom_binding *ydbptr, *ydbptr2;
332 __libc_lock_lock (ypbindlist_lock);
334 ydbptr2 = NULL;
335 ydbptr = __ypbindlist;
336 while (ydbptr != NULL)
338 if (strcmp (ydbptr->dom_domain, indomain) == 0)
340 dom_binding *work;
342 work = ydbptr;
343 if (ydbptr2 == NULL)
344 __ypbindlist = __ypbindlist->dom_pnext;
345 else
346 ydbptr2 = ydbptr->dom_pnext;
347 __yp_unbind (work);
348 free (work);
349 break;
351 ydbptr2 = ydbptr;
352 ydbptr = ydbptr->dom_pnext;
355 __libc_lock_unlock (ypbindlist_lock);
357 return;
360 __libc_lock_define_initialized (static, domainname_lock)
363 yp_get_default_domain (char **outdomain)
365 int result = YPERR_SUCCESS;;
366 *outdomain = NULL;
368 __libc_lock_lock (domainname_lock);
370 if (__ypdomainname[0] == '\0')
372 if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
373 result = YPERR_NODOM;
374 else if (strcmp (__ypdomainname, "(none)") == 0)
376 /* If domainname is not set, some Systems will return "(none)" */
377 __ypdomainname[0] = '\0';
378 result = YPERR_NODOM;
380 else
381 *outdomain = __ypdomainname;
383 else
384 *outdomain = __ypdomainname;
386 __libc_lock_unlock (domainname_lock);
388 return result;
392 __yp_check (char **domain)
394 char *unused;
396 if (__ypdomainname[0] == '\0')
397 if (yp_get_default_domain (&unused))
398 return 0;
400 if (domain)
401 *domain = __ypdomainname;
403 if (yp_bind (__ypdomainname) == 0)
404 return 1;
405 return 0;
409 yp_match (const char *indomain, const char *inmap, const char *inkey,
410 const int inkeylen, char **outval, int *outvallen)
412 ypreq_key req;
413 ypresp_val resp;
414 enum clnt_stat result;
416 if (indomain == NULL || indomain[0] == '\0' ||
417 inmap == NULL || inmap[0] == '\0' ||
418 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
419 return YPERR_BADARGS;
421 req.domain = (char *) indomain;
422 req.map = (char *) inmap;
423 req.key.keydat_val = (char *) inkey;
424 req.key.keydat_len = inkeylen;
426 *outval = NULL;
427 *outvallen = 0;
428 memset (&resp, '\0', sizeof (resp));
430 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
431 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
432 (caddr_t) & resp);
434 if (result != YPERR_SUCCESS)
435 return result;
436 if (resp.stat != YP_TRUE)
437 return ypprot_err (resp.stat);
439 *outvallen = resp.val.valdat_len;
440 *outval = malloc (*outvallen + 1);
441 memcpy (*outval, resp.val.valdat_val, *outvallen);
442 (*outval)[*outvallen] = '\0';
444 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
446 return YPERR_SUCCESS;
450 yp_first (const char *indomain, const char *inmap, char **outkey,
451 int *outkeylen, char **outval, int *outvallen)
453 ypreq_nokey req;
454 ypresp_key_val resp;
455 enum clnt_stat result;
457 if (indomain == NULL || indomain[0] == '\0' ||
458 inmap == NULL || inmap[0] == '\0')
459 return YPERR_BADARGS;
461 req.domain = (char *) indomain;
462 req.map = (char *) inmap;
464 *outkey = *outval = NULL;
465 *outkeylen = *outvallen = 0;
466 memset (&resp, '\0', sizeof (resp));
468 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
469 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
470 (caddr_t) & resp);
472 if (result != RPC_SUCCESS)
473 return YPERR_RPC;
474 if (resp.stat != YP_TRUE)
475 return ypprot_err (resp.stat);
477 *outkeylen = resp.key.keydat_len;
478 *outkey = malloc (*outkeylen + 1);
479 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
480 (*outkey)[*outkeylen] = '\0';
481 *outvallen = resp.val.valdat_len;
482 *outval = malloc (*outvallen + 1);
483 memcpy (*outval, resp.val.valdat_val, *outvallen);
484 (*outval)[*outvallen] = '\0';
486 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
488 return YPERR_SUCCESS;
492 yp_next (const char *indomain, const char *inmap, const char *inkey,
493 const int inkeylen, char **outkey, int *outkeylen, char **outval,
494 int *outvallen)
496 ypreq_key req;
497 ypresp_key_val resp;
498 enum clnt_stat result;
500 if (indomain == NULL || indomain[0] == '\0' ||
501 inmap == NULL || inmap[0] == '\0' ||
502 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
503 return YPERR_BADARGS;
505 req.domain = (char *) indomain;
506 req.map = (char *) inmap;
507 req.key.keydat_val = (char *) inkey;
508 req.key.keydat_len = inkeylen;
510 *outkey = *outval = NULL;
511 *outkeylen = *outvallen = 0;
512 memset (&resp, '\0', sizeof (resp));
514 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
515 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
516 (caddr_t) & resp);
518 if (result != YPERR_SUCCESS)
519 return result;
520 if (resp.stat != YP_TRUE)
521 return ypprot_err (resp.stat);
523 *outkeylen = resp.key.keydat_len;
524 *outkey = malloc (*outkeylen + 1);
525 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
526 (*outkey)[*outkeylen] = '\0';
527 *outvallen = resp.val.valdat_len;
528 *outval = malloc (*outvallen + 1);
529 memcpy (*outval, resp.val.valdat_val, *outvallen);
530 (*outval)[*outvallen] = '\0';
532 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
534 return YPERR_SUCCESS;
538 yp_master (const char *indomain, const char *inmap, char **outname)
540 ypreq_nokey req;
541 ypresp_master resp;
542 enum clnt_stat result;
544 if (indomain == NULL || indomain[0] == '\0' ||
545 inmap == NULL || inmap[0] == '\0')
546 return YPERR_BADARGS;
548 req.domain = (char *) indomain;
549 req.map = (char *) inmap;
551 memset (&resp, '\0', sizeof (ypresp_master));
553 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
554 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
556 if (result != YPERR_SUCCESS)
557 return result;
558 if (resp.stat != YP_TRUE)
559 return ypprot_err (resp.stat);
561 *outname = strdup (resp.peer);
562 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
564 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
568 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
570 struct ypreq_nokey req;
571 struct ypresp_order resp;
572 enum clnt_stat result;
574 if (indomain == NULL || indomain[0] == '\0' ||
575 inmap == NULL || inmap == '\0')
576 return YPERR_BADARGS;
578 req.domain = (char *) indomain;
579 req.map = (char *) inmap;
581 memset (&resp, '\0', sizeof (resp));
583 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
584 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
586 if (result != YPERR_SUCCESS)
587 return result;
588 if (resp.stat != YP_TRUE)
589 return ypprot_err (resp.stat);
591 *outorder = resp.ordernum;
592 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
594 return YPERR_SUCCESS;
597 static void *ypall_data;
598 static int (*ypall_foreach) __P ((int status, char *key, int keylen,
599 char *val, int vallen, char *data));
601 static bool_t
602 __xdr_ypresp_all (XDR *xdrs, u_long *objp)
604 while (1)
606 struct ypresp_all resp;
608 memset (&resp, '\0', sizeof (struct ypresp_all));
609 if (!xdr_ypresp_all (xdrs, &resp))
611 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
612 *objp = YP_YPERR;
613 return FALSE;
615 if (resp.more == 0)
617 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
618 *objp = YP_NOMORE;
619 return TRUE;
622 switch (resp.ypresp_all_u.val.stat)
624 case YP_TRUE:
626 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
627 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
628 int keylen = resp.ypresp_all_u.val.key.keydat_len;
629 int vallen = resp.ypresp_all_u.val.val.valdat_len;
631 *objp = YP_TRUE;
632 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
633 key[keylen] = '\0';
634 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
635 val[vallen] = '\0';
636 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
637 if ((*ypall_foreach) (*objp, key, keylen,
638 val, vallen, ypall_data))
639 return TRUE;
641 break;
642 case YP_NOMORE:
643 *objp = YP_NOMORE;
644 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
645 return TRUE;
646 break;
647 default:
648 *objp = resp.ypresp_all_u.val.stat;
649 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
650 return TRUE;
656 yp_all (const char *indomain, const char *inmap,
657 const struct ypall_callback *incallback)
659 struct ypreq_nokey req;
660 dom_binding *ydb = NULL;
661 int try, res;
662 enum clnt_stat result;
663 struct sockaddr_in clnt_sin;
664 CLIENT *clnt;
665 unsigned long status;
666 int clnt_sock;
667 int saved_errno = errno;
669 if (indomain == NULL || indomain[0] == '\0' ||
670 inmap == NULL || inmap == '\0')
671 return YPERR_BADARGS;
673 try = 0;
674 res = YPERR_YPERR;
676 while (try < MAXTRIES && res != YPERR_SUCCESS)
678 if (__yp_bind (indomain, &ydb) != 0)
680 __set_errno (saved_errno);
681 return YPERR_DOMAIN;
684 /* YPPROC_ALL get its own TCP channel to ypserv. Therefore we
685 close the socket opened by the __yp_bind call. */
686 close (ydb->dom_socket);
687 clnt_sock = RPC_ANYSOCK;
688 clnt_sin = ydb->dom_server_addr;
689 clnt_sin.sin_port = 0;
690 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
691 if (clnt == NULL)
693 __yp_unbind (ydb);
694 __set_errno (saved_errno);
695 return YPERR_PMAP;
697 req.domain = (char *) indomain;
698 req.map = (char *) inmap;
700 ypall_foreach = incallback->foreach;
701 ypall_data = (void *) incallback->data;
703 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
704 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
705 (caddr_t) &status, RPCTIMEOUT);
707 if (result != RPC_SUCCESS)
709 clnt_perror (clnt, "yp_all: clnt_call");
710 res = YPERR_RPC;
712 else
713 res = YPERR_SUCCESS;
715 __yp_unbind (ydb);
716 clnt_destroy (clnt);
718 if (status != YP_NOMORE)
720 __set_errno (saved_errno);
721 return ypprot_err (status);
723 ++try;
726 __set_errno (saved_errno);
728 return res;
732 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
734 struct ypresp_maplist resp;
735 enum clnt_stat result;
737 if (indomain == NULL || indomain[0] == '\0')
738 return YPERR_BADARGS;
740 memset (&resp, '\0', sizeof (resp));
742 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
743 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
745 if (result != YPERR_SUCCESS)
746 return result;
747 if (resp.stat != YP_TRUE)
748 return ypprot_err (resp.stat);
750 *outmaplist = resp.maps;
751 /* We give the list not free, this will be done by ypserv
752 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
754 return YPERR_SUCCESS;
757 const char *
758 yperr_string (const int error)
760 switch (error)
762 case YPERR_SUCCESS:
763 return _("Success");
764 case YPERR_BADARGS:
765 return _("Request arguments bad");
766 case YPERR_RPC:
767 return _("RPC failure on NIS operation");
768 case YPERR_DOMAIN:
769 return _("Can't bind to server which serves this domain");
770 case YPERR_MAP:
771 return _("No such map in server's domain");
772 case YPERR_KEY:
773 return _("No such key in map");
774 case YPERR_YPERR:
775 return _("Internal NIS error");
776 case YPERR_RESRC:
777 return _("Local resource allocation failure");
778 case YPERR_NOMORE:
779 return _("No more records in map database");
780 case YPERR_PMAP:
781 return _("Can't communicate with portmapper");
782 case YPERR_YPBIND:
783 return _("Can't communicate with ypbind");
784 case YPERR_YPSERV:
785 return _("Can't communicate with ypserv");
786 case YPERR_NODOM:
787 return _("Local domain name not set");
788 case YPERR_BADDB:
789 return _("NIS map database is bad");
790 case YPERR_VERS:
791 return _("NIS client/server version mismatch - can't supply service");
792 case YPERR_ACCESS:
793 return _("Permission denied");
794 case YPERR_BUSY:
795 return _("Database is busy");
797 return _("Unknown NIS error code");
801 ypprot_err (const int code)
803 switch (code)
805 case YP_TRUE:
806 return YPERR_SUCCESS;
807 case YP_NOMORE:
808 return YPERR_NOMORE;
809 case YP_FALSE:
810 return YPERR_YPERR;
811 case YP_NOMAP:
812 return YPERR_MAP;
813 case YP_NODOM:
814 return YPERR_DOMAIN;
815 case YP_NOKEY:
816 return YPERR_KEY;
817 case YP_BADOP:
818 return YPERR_YPERR;
819 case YP_BADDB:
820 return YPERR_BADDB;
821 case YP_YPERR:
822 return YPERR_YPERR;
823 case YP_BADARGS:
824 return YPERR_BADARGS;
825 case YP_VERS:
826 return YPERR_VERS;
828 return YPERR_YPERR;
831 const char *
832 ypbinderr_string (const int error)
834 switch (error)
836 case 0:
837 return _("Success");
838 case YPBIND_ERR_ERR:
839 return _("Internal ypbind error");
840 case YPBIND_ERR_NOSERV:
841 return _("Domain not bound");
842 case YPBIND_ERR_RESC:
843 return _("System resource allocation failure");
844 default:
845 return _("Unknown ypbind error");
850 #define WINDOW 60
853 yp_update (char *domain, char *map, unsigned ypop,
854 char *key, int keylen, char *data, int datalen)
856 union
858 ypupdate_args update_args;
859 ypdelete_args delete_args;
861 args;
862 xdrproc_t xdr_argument;
863 unsigned res = 0;
864 CLIENT *clnt;
865 char *master;
866 struct sockaddr saddr;
867 char servername[MAXNETNAMELEN + 1];
868 int r;
870 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
871 return YPERR_BADARGS;
873 args.update_args.mapname = map;
874 args.update_args.key.yp_buf_len = keylen;
875 args.update_args.key.yp_buf_val = key;
876 args.update_args.datum.yp_buf_len = datalen;
877 args.update_args.datum.yp_buf_val = data;
879 if ((r = yp_master (domain, map, &master)) != 0)
880 return r;
882 if (!host2netname (servername, master, domain))
884 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
885 return YPERR_YPERR;
888 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
890 clnt_pcreateerror ("yp_update: clnt_create");
891 return YPERR_RPC;
894 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
896 fputs (_("yp_update: cannot get server address\n"), stderr);
897 return YPERR_RPC;
900 switch (ypop)
902 case YPOP_CHANGE:
903 case YPOP_INSERT:
904 case YPOP_STORE:
905 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
906 break;
907 case YPOP_DELETE:
908 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
909 break;
910 default:
911 return YPERR_BADARGS;
912 break;
915 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
917 if (clnt->cl_auth == NULL)
918 clnt->cl_auth = authunix_create_default ();
920 again:
921 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
922 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
924 if (r == RPC_AUTHERROR)
926 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
928 clnt->cl_auth = authunix_create_default ();
929 goto again;
931 else
932 return YPERR_ACCESS;
934 if (r != RPC_SUCCESS)
936 clnt_perror (clnt, "yp_update: clnt_call");
937 return YPERR_RPC;
939 return res;