/*\
 *	DISTRIBUTION: HNMS v2.0
 *	FILE: hnmsd/sync.c
 *
 *	Object file code for HNMS 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 <sys/param.h>
#include <netdb.h>

#include "stdhnms.h"

/*\
 *  Read object file, if it exists.  We don't read in values for
 *  any of the following:
 *
 *	hnmsObjUName, hnmsObjClass, hnmsObjUString (they are redundant)
 *	hnmsIpaddrLastEchoTime, hnmsIpaddrRTT, hnmsObj*Status,
 *	hnmsAgentLastDiscoverTime (the file is NOT for "current" vars)
 *	hnmsModuleId, hnmsModuleHnmpLastMsgId (as above)
 *	hnmsModuleHnmsHome (obvious)
 *	any non-HNMS variable (we use only HNMS vars for config mgmt)
\*/
int SYNC_read_objs()
{
    FILE		*fp = NULL;
    char		*cp;
    static char		filename[MAXPATHLEN];
    static char		buf[STRBUFLEN];
    int			rval;
    OID			oid;
    int			oid_type;
    PE			pe;
    int			target = -1;
    unsigned int	ts;
    int			n;

    ts = get_int_time();

    cp = PARAM_get_str(oid_hnmsModuleHnmsHome);
    sprintf(filename, "%s/hnmsd.cf", cp);

    fp = fopen(filename, "r");
    if (!fp) {
	hnms_errno = HNMS_err_file_not_found;
	return 0;
    }
    for(;;) {
	bzero(buf, STRBUFLEN);
	rval = fscanf(fp, "%s", buf);
	if (rval == EOF)
	    break;

	if (buf[0] == '#')
	    fscanf(fp, "%[^\n]", buf);

	else if (!strncmp(buf, "LocalParams", 11))
	    target = 0;

	else if (!strncmp(buf, "Object", 6)) {
	    fscanf(fp, "%[\t ]", buf);
	    fscanf(fp, "%[^\n]", buf);
	    rval = OBJ_add_by_uname(0, buf);
	    target = ABS(rval);
	    if (!target)
		target = -1;
	}

	else {
	    oid = MIB_ode2oid(buf, &oid_type);
	    if (!oid)
		fscanf(fp, "%[^\n]", buf);
	    else {
		if (!oid_is_hnms(oid) ||
		    !oid_cmp(oid, oid_hnmsObjUName) ||
		    !oid_cmp(oid, oid_hnmsObjClass) ||
		    !oid_cmp(oid, oid_hnmsObjUString) ||
		    !oid_cmp(oid, oid_hnmsObjReachStatus) ||
		    !oid_cmp(oid, oid_hnmsObjOperStatus) ||
		    !oid_cmp(oid, oid_hnmsObjAdminStatus) ||
		    !oid_cmp(oid, oid_hnmsIpaddrLastEchoOut) ||
		    !oid_cmp(oid, oid_hnmsIpaddrLastEchoIn) ||
		    !oid_cmp(oid, oid_hnmsIpaddrRTT) ||
		    !oid_cmp(oid, oid_hnmsAgentLastDiscoverTime) ||
		    !oid_cmp(oid, oid_hnmsModuleId) ||
		    !oid_cmp(oid, oid_hnmsModuleHnmpLastMsgId) ||
		    !oid_cmp(oid, oid_hnmsModuleHnmpMsgs) ||
		    !oid_cmp(oid, oid_hnmsModuleHnmpRetransMsgs) ||
		    !oid_cmp(oid, oid_hnmsModuleHnmpConnections) ||
		    !oid_cmp(oid, oid_hnmsModuleIoPromiscuous) ||
		    !oid_cmp(oid, oid_hnmsModuleHnmsHome))
		    continue;
		fscanf(fp, "%[\t ]", buf);
		fscanf(fp, "%[^\n]", buf);
		switch (oid_type) {
		case MIB_integer:
		case MIB_enum:
		case MIB_timeticks:
		case MIB_counter:
		case MIB_gauge:
		    pe = int2prim(atoi(buf));
		    break;
		case MIB_ipaddr:
		    pe = ipaddr_int2pe(inet_addr(buf));
		    break;
		case MIB_octetstring:
		case MIB_displaystring:
		    pe = oct2prim(buf, strlen(buf));
		    break;
		default:;
		}
		if (target == 0)
		    PARAM_set_pe(oid, pe);
		else if (target > 0)
		    OBJ_set(target, oid, pe, 0, 0, 0, &ts);
		pe_free(pe);
	    }
	}
    }
    /*
     * Make sure the timestamps are aged at least 1 second.
     */
    sleep(1);
    return 0;
}

