1996-05-16 12:47:46 +01:00
|
|
|
|
/*
|
|
|
|
|
* The new sysinstall program.
|
|
|
|
|
*
|
|
|
|
|
* This is probably the last program in the `sysinstall' line - the next
|
|
|
|
|
* generation being essentially a complete rewrite.
|
|
|
|
|
*
|
1997-09-17 17:18:22 +01:00
|
|
|
|
* $Id: dispatch.c,v 1.23 1997/09/16 18:57:08 jkh Exp $
|
1996-05-16 12:47:46 +01:00
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 1995
|
|
|
|
|
* Jordan Hubbard. 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,
|
|
|
|
|
* verbatim and that no modifications are made prior to this
|
|
|
|
|
* point in the file.
|
|
|
|
|
* 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.
|
|
|
|
|
*
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``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 JORDAN HUBBARD OR HIS PETS 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, LIFE 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.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "sysinstall.h"
|
|
|
|
|
#include <ctype.h>
|
1997-09-16 19:57:18 +01:00
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <sys/signal.h>
|
|
|
|
|
#include <sys/fcntl.h>
|
1996-05-16 12:47:46 +01:00
|
|
|
|
|
1997-09-16 19:57:18 +01:00
|
|
|
|
#include "list.h"
|
|
|
|
|
|
|
|
|
|
static int dispatch_shutdown(dialogMenuItem *unused);
|
|
|
|
|
static int dispatch_systemExecute(dialogMenuItem *unused);
|
1997-09-08 12:09:11 +01:00
|
|
|
|
|
1996-05-16 12:47:46 +01:00
|
|
|
|
static struct _word {
|
|
|
|
|
char *name;
|
|
|
|
|
int (*handler)(dialogMenuItem *self);
|
|
|
|
|
} resWords[] = {
|
|
|
|
|
{ "configAnonFTP", configAnonFTP },
|
1996-11-04 12:56:33 +00:00
|
|
|
|
{ "configRouter", configRouter },
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{ "configNFSServer", configNFSServer },
|
1997-06-05 10:48:03 +01:00
|
|
|
|
{ "configNTP", configNTP },
|
|
|
|
|
{ "configPCNFSD", configPCNFSD },
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{ "configPackages", configPackages },
|
1997-06-05 10:48:03 +01:00
|
|
|
|
{ "configRegister", configRegister },
|
|
|
|
|
{ "configUsers", configUsers },
|
1997-06-21 16:45:15 +01:00
|
|
|
|
{ "configXEnvironment", configXEnvironment },
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{ "diskPartitionEditor", diskPartitionEditor },
|
|
|
|
|
{ "diskPartitionWrite", diskPartitionWrite },
|
|
|
|
|
{ "diskLabelEditor", diskLabelEditor },
|
|
|
|
|
{ "diskLabelCommit", diskLabelCommit },
|
|
|
|
|
{ "distReset", distReset },
|
1997-06-13 10:34:10 +01:00
|
|
|
|
{ "distSetCustom", distSetCustom },
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{ "distSetDeveloper", distSetDeveloper },
|
|
|
|
|
{ "distSetXDeveloper", distSetXDeveloper },
|
|
|
|
|
{ "distSetKernDeveloper", distSetKernDeveloper },
|
|
|
|
|
{ "distSetUser", distSetUser },
|
|
|
|
|
{ "distSetXUser", distSetXUser },
|
|
|
|
|
{ "distSetMinimum", distSetMinimum },
|
|
|
|
|
{ "distSetEverything", distSetEverything },
|
|
|
|
|
{ "distSetDES", distSetDES },
|
|
|
|
|
{ "distSetSrc", distSetSrc },
|
|
|
|
|
{ "distSetXF86", distSetXF86 },
|
|
|
|
|
{ "distExtractAll", distExtractAll },
|
|
|
|
|
{ "docBrowser", docBrowser },
|
|
|
|
|
{ "docShowDocument", docShowDocument },
|
|
|
|
|
{ "installCommit", installCommit },
|
|
|
|
|
{ "installExpress", installExpress },
|
1997-06-05 10:48:03 +01:00
|
|
|
|
{ "installNovice", installNovice },
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{ "installUpgrade", installUpgrade },
|
|
|
|
|
{ "installFixup", installFixup },
|
1997-06-05 10:48:03 +01:00
|
|
|
|
{ "installFixitHoloShell", installFixitHoloShell },
|
|
|
|
|
{ "installFixitCDROM", installFixitCDROM },
|
|
|
|
|
{ "installFixitFloppy", installFixitFloppy },
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{ "installFilesystems", installFilesystems },
|
1997-06-05 10:48:03 +01:00
|
|
|
|
{ "installVarDefaults", installVarDefaults },
|
1997-09-16 19:57:18 +01:00
|
|
|
|
{ "loadConfig", dispatch_load_file },
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{ "mediaSetCDROM", mediaSetCDROM },
|
|
|
|
|
{ "mediaSetFloppy", mediaSetFloppy },
|
|
|
|
|
{ "mediaSetDOS", mediaSetDOS },
|
|
|
|
|
{ "mediaSetTape", mediaSetTape },
|
|
|
|
|
{ "mediaSetFTP", mediaSetFTP },
|
|
|
|
|
{ "mediaSetFTPActive", mediaSetFTPActive },
|
|
|
|
|
{ "mediaSetFTPPassive", mediaSetFTPPassive },
|
|
|
|
|
{ "mediaSetUFS", mediaSetUFS },
|
|
|
|
|
{ "mediaSetNFS", mediaSetNFS },
|
1996-10-01 13:13:29 +01:00
|
|
|
|
{ "mediaSetFTPUserPass", mediaSetFTPUserPass },
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{ "mediaSetCPIOVerbosity", mediaSetCPIOVerbosity },
|
|
|
|
|
{ "mediaGetType", mediaGetType },
|
1996-06-08 10:08:51 +01:00
|
|
|
|
{ "optionsEditor", optionsEditor },
|
1997-03-10 21:11:57 +00:00
|
|
|
|
{ "register", configRegister }, /* Alias */
|
1997-06-13 18:55:32 +01:00
|
|
|
|
{ "packageAdd", packageAdd },
|
1996-12-14 23:09:10 +00:00
|
|
|
|
{ "addGroup", userAddGroup },
|
|
|
|
|
{ "addUser", userAddUser },
|
1997-09-16 19:57:18 +01:00
|
|
|
|
{ "shutdown", dispatch_shutdown },
|
|
|
|
|
{ "system", dispatch_systemExecute },
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{ NULL, NULL },
|
|
|
|
|
};
|
|
|
|
|
|
1997-09-16 19:57:18 +01:00
|
|
|
|
/*
|
|
|
|
|
* Helper routines for buffering data.
|
|
|
|
|
*
|
|
|
|
|
* We read an entire configuration into memory before executing it
|
|
|
|
|
* so that we are truely standalone and can do things like nuke the
|
|
|
|
|
* file or disk we're working on.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
typedef struct command_buffer_ {
|
|
|
|
|
qelement queue;
|
|
|
|
|
char * string;
|
|
|
|
|
} command_buffer;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
dispatch_free_command(command_buffer *item)
|
1996-05-16 12:47:46 +01:00
|
|
|
|
{
|
1997-09-16 19:57:18 +01:00
|
|
|
|
REMQUE(item);
|
|
|
|
|
free(item->string);
|
|
|
|
|
free(item);
|
|
|
|
|
}
|
1996-05-16 12:47:46 +01:00
|
|
|
|
|
1997-09-16 19:57:18 +01:00
|
|
|
|
static void
|
|
|
|
|
dispatch_free_all(qelement *head)
|
|
|
|
|
{
|
|
|
|
|
command_buffer *item;
|
|
|
|
|
|
|
|
|
|
while (!EMPTYQUE(*head)) {
|
|
|
|
|
item = (command_buffer *) head->q_forw;
|
|
|
|
|
dispatch_free_command(item);
|
1996-05-16 12:47:46 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-16 19:57:18 +01:00
|
|
|
|
static command_buffer *
|
|
|
|
|
dispatch_add_command(qelement *head, char *string)
|
|
|
|
|
{
|
|
|
|
|
command_buffer *new;
|
|
|
|
|
|
|
|
|
|
new = malloc(sizeof(command_buffer));
|
|
|
|
|
|
|
|
|
|
if (!new)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
new->string = strdup(string);
|
|
|
|
|
INSQUEUE(new, head->q_back);
|
|
|
|
|
|
|
|
|
|
return new;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Command processing
|
|
|
|
|
*/
|
|
|
|
|
|
1997-01-16 10:24:09 +00:00
|
|
|
|
/* Just convenience */
|
1997-06-22 10:45:41 +01:00
|
|
|
|
static int
|
1997-09-16 19:57:18 +01:00
|
|
|
|
dispatch_shutdown(dialogMenuItem *unused)
|
1997-01-16 10:24:09 +00:00
|
|
|
|
{
|
|
|
|
|
systemShutdown(0);
|
|
|
|
|
return DITEM_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
1997-06-22 10:45:41 +01:00
|
|
|
|
static int
|
1997-09-16 19:57:18 +01:00
|
|
|
|
dispatch_systemExecute(dialogMenuItem *unused)
|
1997-06-22 10:45:41 +01:00
|
|
|
|
{
|
1997-09-17 17:18:22 +01:00
|
|
|
|
char *cmd = variable_get(VAR_COMMAND);
|
1997-06-22 10:45:41 +01:00
|
|
|
|
|
|
|
|
|
if (cmd)
|
|
|
|
|
return systemExecute(cmd) ? DITEM_FAILURE : DITEM_SUCCESS;
|
|
|
|
|
else
|
|
|
|
|
msgDebug("_systemExecute: No command passed in `command' variable.\n");
|
|
|
|
|
return DITEM_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
1997-09-08 12:09:11 +01:00
|
|
|
|
static int
|
1997-09-16 19:57:18 +01:00
|
|
|
|
call_possible_resword(char *name, dialogMenuItem *value, int *status)
|
1997-09-08 12:09:11 +01:00
|
|
|
|
{
|
1997-09-16 19:57:18 +01:00
|
|
|
|
int i, rval;
|
|
|
|
|
|
|
|
|
|
rval = 0;
|
|
|
|
|
for (i = 0; resWords[i].name; i++) {
|
|
|
|
|
if (!strcmp(name, resWords[i].name)) {
|
|
|
|
|
*status = resWords[i].handler(value);
|
|
|
|
|
rval = 1;
|
|
|
|
|
break;
|
1997-09-08 12:09:11 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
1997-09-16 19:57:18 +01:00
|
|
|
|
return rval;
|
1997-09-08 12:09:11 +01:00
|
|
|
|
}
|
|
|
|
|
|
1996-05-16 12:47:46 +01:00
|
|
|
|
/* For a given string, call it or spit out an undefined command diagnostic */
|
|
|
|
|
int
|
|
|
|
|
dispatchCommand(char *str)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
1996-06-26 10:09:30 +01:00
|
|
|
|
char *cp;
|
1996-05-16 12:47:46 +01:00
|
|
|
|
|
|
|
|
|
if (!str || !*str) {
|
|
|
|
|
msgConfirm("Null or zero-length string passed to dispatchCommand");
|
|
|
|
|
return DITEM_FAILURE;
|
|
|
|
|
}
|
1997-01-16 10:24:09 +00:00
|
|
|
|
/* If it's got a newline, trim it */
|
|
|
|
|
if ((cp = index(str, '\n')) != NULL)
|
|
|
|
|
*cp = '\0';
|
|
|
|
|
|
1997-06-05 10:48:03 +01:00
|
|
|
|
/* If it's got a `=' sign in there, assume it's a variable setting */
|
1996-06-26 10:09:30 +01:00
|
|
|
|
if (index(str, '=')) {
|
1997-06-12 08:35:40 +01:00
|
|
|
|
if (isDebug())
|
|
|
|
|
msgDebug("dispatch: setting variable `%s'\n", str);
|
1996-05-16 12:47:46 +01:00
|
|
|
|
variable_set(str);
|
1997-01-16 10:24:09 +00:00
|
|
|
|
i = DITEM_SUCCESS;
|
1996-05-16 12:47:46 +01:00
|
|
|
|
}
|
1997-01-16 10:24:09 +00:00
|
|
|
|
else {
|
1997-09-16 19:57:18 +01:00
|
|
|
|
/* A command might be a pathname if it's encoded in argv[0], which
|
|
|
|
|
we also support */
|
1997-06-05 10:48:03 +01:00
|
|
|
|
if ((cp = rindex(str, '/')) != NULL)
|
1997-01-16 10:24:09 +00:00
|
|
|
|
str = cp + 1;
|
1997-06-12 08:35:40 +01:00
|
|
|
|
if (isDebug())
|
|
|
|
|
msgDebug("dispatch: calling resword `%s'\n", str);
|
1997-01-16 10:24:09 +00:00
|
|
|
|
if (!call_possible_resword(str, NULL, &i)) {
|
1997-06-05 10:48:03 +01:00
|
|
|
|
msgNotify("Warning: No such command ``%s''", str);
|
1997-01-16 10:24:09 +00:00
|
|
|
|
i = DITEM_FAILURE;
|
|
|
|
|
}
|
1996-05-16 12:47:46 +01:00
|
|
|
|
}
|
|
|
|
|
return i;
|
|
|
|
|
}
|
1997-09-16 19:57:18 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* File processing
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static qelement *
|
|
|
|
|
dispatch_load_fp(FILE *fp)
|
|
|
|
|
{
|
|
|
|
|
qelement *head;
|
|
|
|
|
char buf[BUFSIZ], *cp;
|
|
|
|
|
|
|
|
|
|
head = malloc(sizeof(qelement));
|
|
|
|
|
|
|
|
|
|
if (!head)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
INITQUE(*head);
|
|
|
|
|
|
|
|
|
|
while (fgets(buf, sizeof buf, fp)) {
|
|
|
|
|
|
|
|
|
|
if ((cp = strchr(buf, '\n')) != NULL)
|
|
|
|
|
*cp = '\0';
|
|
|
|
|
if (*buf == '\0' || *buf == '#')
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!dispatch_add_command(head, buf))
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return head;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
dispatch_execute(qelement *head)
|
|
|
|
|
{
|
|
|
|
|
int result = DITEM_SUCCESS;
|
|
|
|
|
command_buffer *item;
|
|
|
|
|
|
|
|
|
|
if (!head)
|
|
|
|
|
return result | DITEM_FAILURE;
|
|
|
|
|
|
|
|
|
|
/* Hint to others that we're running from a script, should they care */
|
|
|
|
|
variable_set2(VAR_NONINTERACTIVE, "YES");
|
|
|
|
|
|
|
|
|
|
while (!EMPTYQUE(*head)) {
|
|
|
|
|
item = (command_buffer *) head->q_forw;
|
|
|
|
|
|
|
|
|
|
if (DITEM_STATUS(dispatchCommand(item->string)) != DITEM_SUCCESS) {
|
|
|
|
|
/*
|
|
|
|
|
* Allow a user to prefix a command with "noError" to cause
|
|
|
|
|
* us to ignore any errors for that one command.
|
|
|
|
|
*/
|
|
|
|
|
if (variable_get(VAR_NO_ERROR))
|
|
|
|
|
variable_unset(VAR_NO_ERROR);
|
|
|
|
|
else {
|
|
|
|
|
msgConfirm("Command `%s' failed - rest of script aborted.\n",
|
|
|
|
|
item->string);
|
|
|
|
|
result |= DITEM_FAILURE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dispatch_free_command(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dispatch_free_all(head);
|
|
|
|
|
|
|
|
|
|
variable_unset(VAR_NONINTERACTIVE);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
dispatch_load_file_int(int quiet)
|
|
|
|
|
{
|
|
|
|
|
FILE *fp;
|
|
|
|
|
char *cp;
|
|
|
|
|
int i;
|
|
|
|
|
qelement *list;
|
|
|
|
|
|
|
|
|
|
static const char *names[] = {
|
|
|
|
|
"install.cfg",
|
|
|
|
|
"/stand/install.cfg",
|
|
|
|
|
"/tmp/install.cfg",
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
fp = NULL;
|
|
|
|
|
cp = variable_get(VAR_CONFIG_FILE);
|
|
|
|
|
if (!cp) {
|
|
|
|
|
for (i = 0; names[i]; i++)
|
|
|
|
|
if ((fp = fopen(names[i], "r")) != NULL)
|
|
|
|
|
break;
|
|
|
|
|
} else
|
|
|
|
|
fp = fopen(cp, "r");
|
|
|
|
|
|
|
|
|
|
if (!fp) {
|
|
|
|
|
if (!quiet)
|
|
|
|
|
msgConfirm("Unable to open %s: %s", cp, strerror(errno));
|
|
|
|
|
return DITEM_FAILURE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list = dispatch_load_fp(fp);
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
|
|
return dispatch_execute(list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
dispatch_load_file(dialogMenuItem *self)
|
|
|
|
|
{
|
|
|
|
|
return dispatch_load_file_int(FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
dispatch_load_floppy(dialogMenuItem *self)
|
|
|
|
|
{
|
|
|
|
|
int what = DITEM_RESTORE | DITEM_SUCCESS;
|
|
|
|
|
extern char *distWanted;
|
|
|
|
|
char *cp;
|
|
|
|
|
FILE *fp;
|
|
|
|
|
qelement *list;
|
|
|
|
|
|
|
|
|
|
mediaClose();
|
|
|
|
|
dialog_clear_norefresh();
|
|
|
|
|
|
|
|
|
|
cp = variable_get_value(VAR_INSTALL_CFG,
|
|
|
|
|
"Specify the name of a configuration file\n"
|
|
|
|
|
"residing on a MSDOS or UFS floppy.");
|
|
|
|
|
if (!cp || !*cp) {
|
|
|
|
|
variable_unset(VAR_INSTALL_CFG);
|
|
|
|
|
what |= DITEM_FAILURE;
|
|
|
|
|
return what;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
distWanted = cp;
|
|
|
|
|
/* Try to open the floppy drive */
|
|
|
|
|
if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE) {
|
|
|
|
|
msgConfirm("Unable to set media device to floppy.");
|
|
|
|
|
what |= DITEM_FAILURE;
|
|
|
|
|
mediaClose();
|
|
|
|
|
return what;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!mediaDevice->init(mediaDevice)) {
|
|
|
|
|
msgConfirm("Unable to mount floppy filesystem.");
|
|
|
|
|
what |= DITEM_FAILURE;
|
|
|
|
|
mediaClose();
|
|
|
|
|
return what;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fp = mediaDevice->get(mediaDevice, cp, TRUE);
|
|
|
|
|
if (fp) {
|
|
|
|
|
list = dispatch_load_fp(fp);
|
|
|
|
|
fclose(fp);
|
|
|
|
|
mediaClose();
|
|
|
|
|
|
|
|
|
|
what |= dispatch_execute(list);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
msgConfirm("Configuration file '%s' not found.", cp);
|
|
|
|
|
variable_unset(VAR_INSTALL_CFG);
|
|
|
|
|
what |= DITEM_FAILURE;
|
|
|
|
|
mediaClose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return what;
|
|
|
|
|
}
|
|
|
|
|
|