Update.
[glibc/history.git] / nis / ypclnt.c
blob01bf8bc6b0b760105a3628d5b83289b66fd13867
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 <rpc/rpc.h>
25 #include <rpcsvc/yp.h>
26 #include <rpcsvc/ypclnt.h>
27 #include <rpcsvc/ypupd.h>
29 struct dom_binding
31 struct dom_binding *dom_pnext;
32 char dom_domain[YPMAXDOMAIN + 1];
33 struct sockaddr_in dom_server_addr;
34 int dom_socket;
35 CLIENT *dom_client;
36 long int dom_vers;
38 typedef struct dom_binding dom_binding;
40 static struct timeval TIMEOUT = {25, 0};
41 static int const MAXTRIES = 5;
42 static char __ypdomainname[MAXHOSTNAMELEN + 1] = "\0";
43 __libc_lock_define_initialized (static, ypbindlist_lock)
44 static dom_binding *__ypbindlist = NULL;
47 static int
48 __yp_bind (const char *domain, dom_binding ** ypdb)
50 struct sockaddr_in clnt_saddr;
51 struct ypbind_resp ypbr;
52 dom_binding *ysd;
53 int clnt_sock;
54 CLIENT *client;
55 int is_new = 0;
56 int try;
58 if (ypdb != NULL)
59 *ypdb = NULL;
61 if ((domain == NULL) || (strlen (domain) == 0))
62 return YPERR_BADARGS;
64 ysd = __ypbindlist;
65 while (ysd != NULL)
67 if (strcmp (domain, ysd->dom_domain) == 0)
68 break;
69 ysd = ysd->dom_pnext;
72 if (ysd == NULL)
74 is_new = 1;
75 ysd = (dom_binding *) malloc (sizeof *ysd);
76 memset (ysd, '\0', sizeof *ysd);
77 ysd->dom_socket = -1;
78 ysd->dom_vers = -1;
81 try = 0;
85 try++;
86 if (try > MAXTRIES)
88 if (is_new)
89 free (ysd);
90 return YPERR_YPBIND;
93 if (ysd->dom_vers == -1)
95 if(ysd->dom_client)
97 clnt_destroy(ysd->dom_client);
98 ysd->dom_client = NULL;
99 ysd->dom_socket = -1;
101 memset (&clnt_saddr, '\0', sizeof clnt_saddr);
102 clnt_saddr.sin_family = AF_INET;
103 clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
104 clnt_sock = RPC_ANYSOCK;
105 client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
106 &clnt_sock, 0, 0);
107 if (client == NULL)
109 if (is_new)
110 free (ysd);
111 return YPERR_YPBIND;
114 ** Check the port number -- should be < IPPORT_RESERVED.
115 ** If not, it's possible someone has registered a bogus
116 ** ypbind with the portmapper and is trying to trick us.
118 if (ntohs(clnt_saddr.sin_port) >= IPPORT_RESERVED)
120 clnt_destroy(client);
121 if (is_new)
122 free(ysd);
123 return(YPERR_YPBIND);
126 if (clnt_call (client, YPBINDPROC_DOMAIN,
127 (xdrproc_t) xdr_domainname, (caddr_t) &domain,
128 (xdrproc_t) xdr_ypbind_resp,
129 (caddr_t) &ypbr, TIMEOUT) != RPC_SUCCESS)
131 clnt_destroy (client);
132 if (is_new)
133 free (ysd);
134 return YPERR_YPBIND;
137 clnt_destroy (client);
138 if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
140 switch (ypbr.ypbind_resp_u.ypbind_error)
142 case YPBIND_ERR_ERR:
143 fputs (_("YPBINDPROC_DOMAIN: Internal error\n"), stderr);
144 break;
145 case YPBIND_ERR_NOSERV:
146 fprintf (stderr,
147 _("YPBINDPROC_DOMAIN: No server for domain %s\n"),
148 domain);
149 break;
150 case YPBIND_ERR_RESC:
151 fputs (_("YPBINDPROC_DOMAIN: Resource allocation failure\n"),
152 stderr);
153 break;
154 default:
155 fputs (_("YPBINDPROC_DOMAIN: Unknown error\n"), stderr);
156 break;
158 if (is_new)
159 free (ysd);
160 return YPERR_DOMAIN;
162 memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
163 ysd->dom_server_addr.sin_family = AF_INET;
164 memcpy (&ysd->dom_server_addr.sin_port,
165 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
166 sizeof (ysd->dom_server_addr.sin_port));
167 memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
168 ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
169 sizeof (ysd->dom_server_addr.sin_addr.s_addr));
170 ysd->dom_vers = YPVERS;
171 strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
172 ysd->dom_domain[YPMAXDOMAIN] = '\0';
175 if (ysd->dom_client)
176 clnt_destroy (ysd->dom_client);
177 ysd->dom_socket = RPC_ANYSOCK;
178 ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
179 TIMEOUT, &ysd->dom_socket);
180 if (ysd->dom_client == NULL)
181 ysd->dom_vers = -1;
184 while (ysd->dom_client == NULL);
186 /* If the program exists, close the socket */
187 if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
188 perror (_("fcntl: F_SETFD"));
190 if (is_new)
192 ysd->dom_pnext = __ypbindlist;
193 __ypbindlist = ysd;
196 if (NULL != ypdb)
197 *ypdb = ysd;
199 return YPERR_SUCCESS;
202 static void
203 __yp_unbind (dom_binding *ydb)
205 clnt_destroy (ydb->dom_client);
206 ydb->dom_client = NULL;
207 ydb->dom_socket = -1;
210 static int
211 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
212 caddr_t req, xdrproc_t xres, caddr_t resp)
214 dom_binding *ydb = NULL;
215 int try, result;
217 try = 0;
218 result = YPERR_YPERR;
220 while (try < MAXTRIES && result != RPC_SUCCESS)
222 __libc_lock_lock (ypbindlist_lock);
224 if (__yp_bind (domain, &ydb) != 0)
226 __libc_lock_unlock (ypbindlist_lock);
227 return YPERR_DOMAIN;
230 result = clnt_call (ydb->dom_client, prog,
231 xargs, req, xres, resp, TIMEOUT);
233 if (result != RPC_SUCCESS)
235 clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
236 ydb->dom_vers = -1;
237 __yp_unbind (ydb);
238 result = YPERR_RPC;
241 __libc_lock_unlock (ypbindlist_lock);
243 try++;
246 return result;
250 yp_bind (const char *indomain)
252 int status;
254 __libc_lock_lock (ypbindlist_lock);
256 status = __yp_bind (indomain, NULL);
258 __libc_lock_unlock (ypbindlist_lock);
260 return status;
263 void
264 yp_unbind (const char *indomain)
266 dom_binding *ydbptr, *ydbptr2;
268 __libc_lock_lock (ypbindlist_lock);
270 ydbptr2 = NULL;
271 ydbptr = __ypbindlist;
272 while (ydbptr != NULL)
274 if (strcmp (ydbptr->dom_domain, indomain) == 0)
276 dom_binding *work;
278 work = ydbptr;
279 if (ydbptr2 == NULL)
280 __ypbindlist = __ypbindlist->dom_pnext;
281 else
282 ydbptr2 = ydbptr->dom_pnext;
283 __yp_unbind (work);
284 free (work);
285 break;
287 ydbptr2 = ydbptr;
288 ydbptr = ydbptr->dom_pnext;
291 __libc_lock_unlock (ypbindlist_lock);
293 return;
296 __libc_lock_define_initialized (static, domainname_lock)
299 yp_get_default_domain (char **outdomain)
301 int result = YPERR_SUCCESS;;
302 *outdomain = NULL;
304 __libc_lock_lock (domainname_lock);
306 if (__ypdomainname[0] == '\0')
308 if (getdomainname (__ypdomainname, MAXHOSTNAMELEN))
309 result = YPERR_NODOM;
310 else
311 *outdomain = __ypdomainname;
313 else
314 *outdomain = __ypdomainname;
316 __libc_lock_unlock (domainname_lock);
318 return result;
322 __yp_check (char **domain)
324 char *unused;
326 if (__ypdomainname[0] == '\0')
327 if (yp_get_default_domain (&unused))
328 return 0;
329 else if (strcmp (__ypdomainname, "(none)") == 0)
330 return 0;
332 if (domain)
333 *domain = __ypdomainname;
335 if (yp_bind (__ypdomainname) == 0)
336 return 1;
337 return 0;
341 yp_match (const char *indomain, const char *inmap, const char *inkey,
342 const int inkeylen, char **outval, int *outvallen)
344 ypreq_key req;
345 ypresp_val resp;
346 int result;
348 if (indomain == NULL || indomain[0] == '\0' ||
349 inmap == NULL || inmap[0] == '\0' ||
350 inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
351 return YPERR_BADARGS;
353 req.domain = (char *) indomain;
354 req.map = (char *) inmap;
355 req.key.keydat_val = (char *) inkey;
356 req.key.keydat_len = inkeylen;
358 *outval = NULL;
359 *outvallen = 0;
360 memset (&resp, '\0', sizeof (resp));
362 result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
363 (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
364 (caddr_t) & resp);
366 if (result != RPC_SUCCESS)
367 return result;
368 if (resp.stat != YP_TRUE)
369 return ypprot_err (resp.stat);
371 *outvallen = resp.val.valdat_len;
372 *outval = malloc (*outvallen + 1);
373 memcpy (*outval, resp.val.valdat_val, *outvallen);
374 (*outval)[*outvallen] = '\0';
376 xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
378 return YPERR_SUCCESS;
382 yp_first (const char *indomain, const char *inmap, char **outkey,
383 int *outkeylen, char **outval, int *outvallen)
385 ypreq_nokey req;
386 ypresp_key_val resp;
387 int result;
389 if (indomain == NULL || indomain[0] == '\0' ||
390 inmap == NULL || inmap[0] == '\0')
391 return YPERR_BADARGS;
393 req.domain = (char *) indomain;
394 req.map = (char *) inmap;
396 *outkey = *outval = NULL;
397 *outkeylen = *outvallen = 0;
398 memset (&resp, '\0', sizeof (resp));
400 result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
401 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
402 (caddr_t) & resp);
404 if (result != RPC_SUCCESS)
405 return result;
406 if (resp.stat != YP_TRUE)
407 return ypprot_err (resp.stat);
409 *outkeylen = resp.key.keydat_len;
410 *outkey = malloc (*outkeylen + 1);
411 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
412 (*outkey)[*outkeylen] = '\0';
413 *outvallen = resp.val.valdat_len;
414 *outval = malloc (*outvallen + 1);
415 memcpy (*outval, resp.val.valdat_val, *outvallen);
416 (*outval)[*outvallen] = '\0';
418 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
420 return YPERR_SUCCESS;
424 yp_next (const char *indomain, const char *inmap, const char *inkey,
425 const int inkeylen, char **outkey, int *outkeylen, char **outval,
426 int *outvallen)
428 ypreq_key req;
429 ypresp_key_val resp;
430 int result;
432 if (indomain == NULL || indomain[0] == '\0' ||
433 inmap == NULL || inmap[0] == '\0' ||
434 inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
435 return YPERR_BADARGS;
437 req.domain = (char *) indomain;
438 req.map = (char *) inmap;
439 req.key.keydat_val = (char *) inkey;
440 req.key.keydat_len = inkeylen;
442 *outkey = *outval = NULL;
443 *outkeylen = *outvallen = 0;
444 memset (&resp, '\0', sizeof (resp));
446 result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
447 (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
448 (caddr_t) & resp);
450 if (result != RPC_SUCCESS)
451 return result;
452 if (resp.stat != YP_TRUE)
453 return ypprot_err (resp.stat);
455 *outkeylen = resp.key.keydat_len;
456 *outkey = malloc (*outkeylen + 1);
457 memcpy (*outkey, resp.key.keydat_val, *outkeylen);
458 (*outkey)[*outkeylen] = '\0';
459 *outvallen = resp.val.valdat_len;
460 *outval = malloc (*outvallen + 1);
461 memcpy (*outval, resp.val.valdat_val, *outvallen);
462 (*outval)[*outvallen] = '\0';
464 xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
466 return YPERR_SUCCESS;
470 yp_master (const char *indomain, const char *inmap, char **outname)
472 ypreq_nokey req;
473 ypresp_master resp;
474 int result;
476 if (indomain == NULL || indomain[0] == '\0' ||
477 inmap == NULL || inmap[0] == '\0')
478 return YPERR_BADARGS;
480 req.domain = (char *) indomain;
481 req.map = (char *) inmap;
483 memset (&resp, '\0', sizeof (ypresp_master));
485 result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
486 (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
488 if (result != RPC_SUCCESS)
489 return result;
490 if (resp.stat != YP_TRUE)
491 return ypprot_err (resp.stat);
493 *outname = strdup (resp.peer);
494 xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
496 return YPERR_SUCCESS;
500 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
502 struct ypreq_nokey req;
503 struct ypresp_order resp;
504 int result;
506 if (indomain == NULL || indomain[0] == '\0' ||
507 inmap == NULL || inmap == '\0')
508 return YPERR_BADARGS;
510 req.domain = (char *) indomain;
511 req.map = (char *) inmap;
513 memset (&resp, '\0', sizeof (resp));
515 result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
516 (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
518 if (result != RPC_SUCCESS)
519 return result;
520 if (resp.stat != YP_TRUE)
521 return ypprot_err (resp.stat);
523 *outorder = resp.ordernum;
524 xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
526 return YPERR_SUCCESS;
529 static void *ypall_data;
530 static int (*ypall_foreach) __P ((int status, char *key, int keylen,
531 char *val, int vallen, char *data));
533 static bool_t
534 __xdr_ypresp_all (XDR * xdrs, u_long * objp)
536 while (1)
538 struct ypresp_all resp;
540 memset (&resp, '\0', sizeof (struct ypresp_all));
541 if (!xdr_ypresp_all (xdrs, &resp))
543 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
544 *objp = YP_YPERR;
545 return (FALSE);
547 if (resp.more == 0)
549 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
550 *objp = YP_NOMORE;
551 return (FALSE);
554 switch (resp.ypresp_all_u.val.stat)
556 case YP_TRUE:
558 char key[resp.ypresp_all_u.val.key.keydat_len + 1];
559 char val[resp.ypresp_all_u.val.val.valdat_len + 1];
560 int keylen = resp.ypresp_all_u.val.key.keydat_len;
561 int vallen = resp.ypresp_all_u.val.val.valdat_len;
563 *objp = YP_TRUE;
564 memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
565 key[keylen] = '\0';
566 memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
567 val[vallen] = '\0';
568 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
569 if ((*ypall_foreach) (*objp, key, keylen,
570 val, vallen, ypall_data))
571 return TRUE;
573 break;
574 case YP_NOMORE:
575 *objp = YP_NOMORE;
576 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
577 return TRUE;
578 break;
579 default:
580 *objp = resp.ypresp_all_u.val.stat;
581 xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
582 return TRUE;
588 yp_all (const char *indomain, const char *inmap,
589 const struct ypall_callback *incallback)
591 struct ypreq_nokey req;
592 dom_binding *ydb;
593 int try, result;
594 struct sockaddr_in clnt_sin;
595 CLIENT *clnt;
596 unsigned long status;
597 int clnt_sock;
599 if (indomain == NULL || indomain[0] == '\0' ||
600 inmap == NULL || inmap == '\0')
601 return YPERR_BADARGS;
603 try = 0;
604 result = YPERR_YPERR;
606 while (try < MAXTRIES && result != RPC_SUCCESS)
608 __libc_lock_lock (ypbindlist_lock);
610 if (__yp_bind (indomain, &ydb) != 0)
612 __libc_lock_unlock (ypbindlist_lock);
613 return YPERR_DOMAIN;
616 /* YPPROC_ALL get its own TCP channel to ypserv */
617 clnt_sock = RPC_ANYSOCK;
618 clnt_sin = ydb->dom_server_addr;
619 clnt_sin.sin_port = 0;
620 clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
621 if (clnt == NULL)
623 puts ("yp_all: clnttcp_create failed");
624 __libc_lock_unlock (ypbindlist_lock);
625 return YPERR_PMAP;
627 req.domain = (char *) indomain;
628 req.map = (char *) inmap;
630 ypall_foreach = incallback->foreach;
631 ypall_data = (void *) incallback->data;
633 result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
634 (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
635 (caddr_t) &status, TIMEOUT);
637 if (result != RPC_SUCCESS)
639 clnt_perror (ydb->dom_client, "yp_all: clnt_call");
640 clnt_destroy (clnt);
641 __yp_unbind (ydb);
642 result = YPERR_RPC;
644 else
646 clnt_destroy (clnt);
647 result = YPERR_SUCCESS;
650 __libc_lock_unlock (ypbindlist_lock);
652 if (status != YP_NOMORE)
653 return ypprot_err (status);
654 try++;
657 return result;
661 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
663 struct ypresp_maplist resp;
664 int result;
666 if (indomain == NULL || indomain[0] == '\0')
667 return YPERR_BADARGS;
669 memset (&resp, '\0', sizeof (resp));
671 result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
672 (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
674 if (result != RPC_SUCCESS)
675 return result;
676 if (resp.stat != YP_TRUE)
677 return ypprot_err (resp.stat);
679 *outmaplist = resp.maps;
680 /* We give the list not free, this will be done by ypserv
681 xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
683 return YPERR_SUCCESS;
686 const char *
687 yperr_string (const int error)
689 switch (error)
691 case YPERR_SUCCESS:
692 return _("Success");
693 case YPERR_BADARGS:
694 return _("Request arguments bad");
695 case YPERR_RPC:
696 return _("RPC failure on NIS operation");
697 case YPERR_DOMAIN:
698 return _("Can't bind to server which serves this domain");
699 case YPERR_MAP:
700 return _("No such map in server's domain");
701 case YPERR_KEY:
702 return _("No such key in map");
703 case YPERR_YPERR:
704 return _("Internal NIS error");
705 case YPERR_RESRC:
706 return _("Local resource allocation failure");
707 case YPERR_NOMORE:
708 return _("No more records in map database");
709 case YPERR_PMAP:
710 return _("Can't communicate with portmapper");
711 case YPERR_YPBIND:
712 return _("Can't communicate with ypbind");
713 case YPERR_YPSERV:
714 return _("Can't communicate with ypserv");
715 case YPERR_NODOM:
716 return _("Local domain name not set");
717 case YPERR_BADDB:
718 return _("NIS map data base is bad");
719 case YPERR_VERS:
720 return _("NIS client/server version mismatch - can't supply service");
721 case YPERR_ACCESS:
722 return _("Permission denied");
723 case YPERR_BUSY:
724 return _("Database is busy");
726 return _("Unknown NIS error code");
730 ypprot_err (const int code)
732 switch (code)
734 case YP_TRUE:
735 return YPERR_SUCCESS;
736 case YP_NOMORE:
737 return YPERR_NOMORE;
738 case YP_FALSE:
739 return YPERR_YPERR;
740 case YP_NOMAP:
741 return YPERR_MAP;
742 case YP_NODOM:
743 return YPERR_DOMAIN;
744 case YP_NOKEY:
745 return YPERR_KEY;
746 case YP_BADOP:
747 return YPERR_YPERR;
748 case YP_BADDB:
749 return YPERR_BADDB;
750 case YP_YPERR:
751 return YPERR_YPERR;
752 case YP_BADARGS:
753 return YPERR_BADARGS;
754 case YP_VERS:
755 return YPERR_VERS;
757 return YPERR_YPERR;
760 const char *
761 ypbinderr_string (const int error)
763 switch (error)
765 case 0:
766 return _("Success");
767 case YPBIND_ERR_ERR:
768 return _("Internal ypbind error");
769 case YPBIND_ERR_NOSERV:
770 return _("Domain not bound");
771 case YPBIND_ERR_RESC:
772 return _("System resource allocation failure");
773 default:
774 return _("Unknown ypbind error");
779 #define WINDOW 60
782 yp_update (char *domain, char *map, unsigned ypop,
783 char *key, int keylen, char *data, int datalen)
785 #if defined (HAVE_SECURE_RPC)
786 union
788 ypupdate_args update_args;
789 ypdelete_args delete_args;
791 args;
792 xdrproc_t xdr_argument;
793 unsigned res = 0;
794 CLIENT *clnt;
795 char *master;
796 struct sockaddr saddr;
797 char servername[MAXNETNAMELEN + 1];
798 int r;
800 if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
801 return YPERR_BADARGS;
803 args.update_args.mapname = map;
804 args.update_args.key.yp_buf_len = keylen;
805 args.update_args.key.yp_buf_val = key;
806 args.update_args.datum.yp_buf_len = datalen;
807 args.update_args.datum.yp_buf_val = data;
809 if ((r = yp_master (domain, map, &master)) != 0)
810 return r;
812 if (!host2netname (servername, master, domain))
814 fputs (_("yp_update: cannot convert host to netname\n"), stderr);
815 return YPERR_YPERR;
818 if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
820 clnt_pcreateerror ("yp_update: clnt_create");
821 return YPERR_RPC;
824 if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
826 fputs (_("yp_update: cannot get server address\n"), stderr);
827 return YPERR_RPC;
830 switch (ypop)
832 case YPOP_CHANGE:
833 case YPOP_INSERT:
834 case YPOP_STORE:
835 xdr_argument = (xdrproc_t) xdr_ypupdate_args;
836 break;
837 case YPOP_DELETE:
838 xdr_argument = (xdrproc_t) xdr_ypdelete_args;
839 break;
840 default:
841 return YPERR_BADARGS;
842 break;
845 clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
847 if (clnt->cl_auth == NULL)
848 clnt->cl_auth = authunix_create_default ();
850 again:
851 r = clnt_call (clnt, ypop, xdr_argument, (caddr_t) &args,
852 (xdrproc_t) xdr_u_int, (caddr_t) &res, TIMEOUT);
854 if (r == RPC_AUTHERROR)
856 if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
858 clnt->cl_auth = authunix_create_default ();
859 goto again;
861 else
862 return YPERR_ACCESS;
864 if (r != RPC_SUCCESS)
866 clnt_perror (clnt, "yp_update: clnt_call");
867 return YPERR_RPC;
869 return res;
870 #else
871 return YPERR_YPERR;
872 #endif