(printbody): Fix -CLMNab output.
[glibc.git] / nis / ypclnt.c
blob1dc9ca3126344b91665e99e17187b056ab9566f6
1 /* Copyright (C) 1996, 1997, 1998, 1999 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 <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;
45 long int dom_vers;
47 typedef struct dom_binding dom_binding;
49 static struct timeval RPCTIMEOUT = {25, 0};
50 static struct timeval UDPTIMEOUT = {5, 0};
51 static int const MAXTRIES = 2;
52 static char __ypdomainname[NIS_MAXNAMELEN + 1] = "\0";
53 __libc_lock_define_initialized (static, ypbindlist_lock)
54 static dom_binding *__ypbindlist = NULL;
57 static int
58 __yp_bind (const char *domain, dom_binding **ypdb)
60 struct sockaddr_in clnt_saddr;
61 struct ypbind_resp ypbr;
62 dom_binding *ysd = NULL;
63 int clnt_sock;
64 CLIENT *client;
65 int is_new = 0;
66 int try;
68 if (domain == NULL || domain[0] == '\0')
69 return YPERR_BADARGS;
71 if (ypdb != NULL)
73 ysd = *ypdb;
74 while (ysd != NULL)
76 if (strcmp (domain, ysd->dom_domain) == 0)
77 break;
78 ysd = ysd->dom_pnext;
82 if (ysd == NULL)
84 is_new = 1;
85 ysd = (dom_binding *) calloc (1, sizeof *ysd);
86 ysd->dom_socket = -1;
87 ysd->dom_vers = -1;
90 try = 0;
94 ++try;
95 if (try > MAXTRIES)
97 if (is_new)
98 free (ysd);
99 return YPERR_YPBIND;
102 #if USE_BINDINGDIR
103 if (ysd->dom_vers < 1 && try == 1) /* Try binding dir only first time */
105 char path[sizeof (BINDINGDIR) - 1 + strlen (domain) + 10];
106 struct iovec vec[2];
107 unsigned short port;
108 int fd;
110 sprintf (path, "%s/%s.%d", BINDINGDIR, domain, YPBINDVERS);
111 fd = open (path, O_RDONLY);
112 if (fd >= 0)
114 /* We have a binding file and could save a RPC call */
115 vec[0].iov_base = &port;
116 vec[0].iov_len = sizeof (port);
117 vec[1].iov_base = &ypbr;
118 vec[1].iov_len = sizeof (ypbr);
120 if (readv (fd, vec, 2) == sizeof (port) + sizeof (ypbr))
122 ysd->dom_server_addr.sin_family = AF_INET;
123 memcpy (&ysd->dom_server_addr.sin_port,
124 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
125 sizeof (ysd->dom_server_addr.sin_port));
126 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
127 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
128 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
129 ysd->dom_vers = YPVERS;
130 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
131 ysd->dom_domain[YPMAXDOMAIN] = '\0';
133 close (fd);
136 #endif /* USE_BINDINGDIR */
138 if (ysd->dom_vers == -1)
140 if (ysd->dom_client)
142 clnt_destroy (ysd->dom_client);
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 if (is_new)
167 free (ysd);
168 return YPERR_YPBIND;
171 if (clnt_call (client, YPBINDPROC_DOMAIN,
172 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
173 (xdrproc_t) xdr_ypbind_resp,
174 (caddr_t) &ypbr, RPCTIMEOUT) != RPC_SUCCESS)
176 clnt_destroy (client);
177 if (is_new)
178 free (ysd);
179 return YPERR_YPBIND;
182 clnt_destroy (client);
184 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
186 fprintf (stderr, _("YPBINDPROC_DOMAIN: %s\n"),
187 ypbinderr_string (ypbr.ypbind_resp_u.ypbind_error));
188 if (is_new)
189 free (ysd);
190 return YPERR_DOMAIN;
192 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
193 ysd->dom_server_addr.sin_family = AF_INET;
194 memcpy (&ysd->dom_server_addr.sin_port,
195 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
196 sizeof (ysd->dom_server_addr.sin_port));
197 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
198 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
199 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
200 ysd->dom_vers = YPVERS;
201 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
202 ysd->dom_domain[YPMAXDOMAIN] = '\0';
205 ysd->dom_socket = RPC_ANYSOCK;
206 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
207 UDPTIMEOUT, &ysd->dom_socket);
208 if (ysd->dom_client == NULL)
209 ysd->dom_vers = -1;
212 while (ysd->dom_client == NULL);
214 /* If the program exists, close the socket */
215 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
216 perror ("fcntl: F_SETFD");
218 if (is_new && ypdb != NULL)
220 ysd->dom_pnext = *ypdb;
221 *ypdb = ysd;
224 return YPERR_SUCCESS;
227 static void
228 __yp_unbind (dom_binding *ydb)
230 clnt_destroy (ydb->dom_client);
231 ydb->dom_client = NULL;
232 ydb->dom_socket = -1;
235 static int
236 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
237 caddr_t req, xdrproc_t xres, caddr_t resp)
239 dom_binding *ydb = NULL;
240 bool_t use_ypbindlist = FALSE;
241 int try, status;
242 enum clnt_stat result;
243 int saved_errno = errno;
245 try = 0;
246 status = YPERR_YPERR;
248 __libc_lock_lock (ypbindlist_lock);
249 if (__ypbindlist != NULL)
251 ydb = __ypbindlist;
252 while (ydb != NULL)
254 if (strcmp (domain, ydb->dom_domain) == 0)
255 break;
256 ydb = ydb->dom_pnext;
258 if (ydb != NULL)
259 use_ypbindlist = TRUE;
260 else
261 __libc_lock_unlock (ypbindlist_lock);
263 else
264 __libc_lock_unlock (ypbindlist_lock);
266 while (try < MAXTRIES && status != YPERR_SUCCESS)
268 if (__yp_bind (domain, &ydb) != 0)
270 if (use_ypbindlist)
271 __libc_lock_unlock (ypbindlist_lock);
272 __set_errno (saved_errno);
273 return YPERR_DOMAIN;
276 result = clnt_call (ydb->dom_client, prog,
277 xargs, req, xres, resp, RPCTIMEOUT);
279 if (result != RPC_SUCCESS)
281 clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
282 ydb->dom_vers = -1;
283 if (!use_ypbindlist)
285 __yp_unbind (ydb);
286 free (ydb);
287 ydb = NULL;
289 status = YPERR_RPC;
291 else
292 status = YPERR_SUCCESS;
294 try++;
296 if (use_ypbindlist)
298 __libc_lock_unlock (ypbindlist_lock);
299 use_ypbindlist = FALSE;
301 else
302 if (ydb != NULL)
304 __yp_unbind (ydb);
305 free (ydb);
306 ydb = NULL;
309 __set_errno (saved_errno);
311 return status;
315 yp_bind (const char *indomain)
317 int status;
319 __libc_lock_lock (ypbindlist_lock);
321 status = __yp_bind (indomain, &__ypbindlist);
323 __libc_lock_unlock (ypbindlist_lock);
325 return status;
328 void
329 yp_unbind (const char *indomain)
331 dom_binding *ydbptr, *ydbptr2;
333 __libc_lock_lock (ypbindlist_lock);
335 ydbptr2 = NULL;
336 ydbptr = __ypbindlist;
337 while (ydbptr != NULL)
339 if (strcmp (ydbptr->dom_domain, indomain) == 0)
341 dom_binding *work;
343 work = ydbptr;
344 if (ydbptr2 == NULL)
345 __ypbindlist = __ypbindlist->dom_pnext;
346 else
347 ydbptr2 = ydbptr->dom_pnext;
348 __yp_unbind (work);
349 free (work);
350 break;
352 ydbptr2 = ydbptr;
353 ydbptr = ydbptr->dom_pnext;
356 __libc_lock_unlock (ypbindlist_lock);
358 return;
361 __libc_lock_define_initialized (static, domainname_lock)
364 yp_get_default_domain (char **outdomain)
366 int result = YPERR_SUCCESS;;
367 *outdomain = NULL;
369 __libc_lock_lock (domainname_lock);
371 if (__ypdomainname[0] == '\0')
373 if (getdomainname (__ypdomainname, NIS_MAXNAMELEN))
374 result = YPERR_NODOM;
375 else if (strcmp (__ypdomainname, "(none)") == 0)
377 /* If domainname is not set, some Systems will return "(none)" */
378 __ypdomainname[0] = '\0';
379 result = YPERR_NODOM;
381 else
382 *outdomain = __ypdomainname;
384 else
385 *outdomain = __ypdomainname;
387 __libc_lock_unlock (domainname_lock);
389 return result;
393 __yp_check (char **domain)
395 char *unused;
397 if (__ypdomainname[0] == '\0')
398 if (yp_get_default_domain (&unused))
399 return 0;
401 if (domain)
402 *domain = __ypdomainname;
404 if (yp_bind (__ypdomainname) == 0)
405 return 1;
406 return 0;
410 yp_match (const char *indomain, const char *inmap, const char *inkey,
411 const int inkeylen, char **outval, int *outvallen)
413 ypreq_key req;
414 ypresp_val resp;
415 enum clnt_stat result;
417 if (indomain == NULL || indomain[0] == '\0' ||
418 inmap == NULL || inmap[0] == '\0' ||
419 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
420 return YPERR_BADARGS;
422 req.domain = (char *) indomain;
423 req.map = (char *) inmap;
424 req.key.keydat_val = (char *) inkey;
425 req.key.keydat_len = inkeylen;
427 *outval = NULL;
428 *outvallen = 0;
429 memset (&resp, '\0', sizeof (resp));
431 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
432 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
433 (caddr_t) & resp);
435 if (result != YPERR_SUCCESS)
436 return result;
437 if (resp.stat != YP_TRUE)
438 return ypprot_err (resp.stat);
440 *outvallen = resp.val.valdat_len;
441 *outval = malloc (*outvallen + 1);
442 memcpy (*outval, resp.val.valdat_val, *outvallen);
443 (*outval)[*outvallen] = '\0';
445 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
447 return YPERR_SUCCESS;
451 yp_first (const char *indomain, const char *inmap, char **outkey,
452 int *outkeylen, char **outval, int *outvallen)
454 ypreq_nokey req;
455 ypresp_key_val resp;
456 enum clnt_stat result;
458 if (indomain == NULL || indomain[0] == '\0' ||
459 inmap == NULL || inmap[0] == '\0')
460 return YPERR_BADARGS;
462 req.domain = (char *) indomain;
463 req.map = (char *) inmap;
465 *outkey = *outval = NULL;
466 *outkeylen = *outvallen = 0;
467 memset (&resp, '\0', sizeof (resp));
469 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
470 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
471 (caddr_t) & resp);
473 if (result != RPC_SUCCESS)
474 return YPERR_RPC;
475 if (resp.stat != YP_TRUE)
476 return ypprot_err (resp.stat);
478 *outkeylen = resp.key.keydat_len;
479 *outkey = malloc (*outkeylen + 1);
480 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
481 (*outkey)[*outkeylen] = '\0';
482 *outvallen = resp.val.valdat_len;
483 *outval = malloc (*outvallen + 1);
484 memcpy (*outval, resp.val.valdat_val, *outvallen);
485 (*outval)[*outvallen] = '\0';
487 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
489 return YPERR_SUCCESS;
493 yp_next (const char *indomain, const char *inmap, const char *inkey,
494 const int inkeylen, char **outkey, int *outkeylen, char **outval,
495 int *outvallen)
497 ypreq_key req;
498 ypresp_key_val resp;
499 enum clnt_stat result;
501 if (indomain == NULL || indomain[0] == '\0' ||
502 inmap == NULL || inmap[0] == '\0' ||
503 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
504 return YPERR_BADARGS;
506 req.domain = (char *) indomain;
507 req.map = (char *) inmap;
508 req.key.keydat_val = (char *) inkey;
509 req.key.keydat_len = inkeylen;
511 *outkey = *outval = NULL;
512 *outkeylen = *outvallen = 0;
513 memset (&resp, '\0', sizeof (resp));
515 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
516 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
517 (caddr_t) & resp);
519 if (result != YPERR_SUCCESS)
520 return result;
521 if (resp.stat != YP_TRUE)
522 return ypprot_err (resp.stat);
524 *outkeylen = resp.key.keydat_len;
525 *outkey = malloc (*outkeylen + 1);
526 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
527 (*outkey)[*outkeylen] = '\0';
528 *outvallen = resp.val.valdat_len;
529 *outval = malloc (*outvallen + 1);
530 memcpy (*outval, resp.val.valdat_val, *outvallen);
531 (*outval)[*outvallen] = '\0';
533 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
535 return YPERR_SUCCESS;
539 yp_master (const char *indomain, const char *inmap, char **outname)
541 ypreq_nokey req;
542 ypresp_master resp;
543 enum clnt_stat result;
545 if (indomain == NULL || indomain[0] == '\0' ||
546 inmap == NULL || inmap[0] == '\0')
547 return YPERR_BADARGS;
549 req.domain = (char *) indomain;
550 req.map = (char *) inmap;
552 memset (&resp, '\0', sizeof (ypresp_master));
554 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
555 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
557 if (result != YPERR_SUCCESS)
558 return result;
559 if (resp.stat != YP_TRUE)
560 return ypprot_err (resp.stat);
562 *outname = strdup (resp.peer);
563 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
565 return *outname == NULL ? YPERR_YPERR : YPERR_SUCCESS;
569 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
571 struct ypreq_nokey req;
572 struct ypresp_order resp;
573 enum clnt_stat result;
575 if (indomain == NULL || indomain[0] == '\0' ||
576 inmap == NULL || inmap == '\0')
577 return YPERR_BADARGS;
579 req.domain = (char *) indomain;
580 req.map = (char *) inmap;
582 memset (&resp, '\0', sizeof (resp));
584 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
585 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
587 if (result != YPERR_SUCCESS)
588 return result;
589 if (resp.stat != YP_TRUE)
590 return ypprot_err (resp.stat);
592 *outorder = resp.ordernum;
593 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
595 return YPERR_SUCCESS;
598 static void *ypall_data;
599 static int (*ypall_foreach) __P ((int status, char *key, int keylen,
600 char *val, int vallen, char *data));
602 static bool_t
603 __xdr_ypresp_all (XDR *xdrs, u_long *objp)
605 while (1)
607 struct ypresp_all resp;
609 memset (&resp, '\0', sizeof (struct ypresp_all));
610 if (!xdr_ypresp_all (xdrs, &resp))
612 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
613 *objp = YP_YPERR;
614 return FALSE;
616 if (resp.more == 0)
618 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
619 *objp = YP_NOMORE;
620 return TRUE;
623 switch (resp.ypresp_all_u.val.stat)
625 case YP_TRUE:
627 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
628 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
629 int keylen = resp.ypresp_all_u.val.key.keydat_len;
630 int vallen = resp.ypresp_all_u.val.val.valdat_len;
632 *objp = YP_TRUE;
633 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
634 key[keylen] = '\0';
635 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
636 val[vallen] = '\0';
637 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
638 if ((*ypall_foreach) (*objp, key, keylen,
639 val, vallen, ypall_data))
640 return TRUE;
642 break;
643 case YP_NOMORE:
644 *objp = YP_NOMORE;
645 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
646 return TRUE;
647 break;
648 default:
649 *objp = resp.ypresp_all_u.val.stat;
650 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
651 return TRUE;
657 yp_all (const char *indomain, const char *inmap,
658 const struct ypall_callback *incallback)
660 struct ypreq_nokey req;
661 dom_binding *ydb = NULL;
662 int try, res;
663 enum clnt_stat result;
664 struct sockaddr_in clnt_sin;
665 CLIENT *clnt;
666 unsigned long status;
667 int clnt_sock;
668 int saved_errno = errno;
670 if (indomain == NULL || indomain[0] == '\0' ||
671 inmap == NULL || inmap == '\0')
672 return YPERR_BADARGS;
674 try = 0;
675 res = YPERR_YPERR;
677 while (try < MAXTRIES && res != YPERR_SUCCESS)
679 if (__yp_bind (indomain, &ydb) != 0)
681 __set_errno (saved_errno);
682 return YPERR_DOMAIN;
685 /* YPPROC_ALL get its own TCP channel to ypserv. Therefore we
686 close the socket opened by the __yp_bind call. */
687 close (ydb->dom_socket);
688 clnt_sock = RPC_ANYSOCK;
689 clnt_sin = ydb->dom_server_addr;
690 clnt_sin.sin_port = 0;
691 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
692 if (clnt == NULL)
694 __yp_unbind (ydb);
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 __yp_unbind (ydb);
717 clnt_destroy (clnt);
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;