Update.
[glibc.git] / nis / ypclnt.c
blobaa81655f9163f8a0ba2e51802127da94b302575b
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 u_short port;
107 int fd;
109 sprintf (path, "%s/%s.%ld", 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 close (ysd->dom_socket);
143 ysd->dom_client = NULL;
144 ysd->dom_socket = -1;
146 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
147 clnt_saddr.sin_family = AF_INET;
148 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
149 clnt_sock = RPC_ANYSOCK;
150 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
151 &clnt_sock, 0, 0);
152 if (client == NULL)
154 if (is_new)
155 free (ysd);
156 return YPERR_YPBIND;
159 ** Check the port number -- should be < IPPORT_RESERVED.
160 ** If not, it's possible someone has registered a bogus
161 ** ypbind with the portmapper and is trying to trick us.
163 if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
165 clnt_destroy (client);
166 close (clnt_sock);
167 if (is_new)
168 free (ysd);
169 return YPERR_YPBIND;
172 if (clnt_call (client, YPBINDPROC_DOMAIN,
173 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
174 (xdrproc_t) xdr_ypbind_resp,
175 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
177 clnt_destroy (client);
178 close (clnt_sock);
179 if (is_new)
180 free (ysd);
181 return YPERR_YPBIND;
184 clnt_destroy (client);
185 close (clnt_sock);
187 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
189 fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
190 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
191 if (is_new)
192 free (ysd);
193 return YPERR_DOMAIN;
195 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
196 ysd->dom_server_addr.sin_family = AF_INET;
197 memcpy (&ysd->dom_server_addr.sin_port,
198 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
199 sizeof (ysd->dom_server_addr.sin_port));
200 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
201 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
202 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
203 ysd->dom_vers = YPVERS;
204 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
205 ysd->dom_domain[YPMAXDOMAIN] = '\0';
208 ysd->dom_socket = RPC_ANYSOCK;
209 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
210 UDPTIMEOUT, &ysd->dom_socket);
211 if (ysd->dom_client == NULL)
212 ysd->dom_vers = -1;
215 while (ysd->dom_client == NULL);
217 /* If the program exists, close the socket */
218 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
219 perror ("fcntl: F_SETFD");
221 if (is_new && ypdb != NULL)
223 ysd->dom_pnext = *ypdb;
224 *ypdb = ysd;
227 return YPERR_SUCCESS;
230 static void
231 __yp_unbind (dom_binding *ydb)
233 clnt_destroy (ydb->dom_client);
234 ydb->dom_client = NULL;
235 ydb->dom_socket = -1;
238 static int
239 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
240 caddr_t req, xdrproc_t xres, caddr_t resp)
242 dom_binding *ydb = NULL;
243 bool_t use_ypbindlist = FALSE;
244 int try, status;
245 enum clnt_stat result;
246 int saved_errno = errno;
248 try = 0;
249 status = YPERR_YPERR;
251 __libc_lock_lock (ypbindlist_lock);
252 if (__ypbindlist != NULL)
254 ydb = __ypbindlist;
255 while (ydb != NULL)
257 if (strcmp (domain, ydb->dom_domain) == 0)
258 break;
259 ydb = ydb->dom_pnext;
261 if (ydb != NULL)
262 use_ypbindlist = TRUE;
263 else
264 __libc_lock_unlock (ypbindlist_lock);
266 else
267 __libc_lock_unlock (ypbindlist_lock);
269 while (try < MAXTRIES && status != YPERR_SUCCESS)
271 if (__yp_bind (domain, &ydb) != 0)
273 if (use_ypbindlist)
274 __libc_lock_unlock (ypbindlist_lock);
275 __set_errno (saved_errno);
276 return YPERR_DOMAIN;
279 result = clnt_call (ydb->dom_client, prog,
280 xargs, req, xres, resp, RPCTIMEOUT);
282 if (result != RPC_SUCCESS)
284 clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
285 ydb->dom_vers = -1;
286 if (!use_ypbindlist)
288 __yp_unbind (ydb);
289 free (ydb);
290 ydb = NULL;
292 status = YPERR_RPC;;
294 else
295 status = YPERR_SUCCESS;
297 try++;
299 if (use_ypbindlist)
301 __libc_lock_unlock (ypbindlist_lock);
302 use_ypbindlist = FALSE;
304 else
305 if (ydb != NULL)
307 __yp_unbind (ydb);
308 free (ydb);
309 ydb = NULL;
312 __set_errno (saved_errno);
314 return status;
318 yp_bind (const char *indomain)
320 int status;
322 __libc_lock_lock (ypbindlist_lock);
324 status = __yp_bind (indomain, &__ypbindlist);
326 __libc_lock_unlock (ypbindlist_lock);
328 return status;
331 void
332 yp_unbind (const char *indomain)
334 dom_binding *ydbptr, *ydbptr2;
336 __libc_lock_lock (ypbindlist_lock);
338 ydbptr2 = NULL;
339 ydbptr = __ypbindlist;
340 while (ydbptr != NULL)
342 if (strcmp (ydbptr->dom_domain, indomain) == 0)
344 dom_binding *work;
346 work = ydbptr;
347 if (ydbptr2 == NULL)
348 __ypbindlist = __ypbindlist->dom_pnext;
349 else
350 ydbptr2 = ydbptr->dom_pnext;
351 __yp_unbind (work);
352 free (work);
353 break;
355 ydbptr2 = ydbptr;
356 ydbptr = ydbptr->dom_pnext;
359 __libc_lock_unlock (ypbindlist_lock);
361 return;
364 __libc_lock_define_initialized (static, domainname_lock)
367 yp_get_default_domain (char **outdomain)
369 int result = YPERR_SUCCESS;;
370 *outdomain = NULL;
372 __libc_lock_lock (domainname_lock);
374 if (__ypdomainname[0] == '\0')
376 if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
377 result = YPERR_NODOM;
378 else if (strcmp (__ypdomainname, "(none)") == 0)
380 /* If domainname is not set, some Systems will return "(none)" */
381 __ypdomainname[0] = '\0';
382 result = YPERR_NODOM;
384 else
385 *outdomain = __ypdomainname;
387 else
388 *outdomain = __ypdomainname;
390 __libc_lock_unlock (domainname_lock);
392 return result;
396 __yp_check (char **domain)
398 char *unused;
400 if (__ypdomainname[0] == '\0')
401 if (yp_get_default_domain (&unused))
402 return 0;
404 if (domain)
405 *domain = __ypdomainname;
407 if (yp_bind (__ypdomainname) == 0)
408 return 1;
409 return 0;
413 yp_match (const char *indomain, const char *inmap, const char *inkey,
414 const int inkeylen, char **outval, int *outvallen)
416 ypreq_key req;
417 ypresp_val resp;
418 enum clnt_stat result;
420 if (indomain == NULL || indomain[0] == '\0' ||
421 inmap == NULL || inmap[0] == '\0' ||
422 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
423 return YPERR_BADARGS;
425 req.domain = (char *) indomain;
426 req.map = (char *) inmap;
427 req.key.keydat_val = (char *) inkey;
428 req.key.keydat_len = inkeylen;
430 *outval = NULL;
431 *outvallen = 0;
432 memset (&resp, '\0', sizeof (resp));
434 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
435 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
436 (caddr_t) & resp);
438 if (result != YPERR_SUCCESS)
439 return result;
440 if (resp.stat != YP_TRUE)
441 return ypprot_err (resp.stat);
443 *outvallen = resp.val.valdat_len;
444 *outval = malloc (*outvallen + 1);
445 memcpy (*outval, resp.val.valdat_val, *outvallen);
446 (*outval)[*outvallen] = '\0';
448 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
450 return YPERR_SUCCESS;
454 yp_first (const char *indomain, const char *inmap, char **outkey,
455 int *outkeylen, char **outval, int *outvallen)
457 ypreq_nokey req;
458 ypresp_key_val resp;
459 enum clnt_stat result;
461 if (indomain == NULL || indomain[0] == '\0' ||
462 inmap == NULL || inmap[0] == '\0')
463 return YPERR_BADARGS;
465 req.domain = (char *) indomain;
466 req.map = (char *) inmap;
468 *outkey = *outval = NULL;
469 *outkeylen = *outvallen = 0;
470 memset (&resp, '\0', sizeof (resp));
472 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
473 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
474 (caddr_t) & resp);
476 if (result != RPC_SUCCESS)
477 return YPERR_RPC;
478 if (resp.stat != YP_TRUE)
479 return ypprot_err (resp.stat);
481 *outkeylen = resp.key.keydat_len;
482 *outkey = malloc (*outkeylen + 1);
483 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
484 (*outkey)[*outkeylen] = '\0';
485 *outvallen = resp.val.valdat_len;
486 *outval = malloc (*outvallen + 1);
487 memcpy (*outval, resp.val.valdat_val, *outvallen);
488 (*outval)[*outvallen] = '\0';
490 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
492 return YPERR_SUCCESS;
496 yp_next (const char *indomain, const char *inmap, const char *inkey,
497 const int inkeylen, char **outkey, int *outkeylen, char **outval,
498 int *outvallen)
500 ypreq_key req;
501 ypresp_key_val resp;
502 enum clnt_stat result;
504 if (indomain == NULL || indomain[0] == '\0' ||
505 inmap == NULL || inmap[0] == '\0' ||
506 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
507 return YPERR_BADARGS;
509 req.domain = (char *) indomain;
510 req.map = (char *) inmap;
511 req.key.keydat_val = (char *) inkey;
512 req.key.keydat_len = inkeylen;
514 *outkey = *outval = NULL;
515 *outkeylen = *outvallen = 0;
516 memset (&resp, '\0', sizeof (resp));
518 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
519 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
520 (caddr_t) & resp);
522 if (result != YPERR_SUCCESS)
523 return result;
524 if (resp.stat != YP_TRUE)
525 return ypprot_err (resp.stat);
527 *outkeylen = resp.key.keydat_len;
528 *outkey = malloc (*outkeylen + 1);
529 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
530 (*outkey)[*outkeylen] = '\0';
531 *outvallen = resp.val.valdat_len;
532 *outval = malloc (*outvallen + 1);
533 memcpy (*outval, resp.val.valdat_val, *outvallen);
534 (*outval)[*outvallen] = '\0';
536 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
538 return YPERR_SUCCESS;
542 yp_master (const char *indomain, const char *inmap, char **outname)
544 ypreq_nokey req;
545 ypresp_master resp;
546 enum clnt_stat result;
548 if (indomain == NULL || indomain[0] == '\0' ||
549 inmap == NULL || inmap[0] == '\0')
550 return YPERR_BADARGS;
552 req.domain = (char *) indomain;
553 req.map = (char *) inmap;
555 memset (&resp, '\0', sizeof (ypresp_master));
557 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
558 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
560 if (result != YPERR_SUCCESS)
561 return result;
562 if (resp.stat != YP_TRUE)
563 return ypprot_err (resp.stat);
565 *outname = strdup (resp.peer);
566 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
568 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
572 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
574 struct ypreq_nokey req;
575 struct ypresp_order resp;
576 enum clnt_stat result;
578 if (indomain == NULL || indomain[0] == '\0' ||
579 inmap == NULL || inmap == '\0')
580 return YPERR_BADARGS;
582 req.domain = (char *) indomain;
583 req.map = (char *) inmap;
585 memset (&resp, '\0', sizeof (resp));
587 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
588 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
590 if (result != YPERR_SUCCESS)
591 return result;
592 if (resp.stat != YP_TRUE)
593 return ypprot_err (resp.stat);
595 *outorder = resp.ordernum;
596 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
598 return YPERR_SUCCESS;
601 static void *ypall_data;
602 static int (*ypall_foreach) __P ((int status, char *key, int keylen,
603 char *val, int vallen, char *data));
605 static bool_t
606 __xdr_ypresp_all (XDR * xdrs, u_long * objp)
608 while (1)
610 struct ypresp_all resp;
612 memset (&resp, '\0', sizeof (struct ypresp_all));
613 if (!xdr_ypresp_all (xdrs, &resp))
615 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
616 *objp = YP_YPERR;
617 return FALSE;
619 if (resp.more == 0)
621 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
622 *objp = YP_NOMORE;
623 return TRUE;
626 switch (resp.ypresp_all_u.val.stat)
628 case YP_TRUE:
630 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
631 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
632 int keylen = resp.ypresp_all_u.val.key.keydat_len;
633 int vallen = resp.ypresp_all_u.val.val.valdat_len;
635 *objp = YP_TRUE;
636 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
637 key[keylen] = '\0';
638 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
639 val[vallen] = '\0';
640 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
641 if ((*ypall_foreach) (*objp, key, keylen,
642 val, vallen, ypall_data))
643 return TRUE;
645 break;
646 case YP_NOMORE:
647 *objp = YP_NOMORE;
648 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
649 return TRUE;
650 break;
651 default:
652 *objp = resp.ypresp_all_u.val.stat;
653 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
654 return TRUE;
660 yp_all (const char *indomain, const char *inmap,
661 const struct ypall_callback *incallback)
663 struct ypreq_nokey req;
664 dom_binding *ydb = NULL;
665 int try, res;
666 enum clnt_stat result;
667 struct sockaddr_in clnt_sin;
668 CLIENT *clnt;
669 unsigned long status;
670 int clnt_sock;
671 int saved_errno = errno;
673 if (indomain == NULL || indomain[0] == '\0' ||
674 inmap == NULL || inmap == '\0')
675 return YPERR_BADARGS;
677 try = 0;
678 res = YPERR_YPERR;
680 while (try < MAXTRIES && res != YPERR_SUCCESS)
682 if (__yp_bind (indomain, &ydb) != 0)
684 __set_errno (saved_errno);
685 return YPERR_DOMAIN;
688 /* YPPROC_ALL get its own TCP channel to ypserv */
689 clnt_sock = RPC_ANYSOCK;
690 clnt_sin = ydb->dom_server_addr;
691 clnt_sin.sin_port = 0;
692 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
693 if (clnt == NULL)
695 __set_errno (saved_errno);
696 return YPERR_PMAP;
698 req.domain = (char *) indomain;
699 req.map = (char *) inmap;
701 ypall_foreach = incallback->foreach;
702 ypall_data = (void *) incallback->data;
704 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
705 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
706 (caddr_t) &status, RPCTIMEOUT);
708 if (result != RPC_SUCCESS)
710 clnt_perror (clnt, "yp_all: clnt_call");
711 res = YPERR_RPC;
713 else
714 res = YPERR_SUCCESS;
716 clnt_destroy (clnt);
717 close (clnt_sock);
719 if (status != YP_NOMORE)
721 __set_errno (saved_errno);
722 return ypprot_err (status);
724 ++try;
727 __set_errno (saved_errno);
729 return res;
733 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
735 struct ypresp_maplist resp;
736 enum clnt_stat result;
738 if (indomain == NULL || indomain[0] == '\0')
739 return YPERR_BADARGS;
741 memset (&resp, '\0', sizeof (resp));
743 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
744 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
746 if (result != YPERR_SUCCESS)
747 return result;
748 if (resp.stat != YP_TRUE)
749 return ypprot_err (resp.stat);
751 *outmaplist = resp.maps;
752 /* We give the list not free, this will be done by ypserv
753 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
755 return YPERR_SUCCESS;
758 const char *
759 yperr_string (const int error)
761 switch (error)
763 case YPERR_SUCCESS:
764 return _("Success");
765 case YPERR_BADARGS:
766 return _("Request arguments bad");
767 case YPERR_RPC:
768 return _("RPC failure on NIS operation");
769 case YPERR_DOMAIN:
770 return _("Can't bind to server which serves this domain");
771 case YPERR_MAP:
772 return _("No such map in server's domain");
773 case YPERR_KEY:
774 return _("No such key in map");
775 case YPERR_YPERR:
776 return _("Internal NIS error");
777 case YPERR_RESRC:
778 return _("Local resource allocation failure");
779 case YPERR_NOMORE:
780 return _("No more records in map database");
781 case YPERR_PMAP:
782 return _("Can't communicate with portmapper");
783 case YPERR_YPBIND:
784 return _("Can't communicate with ypbind");
785 case YPERR_YPSERV:
786 return _("Can't communicate with ypserv");
787 case YPERR_NODOM:
788 return _("Local domain name not set");
789 case YPERR_BADDB:
790 return _("NIS map database is bad");
791 case YPERR_VERS:
792 return _("NIS client/server version mismatch - can't supply service");
793 case YPERR_ACCESS:
794 return _("Permission denied");
795 case YPERR_BUSY:
796 return _("Database is busy");
798 return _("Unknown NIS error code");
802 ypprot_err (const int code)
804 switch (code)
806 case YP_TRUE:
807 return YPERR_SUCCESS;
808 case YP_NOMORE:
809 return YPERR_NOMORE;
810 case YP_FALSE:
811 return YPERR_YPERR;
812 case YP_NOMAP:
813 return YPERR_MAP;
814 case YP_NODOM:
815 return YPERR_DOMAIN;
816 case YP_NOKEY:
817 return YPERR_KEY;
818 case YP_BADOP:
819 return YPERR_YPERR;
820 case YP_BADDB:
821 return YPERR_BADDB;
822 case YP_YPERR:
823 return YPERR_YPERR;
824 case YP_BADARGS:
825 return YPERR_BADARGS;
826 case YP_VERS:
827 return YPERR_VERS;
829 return YPERR_YPERR;
832 const char *
833 ypbinderr_string (const int error)
835 switch (error)
837 case 0:
838 return _("Success");
839 case YPBIND_ERR_ERR:
840 return _("Internal ypbind error");
841 case YPBIND_ERR_NOSERV:
842 return _("Domain not bound");
843 case YPBIND_ERR_RESC:
844 return _("System resource allocation failure");
845 default:
846 return _("Unknown ypbind error");
851 #define WINDOW 60
854 yp_update (char *domain, char *map, unsigned ypop,
855 char *key, int keylen, char *data, int datalen)
857 union
859 ypupdate_args update_args;
860 ypdelete_args delete_args;
862 args;
863 xdrproc_t xdr_argument;
864 unsigned res = 0;
865 CLIENT *clnt;
866 char *master;
867 struct sockaddr saddr;
868 char servername[MAXNETNAMELEN + 1];
869 int r;
871 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
872 return YPERR_BADARGS;
874 args.update_args.mapname = map;
875 args.update_args.key.yp_buf_len = keylen;
876 args.update_args.key.yp_buf_val = key;
877 args.update_args.datum.yp_buf_len = datalen;
878 args.update_args.datum.yp_buf_val = data;
880 if ((r = yp_master (domain, map, &master)) != 0)
881 return r;
883 if (!host2netname (servername, master, domain))
885 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
886 return YPERR_YPERR;
889 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
891 clnt_pcreateerror ("yp_update: clnt_create");
892 return YPERR_RPC;
895 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
897 fputs (_("yp_update: cannot get server address\n"), stderr);
898 return YPERR_RPC;
901 switch (ypop)
903 case YPOP_CHANGE:
904 case YPOP_INSERT:
905 case YPOP_STORE:
906 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
907 break;
908 case YPOP_DELETE:
909 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
910 break;
911 default:
912 return YPERR_BADARGS;
913 break;
916 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
918 if (clnt->cl_auth == NULL)
919 clnt->cl_auth = authunix_create_default ();
921 again:
922 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
923 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
925 if (r == RPC_AUTHERROR)
927 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
929 clnt->cl_auth = authunix_create_default ();
930 goto again;
932 else
933 return YPERR_ACCESS;
935 if (r != RPC_SUCCESS)
937 clnt_perror (clnt, "yp_update: clnt_call");
938 return YPERR_RPC;
940 return res;