summary refs log tree commit diff
path: root/nis/ypclnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'nis/ypclnt.c')
-rw-r--r--nis/ypclnt.c868
1 files changed, 868 insertions, 0 deletions
diff --git a/nis/ypclnt.c b/nis/ypclnt.c
new file mode 100644
index 0000000000..3e05cf984c
--- /dev/null
+++ b/nis/ypclnt.c
@@ -0,0 +1,868 @@
+/* Copyright (C) 1996 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <libc-lock.h>
+#include <rpcsvc/yp.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/ypupd.h>
+
+struct dom_binding
+  {
+    struct dom_binding *dom_pnext;
+    char dom_domain[YPMAXDOMAIN + 1];
+    struct sockaddr_in dom_server_addr;
+    int dom_socket;
+    CLIENT *dom_client;
+    long int dom_vers;
+  };
+typedef struct dom_binding dom_binding;
+
+static struct timeval TIMEOUT = {25, 0};
+static int const MAXTRIES = 5;
+static char __ypdomainname[MAXHOSTNAMELEN + 1] = "\0";
+__libc_lock_define_initialized (static, ypbindlist_lock)
+static dom_binding *__ypbindlist = NULL;
+
+static int
+__yp_bind (char *domain, dom_binding ** ypdb)
+{
+  struct sockaddr_in clnt_saddr;
+  struct ypbind_resp ypbr;
+  dom_binding *ysd;
+  int clnt_sock;
+  CLIENT *client;
+  int is_new = 0;
+  int try;
+
+  if (ypdb != NULL)
+    *ypdb = NULL;
+
+  if ((domain == NULL) || (strlen (domain) == 0))
+    return YPERR_BADARGS;
+
+  ysd = __ypbindlist;
+  while (ysd != NULL)
+    {
+      if (strcmp (domain, ysd->dom_domain) == 0)
+        break;
+      ysd = ysd->dom_pnext;
+    }
+
+  if (ysd == NULL)
+    {
+      is_new = 1;
+      ysd = (dom_binding *) malloc (sizeof *ysd);
+      memset (ysd, '\0', sizeof *ysd);
+      ysd->dom_socket = -1;
+      ysd->dom_vers = -1;
+    }
+
+  try = 0;
+
+  do
+    {
+      try++;
+      if (try > MAXTRIES)
+        {
+          if (is_new)
+            free (ysd);
+          return YPERR_YPBIND;
+        }
+
+      if (ysd->dom_vers == -1)
+        {
+          if(ysd->dom_client)
+            {
+              clnt_destroy(ysd->dom_client);
+              ysd->dom_client = NULL;
+              ysd->dom_socket = -1;
+            }
+          memset (&clnt_saddr, '\0', sizeof clnt_saddr);
+          clnt_saddr.sin_family = AF_INET;
+          clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+          clnt_sock = RPC_ANYSOCK;
+          client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS,
+                                   &clnt_sock, 0, 0);
+          if (client == NULL)
+            {
+              if (is_new)
+                free (ysd);
+              return YPERR_YPBIND;
+            }
+          /*
+          ** Check the port number -- should be < IPPORT_RESERVED.
+          ** If not, it's possible someone has registered a bogus
+          ** ypbind with the portmapper and is trying to trick us.
+          */
+          if (ntohs(clnt_saddr.sin_port) >= IPPORT_RESERVED)
+            {
+              clnt_destroy(client);
+              if (is_new)
+                free(ysd);
+              return(YPERR_YPBIND);
+            }
+
+          if (clnt_call (client, YPBINDPROC_DOMAIN,
+                         (xdrproc_t) xdr_domainname, &domain,
+                         (xdrproc_t) xdr_ypbind_resp,
+                         &ypbr, TIMEOUT) != RPC_SUCCESS)
+            {
+              clnt_destroy (client);
+              if (is_new)
+                free (ysd);
+              return YPERR_YPBIND;
+            }
+
+          clnt_destroy (client);
+          if (ypbr.ypbind_status != YPBIND_SUCC_VAL)
+            {
+              switch (ypbr.ypbind_resp_u.ypbind_error)
+                {
+                case YPBIND_ERR_ERR:
+                  fputs (_("YPBINDPROC_DOMAIN: Internal error\n"), stderr);
+                  break;
+                case YPBIND_ERR_NOSERV:
+                  fprintf (stderr,
+                           _("YPBINDPROC_DOMAIN: No server for domain %s\n"),
+                           domain);
+                  break;
+                case YPBIND_ERR_RESC:
+                  fputs (_("YPBINDPROC_DOMAIN: Resource allocation failure\n"),
+                         stderr);
+                  break;
+                default:
+                  fputs (_("YPBINDPROC_DOMAIN: Unknown error\n"), stderr);
+                  break;
+                }
+              if (is_new)
+                free (ysd);
+              return YPERR_DOMAIN;
+            }
+          memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr);
+          ysd->dom_server_addr.sin_family = AF_INET;
+          memcpy (&ysd->dom_server_addr.sin_port,
+                  ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
+                  sizeof (ysd->dom_server_addr.sin_port));
+          memcpy (&ysd->dom_server_addr.sin_addr.s_addr,
+                  ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
+                  sizeof (ysd->dom_server_addr.sin_addr.s_addr));
+          ysd->dom_vers = YPVERS;
+          strcpy (ysd->dom_domain, domain);
+        }
+
+      if (ysd->dom_client)
+        clnt_destroy (ysd->dom_client);
+      ysd->dom_socket = RPC_ANYSOCK;
+      ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS,
+                                        TIMEOUT, &ysd->dom_socket);
+      if (ysd->dom_client == NULL)
+        ysd->dom_vers = -1;
+
+    }
+  while (ysd->dom_client == NULL);
+
+  /* If the program exists, close the socket */
+  if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1)
+    perror (_("fcntl: F_SETFD"));
+
+  if (is_new)
+    {
+      ysd->dom_pnext = __ypbindlist;
+      __ypbindlist = ysd;
+    }
+
+  if (NULL != ypdb)
+    *ypdb = ysd;
+
+  return YPERR_SUCCESS;
+}
+
+static void
+__yp_unbind (dom_binding *ydb)
+{
+  clnt_destroy (ydb->dom_client);
+  ydb->dom_client = NULL;
+  ydb->dom_socket = -1;
+}
+
+static int
+do_ypcall (const char *domain, u_long prog, xdrproc_t xargs,
+	   caddr_t req, xdrproc_t xres, caddr_t resp)
+{
+  dom_binding *ydb = NULL;
+  int try, result;
+
+  try = 0;
+  result = YPERR_YPERR;
+
+  while (try < MAXTRIES && result != RPC_SUCCESS)
+    {
+      __libc_lock_lock (ypbindlist_lock);
+
+      if (__yp_bind (domain, &ydb) != 0)
+	{
+	  __libc_lock_unlock (ypbindlist_lock);
+	  return YPERR_DOMAIN;
+	}
+
+      result = clnt_call (ydb->dom_client, prog,
+			  xargs, req, xres, resp, TIMEOUT);
+
+      if (result != RPC_SUCCESS)
+	{
+	  clnt_perror (ydb->dom_client, "do_ypcall: clnt_call");
+	  ydb->dom_vers = -1;
+	  __yp_unbind (ydb);
+	  result = YPERR_RPC;
+	}
+
+      __libc_lock_unlock (ypbindlist_lock);
+
+      try++;
+    }
+
+  return result;
+}
+
+int
+yp_bind (const char *indomain)
+{
+  int status;
+
+  __libc_lock_lock (ypbindlist_lock);
+
+  status = __yp_bind (indomain, NULL);
+
+  __libc_lock_unlock (ypbindlist_lock);
+
+  return status;
+}
+
+void
+yp_unbind (const char *indomain)
+{
+  dom_binding *ydbptr, *ydbptr2;
+
+  __libc_lock_lock (ypbindlist_lock);
+
+  ydbptr2 = NULL;
+  ydbptr = __ypbindlist;
+  while (ydbptr != NULL)
+    {
+      if (strcmp (ydbptr->dom_domain, indomain) == 0)
+	{
+	  dom_binding *work;
+
+	  work = ydbptr;
+	  if (ydbptr2 == NULL)
+	    __ypbindlist = __ypbindlist->dom_pnext;
+	  else
+	    ydbptr2 = ydbptr->dom_pnext;
+	  __yp_unbind (work);
+	  free (work);
+	  break;
+	}
+      ydbptr2 = ydbptr;
+      ydbptr = ydbptr->dom_pnext;
+    }
+
+  __libc_lock_unlock (ypbindlist_lock);
+
+  return;
+}
+
+__libc_lock_define_initialized (static, domainname_lock)
+
+int
+yp_get_default_domain (char **outdomain)
+{
+  int result = YPERR_SUCCESS;;
+  *outdomain = NULL;
+
+  __libc_lock_lock (domainname_lock);
+
+  if (__ypdomainname[0] == '\0')
+    {
+      if (getdomainname (__ypdomainname, MAXHOSTNAMELEN))
+	result = YPERR_NODOM;
+      else
+	*outdomain = __ypdomainname;
+    }
+  else
+    *outdomain = __ypdomainname;
+
+  __libc_lock_unlock (domainname_lock);
+
+  return result;
+}
+
+int
+__yp_check (char **domain)
+{
+  char *unused;
+
+  if (__ypdomainname[0] == '\0')
+    if (yp_get_default_domain (&unused))
+      return 0;
+    else if (strcmp (__ypdomainname, "(none)") == 0)
+      return 0;
+
+  if (domain)
+    *domain = __ypdomainname;
+
+  if (yp_bind (__ypdomainname) == 0)
+    return 1;
+  return 0;
+}
+
+int
+yp_match (const char *indomain, const char *inmap, const char *inkey,
+	  const int inkeylen, char **outval, int *outvallen)
+{
+  ypreq_key req;
+  ypresp_val resp;
+  int result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap[0] == '\0' ||
+      inkey == NULL || inkey[0] == '\0' || inkeylen <= 0)
+    return YPERR_BADARGS;
+
+  req.domain = indomain;
+  req.map = inmap;
+  req.key.keydat_val = inkey;
+  req.key.keydat_len = inkeylen;
+
+  *outval = NULL;
+  *outvallen = 0;
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key,
+		      (caddr_t) & req, (xdrproc_t) xdr_ypresp_val,
+		      (caddr_t) & resp);
+
+  if (result != RPC_SUCCESS)
+    return result;
+  if (resp.stat != YP_TRUE)
+    return ypprot_err (resp.stat);
+
+  *outvallen = resp.val.valdat_len;
+  *outval = malloc (*outvallen + 1);
+  memcpy (*outval, resp.val.valdat_val, *outvallen);
+  (*outval)[*outvallen] = '\0';
+
+  xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp);
+
+  return YPERR_SUCCESS;
+}
+
+int
+yp_first (const char *indomain, const char *inmap, char **outkey,
+	  int *outkeylen, char **outval, int *outvallen)
+{
+  ypreq_nokey req;
+  ypresp_key_val resp;
+  int result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap[0] == '\0')
+    return YPERR_BADARGS;
+
+  req.domain = indomain;
+  req.map = inmap;
+
+  *outkey = *outval = NULL;
+  *outkeylen = *outvallen = 0;
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey,
+		      (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
+		      (caddr_t) & resp);
+
+  if (result != RPC_SUCCESS)
+    return result;
+  if (resp.stat != YP_TRUE)
+    return ypprot_err (resp.stat);
+
+  *outkeylen = resp.key.keydat_len;
+  *outkey = malloc (*outkeylen + 1);
+  memcpy (*outkey, resp.key.keydat_val, *outkeylen);
+  (*outkey)[*outkeylen] = '\0';
+  *outvallen = resp.val.valdat_len;
+  *outval = malloc (*outvallen + 1);
+  memcpy (*outval, resp.val.valdat_val, *outvallen);
+  (*outval)[*outvallen] = '\0';
+
+  xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
+
+  return YPERR_SUCCESS;
+}
+
+int
+yp_next (const char *indomain, const char *inmap, const char *inkey,
+	 const int inkeylen, char **outkey, int *outkeylen, char **outval,
+	 int *outvallen)
+{
+  ypreq_key req;
+  ypresp_key_val resp;
+  int result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap[0] == '\0' ||
+      inkeylen <= 0 || inkey == NULL || inkey[0] == '\0')
+    return YPERR_BADARGS;
+
+  req.domain = indomain;
+  req.map = inmap;
+  req.key.keydat_val = inkey;
+  req.key.keydat_len = inkeylen;
+
+  *outkey = *outval = NULL;
+  *outkeylen = *outvallen = 0;
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key,
+		      (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val,
+		      (caddr_t) & resp);
+
+  if (result != RPC_SUCCESS)
+    return result;
+  if (resp.stat != YP_TRUE)
+    return ypprot_err (resp.stat);
+
+  *outkeylen = resp.key.keydat_len;
+  *outkey = malloc (*outkeylen + 1);
+  memcpy (*outkey, resp.key.keydat_val, *outkeylen);
+  (*outkey)[*outkeylen] = '\0';
+  *outvallen = resp.val.valdat_len;
+  *outval = malloc (*outvallen + 1);
+  memcpy (*outval, resp.val.valdat_val, *outvallen);
+  (*outval)[*outvallen] = '\0';
+
+  xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp);
+
+  return YPERR_SUCCESS;
+}
+
+int
+yp_master (const char *indomain, const char *inmap, char **outname)
+{
+  ypreq_nokey req;
+  ypresp_master resp;
+  int result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap[0] == '\0')
+    return YPERR_BADARGS;
+
+  req.domain = indomain;
+  req.map = inmap;
+
+  memset (&resp, '\0', sizeof (ypresp_master));
+
+  result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey,
+	  (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp);
+
+  if (result != RPC_SUCCESS)
+    return result;
+  if (resp.stat != YP_TRUE)
+    return ypprot_err (resp.stat);
+
+  *outname = strdup (resp.peer);
+  xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp);
+
+  return YPERR_SUCCESS;
+}
+
+int
+yp_order (const char *indomain, const char *inmap, unsigned int *outorder)
+{
+  struct ypreq_nokey req;
+  struct ypresp_order resp;
+  int result;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap == '\0')
+    return YPERR_BADARGS;
+
+  req.domain = indomain;
+  req.map = inmap;
+
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey,
+	   (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp);
+
+  if (result != RPC_SUCCESS)
+    return result;
+  if (resp.stat != YP_TRUE)
+    return ypprot_err (resp.stat);
+
+  *outorder = resp.ordernum;
+  xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp);
+
+  return YPERR_SUCCESS;
+}
+
+static void *ypall_data;
+static int (*ypall_foreach) ();
+
+static bool_t
+__xdr_ypresp_all (XDR * xdrs, u_long * objp)
+{
+  while (1)
+    {
+      struct ypresp_all resp;
+
+      memset (&resp, '\0', sizeof (struct ypresp_all));
+      if (!xdr_ypresp_all (xdrs, &resp))
+	{
+	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	  *objp = YP_YPERR;
+	  return (FALSE);
+	}
+      if (resp.more == 0)
+	{
+	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	  *objp = YP_NOMORE;
+	  return (FALSE);
+	}
+
+      switch (resp.ypresp_all_u.val.stat)
+	{
+	case YP_TRUE:
+	  {
+	    char key[resp.ypresp_all_u.val.key.keydat_len + 1];
+	    char val[resp.ypresp_all_u.val.val.valdat_len + 1];
+	    int keylen = resp.ypresp_all_u.val.key.keydat_len;
+	    int vallen = resp.ypresp_all_u.val.val.valdat_len;
+
+	    *objp = YP_TRUE;
+	    memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen);
+	    key[keylen] = '\0';
+	    memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen);
+	    val[vallen] = '\0';
+	    xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	    if ((*ypall_foreach) (*objp, key, keylen,
+				  val, vallen, ypall_data))
+	      return TRUE;
+	  }
+	  break;
+	case YP_NOMORE:
+	  *objp = YP_NOMORE;
+	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	  return TRUE;
+	  break;
+	default:
+	  *objp = resp.ypresp_all_u.val.stat;
+	  xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp);
+	  return TRUE;
+	}
+    }
+}
+
+int
+yp_all (const char *indomain, const char *inmap,
+	const struct ypall_callback *incallback)
+{
+  struct ypreq_nokey req;
+  dom_binding *ydb;
+  int try, result;
+  struct sockaddr_in clnt_sin;
+  CLIENT *clnt;
+  unsigned long status;
+  int clnt_sock;
+
+  if (indomain == NULL || indomain[0] == '\0' ||
+      inmap == NULL || inmap == '\0')
+    return YPERR_BADARGS;
+
+  try = 0;
+  result = YPERR_YPERR;
+
+  while (try < MAXTRIES && result != RPC_SUCCESS)
+    {
+      __libc_lock_lock (ypbindlist_lock);
+
+      if (__yp_bind (indomain, &ydb) != 0)
+	{
+	  __libc_lock_unlock (ypbindlist_lock);
+	  return YPERR_DOMAIN;
+	}
+
+      /* YPPROC_ALL get its own TCP channel to ypserv */
+      clnt_sock = RPC_ANYSOCK;
+      clnt_sin = ydb->dom_server_addr;
+      clnt_sin.sin_port = 0;
+      clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
+      if (clnt == NULL)
+	{
+	  puts ("yp_all: clnttcp_create failed");
+	  __libc_lock_unlock (ypbindlist_lock);
+	  return YPERR_PMAP;
+	}
+      req.domain = indomain;
+      req.map = inmap;
+
+      ypall_foreach = incallback->foreach;
+      ypall_data = (void *) incallback->data;
+
+      result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey, &req,
+			  (xdrproc_t) __xdr_ypresp_all, &status, TIMEOUT);
+
+      if (result != RPC_SUCCESS)
+	{
+	  clnt_perror (ydb->dom_client, "yp_all: clnt_call");
+	  clnt_destroy (clnt);
+	  __yp_unbind (ydb);
+	  result = YPERR_RPC;
+	}
+      else
+	{
+	  clnt_destroy (clnt);
+	  result = YPERR_SUCCESS;
+	}
+
+      __libc_lock_unlock (ypbindlist_lock);
+
+      if (status != YP_NOMORE)
+	return ypprot_err (status);
+      try++;
+    }
+
+  return result;
+}
+
+int
+yp_maplist (const char *indomain, struct ypmaplist **outmaplist)
+{
+  struct ypresp_maplist resp;
+  int result;
+
+  if (indomain == NULL || indomain[0] == '\0')
+    return YPERR_BADARGS;
+
+  memset (&resp, '\0', sizeof (resp));
+
+  result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname,
+    (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp);
+
+  if (result != RPC_SUCCESS)
+    return result;
+  if (resp.stat != YP_TRUE)
+    return ypprot_err (resp.stat);
+
+  *outmaplist = resp.maps;
+  /* We give the list not free, this will be done by ypserv
+     xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */
+
+  return YPERR_SUCCESS;
+}
+
+const char *
+yperr_string (const int error)
+{
+  switch (error)
+    {
+    case YPERR_SUCCESS:
+      return _("Success");
+    case YPERR_BADARGS:
+      return _("Request arguments bad");
+    case YPERR_RPC:
+      return _("RPC failure on NIS operation");
+    case YPERR_DOMAIN:
+      return _("Can't bind to server which serves this domain");
+    case YPERR_MAP:
+      return _("No such map in server's domain");
+    case YPERR_KEY:
+      return _("No such key in map");
+    case YPERR_YPERR:
+      return _("Internal NIS error");
+    case YPERR_RESRC:
+      return _("Local resource allocation failure");
+    case YPERR_NOMORE:
+      return _("No more records in map database");
+    case YPERR_PMAP:
+      return _("Can't communicate with portmapper");
+    case YPERR_YPBIND:
+      return _("Can't communicate with ypbind");
+    case YPERR_YPSERV:
+      return _("Can't communicate with ypserv");
+    case YPERR_NODOM:
+      return _("Local domain name not set");
+    case YPERR_BADDB:
+      return _("NIS map data base is bad");
+    case YPERR_VERS:
+      return _("NIS client/server version mismatch - can't supply service");
+    case YPERR_ACCESS:
+      return _("Permission denied");
+    case YPERR_BUSY:
+      return _("Database is busy");
+    }
+  return _("Unknown NIS error code");
+}
+
+int
+ypprot_err (const int code)
+{
+  switch (code)
+    {
+    case YP_TRUE:
+      return YPERR_SUCCESS;
+    case YP_NOMORE:
+      return YPERR_NOMORE;
+    case YP_FALSE:
+      return YPERR_YPERR;
+    case YP_NOMAP:
+      return YPERR_MAP;
+    case YP_NODOM:
+      return YPERR_DOMAIN;
+    case YP_NOKEY:
+      return YPERR_KEY;
+    case YP_BADOP:
+      return YPERR_YPERR;
+    case YP_BADDB:
+      return YPERR_BADDB;
+    case YP_YPERR:
+      return YPERR_YPERR;
+    case YP_BADARGS:
+      return YPERR_BADARGS;
+    case YP_VERS:
+      return YPERR_VERS;
+    }
+  return YPERR_YPERR;
+}
+
+const char *
+ypbinderr_string (const int error)
+{
+  switch (error)
+    {
+    case 0:
+      return _("Success");
+    case YPBIND_ERR_ERR:
+      return _("Internal ypbind error");
+    case YPBIND_ERR_NOSERV:
+      return _("Domain not bound");
+    case YPBIND_ERR_RESC:
+      return _("System resource allocation failure");
+    default:
+      return _("Unknown ypbind error");
+    }
+}
+
+
+#define WINDOW 60
+
+int
+yp_update (char *domain, char *map, unsigned ypop,
+	   char *key, int keylen, char *data, int datalen)
+{
+#if 0
+  union
+    {
+      ypupdate_args update_args;
+      ypdelete_args delete_args;
+    }
+  args;
+  xdrproc_t xdr_argument;
+  unsigned res = 0;
+  CLIENT *clnt;
+  char *master;
+  struct sockaddr saddr;
+  char servername[MAXNETNAMELEN + 1];
+  int r;
+
+  if (!domain || !map || !key || (ypop != YPOP_DELETE && !data))
+    return YPERR_BADARGS;
+
+  args.update_args.mapname = map;
+  args.update_args.key.yp_buf_len = keylen;
+  args.update_args.key.yp_buf_val = key;
+  args.update_args.datum.yp_buf_len = datalen;
+  args.update_args.datum.yp_buf_val = data;
+
+  if ((r = yp_master (domain, map, &master)) != 0)
+    return r;
+
+  if (!host2netname (servername, master, domain))
+    {
+      fputs (_("yp_update: cannot convert host to netname\n"), stderr);
+      return YPERR_YPERR;
+    }
+
+  if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL)
+    {
+      clnt_pcreateerror ("yp_update: clnt_create");
+      return YPERR_RPC;
+    }
+
+  if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr))
+    {
+      fputs (_("yp_update: cannot get server address\n"), stderr);
+      return YPERR_RPC;
+    }
+
+  switch (ypop)
+    {
+    case YPOP_CHANGE:
+    case YPOP_INSERT:
+    case YPOP_STORE:
+      xdr_argument = (xdrproc_t) xdr_ypupdate_args;
+      break;
+    case YPOP_DELETE:
+      xdr_argument = (xdrproc_t) xdr_ypdelete_args;
+      break;
+    default:
+      return YPERR_BADARGS;
+      break;
+    }
+
+  clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL);
+
+  if (clnt->cl_auth == NULL)
+    clnt->cl_auth = authunix_create_default ();
+
+again:
+  r = clnt_call (clnt, ypop, xdr_argument, &args,
+		 (xdrproc_t) xdr_u_int, &res, TIMEOUT);
+
+  if (r == RPC_AUTHERROR)
+    {
+      if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES)
+	{
+	  clnt->cl_auth = authunix_create_default ();
+	  goto again;
+	}
+      else
+	return YPERR_ACCESS;
+    }
+  if (r != RPC_SUCCESS)
+    {
+      clnt_perror (clnt, "yp_update: clnt_call");
+      return YPERR_RPC;
+    }
+  return res;
+#else
+  return YPERR_YPERR;
+#endif
+}