home *** CD-ROM | disk | FTP | other *** search
/ Serving the Web / ServingTheWeb1995.disc1of1.iso / linux / slacksrce / d / libc / libc-4.6 / libc-4 / libc-linux / yp / yplib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-27  |  20.4 KB  |  827 lines

  1. /*
  2.  * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. The name of the author may not be used to endorse or promote
  14.  *    products derived from this software without specific prior written
  15.  *    permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
  18.  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  21.  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27.  * SUCH DAMAGE.
  28.  */
  29.  
  30. /*
  31.  *  Modifications for linux by Swen Thuemmler <swen@uni-paderborn.de>
  32.  */
  33.  
  34. #ifndef LINT
  35. static char *rcsid = "yplib.c,v 2.6 1994/05/27 14:34:43 swen Exp";
  36. #endif
  37.  
  38. #include <sys/param.h>
  39. #include <sys/types.h>
  40. #include <sys/socket.h>
  41. #include <sys/file.h>
  42. #include <sys/uio.h>
  43. #include <errno.h>
  44. #include <stdio.h>
  45. #include <string.h>
  46. #include "yp.h"
  47. #include <rpcsvc/ypclnt.h>
  48.  
  49. #ifndef BINDINGDIR
  50. #define BINDINGDIR "/var/yp/binding"
  51. #endif
  52. #define YPMATCHCACHE
  53. #define USE_BINDINGDIR 0 /* We don't want it */
  54.  
  55. static void ypmatch_add (char *, char *, int, char *, int);
  56. static bool_t ypmatch_find (char *, char *, int, char **, int *);
  57. int __yp_dobind (char *, struct dom_binding **);
  58. static void __yp_unbind (struct dom_binding *);
  59. int __yp_check (char **);
  60. int yp_maplist (char *, struct ypmaplist **);
  61. int (*ypresp_allfn)(int, char *, int, char *, int, char *);
  62. void *ypresp_data;
  63.  
  64. struct dom_binding *__ypbindlist;
  65. static char __yp_domain[MAXHOSTNAMELEN];
  66. int __yplib_timeout = 10;
  67.  
  68. #ifdef YPMATCHCACHE
  69. int __yplib_cache = 5;
  70.  
  71. static struct ypmatch_ent
  72. {
  73.   struct ypmatch_ent *next;
  74.   char *map, *key, *val;
  75.   int keylen, vallen;
  76.   time_t expire_t;
  77. } *ypmc;
  78.  
  79. static void
  80. ypmatch_add (char *map, char *key, int keylen, char *val, int vallen)
  81. {
  82.   struct ypmatch_ent *ep;
  83.   time_t t;
  84.   
  85.   time (&t);
  86.   
  87.   for (ep = ypmc; ep; ep = ep->next)
  88.     if (ep->expire_t < t)
  89.       break;
  90.   if (NULL == ep)
  91.     {
  92.       ep = (struct ypmatch_ent *) malloc (sizeof *ep);
  93.       bzero ((char *) ep, sizeof *ep);
  94.       if (ypmc)
  95.         ep->next = ypmc;
  96.       ypmc = ep;
  97.     }
  98.   
  99.   if (ep->key)
  100.     free (ep->key);
  101.   if (ep->val)
  102.     free (ep->val);
  103.   
  104.   ep->key = NULL;
  105.   ep->val = NULL;
  106.   
  107.   ep->key = (char *) malloc (keylen);
  108.   if (NULL == ep->key)
  109.     return;
  110.   
  111.   ep->val = (char *) malloc (vallen);
  112.   if (NULL == ep->key)
  113.     {
  114.       free (ep->key);
  115.       ep->key = NULL;
  116.       return;
  117.     }
  118.   ep->keylen = keylen;
  119.   ep->vallen = vallen;
  120.   
  121.   bcopy (key, ep->key, ep->keylen);
  122.   bcopy (val, ep->val, ep->vallen);
  123.   
  124.   if (ep->map)
  125.     {
  126.       if (strcmp (ep->map, map))
  127.         {
  128.           free (ep->map);
  129.           ep->map = strdup (map);
  130.         }
  131.     }
  132.   else
  133.     {
  134.       ep->map = strdup (map);
  135.     }
  136.   
  137.   ep->expire_t = t + __yplib_cache;
  138. }
  139.  
  140. static bool_t
  141. ypmatch_find (char *map, char *key, int keylen, char **val, int *vallen)
  142. {
  143.   struct ypmatch_ent *ep;
  144.   time_t t;
  145.   
  146.   if (NULL == ypmc)
  147.     return 0;
  148.   
  149.   time (&t);
  150.   
  151.   for (ep = ypmc; ep; ep = ep->next)
  152.     {
  153.       if (ep->keylen != keylen)
  154.         continue;
  155.       if (strcmp (ep->map, map))
  156.         continue;
  157.       if (bcmp (ep->key, key, keylen))
  158.         continue;
  159.       if (t > ep->expire_t)
  160.         continue;
  161.       
  162.       *val = ep->val;
  163.       *vallen = ep->vallen;
  164.       return 1;
  165.     }
  166.   return 0;
  167. }
  168.  
  169. #endif
  170.  
  171. int
  172. __yp_dobind (char *dom, struct dom_binding **ypdb)
  173. {
  174.   static int pid = -1;
  175.   struct dom_binding *ysd, *ysd2;
  176.   struct ypbind_resp ypbr;
  177.   struct timeval tv;
  178.   struct sockaddr_in clnt_sin;
  179.   int clnt_sock, gpid;
  180. #if USE_BINDINGDIR
  181.   char path[MAXPATHLEN];
  182.   int fd;
  183. #endif  
  184.   CLIENT *client;
  185.   int new = 0, r;
  186.   
  187.   gpid = getpid ();
  188.   if (!(-1 == pid || gpid == pid))
  189.     {
  190.       ysd = __ypbindlist;
  191.       while (ysd)
  192.         {
  193.           if (ysd->dom_client)
  194.             clnt_destroy (ysd->dom_client);
  195.           ysd2 = ysd->dom_pnext;
  196.           free (ysd);
  197.           ysd = ysd2;
  198.         }
  199.       __ypbindlist = NULL;
  200.     }
  201.   pid = gpid;
  202.   
  203.   if (NULL != ypdb)
  204.     *ypdb = NULL;
  205.   
  206.   if (NULL == dom || 0 == strlen (dom))
  207.     return YPERR_BADARGS;
  208.   
  209.   for (ysd = __ypbindlist; ysd; ysd = ysd->dom_pnext)
  210.     if (strcmp (dom, ysd->dom_domain) == 0)
  211.       break;
  212.   if (NULL == ysd)
  213.     {
  214.       ysd = (struct dom_binding *) malloc (sizeof *ysd);
  215.       bzero ((char *) ysd, sizeof *ysd);
  216.       ysd->dom_socket = -1;
  217.       ysd->dom_vers = 0;
  218.       new = 1;
  219.     }
  220.   again:
  221. #if USE_BINDINGDIR
  222.   if (0 == ysd->dom_vers)
  223.     {
  224.       sprintf (path, "%s/%s.%d", BINDINGDIR, dom, 2);
  225.       if ((fd = open (path, O_RDONLY)) == -1)
  226.         {
  227.               /* no binding file, YP is dead. */
  228.           if (new)
  229.             free (ysd);
  230.           return YPERR_YPBIND;
  231.         }
  232.       if (flock (fd, LOCK_EX | LOCK_NB) == -1 && errno == EWOULDBLOCK)
  233.         {
  234.           struct iovec iov[2];
  235.           struct ypbind_resp ybr;
  236.           u_short ypb_port;
  237.           
  238.           iov[0].iov_base = (caddr_t) & ypb_port;
  239.           iov[0].iov_len = sizeof ypb_port;
  240.           iov[1].iov_base = (caddr_t) & ybr;
  241.           iov[1].iov_len = sizeof ybr;
  242.           
  243.           r = readv (fd, iov, 2);
  244.           if (r != iov[0].iov_len + iov[1].iov_len)
  245.             {
  246.               close (fd);
  247.               ysd->dom_vers = -1;
  248.               goto again;
  249.             }
  250.           
  251.           bzero (&ysd->dom_server_addr, sizeof ysd->dom_server_addr);
  252.           ysd->dom_server_addr.sin_family = AF_INET;
  253.           ysd->dom_server_addr.sin_addr.s_addr =
  254.             ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr.s_addr;
  255.           ysd->dom_server_addr.sin_port =
  256.             ybr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port;
  257.           ysd->dom_server_port = ysd->dom_server_addr.sin_port;
  258.           close (fd);
  259.           goto gotit;
  260.         }
  261.       else
  262.         {
  263.               /* no lock on binding file, YP is dead. */
  264.           close (fd);
  265.           if (new)
  266.             free (ysd);
  267.           return YPERR_YPBIND;
  268.         }
  269.     }
  270. #endif
  271.   if (-1 == ysd->dom_vers || 0 == ysd->dom_vers)
  272.     {
  273.       bzero ((char *) &clnt_sin, sizeof clnt_sin);
  274.       clnt_sin.sin_family = AF_INET;
  275.       clnt_sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
  276.       clnt_sock = RPC_ANYSOCK;
  277.       client = clnttcp_create (&clnt_sin,
  278.                                YPBINDPROG, YPBINDVERS,
  279.                                &clnt_sock, 0, 0);
  280.       if (NULL == client)
  281.         {
  282.           clnt_pcreateerror ("clnttcp_create");
  283.           if (new)
  284.             free (ysd);
  285.           return YPERR_YPBIND;
  286.         }
  287.       tv.tv_sec = __yplib_timeout;
  288.       tv.tv_usec = 0;
  289.       r = clnt_call (client,
  290.                      YPBINDPROC_DOMAIN,
  291.                      xdr_domainname, dom,
  292.                      xdr_ypbind_resp, &ypbr,
  293.                      tv);
  294.       if (r != RPC_SUCCESS)
  295.         {
  296.           fprintf (stderr,
  297.                    "YP: server for domain %s not responding, still trying\n",
  298.                    dom);
  299.           clnt_destroy (client);
  300.           ysd->dom_vers = -1;
  301.           goto again;
  302.         }
  303.       clnt_destroy (client);
  304.       switch (ypbr.ypbind_status)
  305.         {
  306.         case YPBIND_FAIL_VAL:
  307.           switch(ypbr.ypbind_respbody.ypbind_error)
  308.             {
  309.             case YPBIND_ERR_ERR:
  310.               fprintf(stderr, "YPBINDPROC_DOMAIN: Internal error\n");
  311.               break;
  312.             case YPBIND_ERR_NOSERV:
  313.               fprintf(stderr,
  314.                       "YPBINDPROC_DOMAIN: No bound server for domain %s\n",
  315.  
  316.                       dom);
  317.               break;
  318.             case YPBIND_ERR_RESC:
  319.               fprintf(stderr, "YPBINDPROC_DOMAIN: Resource allocation failure\n");
  320.               break;
  321.             default:
  322.               fprintf(stderr, "YPBINDPROC_DOMAIN: Unknown error\n");
  323.               break;
  324.             }
  325.           return YPERR_DOMAIN;
  326.         case YPBIND_SUCC_VAL:
  327.           {
  328.             bzero ((char *) &ysd->dom_server_addr, sizeof ysd->dom_server_addr);
  329.             ysd->dom_server_addr.sin_family = AF_INET;
  330.             ysd->dom_server_addr.sin_port = 
  331.               ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port;
  332.             ysd->dom_server_addr.sin_addr.s_addr =
  333.               ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr.s_addr;
  334.             ysd->dom_server_port = 
  335.               ypbr.ypbind_respbody.ypbind_bindinfo.ypbind_binding_port;
  336.           }
  337.         }
  338.       gotit:
  339.       ysd->dom_vers = YPVERS;
  340.       strcpy (ysd->dom_domain, dom);
  341.     }
  342.   tv.tv_sec = __yplib_timeout / 2;
  343.   tv.tv_usec = 0;
  344.   if (ysd->dom_client)
  345.     clnt_destroy (ysd->dom_client);
  346.   ysd->dom_socket = RPC_ANYSOCK;
  347.   ysd->dom_client = clntudp_create (&ysd->dom_server_addr,
  348.                                     YPPROG, YPVERS,
  349.                                     tv, &ysd->dom_socket);
  350.   if (NULL == ysd->dom_client)
  351.     {
  352.       clnt_pcreateerror ("clntudp_create");
  353.       ysd->dom_vers = -1;
  354.       goto again;
  355.     }
  356.   if (-1 == fcntl (ysd->dom_socket, F_SETFD, 1))
  357.     perror ("fcntl: F_SETFD");
  358.   
  359.   if (new)
  360.     {
  361.       ysd->dom_pnext = __ypbindlist;
  362.       __ypbindlist = ysd;
  363.     }
  364.   
  365.   if (NULL != ypdb)
  366.     *ypdb = ysd;
  367.   return 0;
  368. }
  369.  
  370. static void
  371. __yp_unbind (struct dom_binding *ypb)
  372. {
  373.   clnt_destroy (ypb->dom_client);
  374.   ypb->dom_client = NULL;
  375.   ypb->dom_socket = -1;
  376. }
  377.  
  378. int
  379. yp_bind (char *dom)
  380. {
  381.   return __yp_dobind (dom, NULL);
  382. }
  383.  
  384. void
  385. yp_unbind (char *dom)
  386. {
  387.   struct dom_binding *ypb, *ypbp;
  388.   
  389.   ypbp = NULL;
  390.   for (ypb = __ypbindlist; ypb; ypb = ypb->dom_pnext)
  391.     {
  392.       if (strcmp (dom, ypb->dom_domain) == 0)
  393.         {
  394.           clnt_destroy (ypb->dom_client);
  395.           if (ypbp)
  396.             ypbp->dom_pnext = ypb->dom_pnext;
  397.           else
  398.             __ypbindlist = ypb->dom_pnext;
  399.           free (ypb);
  400.           return;
  401.         }
  402.       ypbp = ypb;
  403.     }
  404.   return;
  405. }
  406.  
  407. int
  408. yp_match (char *indomain, char *inmap, char *inkey, int inkeylen, char **outval, int *outvallen)
  409. {
  410.   struct dom_binding *ysd;
  411.   struct ypresp_val yprv;
  412.   struct timeval tv;
  413.   struct ypreq_key yprk;
  414.   int r;
  415.   
  416.   *outval = NULL;
  417.   *outvallen = 0;
  418.   
  419.   again:
  420.   if (__yp_dobind (indomain, &ysd) != 0)
  421.     return YPERR_DOMAIN;
  422.   
  423. #ifdef YPMATCHCACHE
  424.   if (!strcmp (__yp_domain, indomain)
  425.       && ypmatch_find (inmap, inkey,
  426.                        inkeylen, &yprv.valdat.dptr, &yprv.valdat.dsize))
  427.     {
  428.       *outvallen = yprv.valdat.dsize;
  429.       *outval = (char *) malloc (*outvallen + 2);
  430.       bcopy (yprv.valdat.dptr, *outval, *outvallen);
  431.       (*outval)[*outvallen] = '\n';
  432.       (*outval)[*outvallen + 1] = '\0';
  433.       return 0;
  434.     }
  435. #endif
  436.   
  437.   tv.tv_sec = __yplib_timeout;
  438.   tv.tv_usec = 0;
  439.   
  440.   yprk.domain = indomain;
  441.   yprk.map = inmap;
  442.   yprk.keydat.dptr = inkey;
  443.   yprk.keydat.dsize = inkeylen;
  444.   
  445.   bzero ((char *) &yprv, sizeof yprv);
  446.   
  447.   r = clnt_call (ysd->dom_client, YPPROC_MATCH,
  448.                  xdr_ypreq_key, &yprk,
  449.                  xdr_ypresp_val, &yprv,
  450.                  tv);
  451.   if (r != RPC_SUCCESS)
  452.     {
  453.       clnt_perror (ysd->dom_client, "yp_match: clnt_call");
  454.       ysd->dom_vers = -1;
  455.       goto again;
  456.     }
  457.   if (!(r = ypprot_err (yprv.status)))
  458.     {
  459.       *outvallen = yprv.valdat.dsize;
  460.       *outval = (char *) malloc (*outvallen + 2);
  461.       bcopy (yprv.valdat.dptr, *outval, *outvallen);
  462.       (*outval)[*outvallen] = '\n';
  463.       (*outval)[*outvallen + 1] = '\0';
  464. #ifdef YPMATCHCACHE
  465.       if (strcmp (__yp_domain, indomain) == 0)
  466.         ypmatch_add (inmap, inkey, inkeylen, *outval, *outvallen);
  467. #endif
  468.     }
  469.   xdr_free (xdr_ypresp_val, (char *) &yprv);
  470.   __yp_unbind (ysd);
  471.   return r;
  472. }
  473.  
  474. int
  475. yp_get_default_domain (char **domp)
  476. {
  477.   *domp = NULL;
  478.   if ('\0' == __yp_domain[0])
  479.     if (getdomainname (__yp_domain, sizeof __yp_domain))
  480.       return YPERR_NODOM;
  481.   *domp = __yp_domain;
  482.   return 0;
  483. }
  484.  
  485. int
  486. yp_first (char *indomain, char *inmap, char **outkey, int *outkeylen, char **outval, int *outvallen)
  487. {
  488.   struct ypresp_key_val yprkv;
  489.   struct ypreq_nokey yprnk;
  490.   struct dom_binding *ysd;
  491.   struct timeval tv;
  492.   int r;
  493.  
  494.   *outkey = *outval = NULL;
  495.   *outkeylen = *outvallen = 0;
  496.  
  497.   again:
  498.   if (__yp_dobind (indomain, &ysd) != 0)
  499.     return YPERR_DOMAIN;
  500.   
  501.   tv.tv_sec = __yplib_timeout;
  502.   tv.tv_usec = 0;
  503.   
  504.   yprnk.domain = indomain;
  505.   yprnk.map = inmap;
  506.   bzero ((char *) &yprkv, sizeof yprkv);
  507.   
  508.   r = clnt_call (ysd->dom_client, YPPROC_FIRST,
  509.                  xdr_ypreq_nokey, &yprnk,
  510.                  xdr_ypresp_key_val, &yprkv,
  511.                  tv);
  512.   if (r != RPC_SUCCESS)
  513.     {
  514.       clnt_perror (ysd->dom_client, "yp_first: clnt_call");
  515.       ysd->dom_vers = -1;
  516.       goto again;
  517.     }
  518.   if (!(r = ypprot_err (yprkv.status)))
  519.     {
  520.       *outkeylen = yprkv.keydat.dsize;
  521.       *outkey = (char *) malloc (*outkeylen + 2);
  522.       bcopy (yprkv.keydat.dptr, *outkey, *outkeylen);
  523.       (*outkey)[*outkeylen] = '\n';
  524.       (*outkey)[*outkeylen + 1] = '\0';
  525.       *outvallen = yprkv.valdat.dsize;
  526.       *outval = (char *) malloc (*outvallen + 2);
  527.       bcopy (yprkv.valdat.dptr, *outval, *outvallen);
  528.       (*outval)[*outvallen] = '\n';
  529.       (*outval)[*outvallen + 1] = '\0';
  530.     }
  531.   xdr_free (xdr_ypresp_key_val, (char *) &yprkv);
  532.   __yp_unbind (ysd);
  533.   return r;
  534. }
  535.  
  536. int
  537. yp_next (char *indomain, char *inmap, char *inkey, int inkeylen, char **outkey, int *outkeylen, char **outval, int *outvallen)
  538. {
  539.   struct ypresp_key_val yprkv;
  540.   struct ypreq_key yprk;
  541.   struct dom_binding *ysd;
  542.   struct timeval tv;
  543.   int r;
  544.   
  545.   *outkey = *outval = NULL;
  546.   *outkeylen = *outvallen = 0;
  547.   
  548.   again:
  549.   if (__yp_dobind (indomain, &ysd) != 0)
  550.     return YPERR_DOMAIN;
  551.   
  552.   tv.tv_sec = __yplib_timeout;
  553.   tv.tv_usec = 0;
  554.   
  555.   yprk.domain = indomain;
  556.   yprk.map = inmap;
  557.   yprk.keydat.dptr = inkey;
  558.   yprk.keydat.dsize = inkeylen;
  559.   bzero ((char *) &yprkv, sizeof yprkv);
  560.   
  561.   r = clnt_call (ysd->dom_client, YPPROC_NEXT,
  562.                  xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv);
  563.   if (r != RPC_SUCCESS)
  564.     {
  565.       clnt_perror (ysd->dom_client, "yp_next: clnt_call");
  566.       ysd->dom_vers = -1;
  567.       goto again;
  568.     }
  569.   if (!(r = ypprot_err (yprkv.status)))
  570.     {
  571.       *outkeylen = yprkv.keydat.dsize;
  572.       *outkey = (char *) malloc (*outkeylen + 2);
  573.       bcopy (yprkv.keydat.dptr, *outkey, *outkeylen);
  574.       (*outkey)[*outkeylen] = '\n';
  575.       (*outkey)[*outkeylen + 1] = '\0';
  576.       *outvallen = yprkv.valdat.dsize;
  577.       *outval = (char *) malloc (*outvallen + 2);
  578.       bcopy (yprkv.valdat.dptr, *outval, *outvallen);
  579.       (*outval)[*outvallen] = '\n';
  580.       (*outval)[*outvallen + 1] = '\0';
  581.     }
  582.   xdr_free (xdr_ypresp_key_val, (char *) &yprkv);
  583.   __yp_unbind (ysd);
  584.   return r;
  585. }
  586.  
  587. int
  588. yp_all (char *indomain, char *inmap, struct ypall_callback *incallback)
  589. {
  590.   struct ypreq_nokey yprnk;
  591.   struct dom_binding *ysd;
  592.   struct timeval tv;
  593.   struct sockaddr_in clnt_sin;
  594.   CLIENT *clnt;
  595.   u_long status;
  596.   int clnt_sock;
  597.   
  598.   if (__yp_dobind (indomain, &ysd) != 0)
  599.     return YPERR_DOMAIN;
  600.   
  601.   tv.tv_sec = __yplib_timeout;
  602.   tv.tv_usec = 0;
  603.   clnt_sock = RPC_ANYSOCK;
  604.   clnt_sin = ysd->dom_server_addr;
  605.   clnt_sin.sin_port = 0;
  606.   clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
  607.   if (NULL == clnt)
  608.     {
  609.       printf ("clnttcp_create failed\n");
  610.       return YPERR_PMAP;
  611.     }
  612.   
  613.   yprnk.domain = indomain;
  614.   yprnk.map = inmap;
  615.   ypresp_allfn = incallback->foreach;
  616.   ypresp_data = (void *) incallback->data;
  617.   
  618.   (void) clnt_call (clnt, YPPROC_ALL,
  619.           xdr_ypreq_nokey, &yprnk, xdr_ypresp_all_seq, &status, tv);
  620.   clnt_destroy (clnt);
  621.   xdr_free (xdr_ypresp_all_seq, (char *) &status);    /* not really needed... */
  622.   __yp_unbind (ysd);
  623.   
  624.   if (status != YP_FALSE)
  625.     return ypprot_err (status);
  626.   return 0;
  627. }
  628.  
  629. int
  630. yp_order (char *indomain, char *inmap, int *outorder)
  631. {
  632.   struct dom_binding *ysd;
  633.   struct ypresp_order ypro;
  634.   struct ypreq_nokey yprnk;
  635.   struct timeval tv;
  636.   int r;
  637.   
  638.   again:
  639.   if (__yp_dobind (indomain, &ysd) != 0)
  640.     return YPERR_DOMAIN;
  641.   
  642.   tv.tv_sec = __yplib_timeout;
  643.   tv.tv_usec = 0;
  644.   
  645.   yprnk.domain = indomain;
  646.   yprnk.map = inmap;
  647.   
  648.   bzero ((char *) (char *) &ypro, sizeof ypro);
  649.   
  650.   r = clnt_call (ysd->dom_client, YPPROC_ORDER,
  651.                  xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv);
  652.   if (r != RPC_SUCCESS)
  653.     {
  654.       clnt_perror (ysd->dom_client, "yp_order: clnt_call");
  655.       ysd->dom_vers = -1;
  656.       goto again;
  657.     }
  658.  
  659.   *outorder = ypro.ordernum;
  660.   xdr_free (xdr_ypresp_order, (char *) &ypro);
  661.   __yp_unbind (ysd);
  662.   return ypprot_err (ypro.status);
  663. }
  664.  
  665. int
  666. yp_master (char *indomain, char *inmap, char **outname)
  667. {
  668.   struct dom_binding *ysd;
  669.   struct ypresp_master yprm;
  670.   struct ypreq_nokey yprnk;
  671.   struct timeval tv;
  672.   int r;
  673.   
  674.   again:
  675.   if (__yp_dobind (indomain, &ysd) != 0)
  676.     return YPERR_DOMAIN;
  677.   
  678.   tv.tv_sec = __yplib_timeout;
  679.   tv.tv_usec = 0;
  680.  
  681.   yprnk.domain = indomain;
  682.   yprnk.map = inmap;
  683.   
  684.   bzero ((char *) &yprm, sizeof yprm);
  685.  
  686.   r = clnt_call (ysd->dom_client, YPPROC_MASTER,
  687.                  xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv);
  688.   if (r != RPC_SUCCESS)
  689.     {
  690.       clnt_perror (ysd->dom_client, "yp_master: clnt_call");
  691.       ysd->dom_vers = -1;
  692.       goto again;
  693.     }
  694.   if (!(r = ypprot_err (yprm.status)))
  695.     {
  696.       *outname = (char *) strdup (yprm.master);
  697.     }
  698.   xdr_free (xdr_ypresp_master, (char *) &yprm);
  699.   __yp_unbind (ysd);
  700.   return r;
  701. }
  702.  
  703. int
  704. yp_maplist (char *indomain, struct ypmaplist **outmaplist)
  705. {
  706.   struct dom_binding *ysd;
  707.   struct ypresp_maplist ypml;
  708.   struct timeval tv;
  709.   int r;
  710.   
  711.   again:
  712.   if (__yp_dobind (indomain, &ysd) != 0)
  713.     return YPERR_DOMAIN;
  714.   
  715.   tv.tv_sec = __yplib_timeout;
  716.   tv.tv_usec = 0;
  717.   
  718.   bzero ((char *) &ypml, sizeof ypml);
  719.   
  720.   r = clnt_call (ysd->dom_client, YPPROC_MAPLIST,
  721.                  xdr_domainname, indomain, xdr_ypresp_maplist, &ypml, tv);
  722.   if (r != RPC_SUCCESS)
  723.     {
  724.       clnt_perror (ysd->dom_client, "yp_maplist: clnt_call");
  725.       ysd->dom_vers = -1;
  726.       goto again;
  727.     }
  728.   *outmaplist = ypml.list;
  729.       /* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/
  730.   __yp_unbind (ysd);
  731.   return ypprot_err (ypml.status);
  732. }
  733.  
  734. char *
  735. yperr_string (int incode)
  736. {
  737.   static char err[80];
  738.   
  739.   switch (incode)
  740.     {
  741.     case 0:
  742.       return "Success";
  743.     case YPERR_BADARGS:
  744.       return "Request arguments bad";
  745.     case YPERR_RPC:
  746.       return "RPC failure";
  747.     case YPERR_DOMAIN:
  748.       return "Can't bind to server which serves this domain";
  749.     case YPERR_MAP:
  750.       return "No such map in server's domain";
  751.     case YPERR_KEY:
  752.       return "No such key in map";
  753.     case YPERR_YPERR:
  754.       return "YP server error";
  755.     case YPERR_RESRC:
  756.       return "Local resource allocation failure";
  757.     case YPERR_NOMORE:
  758.       return "No more records in map database";
  759.     case YPERR_PMAP:
  760.       return "Can't communicate with portmapper";
  761.     case YPERR_YPBIND:
  762.       return "Can't communicate with ypbind";
  763.     case YPERR_YPSERV:
  764.       return "Can't communicate with ypserv";
  765.     case YPERR_NODOM:
  766.       return "Local domain name not set";
  767.     case YPERR_BADDB:
  768.       return "Server data base is bad";
  769.     case YPERR_VERS:
  770.       return "YP server version mismatch - server can't supply service.";
  771.     case YPERR_ACCESS:
  772.       return "Access violation";
  773.     case YPERR_BUSY:
  774.       return "Database is busy";
  775.     }
  776.   sprintf (err, "YP unknown error %d\n", incode);
  777.   return err;
  778. }
  779.  
  780. int
  781. ypprot_err (long int incode)
  782. {
  783.   switch (incode)
  784.     {
  785.     case YP_TRUE:
  786.       return 0;
  787.     case YP_FALSE:
  788.       return YPERR_YPBIND;
  789.     case YP_NOMORE:
  790.       return YPERR_NOMORE;
  791.     case YP_NOMAP:
  792.       return YPERR_MAP;
  793.     case YP_NODOM:
  794.       return YPERR_NODOM;
  795.     case YP_NOKEY:
  796.       return YPERR_KEY;
  797.     case YP_BADOP:
  798.       return YPERR_YPERR;
  799.     case YP_BADDB:
  800.       return YPERR_BADDB;
  801.     case YP_YPERR:
  802.       return YPERR_YPERR;
  803.     case YP_BADARGS:
  804.       return YPERR_BADARGS;
  805.     case YP_VERS:
  806.       return YPERR_VERS;
  807.     }
  808.   return YPERR_YPERR;
  809. }
  810.  
  811. int
  812. __yp_check (char **dom)
  813. {
  814.   char *unused;
  815.   
  816.   if ('\0' == __yp_domain[0])
  817.     if (yp_get_default_domain (&unused))
  818.       return 0;
  819.   
  820.   if (dom)
  821.     *dom = __yp_domain;
  822.   
  823.   if (yp_bind (__yp_domain) == 0)
  824.     return 1;
  825.   return 0;
  826. }
  827.