/*\
 *	DISTRIBUTION: HNMS v2.0
 *	FILE: hnmsd/hnmsd.c
 *
 *	HNMS daemon.  Contains Server, IO, and RBIP modules.
 *
 *	Jude George
 *	NAS Facility, NASA Ames Research Center
 *
 *	Copyright (c) 1994 Jude George
 *
 *	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 1, 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, write to the Free Software
 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
\*/

#include <stdio.h>

#include "stdhnms.h"
#include "server.h"
#include "sync.h"
#include "rbip.h"
#include "io.h"
#include "snmp.h"
#include "icmp.h"
#include "ll2.h"

void showusage(bname)
    const char		*bname;
{
    printf("\tHNMS Server Module\n");
    printf("\tHNMS RBIP Module\n");
    printf("\tHNMS IO Module\n\n");
    printf("Usage: %s    -- run in background\n",bname);
    printf("       %s -f -- run in foreground\n", bname);
}

/*\
 *  Callback routine called after HNMP closes a session.
\*/
void HNMP_close_callback(module_id)
    const int		module_id;
{

}

/*\
 *  Callback routine called after HNMP opens a session.
\*/
void HNMP_open_callback(module_id)
    const int		module_id;
{
    PEER_welcome(module_id);
    PEER_announce_all_to_one(module_id);
}

/*\
 *  Callback routine to process an incoming message.
\*/
void HNMP_Message_process(msg)
    const Message	msg;
{
    int			my_module_id;
    int			my_module_type;
    int			id;
    VarBindList		vbl;
    static char		uname[STRBUFLEN];

    switch (msg->data->offset) {
    case HNMP_ANNOUNCE:
	vbl = (VarBindList)Message_get(msg, HNMP_variables);
	bzero(uname, STRBUFLEN);
	VarBindList_get(vbl, oid_hnmsObjUName, uname, 0, 0, 0, 0);
	id = OBJ_add_by_uname(0, uname);
	if (id > 0) {
	    OBJ_set_list(id, vbl);
	}
	break;

    case HNMP_DELETE:
	id = *(int *)Message_get(msg, HNMP_object_id);
	OBJ_delete(id);
	my_module_type = PARAM_get_int(oid_hnmsModuleType);
	if (my_module_type == MODULE_SERVER)
	    PEER_delete_one_to_all(id);
	break;

    case HNMP_SUB_DATA:
	vbl = (VarBindList)Message_get(msg, HNMP_variables);
	id = *(int *)Message_get(msg, HNMP_object_id);
	PEER_add_sub(msg->from__module__id, id, vbl);
	break;

    case HNMP_UNSUB_DATA:
	id = *(int *)Message_get(msg, HNMP_object_id);
	PEER_drop_sub(msg->from__module__id, id);
	break;

    case HNMP_SEND_DATA:
	vbl = (VarBindList)Message_get(msg, HNMP_variables);
	id = *(int *)Message_get(msg, HNMP_object_id);
	OBJ_set_list(id, vbl);
	break;

    case HNMP_SET_DATA:
	vbl = (VarBindList)Message_get(msg, HNMP_variables);
	id = *(int *)Message_get(msg, HNMP_object_id);
	OBJ_set_hnmsvars(id, vbl);
	SNMP_set(id, vbl);
	break;

    case HNMP_GET_DATA:
	vbl = (VarBindList)Message_get(msg, HNMP_variables);
	id = *(int *)Message_get(msg, HNMP_object_id);
	SNMP_get(id, vbl, msg->from__module__id);
	break;

    case HNMP_GET_NEXT_DATA:
	vbl = (VarBindList)Message_get(msg, HNMP_variables);
	id = *(int *)Message_get(msg, HNMP_object_id);
	SNMP_getnext(id, vbl, msg->from__module__id);
	break;

    case HNMP_GET_WALK_DATA:
	vbl = (VarBindList)Message_get(msg, HNMP_variables);
	id = *(int *)Message_get(msg, HNMP_object_id);
	SNMP_walk(id, vbl, msg->from__module__id);
	break;

    case HNMP_SUB_RELATIONS:
	vbl = (VarBindList)Message_get(msg, HNMP_variables);
	id = *(int *)Message_get(msg, HNMP_object_id);
	PEER_add_rel_sub(msg->from__module__id, id, vbl);
	break;

    case HNMP_UNSUB_RELATIONS:
	id = *(int *)Message_get(msg, HNMP_object_id);
	PEER_drop_rel_sub(msg->from__module__id, id);
	break;

    default:;
    }
}

/*\
 *  Top level.
\*/
main(argc, argv)
    int			argc;
    char		*argv[];
{
    int			server = 0;
    char		*cp;
    char		hostname[STRBUFLEN];
#ifdef sgi
    mallopt(M_FREEHD, 1);
#endif

    /*
     * Command-line arguments:
     * <none>:		run in background
     * -f:		run in foreground
     * <anything else>:	show usage screen and exit
     */
    switch (argc) {
    case 1:
	if (fork() > 0)
	    exit(0);
	break;
    case 2:
	if (!strcmp(argv[1], "-f"))
	    break;
	else {
	    showusage(argv[0]);
	    exit(0);
	}
    default:
	showusage(argv[0]);
	exit(0);
    }

    if (geteuid() != 0) {
	printf("%s must run as root.  exiting.\n", argv[0]);
	exit(1);
    }

/*
    cp = getenv("HNMS_SERVER");
    if (!cp)
	server = 1;
    else {
	bzero(hostname, STRBUFLEN);
	gethostname(hostname, STRBUFLEN);
	if (!strcmp(cp, hostname))
	    server = 1;
    }
*/
    server = 1;

    if (server)
	HNMS_init(MODULE_SERVER);
    else
	HNMS_init(MODULE_IO);

    HNMS_create_task("Server File I/O", SYNC_read_objs, SYNC_write_objs, 1);
    HNMS_create_task("Server Make Internet/Networks/Subnets",
		     SERVER_make_internet, SERVER_make_ip_parents, 1);
    HNMS_create_task("Server Assign Status", NULL, SERVER_assign_status, 1);
    HNMS_create_task("Server Fill UI Subs", NULL, PEER_fill_subs, 1);
    HNMS_create_task("Server Make IO Subs", NULL, PEER_merge_subs, 1);
    HNMS_create_task("RBIP Calc Traffic", NULL, RBIP_calc_traffic, 1);
    HNMS_create_task("IO SNMP Listening", SNMP_init, SNMP_listen, 0);
    HNMS_create_task("IO SNMP Discovery Polling", SNMP_init,
		     SNMP_discovery_poll, 1);
    HNMS_create_task("IO SNMP Sub Polling", SNMP_init, SNMP_sub_poll, 1);
    HNMS_create_task("IO Assign Status", NULL, IO_assign_status, 1);
    HNMS_create_task("IO Make Ipaddrs", NULL, IO_make_ipaddrs, 1);
    HNMS_create_task("IO ICMP Status Polling", ICMP_init, ICMP_status_poll, 1);
/*  HNMS_create_task("IO ICMP Listening", ICMP_init, ICMP_listen, 0); */
    HNMS_create_task("IO MAC-layer Listening", LL2_init, LL2_listen, 0);

    for(;;) {
	HNMS_process();
#ifdef sgi
	sginap(5); /* 100 ticks per second */
#else
	sleep(1);
#endif	
    }
}
