/* 
 * sysconfig: the interface to the SYSCONFIG configuration file
 *
 * Copyright (c) 1996,1998 David L Parsons
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by David L Parsons (orc@pell.chi.il.us).  My name may not be used
 * to endorse or promote products derived from this software without
 * specific prior written permission.  THIS SOFTWARE IS PROVIDED
 * ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.
 */
static const char rcsid[] = "$Id: s.Sysconfig.cc 1.6 99/03/30 08:33:28-00:00 orc $";

extern "C" {
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>

#include <sys/types.h>
#include <sys/wait.h>
#include <sys/fcntl.h>

#include <netdb.h>
}

#include "Sysconfig.H"
#include "Hosts.H"
#include "util.H"

/*
 * load up sysconfig.cf, or suitable defaults
 */
Sysconfig::Sysconfig():Karray()
{
    Refresh();
    changed(0);
} /* Sysconfig::Sysconfig */

/*
 * if anything has changed, write it to disk.
 * 
 * TODO: file locking, dirty file checking.
 */
int
Sysconfig::commit()
{
    FILE *cf;

    int mousechanged;
    int ypchanged;

    if (changed()) {
	mousechanged = valueof("MOUSETYPE").changed() ||
			valueof("MOUSEDEV").changed();
	ypchanged = valueof("DOMAINNAME").changed();

	if (backup(SYSCONFIG_CONF) != 0)
	    return EOF;
	if ((cf = fopen(SYSCONFIG_CONF, "w")) == (FILE*)0)
	    return EOF;
	make_header(cf, 0);
	print(cf);
	fclose(cf);

#ifdef ACTUAL
	if (Runlevel() == MULTIUSER) {
	    if (valueof("HOSTNAME").changed())
		system("/etc/rc.d/functions/sethostname");


	    if (mousechanged || ypchanged) {
		pid_t child;
		int status;

		if ((child=fork()) == 0) {
		    /* ignore common signals, close all i/o, then attempt to
		     * reconfigure the system.  If we take the network down,
		     * the calling program should get a hup and promptly fall
		     * over if we're doing remote administration otherwise
		     * we'll just continue along like normal.
		     */
		    signal(SIGHUP, SIG_IGN);
		    signal(SIGQUIT, SIG_IGN);
		    signal(SIGTERM, SIG_IGN);
		    close(0);	dup2(open("/dev/null", O_RDWR), 0);
		    close(1);	dup2(open("/dev/null", O_RDWR), 1);
		    close(2);	dup2(open("/dev/null", O_RDWR), 1);
		    setpgrp();

		    if (ypchanged)
			system( "/etc/rc.d/functions/restart yellowpages");

		    if (mousechanged)
			system( "/etc/rc.d/functions/restart mouse");

		    exit(0);
		}
		else if (child > 0)
		    while (waitpid(child, &status, 0) < 0 && errno == ERESTART)
			;
	    }
	}
#endif
	changed(0);
    }
    return 0;
} /* Sysconfig::commit */


/*
 * has the disk configuration file been touched since we last loaded it in?
 */
int
Sysconfig::dirty()
{
    return 0;
}

/*
 * Refresh the configuration from the disk image 
 */
int
Sysconfig::Refresh()
{
    FILE *cf;
    int rc = EOF;

    if ((cf = fopen(SYSCONFIG_CONF, "r")) != (FILE*)0) {
	Erase();		/* never merge configurations */
	read(cf);
	fclose(cf);
	rc = 0;
    }
    autoappend(1);
    changed(0);
    return rc;
} /* Sysconfig::Refresh */
