diff options
Diffstat (limited to 'usr.sbin/sysinstall/dispatch.c')
| -rw-r--r-- | usr.sbin/sysinstall/dispatch.c | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/usr.sbin/sysinstall/dispatch.c b/usr.sbin/sysinstall/dispatch.c new file mode 100644 index 0000000000000..4896b235c1460 --- /dev/null +++ b/usr.sbin/sysinstall/dispatch.c @@ -0,0 +1,440 @@ +/* + * The new sysinstall program. + * + * This is probably the last program in the `sysinstall' line - the next + * generation being essentially a complete rewrite. + * + * $FreeBSD$ + * + * 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> +#include <errno.h> +#include <sys/signal.h> +#include <sys/fcntl.h> + +#include "list.h" + +static int dispatch_shutdown(dialogMenuItem *unused); +static int dispatch_systemExecute(dialogMenuItem *unused); +static int dispatch_msgConfirm(dialogMenuItem *unused); +static int dispatch_mediaClose(dialogMenuItem *unused); + +static struct _word { + char *name; + int (*handler)(dialogMenuItem *self); +} resWords[] = { + { "configAnonFTP", configAnonFTP }, + { "configRouter", configRouter }, + { "configInetd", configInetd }, + { "configNFSServer", configNFSServer }, + { "configNTP", configNTP }, + { "configPCNFSD", configPCNFSD }, + { "configPackages", configPackages }, + { "configUsers", configUsers }, +#ifdef WITH_SLICES + { "diskPartitionEditor", diskPartitionEditor }, +#endif + { "diskPartitionWrite", diskPartitionWrite }, + { "diskLabelEditor", diskLabelEditor }, + { "diskLabelCommit", diskLabelCommit }, + { "distReset", distReset }, + { "distSetCustom", distSetCustom }, + { "distUnsetCustom", distUnsetCustom }, + { "distSetDeveloper", distSetDeveloper }, + { "distSetXDeveloper", distSetXDeveloper }, + { "distSetKernDeveloper", distSetKernDeveloper }, + { "distSetUser", distSetUser }, + { "distSetXUser", distSetXUser }, + { "distSetMinimum", distSetMinimum }, + { "distSetEverything", distSetEverything }, + { "distSetSrc", distSetSrc }, + { "distExtractAll", distExtractAll }, + { "docBrowser", docBrowser }, + { "docShowDocument", docShowDocument }, + { "installCommit", installCommit }, + { "installExpress", installExpress }, + { "installStandard", installStandard }, + { "installUpgrade", installUpgrade }, + { "installFixupBase", installFixupBase }, + { "installFixitHoloShell", installFixitHoloShell }, + { "installFixitCDROM", installFixitCDROM }, + { "installFixitFloppy", installFixitFloppy }, + { "installFilesystems", installFilesystems }, + { "installVarDefaults", installVarDefaults }, + { "loadConfig", dispatch_load_file }, + { "loadFloppyConfig", dispatch_load_floppy }, + { "mediaClose", dispatch_mediaClose }, + { "mediaSetCDROM", mediaSetCDROM }, + { "mediaSetFloppy", mediaSetFloppy }, + { "mediaSetDOS", mediaSetDOS }, + { "mediaSetTape", mediaSetTape }, + { "mediaSetFTP", mediaSetFTP }, + { "mediaSetFTPActive", mediaSetFTPActive }, + { "mediaSetFTPPassive", mediaSetFTPPassive }, + { "mediaSetHTTP", mediaSetHTTP }, + { "mediaSetUFS", mediaSetUFS }, + { "mediaSetNFS", mediaSetNFS }, + { "mediaSetFTPUserPass", mediaSetFTPUserPass }, + { "mediaSetCPIOVerbosity", mediaSetCPIOVerbosity }, + { "mediaGetType", mediaGetType }, + { "msgConfirm", dispatch_msgConfirm }, + { "optionsEditor", optionsEditor }, + { "packageAdd", packageAdd }, + { "addGroup", userAddGroup }, + { "addUser", userAddUser }, + { "shutdown", dispatch_shutdown }, + { "system", dispatch_systemExecute }, + { "dumpVariables", dump_variables }, + { "tcpMenuSelect", tcpMenuSelect }, + { NULL, NULL }, +}; + +/* + * 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) +{ + REMQUE(item); + free(item->string); + free(item); +} + +static void +dispatch_free_all(qelement *head) +{ + command_buffer *item; + + while (!EMPTYQUE(*head)) { + item = (command_buffer *) head->q_forw; + dispatch_free_command(item); + } +} + +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 + */ + +/* Just convenience */ +static int +dispatch_shutdown(dialogMenuItem *unused) +{ + systemShutdown(0); + return DITEM_FAILURE; +} + +static int +dispatch_systemExecute(dialogMenuItem *unused) +{ + char *cmd = variable_get(VAR_COMMAND); + + if (cmd) + return systemExecute(cmd) ? DITEM_FAILURE : DITEM_SUCCESS; + else + msgDebug("_systemExecute: No command passed in `command' variable.\n"); + return DITEM_FAILURE; +} + +static int +dispatch_msgConfirm(dialogMenuItem *unused) +{ + char *msg = variable_get(VAR_COMMAND); + + if (msg) { + msgConfirm("%s", msg); + return DITEM_SUCCESS; + } + + msgDebug("_msgConfirm: No message passed in `command' variable.\n"); + return DITEM_FAILURE; +} + +static int +dispatch_mediaClose(dialogMenuItem *unused) +{ + mediaClose(); + return DITEM_SUCCESS; +} + +static int +call_possible_resword(char *name, dialogMenuItem *value, int *status) +{ + 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; + } + } + return rval; +} + +/* For a given string, call it or spit out an undefined command diagnostic */ +int +dispatchCommand(char *str) +{ + int i; + char *cp; + + if (!str || !*str) { + msgConfirm("Null or zero-length string passed to dispatchCommand"); + return DITEM_FAILURE; + } + /* If it's got a newline, trim it */ + if ((cp = index(str, '\n')) != NULL) + *cp = '\0'; + + /* If it's got a `=' sign in there, assume it's a variable setting */ + if (index(str, '=')) { + if (isDebug()) + msgDebug("dispatch: setting variable `%s'\n", str); + variable_set(str, 0); + i = DITEM_SUCCESS; + } + else { + /* A command might be a pathname if it's encoded in argv[0], which + we also support */ + if ((cp = rindex(str, '/')) != NULL) + str = cp + 1; + if (isDebug()) + msgDebug("dispatch: calling resword `%s'\n", str); + if (!call_possible_resword(str, NULL, &i)) { + msgNotify("Warning: No such command ``%s''", str); + i = DITEM_FAILURE; + } + /* + * Allow a user to prefix a command with "noError" to cause + * us to ignore any errors for that one command. + */ + if (i != DITEM_SUCCESS && variable_get(VAR_NO_ERROR)) + i = DITEM_SUCCESS; + variable_unset(VAR_NO_ERROR); + } + return i; +} + + +/* + * 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; + char *old_interactive; + + if (!head) + return result | DITEM_FAILURE; + + old_interactive = variable_get(VAR_NONINTERACTIVE); + if (old_interactive) + old_interactive = strdup(old_interactive); /* save copy */ + + /* Hint to others that we're running from a script, should they care */ + variable_set2(VAR_NONINTERACTIVE, "yes", 0); + + while (!EMPTYQUE(*head)) { + item = (command_buffer *) head->q_forw; + + if (DITEM_STATUS(dispatchCommand(item->string)) != DITEM_SUCCESS) { + msgConfirm("Command `%s' failed - rest of script aborted.\n", + item->string); + result |= DITEM_FAILURE; + break; + } + dispatch_free_command(item); + } + + dispatch_free_all(head); + + if (!old_interactive) + variable_unset(VAR_NONINTERACTIVE); + else { + variable_set2(VAR_NONINTERACTIVE, old_interactive, 0); + free(old_interactive); + } + + 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_SUCCESS; + extern char *distWanted; + char *cp; + FILE *fp; + qelement *list; + + mediaClose(); + cp = variable_get_value(VAR_INSTALL_CFG, + "Specify the name of a configuration file\n" + "residing on a MSDOS or UFS floppy.", 0); + 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 (!DEVICE_INIT(mediaDevice)) { + msgConfirm("Unable to mount floppy filesystem."); + what |= DITEM_FAILURE; + mediaClose(); + return what; + } + + fp = DEVICE_GET(mediaDevice, cp, TRUE); + if (fp) { + list = dispatch_load_fp(fp); + fclose(fp); + mediaClose(); + + what |= dispatch_execute(list); + } + else { + if (!variable_get(VAR_NO_ERROR)) + msgConfirm("Configuration file '%s' not found.", cp); + variable_unset(VAR_INSTALL_CFG); + what |= DITEM_FAILURE; + mediaClose(); + } + return what; +} + |
