/*
 * Copyright (C) 1994, 1995 Free Software Foundation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can either send email to this
 * program's author (see below) or write to:
 *
 *              The Free Software Foundation, Inc.
 *              675 Mass Ave.
 *              Cambridge, MA 02139, USA. 
 *
 * Please send bug reports, etc. to zappo@gnu.ai.mit.edu.
 *
 * etalk.c
 *
 * Purpose:
 *  This file contains the startup code for initializing the udp and
 * connection sockets.  It then starts up main_loop which waits on all
 * registered file descriptors.
 *
 * $Log: etalk.c,v $
 * Revision 1.10  1995/07/16  15:42:25  zappo
 * verbosity now increments inself which each occurance of "-v"
 *
 * Revision 1.9  1995/05/09  23:48:13  zappo
 * reduced comment size, and added --copyright parameter
 *
 * Revision 1.8  1995/03/30  02:34:11  zappo
 * Signal handler now takes a dynamic type from autoconf
 *
 * Revision 1.7  1995/03/25  03:22:50  zappo
 * Updated copyright notice to 1995.
 *
 * Revision 1.6  1995/03/23  02:50:56  zappo
 * Help text wasn't perfectly lined up.
 *
 * Revision 1.5  1995/03/04  14:45:12  zappo
 * Added syslogdebug variable needed to link against etalklib
 *
 * Revision 1.4  1995/02/11  17:47:55  zappo
 * Added signal handling to prevent ringer files from being left around
 * when someone ungracefully terminates etalk.
 *
 * Revision 1.3  1995/01/28  16:12:32  zappo
 * Removed some command line options, and setup new ringer socket.
 *
 * Revision 1.2  1994/10/11  00:32:00  zappo
 * Initial GETOPT version.
 *
 * Revision 1.1  1994/08/29  23:36:53  zappo
 * Initial revision
 *
 * History:
 * eml 8/17/94
 * Added call to check for sizes of net messages.  Will serve as a
 * preliminary check to make everything is kool.
 *
 * ::Header:: etalk.h */
#include "getopt.h"
#include "etalklib.h"
#include "etalk.h"

#if HAVE_SIGNAL_H == 1
#include <signal.h>
#endif

int verbose     = FALSE;	/* verbosity variable            */
int syslogdebug = FALSE;	/* syslogdebug variable          */
struct TalkContext Ctxt;	/* context of this talk instance */

extern RETSIGTYPE etalk_sighandle(); /* signal handler function       */

