/*
 *   Copyright (c) 1997,1998 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.admintool.c 1.13 00/02/01 22:28:41-00:00 orc $";

/*
 * admintool: is a toplevel tool that presents menus pointing at various
 *            configuration programs.
 *
 * SYSTEM
 *	-> sysconfig
 *	-> services
 *	-> timezone
 * 	-> date and time
 *	-> ntp time
 *	-> PCMCIA card services
 * NETWORK
 *	-> network
 *	-> yellowpages
 *	-> resolver
 * DISPLAY
 *	-> mouse
 *	-> xf86config
 * ADMIN
 *	-> user
 */
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <curses.h>
#include <ndialog.h>
#include <string.h>

#include "admin.h"

/*
 * various menus for administration;  the toplevel, which simply selects submenus
 */
static ListItem topmenu[] = {
    { "SYSTEM",		"System settings",		"admintool.html#System" },
    { "NETWORK",	"Network configuration",	"admintool.html#Network"},
    { "DISPLAY",	"Display settings",		"admintool.html#Display" },
    { "ADMIN",		"Administrative tasks",		"admintool.html#Tasks" },
};
#define NR_TOP	(sizeof topmenu/sizeof topmenu[0])

/*
 * the system menu, which selects programs
 */
static ListItem systemmenu[] = {
    { LIBDIR "sysconfig",		"System name", "sysconfig.html" },
    { LIBDIR "services",		"Services", "services.html" },
    { LIBDIR "timezone",		"Timezone", "timezone.html" },
    { LIBDIR "date",			"Date and Time", "date.html" },
    { LIBDIR "ntp",			"Configure NTP", "ntp.html" },
} ;
#define NR_SYSTEM	(sizeof systemmenu / sizeof systemmenu[0])

/*
 * the network menu, which selects programs
 */
static ListItem networkmenu[] = {
    { LIBDIR "network",			"Network devices", "network.html" },
    { LIBDIR "yellowpages",		"Yellow Pages", "nis.html" },
    { LIBDIR "resolver",		"DNS", "resolv.html" },
} ;
#define NR_NETWORK	(sizeof networkmenu / sizeof networkmenu[0])

/*
 * the display menu, which selects (one, for now) program
 */
static ListItem displaymenu[] = {
    { LIBDIR "mouse",			"Mouse/pointing devices", "mouse.html" },
#if WITHX
    { "/usr/X11R6/bin/Xconfig",	"X windows", "x-windows.html" },
#endif
} ;
#define NR_DISPLAY	(sizeof displaymenu / sizeof displaymenu[0])


/*
 * the administration menu, which does various admin tasks
 */
static ListItem adminmenu[] = {
    { LIBDIR "user",			"User administration", "user.html" },
} ;
#define NR_ADMIN	(sizeof adminmenu / sizeof adminmenu[0])


/*
 * firemenu() is a callback that's called from a submenu.
 */
static int
firemenu(void *obj)
{
    pid_t child;
    int rc;
    char message[200];
    int ix = currentSelection(obj);
    ListItem *list = getObjList(obj);


    if (ix >= 0 && ix < getObjListSize(obj))
	if (access(list[ix].id, X_OK) != 0) {
	    sprintf(message, "%s\n%s", list[ix].id, strerror(errno));
	    Error(message);
	}
	else if ((child = fork()) == 0) {
	    execl(list[ix].id,list[ix].id, (char*)0);
	    sprintf(message, "%s\n%s", list[ix].id, strerror(errno));
	    Error(message);
	    return -1;
	}
	else if (child > 0) {
	    while (waitpid(child, &rc, 0) != child && errno != ECHILD)
		;
	    wclear(stdscr);
	    touchwin(stdscr);
	    wrefresh(stdscr);
	}
	else {
	    sprintf(message, "%s\n%s", list[ix].id, strerror(errno));
	    Error(message);
	}
    return 0;
} /* firemenu */


/*
 * firesubmenu() is a callback called when a topmenu item is poked at
 */
static int
firesubmenu(void *obj)
{
    ndObject choices;
    ndObject goaway;
    ndObject chain;
    int rc;
    int ix = currentSelection(obj);
    ListItem *list = getObjList(obj);
    ListItem *submenu;
    int subsize;

    submenu = 0;
    if (ix >= 0 && ix < getObjListSize(obj)) {
	if (strcasecmp(list[ix].id, "SYSTEM") == 0) {
	    submenu = systemmenu;
	    subsize = NR_SYSTEM;
	}
	else if (strcasecmp(list[ix].id, "NETWORK") == 0) {
	    submenu = networkmenu;
	    subsize = NR_NETWORK;
	}
	else if (strcasecmp(list[ix].id, "DISPLAY") == 0) {
	    submenu = displaymenu;
	    subsize = NR_DISPLAY;
	}
	else if (strcasecmp(list[ix].id, "ADMIN") == 0) {
	    submenu = adminmenu;
	    subsize = NR_ADMIN;
	}
    }
    if (submenu == 0) {
	Error("Bogus call to firesubmenu");
	return 0;
    }


    choices = newMenu(-1,0,-1,-1,subsize,submenu,0, "", 0, firemenu, 0);
    goaway  = newCancelButton(0, "Done", 0, 0);

    chain = ObjChain(choices, goaway);
    while (1) {
	rc = MENU(chain, -1, -1, list[ix].id, 0, 0);

	if (rc == MENU_CANCEL || rc == MENU_ESCAPE)
	    break;
    }
    deleteObjChain(chain);
    return 0;
} /* firesubmenu */


/*
 * doit() runs the admintool menu
 */
int
doit(int argc, char **argv)
{
    ndObject choices;
    ndObject goaway;
    ndObject chain;
    int rc;

    /* add a title bar across the top of the background with the machine
     * name and what other information I think might be appropriate
     */

    choices = newMenu(0,0,-1,-1,NR_TOP,topmenu,0,"", 0, firesubmenu, 0);
    goaway  = newCancelButton(0, "Exit", 0, 0);

    chain = ObjChain(choices, goaway);
    while (1) {
	rc = MENU(chain, -1, -1, "Settings", 0, 0);

	if (rc == MENU_CANCEL || rc == MENU_ESCAPE)
	    break;
    }
    deleteObjChain(chain);
    return 0;
} /* doit */
