/*
	Auther	Satoshi Yasuda	7m3tjz/ad6gz
*/

#include	"trustDB.h"
#include	"db_define.h"

void	exit (int status);

void	MainLoop();
void	CloseSocket();
void	CloseChild();
char	*FindRepeater(char call[]);
void	DB_connect(void);

void main(argc, argv)
int	argc;
char	*argv[];
{
	FILE	*PidFile;

	logfile = fopen (LOGFILE, "a");
	now = time(NULL);
	fprintf (logfile, "%24.24s TrustDB Start\n",ctime(&now));
	fclose (logfile);
	TrustDB_in = 0;
	TrustDB_out = 0;
	cmdin = 0;
	cmdmode = 0;
	AutoEntry = 0;
	RepAutoEntry = 0;
	dbInPort = htons(29001);	/* default port number */
	dbOutPort = htons(29002);	/* default port number */

        PidFile = fopen ("/var/run/dstrustdb.pid","w");
        if (PidFile == NULL)
        {
		logfile = fopen (LOGFILE, "a");
		now = time(NULL);
                fprintf (logfile, "%24.24s must run on supper user\n", ctime(&now));
		fclose (logfile);
                exit(-1);
        }
        fprintf (PidFile, "%d\n",(int)getpid());
        fclose (PidFile);

        config();

        if (cmdmode == 0)
        {
                cmdin = 0;
        }
        else
        {
                cmdin = open ("/tmp/dstrustdb-cmdin", O_NONBLOCK | O_RDONLY);
                if (cmdin < 0)
                {
			logfile = fopen (LOGFILE, "a");
			now = time(NULL);
                        fprintf (logfile, "%24.24s ERROR FIFO file not open /tmp/dstrustdb-cmdin\n", ctime(&now));
			fclose (logfile);
                        cmdin = 0;
                }
        }

	DB_connect();	

	InitSocket();
	InitSignal();
	MainLoop();
}

int InitSocket(void)
{
	int	opt;
	struct	hostent	*hp;


        if ((TrustDB_in = socket(PF_INET,SOCK_DGRAM,0)) < 0){
                perror("socket:TrustDB_in");
                exit(-1);
        }

        opt=1;
        if (setsockopt(TrustDB_in,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int)) != 0){
                perror("setsockopt");
                exit(-1);
        }

        if ((TrustDB_out = socket(PF_INET,SOCK_DGRAM,0)) < 0){
                perror("socket:TrustDB_out");
                exit(-1);
        }
        opt=1;
        if (setsockopt(TrustDB_out,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int)) != 0){
                perror("setsockopt");
                exit(-1);
        }
	memset((char *)&db_out,0,sizeof(db_out));
	db_out.sin_family=PF_INET;
	db_out.sin_port=dbOutPort;
	if (bind(TrustDB_out,(struct sockaddr *)&db_out, sizeof(db_out)) == -1){
		perror("bind:db_out");
		exit(-1);
	}

        hp = gethostbyname(TrustDbDomainName);
        memcpy (&dbIP, hp->h_addr_list[0], hp->h_length);

	return(0);
}

void CloseSocket()
{
        if(TrustDB_in != 0){
                close(TrustDB_in);
                TrustDB_in = 0;
        }
        if(TrustDB_out != 0){
                close(TrustDB_out);
                TrustDB_out = 0;
        }

	PQfinish (conDB);

        logfile = fopen (LOGFILE, "a");
        now = time(NULL);
        fprintf (logfile, "%24.24s TrustDB End\n",ctime(&now));
        fclose (logfile);
	exit(0);
}

void CloseChild()
{
	int	pid;

	pid=wait(0);
	signal(SIGCLD,CloseChild);
}

int InitSignal()
{
	signal(SIGINT,CloseSocket);
	signal(SIGTERM,CloseSocket);
	signal(SIGCLD,CloseChild);

	return(0);
}

void	DB_connect(void)
{
	char	string[128];

	sprintf (string,"user=%s dbname=%s", DBUSER, DBNAME);
	conDB = PQconnectdb (string);
	if (PQstatus(conDB) == CONNECTION_BAD)
	{
		logfile = fopen (LOGFILE, "a");
		now = time(NULL);
		fprintf(logfile, "%24.24s  データベース '%s' への接続に失敗しました \n" ,ctime(&now), DBNAME);
		fprintf(logfile, "%24.24s %s\n", ctime(&now), PQerrorMessage(conDB));
		fclose (logfile);
		exit(0);
	}
}

void MainLoop(void)
{
	int	n;
	int	len,width, pid;
	fd_set	readOk,Mask;
	struct	timeval	timeout;
	char	client[64];

	FD_ZERO(&Mask);
	FD_SET(TrustDB_out, &Mask);
	FD_SET(cmdin, &Mask);
	width = TrustDB_out;
	if (width < cmdin) width = cmdin;
	width += 1;

	while(1){
		readOk = Mask;
		timeout.tv_sec = 1;
		timeout.tv_usec = 0;
		switch (select(width,(fd_set *)&readOk, NULL, NULL, &timeout)){
			case	-1:
				perror("select");
				break;
			case	0:
				break;
			default:
				if (FD_ISSET(TrustDB_out, &readOk)) {
					CheckEntry();
				}
				if(FD_ISSET(cmdin, &readOk)){
					KeyIn();
				}
				break;
		}
	}
}

int KeyIn(void)
{
	char	buf[128];

	read (cmdin, buf, sizeof(buf));

	DoKeyInCommand(buf);

	return(0);
}

int DoKeyInCommand(char *str)
{
	int	k, n;

	k = strlen(str);
	for (n = 0 ; n < k ; n++)
	{	
		if (str[n] == 0x0a) str[n] = 0x00;
		if (str[n] == 0x0d) str[n] = 0x00;
	}

	if (strlen(str))
	{
		if((strncmp(str,"end", strlen(str))==0) 
			|| strncmp(str, "exit", strlen(str)) == 0){
			killpg(getpid(),SIGTERM);
			CloseSocket();
			return(1);
		}
	}

	return(0);
}

