
#include <mcheck.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "nis_db.h"
#include "db_private.h"

#ifndef MAX_TABLES
#define MAX_TABLES 5
#endif
#ifndef MAX_ENTRIES
#define MAX_ENTRIES 200
#endif

static table_obj *
create_table (void)
{
  table_obj *table = (table_obj *)malloc (sizeof (table_obj));
  table_col *tcol = malloc (sizeof (table_col) * 7);

  memset (table, '\0', sizeof(table_obj));
  memset (tcol, '\0', sizeof (table_col) * 7);

  table->ta_type = strdup ("passwd_tbl");
  table->ta_maxcol = 64;
  table->ta_sep = ':';
  table->ta_path = strdup ("foo");

  tcol[0].tc_name = strdup ("name");
  tcol[0].tc_flags = TA_SEARCHABLE | TA_CASE;
  tcol[0].tc_rights = DEFAULT_RIGHTS;

  tcol[1].tc_name = strdup ("passwd");
  tcol[1].tc_flags = TA_CASE;
  tcol[1].tc_rights = DEFAULT_RIGHTS;

  tcol[2].tc_name = strdup ("uid");
  tcol[2].tc_flags = TA_SEARCHABLE | TA_CASE;
  tcol[2].tc_rights = DEFAULT_RIGHTS;

  tcol[3].tc_name = strdup ("gid");
  tcol[3].tc_flags = TA_SEARCHABLE | TA_CASE;
  tcol[3].tc_rights = DEFAULT_RIGHTS;

  tcol[4].tc_name = strdup ("gecos");
  tcol[4].tc_flags = TA_CASE;
  tcol[4].tc_rights = DEFAULT_RIGHTS;

  tcol[5].tc_name = strdup ("home");
  tcol[5].tc_flags = TA_CASE;
  tcol[5].tc_rights = DEFAULT_RIGHTS;

  tcol[6].tc_name = strdup ("shell");
  tcol[6].tc_flags = TA_SEARCHABLE | TA_CASE;
  tcol[6].tc_rights = DEFAULT_RIGHTS;

  table->ta_cols.ta_cols_len = 7;
  table->ta_cols.ta_cols_val = tcol;

  return table;
}

static entry_obj *
create_entry (unsigned int number)
{
  entry_obj *entry;
  entry_col *col;
  char buf[1024];

  entry = (entry_obj *)calloc(1, sizeof(entry_obj));
  col = (entry_col *)calloc(1, sizeof(entry_col) * 7);

  /* Username */
  sprintf (buf, "user%.6d", number);
  col[0].ec_flags = 0;
  col[0].ec_value.ec_value_val = strdup (buf);
  col[0].ec_value.ec_value_len = strlen(col[0].ec_value.ec_value_val) + 1;

  col[1].ec_flags = 0;
  col[1].ec_value.ec_value_val = strdup ("*");
  col[1].ec_value.ec_value_len = strlen(col[1].ec_value.ec_value_val) + 1;

  /* uid */
  sprintf (buf, "%d", number);
  col[2].ec_flags = 0;
  col[2].ec_value.ec_value_val = strdup (buf);
  col[2].ec_value.ec_value_len = strlen(col[2].ec_value.ec_value_val) + 1;

  col[3].ec_flags = 0;
  col[3].ec_value.ec_value_val = strdup ("0");
  col[3].ec_value.ec_value_len = strlen(col[3].ec_value.ec_value_val) + 1;

  col[4].ec_flags = 0;
  col[4].ec_value.ec_value_val = strdup ("This is a sample account");
  col[4].ec_value.ec_value_len = strlen(col[4].ec_value.ec_value_val) + 1;

  col[5].ec_flags = 0;
  col[5].ec_value.ec_value_val = strdup ("/dev/null");
  col[5].ec_value.ec_value_len = strlen(col[5].ec_value.ec_value_val) + 1;

  col[6].ec_flags = 0;
  col[6].ec_value.ec_value_val = strdup ("/bin/false");
  col[6].ec_value.ec_value_len = strlen(col[6].ec_value.ec_value_val) + 1;

  entry->en_type = strdup ("passwd_tbl");
  entry->en_cols.en_cols_len = 7;
  entry->en_cols.en_cols_val = col;

  return entry;
}