/*\
 *  Write a variable and its value to a file.
 *  Return 1 on  success, 0 on failure.
\*/
static int SYNC_write_var(oid, pe, fp)
    const OID		oid;
    const PE		pe;
    FILE		*fp;
{
    int			oid_type;
    char		*cp, *cp2;
    int			len;

    if (!oid || !pe)
	return 0;

    if (!oid_cmp(oid, oid_hnmsObjUName) ||
	!oid_cmp(oid, oid_hnmsObjClass) ||
	!oid_cmp(oid, oid_hnmsObjUString))
	return 0;

    cp = MIB_oid2ode(oid, &oid_type);
    if (!cp)
	return 0;

    switch (oid_type) {
    case MIB_integer:
    case MIB_enum:
    case MIB_timeticks:
    case MIB_gauge:
	fprintf(fp, "\t%s %d\n", cp, prim2num(pe));
	fflush(fp);
	return 1;
    case MIB_counter:
	fprintf(fp, "\t%s %u\n", cp, (unsigned int)fixed_prim2num(pe));
	fflush(fp);
	return 1;
    case MIB_ipaddr:
	fprintf(fp, "\t%s %s\n", cp, ipaddr_pe2str(pe));
	fflush(fp);
	return 1;
    case MIB_octetstring:
    case MIB_displaystring:
	cp2 = prim2str(pe, &len);
	fprintf(fp, "\t%s %s\n", cp, cp2);
	fflush(fp);
	free(cp2);
	return 1;
    default:;
    }
    return 0;
}

/*\
 *  Write an HNMS object to a file.
\*/
static void SYNC_write_obj(id, fp)
    const int		id;
    FILE		*fp;
{
    VarBindList		vbl;
    static char		*cp;

    cp = OBJ_get_uname(id);
    fprintf(fp, "Object %s\n", cp);
    fflush(fp);
    vbl = OBJ_get_vbl(id);
    VarBindList_iterate(vbl, SYNC_write_var, fp);
}

/*\
 *  Write object file.
\*/
int SYNC_write_objs()
{
    char		filename[MAXPATHLEN];
    FILE		*fp;
    VarBindList		v;
    struct hostent	*host;
    int			oid_type, len;
    char		*community;
    unsigned int	ip_address, mask;
    char		*cp1;
    unsigned int	current_time, psi;
    static unsigned int	last_sync_time = 0;
    
    current_time = get_int_time();
    psi = PARAM_get_int(oid_hnmsModuleServerSyncInterval);
    if (current_time - last_sync_time >= psi) {
	last_sync_time = current_time;

	cp1 = PARAM_get_str(oid_hnmsModuleHnmsHome);
	if (!cp1)
	    return 0;
	sprintf(filename, "%s/hnmsd.cf", cp1);
	
	umask(0);
	fp = fopen(filename, "w");
	if (!fp)
	    return 0;
	
	fprintf(fp, "#\n");
	fprintf(fp, "#\tLocal Parameters\n");
	fprintf(fp, "#\n");
	fprintf(fp, "LocalParams\n");
	PARAM_iterate(SYNC_write_var, fp);
	fprintf(fp, "#\n");
	fprintf(fp, "#\tObjects\n");
	fprintf(fp, "#\n");
	OBJ_iterate(SYNC_write_obj, fp);
	fclose(fp);
    }
    return 0;
}
