update from main archive 961214
[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 extern void xdr_free (xdrproc_t proc, char *objp);
46
47 static int
48 __yp_bind (const char *domain, dom_binding ** ypdb)
49 {
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;
57
58   if (ypdb != NULL)
59     *ypdb = NULL;
60
61   if ((domain == NULL) || (strlen (domain) == 0))
62     return YPERR_BADARGS;
63
64   ysd = __ypbindlist;
65   while (ysd != NULL)
66     {
67       if (strcmp (domain, ysd->dom_domain) == 0)
68         break;
69       ysd = ysd->dom_pnext;
70     }
71
72   if (ysd == NULL)
73     {
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;
79     }
80
81   try = 0;
82
83   do
84     {
85       try++;
86       if (try > MAXTRIES)
87         {
88           if (is_new)
89             free (ysd);
90           return YPERR_YPBIND;
91         }
92
93       if (ysd->dom_vers == -1)
94         {
95           if(ysd->dom_client)
96             {
97               clnt_destroy(ysd->dom_client);
98               ysd->dom_client = NULL;
99               ysd->dom_socket = -1;
100             }
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)
108             {
109               if (is_new)
110                 free (ysd);
111               return YPERR_YPBIND;
112             }
113           /*
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.
117           */
118           if (ntohs(clnt_saddr.sin_port) >= IPPORT_RESERVED)
119             {
120               clnt_destroy(client);
121               if (is_new)
122                 free(ysd);
123               return(YPERR_YPBIND);
124             }
125
126           if (clnt_call (client, YPBINDPROC_DOMAIN,
127                          (xdrproc_t) xdr_domainname, &domain,
128                          (xdrproc_t) xdr_ypbind_resp,
129                          &ypbr, TIMEOUT) != RPC_SUCCESS)
130             {
131               clnt_destroy (client);
132               if (is_new)
133                 free (ysd);
134               return YPERR_YPBIND;
135             }
136
137           clnt_destroy (client);
138           if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
139             {
140               switch (ypbr.ypbind_resp_u.ypbind_error)
141                 {
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;
157                 }
158               if (is_new)
159                 free (ysd);
160               return YPERR_DOMAIN;
161             }
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           strcpy (ysd->dom_domain, domain);
172         }
173
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;
181
182     }
183   while (ysd->dom_client == NULL);
184
185   /* If the program exists, close the socket */
186   if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
187     perror (_("fcntl: F_SETFD"));
188
189   if (is_new)
190     {
191       ysd->dom_pnext = __ypbindlist;
192       __ypbindlist = ysd;
193     }
194
195   if (NULL != ypdb)
196     *ypdb = ysd;
197
198   return YPERR_SUCCESS;
199 }
200
201 static void
202 __yp_unbind (dom_binding *ydb)
203 {
204   clnt_destroy (ydb->dom_client);
205   ydb->dom_client = NULL;
206   ydb->dom_socket = -1;
207 }
208
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)
212 {
213   dom_binding *ydb = NULL;
214   int try, result;
215
216   try = 0;
217   result = YPERR_YPERR;
218
219   while (try < MAXTRIES && result != RPC_SUCCESS)
220     {
221       __libc_lock_lock (ypbindlist_lock);
222
223       if (__yp_bind (domain, &ydb) != 0)
224         {
225           __libc_lock_unlock (ypbindlist_lock);
226           return YPERR_DOMAIN;
227         }
228
229       result = clnt_call (ydb->dom_client, prog,
230                           xargs, req, xres, resp, TIMEOUT);
231
232       if (result != RPC_SUCCESS)
233         {
234           clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
235           ydb->dom_vers = -1;
236           __yp_unbind (ydb);
237           result = YPERR_RPC;
238         }
239
240       __libc_lock_unlock (ypbindlist_lock);
241
242       try++;
243     }
244
245   return result;
246 }
247
248 int
249 yp_bind (const char *indomain)
250 {
251   int status;
252
253   __libc_lock_lock (ypbindlist_lock);
254
255   status = __yp_bind (indomain, NULL);
256
257   __libc_lock_unlock (ypbindlist_lock);
258
259   return status;
260 }
261
262 void
263 yp_unbind (const char *indomain)
264 {
265   dom_binding *ydbptr, *ydbptr2;
266
267   __libc_lock_lock (ypbindlist_lock);
268
269   ydbptr2 = NULL;
270   ydbptr = __ypbindlist;
271   while (ydbptr != NULL)
272     {
273       if (strcmp (ydbptr->dom_domain, indomain) == 0)
274         {
275           dom_binding *work;
276
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;
285         }
286       ydbptr2 = ydbptr;
287       ydbptr = ydbptr->dom_pnext;
288     }
289
290   __libc_lock_unlock (ypbindlist_lock);
291
292   return;
293 }
294
295 __libc_lock_define_initialized (static, domainname_lock)
296
297 int
298 yp_get_default_domain (char **outdomain)
299 {
300   int result = YPERR_SUCCESS;;
301   *outdomain = NULL;
302
303   __libc_lock_lock (domainname_lock);
304
305   if (__ypdomainname[0] == '\0')
306     {
307       if (getdomainname (__ypdomainname, MAXHOSTNAMELEN))
308         result = YPERR_NODOM;
309       else
310         *outdomain = __ypdomainname;
311     }
312   else
313     *outdomain = __ypdomainname;
314
315   __libc_lock_unlock (domainname_lock);
316
317   return result;
318 }
319
320 int
321 __yp_check (char **domain)
322 {
323   char *unused;
324
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;
330
331   if (domain)
332     *domain = __ypdomainname;
333
334   if (yp_bind (__ypdomainname) == 0)
335     return 1;
336   return 0;
337 }
338
339 int
340 yp_match (const char *indomain, const char *inmap, const char *inkey,
341           const int inkeylen, char **outval, int *outvallen)
342 {
343   ypreq_key req;
344   ypresp_val resp;
345   int result;
346
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;
351
352   req.domain = (char *) indomain;
353   req.map = (char *) inmap;
354   req.key.keydat_val = (char *) inkey;
355   req.key.keydat_len = inkeylen;
356
357   *outval = NULL;
358   *outvallen = 0;
359   memset (&resp, '\0', sizeof (resp));
360
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);
364
365   if (result != RPC_SUCCESS)
366     return result;
367   if (resp.stat != YP_TRUE)
368     return ypprot_err (resp.stat);
369
370   *outvallen = resp.val.valdat_len;
371   *outval = malloc (*outvallen + 1);
372   memcpy (*outval, resp.val.valdat_val, *outvallen);
373   (*outval)[*outvallen] = '\0';
374
375   xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
376
377   return YPERR_SUCCESS;
378 }
379
380 int
381 yp_first (const char *indomain, const char *inmap, char **outkey,
382           int *outkeylen, char **outval, int *outvallen)
383 {
384   ypreq_nokey req;
385   ypresp_key_val resp;
386   int result;
387
388   if (indomain == NULL || indomain[0] == '\0' ||
389       inmap == NULL || inmap[0] == '\0')
390     return YPERR_BADARGS;
391
392   req.domain = (char *) indomain;
393   req.map = (char *) inmap;
394
395   *outkey = *outval = NULL;
396   *outkeylen = *outvallen = 0;
397   memset (&resp, '\0', sizeof (resp));
398
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);
402
403   if (result != RPC_SUCCESS)
404     return result;
405   if (resp.stat != YP_TRUE)
406     return ypprot_err (resp.stat);
407
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';
416
417   xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
418
419   return YPERR_SUCCESS;
420 }
421
422 int
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)
426 {
427   ypreq_key req;
428   ypresp_key_val resp;
429   int result;
430
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;
435
436   req.domain = (char *) indomain;
437   req.map = (char *) inmap;
438   req.key.keydat_val = (char *) inkey;
439   req.key.keydat_len = inkeylen;
440
441   *outkey = *outval = NULL;
442   *outkeylen = *outvallen = 0;
443   memset (&resp, '\0', sizeof (resp));
444
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);
448
449   if (result != RPC_SUCCESS)
450     return result;
451   if (resp.stat != YP_TRUE)
452     return ypprot_err (resp.stat);
453
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';
462
463   xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
464
465   return YPERR_SUCCESS;
466 }
467
468 int
469 yp_master (const char *indomain, const char *inmap, char **outname)
470 {
471   ypreq_nokey req;
472   ypresp_master resp;
473   int result;
474
475   if (indomain == NULL || indomain[0] == '\0' ||
476       inmap == NULL || inmap[0] == '\0')
477     return YPERR_BADARGS;
478
479   req.domain = (char *) indomain;
480   req.map = (char *) inmap;
481
482   memset (&resp, '\0', sizeof (ypresp_master));
483
484   result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
485           (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
486
487   if (result != RPC_SUCCESS)
488     return result;
489   if (resp.stat != YP_TRUE)
490     return ypprot_err (resp.stat);
491
492   *outname = strdup (resp.peer);
493   xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
494
495   return YPERR_SUCCESS;
496 }
497
498 int
499 yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
500 {
501   struct ypreq_nokey req;
502   struct ypresp_order resp;
503   int result;
504
505   if (indomain == NULL || indomain[0] == '\0' ||
506       inmap == NULL || inmap == '\0')
507     return YPERR_BADARGS;
508
509   req.domain = (char *) indomain;
510   req.map = (char *) inmap;
511
512   memset (&resp, '\0', sizeof (resp));
513
514   result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
515            (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
516
517   if (result != RPC_SUCCESS)
518     return result;
519   if (resp.stat != YP_TRUE)
520     return ypprot_err (resp.stat);
521
522   *outorder = resp.ordernum;
523   xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
524
525   return YPERR_SUCCESS;
526 }
527
528 static void *ypall_data;
529 static int (*ypall_foreach) ();
530
531 static bool_t
532 __xdr_ypresp_all (XDR * xdrs, u_long * objp)
533 {
534   while (1)
535     {
536       struct ypresp_all resp;
537
538       memset (&resp, '\0', sizeof (struct ypresp_all));
539       if (!xdr_ypresp_all (xdrs, &resp))
540         {
541           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
542           *objp = YP_YPERR;
543           return (FALSE);
544         }
545       if (resp.more == 0)
546         {
547           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
548           *objp = YP_NOMORE;
549           return (FALSE);
550         }
551
552       switch (resp.ypresp_all_u.val.stat)
553         {
554         case YP_TRUE:
555           {
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;
560
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;
570           }
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;
581         }
582     }
583 }
584
585 int
586 yp_all (const char *indomain, const char *inmap,
587         const struct ypall_callback *incallback)
588 {
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;
596
597   if (indomain == NULL || indomain[0] == '\0' ||
598       inmap == NULL || inmap == '\0')
599     return YPERR_BADARGS;
600
601   try = 0;
602   result = YPERR_YPERR;
603
604   while (try < MAXTRIES && result != RPC_SUCCESS)
605     {
606       __libc_lock_lock (ypbindlist_lock);
607
608       if (__yp_bind (indomain, &ydb) != 0)
609         {
610           __libc_lock_unlock (ypbindlist_lock);
611           return YPERR_DOMAIN;
612         }
613
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)
620         {
621           puts ("yp_all: clnttcp_create failed");
622           __libc_lock_unlock (ypbindlist_lock);
623           return YPERR_PMAP;
624         }
625       req.domain = (char *) indomain;
626       req.map = (char *) inmap;
627
628       ypall_foreach = incallback->foreach;
629       ypall_data = (void *) incallback->data;
630
631       result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey, &req,
632                           (xdrproc_t) __xdr_ypresp_all, &status, TIMEOUT);
633
634       if (result != RPC_SUCCESS)
635         {
636           clnt_perror (ydb->dom_client, "yp_all: clnt_call");
637           clnt_destroy (clnt);
638           __yp_unbind (ydb);
639           result = YPERR_RPC;
640         }
641       else
642         {
643           clnt_destroy (clnt);
644           result = YPERR_SUCCESS;
645         }
646
647       __libc_lock_unlock (ypbindlist_lock);
648
649       if (status != YP_NOMORE)
650         return ypprot_err (status);
651       try++;
652     }
653
654   return result;
655 }
656
657 int
658 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
659 {
660   struct ypresp_maplist resp;
661   int result;
662
663   if (indomain == NULL || indomain[0] == '\0')
664     return YPERR_BADARGS;
665
666   memset (&resp, '\0', sizeof (resp));
667
668   result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
669     (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
670
671   if (result != RPC_SUCCESS)
672     return result;
673   if (resp.stat != YP_TRUE)
674     return ypprot_err (resp.stat);
675
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); */
679
680   return YPERR_SUCCESS;
681 }
682
683 const char *
684 yperr_string (const int error)
685 {
686   switch (error)
687     {
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");
722     }
723   return _("Unknown NIS error code");
724 }
725
726 int
727 ypprot_err (const int code)
728 {
729   switch (code)
730     {
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;
753     }
754   return YPERR_YPERR;
755 }
756
757 const char *
758 ypbinderr_string (const int error)
759 {
760   switch (error)
761     {
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");
772     }
773 }
774
775
776 #define WINDOW 60
777
778 int
779 yp_update (char *domain, char *map, unsigned ypop,
780            char *key, int keylen, char *data, int datalen)
781 {
782 #if 0
783   union
784     {
785       ypupdate_args update_args;
786       ypdelete_args delete_args;
787     }
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;
796
797   if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
798     return YPERR_BADARGS;
799
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;
805
806   if ((r = yp_master (domain, map, &master)) != 0)
807     return r;
808
809   if (!host2netname (servername, master, domain))
810     {
811       fputs (_("yp_update: cannot convert host to netname\n"), stderr);
812       return YPERR_YPERR;
813     }
814
815   if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
816     {
817       clnt_pcreateerror ("yp_update: clnt_create");
818       return YPERR_RPC;
819     }
820
821   if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
822     {
823       fputs (_("yp_update: cannot get server address\n"), stderr);
824       return YPERR_RPC;
825     }
826
827   switch (ypop)
828     {
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;
840     }
841
842   clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
843
844   if (clnt->cl_auth == NULL)
845     clnt->cl_auth = authunix_create_default ();
846
847 again:
848   r = clnt_call (clnt, ypop, xdr_argument, &args,
849                  (xdrproc_t) xdr_u_int, &res, TIMEOUT);
850
851   if (r == RPC_AUTHERROR)
852     {
853       if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
854         {
855           clnt->cl_auth = authunix_create_default ();
856           goto again;
857         }
858       else
859         return YPERR_ACCESS;
860     }
861   if (r != RPC_SUCCESS)
862     {
863       clnt_perror (clnt, "yp_update: clnt_call");
864       return YPERR_RPC;
865     }
866   return res;
867 #else
868   return YPERR_YPERR;
869 #endif
870 }