update from main arcive 961210
[kopensolaris-gnu/glibc.git] / nis / ypclnt.c
1 /* Copyright (C) 1996 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.
4
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.
9
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.
14
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.  */
19
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>
27
28 struct dom_binding
29   {
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;
36   };
37 typedef struct dom_binding dom_binding;
38
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;
44
45 static int
46 __yp_bind (char *domain, dom_binding ** ypdb)
47 {
48   struct sockaddr_in clnt_saddr;
49   struct ypbind_resp ypbr;
50   dom_binding *ysd;
51   int clnt_sock;
52   CLIENT *client;
53   int is_new = 0;
54   int try;
55
56   if (ypdb != NULL)
57     *ypdb = NULL;
58
59   if ((domain == NULL) || (strlen (domain) == 0))
60     return YPERR_BADARGS;
61
62   ysd = __ypbindlist;
63   while (ysd != NULL)
64     {
65       if (strcmp (domain, ysd->dom_domain) == 0)
66         break;
67       ysd = ysd->dom_pnext;
68     }
69
70   if (ysd == NULL)
71     {
72       is_new = 1;
73       ysd = (dom_binding *) malloc (sizeof *ysd);
74       memset (ysd, '\0', sizeof *ysd);
75       ysd->dom_socket = -1;
76       ysd->dom_vers = -1;
77     }
78
79   try = 0;
80
81   do
82     {
83       try++;
84       if (try > MAXTRIES)
85         {
86           if (is_new)
87             free (ysd);
88           return YPERR_YPBIND;
89         }
90
91       if (ysd->dom_vers == -1)
92         {
93           if(ysd->dom_client)
94             {
95               clnt_destroy(ysd->dom_client);
96               ysd->dom_client = NULL;
97               ysd->dom_socket = -1;
98             }
99           memset (&clnt_saddr, '\0', sizeof clnt_saddr);
100           clnt_saddr.sin_family = AF_INET;
101           clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
102           clnt_sock = RPC_ANYSOCK;
103           client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
104                                    &clnt_sock, 0, 0);
105           if (client == NULL)
106             {
107               if (is_new)
108                 free (ysd);
109               return YPERR_YPBIND;
110             }
111           /*
112           ** Check the port number -- should be < IPPORT_RESERVED.
113           ** If not, it's possible someone has registered a bogus
114           ** ypbind with the portmapper and is trying to trick us.
115           */
116           if (ntohs(clnt_saddr.sin_port) >= IPPORT_RESERVED)
117             {
118               clnt_destroy(client);
119               if (is_new)
120                 free(ysd);
121               return(YPERR_YPBIND);
122             }
123
124           if (clnt_call (client, YPBINDPROC_DOMAIN,
125                          (xdrproc_t) xdr_domainname, &domain,
126                          (xdrproc_t) xdr_ypbind_resp,
127                          &ypbr, TIMEOUT) != RPC_SUCCESS)
128             {
129               clnt_destroy (client);
130               if (is_new)
131                 free (ysd);
132               return YPERR_YPBIND;
133             }
134
135           clnt_destroy (client);
136           if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
137             {
138               switch (ypbr.ypbind_resp_u.ypbind_error)
139                 {
140                 case YPBIND_ERR_ERR:
141                   fputs (_("YPBINDPROC_DOMAIN: Internal error\n"), stderr);
142                   break;
143                 case YPBIND_ERR_NOSERV:
144                   fprintf (stderr,
145                            _("YPBINDPROC_DOMAIN: No server for domain %s\n"),
146                            domain);
147                   break;
148                 case YPBIND_ERR_RESC:
149                   fputs (_("YPBINDPROC_DOMAIN: Resource allocation failure\n"),
150                          stderr);
151                   break;
152                 default:
153                   fputs (_("YPBINDPROC_DOMAIN: Unknown error\n"), stderr);
154                   break;
155                 }
156               if (is_new)
157                 free (ysd);
158               return YPERR_DOMAIN;
159             }
160           memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
161           ysd->dom_server_addr.sin_family = AF_INET;
162           memcpy (&ysd->dom_server_addr.sin_port,
163                   ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
164                   sizeof (ysd->dom_server_addr.sin_port));
165           memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
166                   ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
167                   sizeof (ysd->dom_server_addr.sin_addr.s_addr));
168           ysd->dom_vers = YPVERS;
169           strcpy (ysd->dom_domain, domain);
170         }
171
172       if (ysd->dom_client)
173         clnt_destroy (ysd->dom_client);
174       ysd->dom_socket = RPC_ANYSOCK;
175       ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
176                                         TIMEOUT, &ysd->dom_socket);
177       if (ysd->dom_client == NULL)
178         ysd->dom_vers = -1;
179
180     }
181   while (ysd->dom_client == NULL);
182
183   /* If the program exists, close the socket */
184   if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
185     perror (_("fcntl: F_SETFD"));
186
187   if (is_new)
188     {
189       ysd->dom_pnext = __ypbindlist;
190       __ypbindlist = ysd;
191     }
192
193   if (NULL != ypdb)
194     *ypdb = ysd;
195
196   return YPERR_SUCCESS;
197 }
198
199 static void
200 __yp_unbind (dom_binding *ydb)
201 {
202   clnt_destroy (ydb->dom_client);
203   ydb->dom_client = NULL;
204   ydb->dom_socket = -1;
205 }
206
207 static int
208 do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
209            caddr_t req, xdrproc_t xres, caddr_t resp)
210 {
211   dom_binding *ydb = NULL;
212   int try, result;
213
214   try = 0;
215   result = YPERR_YPERR;
216
217   while (try < MAXTRIES && result != RPC_SUCCESS)
218     {
219       __libc_lock_lock (ypbindlist_lock);
220
221       if (__yp_bind (domain, &ydb) != 0)
222         {
223           __libc_lock_unlock (ypbindlist_lock);
224           return YPERR_DOMAIN;
225         }
226
227       result = clnt_call (ydb->dom_client, prog,
228                           xargs, req, xres, resp, TIMEOUT);
229
230       if (result != RPC_SUCCESS)
231         {
232           clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
233           ydb->dom_vers = -1;
234           __yp_unbind (ydb);
235           result = YPERR_RPC;
236         }
237
238       __libc_lock_unlock (ypbindlist_lock);
239
240       try++;
241     }
242
243   return result;
244 }
245
246 int
247 yp_bind (const char *indomain)
248 {
249   int status;
250
251   __libc_lock_lock (ypbindlist_lock);
252
253   status = __yp_bind (indomain, NULL);
254
255   __libc_lock_unlock (ypbindlist_lock);
256
257   return status;
258 }
259
260 void
261 yp_unbind (const char *indomain)
262 {
263   dom_binding *ydbptr, *ydbptr2;
264
265   __libc_lock_lock (ypbindlist_lock);
266
267   ydbptr2 = NULL;
268   ydbptr = __ypbindlist;
269   while (ydbptr != NULL)
270     {
271       if (strcmp (ydbptr->dom_domain, indomain) == 0)
272         {
273           dom_binding *work;
274
275           work = ydbptr;
276           if (ydbptr2 == NULL)
277             __ypbindlist = __ypbindlist->dom_pnext;
278           else
279             ydbptr2 = ydbptr->dom_pnext;
280           __yp_unbind (work);
281           free (work);
282           break;
283         }
284       ydbptr2 = ydbptr;
285       ydbptr = ydbptr->dom_pnext;
286     }
287
288   __libc_lock_unlock (ypbindlist_lock);
289
290   return;
291 }
292
293 __libc_lock_define_initialized (static, domainname_lock)
294
295 int
296 yp_get_default_domain (char **outdomain)
297 {
298   int result = YPERR_SUCCESS;;
299   *outdomain = NULL;
300
301   __libc_lock_lock (domainname_lock);
302
303   if (__ypdomainname[0] == '\0')
304     {
305       if (getdomainname (__ypdomainname, MAXHOSTNAMELEN))
306         result = YPERR_NODOM;
307       else
308         *outdomain = __ypdomainname;
309     }
310   else
311     *outdomain = __ypdomainname;
312
313   __libc_lock_unlock (domainname_lock);
314
315   return result;
316 }
317
318 int
319 __yp_check (char **domain)
320 {
321   char *unused;
322
323   if (__ypdomainname[0] == '\0')
324     if (yp_get_default_domain (&unused))
325       return 0;
326     else if (strcmp (__ypdomainname, "(none)") == 0)
327       return 0;
328
329   if (domain)
330     *domain = __ypdomainname;
331
332   if (yp_bind (__ypdomainname) == 0)
333     return 1;
334   return 0;
335 }
336
337 int
338 yp_match (const char *indomain, const char *inmap, const char *inkey,
339           const int inkeylen, char **outval, int *outvallen)
340 {
341   ypreq_key req;
342   ypresp_val resp;
343   int result;
344
345   if (indomain == NULL || indomain[0] == '\0' ||
346       inmap == NULL || inmap[0] == '\0' ||
347       inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
348     return YPERR_BADARGS;
349
350   req.domain = indomain;
351   req.map = inmap;
352   req.key.keydat_val = inkey;
353   req.key.keydat_len = inkeylen;
354
355   *outval = NULL;
356   *outvallen = 0;
357   memset (&resp, '\0', sizeof (resp));
358
359   result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
360                       (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
361                       (caddr_t) & resp);
362
363   if (result != RPC_SUCCESS)
364     return result;
365   if (resp.stat != YP_TRUE)
366     return ypprot_err (resp.stat);
367
368   *outvallen = resp.val.valdat_len;
369   *outval = malloc (*outvallen + 1);
370   memcpy (*outval, resp.val.valdat_val, *outvallen);
371   (*outval)[*outvallen] = '\0';
372
373   xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
374
375   return YPERR_SUCCESS;
376 }
377
378 int
379 yp_first (const char *indomain, const char *inmap, char **outkey,
380           int *outkeylen, char **outval, int *outvallen)
381 {
382   ypreq_nokey req;
383   ypresp_key_val resp;
384   int result;
385
386   if (indomain == NULL || indomain[0] == '\0' ||
387       inmap == NULL || inmap[0] == '\0')
388     return YPERR_BADARGS;
389
390   req.domain = indomain;
391   req.map = inmap;
392
393   *outkey = *outval = NULL;
394   *outkeylen = *outvallen = 0;
395   memset (&resp, '\0', sizeof (resp));
396
397   result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
398                       (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
399                       (caddr_t) & resp);
400
401   if (result != RPC_SUCCESS)
402     return result;
403   if (resp.stat != YP_TRUE)
404     return ypprot_err (resp.stat);
405
406   *outkeylen = resp.key.keydat_len;
407   *outkey = malloc (*outkeylen + 1);
408   memcpy (*outkey, resp.key.keydat_val, *outkeylen);
409   (*outkey)[*outkeylen] = '\0';
410   *outvallen = resp.val.valdat_len;
411   *outval = malloc (*outvallen + 1);
412   memcpy (*outval, resp.val.valdat_val, *outvallen);
413   (*outval)[*outvallen] = '\0';
414
415   xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
416
417   return YPERR_SUCCESS;
418 }
419
420 int
421 yp_next (const char *indomain, const char *inmap, const char *inkey,
422          const int inkeylen, char **outkey, int *outkeylen, char **outval,
423          int *outvallen)
424 {
425   ypreq_key req;
426   ypresp_key_val resp;
427   int result;
428
429   if (indomain == NULL || indomain[0] == '\0' ||
430       inmap == NULL || inmap[0] == '\0' ||
431       inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
432     return YPERR_BADARGS;
433
434   req.domain = indomain;
435   req.map = inmap;
436   req.key.keydat_val = inkey;
437   req.key.keydat_len = inkeylen;
438
439   *outkey = *outval = NULL;
440   *outkeylen = *outvallen = 0;
441   memset (&resp, '\0', sizeof (resp));
442
443   result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
444                       (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
445                       (caddr_t) & resp);
446
447   if (result != RPC_SUCCESS)
448     return result;
449   if (resp.stat != YP_TRUE)
450     return ypprot_err (resp.stat);
451
452   *outkeylen = resp.key.keydat_len;
453   *outkey = malloc (*outkeylen + 1);
454   memcpy (*outkey, resp.key.keydat_val, *outkeylen);
455   (*outkey)[*outkeylen] = '\0';
456   *outvallen = resp.val.valdat_len;
457   *outval = malloc (*outvallen + 1);
458   memcpy (*outval, resp.val.valdat_val, *outvallen);
459   (*outval)[*outvallen] = '\0';
460
461   xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
462
463   return YPERR_SUCCESS;
464 }
465
466 int
467 yp_master (const char *indomain, const char *inmap, char **outname)
468 {
469   ypreq_nokey req;
470   ypresp_master resp;
471   int result;
472
473   if (indomain == NULL || indomain[0] == '\0' ||
474       inmap == NULL || inmap[0] == '\0')
475     return YPERR_BADARGS;
476
477   req.domain = indomain;
478   req.map = inmap;
479
480   memset (&resp, '\0', sizeof (ypresp_master));
481
482   result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
483           (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
484
485   if (result != RPC_SUCCESS)
486     return result;
487   if (resp.stat != YP_TRUE)
488     return ypprot_err (resp.stat);
489
490   *outname = strdup (resp.peer);
491   xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
492
493   return YPERR_SUCCESS;
494 }
495
496 int
497 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
498 {
499   struct ypreq_nokey req;
500   struct ypresp_order resp;
501   int result;
502
503   if (indomain == NULL || indomain[0] == '\0' ||
504       inmap == NULL || inmap == '\0')
505     return YPERR_BADARGS;
506
507   req.domain = indomain;
508   req.map = inmap;
509
510   memset (&resp, '\0', sizeof (resp));
511
512   result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
513            (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
514
515   if (result != RPC_SUCCESS)
516     return result;
517   if (resp.stat != YP_TRUE)
518     return ypprot_err (resp.stat);
519
520   *outorder = resp.ordernum;
521   xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
522
523   return YPERR_SUCCESS;
524 }
525
526 static void *ypall_data;
527 static int (*ypall_foreach) ();
528
529 static bool_t
530 __xdr_ypresp_all (XDR * xdrs, u_long * objp)
531 {
532   while (1)
533     {
534       struct ypresp_all resp;
535
536       memset (&resp, '\0', sizeof (struct ypresp_all));
537       if (!xdr_ypresp_all (xdrs, &resp))
538         {
539           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
540           *objp = YP_YPERR;
541           return (FALSE);
542         }
543       if (resp.more == 0)
544         {
545           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
546           *objp = YP_NOMORE;
547           return (FALSE);
548         }
549
550       switch (resp.ypresp_all_u.val.stat)
551         {
552         case YP_TRUE:
553           {
554             char key[resp.ypresp_all_u.val.key.keydat_len + 1];
555             char val[resp.ypresp_all_u.val.val.valdat_len + 1];
556             int keylen = resp.ypresp_all_u.val.key.keydat_len;
557             int vallen = resp.ypresp_all_u.val.val.valdat_len;
558
559             *objp = YP_TRUE;
560             memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
561             key[keylen] = '\0';
562             memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
563             val[vallen] = '\0';
564             xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
565             if ((*ypall_foreach) (*objp, key, keylen,
566                                   val, vallen, ypall_data))
567               return TRUE;
568           }
569           break;
570         case YP_NOMORE:
571           *objp = YP_NOMORE;
572           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
573           return TRUE;
574           break;
575         default:
576           *objp = resp.ypresp_all_u.val.stat;
577           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
578           return TRUE;
579         }
580     }
581 }
582
583 int
584 yp_all (const char *indomain, const char *inmap,
585         const struct ypall_callback *incallback)
586 {
587   struct ypreq_nokey req;
588   dom_binding *ydb;
589   int try, result;
590   struct sockaddr_in clnt_sin;
591   CLIENT *clnt;
592   unsigned long status;
593   int clnt_sock;
594
595   if (indomain == NULL || indomain[0] == '\0' ||
596       inmap == NULL || inmap == '\0')
597     return YPERR_BADARGS;
598
599   try = 0;
600   result = YPERR_YPERR;
601
602   while (try < MAXTRIES && result != RPC_SUCCESS)
603     {
604       __libc_lock_lock (ypbindlist_lock);
605
606       if (__yp_bind (indomain, &ydb) != 0)
607         {
608           __libc_lock_unlock (ypbindlist_lock);
609           return YPERR_DOMAIN;
610         }
611
612       /* YPPROC_ALL get its own TCP channel to ypserv */
613       clnt_sock = RPC_ANYSOCK;
614       clnt_sin = ydb->dom_server_addr;
615       clnt_sin.sin_port = 0;
616       clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
617       if (clnt == NULL)
618         {
619           puts ("yp_all: clnttcp_create failed");
620           __libc_lock_unlock (ypbindlist_lock);
621           return YPERR_PMAP;
622         }
623       req.domain = indomain;
624       req.map = inmap;
625
626       ypall_foreach = incallback->foreach;
627       ypall_data = (void *) incallback->data;
628
629       result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey, &req,
630                           (xdrproc_t) __xdr_ypresp_all, &status, TIMEOUT);
631
632       if (result != RPC_SUCCESS)
633         {
634           clnt_perror (ydb->dom_client, "yp_all: clnt_call");
635           clnt_destroy (clnt);
636           __yp_unbind (ydb);
637           result = YPERR_RPC;
638         }
639       else
640         {
641           clnt_destroy (clnt);
642           result = YPERR_SUCCESS;
643         }
644
645       __libc_lock_unlock (ypbindlist_lock);
646
647       if (status != YP_NOMORE)
648         return ypprot_err (status);
649       try++;
650     }
651
652   return result;
653 }
654
655 int
656 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
657 {
658   struct ypresp_maplist resp;
659   int result;
660
661   if (indomain == NULL || indomain[0] == '\0')
662     return YPERR_BADARGS;
663
664   memset (&resp, '\0', sizeof (resp));
665
666   result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
667     (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
668
669   if (result != RPC_SUCCESS)
670     return result;
671   if (resp.stat != YP_TRUE)
672     return ypprot_err (resp.stat);
673
674   *outmaplist = resp.maps;
675   /* We give the list not free, this will be done by ypserv
676      xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
677
678   return YPERR_SUCCESS;
679 }
680
681 const char *
682 yperr_string (const int error)
683 {
684   switch (error)
685     {
686     case YPERR_SUCCESS:
687       return _("Success");
688     case YPERR_BADARGS:
689       return _("Request arguments bad");
690     case YPERR_RPC:
691       return _("RPC failure on NIS operation");
692     case YPERR_DOMAIN:
693       return _("Can't bind to server which serves this domain");
694     case YPERR_MAP:
695       return _("No such map in server's domain");
696     case YPERR_KEY:
697       return _("No such key in map");
698     case YPERR_YPERR:
699       return _("Internal NIS error");
700     case YPERR_RESRC:
701       return _("Local resource allocation failure");
702     case YPERR_NOMORE:
703       return _("No more records in map database");
704     case YPERR_PMAP:
705       return _("Can't communicate with portmapper");
706     case YPERR_YPBIND:
707       return _("Can't communicate with ypbind");
708     case YPERR_YPSERV:
709       return _("Can't communicate with ypserv");
710     case YPERR_NODOM:
711       return _("Local domain name not set");
712     case YPERR_BADDB:
713       return _("NIS map data base is bad");
714     case YPERR_VERS:
715       return _("NIS client/server version mismatch - can't supply service");
716     case YPERR_ACCESS:
717       return _("Permission denied");
718     case YPERR_BUSY:
719       return _("Database is busy");
720     }
721   return _("Unknown NIS error code");
722 }
723
724 int
725 ypprot_err (const int code)
726 {
727   switch (code)
728     {
729     case YP_TRUE:
730       return YPERR_SUCCESS;
731     case YP_NOMORE:
732       return YPERR_NOMORE;
733     case YP_FALSE:
734       return YPERR_YPERR;
735     case YP_NOMAP:
736       return YPERR_MAP;
737     case YP_NODOM:
738       return YPERR_DOMAIN;
739     case YP_NOKEY:
740       return YPERR_KEY;
741     case YP_BADOP:
742       return YPERR_YPERR;
743     case YP_BADDB:
744       return YPERR_BADDB;
745     case YP_YPERR:
746       return YPERR_YPERR;
747     case YP_BADARGS:
748       return YPERR_BADARGS;
749     case YP_VERS:
750       return YPERR_VERS;
751     }
752   return YPERR_YPERR;
753 }
754
755 const char *
756 ypbinderr_string (const int error)
757 {
758   switch (error)
759     {
760     case 0:
761       return _("Success");
762     case YPBIND_ERR_ERR:
763       return _("Internal ypbind error");
764     case YPBIND_ERR_NOSERV:
765       return _("Domain not bound");
766     case YPBIND_ERR_RESC:
767       return _("System resource allocation failure");
768     default:
769       return _("Unknown ypbind error");
770     }
771 }
772
773
774 #define WINDOW 60
775
776 int
777 yp_update (char *domain, char *map, unsigned ypop,
778            char *key, int keylen, char *data, int datalen)
779 {
780 #if 0
781   union
782     {
783       ypupdate_args update_args;
784       ypdelete_args delete_args;
785     }
786   args;
787   xdrproc_t xdr_argument;
788   unsigned res = 0;
789   CLIENT *clnt;
790   char *master;
791   struct sockaddr saddr;
792   char servername[MAXNETNAMELEN + 1];
793   int r;
794
795   if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
796     return YPERR_BADARGS;
797
798   args.update_args.mapname = map;
799   args.update_args.key.yp_buf_len = keylen;
800   args.update_args.key.yp_buf_val = key;
801   args.update_args.datum.yp_buf_len = datalen;
802   args.update_args.datum.yp_buf_val = data;
803
804   if ((r = yp_master (domain, map, &master)) != 0)
805     return r;
806
807   if (!host2netname (servername, master, domain))
808     {
809       fputs (_("yp_update: cannot convert host to netname\n"), stderr);
810       return YPERR_YPERR;
811     }
812
813   if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
814     {
815       clnt_pcreateerror ("yp_update: clnt_create");
816       return YPERR_RPC;
817     }
818
819   if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
820     {
821       fputs (_("yp_update: cannot get server address\n"), stderr);
822       return YPERR_RPC;
823     }
824
825   switch (ypop)
826     {
827     case YPOP_CHANGE:
828     case YPOP_INSERT:
829     case YPOP_STORE:
830       xdr_argument = (xdrproc_t) xdr_ypupdate_args;
831       break;
832     case YPOP_DELETE:
833       xdr_argument = (xdrproc_t) xdr_ypdelete_args;
834       break;
835     default:
836       return YPERR_BADARGS;
837       break;
838     }
839
840   clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
841
842   if (clnt->cl_auth == NULL)
843     clnt->cl_auth = authunix_create_default ();
844
845 again:
846   r = clnt_call (clnt, ypop, xdr_argument, &args,
847                  (xdrproc_t) xdr_u_int, &res, TIMEOUT);
848
849   if (r == RPC_AUTHERROR)
850     {
851       if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
852         {
853           clnt->cl_auth = authunix_create_default ();
854           goto again;
855         }
856       else
857         return YPERR_ACCESS;
858     }
859   if (r != RPC_SUCCESS)
860     {
861       clnt_perror (clnt, "yp_update: clnt_call");
862       return YPERR_RPC;
863     }
864   return res;
865 #else
866   return YPERR_YPERR;
867 #endif
868 }