/*
 * Copyright 1990 by Baylor College of Medicine ALL RIGHTS RESERVED. 
 *
 * This program is subject to a license agreement between 
 * Baylor College of Medicine and MIT. Any use inconsistent with
 * said license and any use by persons other than the faculty, 
 * students and staff at MIT or any use on a computer not operated 
 * as part of the Athena Computing Environment (ACE) is expressly 
 * prohibited.
 */
/****************************************************************
 * File: dbsrv.c 
 * Date: 01/17/91
 * Description:
 *   This program does all interfacing to the database.  It listens
 *   for connection requests and attempts to service all info requests
 *   with that connection.  It also allows the actions of one information
 *   client to affect other clients.
 * Revisions:
 ****************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <signal.h>
#include <pwd.h>

#include "dbsrv.h"

static
void
usage(name,fp)
	char *name;
	FILE *fp;
{
	fprintf(fp,"Usage: %s <db directory> <port> <db name> ",name);
	fprintf(fp,"[<db name 2> ... <db name n>]\n") ;
}

static
int
isnumber(s)
	char *s;
{
	int i = 0;

	while (s[i] != '\0')
	{
		if (isdigit(s[i]))
		{
			++i;
		}
		else
		{
			return 0;
		}
	}

	return 1;
}

dbsrv_main(argc,argv)
	char *argv[] ;
{
	struct stat st;

	/* printout the version number and protocol number */
	printf("%s(%d.%d.%d): ",argv[0],DBSRV_MAJOR,DBSRV_MINOR,DBSRV_RELEASE);
	printf("protocol(%d.%d)\n",VNS_PROTO_MAJOR,VNS_PROTO_MINOR);

	/* initialize list of databases to NULL */
	pc.dbs = NULL;

	/* check for the correct number of arguments */
	if (argc < 4)
	{
		usage(argv[0],stdout);
		exit(-1) ;
	}

	/* Check the database directory path specified */
	if (stat(argv[1],&st) < 0 || !(st.st_mode & S_IFDIR))
	{
		fprintf(stdout,"dbsrv: error: %s is not a valid directory\n",argv[1]);
		usage(argv[0],stdout);
		exit(-1);
	}
	else
	{
		strcpy(pc.data_dir,argv[1]) ;
	}

	/* convert the third arguement string to the port number */
	if (isnumber(argv[2]) != 0)
	{
		pc.port = atoi(argv[2]);
	}
	else
	{
		fprintf(stdout,"dbsrv: Error: port was not specified as a number:");
		fprintf(stdout," %s\n",argv[2]);
		usage(argv[0],stdout);
		exit(-1);
	}

	/* Initialize connection to Database */
	{
		int err = dbsrvinit_db() ;
		if (err < 0)
		{
			fprintf(stderr,"dbsrv: error: Could not connect to SQL database.");
			fprintf(stderr," (err = %d)\n",err) ;
			exit(-1) ;
		}
	}

	fprintf(stdout,"dbsrv: data directory: %s",pc.data_dir);
	fprintf(stdout," port: %d\n",pc.port);

	/* Load all of the databases */
	{
		int i ;
		for(i = 3; i < argc; i++)
		{
			char buf[512];
			sprintf(buf,"%s/%s",pc.data_dir,argv[i]);
			if (stat(buf,&st) < 0 || !(st.st_mode & S_IFDIR))
			{
				fprintf(stdout,"dbsrv: warning: invalid db: %s",argv[i]);
				fprintf(stdout," (loading ignored)\n");
			}
			else
			{
				fprintf(stdout,"Loading: %s\n",argv[i]);
				load_database(argv[i]) ;
			}
		}
	}

	/* if no database were loaded then issue error message and abort */
	if (pc.dbs == NULL)
	{
		fprintf(stdout,"dbsrv: error: no databases were loaded\n");
		usage(argv[0],stdout);
		exit(-1);
	}

	/* find the vns user id */
	{
		struct passwd *pwd = getpwnam("vns");
		if (pwd == NULL)
		{
			pc.vns_uid = -1;
		}
		else
		{
			pc.vns_uid = pwd->pw_uid;
		}
	}

	/* Initialize the listening socket (Connection requests) */
	{
		int err = dbsrv_init_listen(pc.port) ;
		if (err < 0)
		{
			fprintf(stderr,"dbsrv: error: Could not establish listening ");
			fprintf(stderr,"socket. (err = %d)\n",err) ;
			exit(-2) ;
		}
	}

	/* Ignore pipe errors */
	signal(SIGPIPE,SIG_IGN) ;

	fprintf(stdout,"dbsrv: message: entering main loop\n");

	/* Go into infinite loop waiting for client connections and requests */
	for(;;)
	{
		dbsrv_process_requests() ;
	}
}
