]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/sade/dispatch.c
Oops, forgot this cosmetic tweak to the perl menu item in my previous
[FreeBSD/FreeBSD.git] / usr.sbin / sade / dispatch.c
1 /*
2  * The new sysinstall program.
3  *
4  * This is probably the last program in the `sysinstall' line - the next
5  * generation being essentially a complete rewrite.
6  *
7  * $FreeBSD$
8  *
9  * Copyright (c) 1995
10  *      Jordan Hubbard.  All rights reserved.
11  *
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.
22  *
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.
34  *
35  */
36
37 #include "sysinstall.h"
38 #include <ctype.h>
39 #include <errno.h>
40 #include <sys/signal.h>
41 #include <sys/fcntl.h>
42
43 #include "list.h"
44
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_mediaClose(dialogMenuItem *unused);
49
50 static struct _word {
51     char *name;
52     int (*handler)(dialogMenuItem *self);
53 } resWords[] = {
54     { "configAnonFTP",          configAnonFTP           },
55     { "configRouter",           configRouter            },
56     { "configInetd",            configInetd             },
57     { "configNFSServer",        configNFSServer         },
58     { "configNTP",              configNTP               },
59     { "configPCNFSD",           configPCNFSD            },
60     { "configPackages",         configPackages          },
61     { "configUsers",            configUsers             },
62     { "configXSetup",           configXSetup    },
63     { "configXDesktop",         configXDesktop  },
64 #ifdef WITH_SLICES
65     { "diskPartitionEditor",    diskPartitionEditor     },
66 #endif
67     { "diskPartitionWrite",     diskPartitionWrite      },
68     { "diskLabelEditor",        diskLabelEditor         },
69     { "diskLabelCommit",        diskLabelCommit         },
70     { "distReset",              distReset               },
71     { "distSetCustom",          distSetCustom           },
72     { "distUnsetCustom",        distUnsetCustom         },
73     { "distSetDeveloper",       distSetDeveloper        },
74     { "distSetXDeveloper",      distSetXDeveloper       },
75     { "distSetKernDeveloper",   distSetKernDeveloper    },
76     { "distSetUser",            distSetUser             },
77     { "distSetXUser",           distSetXUser            },
78     { "distSetMinimum",         distSetMinimum          },
79     { "distSetEverything",      distSetEverything       },
80     { "distSetSrc",             distSetSrc              },
81 #ifndef X_AS_PKG
82     { "distSetXF86",            distSetXF86             },
83 #endif
84     { "distExtractAll",         distExtractAll          },
85     { "docBrowser",             docBrowser              },
86     { "docShowDocument",        docShowDocument         },
87     { "installCommit",          installCommit           },
88     { "installExpress",         installExpress          },
89     { "installStandard",        installStandard         },
90     { "installUpgrade",         installUpgrade          },
91     { "installFixupBin",        installFixupBin         },
92 #ifndef X_AS_PKG
93     { "installFixupXFree",      installFixupXFree       },
94 #endif
95     { "installFixitHoloShell",  installFixitHoloShell   },
96     { "installFixitCDROM",      installFixitCDROM       },
97     { "installFixitFloppy",     installFixitFloppy      },
98     { "installFilesystems",     installFilesystems      },
99     { "installVarDefaults",     installVarDefaults      },
100     { "loadConfig",             dispatch_load_file      },
101     { "loadFloppyConfig",       dispatch_load_floppy    },
102     { "mediaClose",             dispatch_mediaClose     },
103     { "mediaSetCDROM",          mediaSetCDROM           },
104     { "mediaSetFloppy",         mediaSetFloppy          },
105     { "mediaSetDOS",            mediaSetDOS             },
106     { "mediaSetTape",           mediaSetTape            },
107     { "mediaSetFTP",            mediaSetFTP             },
108     { "mediaSetFTPActive",      mediaSetFTPActive       },
109     { "mediaSetFTPPassive",     mediaSetFTPPassive      },
110     { "mediaSetHTTP",           mediaSetHTTP            },
111     { "mediaSetUFS",            mediaSetUFS             },
112     { "mediaSetNFS",            mediaSetNFS             },
113     { "mediaSetFTPUserPass",    mediaSetFTPUserPass     },
114     { "mediaSetCPIOVerbosity",  mediaSetCPIOVerbosity   },
115     { "mediaGetType",           mediaGetType            },
116     { "msgConfirm",             dispatch_msgConfirm     },
117     { "optionsEditor",          optionsEditor           },
118     { "packageAdd",             packageAdd              },
119     { "addGroup",               userAddGroup            },
120     { "addUser",                userAddUser             },
121     { "shutdown",               dispatch_shutdown       },
122     { "system",                 dispatch_systemExecute  },
123     { "dumpVariables",          dump_variables          },
124     { "tcpMenuSelect",          tcpMenuSelect           },
125     { NULL, NULL },
126 };
127
128 /*
129  * Helper routines for buffering data.
130  *
131  * We read an entire configuration into memory before executing it
132  * so that we are truely standalone and can do things like nuke the
133  * file or disk we're working on.
134  */
135
136 typedef struct command_buffer_ {
137     qelement    queue;
138     char *      string;
139 } command_buffer;
140
141 static void
142 dispatch_free_command(command_buffer *item)
143 {
144     REMQUE(item);
145     free(item->string);
146     free(item);
147 }
148
149 static void
150 dispatch_free_all(qelement *head)
151 {
152     command_buffer *item;
153
154     while (!EMPTYQUE(*head)) {
155         item = (command_buffer *) head->q_forw;
156         dispatch_free_command(item);
157     }
158 }
159
160 static command_buffer *
161 dispatch_add_command(qelement *head, char *string)
162 {
163     command_buffer *new;
164
165     new = malloc(sizeof(command_buffer));
166
167     if (!new)
168         return NULL;
169
170     new->string = strdup(string);
171     INSQUEUE(new, head->q_back);
172
173     return new;
174 }
175 \f
176 /*
177  * Command processing
178  */
179
180 /* Just convenience */
181 static int
182 dispatch_shutdown(dialogMenuItem *unused)
183 {
184     systemShutdown(0);
185     return DITEM_FAILURE;
186 }
187
188 static int
189 dispatch_systemExecute(dialogMenuItem *unused)
190 {
191     char *cmd = variable_get(VAR_COMMAND);
192
193     if (cmd)
194         return systemExecute(cmd) ? DITEM_FAILURE : DITEM_SUCCESS;
195     else
196         msgDebug("_systemExecute: No command passed in `command' variable.\n");
197     return DITEM_FAILURE;
198 }
199
200 static int
201 dispatch_msgConfirm(dialogMenuItem *unused)
202 {
203     char *msg = variable_get(VAR_COMMAND);
204
205     if (msg) {
206         msgConfirm("%s", msg);
207         return DITEM_SUCCESS;
208     }
209
210     msgDebug("_msgConfirm: No message passed in `command' variable.\n");
211     return DITEM_FAILURE;
212 }
213
214 static int
215 dispatch_mediaClose(dialogMenuItem *unused)
216 {
217     mediaClose();
218     return DITEM_SUCCESS;
219 }
220
221 static int
222 call_possible_resword(char *name, dialogMenuItem *value, int *status)
223 {
224     int i, rval;
225
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;
232         }
233     }
234     return rval;
235 }
236
237 /* For a given string, call it or spit out an undefined command diagnostic */
238 int
239 dispatchCommand(char *str)
240 {
241     int i;
242     char *cp;
243
244     if (!str || !*str) {
245         msgConfirm("Null or zero-length string passed to dispatchCommand");
246         return DITEM_FAILURE;
247     }
248     /* If it's got a newline, trim it */
249     if ((cp = index(str, '\n')) != NULL)
250         *cp = '\0';
251
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;
258     }
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;
269         }
270         /*
271          * Allow a user to prefix a command with "noError" to cause
272          * us to ignore any errors for that one command.
273          */
274         if (i != DITEM_SUCCESS && variable_get(VAR_NO_ERROR))
275             i = DITEM_SUCCESS;
276         variable_unset(VAR_NO_ERROR);
277     }
278     return i;
279 }
280
281 \f
282 /*
283  * File processing
284  */
285
286 static qelement *
287 dispatch_load_fp(FILE *fp)
288 {
289     qelement *head;
290     char buf[BUFSIZ], *cp;
291
292     head = malloc(sizeof(qelement));
293
294     if (!head)
295         return NULL;
296
297     INITQUE(*head);
298
299     while (fgets(buf, sizeof buf, fp)) {
300
301         if ((cp = strchr(buf, '\n')) != NULL)
302             *cp = '\0';
303         if (*buf == '\0' || *buf == '#')
304             continue;
305
306         if (!dispatch_add_command(head, buf))
307             return NULL;
308     }
309
310     return head;
311 }
312
313 static int
314 dispatch_execute(qelement *head)
315 {
316     int result = DITEM_SUCCESS;
317     command_buffer *item;
318     char *old_interactive;
319
320     if (!head)
321         return result | DITEM_FAILURE;
322
323     old_interactive = variable_get(VAR_NONINTERACTIVE);
324     if (old_interactive)
325          old_interactive = strdup(old_interactive);     /* save copy */
326
327     /* Hint to others that we're running from a script, should they care */
328     variable_set2(VAR_NONINTERACTIVE, "yes", 0);
329
330     while (!EMPTYQUE(*head)) {
331         item = (command_buffer *) head->q_forw;
332         
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;
338         }
339         dispatch_free_command(item);
340     }
341
342     dispatch_free_all(head);
343
344     if (!old_interactive)
345         variable_unset(VAR_NONINTERACTIVE);
346     else {
347         variable_set2(VAR_NONINTERACTIVE, old_interactive, 0);
348         free(old_interactive);
349     }
350
351     return result;
352 }
353
354 int
355 dispatch_load_file_int(int quiet)
356 {
357     FILE *fp;
358     char *cp;
359     int  i;
360     qelement *list;
361
362     static const char *names[] = {
363         "install.cfg",
364         "/stand/install.cfg",
365         "/tmp/install.cfg",
366         NULL
367     };
368
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");
377
378     if (!fp) {
379         if (!quiet)
380             msgConfirm("Unable to open %s: %s", cp, strerror(errno));
381         return DITEM_FAILURE;
382     }
383
384     list = dispatch_load_fp(fp);
385     fclose(fp);
386
387     return dispatch_execute(list);
388 }
389
390 int
391 dispatch_load_file(dialogMenuItem *self)
392 {
393     return dispatch_load_file_int(FALSE);
394 }
395
396 int
397 dispatch_load_floppy(dialogMenuItem *self)
398 {
399     int             what = DITEM_SUCCESS;
400     extern char    *distWanted;
401     char           *cp;
402     FILE           *fp;
403     qelement       *list;
404
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;
413     }
414
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;
422     }
423
424     if (!DEVICE_INIT(mediaDevice)) {
425         msgConfirm("Unable to mount floppy filesystem.");
426         what |= DITEM_FAILURE;
427         mediaClose();
428         return what;
429     }
430
431     fp = DEVICE_GET(mediaDevice, cp, TRUE);
432     if (fp) {
433         list = dispatch_load_fp(fp);
434         fclose(fp);
435         mediaClose();
436
437         what |= dispatch_execute(list);
438     }
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();
445     }
446     return what;
447 }
448