fkvm_vcpu_run(): really messy and largely copied from kvm
[freebsd-src/fkvm-freebsd.git] / usr.sbin / sysinstall / dispatch.c
blobb1d0099b6803d90542abf117cf2a50bb561c7e2a
1 /*
2 * The new sysinstall program.
4 * This is probably the last program in the `sysinstall' line - the next
5 * generation being essentially a complete rewrite.
7 * $FreeBSD$
9 * Copyright (c) 1995
10 * Jordan Hubbard. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer,
17 * verbatim and that no modifications are made prior to this
18 * point in the file.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
23 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
37 #include "sysinstall.h"
38 #include <ctype.h>
39 #include <errno.h>
40 #include <sys/signal.h>
41 #include <sys/fcntl.h>
43 #include "list.h"
45 static int dispatch_shutdown(dialogMenuItem *unused);
46 static int dispatch_systemExecute(dialogMenuItem *unused);
47 static int dispatch_msgConfirm(dialogMenuItem *unused);
48 static int dispatch_mediaOpen(dialogMenuItem *unused);
49 static int dispatch_mediaClose(dialogMenuItem *unused);
51 static struct _word {
52 char *name;
53 int (*handler)(dialogMenuItem *self);
54 } resWords[] = {
55 { "configAnonFTP", configAnonFTP },
56 { "configRouter", configRouter },
57 { "configInetd", configInetd },
58 { "configNFSServer", configNFSServer },
59 { "configNTP", configNTP },
60 { "configPCNFSD", configPCNFSD },
61 { "configPackages", configPackages },
62 { "configUsers", configUsers },
63 #ifdef WITH_SLICES
64 { "diskPartitionEditor", diskPartitionEditor },
65 #endif
66 { "diskPartitionWrite", diskPartitionWrite },
67 { "diskLabelEditor", diskLabelEditor },
68 { "diskLabelCommit", diskLabelCommit },
69 { "distReset", distReset },
70 { "distSetCustom", distSetCustom },
71 { "distUnsetCustom", distUnsetCustom },
72 { "distSetDeveloper", distSetDeveloper },
73 { "distSetXDeveloper", distSetXDeveloper },
74 { "distSetKernDeveloper", distSetKernDeveloper },
75 { "distSetUser", distSetUser },
76 { "distSetXUser", distSetXUser },
77 { "distSetMinimum", distSetMinimum },
78 { "distSetEverything", distSetEverything },
79 { "distSetSrc", distSetSrc },
80 { "distExtractAll", distExtractAll },
81 { "docBrowser", docBrowser },
82 { "docShowDocument", docShowDocument },
83 { "installCommit", installCommit },
84 { "installExpress", installExpress },
85 { "installStandard", installStandard },
86 { "installUpgrade", installUpgrade },
87 { "installFixupBase", installFixupBase },
88 { "installFixitHoloShell", installFixitHoloShell },
89 { "installFixitCDROM", installFixitCDROM },
90 { "installFixitFloppy", installFixitFloppy },
91 { "installFilesystems", installFilesystems },
92 { "installVarDefaults", installVarDefaults },
93 { "loadConfig", dispatch_load_file },
94 { "loadFloppyConfig", dispatch_load_floppy },
95 { "mediaOpen", dispatch_mediaOpen },
96 { "mediaClose", dispatch_mediaClose },
97 { "mediaSetCDROM", mediaSetCDROM },
98 { "mediaSetFloppy", mediaSetFloppy },
99 { "mediaSetDOS", mediaSetDOS },
100 { "mediaSetTape", mediaSetTape },
101 { "mediaSetFTP", mediaSetFTP },
102 { "mediaSetFTPActive", mediaSetFTPActive },
103 { "mediaSetFTPPassive", mediaSetFTPPassive },
104 { "mediaSetHTTP", mediaSetHTTP },
105 { "mediaSetUFS", mediaSetUFS },
106 { "mediaSetNFS", mediaSetNFS },
107 { "mediaSetFTPUserPass", mediaSetFTPUserPass },
108 { "mediaSetCPIOVerbosity", mediaSetCPIOVerbosity },
109 { "mediaGetType", mediaGetType },
110 { "msgConfirm", dispatch_msgConfirm },
111 { "optionsEditor", optionsEditor },
112 { "packageAdd", packageAdd },
113 { "addGroup", userAddGroup },
114 { "addUser", userAddUser },
115 { "shutdown", dispatch_shutdown },
116 { "system", dispatch_systemExecute },
117 { "dumpVariables", dump_variables },
118 { "tcpMenuSelect", tcpMenuSelect },
119 { NULL, NULL },
123 * Helper routines for buffering data.
125 * We read an entire configuration into memory before executing it
126 * so that we are truely standalone and can do things like nuke the
127 * file or disk we're working on.
130 typedef struct command_buffer_ {
131 qelement queue;
132 char * string;
133 } command_buffer;
135 static void
136 dispatch_free_command(command_buffer *item)
138 REMQUE(item);
139 free(item->string);
140 free(item);
143 static void
144 dispatch_free_all(qelement *head)
146 command_buffer *item;
148 while (!EMPTYQUE(*head)) {
149 item = (command_buffer *) head->q_forw;
150 dispatch_free_command(item);
154 static command_buffer *
155 dispatch_add_command(qelement *head, char *string)
157 command_buffer *new;
159 new = malloc(sizeof(command_buffer));
161 if (!new)
162 return NULL;
164 new->string = strdup(string);
165 INSQUEUE(new, head->q_back);
167 return new;
171 * Command processing
174 /* Just convenience */
175 static int
176 dispatch_shutdown(dialogMenuItem *unused)
178 systemShutdown(0);
179 return DITEM_FAILURE;
182 static int
183 dispatch_systemExecute(dialogMenuItem *unused)
185 char *cmd = variable_get(VAR_COMMAND);
187 if (cmd)
188 return systemExecute(cmd) ? DITEM_FAILURE : DITEM_SUCCESS;
189 else
190 msgDebug("_systemExecute: No command passed in `command' variable.\n");
191 return DITEM_FAILURE;
194 static int
195 dispatch_msgConfirm(dialogMenuItem *unused)
197 char *msg = variable_get(VAR_COMMAND);
199 if (msg) {
200 msgConfirm("%s", msg);
201 return DITEM_SUCCESS;
204 msgDebug("_msgConfirm: No message passed in `command' variable.\n");
205 return DITEM_FAILURE;
208 static int
209 dispatch_mediaOpen(dialogMenuItem *unused)
211 return mediaOpen();
214 static int
215 dispatch_mediaClose(dialogMenuItem *unused)
217 mediaClose();
218 return DITEM_SUCCESS;
221 static int
222 call_possible_resword(char *name, dialogMenuItem *value, int *status)
224 int i, rval;
226 rval = 0;
227 for (i = 0; resWords[i].name; i++) {
228 if (!strcmp(name, resWords[i].name)) {
229 *status = resWords[i].handler(value);
230 rval = 1;
231 break;
234 return rval;
237 /* For a given string, call it or spit out an undefined command diagnostic */
239 dispatchCommand(char *str)
241 int i;
242 char *cp;
244 if (!str || !*str) {
245 msgConfirm("Null or zero-length string passed to dispatchCommand");
246 return DITEM_FAILURE;
248 /* If it's got a newline, trim it */
249 if ((cp = index(str, '\n')) != NULL)
250 *cp = '\0';
252 /* If it's got a `=' sign in there, assume it's a variable setting */
253 if (index(str, '=')) {
254 if (isDebug())
255 msgDebug("dispatch: setting variable `%s'\n", str);
256 variable_set(str, 0);
257 i = DITEM_SUCCESS;
259 else {
260 /* A command might be a pathname if it's encoded in argv[0], which
261 we also support */
262 if ((cp = rindex(str, '/')) != NULL)
263 str = cp + 1;
264 if (isDebug())
265 msgDebug("dispatch: calling resword `%s'\n", str);
266 if (!call_possible_resword(str, NULL, &i)) {
267 msgNotify("Warning: No such command ``%s''", str);
268 i = DITEM_FAILURE;
271 * Allow a user to prefix a command with "noError" to cause
272 * us to ignore any errors for that one command.
274 if (i != DITEM_SUCCESS && variable_get(VAR_NO_ERROR))
275 i = DITEM_SUCCESS;
276 variable_unset(VAR_NO_ERROR);
278 return i;
283 * File processing
286 static qelement *
287 dispatch_load_fp(FILE *fp)
289 qelement *head;
290 char buf[BUFSIZ], *cp;
292 head = malloc(sizeof(qelement));
294 if (!head)
295 return NULL;
297 INITQUE(*head);
299 while (fgets(buf, sizeof buf, fp)) {
301 if ((cp = strchr(buf, '\n')) != NULL)
302 *cp = '\0';
303 if (*buf == '\0' || *buf == '#')
304 continue;
306 if (!dispatch_add_command(head, buf))
307 return NULL;
310 return head;
313 static int
314 dispatch_execute(qelement *head)
316 int result = DITEM_SUCCESS;
317 command_buffer *item;
318 char *old_interactive;
320 if (!head)
321 return result | DITEM_FAILURE;
323 old_interactive = variable_get(VAR_NONINTERACTIVE);
324 if (old_interactive)
325 old_interactive = strdup(old_interactive); /* save copy */
327 /* Hint to others that we're running from a script, should they care */
328 variable_set2(VAR_NONINTERACTIVE, "yes", 0);
330 while (!EMPTYQUE(*head)) {
331 item = (command_buffer *) head->q_forw;
333 if (DITEM_STATUS(dispatchCommand(item->string)) != DITEM_SUCCESS) {
334 msgConfirm("Command `%s' failed - rest of script aborted.\n",
335 item->string);
336 result |= DITEM_FAILURE;
337 break;
339 dispatch_free_command(item);
342 dispatch_free_all(head);
344 if (!old_interactive)
345 variable_unset(VAR_NONINTERACTIVE);
346 else {
347 variable_set2(VAR_NONINTERACTIVE, old_interactive, 0);
348 free(old_interactive);
351 return result;
355 dispatch_load_file_int(int quiet)
357 FILE *fp;
358 char *cp;
359 int i;
360 qelement *list;
362 static const char *names[] = {
363 "install.cfg",
364 "/stand/install.cfg",
365 "/tmp/install.cfg",
366 NULL
369 fp = NULL;
370 cp = variable_get(VAR_CONFIG_FILE);
371 if (!cp) {
372 for (i = 0; names[i]; i++)
373 if ((fp = fopen(names[i], "r")) != NULL)
374 break;
375 } else
376 fp = fopen(cp, "r");
378 if (!fp) {
379 if (!quiet)
380 msgConfirm("Unable to open %s: %s", cp, strerror(errno));
381 return DITEM_FAILURE;
384 list = dispatch_load_fp(fp);
385 fclose(fp);
387 return dispatch_execute(list);
391 dispatch_load_file(dialogMenuItem *self)
393 return dispatch_load_file_int(FALSE);
397 dispatch_load_floppy(dialogMenuItem *self)
399 int what = DITEM_SUCCESS;
400 extern char *distWanted;
401 char *cp;
402 FILE *fp;
403 qelement *list;
405 mediaClose();
406 cp = variable_get_value(VAR_INSTALL_CFG,
407 "Specify the name of a configuration file\n"
408 "residing on a MSDOS or UFS floppy.", 0);
409 if (!cp || !*cp) {
410 variable_unset(VAR_INSTALL_CFG);
411 what |= DITEM_FAILURE;
412 return what;
415 distWanted = cp;
416 /* Try to open the floppy drive */
417 if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE) {
418 msgConfirm("Unable to set media device to floppy.");
419 what |= DITEM_FAILURE;
420 mediaClose();
421 return what;
424 if (!DEVICE_INIT(mediaDevice)) {
425 msgConfirm("Unable to mount floppy filesystem.");
426 what |= DITEM_FAILURE;
427 mediaClose();
428 return what;
431 fp = DEVICE_GET(mediaDevice, cp, TRUE);
432 if (fp) {
433 list = dispatch_load_fp(fp);
434 fclose(fp);
435 mediaClose();
437 what |= dispatch_execute(list);
439 else {
440 if (!variable_get(VAR_NO_ERROR))
441 msgConfirm("Configuration file '%s' not found.", cp);
442 variable_unset(VAR_INSTALL_CFG);
443 what |= DITEM_FAILURE;
444 mediaClose();
446 return what;