/*
 * server_main.c
 *
 * $Author: dm3e $
 * $Date: 1993/01/08 19:14:32 $
 * $Revision: 1.19 $
 * $State: Exp $
 * $Locker: dm3e $
 */

/***********************************************************
        Copyright 1991 by Carnegie Mellon University

                      All Rights Reserved

Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of CMU not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.

CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
******************************************************************/

#include "emtd.h"
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <afs/cmd.h>

#define N_SECURITY_OBJECTS 2

extern              EMT_ExecuteRequest ();
extern              read_applications ();
extern int          errno,
                    rx_stackSize;
extern unsigned long admHostId;
extern unsigned short admPortId;
extern unsigned short admServiceId;


/***************************************************************************
 * [exported] emt_InitCmd
 *
 * Description:
 *      Setup the server.
 *
 * Arguments:
 *
 * Environment:
 *
 * History:
 *      Wed Jun 10 12:36:53 1992 - created by David Allen Markley
 *
 ***************************************************************************/
emt_InitCmd (syndesc, rock)
     struct cmd_syndesc *syndesc;
     char               *rock;
{
    char                path[MAXPATHLEN];
    char           *dbfile;
    struct admlib_rpc_serviceDesc serviceDesc;
    struct rx_service *service;
    char            event;
    struct timeval      tp;
    struct timezone     tzp;
    register long       code;

#ifndef DEBUG
    if (syndesc->parms[2].items)
      emt_detach ();
#endif				/* !DEBUG */

    trees = NULL;

    if (NULL != (code = Authenticate ())) {
	Log("Error authenticating (%ld).\n", code);
	exit(code);
    }
    Log ("Environment Maintenance Tool Daemon %s\n", SERVER_VERSION);
    Log ("Copyright (C) 1991, Carnegie Mellon, Pittsburgh, PA, USA\n");
    sprintf (path, "%s/emtd.config", EMTD_WORKING_DIRECTORY);
    emtd_GetConfig(path, &trees);
    emtd_GetAllTreeConfigs();
    gettimeofday (&tp, &tzp);
    srandom ((int) (tp.tv_usec));

    if (syndesc->parms[3].items)
	IF_RTN(admlib_log_SetLevel(atoi(syndesc->parms[3].items->data)));
    if (syndesc->parms[4].items)
	IF_RTN(admlib_log_SetPath(syndesc->parms[4].items->data));
    if (syndesc->parms[5].items)
	dbfile = syndesc->parms[5].items->data;
    else
	dbfile = (char *) 0;
    if (syndesc->parms[6].items)
	IF_RTN(admlib_conf_SetPath(syndesc->parms[6].items->data));
    if (syndesc->parms[7].items) {
	IF_RTN(admlib_conf_GetPortIdByPortName
	       (syndesc->parms[7].items->data, &serviceDesc.port));
    } else {
	serviceDesc.port = EMTD_RPC_PORT;
/*
  IF_RTN(admlib_conf_GetPortIdByPortName
  (EMTD_RPC_PORTNAME, &serviceDesc.port));
*/
    }

    serviceDesc.port = EMTD_RPC_PORT;
    serviceDesc.service = EMTD_RPC_SERVICE;
    serviceDesc.name = EMTD_RPC_NAME;
    serviceDesc.level = (rxkad_level) rxkad_crypt;
    serviceDesc.proc = EMT_ExecuteRequest;
    serviceDesc.maxProcs = 3;
    serviceDesc.minProcs = 3;

    IF_RTN(emt_rpc_NewService(&serviceDesc, &service));
    rx_SetStackSize(service, 131072);

    if (syndesc->parms[0].items)
      admlib_conf_GetHostIdByHostName
	(syndesc->parms[0].items->data, &admHostId);
    else
      admlib_conf_GetHostIdByHostName (EMTD_DEFAULT_ADM_SERVER, &admHostId);
    if (syndesc->parms[1].items)
      admlib_conf_GetPortIdByPortName
	(syndesc->parms[1].items->data, &admPortId);
    else
      admlib_conf_GetPortIdByPortName (EMTD_DEFAULT_ADM_PORT, &admPortId);
    admServiceId = ADMLIB_CONF_SERVICEID;
    if (code = EstablishADMConnection
	( /* cellName */ (char *) 0, admHostId, admPortId, admServiceId,
	 (long) (25 * 60 * 60))) {
	Log ("error connecting with adm \(%ld\).\n", code);
	exit (code);
	 }
    Log ("Server starting now...\n");
    rx_StartServer ( /* donateMe */ 1);
    Log ("StartServer returned?\n");
}

/*****************************************************************************/

/* ARGSUSED */
static long
emtd_main_AddKey(ts, rock)
    struct cmd_syndesc *ts;
    char           *rock;
{
    if (ts->parms[2].items)
	IF_RTN(emtd_conf_SetPath(ts->parms[2].items->data));
    return emtd_conf_AddKeyByString
	(ts->parms[1].items ? atol(ts->parms[1].items->data) : (long) 0,
	 ts->parms[0].items->data);
}

/*****************************************************************************/

