Fix prototypes.
[kopensolaris-gnu/glibc.git] / nis / ypclnt.c
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.
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, (caddr_t) &domain,
127                          (xdrproc_t) xdr_ypbind_resp,
128                          (caddr_t) &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           strncpy (ysd->dom_domain, domain, YPMAXDOMAIN);
171           ysd->dom_domain[YPMAXDOMAIN] = '\0';
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) __P ((int status, char *key, int keylen,
530                                   char *val, int vallen, char *data));
531
532 static bool_t
533 __xdr_ypresp_all (XDR * xdrs, u_long * objp)
534 {
535   while (1)
536     {
537       struct ypresp_all resp;
538
539       memset (&resp, '\0', sizeof (struct ypresp_all));
540       if (!xdr_ypresp_all (xdrs, &resp))
541         {
542           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
543           *objp = YP_YPERR;
544           return (FALSE);
545         }
546       if (resp.more == 0)
547         {
548           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
549           *objp = YP_NOMORE;
550           return (FALSE);
551         }
552
553       switch (resp.ypresp_all_u.val.stat)
554         {
555         case YP_TRUE:
556           {
557             char key[resp.ypresp_all_u.val.key.keydat_len + 1];
558             char val[resp.ypresp_all_u.val.val.valdat_len + 1];
559             int keylen = resp.ypresp_all_u.val.key.keydat_len;
560             int vallen = resp.ypresp_all_u.val.val.valdat_len;
561
562             *objp = YP_TRUE;
563             memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
564             key[keylen] = '\0';
565             memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
566             val[vallen] = '\0';
567             xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
568             if ((*ypall_foreach) (*objp, key, keylen,
569                                   val, vallen, ypall_data))
570               return TRUE;
571           }
572           break;
573         case YP_NOMORE:
574           *objp = YP_NOMORE;
575           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
576           return TRUE;
577           break;
578         default:
579           *objp = resp.ypresp_all_u.val.stat;
580           xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
581           return TRUE;
582         }
583     }
584 }
585
586 int
587 yp_all (const char *indomain, const char *inmap,
588         const struct ypall_callback *incallback)
589 {
590   struct ypreq_nokey req;
591   dom_binding *ydb;
592   int try, result;
593   struct sockaddr_in clnt_sin;
594   CLIENT *clnt;
595   unsigned long status;
596   int clnt_sock;
597
598   if (indomain == NULL || indomain[0] == '\0' ||
599       inmap == NULL || inmap == '\0')
600     return YPERR_BADARGS;
601
602   try = 0;
603   result = YPERR_YPERR;
604
605   while (try < MAXTRIES && result != RPC_SUCCESS)
606     {
607       __libc_lock_lock (ypbindlist_lock);
608
609       if (__yp_bind (indomain, &ydb) != 0)
610         {
611           __libc_lock_unlock (ypbindlist_lock);
612           return YPERR_DOMAIN;
613         }
614
615       /* YPPROC_ALL get its own TCP channel to ypserv */
616       clnt_sock = RPC_ANYSOCK;
617       clnt_sin = ydb->dom_server_addr;
618       clnt_sin.sin_port = 0;
619       clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
620       if (clnt == NULL)
621         {
622           puts ("yp_all: clnttcp_create failed");
623           __libc_lock_unlock (ypbindlist_lock);
624           return YPERR_PMAP;
625         }
626       req.domain = (char *) indomain;
627       req.map = (char *) inmap;
628
629       ypall_foreach = incallback->foreach;
630       ypall_data = (void *) incallback->data;
631
632       result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey,
633                           (caddr_t) &req, (xdrproc_t) __xdr_ypresp_all,
634                           (caddr_t) &status, TIMEOUT);
635
636       if (result != RPC_SUCCESS)
637         {
638           clnt_perror (ydb->dom_client, "yp_all: clnt_call");
639           clnt_destroy (clnt);
640           __yp_unbind (ydb);
641           result = YPERR_RPC;
642         }
643       else
644         {
645           clnt_destroy (clnt);
646           result = YPERR_SUCCESS;
647         }
648
649       __libc_lock_unlock (ypbindlist_lock);
650
651       if (status != YP_NOMORE)
652         return ypprot_err (status);
653       try++;
654     }
655
656   return result;
657 }
658
659 int
660 yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
661 {
662   struct ypresp_maplist resp;
663   int result;
664
665   if (indomain == NULL || indomain[0] == '\0')
666     return YPERR_BADARGS;
667
668   memset (&resp, '\0', sizeof (resp));
669
670   result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
671     (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
672
673   if (result != RPC_SUCCESS)
674     return result;
675   if (resp.stat != YP_TRUE)
676     return ypprot_err (resp.stat);
677
678   *outmaplist = resp.maps;
679   /* We give the list not free, this will be done by ypserv
680      xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
681
682   return YPERR_SUCCESS;
683 }
684
685 const char *
686 yperr_string (const int error)
687 {
688   switch (error)
689     {
690     case YPERR_SUCCESS:
691       return _("Success");
692     case YPERR_BADARGS:
693       return _("Request arguments bad");
694     case YPERR_RPC:
695       return _("RPC failure on NIS operation");
696     case YPERR_DOMAIN:
697       return _("Can't bind to server which serves this domain");
698     case YPERR_MAP:
699       return _("No such map in server's domain");
700     case YPERR_KEY:
701       return _("No such key in map");
702     case YPERR_YPERR:
703       return _("Internal NIS error");
704     case YPERR_RESRC:
705       return _("Local resource allocation failure");
706     case YPERR_NOMORE:
707       return _("No more records in map database");
708     case YPERR_PMAP:
709       return _("Can't communicate with portmapper");
710     case YPERR_YPBIND:
711       return _("Can't communicate with ypbind");
712     case YPERR_YPSERV:
713       return _("Can't communicate with ypserv");
714     case YPERR_NODOM:
715       return _("Local domain name not set");
716     case YPERR_BADDB:
717       return _("NIS map data base is bad");
718     case YPERR_VERS:
719       return _("NIS client/server version mismatch - can't supply service");
720     case YPERR_ACCESS:
721       return _("Permission denied");
722     case YPERR_BUSY:
723       return _("Database is busy");
724     }
725   return _("Unknown NIS error code");
726 }
727
728 int
729 ypprot_err (const int code)
730 {
731   switch (code)
732     {
733     case YP_TRUE:
734       return YPERR_SUCCESS;
735     case YP_NOMORE:
736       return YPERR_NOMORE;
737     case YP_FALSE:
738       return YPERR_YPERR;
739     case YP_NOMAP:
740       return YPERR_MAP;
741     case YP_NODOM:
742       return YPERR_DOMAIN;
743     case YP_NOKEY:
744       return YPERR_KEY;
745     case YP_BADOP:
746       return YPERR_YPERR;
747     case YP_BADDB:
748       return YPERR_BADDB;
749     case YP_YPERR:
750       return YPERR_YPERR;
751     case YP_BADARGS:
752       return YPERR_BADARGS;
753     case YP_VERS:
754       return YPERR_VERS;
755     }
756   return YPERR_YPERR;
757 }
758
759 const char *
760 ypbinderr_string (const int error)
761 {
762   switch (error)
763     {
764     case 0:
765       return _("Success");
766     case YPBIND_ERR_ERR:
767       return _("Internal ypbind error");
768     case YPBIND_ERR_NOSERV:
769       return _("Domain not bound");
770     case YPBIND_ERR_RESC:
771       return _("System resource allocation failure");
772     default:
773       return _("Unknown ypbind error");
774     }
775 }
776
777
778 #define WINDOW 60
779
780 int
781 yp_update (char *domain, char *map, unsigned ypop,
782            char *key, int keylen, char *data, int datalen)
783 {
784 #if 0
785   union
786     {
787       ypupdate_args update_args;
788       ypdelete_args delete_args;
789     }
790   args;
791   xdrproc_t xdr_argument;
792   unsigned res = 0;
793   CLIENT *clnt;
794   char *master;
795   struct sockaddr saddr;
796   char servername[MAXNETNAMELEN + 1];
797   int r;
798
799   if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
800     return YPERR_BADARGS;
801
802   args.update_args.mapname = map;
803   args.update_args.key.yp_buf_len = keylen;
804   args.update_args.key.yp_buf_val = key;
805   args.update_args.datum.yp_buf_len = datalen;
806   args.update_args.datum.yp_buf_val = data;
807
808   if ((r = yp_master (domain, map, &master)) != 0)
809     return r;
810
811   if (!host2netname (servername, master, domain))
812     {
813       fputs (_("yp_update: cannot convert host to netname\n"), stderr);
814       return YPERR_YPERR;
815     }
816
817   if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
818     {
819       clnt_pcreateerror ("yp_update: clnt_create");
820       return YPERR_RPC;
821     }
822
823   if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
824     {
825       fputs (_("yp_update: cannot get server address\n"), stderr);
826       return YPERR_RPC;
827     }
828
829   switch (ypop)
830     {
831     case YPOP_CHANGE:
832     case YPOP_INSERT:
833     case YPOP_STORE:
834       xdr_argument = (xdrproc_t) xdr_ypupdate_args;
835       break;
836     case YPOP_DELETE:
837       xdr_argument = (xdrproc_t) xdr_ypdelete_args;
838       break;
839     default:
840       return YPERR_BADARGS;
841       break;
842     }
843
844   clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
845
846   if (clnt->cl_auth == NULL)
847     clnt->cl_auth = authunix_create_default ();
848
849 again:
850   r = clnt_call (clnt, ypop, xdr_argument, &args,
851                  (xdrproc_t) xdr_u_int, &res, TIMEOUT);
852
853   if (r == RPC_AUTHERROR)
854     {
855       if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
856         {
857           clnt->cl_auth = authunix_create_default ();
858           goto again;
859         }
860       else
861         return YPERR_ACCESS;
862     }
863   if (r != RPC_SUCCESS)
864     {
865       clnt_perror (clnt, "yp_update: clnt_call");
866       return YPERR_RPC;
867     }
868   return res;
869 #else
870   return YPERR_YPERR;
871 #endif
872 }