Update.
[glibc.git] / nis / ypclnt.c
blobb128ad63661f6da94c71e4fcb38a782b0e36266e
1 /* Copyright (C) 1996, 1997 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 <string.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <libc-lock.h>
24 #include <rpcsvc/yp.h>
25 #include <rpcsvc/ypclnt.h>
26 #include <rpcsvc/ypupd.h>
28 struct dom_binding
30 struct dom_binding *dom_pnext;
31 char dom_domain[YPMAXDOMAIN + 1];
32 struct sockaddr_in dom_server_addr;
33 int dom_socket;
34 CLIENT *dom_client;
35 long int dom_vers;
37 typedef struct dom_binding dom_binding;
39 static struct timeval TIMEOUT = {25, 0};
40 static int const MAXTRIES = 5;
41 static char __ypdomainname[MAXHOSTNAMELEN + 1] = "\0";
42 __libc_lock_define_initialized (static, ypbindlist_lock)
43 static dom_binding *__ypbindlist = NULL;
46 static int
47 __yp_bind (const char *domain, dom_binding ** ypdb)
49 struct sockaddr_in clnt_saddr;
50 struct ypbind_resp ypbr;
51 dom_binding *ysd;
52 int clnt_sock;
53 CLIENT *client;
54 int is_new = 0;
55 int try;
57 if (ypdb != NULL)
58 *ypdb = NULL;
60 if ((domain == NULL) || (strlen (domain) == 0))
61 return YPERR_BADARGS;
63 ysd = __ypbindlist;
64 while (ysd != NULL)
66 if (strcmp (domain, ysd->dom_domain) == 0)
67 break;
68 ysd = ysd->dom_pnext;
71 if (ysd == NULL)
73 is_new = 1;
74 ysd = (dom_binding *) malloc (sizeof *ysd);
75 memset (ysd, '\0', sizeof *ysd);
76 ysd->dom_socket = -1;
77 ysd->dom_vers = -1;
80 try = 0;
84 try++;
85 if (try > MAXTRIES)
87 if (is_new)
88 free (ysd);
89 return YPERR_YPBIND;
92 if (ysd->dom_vers == -1)
94 if(ysd->dom_client)
96 clnt_destroy(ysd->dom_client);
97 ysd->dom_client = NULL;
98 ysd->dom_socket = -1;
100 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
101 clnt_saddr.sin_family = AF_INET;
102 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
103 clnt_sock = RPC_ANYSOCK;
104 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
105 &clnt_sock, 0, 0);
106 if (client == NULL)
108 if (is_new)
109 free (ysd);
110 return YPERR_YPBIND;
113 ** Check the port number -- should be < IPPORT_RESERVED.
114 ** If not, it's possible someone has registered a bogus
115 ** ypbind with the portmapper and is trying to trick us.
117 if (ntohs(clnt_saddr.sin_port) >= IPPORT_RESERVED)
119 clnt_destroy(client);
120 if (is_new)
121 free(ysd);
122 return(YPERR_YPBIND);
125 if (clnt_call (client, YPBINDPROC_DOMAIN,
126 (xdrproc_t) xdr_domainname, &domain,
127 (xdrproc_t) xdr_ypbind_resp,
128 &ypbr, TIMEOUT) != RPC_SUCCESS)
130 clnt_destroy (client);
131 if (is_new)
132 free (ysd);
133 return YPERR_YPBIND;
136 clnt_destroy (client);
137 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
139 switch (ypbr.ypbind_resp_u.ypbind_error)
141 case YPBIND_ERR_ERR:
142 fputs (_("YPBINDPROC_DOMAIN: Internal error\n"), stderr);
143 break;
144 case YPBIND_ERR_NOSERV:
145 fprintf (stderr,
146 _("YPBINDPROC_DOMAIN: No server for domain %s\n"),
147 domain);
148 break;
149 case YPBIND_ERR_RESC:
150 fputs (_("YPBINDPROC_DOMAIN: Resource allocation failure\n"),
151 stderr);
152 break;
153 default:
154 fputs (_("YPBINDPROC_DOMAIN: Unknown error\n"), stderr);
155 break;
157 if (is_new)
158 free (ysd);
159 return YPERR_DOMAIN;
161 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
162 ysd->dom_server_addr.sin_family = AF_INET;
163 memcpy (&ysd->dom_server_addr.sin_port,
164 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
165 sizeof (ysd->dom_server_addr.sin_port));
166 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
167 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
168 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
169 ysd->dom_vers = YPVERS;
170 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
171 ysd->dom_domain[YPMAXDOMAIN] = '\0';
174 if (ysd->dom_client)
175 clnt_destroy (ysd->dom_client);
176 ysd->dom_socket = RPC_ANYSOCK;
177 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
178 TIMEOUT, &ysd->dom_socket);
179 if (ysd->dom_client == NULL)
180 ysd->dom_vers = -1;
183 while (ysd->dom_client == NULL);
185 /* If the program exists, close the socket */
186 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
187 perror (_("fcntl: F_SETFD"));
189 if (is_new)
191 ysd->dom_pnext = __ypbindlist;
192 __ypbindlist = ysd;
195 if (NULL != ypdb)
196 *ypdb = ysd;
198 return YPERR_SUCCESS;
201 static void
202 __yp_unbind (dom_binding *ydb)
204 clnt_destroy (ydb->dom_client);
205 ydb->dom_client = NULL;
206 ydb->dom_socket = -1;
209 static int
210 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
211 caddr_t req, xdrproc_t xres, caddr_t resp)
213 dom_binding *ydb = NULL;
214 int try, result;
216 try = 0;
217 result = YPERR_YPERR;
219 while (try < MAXTRIES && result != RPC_SUCCESS)
221 __libc_lock_lock (ypbindlist_lock);
223 if (__yp_bind (domain, &ydb) != 0)
225 __libc_lock_unlock (ypbindlist_lock);
226 return YPERR_DOMAIN;
229 result = clnt_call (ydb->dom_client, prog,
230 xargs, req, xres, resp, TIMEOUT);
232 if (result != RPC_SUCCESS)
234 clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
235 ydb->dom_vers = -1;
236 __yp_unbind (ydb);
237 result = YPERR_RPC;
240 __libc_lock_unlock (ypbindlist_lock);
242 try++;
245 return result;
249 yp_bind (const char *indomain)
251 int status;
253 __libc_lock_lock (ypbindlist_lock);
255 status = __yp_bind (indomain, NULL);
257 __libc_lock_unlock (ypbindlist_lock);
259 return status;
262 void
263 yp_unbind (const char *indomain)
265 dom_binding *ydbptr, *ydbptr2;
267 __libc_lock_lock (ypbindlist_lock);
269 ydbptr2 = NULL;
270 ydbptr = __ypbindlist;
271 while (ydbptr != NULL)
273 if (strcmp (ydbptr->dom_domain, indomain) == 0)
275 dom_binding *work;
277 work = ydbptr;
278 if (ydbptr2 == NULL)
279 __ypbindlist = __ypbindlist->dom_pnext;
280 else
281 ydbptr2 = ydbptr->dom_pnext;
282 __yp_unbind (work);
283 free (work);
284 break;
286 ydbptr2 = ydbptr;
287 ydbptr = ydbptr->dom_pnext;
290 __libc_lock_unlock (ypbindlist_lock);
292 return;
295 __libc_lock_define_initialized (static, domainname_lock)
298 yp_get_default_domain (char **outdomain)
300 int result = YPERR_SUCCESS;;
301 *outdomain = NULL;
303 __libc_lock_lock (domainname_lock);
305 if (__ypdomainname[0] == '\0')
307 if (getdomainname (__ypdomainname, MAXHOSTNAMELEN))
308 result = YPERR_NODOM;
309 else
310 *outdomain = __ypdomainname;
312 else
313 *outdomain = __ypdomainname;
315 __libc_lock_unlock (domainname_lock);
317 return result;
321 __yp_check (char **domain)
323 char *unused;
325 if (__ypdomainname[0] == '\0')
326 if (yp_get_default_domain (&unused))
327 return 0;
328 else if (strcmp (__ypdomainname, "(none)") == 0)
329 return 0;
331 if (domain)
332 *domain = __ypdomainname;
334 if (yp_bind (__ypdomainname) == 0)
335 return 1;
336 return 0;
340 yp_match (const char *indomain, const char *inmap, const char *inkey,
341 const int inkeylen, char **outval, int *outvallen)
343 ypreq_key req;
344 ypresp_val resp;
345 int result;
347 if (indomain == NULL || indomain[0] == '\0' ||
348 inmap == NULL || inmap[0] == '\0' ||
349 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
350 return YPERR_BADARGS;
352 req.domain = (char *) indomain;
353 req.map = (char *) inmap;
354 req.key.keydat_val = (char *) inkey;
355 req.key.keydat_len = inkeylen;
357 *outval = NULL;
358 *outvallen = 0;
359 memset (&resp, '\0', sizeof (resp));
361 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
362 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
363 (caddr_t) & resp);
365 if (result != RPC_SUCCESS)
366 return result;
367 if (resp.stat != YP_TRUE)
368 return ypprot_err (resp.stat);
370 *outvallen = resp.val.valdat_len;
371 *outval = malloc (*outvallen + 1);
372 memcpy (*outval, resp.val.valdat_val, *outvallen);
373 (*outval)[*outvallen] = '\0';
375 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
377 return YPERR_SUCCESS;
381 yp_first (const char *indomain, const char *inmap, char **outkey,
382 int *outkeylen, char **outval, int *outvallen)
384 ypreq_nokey req;
385 ypresp_key_val resp;
386 int result;
388 if (indomain == NULL || indomain[0] == '\0' ||
389 inmap == NULL || inmap[0] == '\0')
390 return YPERR_BADARGS;
392 req.domain = (char *) indomain;
393 req.map = (char *) inmap;
395 *outkey = *outval = NULL;
396 *outkeylen = *outvallen = 0;
397 memset (&resp, '\0', sizeof (resp));
399 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
400 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
401 (caddr_t) & resp);
403 if (result != RPC_SUCCESS)
404 return result;
405 if (resp.stat != YP_TRUE)
406 return ypprot_err (resp.stat);
408 *outkeylen = resp.key.keydat_len;
409 *outkey = malloc (*outkeylen + 1);
410 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
411 (*outkey)[*outkeylen] = '\0';
412 *outvallen = resp.val.valdat_len;
413 *outval = malloc (*outvallen + 1);
414 memcpy (*outval, resp.val.valdat_val, *outvallen);
415 (*outval)[*outvallen] = '\0';
417 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
419 return YPERR_SUCCESS;
423 yp_next (const char *indomain, const char *inmap, const char *inkey,
424 const int inkeylen, char **outkey, int *outkeylen, char **outval,
425 int *outvallen)
427 ypreq_key req;
428 ypresp_key_val resp;
429 int result;
431 if (indomain == NULL || indomain[0] == '\0' ||
432 inmap == NULL || inmap[0] == '\0' ||
433 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
434 return YPERR_BADARGS;
436 req.domain = (char *) indomain;
437 req.map = (char *) inmap;
438 req.key.keydat_val = (char *) inkey;
439 req.key.keydat_len = inkeylen;
441 *outkey = *outval = NULL;
442 *outkeylen = *outvallen = 0;
443 memset (&resp, '\0', sizeof (resp));
445 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
446 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
447 (caddr_t) & resp);
449 if (result != RPC_SUCCESS)
450 return result;
451 if (resp.stat != YP_TRUE)
452 return ypprot_err (resp.stat);
454 *outkeylen = resp.key.keydat_len;
455 *outkey = malloc (*outkeylen + 1);
456 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
457 (*outkey)[*outkeylen] = '\0';
458 *outvallen = resp.val.valdat_len;
459 *outval = malloc (*outvallen + 1);
460 memcpy (*outval, resp.val.valdat_val, *outvallen);
461 (*outval)[*outvallen] = '\0';
463 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
465 return YPERR_SUCCESS;
469 yp_master (const char *indomain, const char *inmap, char **outname)
471 ypreq_nokey req;
472 ypresp_master resp;
473 int result;
475 if (indomain == NULL || indomain[0] == '\0' ||
476 inmap == NULL || inmap[0] == '\0')
477 return YPERR_BADARGS;
479 req.domain = (char *) indomain;
480 req.map = (char *) inmap;
482 memset (&resp, '\0', sizeof (ypresp_master));
484 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
485 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
487 if (result != RPC_SUCCESS)
488 return result;
489 if (resp.stat != YP_TRUE)
490 return ypprot_err (resp.stat);
492 *outname = strdup (resp.peer);
493 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
495 return YPERR_SUCCESS;
499 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
501 struct ypreq_nokey req;
502 struct ypresp_order resp;
503 int result;
505 if (indomain == NULL || indomain[0] == '\0' ||
506 inmap == NULL || inmap == '\0')
507 return YPERR_BADARGS;
509 req.domain = (char *) indomain;
510 req.map = (char *) inmap;
512 memset (&resp, '\0', sizeof (resp));
514 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
515 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
517 if (result != RPC_SUCCESS)
518 return result;
519 if (resp.stat != YP_TRUE)
520 return ypprot_err (resp.stat);
522 *outorder = resp.ordernum;
523 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
525 return YPERR_SUCCESS;
528 static void *ypall_data;
529 static int (*ypall_foreach) ();
531 static bool_t
532 __xdr_ypresp_all (XDR * xdrs, u_long * objp)
534 while (1)
536 struct ypresp_all resp;
538 memset (&resp, '\0', sizeof (struct ypresp_all));
539 if (!xdr_ypresp_all (xdrs, &resp))
541 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
542 *objp = YP_YPERR;
543 return (FALSE);
545 if (resp.more == 0)
547 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
548 *objp = YP_NOMORE;
549 return (FALSE);
552 switch (resp.ypresp_all_u.val.stat)
554 case YP_TRUE:
556 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
557 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
558 int keylen = resp.ypresp_all_u.val.key.keydat_len;
559 int vallen = resp.ypresp_all_u.val.val.valdat_len;
561 *objp = YP_TRUE;
562 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
563 key[keylen] = '\0';
564 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
565 val[vallen] = '\0';
566 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
567 if ((*ypall_foreach) (*objp, key, keylen,
568 val, vallen, ypall_data))
569 return TRUE;
571 break;
572 case YP_NOMORE:
573 *objp = YP_NOMORE;
574 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
575 return TRUE;
576 break;
577 default:
578 *objp = resp.ypresp_all_u.val.stat;
579 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
580 return TRUE;
586 yp_all (const char *indomain, const char *inmap,
587 const struct ypall_callback *incallback)
589 struct ypreq_nokey req;
590 dom_binding *ydb;
591 int try, result;
592 struct sockaddr_in clnt_sin;
593 CLIENT *clnt;
594 unsigned long status;
595 int clnt_sock;
597 if (indomain == NULL || indomain[0] == '\0' ||
598 inmap == NULL || inmap == '\0')
599 return YPERR_BADARGS;
601 try = 0;
602 result = YPERR_YPERR;
604 while (try < MAXTRIES && result != RPC_SUCCESS)
606 __libc_lock_lock (ypbindlist_lock);
608 if (__yp_bind (indomain, &ydb) != 0)
610 __libc_lock_unlock (ypbindlist_lock);
611 return YPERR_DOMAIN;
614 /* YPPROC_ALL get its own TCP channel to ypserv */
615 clnt_sock = RPC_ANYSOCK;
616 clnt_sin = ydb->dom_server_addr;
617 clnt_sin.sin_port = 0;
618 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
619 if (clnt == NULL)
621 puts ("yp_all: clnttcp_create failed");
622 __libc_lock_unlock (ypbindlist_lock);
623 return YPERR_PMAP;
625 req.domain = (char *) indomain;
626 req.map = (char *) inmap;
628 ypall_foreach = incallback->foreach;
629 ypall_data = (void *) incallback->data;
631 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey, &req,
632 (xdrproc_t) __xdr_ypresp_all, &status, TIMEOUT);
634 if (result != RPC_SUCCESS)
636 clnt_perror (ydb->dom_client, "yp_all: clnt_call");
637 clnt_destroy (clnt);
638 __yp_unbind (ydb);
639 result = YPERR_RPC;
641 else
643 clnt_destroy (clnt);
644 result = YPERR_SUCCESS;
647 __libc_lock_unlock (ypbindlist_lock);
649 if (status != YP_NOMORE)
650 return ypprot_err (status);
651 try++;
654 return result;
658 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
660 struct ypresp_maplist resp;
661 int result;
663 if (indomain == NULL || indomain[0] == '\0')
664 return YPERR_BADARGS;
666 memset (&resp, '\0', sizeof (resp));
668 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
669 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
671 if (result != RPC_SUCCESS)
672 return result;
673 if (resp.stat != YP_TRUE)
674 return ypprot_err (resp.stat);
676 *outmaplist = resp.maps;
677 /* We give the list not free, this will be done by ypserv
678 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
680 return YPERR_SUCCESS;
683 const char *
684 yperr_string (const int error)
686 switch (error)
688 case YPERR_SUCCESS:
689 return _("Success");
690 case YPERR_BADARGS:
691 return _("Request arguments bad");
692 case YPERR_RPC:
693 return _("RPC failure on NIS operation");
694 case YPERR_DOMAIN:
695 return _("Can't bind to server which serves this domain");
696 case YPERR_MAP:
697 return _("No such map in server's domain");
698 case YPERR_KEY:
699 return _("No such key in map");
700 case YPERR_YPERR:
701 return _("Internal NIS error");
702 case YPERR_RESRC:
703 return _("Local resource allocation failure");
704 case YPERR_NOMORE:
705 return _("No more records in map database");
706 case YPERR_PMAP:
707 return _("Can't communicate with portmapper");
708 case YPERR_YPBIND:
709 return _("Can't communicate with ypbind");
710 case YPERR_YPSERV:
711 return _("Can't communicate with ypserv");
712 case YPERR_NODOM:
713 return _("Local domain name not set");
714 case YPERR_BADDB:
715 return _("NIS map data base is bad");
716 case YPERR_VERS:
717 return _("NIS client/server version mismatch - can't supply service");
718 case YPERR_ACCESS:
719 return _("Permission denied");
720 case YPERR_BUSY:
721 return _("Database is busy");
723 return _("Unknown NIS error code");
727 ypprot_err (const int code)
729 switch (code)
731 case YP_TRUE:
732 return YPERR_SUCCESS;
733 case YP_NOMORE:
734 return YPERR_NOMORE;
735 case YP_FALSE:
736 return YPERR_YPERR;
737 case YP_NOMAP:
738 return YPERR_MAP;
739 case YP_NODOM:
740 return YPERR_DOMAIN;
741 case YP_NOKEY:
742 return YPERR_KEY;
743 case YP_BADOP:
744 return YPERR_YPERR;
745 case YP_BADDB:
746 return YPERR_BADDB;
747 case YP_YPERR:
748 return YPERR_YPERR;
749 case YP_BADARGS:
750 return YPERR_BADARGS;
751 case YP_VERS:
752 return YPERR_VERS;
754 return YPERR_YPERR;
757 const char *
758 ypbinderr_string (const int error)
760 switch (error)
762 case 0:
763 return _("Success");
764 case YPBIND_ERR_ERR:
765 return _("Internal ypbind error");
766 case YPBIND_ERR_NOSERV:
767 return _("Domain not bound");
768 case YPBIND_ERR_RESC:
769 return _("System resource allocation failure");
770 default:
771 return _("Unknown ypbind error");
776 #define WINDOW 60
779 yp_update (char *domain, char *map, unsigned ypop,
780 char *key, int keylen, char *data, int datalen)
782 #if 0
783 union
785 ypupdate_args update_args;
786 ypdelete_args delete_args;
788 args;
789 xdrproc_t xdr_argument;
790 unsigned res = 0;
791 CLIENT *clnt;
792 char *master;
793 struct sockaddr saddr;
794 char servername[MAXNETNAMELEN + 1];
795 int r;
797 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
798 return YPERR_BADARGS;
800 args.update_args.mapname = map;
801 args.update_args.key.yp_buf_len = keylen;
802 args.update_args.key.yp_buf_val = key;
803 args.update_args.datum.yp_buf_len = datalen;
804 args.update_args.datum.yp_buf_val = data;
806 if ((r = yp_master (domain, map, &master)) != 0)
807 return r;
809 if (!host2netname (servername, master, domain))
811 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
812 return YPERR_YPERR;
815 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
817 clnt_pcreateerror ("yp_update: clnt_create");
818 return YPERR_RPC;
821 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
823 fputs (_("yp_update: cannot get server address\n"), stderr);
824 return YPERR_RPC;
827 switch (ypop)
829 case YPOP_CHANGE:
830 case YPOP_INSERT:
831 case YPOP_STORE:
832 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
833 break;
834 case YPOP_DELETE:
835 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
836 break;
837 default:
838 return YPERR_BADARGS;
839 break;
842 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
844 if (clnt->cl_auth == NULL)
845 clnt->cl_auth = authunix_create_default ();
847 again:
848 r = clnt_call (clnt, ypop, xdr_argument, &args,
849 (xdrproc_t) xdr_u_int, &res, TIMEOUT);
851 if (r == RPC_AUTHERROR)
853 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
855 clnt->cl_auth = authunix_create_default ();
856 goto again;
858 else
859 return YPERR_ACCESS;
861 if (r != RPC_SUCCESS)
863 clnt_perror (clnt, "yp_update: clnt_call");
864 return YPERR_RPC;
866 return res;
867 #else
868 return YPERR_YPERR;
869 #endif