/* ARGSUSED */
static long
emtd_main_DeleteKey(ts, rock)
    struct cmd_syndesc *ts;
    char           *rock;
{
    if (ts->parms[1].items)
	IF_RTN(emtd_conf_SetPath(ts->parms[1].items->data));
    return emtd_conf_DeleteKey(atol(ts->parms[0].items->data));
}

/*****************************************************************************/

/* ARGSUSED */
static long
emtd_main_ListKeys(ts, rock)
    struct cmd_syndesc *ts;
    char           *rock;
{
    if (ts->parms[0].items)
	IF_RTN(emtd_conf_SetPath(ts->parms[0].items->data));
    return emtd_conf_ListKeys(ADMLIB_LOG_INTERACTIVE, stdout);
}

/***************************************************************************
 * [static] emt_main
 *
 * Description:
 *      Server's main.
 *
 * Arguments:
 *
 * Environment:
 *
 * History:
 *      Wed Jun 10 12:37:55 1992 - created by David Allen Markley
 *
 ***************************************************************************/
static int
emt_main (argc, argv)
     int                 argc;
     char               *argv[];
{
    register long code;
    struct cmd_syndesc *ts;


    ts = cmd_CreateSyntax
      ("initcmd", emt_InitCmd,
       /* rock */ (char *) 0, "start server");
    cmd_AddParm (ts, "-admserver", CMD_SINGLE, (long) CMD_OPTIONAL,
		 "adm server host");
    cmd_AddParm (ts, "-admport", CMD_SINGLE, (long) CMD_OPTIONAL,
		 "adm server port");
    cmd_AddParm (ts, "-detach", CMD_FLAG, (long) CMD_OPTIONAL,
		 "detach after startup");
    cmd_AddParm(ts, "-loglevel", CMD_SINGLE, (long) CMD_OPTIONAL,
		"logging level");
    cmd_AddParm(ts, "-logfile", CMD_SINGLE, (long) CMD_OPTIONAL,
		"logging file");
    cmd_AddParm(ts, "-dbfile", CMD_SINGLE, (long) CMD_OPTIONAL,
		"database file");
    cmd_AddParm(ts, "-confdir", CMD_SINGLE, (long) CMD_OPTIONAL,
		"configuration directory");
    cmd_AddParm(ts, "-port", CMD_SINGLE, (long) CMD_OPTIONAL, "server port");

    ts = cmd_CreateSyntax
	("addkey", emtd_main_AddKey,
	 /* rock */ (char *) 0, "add a key to the KeyFile");
    cmd_AddParm(ts, "-key", CMD_SINGLE, (long) CMD_REQUIRED,
		"key");
    cmd_AddParm(ts, "-kvno", CMD_SINGLE, (long) CMD_OPTIONAL,
		"key version number");
    cmd_AddParm(ts, "-confdir", CMD_SINGLE, (long) CMD_OPTIONAL,
		"configuration directory");

    ts = cmd_CreateSyntax
	("deletekey", emtd_main_DeleteKey,
	 /* rock */ (char *) 0, "delete a key from the KeyFile");
    cmd_AddParm(ts, "-kvno", CMD_SINGLE, (long) CMD_REQUIRED,
		"key version number");
    cmd_AddParm(ts, "-confdir", CMD_SINGLE, (long) CMD_OPTIONAL,
		"configuration directory");

    ts = cmd_CreateSyntax
      ("listkeys", emtd_main_ListKeys,
       /* rock */ (char *) 0, "list keys in the KeyFile");
    cmd_AddParm(ts, "-confdir", CMD_SINGLE, (long) CMD_OPTIONAL,
		"configuration directory");

    code = cmd_Dispatch(argc, argv);
    /* Transarc bug in cmd_HelpProc (random return) */
    if (argc >= 2 && !strcmp(argv[1], "help"))
      code = 0;
    return code;
}

/***************************************************************************
 * [exported] main
 *
 * Description:
 *      Duh.
 *
 * Arguments:
 *
 * Environment:
 *
 * History:
 *      Wed Jun 10 12:40:13 1992 - created by David Allen Markley
 *
 ***************************************************************************/
int
main (argc, argv)
     int                 argc;
     char               *argv[];
{
  int                 code;

  setbuf (stdout, NULL);	/* Unbuffer stdout so log files make sense */
  if (code = emt_main (argc, argv)) {
    Log ("%s: %s [%s] %ld\n", argv[0], error_message (code),
	 error_table_name (code), code);
    return 1;
  }
  return 0;
}

#ifndef DEBUG
/***************************************************************************
 * [static] emt_detach
 *
 * Description:
 *      detach from terminal and fork.
 *
 * Arguments:
 *
 * Environment:
 *
 * History:
 *      Wed Jun 10 12:40:41 1992 - created by David Allen Markley
 *
 ***************************************************************************/
static 
emt_detach ()
{
  /* detach from terminal and fork. */
  register int        i,
                      size = getdtablesize ();
  union wait          status;

  if (i = fork ()){
    if (i < 0)
      perror ("fork");
    exit (EMTD_BAD_MALLOC);
  }
  wait (&status);
  for (i = 0; i < size; i++) {
    (void) close (i);
  }
  i = open ("/dev/tty", O_RDWR, 666);
  (void) ioctl (i, TIOCNOTTY, (caddr_t) 0);
  (void) close (i);
}

#endif				/* !DEBUG */
