115788Sjkh/*
215788Sjkh * The new sysinstall program.
315788Sjkh *
415788Sjkh * This is probably the last program in the `sysinstall' line - the next
515788Sjkh * generation being essentially a complete rewrite.
615788Sjkh *
750479Speter * $FreeBSD$
815788Sjkh *
915788Sjkh * Copyright (c) 1995
1015788Sjkh *	Jordan Hubbard.  All rights reserved.
1115788Sjkh *
1215788Sjkh * Redistribution and use in source and binary forms, with or without
1315788Sjkh * modification, are permitted provided that the following conditions
1415788Sjkh * are met:
1515788Sjkh * 1. Redistributions of source code must retain the above copyright
1615788Sjkh *    notice, this list of conditions and the following disclaimer,
1715788Sjkh *    verbatim and that no modifications are made prior to this
1815788Sjkh *    point in the file.
1915788Sjkh * 2. Redistributions in binary form must reproduce the above copyright
2015788Sjkh *    notice, this list of conditions and the following disclaimer in the
2115788Sjkh *    documentation and/or other materials provided with the distribution.
2215788Sjkh *
2315788Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
2415788Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2515788Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2615788Sjkh * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
2715788Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2815788Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2915788Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
3015788Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3115788Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3215788Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3315788Sjkh * SUCH DAMAGE.
3415788Sjkh *
3515788Sjkh */
3615788Sjkh
3715788Sjkh#include "sysinstall.h"
3815788Sjkh#include <ctype.h>
3929517Sjkh#include <errno.h>
4029517Sjkh#include <sys/signal.h>
4129517Sjkh#include <sys/fcntl.h>
4215788Sjkh
4329517Sjkh#include "list.h"
4429222Sjkh
4529517Sjkhstatic int dispatch_shutdown(dialogMenuItem *unused);
4629517Sjkhstatic int dispatch_systemExecute(dialogMenuItem *unused);
4737735Sjkhstatic int dispatch_msgConfirm(dialogMenuItem *unused);
48154925Sjkimstatic int dispatch_mediaOpen(dialogMenuItem *unused);
4997777Sjhbstatic int dispatch_mediaClose(dialogMenuItem *unused);
50189754Sgrogstatic int cfgModuleFire(dialogMenuItem *self);
5129517Sjkh
5215788Sjkhstatic struct _word {
5315788Sjkh    char *name;
5415788Sjkh    int (*handler)(dialogMenuItem *self);
5515788Sjkh} resWords[] = {
5615788Sjkh    { "configAnonFTP",		configAnonFTP		},
5719385Sjkh    { "configRouter",		configRouter		},
5881023Srwatson    { "configInetd",		configInetd		},
5915788Sjkh    { "configNFSServer",	configNFSServer		},
6026456Sjkh    { "configNTP",		configNTP		},
6126456Sjkh    { "configPCNFSD",		configPCNFSD		},
6226456Sjkh    { "configPackages",		configPackages		},
6326456Sjkh    { "configUsers",		configUsers		},
64107339Sjhb#ifdef WITH_SLICES
6515788Sjkh    { "diskPartitionEditor",	diskPartitionEditor	},
66107339Sjhb#endif
6715788Sjkh    { "diskPartitionWrite",	diskPartitionWrite	},
6815788Sjkh    { "diskLabelEditor",	diskLabelEditor		},
6915788Sjkh    { "diskLabelCommit",	diskLabelCommit		},
7015788Sjkh    { "distReset",		distReset		},
7126601Sjkh    { "distSetCustom",		distSetCustom		},
7253015Sjkh    { "distUnsetCustom",	distUnsetCustom		},
7315788Sjkh    { "distSetDeveloper",	distSetDeveloper	},
7415788Sjkh    { "distSetKernDeveloper",	distSetKernDeveloper	},
7515788Sjkh    { "distSetUser",		distSetUser		},
7615788Sjkh    { "distSetMinimum",		distSetMinimum		},
7715788Sjkh    { "distSetEverything",	distSetEverything	},
7815788Sjkh    { "distSetSrc",		distSetSrc		},
7915788Sjkh    { "distExtractAll",		distExtractAll		},
8015788Sjkh    { "docBrowser",		docBrowser		},
8115788Sjkh    { "docShowDocument",	docShowDocument		},
8215788Sjkh    { "installCommit",		installCommit		},
8315788Sjkh    { "installExpress",		installExpress		},
8457315Sjkh    { "installStandard",	installStandard		},
85209832Srandi    { "installUpgrade",		installUpgrade		},
86109434Sjhb    { "installFixupBase",	installFixupBase	},
8726456Sjkh    { "installFixitHoloShell",	installFixitHoloShell	},
8826456Sjkh    { "installFixitCDROM",	installFixitCDROM	},
89195442Scperciva    { "installFixitUSB",	installFixitUSB		},
9026456Sjkh    { "installFixitFloppy",	installFixitFloppy	},
9115788Sjkh    { "installFilesystems",	installFilesystems	},
9226456Sjkh    { "installVarDefaults",	installVarDefaults	},
9329517Sjkh    { "loadConfig",		dispatch_load_file	},
9437735Sjkh    { "loadFloppyConfig",	dispatch_load_floppy	},
95189754Sgrog    { "loadCDROMConfig",	dispatch_load_cdrom	},
96154925Sjkim    { "mediaOpen",		dispatch_mediaOpen	},
9797777Sjhb    { "mediaClose",		dispatch_mediaClose	},
9815788Sjkh    { "mediaSetCDROM",		mediaSetCDROM		},
9915788Sjkh    { "mediaSetFloppy",		mediaSetFloppy		},
100194931Scperciva    { "mediaSetUSB",		mediaSetUSB		},
10115788Sjkh    { "mediaSetDOS",		mediaSetDOS		},
10215788Sjkh    { "mediaSetFTP",		mediaSetFTP		},
10315788Sjkh    { "mediaSetFTPActive",	mediaSetFTPActive	},
10415788Sjkh    { "mediaSetFTPPassive",	mediaSetFTPPassive	},
10555392Sjkh    { "mediaSetHTTP",		mediaSetHTTP		},
106248313Sdteske    { "mediaSetHTTPDirect",	mediaSetHTTPDirect	},
10715788Sjkh    { "mediaSetUFS",		mediaSetUFS		},
10815788Sjkh    { "mediaSetNFS",		mediaSetNFS		},
10918619Sjkh    { "mediaSetFTPUserPass",	mediaSetFTPUserPass	},
11015788Sjkh    { "mediaSetCPIOVerbosity",	mediaSetCPIOVerbosity	},
11115788Sjkh    { "mediaGetType",		mediaGetType		},
11237735Sjkh    { "msgConfirm",		dispatch_msgConfirm	},
11316208Sjkh    { "optionsEditor",		optionsEditor		},
11426613Sjkh    { "packageAdd",		packageAdd		},
11520484Sjkh    { "addGroup",		userAddGroup		},
11620484Sjkh    { "addUser",		userAddUser		},
11729517Sjkh    { "shutdown",		dispatch_shutdown 	},
11829517Sjkh    { "system",			dispatch_systemExecute	},
11937735Sjkh    { "dumpVariables",		dump_variables		},
12037735Sjkh    { "tcpMenuSelect",		tcpMenuSelect		},
12115788Sjkh    { NULL, NULL },
12215788Sjkh};
12315788Sjkh
12429517Sjkh/*
12529517Sjkh * Helper routines for buffering data.
12629517Sjkh *
12729517Sjkh * We read an entire configuration into memory before executing it
12829517Sjkh * so that we are truely standalone and can do things like nuke the
12929517Sjkh * file or disk we're working on.
13029517Sjkh */
13129517Sjkh
13229517Sjkhtypedef struct command_buffer_ {
13329517Sjkh    qelement	queue;
13429517Sjkh    char *	string;
13529517Sjkh} command_buffer;
13629517Sjkh
13729517Sjkhstatic void
13829517Sjkhdispatch_free_command(command_buffer *item)
13915788Sjkh{
140215637Sbrucec    if (item != NULL) {
141215637Sbrucec	REMQUE(item);
142215637Sbrucec	free(item->string);
143215637Sbrucec	item->string = NULL;
144215637Sbrucec    }
145215637Sbrucec
14629517Sjkh    free(item);
14729517Sjkh}
14815788Sjkh
14929517Sjkhstatic void
15029517Sjkhdispatch_free_all(qelement *head)
15129517Sjkh{
15229517Sjkh    command_buffer *item;
15329517Sjkh
15429517Sjkh    while (!EMPTYQUE(*head)) {
15529517Sjkh	item = (command_buffer *) head->q_forw;
15629517Sjkh	dispatch_free_command(item);
15715788Sjkh    }
15815788Sjkh}
15915788Sjkh
16029517Sjkhstatic command_buffer *
16129517Sjkhdispatch_add_command(qelement *head, char *string)
16229517Sjkh{
163215637Sbrucec    command_buffer *new = NULL;
16429517Sjkh
16529517Sjkh    new = malloc(sizeof(command_buffer));
16629517Sjkh
167215637Sbrucec    if (new != NULL) {
16829517Sjkh
169215637Sbrucec	new->string = strdup(string);
17029517Sjkh
171215637Sbrucec	/*
172215637Sbrucec	 * We failed to copy `string'; clean up the allocated
173215637Sbrucec	 * resources.
174215637Sbrucec	 */
175215637Sbrucec	if (new->string == NULL) {
176215637Sbrucec	    free(new);
177215637Sbrucec	    new = NULL;
178215637Sbrucec	} else {
179215637Sbrucec	    INSQUEUE(new, head->q_back);
180215637Sbrucec	}
181215637Sbrucec    }
182215637Sbrucec
18329517Sjkh    return new;
18429517Sjkh}
185215637Sbrucec
18629517Sjkh/*
18729517Sjkh * Command processing
18829517Sjkh */
18929517Sjkh
19021764Sjkh/* Just convenience */
19126795Sjkhstatic int
19229517Sjkhdispatch_shutdown(dialogMenuItem *unused)
19321764Sjkh{
19421764Sjkh    systemShutdown(0);
19521764Sjkh    return DITEM_FAILURE;
19621764Sjkh}
19721764Sjkh
19826795Sjkhstatic int
19929517Sjkhdispatch_systemExecute(dialogMenuItem *unused)
20026795Sjkh{
20129539Spst    char *cmd = variable_get(VAR_COMMAND);
20226795Sjkh
20326795Sjkh    if (cmd)
20426795Sjkh	return systemExecute(cmd) ? DITEM_FAILURE : DITEM_SUCCESS;
20526795Sjkh    else
20626795Sjkh	msgDebug("_systemExecute: No command passed in `command' variable.\n");
20726795Sjkh    return DITEM_FAILURE;
20826795Sjkh}
20926795Sjkh
21029222Sjkhstatic int
21137735Sjkhdispatch_msgConfirm(dialogMenuItem *unused)
21237735Sjkh{
21337735Sjkh    char *msg = variable_get(VAR_COMMAND);
21437735Sjkh
21537735Sjkh    if (msg) {
21679304Skris	msgConfirm("%s", msg);
21737735Sjkh	return DITEM_SUCCESS;
21837735Sjkh    }
21937735Sjkh
22037735Sjkh    msgDebug("_msgConfirm: No message passed in `command' variable.\n");
22137735Sjkh    return DITEM_FAILURE;
22237735Sjkh}
22337735Sjkh
22437735Sjkhstatic int
225154925Sjkimdispatch_mediaOpen(dialogMenuItem *unused)
226154925Sjkim{
227154925Sjkim    return mediaOpen();
228154925Sjkim}
229154925Sjkim
230154925Sjkimstatic int
23197777Sjhbdispatch_mediaClose(dialogMenuItem *unused)
23297777Sjhb{
23397777Sjhb    mediaClose();
23497777Sjhb    return DITEM_SUCCESS;
23597777Sjhb}
23697777Sjhb
23797777Sjhbstatic int
23829517Sjkhcall_possible_resword(char *name, dialogMenuItem *value, int *status)
23929222Sjkh{
24029517Sjkh    int i, rval;
24129222Sjkh
24229517Sjkh    rval = 0;
24329517Sjkh    for (i = 0; resWords[i].name; i++) {
24429517Sjkh	if (!strcmp(name, resWords[i].name)) {
24529517Sjkh	    *status = resWords[i].handler(value);
24629517Sjkh	    rval = 1;
24729517Sjkh	    break;
24829222Sjkh	}
24929222Sjkh    }
25029517Sjkh    return rval;
25129222Sjkh}
25229222Sjkh
25315788Sjkh/* For a given string, call it or spit out an undefined command diagnostic */
25415788Sjkhint
25515788SjkhdispatchCommand(char *str)
25615788Sjkh{
25715788Sjkh    int i;
25816766Sjkh    char *cp;
25915788Sjkh
26015788Sjkh    if (!str || !*str) {
26115788Sjkh	msgConfirm("Null or zero-length string passed to dispatchCommand");
26215788Sjkh	return DITEM_FAILURE;
26315788Sjkh    }
264189754Sgrog
265189754Sgrog    /* Fixup DOS abuse */
266189754Sgrog    if ((cp = index(str, '\r')) != NULL)
26721764Sjkh	*cp = '\0';
26821764Sjkh
26926456Sjkh    /* If it's got a `=' sign in there, assume it's a variable setting */
27016766Sjkh    if (index(str, '=')) {
27126572Sjkh	if (isDebug())
27226572Sjkh	    msgDebug("dispatch: setting variable `%s'\n", str);
27343685Sjkh	variable_set(str, 0);
27421764Sjkh	i = DITEM_SUCCESS;
27515788Sjkh    }
27621764Sjkh    else {
27729517Sjkh	/* A command might be a pathname if it's encoded in argv[0], which
27829517Sjkh	   we also support */
27926456Sjkh	if ((cp = rindex(str, '/')) != NULL)
28021764Sjkh	    str = cp + 1;
28126572Sjkh	if (isDebug())
28226572Sjkh	    msgDebug("dispatch: calling resword `%s'\n", str);
28321764Sjkh	if (!call_possible_resword(str, NULL, &i)) {
28426456Sjkh	    msgNotify("Warning: No such command ``%s''", str);
28521764Sjkh	    i = DITEM_FAILURE;
28621764Sjkh	}
28797778Sjhb	/*
28897778Sjhb	 * Allow a user to prefix a command with "noError" to cause
28997778Sjhb	 * us to ignore any errors for that one command.
29097778Sjhb	 */
29197778Sjhb	if (i != DITEM_SUCCESS && variable_get(VAR_NO_ERROR))
29297778Sjhb	    i = DITEM_SUCCESS;
29397778Sjhb	variable_unset(VAR_NO_ERROR);
29415788Sjkh    }
29515788Sjkh    return i;
29615788Sjkh}
29729517Sjkh
298215637Sbrucec
29929517Sjkh/*
30029517Sjkh * File processing
30129517Sjkh */
30229517Sjkh
30329517Sjkhstatic qelement *
30429517Sjkhdispatch_load_fp(FILE *fp)
30529517Sjkh{
30629517Sjkh    qelement *head;
30729517Sjkh    char buf[BUFSIZ], *cp;
30829517Sjkh
30929517Sjkh    head = malloc(sizeof(qelement));
31029517Sjkh
31129517Sjkh    if (!head)
31229517Sjkh	return NULL;
31329517Sjkh
31429517Sjkh    INITQUE(*head);
31529517Sjkh
31629517Sjkh    while (fgets(buf, sizeof buf, fp)) {
317189754Sgrog	/* Fix up DOS abuse */
318189754Sgrog	if ((cp = index(buf, '\r')) != NULL)
31929517Sjkh	    *cp = '\0';
320189754Sgrog	/* If it's got a new line, trim it */
321189754Sgrog       if ((cp = index(buf, '\n')) != NULL)
322189754Sgrog            *cp = '\0';
32329517Sjkh	if (*buf == '\0' || *buf == '#')
32429517Sjkh	    continue;
32529517Sjkh
32629517Sjkh	if (!dispatch_add_command(head, buf))
32729517Sjkh	    return NULL;
32829517Sjkh    }
32929517Sjkh
33029517Sjkh    return head;
33129517Sjkh}
33229517Sjkh
33329517Sjkhstatic int
33429517Sjkhdispatch_execute(qelement *head)
33529517Sjkh{
33629517Sjkh    int result = DITEM_SUCCESS;
33729517Sjkh    command_buffer *item;
33837735Sjkh    char *old_interactive;
33929517Sjkh
34029517Sjkh    if (!head)
34129517Sjkh	return result | DITEM_FAILURE;
34229517Sjkh
34337735Sjkh    old_interactive = variable_get(VAR_NONINTERACTIVE);
34437735Sjkh    if (old_interactive)
34537735Sjkh	 old_interactive = strdup(old_interactive);	/* save copy */
34637735Sjkh
34729517Sjkh    /* Hint to others that we're running from a script, should they care */
34843685Sjkh    variable_set2(VAR_NONINTERACTIVE, "yes", 0);
34929517Sjkh
35029517Sjkh    while (!EMPTYQUE(*head)) {
35129517Sjkh	item = (command_buffer *) head->q_forw;
352189754Sgrog
35329517Sjkh	if (DITEM_STATUS(dispatchCommand(item->string)) != DITEM_SUCCESS) {
35497778Sjhb	    msgConfirm("Command `%s' failed - rest of script aborted.\n",
35597778Sjhb		       item->string);
35697778Sjhb	    result |= DITEM_FAILURE;
35797778Sjhb	    break;
35829517Sjkh	}
35929517Sjkh	dispatch_free_command(item);
36029517Sjkh    }
36129517Sjkh
36229517Sjkh    dispatch_free_all(head);
36329517Sjkh
36437735Sjkh    if (!old_interactive)
36537735Sjkh	variable_unset(VAR_NONINTERACTIVE);
36637735Sjkh    else {
36743685Sjkh	variable_set2(VAR_NONINTERACTIVE, old_interactive, 0);
36837735Sjkh	free(old_interactive);
36937735Sjkh    }
37029517Sjkh
37129517Sjkh    return result;
37229517Sjkh}
37329517Sjkh
37429517Sjkhint
37529517Sjkhdispatch_load_file_int(int quiet)
37629517Sjkh{
37729517Sjkh    FILE *fp;
37829517Sjkh    char *cp;
37929517Sjkh    int  i;
38029517Sjkh    qelement *list;
38129517Sjkh
38229517Sjkh    static const char *names[] = {
38329517Sjkh	"install.cfg",
38429517Sjkh	"/stand/install.cfg",
38529517Sjkh	"/tmp/install.cfg",
38629517Sjkh	NULL
38729517Sjkh    };
38829517Sjkh
38929517Sjkh    fp = NULL;
39029517Sjkh    cp = variable_get(VAR_CONFIG_FILE);
39129517Sjkh    if (!cp) {
39229517Sjkh	for (i = 0; names[i]; i++)
39329517Sjkh	    if ((fp = fopen(names[i], "r")) != NULL)
39429517Sjkh		break;
39529517Sjkh    } else
39629517Sjkh	fp = fopen(cp, "r");
39729517Sjkh
39829517Sjkh    if (!fp) {
39929517Sjkh	if (!quiet)
40029517Sjkh	    msgConfirm("Unable to open %s: %s", cp, strerror(errno));
40129517Sjkh	return DITEM_FAILURE;
40229517Sjkh    }
40329517Sjkh
40429517Sjkh    list = dispatch_load_fp(fp);
40529517Sjkh    fclose(fp);
40629517Sjkh
40729517Sjkh    return dispatch_execute(list);
40829517Sjkh}
40929517Sjkh
41029517Sjkhint
41129517Sjkhdispatch_load_file(dialogMenuItem *self)
41229517Sjkh{
41329517Sjkh    return dispatch_load_file_int(FALSE);
41429517Sjkh}
41529517Sjkh
41629517Sjkhint
41729517Sjkhdispatch_load_floppy(dialogMenuItem *self)
41829517Sjkh{
41954587Sjkh    int             what = DITEM_SUCCESS;
42029517Sjkh    extern char    *distWanted;
42129517Sjkh    char           *cp;
42229517Sjkh    FILE           *fp;
42329517Sjkh    qelement	   *list;
42429517Sjkh
42529517Sjkh    mediaClose();
42629517Sjkh    cp = variable_get_value(VAR_INSTALL_CFG,
427189754Sgrog			    "Specify the name of a configuration file", 0);
42829517Sjkh    if (!cp || !*cp) {
42929517Sjkh	variable_unset(VAR_INSTALL_CFG);
43029517Sjkh	what |= DITEM_FAILURE;
43129517Sjkh	return what;
43229517Sjkh    }
43329517Sjkh
43429517Sjkh    distWanted = cp;
43529517Sjkh    /* Try to open the floppy drive */
43629517Sjkh    if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE) {
43729517Sjkh	msgConfirm("Unable to set media device to floppy.");
43829517Sjkh	what |= DITEM_FAILURE;
43929517Sjkh	mediaClose();
44029517Sjkh	return what;
44129517Sjkh    }
44229517Sjkh
44379065Sdd    if (!DEVICE_INIT(mediaDevice)) {
44429517Sjkh	msgConfirm("Unable to mount floppy filesystem.");
44529517Sjkh	what |= DITEM_FAILURE;
44629517Sjkh	mediaClose();
44729517Sjkh	return what;
44829517Sjkh    }
44929517Sjkh
45079065Sdd    fp = DEVICE_GET(mediaDevice, cp, TRUE);
45129517Sjkh    if (fp) {
45229517Sjkh	list = dispatch_load_fp(fp);
45329517Sjkh	fclose(fp);
45429517Sjkh	mediaClose();
45529517Sjkh
45629517Sjkh	what |= dispatch_execute(list);
45729517Sjkh    }
45829517Sjkh    else {
45937735Sjkh	if (!variable_get(VAR_NO_ERROR))
46037735Sjkh	    msgConfirm("Configuration file '%s' not found.", cp);
46129517Sjkh	variable_unset(VAR_INSTALL_CFG);
46229517Sjkh	what |= DITEM_FAILURE;
46329517Sjkh	mediaClose();
46429517Sjkh    }
46529517Sjkh    return what;
46629517Sjkh}
46729517Sjkh
468189754Sgrogint
469189754Sgrogdispatch_load_cdrom(dialogMenuItem *self)
470189754Sgrog{
471189754Sgrog    int             what = DITEM_SUCCESS;
472189754Sgrog    extern char    *distWanted;
473189754Sgrog    char           *cp;
474189754Sgrog    FILE           *fp;
475189754Sgrog    qelement	   *list;
476189754Sgrog
477189754Sgrog    mediaClose();
478189754Sgrog    cp = variable_get_value(VAR_INSTALL_CFG,
479189754Sgrog			    "Specify the name of a configuration file\n"
480189754Sgrog			    "residing on the CDROM.", 0);
481189754Sgrog    if (!cp || !*cp) {
482189754Sgrog	variable_unset(VAR_INSTALL_CFG);
483189754Sgrog	what |= DITEM_FAILURE;
484189754Sgrog	return what;
485189754Sgrog    }
486189754Sgrog
487189754Sgrog    distWanted = cp;
488189754Sgrog    /* Try to open the floppy drive */
489189754Sgrog    if (DITEM_STATUS(mediaSetCDROM(NULL)) == DITEM_FAILURE) {
490189754Sgrog	msgConfirm("Unable to set media device to CDROM.");
491189754Sgrog	what |= DITEM_FAILURE;
492189754Sgrog	mediaClose();
493189754Sgrog	return what;
494189754Sgrog    }
495189754Sgrog
496189754Sgrog    if (!DEVICE_INIT(mediaDevice)) {
497189754Sgrog	msgConfirm("Unable to CDROM filesystem.");
498189754Sgrog	what |= DITEM_FAILURE;
499189754Sgrog	mediaClose();
500189754Sgrog	return what;
501189754Sgrog    }
502189754Sgrog
503189754Sgrog    fp = DEVICE_GET(mediaDevice, cp, TRUE);
504189754Sgrog    if (fp) {
505189754Sgrog	list = dispatch_load_fp(fp);
506189754Sgrog	fclose(fp);
507189754Sgrog	mediaClose();
508189754Sgrog
509189754Sgrog	what |= dispatch_execute(list);
510189754Sgrog    }
511189754Sgrog    else {
512189754Sgrog	if (!variable_get(VAR_NO_ERROR))
513189754Sgrog	    msgConfirm("Configuration file '%s' not found.", cp);
514189754Sgrog	variable_unset(VAR_INSTALL_CFG);
515189754Sgrog	what |= DITEM_FAILURE;
516189754Sgrog	mediaClose();
517189754Sgrog    }
518189754Sgrog    return what;
519189754Sgrog}
520189754Sgrog
521189754Sgrog/*
522189754Sgrog * Create a menu based on available disk devices
523189754Sgrog */
524189754Sgrogint
525189754Sgrogdispatch_load_menu(dialogMenuItem *self)
526189754Sgrog{
527189754Sgrog    DMenu	*menu;
528189754Sgrog    Device	**devlist;
529189754Sgrog    char	*err;
530189754Sgrog    int		what, i, j, msize, count;
531194931Scperciva    DeviceType	dtypes[] = {DEVICE_TYPE_FLOPPY, DEVICE_TYPE_CDROM,
532194931Scperciva	DEVICE_TYPE_DOS, DEVICE_TYPE_UFS, DEVICE_TYPE_USB};
533189754Sgrog
534189754Sgrog    fprintf(stderr, "dispatch_load_menu called\n");
535189754Sgrog
536189754Sgrog    msize = sizeof(DMenu) + (sizeof(dialogMenuItem) * 2);
537189754Sgrog    count = 0;
538189754Sgrog    err = NULL;
539189754Sgrog    what = DITEM_SUCCESS;
540189754Sgrog
541189754Sgrog    if ((menu = malloc(msize)) == NULL) {
542189754Sgrog	err = "Failed to allocate memory for menu";
543189754Sgrog	goto errout;
544189754Sgrog    }
545189754Sgrog
546189754Sgrog    bcopy(&MenuConfig, menu, sizeof(DMenu));
547189754Sgrog
548189754Sgrog    bzero(&menu->items[count], sizeof(menu->items[0]));
549189754Sgrog    menu->items[count].prompt = strdup("X Exit");
550189754Sgrog    menu->items[count].title = strdup("Exit this menu (returning to previous)");
551189754Sgrog    menu->items[count].fire = dmenuExit;
552189754Sgrog    count++;
553189754Sgrog
554189754Sgrog    for (i = 0; i < sizeof(dtypes) / sizeof(dtypes[0]); i++) {
555189754Sgrog	if ((devlist = deviceFind(NULL, dtypes[i])) == NULL) {
556189754Sgrog	    fprintf(stderr, "No devices found for type %d\n", dtypes[i]);
557189754Sgrog	    continue;
558189754Sgrog	}
559189754Sgrog
560189754Sgrog	for (j = 0; devlist[j] != NULL; j++) {
561189754Sgrog	    fprintf(stderr, "device type %d device name %s\n", dtypes[i], devlist[j]->name);
562189754Sgrog	    msize += sizeof(dialogMenuItem);
563189754Sgrog	    if ((menu = realloc(menu, msize)) == NULL) {
564189754Sgrog		err = "Failed to allocate memory for menu item";
565189754Sgrog		goto errout;
566189754Sgrog	    }
567189754Sgrog
568189754Sgrog	    bzero(&menu->items[count], sizeof(menu->items[0]));
569189754Sgrog	    menu->items[count].fire = cfgModuleFire;
570189754Sgrog
571189754Sgrog	    menu->items[count].prompt = strdup(devlist[j]->name);
572189754Sgrog	    menu->items[count].title = strdup(devlist[j]->description);
573189754Sgrog	    /* XXX: dialog(3) sucks */
574189754Sgrog	    menu->items[count].aux = (long)devlist[j];
575189754Sgrog	    count++;
576189754Sgrog	}
577189754Sgrog    }
578189754Sgrog
579189754Sgrog    menu->items[count].prompt = NULL;
580189754Sgrog    menu->items[count].title = NULL;
581189754Sgrog
582189754Sgrog    dmenuOpenSimple(menu, FALSE);
583189754Sgrog
584189754Sgrog  errout:
585189754Sgrog    for (i = 0; i < count; i++) {
586189754Sgrog	free(menu->items[i].prompt);
587189754Sgrog	free(menu->items[i].title);
588189754Sgrog    }
589189754Sgrog
590189754Sgrog    free(menu);
591189754Sgrog
592189754Sgrog    if (err != NULL) {
593189754Sgrog	what |= DITEM_FAILURE;
594189754Sgrog	if (!variable_get(VAR_NO_ERROR))
595234737Sdim	    msgConfirm("%s", err);
596189754Sgrog    }
597189754Sgrog
598189754Sgrog    return (what);
599189754Sgrog
600189754Sgrog}
601189754Sgrog
602189754Sgrogstatic int
603189754SgrogcfgModuleFire(dialogMenuItem *self) {
604189754Sgrog    Device	*d;
605189754Sgrog    FILE	*fp;
606189754Sgrog    int		what = DITEM_SUCCESS;
607189754Sgrog    extern char *distWanted;
608189754Sgrog    qelement	*list;
609189754Sgrog    char	*cp;
610189754Sgrog
611189754Sgrog    d = (Device *)self->aux;
612189754Sgrog
613189754Sgrog    msgDebug("cfgModuleFire: User selected %s (%s)\n", self->prompt, d->devname);
614189754Sgrog
615189754Sgrog    mediaClose();
616189754Sgrog
617189754Sgrog    cp = variable_get_value(VAR_INSTALL_CFG,
618189754Sgrog			    "Specify the name of a configuration file", 0);
619189754Sgrog    if (!cp || !*cp) {
620189754Sgrog	variable_unset(VAR_INSTALL_CFG);
621189754Sgrog	what |= DITEM_FAILURE;
622189754Sgrog	return what;
623189754Sgrog    }
624189754Sgrog
625189754Sgrog    distWanted = cp;
626189754Sgrog
627189754Sgrog    mediaDevice = d;
628189754Sgrog    if (!DEVICE_INIT(mediaDevice)) {
629189754Sgrog	msgConfirm("Unable to mount filesystem.");
630189754Sgrog	what |= DITEM_FAILURE;
631189754Sgrog	mediaClose();
632189754Sgrog	return what;
633189754Sgrog    }
634189754Sgrog    msgDebug("getting fp for %s\n", cp);
635189754Sgrog
636189754Sgrog    fp = DEVICE_GET(mediaDevice, cp, TRUE);
637189754Sgrog    if (fp) {
638189754Sgrog	msgDebug("opened OK, processing..\n");
639189754Sgrog
640189754Sgrog	list = dispatch_load_fp(fp);
641189754Sgrog	fclose(fp);
642189754Sgrog	mediaClose();
643189754Sgrog
644189754Sgrog	what |= dispatch_execute(list);
645189754Sgrog    } else {
646189754Sgrog	if (!variable_get(VAR_NO_ERROR))
647189754Sgrog	    msgConfirm("Configuration file '%s' not found.", cp);
648189754Sgrog	variable_unset(VAR_INSTALL_CFG);
649189754Sgrog	what |= DITEM_FAILURE;
650189754Sgrog	mediaClose();
651189754Sgrog    }
652189754Sgrog
653189754Sgrog    return(what);
654189754Sgrog }
655