* sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Support cancellation
[glibc.git] / nis / ypclnt.c
blobb440106b34ec31a09b2cac1cbabcdaf0bdf50ec6
1 /* Copyright (C) 1996-2001, 2002, 2003 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 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;
66 if (domain == NULL || domain[0] == '\0')
67 return YPERR_BADARGS;
69 ysd = *ypdb;
70 while (ysd != NULL)
72 if (strcmp (domain, ysd->dom_domain) == 0)
73 break;
74 ysd = ysd->dom_pnext;
77 if (ysd == NULL)
79 is_new = 1;
80 ysd = (dom_binding *) calloc (1, sizeof *ysd);
81 if (__builtin_expect (ysd == NULL, 0))
82 return YPERR_RESRC;
85 #if USE_BINDINGDIR
86 if (ysd->dom_client == NULL)
88 /* Try binding dir at first if we have no binding */
89 char path[sizeof (BINDINGDIR) + strlen (domain) + 10];
90 struct iovec vec[2];
91 unsigned short port;
92 int fd;
94 sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
95 fd = open (path, O_RDONLY);
96 if (fd >= 0)
98 /* We have a binding file and could save a RPC call */
99 vec[0].iov_base = &port;
100 vec[0].iov_len = sizeof (port);
101 vec[1].iov_base = &ypbr;
102 vec[1].iov_len = sizeof (ypbr);
104 if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
106 ysd->dom_server_addr.sin_family = AF_INET;
107 memcpy (&ysd->dom_server_addr.sin_port,
108 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
109 sizeof (ysd->dom_server_addr.sin_port));
110 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
111 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
112 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
113 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
114 ysd->dom_domain[YPMAXDOMAIN] = '\0';
116 ysd->dom_socket = RPC_ANYSOCK;
117 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG,
118 YPVERS, UDPTIMEOUT,
119 &ysd->dom_socket);
121 if (ysd->dom_client != NULL)
122 /* If the program exits, close the socket */
123 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
124 perror ("fcntl: F_SETFD");
126 close (fd);
129 #endif /* USE_BINDINGDIR */
131 if (ysd->dom_client == NULL)
133 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
134 clnt_saddr.sin_family = AF_INET;
135 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
136 clnt_sock = RPC_ANYSOCK;
137 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
138 &clnt_sock, 0, 0);
139 if (client == NULL)
141 if (is_new)
142 free (ysd);
143 return YPERR_YPBIND;
145 /* Check the port number -- should be < IPPORT_RESERVED.
146 If not, it's possible someone has registered a bogus
147 ypbind with the portmapper and is trying to trick us. */
148 if (ntohs (clnt_saddr.sin_port) >= IPPORT_RESERVED)
150 clnt_destroy (client);
151 if (is_new)
152 free (ysd);
153 return YPERR_YPBIND;
156 if (clnt_call (client, YPBINDPROC_DOMAIN,
157 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
158 (xdrproc_t) xdr_ypbind_resp,
159 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
161 clnt_destroy (client);
162 if (is_new)
163 free (ysd);
164 return YPERR_YPBIND;
167 clnt_destroy (client);
169 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
171 fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
172 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
173 if (is_new)
174 free (ysd);
175 return YPERR_DOMAIN;
177 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
178 ysd->dom_server_addr.sin_family = AF_INET;
179 memcpy (&ysd->dom_server_addr.sin_port,
180 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
181 sizeof (ysd->dom_server_addr.sin_port));
182 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
183 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
184 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
185 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
186 ysd->dom_domain[YPMAXDOMAIN] = '\0';
188 ysd->dom_socket = RPC_ANYSOCK;
189 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
190 UDPTIMEOUT, &ysd->dom_socket);
192 if (ysd->dom_client != NULL)
193 /* If the program exits, close the socket */
194 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
195 perror ("fcntl: F_SETFD");
198 if (ysd->dom_client == NULL)
200 if (is_new)
201 free (ysd);
202 return YPERR_YPSERV;
205 if (is_new)
207 ysd->dom_pnext = *ypdb;
208 *ypdb = ysd;
211 return YPERR_SUCCESS;
214 static void
215 __yp_unbind (dom_binding *ydb)
217 clnt_destroy (ydb->dom_client);
218 ydb->dom_client = NULL;
219 free (ydb);
223 yp_bind (const char *indomain)
225 int status;
227 __libc_lock_lock (ypbindlist_lock);
229 status = __yp_bind (indomain, &__ypbindlist);
231 __libc_lock_unlock (ypbindlist_lock);
233 return status;
236 static void
237 yp_unbind_locked (const char *indomain)
239 dom_binding *ydbptr, *ydbptr2;
241 ydbptr2 = NULL;
242 ydbptr = __ypbindlist;
244 while (ydbptr != NULL)
246 if (strcmp (ydbptr->dom_domain, indomain) == 0)
248 dom_binding *work;
250 work = ydbptr;
251 if (ydbptr2 == NULL)
252 __ypbindlist = __ypbindlist->dom_pnext;
253 else
254 ydbptr2 = ydbptr->dom_pnext;
255 __yp_unbind (work);
256 break;
258 ydbptr2 = ydbptr;
259 ydbptr = ydbptr->dom_pnext;
263 void
264 yp_unbind (const char *indomain)
266 __libc_lock_lock (ypbindlist_lock);
268 yp_unbind_locked (indomain);
270 __libc_lock_unlock (ypbindlist_lock);
272 return;
275 static int
276 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
277 caddr_t req, xdrproc_t xres, caddr_t resp)
279 dom_binding *ydb = NULL;
280 bool_t use_ypbindlist = FALSE;
281 int try, status;
282 enum clnt_stat result;
283 int saved_errno = errno;
285 try = 0;
286 status = YPERR_YPERR;
288 __libc_lock_lock (ypbindlist_lock);
289 if (__ypbindlist != NULL)
291 ydb = __ypbindlist;
292 while (ydb != NULL)
294 if (strcmp (domain, ydb->dom_domain) == 0)
295 break;
296 ydb = ydb->dom_pnext;
298 if (ydb != NULL)
299 use_ypbindlist = TRUE;
300 else
301 __libc_lock_unlock (ypbindlist_lock);
303 else
304 __libc_lock_unlock (ypbindlist_lock);
306 while (try < MAXTRIES && status != YPERR_SUCCESS)
308 if (__yp_bind (domain, &ydb) != 0)
310 if (use_ypbindlist)
311 __libc_lock_unlock (ypbindlist_lock);
312 __set_errno (saved_errno);
313 return YPERR_DOMAIN;
316 result = clnt_call (ydb->dom_client, prog,
317 xargs, req, xres, resp, RPCTIMEOUT);
319 if (result != RPC_SUCCESS)
321 /* Don't print the error message on the first try. It
322 could be that we use cached data which is now invalid. */
323 if (try != 0)
324 clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
326 if (use_ypbindlist)
328 /* We use ypbindlist, and the old cached data is
329 invalid. unbind now and create a new binding */
330 yp_unbind_locked (domain);
331 __libc_lock_unlock (ypbindlist_lock);
332 use_ypbindlist = FALSE;
334 else
335 __yp_unbind (ydb);
337 ydb = NULL;
338 status = YPERR_RPC;
340 else
341 status = YPERR_SUCCESS;
343 try++;
345 if (use_ypbindlist)
347 __libc_lock_unlock (ypbindlist_lock);
348 use_ypbindlist = FALSE;
350 else
351 if (ydb != NULL)
352 __yp_unbind (ydb);
354 __set_errno (saved_errno);
356 return status;
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 if (__builtin_expect (*outval == NULL, 0))
442 return YPERR_RESRC;
443 memcpy (*outval, resp.val.valdat_val, *outvallen);
444 (*outval)[*outvallen] = '\0';
446 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
448 return YPERR_SUCCESS;
452 yp_first (const char *indomain, const char *inmap, char **outkey,
453 int *outkeylen, char **outval, int *outvallen)
455 ypreq_nokey req;
456 ypresp_key_val resp;
457 enum clnt_stat result;
459 if (indomain == NULL || indomain[0] == '\0' ||
460 inmap == NULL || inmap[0] == '\0')
461 return YPERR_BADARGS;
463 req.domain = (char *) indomain;
464 req.map = (char *) inmap;
466 *outkey = *outval = NULL;
467 *outkeylen = *outvallen = 0;
468 memset (&resp, '\0', sizeof (resp));
470 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
471 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
472 (caddr_t) & resp);
474 if (result != RPC_SUCCESS)
475 return YPERR_RPC;
476 if (resp.stat != YP_TRUE)
477 return ypprot_err (resp.stat);
479 *outkeylen = resp.key.keydat_len;
480 *outkey = malloc (*outkeylen + 1);
481 if (__builtin_expect (*outkey == NULL, 0))
482 return YPERR_RESRC;
483 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
484 (*outkey)[*outkeylen] = '\0';
485 *outvallen = resp.val.valdat_len;
486 *outval = malloc (*outvallen + 1);
487 if (__builtin_expect (*outval == NULL, 0))
488 return YPERR_RESRC;
489 memcpy (*outval, resp.val.valdat_val, *outvallen);
490 (*outval)[*outvallen] = '\0';
492 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
494 return YPERR_SUCCESS;
498 yp_next (const char *indomain, const char *inmap, const char *inkey,
499 const int inkeylen, char **outkey, int *outkeylen, char **outval,
500 int *outvallen)
502 ypreq_key req;
503 ypresp_key_val resp;
504 enum clnt_stat result;
506 if (indomain == NULL || indomain[0] == '\0' ||
507 inmap == NULL || inmap[0] == '\0' ||
508 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
509 return YPERR_BADARGS;
511 req.domain = (char *) indomain;
512 req.map = (char *) inmap;
513 req.key.keydat_val = (char *) inkey;
514 req.key.keydat_len = inkeylen;
516 *outkey = *outval = NULL;
517 *outkeylen = *outvallen = 0;
518 memset (&resp, '\0', sizeof (resp));
520 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
521 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
522 (caddr_t) & resp);
524 if (result != YPERR_SUCCESS)
525 return result;
526 if (resp.stat != YP_TRUE)
527 return ypprot_err (resp.stat);
529 *outkeylen = resp.key.keydat_len;
530 *outkey = malloc (*outkeylen + 1);
531 if (__builtin_expect (*outkey == NULL, 0))
532 return YPERR_RESRC;
533 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
534 (*outkey)[*outkeylen] = '\0';
535 *outvallen = resp.val.valdat_len;
536 *outval = malloc (*outvallen + 1);
537 if (__builtin_expect (*outval == NULL, 0))
538 return YPERR_RESRC;
539 memcpy (*outval, resp.val.valdat_val, *outvallen);
540 (*outval)[*outvallen] = '\0';
542 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
544 return YPERR_SUCCESS;
548 yp_master (const char *indomain, const char *inmap, char **outname)
550 ypreq_nokey req;
551 ypresp_master resp;
552 enum clnt_stat result;
554 if (indomain == NULL || indomain[0] == '\0' ||
555 inmap == NULL || inmap[0] == '\0')
556 return YPERR_BADARGS;
558 req.domain = (char *) indomain;
559 req.map = (char *) inmap;
561 memset (&resp, '\0', sizeof (ypresp_master));
563 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
564 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
566 if (result != YPERR_SUCCESS)
567 return result;
568 if (resp.stat != YP_TRUE)
569 return ypprot_err (resp.stat);
571 *outname = strdup (resp.peer);
572 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
574 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
578 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
580 struct ypreq_nokey req;
581 struct ypresp_order resp;
582 enum clnt_stat result;
584 if (indomain == NULL || indomain[0] == '\0' ||
585 inmap == NULL || inmap == '\0')
586 return YPERR_BADARGS;
588 req.domain = (char *) indomain;
589 req.map = (char *) inmap;
591 memset (&resp, '\0', sizeof (resp));
593 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
594 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
596 if (result != YPERR_SUCCESS)
597 return result;
598 if (resp.stat != YP_TRUE)
599 return ypprot_err (resp.stat);
601 *outorder = resp.ordernum;
602 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
604 return YPERR_SUCCESS;
607 static void *ypall_data;
608 static int (*ypall_foreach) (int status, char *key, int keylen,
609 char *val, int vallen, char *data);
611 static bool_t
612 __xdr_ypresp_all (XDR *xdrs, u_long *objp)
614 while (1)
616 struct ypresp_all resp;
618 memset (&resp, '\0', sizeof (struct ypresp_all));
619 if (!xdr_ypresp_all (xdrs, &resp))
621 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
622 *objp = YP_YPERR;
623 return FALSE;
625 if (resp.more == 0)
627 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
628 *objp = YP_NOMORE;
629 return TRUE;
632 switch (resp.ypresp_all_u.val.stat)
634 case YP_TRUE:
636 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
637 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
638 int keylen = resp.ypresp_all_u.val.key.keydat_len;
639 int vallen = resp.ypresp_all_u.val.val.valdat_len;
641 /* We are not allowed to modify the key and val data.
642 But we are allowed to add data behind the buffer,
643 if we don't modify the length. So add an extra NUL
644 character to avoid trouble with broken code. */
645 *objp = YP_TRUE;
646 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
647 key[keylen] = '\0';
648 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
649 val[vallen] = '\0';
650 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
651 if ((*ypall_foreach) (*objp, key, keylen,
652 val, vallen, ypall_data))
653 return TRUE;
655 break;
656 default:
657 *objp = resp.ypresp_all_u.val.stat;
658 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
659 /* Sun says we don't need to make this call, but must return
660 immediatly. Since Solaris makes this call, we will call
661 the callback function, too. */
662 (*ypall_foreach) (*objp, NULL, 0, NULL, 0, ypall_data);
663 return TRUE;
669 yp_all (const char *indomain, const char *inmap,
670 const struct ypall_callback *incallback)
672 struct ypreq_nokey req;
673 dom_binding *ydb = NULL;
674 int try, res;
675 enum clnt_stat result;
676 struct sockaddr_in clnt_sin;
677 CLIENT *clnt;
678 unsigned long status;
679 int clnt_sock;
680 int saved_errno = errno;
682 if (indomain == NULL || indomain[0] == '\0' ||
683 inmap == NULL || inmap == '\0')
684 return YPERR_BADARGS;
686 try = 0;
687 res = YPERR_YPERR;
689 while (try < MAXTRIES && res != YPERR_SUCCESS)
691 if (__yp_bind (indomain, &ydb) != 0)
693 __set_errno (saved_errno);
694 return YPERR_DOMAIN;
697 clnt_sock = RPC_ANYSOCK;
698 clnt_sin = ydb->dom_server_addr;
699 clnt_sin.sin_port = 0;
701 /* We don't need the UDP connection anymore. */
702 __yp_unbind (ydb);
703 ydb = NULL;
705 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
706 if (clnt == NULL)
708 __set_errno (saved_errno);
709 return YPERR_PMAP;
711 req.domain = (char *) indomain;
712 req.map = (char *) inmap;
714 ypall_foreach = incallback->foreach;
715 ypall_data = (void *) incallback->data;
717 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
718 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
719 (caddr_t) &status, RPCTIMEOUT);
721 if (result != RPC_SUCCESS)
723 /* Print the error message only on the last try */
724 if (try == MAXTRIES - 1)
725 clnt_perror (clnt, "yp_all: clnt_call");
726 res = YPERR_RPC;
728 else
729 res = YPERR_SUCCESS;
731 clnt_destroy (clnt);
733 if (res == YPERR_SUCCESS && status != YP_NOMORE)
735 __set_errno (saved_errno);
736 return ypprot_err (status);
738 ++try;
741 __set_errno (saved_errno);
743 return res;
747 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
749 struct ypresp_maplist resp;
750 enum clnt_stat result;
752 if (indomain == NULL || indomain[0] == '\0')
753 return YPERR_BADARGS;
755 memset (&resp, '\0', sizeof (resp));
757 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
758 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
760 if (result != YPERR_SUCCESS)
761 return result;
762 if (resp.stat != YP_TRUE)
763 return ypprot_err (resp.stat);
765 *outmaplist = resp.maps;
766 /* We give the list not free, this will be done by ypserv
767 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
769 return YPERR_SUCCESS;
772 const char *
773 yperr_string (const int error)
775 switch (error)
777 case YPERR_SUCCESS:
778 return _("Success");
779 case YPERR_BADARGS:
780 return _("Request arguments bad");
781 case YPERR_RPC:
782 return _("RPC failure on NIS operation");
783 case YPERR_DOMAIN:
784 return _("Can't bind to server which serves this domain");
785 case YPERR_MAP:
786 return _("No such map in server's domain");
787 case YPERR_KEY:
788 return _("No such key in map");
789 case YPERR_YPERR:
790 return _("Internal NIS error");
791 case YPERR_RESRC:
792 return _("Local resource allocation failure");
793 case YPERR_NOMORE:
794 return _("No more records in map database");
795 case YPERR_PMAP:
796 return _("Can't communicate with portmapper");
797 case YPERR_YPBIND:
798 return _("Can't communicate with ypbind");
799 case YPERR_YPSERV:
800 return _("Can't communicate with ypserv");
801 case YPERR_NODOM:
802 return _("Local domain name not set");
803 case YPERR_BADDB:
804 return _("NIS map database is bad");
805 case YPERR_VERS:
806 return _("NIS client/server version mismatch - can't supply service");
807 case YPERR_ACCESS:
808 return _("Permission denied");
809 case YPERR_BUSY:
810 return _("Database is busy");
812 return _("Unknown NIS error code");
816 ypprot_err (const int code)
818 switch (code)
820 case YP_TRUE:
821 return YPERR_SUCCESS;
822 case YP_NOMORE:
823 return YPERR_NOMORE;
824 case YP_FALSE:
825 return YPERR_YPERR;
826 case YP_NOMAP:
827 return YPERR_MAP;
828 case YP_NODOM:
829 return YPERR_DOMAIN;
830 case YP_NOKEY:
831 return YPERR_KEY;
832 case YP_BADOP:
833 return YPERR_YPERR;
834 case YP_BADDB:
835 return YPERR_BADDB;
836 case YP_YPERR:
837 return YPERR_YPERR;
838 case YP_BADARGS:
839 return YPERR_BADARGS;
840 case YP_VERS:
841 return YPERR_VERS;
843 return YPERR_YPERR;
846 const char *
847 ypbinderr_string (const int error)
849 switch (error)
851 case 0:
852 return _("Success");
853 case YPBIND_ERR_ERR:
854 return _("Internal ypbind error");
855 case YPBIND_ERR_NOSERV:
856 return _("Domain not bound");
857 case YPBIND_ERR_RESC:
858 return _("System resource allocation failure");
859 default:
860 return _("Unknown ypbind error");
865 #define WINDOW 60
868 yp_update (char *domain, char *map, unsigned ypop,
869 char *key, int keylen, char *data, int datalen)
871 union
873 ypupdate_args update_args;
874 ypdelete_args delete_args;
876 args;
877 xdrproc_t xdr_argument;
878 unsigned res = 0;
879 CLIENT *clnt;
880 char *master;
881 struct sockaddr saddr;
882 char servername[MAXNETNAMELEN + 1];
883 int r;
885 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
886 return YPERR_BADARGS;
888 args.update_args.mapname = map;
889 args.update_args.key.yp_buf_len = keylen;
890 args.update_args.key.yp_buf_val = key;
891 args.update_args.datum.yp_buf_len = datalen;
892 args.update_args.datum.yp_buf_val = data;
894 if ((r = yp_master (domain, map, &master)) != 0)
895 return r;
897 if (!host2netname (servername, master, domain))
899 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
900 return YPERR_YPERR;
903 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
905 clnt_pcreateerror ("yp_update: clnt_create");
906 return YPERR_RPC;
909 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
911 fputs (_("yp_update: cannot get server address\n"), stderr);
912 return YPERR_RPC;
915 switch (ypop)
917 case YPOP_CHANGE:
918 case YPOP_INSERT:
919 case YPOP_STORE:
920 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
921 break;
922 case YPOP_DELETE:
923 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
924 break;
925 default:
926 return YPERR_BADARGS;
927 break;
930 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
932 if (clnt->cl_auth == NULL)
933 clnt->cl_auth = authunix_create_default ();
935 again:
936 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
937 (xdrproc_t) xdr_u_int, (caddr_t) &res, RPCTIMEOUT);
939 if (r == RPC_AUTHERROR)
941 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
943 clnt->cl_auth = authunix_create_default ();
944 goto again;
946 else
947 return YPERR_ACCESS;
949 if (r != RPC_SUCCESS)
951 clnt_perror (clnt, "yp_update: clnt_call");
952 return YPERR_RPC;
954 return res;