#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include "directory.h"
#include <sys/stat.h>
#ifdef HAS_NDBM_H
#include <ndbm.h>
#else
#include <dbm.h>
#endif
#include "xutil.h"
#include "lutil.h"
#include "ftn.h"
#include "config.h"
#include "nodecheck.h"
#include "nlindex.h"

#ifndef IF_DBM_SUFFIX
#ifdef HAS_BSD_DB
#define IF_DBM_SUFFIX	".db"
#else
#define IF_DBM_SUFFIX	".dir"
#endif
#endif

#ifdef HAS_NDBM_H
DBM *nldb=NULL;
#endif
int openstatus = 0;
int n;

DIR *dp;
struct dirent *de;

struct _nodelist *nodevector;

int initnl(void)
{
	int i,rc;
	fa_list *tmp;
	time_t lastmtime;
	struct stat stbuf;
	char *indexnm,*nlnm=NULL,*p;

	if (openstatus > 1) return openstatus;
	if (openstatus == 1) return 0;

	n=0;
	for (tmp=nllist;tmp;tmp=tmp->next) n++;
	debug(20,"Initialize %d nodelists",n);

	nodevector=(struct _nodelist *)xmalloc(n * sizeof(struct _nodelist));

	lastmtime=configtime;
	i=0;
	for (tmp=nllist;tmp;tmp=tmp->next)
	{
		if (tmp->addr->domain)
			nodevector[i].domain=tmp->addr->domain;
		else if (whoami->addr->domain)
			nodevector[i].domain=whoami->addr->domain;
		else
			nodevector[i].domain="fidonet";

		nlnm=xstrcpy(tmp->addr->name);
		if ((rc=stat(tmp->addr->name,&stbuf)) != 0)
		{
			int next,mext=0;

			if (nlnm) free(nlnm);
			if ((nlnm=strrchr(tmp->addr->name,'/')))
				nlnm++;
			else nlnm=tmp->addr->name;
			if (dp == NULL) dp=opendir(nlbase);
			if (dp != NULL)
			{
				rewinddir(dp);
				while ((de=readdir(dp)))
				if (strncmp(de->d_name,nlnm,strlen(nlnm)) == 0)
				{
					p=(de->d_name)+strlen(nlnm);
					if ((*p == '.') && (strlen(p) == 4) &&
					    (strspn(p+1,"0123456789") == 3))
					{
						next=atoi(p+1);
						if (next > mext) mext=next;
					}
				}
			}
			else logerr("$cannot open \"%s\" directory",S(nlbase));
			nlnm=xstrcpy(tmp->addr->name);
			nlnm=xstrcat(nlnm,".999");
			sprintf(nlnm+strlen(nlnm)-3,"%03d",mext);
			debug(20,"try \"%s\" nodelist",S(nlnm));
			rc=stat(nlnm,&stbuf);
		}
		if (rc == 0)
		{
			if (stbuf.st_mtime > lastmtime) 
				lastmtime=stbuf.st_mtime;
			nodevector[i].fp=fopen(nlnm,"r");
			if (nodevector[i].fp == NULL)
				logerr("$cannot open nodelist \"%s\"",S(nlnm));
			else debug(20,"opened nodelist \"%s\"",S(nlnm));
		}
		else
		{
			logerr("$cannot stat nodelist \"%s\"",
				S(tmp->addr->name));
			nodevector[i].fp=NULL;
		}
		i++;
		if (nlnm) free(nlnm);
	}

	if (dp != NULL) closedir(dp);
	dp=NULL;

	for (i=0;i<n;i++)
	{
		debug(20,"nodelist: %3d: %-08s %08lx",
			i,nodevector[i].domain,nodevector[i].fp);
	}

	indexnm=xstrcpy(nlbase);
	indexnm=xstrcat(indexnm,INDEX);
	indexnm=xstrcat(indexnm,IF_DBM_SUFFIX);
	if ((stat(indexnm,&stbuf) != 0) || (stbuf.st_mtime < lastmtime)) rc=1;
	else rc=0;

	indexnm[strlen(indexnm)-strlen(IF_DBM_SUFFIX)]='\0';
	debug(20,"Trying open existing \"%s\"",S(indexnm));
#ifdef HAS_NDBM_H
	if (nldb == NULL)
	if ((nldb=dbm_open(indexnm,O_RDONLY,0600)) == NULL)
		rc=2;
#else
	if (dbminit(indexnm) != 0) rc=2;
#endif

	free(indexnm);

	if (rc > 1)
	{
		openstatus=2;
		logerr("$cannot open nodelist index (%d)",rc);
	}
	else openstatus=1;

	return rc;
}
