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.
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
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
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
37 #include "sysinstall.h"
40 #include <sys/signal.h>
41 #include <sys/fcntl.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
);
53 int (*handler
)(dialogMenuItem
*self
);
55 { "configAnonFTP", configAnonFTP
},
56 { "configRouter", configRouter
},
57 { "configInetd", configInetd
},
58 { "configNFSServer", configNFSServer
},
59 { "configNTP", configNTP
},
60 { "configPCNFSD", configPCNFSD
},
61 { "configPackages", configPackages
},
62 { "configUsers", configUsers
},
64 { "diskPartitionEditor", diskPartitionEditor
},
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
},
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_
{
136 dispatch_free_command(command_buffer
*item
)
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
)
159 new = malloc(sizeof(command_buffer
));
164 new->string
= strdup(string
);
165 INSQUEUE(new, head
->q_back
);
174 /* Just convenience */
176 dispatch_shutdown(dialogMenuItem
*unused
)
179 return DITEM_FAILURE
;
183 dispatch_systemExecute(dialogMenuItem
*unused
)
185 char *cmd
= variable_get(VAR_COMMAND
);
188 return systemExecute(cmd
) ? DITEM_FAILURE
: DITEM_SUCCESS
;
190 msgDebug("_systemExecute: No command passed in `command' variable.\n");
191 return DITEM_FAILURE
;
195 dispatch_msgConfirm(dialogMenuItem
*unused
)
197 char *msg
= variable_get(VAR_COMMAND
);
200 msgConfirm("%s", msg
);
201 return DITEM_SUCCESS
;
204 msgDebug("_msgConfirm: No message passed in `command' variable.\n");
205 return DITEM_FAILURE
;
209 dispatch_mediaOpen(dialogMenuItem
*unused
)
215 dispatch_mediaClose(dialogMenuItem
*unused
)
218 return DITEM_SUCCESS
;
222 call_possible_resword(char *name
, dialogMenuItem
*value
, int *status
)
227 for (i
= 0; resWords
[i
].name
; i
++) {
228 if (!strcmp(name
, resWords
[i
].name
)) {
229 *status
= resWords
[i
].handler(value
);
237 /* For a given string, call it or spit out an undefined command diagnostic */
239 dispatchCommand(char *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
)
252 /* If it's got a `=' sign in there, assume it's a variable setting */
253 if (index(str
, '=')) {
255 msgDebug("dispatch: setting variable `%s'\n", str
);
256 variable_set(str
, 0);
260 /* A command might be a pathname if it's encoded in argv[0], which
262 if ((cp
= rindex(str
, '/')) != NULL
)
265 msgDebug("dispatch: calling resword `%s'\n", str
);
266 if (!call_possible_resword(str
, NULL
, &i
)) {
267 msgNotify("Warning: No such command ``%s''", str
);
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
))
276 variable_unset(VAR_NO_ERROR
);
287 dispatch_load_fp(FILE *fp
)
290 char buf
[BUFSIZ
], *cp
;
292 head
= malloc(sizeof(qelement
));
299 while (fgets(buf
, sizeof buf
, fp
)) {
301 if ((cp
= strchr(buf
, '\n')) != NULL
)
303 if (*buf
== '\0' || *buf
== '#')
306 if (!dispatch_add_command(head
, buf
))
314 dispatch_execute(qelement
*head
)
316 int result
= DITEM_SUCCESS
;
317 command_buffer
*item
;
318 char *old_interactive
;
321 return result
| DITEM_FAILURE
;
323 old_interactive
= variable_get(VAR_NONINTERACTIVE
);
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",
336 result
|= DITEM_FAILURE
;
339 dispatch_free_command(item
);
342 dispatch_free_all(head
);
344 if (!old_interactive
)
345 variable_unset(VAR_NONINTERACTIVE
);
347 variable_set2(VAR_NONINTERACTIVE
, old_interactive
, 0);
348 free(old_interactive
);
355 dispatch_load_file_int(int quiet
)
362 static const char *names
[] = {
364 "/stand/install.cfg",
370 cp
= variable_get(VAR_CONFIG_FILE
);
372 for (i
= 0; names
[i
]; i
++)
373 if ((fp
= fopen(names
[i
], "r")) != NULL
)
380 msgConfirm("Unable to open %s: %s", cp
, strerror(errno
));
381 return DITEM_FAILURE
;
384 list
= dispatch_load_fp(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
;
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);
410 variable_unset(VAR_INSTALL_CFG
);
411 what
|= DITEM_FAILURE
;
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
;
424 if (!DEVICE_INIT(mediaDevice
)) {
425 msgConfirm("Unable to mount floppy filesystem.");
426 what
|= DITEM_FAILURE
;
431 fp
= DEVICE_GET(mediaDevice
, cp
, TRUE
);
433 list
= dispatch_load_fp(fp
);
437 what
|= dispatch_execute(list
);
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
;