int main(argc, argv)
     int   argc;
     char *argv[];
{
  int                local_test_flag = FALSE;

  /* First things first, install signal handlers.  Need this to zap */
  /* rogue invites/etc, and to zap .ringer files.                   */
  signal(SIGHUP, etalk_sighandle);
  signal(SIGINT, etalk_sighandle);
  signal(SIGKILL, etalk_sighandle);
  signal(SIGTERM, etalk_sighandle);

  printf("%s\n", ETALK_);

  /* Default value of socketflag. */
  Ctxt.socketflag = TRUE;

  /* Here is a chunk from the GNU getopt manual page with the correct
   * extensions for etalk.
   */
  while(1)
    {
      int option_index = 0;	/* options returned index */
      int c;			/* return value           */
      static char *short_options = "?Chtv";
      static struct option long_options[] =
	{
	  { "copyrite", FALSE, NULL, 'C' },
	  { "help", FALSE, NULL, 'h' },
	  { "test", FALSE, NULL, 't' },
	  { "verbose", FALSE, NULL, 'v' },
	  { "version", FALSE, NULL, 0 },
	  { NULL, FALSE, NULL, 0 }
	};

      c = getopt_long(argc, argv, short_options,
		      long_options, &option_index);

      if(c == -1) break;
            
      switch(c) {
      case 0:
	/* version is the only weird one, and it has already been
	 * printed, so just exit
	 */
	exit(0);
      case 'C':
	CW_display_copywrite();
	exit(0);
      case 'h':
      case '?':
	printf("Etalk command line options:\n");
	printf(" --copyright\t-C\tDisplay copyright information.\n");
	printf(" --help\t\t-h,-?\tPrint this help.\n");
	printf(" --test\t\t-t\tRun system verification test.\n");
	printf(" --verbose\t-v\tPrint debugging information as we go.\n");
	printf(" --version\t\tPrint version and exit.\n\n");
	printf("Etalk currently only supports communication through sockets.\n");
	exit(0);
      case 't':
	local_test_flag = TRUE;
	break;
      case 'v':
	verbose++;
	printf("Verbosity Set to %d.\n", verbose);
	break;
      default:
	printf("Illegal option %c\n", c);
	exit(0);
      }
    }
  
  Ctxt.myname        = NULL;
  Ctxt.myappname     = NULL;
  Ctxt.message_delay = 30;
  Ctxt.ringerflag    = 0;

  if(DMN_check_compile() == Fail)
    /* Return error status on this check. */
    return 1;

  RC_load_all_hosts();

  printf("Initializing Network Interface.\n");

  Ctxt.me             = HOST_gen_local_host();
  /* We must set readme by hand here because the device library does not
   * not provide the reader.
   */
  Ctxt.tty            = ET_tty();
  Ctxt.tty->readme    = ETC_parse_command;

  Ctxt.emacs_connect  = TCP_listen(); /* we must set host by hand */
  Ctxt.emacs_connect->name = "emacs_connect";
  Ctxt.emacs_connect->host = Ctxt.me;
  Ctxt.emacs_connect->readme = LOCAL_new_tcp;
  Ctxt.emacs_connect->timeout = 0;

  printf("\03%c%d\n", TTY_LOCALPORT,
	 ntohs(Ctxt.emacs_connect->raddr.sin_port));

  Ctxt.remote_connect = TCP_listen();
  Ctxt.remote_connect->name = "remote_connect";
  Ctxt.remote_connect->host = Ctxt.me;
  printf("\03%c%d\n", TTY_REMOTEPORT,
	 ntohs(Ctxt.remote_connect->raddr.sin_port));

  /* Set up ringer port.  Reset UDP creators in between. */
  UDP_setup_localport();
  Ctxt.udp_ring           = UDP_host(Ctxt.me->name);
  Ctxt.udp_ring->name     = "ring_port";
  UDP_reset_ports();

  UDP_setup_localport();
  /* Set up local UDP port for discussion over talk protocol */
  Ctxt.udp_port           = UDP_host(Ctxt.me->name);
  Ctxt.udp_port->name     = "udp_port";
  Ctxt.local_daemon       = UDP_host(Ctxt.me->name);
  Ctxt.local_daemon->name = "local_daemon";
  
  /* Setup edit keys. */
  Ctxt.editkeys[0] = '';
  Ctxt.editkeys[1] = '';
  Ctxt.editkeys[2] = '';

  Ctxt.pid            = getpid();

  printf("Initialization complete.\n");

  if(local_test_flag == TRUE)
    {
      /* Run the test to see what's going on! */
      return ETC_test(&Ctxt, "");
    }
  else
    {
      /* Select loop.  This should be the only occurance with NULL as the
       * reton parameter...
       */
      ET_select_all(&Ctxt, NULL);
    }

  /* If we get here, then there is some sort of error.
   */
  return 1;
}


/*
 * Function: etalk_sighandle
 *
 *   Etalk shutdown handler.  If any unpleasant signals are trapped,
 * make sure things are cleaned up whenever possible.
 *
 * Parameters:  val - Number of val
 *
 * History:
 * zappo   2/11/95    Created
 */
RETSIGTYPE etalk_sighandle(val)
     int val;
{
  etalk_shutdown();
}


/*
 * Function: etalk_shutdown
 *
 *   Run all necessary shutdown procedures, then exit the program.
 *
 * Returns:     Nothing
 * Parameters:  None
 *
 * History:
 * zappo   2/11/95    Created
 */
void etalk_shutdown()
{
  PROTOCOL_delete_all(&Ctxt, TRUE);
  ET_close_all(&Ctxt);
  RING_deactivate();
  printf("Shutdown complete...\n");
  exit(0);
}
