/* ==== main.c ============================================================
 * Copyright (c) 1995 by Chris Provenzano, proven@mit.edu
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *  This product includes software developed by Chris Provenzano.
 * 4. The name of Chris Provenzano may not be used to endorse or promote 
 *	  products derived from this software without specific prior written
 *	  permission.
 *
 * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY 
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 * SUCH DAMAGE.
 *
 * Description : The arg parser and main loop for phttpd.
 *
 *  1.00 95/03/14 proven
 *      -Started coding this file.
 */

#include <fcntl.h>			/* For O_RDONLY */
#include <stdio.h>
#include <pthread.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include "accept_buf.h"
#include "plog.h"

#ifndef EOF
#define EOF -1
#endif

extern void * talk_to_client(void *);

void usage(int eval)
{
	fprintf(stderr, 
			"usage: phttpd [-dns] [-D <debug level>] [ -S <logfile>]\n");
	exit(eval);
}

extern int use_syslog;

short port = 8002;

void setup(void) 
{
  	struct sockaddr_in connect_addr;
  	int connect_port, len;
  	pthread_t thread_id;

    /* Setup signal handler */
/*
    if (pthread_create(&thread_id, NULL, deal_with_signal, NULL)) {
		plog_error(PLOG_ERR, "Can't create signal thread!");
		exit(1);
    }
*/

    /* Setup server */
    if ((connect_port = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		plog_error(PLOG_ERR, "socket");
		exit(1);
    }

    connect_addr.sin_family 		= AF_INET;
    connect_addr.sin_port           = htons(port);
    connect_addr.sin_addr.s_addr	= INADDR_ANY;
      
    len = sizeof(connect_addr);
    if (bind(connect_port, (struct sockaddr *)(&connect_addr), len)) {
		plog_error(PLOG_ERR, "bind");
		exit(1);
    }

    listen(connect_port, 8);

	/* Setup threads */
      
    while (1) {
		struct sockaddr_in accept_addr;
    	struct accept_buf * buf;

        /* Allocte a new accept buffer */
		buf = accept_buf_malloc();

no_malloc:
		len = sizeof(struct sockaddr_in);
        if ((buf->fd = accept(connect_port, &accept_addr, &len)) < 0) {
	    	/* This might be just a warning */
	    	plog_error(PLOG_ERR, "accept");
	    	break;
		}

		/* buf->host = find_peer_name(&accept_addr); */
	
        if (pthread_create(&thread_id, NULL, talk_to_client, (void *)buf)) {
	    	plog_error(PLOG_WARN, "pthread_create");
	    	/* Send an error back to the connector */

            /* Close connection and free buffer */
	    	close(buf->fd);
	    	goto no_malloc;
	  	}
		pthread_detach(thread_id);
    }

    /* At least let all the current connections finish */
    pthread_exit(NULL);
}

/*
void daemonize()
{
  int x;

  chdir("/");
  if((x = fork()) > 0)
    exit(0);
  else if(x == -1) 
    {
      fprintf(stderr,"kphttpd: unable to fork new process\n");
      perror("fork");
      exit(1);
    }
}
*/
void daemonize()
{
	return;
}

int main(int argc, char ** argv)
{
  	char * debug_file = NULL;
  	int debug_level = 0;
	int no_fork = 0;
  	char ch;

  	/* getopt variables */
  	extern char *optarg;
  	extern int optind;

  	while ((ch = getopt(argc, argv, "dD:nsS:")) != (char)EOF)
    	switch(ch) {
      	case 'd':   
			debug_level++;
			break;
      	case 's':
			use_syslog++;
			break;
      	case 'n':
			no_fork++;
			break;
      	case 'D':
			if ((debug_level = atoi(optarg)) <= 0) {
	    		usage(1);
	  		}
			break;
      	case 'S':
			debug_file = optarg;
			break;
      	case '?':
			usage(0);
			break;
		default:
			usage(1);
			break;
      	}

  	/* Setup syslog */
  	if (plog_open(debug_level, debug_file, argv[0]) < OK) {
		fprintf(stderr, "Can't open log files\n");
		exit(1);
    }

    /* Do some optomization here */
    /* We don't need float, they all should be FIFO, and detached */

    if (!no_fork) daemonize();

	setup();
}
      