int
main (int argc, char *argv[])
{
  char *catalog_file = "data.dict";
  unsigned int i;
  db_result *result;
  nis_attr *attrs;
  int no_unlink = 0;
  table_obj *obj;
  entry_obj *eobj;

  if (argc == 2 && strcmp (argv[1], "-n") == 0)
    no_unlink = 1;

  mtrace ();

  /* Initialize the database backend */
  if (db_initialize (catalog_file) == FALSE)
    {
      fprintf (stderr, "db_initialize (%s) failed.\n", catalog_file);
      return 1;
    }

  attrs = (nis_attr *)calloc(1, sizeof(nis_attr) * 7);

  attrs[0].zattr_ndx = "name";
  attrs[0].zattr_val.zattr_val_len = 1;
  attrs[0].zattr_val.zattr_val_val = "";

  attrs[1].zattr_ndx = "uid";
  attrs[1].zattr_val.zattr_val_len = strlen("0") + 1;
  attrs[1].zattr_val.zattr_val_val = "0";

  for (i = 0; i < MAX_TABLES; ++i)
    {
      db_status status;
      char buf[255];
      unsigned int j;

      sprintf (buf, "table_%.8d", i);
      obj = create_table ();
      status = db_create_table (buf, obj);
      xdr_free ((xdrproc_t) __nisdb_xdr_table_obj, (caddr_t)obj);
      free (obj);
      if (status != DB_SUCCESS)
	{
	  fprintf (stderr, "db_create_table (\"%s\") failed: %d\n", buf,
		   status);
	  return 1;
	}

      for (j = 0; j < MAX_ENTRIES; ++j)
	{
	  eobj = create_entry (j);
	  result = db_add_entry (buf, 1, attrs, eobj);
	  xdr_free ((xdrproc_t) __nisdb_xdr_entry_obj, (caddr_t)eobj);
	  free (eobj);
	  if (result->status != DB_SUCCESS)
	    {
	      fprintf (stderr, "db_add_entry (\"%s\", %d) failed: %d\n",
		       buf, j, result->status);
	      return 1;
	    }
	  db_free_result (result);

	  status = db_standby (buf);
	  if (status != DB_SUCCESS)
	    {
	      fprintf (stderr, "db_standby (\"%s\") failed: %d\n", buf,
		       status);
	      return 1;
	    }
	}

      status = db_unload_table (buf);
      if (status != DB_SUCCESS)
	{
	  fprintf (stderr, "db_unload_table (\"%s\") failed: %d\n", buf,
		   status);
	  return 1;
	}
    }

  eobj = create_entry(00000);
  result = db_add_entry ("table_00000000", 1, attrs, eobj);
  xdr_free ((xdrproc_t) __nisdb_xdr_entry_obj, (caddr_t) eobj);
  free (eobj);
  if (result->status != DB_SUCCESS)
    {
      fprintf (stderr, "db_add_entry (\"%s\", 00000) failed: %d\n",
	       "table_0000000", result->status);
      return 1;
    }
  db_free_result (result);

  eobj = create_entry(00000);
  result = db_add_entry ("table_00000000", 1, attrs, eobj);
  xdr_free ((xdrproc_t) __nisdb_xdr_entry_obj, (caddr_t) eobj);
  free (eobj);
  if (result->status != DB_SUCCESS)
    {
      fprintf (stderr, "db_add_entry (\"%s\", 00000) failed: %d\n",
	       "table_0000000", result->status);
      return 1;
    }
  db_free_result (result);

  attrs[0].zattr_val.zattr_val_len = 11;
  attrs[0].zattr_val.zattr_val_val = "user000000";

  eobj = create_entry(00000);
  result = db_add_entry ("table_00000000", 1, attrs, eobj);
  xdr_free ((xdrproc_t) __nisdb_xdr_entry_obj, (caddr_t) eobj);
  free (eobj);
  if (result->status != DB_NOTUNIQUE)
    {
      fprintf (stderr, "db_add_entry (\"%s\", 00000) failed: %d\n",
	       "table_0000000", result->status);
      fprintf (stderr, "result should be %d.\n", DB_NOTUNIQUE);
      return 1;
    }
  db_free_result (result);

  attrs[0].zattr_val.zattr_val_len = 1;
  attrs[0].zattr_val.zattr_val_val = "";

  /* At least one attr is required */
  eobj = create_entry(100000);
  result = db_add_entry ("table_00000000", 0, NULL, eobj);
  xdr_free ((xdrproc_t) __nisdb_xdr_entry_obj, (caddr_t) eobj);
  free (eobj);
  if (result->status != DB_BADQUERY)
    {
      fprintf (stderr, "db_add_entry (\"%s\", 100000) failed: %d\n",
	       "table_0000000", result->status);
      fprintf (stderr, "result should be %d.\n", DB_BADQUERY);
      return 1;
    }
  db_free_result (result);

  free (attrs);

  for (i = 0; i < MAX_TABLES; ++i)
    {
      db_status status;
      char buf[255];

      sprintf (buf, "table_%.8d", i);

      status = db_checkpoint (buf);
      if (status != DB_SUCCESS)
	{
	  fprintf (stderr, "db_checkpoint (\"%s\") failed: %d\n", buf,
		   status);
	  return 1;
	}

      status = db_destroy_table (buf);
      if (status != DB_SUCCESS)
	{
	  fprintf (stderr, "db_destroy_table (\"%s\") failed: %d\n", buf,
		   status);
	  return 1;
	}
    }

  if (!no_unlink)
    {
      unlink ("data.dict");
      unlink ("data.dict.log");
    }

  muntrace ();

  return 0;
}
