/* Copyright (c) 1999 Thorsten Kukuk
   Author: Thorsten Kukuk <kukuk@suse.de>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   This program 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <assert.h>
#include <locale.h>
#include <libintl.h>
#include <rpcsvc/nis.h>
#include "nis_db.h"
#include "nis_xdr.h"
#include "nisd.h"
#include "log_msg.h"

#ifndef _
#define _(String) gettext (String)
#endif

nis_result *
nis_lookup (const_nis_name name, const unsigned int flags)
{
  fputs ("nis_lookup() was called\n", stderr);
  abort ();
}

bool_t
nisd_i_am_replica (directory_obj *dir)
{
  unsigned long i;
  nis_name local_host = nis_local_host ();

  assert (dir);

  for (i = 0; i < dir->do_servers.do_servers_len; ++i)
    if (!strcasecmp (dir->do_servers.do_servers_val[i].name, local_host))
      return TRUE;

  return FALSE;
}

nis_result *
nisd_lookup (const_nis_name name, unsigned int flags)
{
  bool_t master_dir = FALSE, local_dir = FALSE, local_search = FALSE;
  nis_result *res = NULL;
  u_long dticks = 0;

  if (verbose)
    log_msg (LOG_DEBUG, "nisd_lookup (%s, %d)", name, flags);

  /* Do we serve the object ? */
  if (is_in_srvlist (name) == TRUE)
    {
      res = db_lookup (name);
      local_dir = TRUE; /* This must be correct, since we serve the name */
    }
  else
    { /* We don't serve the object itself, but maybe the parent directory ? */
      size_t buflen = strlen (name) + 1;
      char buffer[buflen];
      char *cp = nis_domain_of_r (name, buffer, buflen);

      if (is_in_srvlist (cp) == TRUE)
	res = db_lookup (cp);
    }

  if (res)
    {
      if (res->status == NIS_SUCCESS)
	{
	  nis_object *obj = NIS_RES_OBJECT (res);
	  master_dir = (nis_dir_cmp (obj->DI_data.do_servers.do_servers_val[0].name, nis_local_host ()) == SAME_NAME);
	  local_dir = nisd_i_am_replica (&obj->DI_data);
	}
      if (res->status == NIS_NOTFOUND && local_dir)
	local_search = TRUE; /* We serve the table, but don't have the
				object -> We remove the local directory. */
      dticks = res->dticks;
      nis_freeresult (res);
      res = NULL;
    }

  if (flags & MASTER_ONLY)
    {
      if (master_dir == TRUE)
	local_search = TRUE;
    }
  else
    {
      if (local_dir == TRUE)
	local_search = TRUE;
    }

  if (local_search == TRUE) /* We serve the object, so no remote NIS+ */
    {                       /* query is necessary. */
#if 0
      /* I don't think this is necessary, we call nisd_lookup from
	 nis_ocache_lookup */

      CACHE_CLOCK_DECLS;

      if ((res = calloc (1, sizeof (nis_object))) == NULL)
	return NULL;

      /* Try cache first */
      start_clock (CACHE_CLOCK);
      res->status = nis_ocache_lookup (name, CACHE_ONLY, 0, &obj);
      res->aticks = stop_clock (CACHE_CLOCK);
      if (res->status == NIS_SUCCESS)
	{
	  NIS_RES_OBJECT(res) = nis_clone_object (obj, NULL);
	  NIS_RES_NUMOBJ(res) = 1;
	  return res;
	}
#endif
      res = db_lookup (name);
      if (res->status == NIS_SUCCESS)
	{
	  res->dticks += dticks;
	  nis_ocache_insert (NIS_RES_OBJECT(res));
	  return res;
	}
#if 0
      else if (master_dir == FALSE)
	{
	  nis_freeresult (res);
	  res = NULL;
	  goto do_lookup_rpc;
	}
#endif
    }
  else
    {
#if 0
    do_lookup_rpc:
#endif
      if (verbose)
	log_msg (LOG_DEBUG, "RPCING FOR %s", name);
      res = nis_lookup (name, flags);

      if (res == NULL)
	return NULL;

      if (res->status == NIS_SUCCESS)
	nis_ocache_insert (NIS_RES_OBJECT(res));
    }

  return res;
}
