/*
 * sysconfig: edit /etc/rc.d/sysconfig
 *
 *   Copyright (c) 1996 David Parsons. All rights reserved.
 *   
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *  3. All advertising materials mentioning features or use of this
 *     software must display the following acknowledgement:
 *     
 *   This product includes software developed by David Parsons
 *   (orc@pell.chi.il.us)
 *
 *  4. My name may not be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *     
 *  THIS SOFTWARE IS PROVIDED BY DAVID PARSONS ``AS IS'' AND ANY
 *  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 *  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID
 *  PARSONS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 *  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 *  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 *  THE POSSIBILITY OF SUCH DAMAGE.
 */

static const char rcsid[] = "$Id: s.sysconfig.cc 1.18 02/05/04 01:28:32-07:00 root@egypt.pell.portland.or.us $";

extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include <string.h>
#include <ndialog.h>
#include <dialog.h>
#include <basis/validators.h>
}
#include <basis/Sysconfig.H>
#include <basis/Hosts.H>
#include <basis/Nic.H>

#include "buttons.h"
#include "util.h"

static char hostname[80];		/* in /etc/rc.d/sysconfig */
static char dnsdomain[80];

/* forward declarations */
static int chk_hostname(ndObject, ndDisplay display);
static int chk_domainname(ndObject, ndDisplay display);
static int finalcheck(ndObject, ndDisplay display);

ndObject o_host, o_domain;


/*
 * newSysconfigMenu() builds the object chain for the sysconfig form
 */
ndObject
newSysconfigMenu()
{
    ndObject chain;
    o_host = newString( 0, 0, 30, sizeof hostname, hostname,
                   0, "Host name  ", chk_hostname, "sysconfig.html#hostname");

    o_domain = newString( 0, 3, 30, sizeof dnsdomain, dnsdomain,
		    0, "Domain name", chk_domainname, "sysconfig.html#domain");


    chain = ObjChain(o_host, o_domain);

#if STAGE2
    chain = ObjChain(chain,
		newOKButton(1, "NEXT", finalcheck, 0));
    chain = ObjChain(chain,
		newCancelButton(2, "BACK", finalcheck, 0));
#else
    chain = ObjChain(chain,
		newOKButton(1, "  OK  ", finalcheck, 0));
    chain = ObjChain(chain,
		newCancelButton(2, "CANCEL", 0, 0));
#endif

    return chain;
} /* newSysconfigMenu */

/*
 * sysconfiginventory() builds a sysconfig inventory
 */
void
sysconfiginventory(char *inventory)
{
    char *p;
    /* build an inventory list for the "changes are done" message
     */
    if (dnsdomain[0]) {
	if ((p = strchr(hostname, '.')) != 0)
	    sprintf(END(inventory), "Hostname: %.*s\n"
				    "Domain  : %s\n",
				    (p-hostname), hostname, dnsdomain);
	else
	    sprintf(END(inventory), "Hostname: %s\n"
				    "Domain  : %s\n",
				    hostname, dnsdomain);

    }
    else
	sprintf(END(inventory), "Hostname: %s\n", hostname);
} /* sysconfiginventory */


static int
finalcheck(ndObject dummy, ndDisplay display)
{
    if (!hostname[0]) {
	Error("Please set the hostname for this machine");
	return 0;
    }
#if STAGE2
    return 1;
#else
    {
	char inventory[200];

	inventory[0] = 0;
	sysconfiginventory(inventory);
	return dialog_mesgbox("Change System Name?", inventory, -1, -1) == 0;
    }
#endif
} /* finalcheck */


/*
 * chk_hostname() makes sure the hostname is okay
 */
static int
chk_hostname(ndObject obj, ndDisplay display)
{
    char *hostname = (char*)objDataPtr(obj);
    char *tmp;

    for (tmp = hostname; *tmp; ++tmp)
	if (!isalnum(*tmp) && *tmp != '-' && *tmp != '.') {
	    Error("only alphanumerics and - are allowed in host names");
	    return 0;
	}

    if ((tmp = index(hostname, '.')) != NULL) {
	strncpy(dnsdomain, tmp + 1, strlen(tmp + 1));
	dnsdomain[strlen(tmp+1)] = '\0';
	drawObj(o_domain, display);
    }
    return 1;
} /* chk_hostname */


static int
chk_domainname(ndObject obj, ndDisplay display)
{
    char *domain = (char*)objDataPtr(obj);

    if (!index(hostname, '.') && *domain) {
	strcat(hostname, ".");
	strcat(hostname, dnsdomain);
	drawObj(o_host, display);
    }
    return 1;
}


/*
 * sysconfiginit() populates the local fields from the given
 * Sysconfig
 */
void
sysconfiginit(Sysconfig &cf)
{
    safecopy(hostname,  (char*)cf["HOSTNAME"]);
    safecopy(dnsdomain, (char*)cf["DNSDOMAIN"]);
} /* sysconfiginit */


/*
 * sysconfigcommit() populates the given Sysconfig from the menu
 */
void
sysconfigcommit(Sysconfig &cf, Hosts &host, Nic *netif)
{
    char *p;
    int assign_to_localhost, good_netif;

    if ((p = strchr(hostname, '.')) != 0)
	*p = 0;

    good_netif = netif && netif->isvalid();
    assign_to_localhost = ! (good_netif && streq((*netif)["CONF"], "MANUAL"));

    cf["HOSTNAME"]   = hostname;
    if (dnsdomain[0]) {
	char *fqdn = new char[strlen(hostname)+strlen(dnsdomain)+10];
	sprintf(fqdn, "%s.%s", hostname, dnsdomain);

	cf["DNSDOMAIN"]  = dnsdomain;

	if (assign_to_localhost) {
	    host["127.0.0.1"] = fqdn;
	    host["127.0.0.1"] += hostname;
	}
	else {
	    host[(*netif)["ADDRESS"]] = fqdn;
	    host[(*netif)["ADDRESS"]] += hostname;
	}
	delete fqdn;
    }
    else {
	cf.drop("DNSDOMAIN");
	if (assign_to_localhost)
	    host["127.0.0.1"] = hostname;
	else 
	    host[(*netif)["ADDRESS"]] = hostname;
    }
    host["127.0.0.1"] += "localhost";

    host.commit();
    cf.commit();
} /* sysconfigcommit */


#if STAGE2
int
sysconfigmenu()
{
    int rc;
    ndObject layout = newSysconfigMenu();

    rc = MENU(layout,
		-1, -1,
		"System Name", 0, 0);
    deleteObjChain(layout);


    switch (rc) {
    case MENU_CANCEL:
    case MENU_ESCAPE:	return BACK_BUTTON;
    case MENU_OK:	return NEXT_BUTTON;
    default:		return ERROR_BUTTON;
    }
} /* sysconfigmenu */

#else

extern "C" {
/*
 * doit actually splashes up the menus and gathers information
 */
int
doit()
{
    Sysconfig cf;
    Hosts host;
    int rc;
    char *p;
    Nic *netif;

    sysconfiginit(cf);
    ndObject layout = newSysconfigMenu();

    rc = MENU(layout,
		-1, -1,
		"System Name", 0, 0);

    deleteObjChain(layout);

    if (rc == MENU_OK) {
	netif = new Nic("eth0");
	if (netif->isvalid() == 0) {
	    delete netif;
	    netif = new Nic("tr0");
	}

	sysconfigcommit(cf, host, netif);
	delete netif;
    }

    return (rc==MENU_OK) ? 0 : 1;
} /* doit */
} /* extern "C" */

#endif
