#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
/* #include <getopt.h> -- used only for getopt_long */
#include <sys/wait.h>
#include <signal.h>

#include "config.h"

void sig_handler(int par);

void some_init(void)
{
  users=NULL;
  areas=NULL;

  ticlist_list=NULL;
  ticlist_list_max=0;

	hatcher_areaname=NULL;
	hatcher_filename=NULL;
	hatcher_replaces=NULL;
	hatcher_desc=NULL;
	hatcher_copy=0;
	hatcher_koi8=0;
	hatcher_desc_stdin=0;

	crc32_ignore=0;
}

void usage(char *argv0)
{
  fprintf(stderr,"\n"
  "gtic "VERSION" The GNU file forwarder (FSC-0087) for fidonet-like networks\n"
  "Copyright (c) 1998, Yuri Kuzmenko <yuri@cracksoft.kiev.ua> 2:463/169\n\n"
#ifdef SECURE_CONFIG
  "Usage: gtic [-t|-m|-h] [options]\n\n"
#else
  "Usage: gtic [-t|-m|-h] [-c config_file] [options]\n\n"
#endif
	" -t - tosser, optional options\n"
	"  -i - ignore CRC32 errors\n\n"
  " -m - area manager, no options\n\n"
	" -h - hatcher, options required\n"
	"  -a areaname - name of area for hatching, required\n"
	"  -f filename - full path to file for hatching, required\n"
	"  -r replaces - \"replaces\" keyword, optional\n"
	"  -d \"desc, one line\" - description for file, optional\n"
	"  -s - read multiline desc (LDESC) from stdin (use with -d), optional\n"
	"  -C - copy file to inbound instead of hardlink(copy), optional\n"
	"  -k - use koi8-alt description recoding, optional\n\n"
#ifndef SECURE_CONFIG
  "config_file can override CONFIG_define and \"%s.config\"\n"
	,argv0
#endif
         );
  exit(1);
}

#define RUNMODE_UNKNOWN 0
#define RUNMODE_TOSSER	1
#define RUNMODE_MANAGER	2
#define RUNMODE_HATCHER	3

int main(int argc,char *argv[])
{
  char *configname=NULL;
#ifndef SECURE_CONFIG
	char *config_tmp=NULL;
#endif
  int runmode=RUNMODE_UNKNOWN;
	int i;
#ifndef NO_LOCK
  int res_fork,w;
#endif

	/* tmp */
/*	fprintf(stderr,"\n");*/

#ifndef NO_LOCK
	if(getuid()==0 || geteuid()==0 || getgid()==0 || getegid()==0)
	{
	  fprintf(stderr,"gtic CAN NOT run from root user/group\n");
		exit(-(0xdead));
	}
#endif

  srandom(time(NULL));

	while((i=getopt(argc,argv,"t?m?h?c:a:f:r:d:C?k?s?i?"))!=-1)
	{
		switch(i)
		{
#ifndef SECURE_CONFIG
			case 'c': config_tmp=optarg; break;
#endif
			
			case 't': runmode=RUNMODE_TOSSER; break;
			case 'm': runmode=RUNMODE_MANAGER; break;
			case 'h': runmode=RUNMODE_HATCHER; break;

			case 'i': crc32_ignore=1; break;
			
			case 'a': hatcher_areaname=optarg; break;
			case 'f': hatcher_filename=optarg; break;
			case 'r': hatcher_replaces=optarg; break;
			case 'd': hatcher_desc=optarg; break;
			case 'C': hatcher_copy=1; break;
			case 'k': hatcher_koi8=1; break;
			case 's': hatcher_desc_stdin=1; break;
			
			default: usage(argv[0]);
		}
	}

	if(runmode==RUNMODE_UNKNOWN)
		usage(argv[0]);

	if(runmode==RUNMODE_HATCHER)
		if(hatcher_areaname==NULL || hatcher_filename==NULL)
			usage(argv[0]);

#ifdef SECURE_CONFIG
#ifndef CONFIG
	#error ${CONFIG} must be defined in Makefile
#endif
	configname=CONFIG;
#else
	if(config_tmp)
  {
    if(access_via_stat(config_tmp,F_OK)==0)
      configname=config_tmp;
    else
      e_printf("configname %s not exist",config_tmp);
  }
  if(configname==NULL) /* config_tmp failed */
  {
    configname=xstrcpy(argv[0]);
    configname=xstrcat(configname,".config");
#ifdef CONFIG
    if(access_via_stat(configname,F_OK)) /* not exist */
      configname=CONFIG;
#endif
  }
#endif
  
  readconfig(configname);

  l_init(log_file);
  l_printf("gtic version " VERSION " started");
  l_printf("UID=%d, GID=%d, EUID=%d, EGID=%d",
		getuid(),getgid(),geteuid(),getegid());

#ifndef NO_LOCK
  if(check_lock())
  {
    l_printf("Another gtic already running (LockPipe %s)",lock_file);
    return 1;
  }

  /* Now fork. Child process work as main process, parent process work as lock
     pipe handler */
  res_fork=fork();
  if(res_fork==-1)
  {
    e_printf("unable to fork");
    abort2();
  }
  if(res_fork!=0)
  {
    /* parent, lock handler */
    touch_lock();
    e_printf("Unable to touch lockpipe %s - lock ignored.",lock_file);
    while(1)
    {
      w=waitpid(res_fork,NULL,0);
      if(w==0 || w==-1) break;
    }
    exit(0);
  }
#endif

#ifndef NO_LOCK
	while(!check_lock())
	{
		l_printf("Sucks! Our parent is brake. Sleep 1 second...");
		sleep(1);
	}
#endif

  /* child, main process */

	read_domains_file();
  readusers();
  readareas();

  if(runmode==RUNMODE_TOSSER)
  {
    readticlist();
    read_tics_from_list();
    toss();
    freeticlist();
  }
  if(runmode==RUNMODE_MANAGER)
  {
    area_manager();
    writeusers();
    writeareas();
  }
  if(runmode==RUNMODE_HATCHER)
  {
    hatcher();
  }

  exit(0);
}


syntax highlighted by Code2HTML, v. 0.9.1