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