]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/sade/config.c
This commit was generated by cvs2svn to compensate for changes in r89232,
[FreeBSD/FreeBSD.git] / usr.sbin / sade / config.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 <sys/disklabel.h>
39 #include <sys/wait.h>
40 #include <sys/errno.h>
41 #include <sys/ioctl.h>
42 #include <sys/fcntl.h>
43 #include <sys/param.h>
44 #include <sys/stat.h>
45 #include <unistd.h>
46 #include <sys/mount.h>
47 #include <time.h>
48
49 static Chunk *chunk_list[MAX_CHUNKS];
50 static int nchunks;
51 static int rootdev_is_od;
52
53 /* arg to sort */
54 static int
55 chunk_compare(Chunk *c1, Chunk *c2)
56 {
57     if (!c1 && !c2)
58         return 0;
59     else if (!c1 && c2)
60         return 1;
61     else if (c1 && !c2)
62         return -1;
63     else if (!c1->private_data && !c2->private_data)
64         return 0;
65     else if (c1->private_data && !c2->private_data)
66         return 1;
67     else if (!c1->private_data && c2->private_data)
68         return -1;
69     else
70         return strcmp(((PartInfo *)(c1->private_data))->mountpoint, ((PartInfo *)(c2->private_data))->mountpoint);
71 }
72
73 static void
74 chunk_sort(void)
75 {
76     int i, j;
77
78     for (i = 0; i < nchunks; i++) {
79         for (j = 0; j < nchunks; j++) {
80             if (chunk_compare(chunk_list[j], chunk_list[j + 1]) > 0) {
81                 Chunk *tmp = chunk_list[j];
82
83                 chunk_list[j] = chunk_list[j + 1];
84                 chunk_list[j + 1] = tmp;
85             }
86         }
87     }
88 }
89
90 static void
91 check_rootdev(Chunk **list, int n)
92 {
93         int i;
94         Chunk *c;
95
96         rootdev_is_od = 0;
97         for (i = 0; i < n; i++) {
98                 c = *list++;
99                 if (c->type == part && (c->flags & CHUNK_IS_ROOT)
100                     && strncmp(c->disk->name, "od", 2) == 0)
101                         rootdev_is_od = 1;
102         }
103 }
104
105 static char *
106 name_of(Chunk *c1)
107 {
108     return c1->name;
109 }
110
111 static char *
112 mount_point(Chunk *c1)
113 {
114     if (c1->type == part && c1->subtype == FS_SWAP)
115         return "none";
116     else if (c1->type == part || c1->type == fat)
117         return ((PartInfo *)c1->private_data)->mountpoint;
118     return "/bogus";
119 }
120
121 static char *
122 fstype(Chunk *c1)
123 {
124     if (c1->type == fat)
125         return "msdosfs";
126     else if (c1->type == part) {
127         if (c1->subtype != FS_SWAP)
128             return "ufs";
129         else
130             return "swap";
131     }
132     return "bogus";
133 }
134
135 static char *
136 fstype_short(Chunk *c1)
137 {
138     if (c1->type == part) {
139         if (c1->subtype != FS_SWAP) {
140             if (rootdev_is_od == 0 && strncmp(c1->name, "od", 2) == 0)
141                 return "rw,noauto";
142             else
143                 return "rw";
144         }
145         else
146             return "sw";
147     }
148     else if (c1->type == fat) {
149         if (strncmp(c1->name, "od", 2) == 0)
150             return "ro,noauto";
151         else
152             return "ro";
153     }
154     return "bog";
155 }
156
157 static int
158 seq_num(Chunk *c1)
159 {
160     if (c1->type == part && c1->subtype != FS_SWAP) {
161         if (rootdev_is_od == 0 && strncmp(c1->name, "od", 2) == 0)
162             return 0;
163         else if (c1->flags & CHUNK_IS_ROOT)
164             return 1;
165         else
166             return 2;
167     }
168     return 0;
169 }
170
171 int
172 configFstab(dialogMenuItem *self)
173 {
174     Device **devs;
175     Disk *disk;
176     FILE *fstab;
177     int i, cnt;
178     Chunk *c1, *c2;
179
180     if (!RunningAsInit) {
181         if (file_readable("/etc/fstab"))
182             return DITEM_SUCCESS;
183         else {
184             msgConfirm("Attempting to rebuild your /etc/fstab file.  Warning: If you had\n"
185                        "any CD devices in use before running sysinstall then they may NOT\n"
186                        "be found by this run!");
187         }
188     }
189
190     devs = deviceFind(NULL, DEVICE_TYPE_DISK);
191     if (!devs) {
192         msgConfirm("No disks found!");
193         return DITEM_FAILURE;
194     }
195
196     /* Record all the chunks */
197     nchunks = 0;
198     for (i = 0; devs[i]; i++) {
199         if (!devs[i]->enabled)
200             continue;
201         disk = (Disk *)devs[i]->private;
202         if (!disk->chunks)
203             msgFatal("No chunk list found for %s!", disk->name);
204         for (c1 = disk->chunks->part; c1; c1 = c1->next) {
205             if (c1->type == freebsd) {
206                 for (c2 = c1->part; c2; c2 = c2->next) {
207                     if (c2->type == part && (c2->subtype == FS_SWAP || c2->private_data))
208                         chunk_list[nchunks++] = c2;
209                 }
210             }
211             else if (c1->type == fat && c1->private_data)
212                 chunk_list[nchunks++] = c1;
213         }
214     }
215     chunk_list[nchunks] = 0;
216     chunk_sort();
217     
218     fstab = fopen("/etc/fstab", "w");
219     if (!fstab) {
220         msgConfirm("Unable to create a new /etc/fstab file!  Manual intervention\n"
221                    "will be required.");
222         return DITEM_FAILURE;
223     }
224     
225     check_rootdev(chunk_list, nchunks);
226     
227     /* Go for the burn */
228     msgDebug("Generating /etc/fstab file\n");
229     fprintf(fstab, "# Device\t\tMountpoint\tFStype\tOptions\t\tDump\tPass#\n");
230     for (i = 0; i < nchunks; i++)
231         fprintf(fstab, "/dev/%s\t\t%s\t\t%s\t%s\t\t%d\t%d\n", name_of(chunk_list[i]), mount_point(chunk_list[i]),
232                 fstype(chunk_list[i]), fstype_short(chunk_list[i]), seq_num(chunk_list[i]), seq_num(chunk_list[i]));
233     
234     /* Now look for the CDROMs */
235     devs = deviceFind(NULL, DEVICE_TYPE_CDROM);
236     cnt = deviceCount(devs);
237     
238     /* Write out the CDROM entries */
239     for (i = 0; i < cnt; i++) {
240         char cdname[10];
241         
242         sprintf(cdname, "/cdrom%s", i ? itoa(i) : "");
243         if (Mkdir(cdname))
244             msgConfirm("Unable to make mount point for: %s", cdname);
245         else
246             fprintf(fstab, "/dev/%s\t\t%s\t\tcd9660\tro,noauto\t0\t0\n", devs[i]->name, cdname);
247     }
248     
249     /* And finally, a /proc. */
250     fprintf(fstab, "proc\t\t\t/proc\t\tprocfs\trw\t\t0\t0\n");
251     Mkdir("/proc");
252
253     fclose(fstab);
254     if (isDebug())
255         msgDebug("Wrote out /etc/fstab file\n");
256     return DITEM_SUCCESS;
257 }
258
259 /* Do the work of sucking in a config file.
260  * config is the filename to read in.
261  * lines is a fixed (max) sized array of char*
262  * returns number of lines read.  line contents
263  * are malloc'd and must be freed by the caller.
264  */
265 int
266 readConfig(char *config, char **lines, int max)
267 {
268     FILE *fp;
269     char line[256];
270     int i, nlines;
271
272     fp = fopen(config, "r");
273     if (!fp)
274         return -1;
275
276     nlines = 0;
277     /* Read in the entire file */
278     for (i = 0; i < max; i++) {
279         if (!fgets(line, sizeof line, fp))
280             break;
281         lines[nlines++] = strdup(line);
282     }
283     fclose(fp);
284     if (isDebug())
285         msgDebug("readConfig: Read %d lines from %s.\n", nlines, config);
286     return nlines;
287 }
288
289 #define MAX_LINES  2000 /* Some big number we're not likely to ever reach - I'm being really lazy here, I know */
290
291 static void
292 readConfigFile(char *config, int marked)
293 {
294     char *lines[MAX_LINES], *cp, *cp2;
295     int i, nlines;
296
297     nlines = readConfig(config, lines, MAX_LINES);
298     if (nlines == -1)
299         return;
300
301     for (i = 0; i < nlines; i++) {
302         /* Skip the comments & non-variable settings */
303         if (lines[i][0] == '#' || !(cp = index(lines[i], '='))) {
304             free(lines[i]);
305             continue;
306         }
307         *cp++ = '\0';
308         /* Find quotes */
309         if ((cp2 = index(cp, '"')) || (cp2 = index(cp, '\047'))) {
310             cp = cp2 + 1;
311             cp2 = index(cp, *cp2);
312         }
313         /* If valid quotes, use it */
314         if (cp2) {
315             *cp2 = '\0';
316             /* If we have a legit value, set it */
317             if (strlen(cp))
318                 variable_set2(lines[i], cp, marked);
319         }
320         free(lines[i]);
321     }
322 }
323
324 /* Load the environment from rc.conf file(s) */
325 void
326 configEnvironmentRC_conf(void)
327 {
328     static struct {
329         char *fname;
330         int marked;
331     } configs[] = {
332         { "/etc/defaults/rc.conf", 0 },
333         { "/etc/rc.conf", 0 },
334         { "/etc/rc.conf.local", 0 },
335         { NULL, 0 },
336     };
337     int i;
338
339     for (i = 0; configs[i].fname; i++) {
340         if (file_readable(configs[i].fname))
341             readConfigFile(configs[i].fname, configs[i].marked);
342     }
343 }
344
345 /* Load the environment from a resolv.conf file */
346 void
347 configEnvironmentResolv(char *config)
348 {
349     char *lines[MAX_LINES];
350     int i, nlines;
351
352     nlines = readConfig(config, lines, MAX_LINES);
353     if (nlines == -1)
354         return;
355     for (i = 0; i < nlines; i++) {
356         Boolean name_set = variable_get(VAR_NAMESERVER) ? 1 : 0;
357
358         if (!strncmp(lines[i], "domain", 6) && !variable_get(VAR_DOMAINNAME))
359             variable_set2(VAR_DOMAINNAME, string_skipwhite(string_prune(lines[i] + 6)), 0);
360         else if (!name_set && !strncmp(lines[i], "nameserver", 10)) {
361             /* Only take the first nameserver setting - we're lame */
362             variable_set2(VAR_NAMESERVER, string_skipwhite(string_prune(lines[i] + 10)), 0);
363         }
364         free(lines[i]);
365     }
366 }
367
368 /* Version of below for dispatch routines */
369 int
370 configRC(dialogMenuItem *unused)
371 {
372     configRC_conf();
373     return DITEM_SUCCESS;
374 }
375
376 void
377 configRC_conf(void)
378 {
379     FILE *rcSite;
380     Variable *v;
381     int write_header;
382     time_t t_loc;
383     char *cp;
384     static int did_marker = 0;
385     time_t tp;
386
387     configTtys();
388     write_header = !file_readable("/etc/rc.conf");
389     rcSite = fopen("/etc/rc.conf", "a");
390     if (!rcSite)
391         return;
392     if (write_header) {
393         fprintf(rcSite, "# This file now contains just the overrides from /etc/defaults/rc.conf.\n");
394         fprintf(rcSite, "# Please make all changes to this file, not to /etc/defaults/rc.conf.\n\n");
395         fprintf(rcSite, "# Enable network daemons for user convenience.\n");
396         if ((t_loc = time(NULL)) != -1 && (cp = ctime(&t_loc)))
397             fprintf(rcSite, "# Created: %s", cp);
398     }
399
400     /* Now do variable substitutions */
401     for (v = VarHead; v; v = v->next) {
402         if (v->dirty) {
403             if (!did_marker) {
404                 time(&tp);
405                 fprintf(rcSite, "# -- sysinstall generated deltas -- # "
406                     "%s", ctime(&tp));
407                 did_marker = 1;
408             }
409             fprintf(rcSite, "%s=\"%s\"\n", v->name, v->value);
410             v->dirty = 0;
411         }
412     }
413     fclose(rcSite);
414     /* Tidy up the resulting file if it's late enough in the installation
415         for sort and uniq to be available */
416     if (RunningAsInit && file_readable("/usr/bin/sort") && file_readable("/usr/bin/uniq"))
417         (void)vsystem("sort /etc/rc.conf | uniq > /etc/rc.conf.new && mv /etc/rc.conf.new /etc/rc.conf");
418 }
419
420 int
421 configSaver(dialogMenuItem *self)
422 {
423     variable_set((char *)self->data, 1);
424     if (!variable_get(VAR_BLANKTIME))
425         variable_set2(VAR_BLANKTIME, "300", 1);
426     return DITEM_SUCCESS;
427 }
428
429 int
430 configSaverTimeout(dialogMenuItem *self)
431 {
432     return (variable_get_value(VAR_BLANKTIME,
433             "Enter time-out period in seconds for screen saver", 1) ?
434         DITEM_SUCCESS : DITEM_FAILURE);
435 }
436
437 int
438 configNTP(dialogMenuItem *self)
439 {
440     int status;
441
442     status = variable_get_value(VAR_NTPDATE_FLAGS,
443                                 "Enter the name of an NTP server", 1)
444              ? DITEM_SUCCESS : DITEM_FAILURE;
445     if (status == DITEM_SUCCESS) {
446         static char tmp[255];
447
448         snprintf(tmp, sizeof(tmp), "ntpdate_enable=YES,ntpdate_flags=%s",
449                  variable_get(VAR_NTPDATE_FLAGS));
450         self->data = tmp;
451         dmenuSetVariables(self);
452     }
453     return status;
454 }
455
456 int
457 configUsers(dialogMenuItem *self)
458 {
459     WINDOW *w = savescr();
460
461     dialog_clear_norefresh();
462     dmenuOpenSimple(&MenuUsermgmt, FALSE); 
463     restorescr(w);
464     return DITEM_SUCCESS;
465 }
466
467 int
468 configLinux(dialogMenuItem *self)
469 {
470     WINDOW *w = savescr();
471     int i;
472
473     dialog_clear_norefresh();
474     variable_set2(VAR_LINUX_ENABLE, "YES", 1);
475     Mkdir("/compat/linux");
476     msgNotify("Installing Linux compatibility library...");
477     i = package_add("linux_base");
478     restorescr(w);
479     return i;
480 }
481
482 int
483 configSecurity(dialogMenuItem *self)
484 {
485     WINDOW *w = savescr();
486
487     dialog_clear_norefresh();
488     dmenuOpenSimple(&MenuSecurity, FALSE);
489     restorescr(w);
490     return DITEM_SUCCESS;
491 }
492
493 int
494 configSecurityProfile(dialogMenuItem *self)
495 {
496     WINDOW *w = savescr();
497
498     dialog_clear_norefresh();
499     dmenuOpenSimple(&MenuSecurityProfile, FALSE); 
500     restorescr(w);
501     return DITEM_SUCCESS;
502 }
503
504 /* Use the most extreme security settings */
505 int
506 configSecurityExtreme(dialogMenuItem *self)
507 {
508     WINDOW *w = savescr();
509
510     variable_set2("nfs_server_enable", "NO", 1);
511     variable_set2("sendmail_enable", "NO", 1);
512     variable_set2("sshd_enable", "NO", 1);
513     variable_set2("kern_securelevel_enable", "YES", 1);
514     variable_set2("kern_securelevel", "2", 1);
515
516     if (self)
517         msgConfirm("Extreme security settings have been selected.\n\n"
518             "Sendmail, sshd, and NFS services have been disabled, and\n"
519             "securelevels have been enabled.\n\n"
520             "PLEASE NOTE that this still does not save you from having\n"
521             "to properly secure your system in other ways or exercise\n"
522             "due diligence in your administration, this simply picks\n"
523             "a more secure set of out-of-box defaults to start with.\n\n"
524             "To change any of these settings later, edit /etc/rc.conf");
525
526     restorescr(w);
527     return DITEM_SUCCESS;
528 }
529
530 int
531 configSecurityModerate(dialogMenuItem *self)
532 {
533     WINDOW *w = savescr();
534
535     variable_set2("sendmail_enable", "YES", 1);
536     variable_set2("sshd_enable", "YES", 1);
537     variable_set2("kern_securelevel_enable", "NO", 1);
538
539     if (self)
540         msgConfirm("Moderate security settings have been selected.\n\n"
541             "Sendmail and sshd have been enabled, securelevels are\n"
542             "disabled, and NFS server settings have been left intact.\n\n"
543             "PLEASE NOTE that this still does not save you from having\n"
544             "to properly secure your system in other ways or exercise\n"
545             "due diligence in your administration, this simply picks\n"
546             "a standard set of out-of-box defaults to start with.\n\n"
547             "To change any of these settings later, edit /etc/rc.conf");
548
549     restorescr(w);
550     return DITEM_SUCCESS;
551 }
552
553 static void
554 write_root_xprofile(char *str)
555 {
556     FILE *fp;
557     int len;
558     char **cp;
559     static char *flist[] = { /* take care of both xdm and startx */
560         "/root/.xinitrc",
561         "/root/.xsession",
562         "/usr/share/skel/dot.xinitrc",
563         "/usr/share/skel/dot.xsession",
564         NULL,
565     };
566
567     len = strlen(str);
568     for (cp = flist; *cp; cp++) {
569         fp = fopen(*cp, "w");
570         if (fp) {
571             fwrite(str, 1, len, fp);
572             fchmod(fileno(fp), 0755);
573             fclose(fp);
574         }
575     }
576 }
577
578 static int
579 gotit(char *fname)
580 {
581     char tmp[FILENAME_MAX];
582
583     snprintf(tmp, sizeof tmp, "/usr/X11R6/bin/%s", fname);
584     if (file_executable(tmp))
585         return TRUE;
586     snprintf(tmp, sizeof tmp, "/usr/local/bin/%s", fname);
587     return file_executable(tmp);
588 }
589
590 int
591 configXDesktop(dialogMenuItem *self)
592 {
593     char *desk;
594     int ret = DITEM_SUCCESS;
595     WINDOW *w = savescr();
596     
597     dialog_clear_norefresh();
598     if (!dmenuOpenSimple(&MenuXDesktops, FALSE) || !(desk = variable_get(VAR_DESKSTYLE))) {
599         restorescr(w);
600         return DITEM_FAILURE;
601     }
602     if (!strcmp(desk, "kde")) {
603         ret = package_add("kde");
604         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("startkde"))
605             write_root_xprofile("exec startkde\n");
606     }
607     else if (!strcmp(desk, "gnome")) {
608         ret = package_add("gnomecore");
609         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("gnome-session")) {
610             ret = package_add("sawfish-gnome");
611             if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("sawfish"))
612                 write_root_xprofile("exec gnome-session\n");
613         }
614     }
615     else if (!strcmp(desk, "enlightenment")) {
616         ret = package_add("gnomecore");
617         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("gnome-session")) {
618             ret = package_add("enlightenment");
619             if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("enlightenment"))
620                 write_root_xprofile("exec gnome-session\n");
621         }
622     }
623     else if (!strcmp(desk, "afterstep")) {
624         ret = package_add("afterstep");
625         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("afterstep"))
626             write_root_xprofile("exec afterstep\n");
627     }
628     else if (!strcmp(desk, "windowmaker")) {
629         ret = package_add("windowmaker");
630         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("wmaker.inst")) {
631             write_root_xprofile("xterm &\n[ ! -d $HOME/GNUstep/Library/WindowMaker ] && /usr/X11R6/bin/wmaker.inst\nexec /usr/X11R6/bin/wmaker\n");
632         }
633     }
634     else if (!strcmp(desk, "fvwm2")) {
635         ret = package_add("fvwm");
636         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("fvwm"))
637             write_root_xprofile("exec fvwm\n");
638     }
639     if (DITEM_STATUS(ret) == DITEM_FAILURE)
640         msgConfirm("An error occurred while adding the package(s) required\n"
641                    "by this desktop type.  Please change installation media\n"
642                    "and/or select a different, perhaps simpler, desktop\n"
643                    "environment and try again.");
644     restorescr(w);
645     return ret;
646 }
647
648 int
649 configXSetup(dialogMenuItem *self)
650 {
651     char *config, *execfile, *style;
652     char *moused;
653     WINDOW *w = savescr();
654     
655     setenv("XWINHOME", "/usr/X11R6", 1);
656 tryagain:
657     variable_unset(VAR_DESKSTYLE);
658     variable_unset(VAR_XF86_CONFIG);
659     dialog_clear_norefresh();
660     if (!dmenuOpenSimple(&MenuXF86Config, FALSE)) {
661         restorescr(w);
662         return DITEM_FAILURE;
663     }
664     config = variable_get(VAR_XF86_CONFIG);
665     style = variable_get(VAR_DESKSTYLE);
666     if (!config) {
667         if (style)
668             goto config_desktop;
669         else {
670             restorescr(w);
671             return DITEM_FAILURE;
672         }
673     }
674
675     if (file_readable("/var/run/ld-elf.so.hints"))
676         vsystem("/sbin/ldconfig -m /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
677     else
678         vsystem("/sbin/ldconfig /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
679     if (file_readable("/var/run/ld.so.hints"))
680         vsystem("ldconfig -m -aout /usr/lib/aout /usr/lib/compat/aout /usr/local/lib/aout /usr/X11R6/lib/aout");
681     else
682         vsystem("ldconfig -aout /usr/lib/aout /usr/lib/compat/aout /usr/local/lib/aout /usr/X11R6/lib/aout");
683
684     vsystem("/sbin/ifconfig lo0 127.0.0.1");
685     execfile = string_concat("/usr/X11R6/bin/", config);
686     if (file_executable(execfile)) {
687         moused = variable_get(VAR_MOUSED);
688         while (!moused || strcmp(moused, "YES")) {
689             if (msgYesNo("The X server may access the mouse in two ways: direct access\n"
690                          "or indirect access via the mouse daemon.  You have not\n"
691                          "configured the mouse daemon.  Would you like to configure it\n"
692                          "now?  If you intend to let the X server access the mouse\n"
693                          "directly, choose \"No\" at this time."))
694                 break;
695             dialog_clear_norefresh();
696             dmenuOpenSimple(&MenuMouse, FALSE); 
697             moused = variable_get(VAR_MOUSED);
698         }
699         if (moused && !strcmp(moused, "YES"))
700             msgConfirm("You have configured and are now running the mouse daemon.\n"
701                        "Choose \"/dev/sysmouse\" as the mouse port and \"SysMouse\" or\n"
702                        "\"MouseSystems\" as the mouse protocol in the X configuration\n"
703                        "utility.");
704         systemExecute(execfile);
705         if (!file_readable("/etc/XF86Config")) {
706             if (!msgYesNo("The XFree86 configuration process seems to have\nfailed.  Would you like to try again?"))
707                 goto tryagain;
708             else {
709                 restorescr(w);
710                 return DITEM_FAILURE;
711             }
712         }
713 config_desktop:
714         configXDesktop(self);
715         restorescr(w);
716         return DITEM_SUCCESS;
717     }
718     else {
719         msgConfirm("The XFree86 setup utility you chose does not appear to be installed!\n"
720                    "Please install this before attempting to configure XFree86.");
721         restorescr(w);
722         return DITEM_FAILURE;
723     }
724 }
725
726 int
727 configResolv(dialogMenuItem *ditem)
728 {
729     FILE *fp;
730     char *cp, *c6p, *dp, *hp;
731
732     cp = variable_get(VAR_NAMESERVER);
733     if (!cp || !*cp)
734         goto skip;
735     Mkdir("/etc");
736     fp = fopen("/etc/resolv.conf", "w");
737     if (!fp)
738         return DITEM_FAILURE;
739     if (variable_get(VAR_DOMAINNAME))
740         fprintf(fp, "domain\t%s\n", variable_get(VAR_DOMAINNAME));
741     fprintf(fp, "nameserver\t%s\n", cp);
742     fclose(fp);
743     if (isDebug())
744         msgDebug("Wrote out /etc/resolv.conf\n");
745
746 skip:
747     dp = variable_get(VAR_DOMAINNAME);
748     cp = variable_get(VAR_IPADDR);
749     c6p = variable_get(VAR_IPV6ADDR);
750     hp = variable_get(VAR_HOSTNAME);
751     /* Tack ourselves into /etc/hosts */
752     fp = fopen("/etc/hosts", "w");
753     if (!fp)
754         return DITEM_FAILURE;
755     /* Add an entry for localhost */
756     if (!variable_cmp(VAR_IPV6_ENABLE, "YES")) {
757         if (dp)
758             fprintf(fp, "::1\t\t\tlocalhost.%s localhost\n", dp);
759         else
760             fprintf(fp, "::1\t\t\tlocalhost\n");
761     }
762     if (dp)
763         fprintf(fp, "127.0.0.1\t\tlocalhost.%s localhost\n", dp);
764     else
765         fprintf(fp, "127.0.0.1\t\tlocalhost\n");
766     /* Now the host entries, if applicable */
767     if (((cp && cp[0] != '0') || (c6p && c6p[0] != '0')) && hp) {
768         char cp2[255];
769
770         if (!index(hp, '.'))
771             cp2[0] = '\0';
772         else {
773             SAFE_STRCPY(cp2, hp);
774             *(index(cp2, '.')) = '\0';
775         }
776         if (c6p && c6p[0] != '0') {
777             fprintf(fp, "%s\t%s %s\n", c6p, hp, cp2);
778             fprintf(fp, "%s\t%s.\n", c6p, hp);
779         }
780         if (cp && cp[0] != '0') {
781             fprintf(fp, "%s\t\t%s %s\n", cp, hp, cp2);
782             fprintf(fp, "%s\t\t%s.\n", cp, hp);
783         }
784     }
785     fclose(fp);
786     if (isDebug())
787         msgDebug("Wrote out /etc/hosts\n");
788     return DITEM_SUCCESS;
789 }
790
791 int
792 configRouter(dialogMenuItem *self)
793 {
794     int ret;
795
796     ret = variable_get_value(VAR_ROUTER,
797                              "Please specify the router you wish to use.  Routed is\n"
798                              "provided with the stock system and gated is provided\n"
799                              "as an optional package which this installation system\n"
800                              "will attempt to load if you select gated.  Any other\n"
801                              "choice of routing daemon will be assumed to be something\n"
802                              "the user intends to install themselves before rebooting\n"
803                              "the system.  If you don't want any routing daemon, choose NO", 1)
804       ? DITEM_SUCCESS : DITEM_FAILURE;
805   
806     if (ret == DITEM_SUCCESS) {
807         char *cp = variable_get(VAR_ROUTER);
808     
809         if (cp && strcmp(cp, "NO")) {
810             variable_set2(VAR_ROUTER_ENABLE, "YES", 1);
811             if (!strcmp(cp, "gated")) {
812                 if (package_add("gated") != DITEM_SUCCESS) {
813                     msgConfirm("Unable to load gated package.  Falling back to no router.");
814                     variable_unset(VAR_ROUTER);
815                     variable_unset(VAR_ROUTERFLAGS);
816                     variable_set2(VAR_ROUTER_ENABLE, "NO", 1);
817                     cp = NULL;
818                 }
819             }
820             if (cp) {
821                 /* Now get the flags, if they chose a router */
822                 ret = variable_get_value(VAR_ROUTERFLAGS, 
823                                          "Please Specify the routing daemon flags; if you're running routed\n"
824                                          "then -q is the right choice for nodes and -s for gateway hosts.\n", 1)
825                   ? DITEM_SUCCESS : DITEM_FAILURE;
826                 if (ret != DITEM_SUCCESS)
827                     variable_unset(VAR_ROUTERFLAGS);
828             }
829         }
830         else {
831             /* No router case */
832             variable_set2(VAR_ROUTER_ENABLE, "NO", 1);
833             variable_unset(VAR_ROUTERFLAGS);
834             variable_unset(VAR_ROUTER);
835         }
836     }
837     else {
838         variable_set2(VAR_ROUTER_ENABLE, "NO", 1);
839         variable_unset(VAR_ROUTERFLAGS);
840         variable_unset(VAR_ROUTER);
841     }
842     return ret;
843 }
844
845 /* Shared between us and index_initialize() */
846 extern PkgNode Top, Plist;
847
848 int
849 configPackages(dialogMenuItem *self)
850 {
851     int i, restoreflag = 0;
852     PkgNodePtr tmp;
853
854     /* Did we get an INDEX? */
855     i = index_initialize("packages/INDEX");
856     if (DITEM_STATUS(i) == DITEM_FAILURE)
857         return i;
858
859     while (1) {
860         int ret, pos, scroll;
861
862         /* Bring up the packages menu */
863         pos = scroll = 0;
864         index_menu(&Top, &Top, &Plist, &pos, &scroll);
865
866         if (Plist.kids && Plist.kids->name) {
867             /* Now show the packing list menu */
868             pos = scroll = 0;
869             ret = index_menu(&Plist, &Plist, NULL, &pos, &scroll);
870             if (ret & DITEM_LEAVE_MENU)
871                 break;
872             else if (DITEM_STATUS(ret) != DITEM_FAILURE) {
873                 dialog_clear();
874                 restoreflag = 1;
875                 for (tmp = Plist.kids; tmp && tmp->name; tmp = tmp->next)
876                     (void)index_extract(mediaDevice, &Top, tmp, FALSE);
877                 break;
878             }
879         }
880         else {
881             msgConfirm("No packages were selected for extraction.");
882             break;
883         }
884     }
885     tmp = Plist.kids;
886     while (tmp) {
887         PkgNodePtr tmp2 = tmp->next;
888            
889         safe_free(tmp);
890         tmp = tmp2;
891     }
892     index_init(NULL, &Plist);
893     return DITEM_SUCCESS | (restoreflag ? DITEM_RESTORE : 0);
894 }
895
896 /* Load pcnfsd package */
897 int
898 configPCNFSD(dialogMenuItem *self)
899 {
900     int ret;
901
902     ret = package_add("pcnfsd");
903     if (DITEM_STATUS(ret) == DITEM_SUCCESS) {
904         variable_set2(VAR_PCNFSD, "YES", 0);
905         variable_set2("mountd_flags", "-n", 1);
906     }
907     return ret;
908 }
909
910 int
911 configInetd(dialogMenuItem *self)
912 {
913     char cmd[256];
914
915     WINDOW *w = savescr();
916
917     if (msgYesNo("The Internet Super Server (inetd) allows a number of simple Internet\n"
918                  "services to be enabled, including finger, ftp, and telnetd.  Enabling\n"
919                  "these services may increase risk of security problems by increasing\n"
920                  "the exposure of your system.\n\n"
921                  "With this in mind, do you wish to enable inetd?\n")) {
922         variable_set2("inetd_enable", "NO", 1);
923     } else {
924         /* If inetd is enabled, we'll need an inetd.conf */
925
926         if (!msgYesNo("inetd(8) relies on its configuration file, /etc/inetd.conf, to determine\n"
927                    "which of its Internet services will be available.  The default FreeBSD\n"
928                    "inetd.conf(5) leaves all services disabled by default, so they must be\n"
929                    "specifically enabled in the configuration file before they will\n"
930                    "function, even once inetd(8) is enabled.  Note that services for\n"
931                    "IPv6 must be seperately enabled from IPv4 services.\n\n"
932                    "Select [Yes] now to invoke an editor on /etc/inetd.conf, or [No] to\n"
933                    "use the current settings.\n")) {
934             sprintf(cmd, "%s /etc/inetd.conf", variable_get(VAR_EDITOR));
935             dialog_clear();
936             systemExecute(cmd);
937             variable_set2("inetd_enable", "YES", 1);
938         }
939     }
940     restorescr(w);
941     return DITEM_SUCCESS;
942 }
943
944 int
945 configNFSServer(dialogMenuItem *self)
946 {
947     char cmd[256];
948
949     /* If we're an NFS server, we need an exports file */
950     if (!file_readable("/etc/exports")) {
951         WINDOW *w = savescr();
952
953         if (file_readable("/etc/exports.disabled"))
954             vsystem("mv /etc/exports.disabled /etc/exports");
955         else {
956             dialog_clear_norefresh();
957             msgConfirm("Operating as an NFS server means that you must first configure\n"
958                        "an /etc/exports file to indicate which hosts are allowed certain\n"
959                        "kinds of access to your local file systems.\n"
960                        "Press [ENTER] now to invoke an editor on /etc/exports\n");
961             vsystem("echo '#The following examples export /usr to 3 machines named after ducks,' > /etc/exports");
962             vsystem("echo '#/usr/src and /usr/ports read-only to machines named after trouble makers' >> /etc/exports");
963             vsystem("echo '#/home and all directories under it to machines named after dead rock stars' >> /etc/exports");
964             vsystem("echo '#and, /a to a network of privileged machines allowed to write on it as root.' >> /etc/exports");
965             vsystem("echo '#/usr                   huey louie dewie' >> /etc/exports");
966             vsystem("echo '#/usr/src /usr/obj -ro  calvin hobbes' >> /etc/exports");
967             vsystem("echo '#/home   -alldirs       janice jimmy frank' >> /etc/exports");
968             vsystem("echo '#/a      -maproot=0  -network 10.0.1.0 -mask 255.255.248.0' >> /etc/exports");
969             vsystem("echo '#' >> /etc/exports");
970             vsystem("echo '# You should replace these lines with your actual exported filesystems.' >> /etc/exports");
971             vsystem("echo '# Note that BSD's export synatx is \"host-centric\" vs. Sun\'s \"FS-centric\" one.' >> /etc/exports");
972             vsystem("echo >> /etc/exports");
973             sprintf(cmd, "%s /etc/exports", variable_get(VAR_EDITOR));
974             dialog_clear();
975             systemExecute(cmd);
976         }
977         variable_set2(VAR_NFS_SERVER, "YES", 1);
978         restorescr(w);
979     }
980     else if (variable_get(VAR_NFS_SERVER)) { /* We want to turn it off again? */
981         vsystem("mv -f /etc/exports /etc/exports.disabled");
982         variable_unset(VAR_NFS_SERVER);
983     }
984     return DITEM_SUCCESS;
985 }
986
987 int
988 configEtcTtys(dialogMenuItem *self)
989 {
990     char cmd[256];
991
992     WINDOW *w = savescr();
993
994     /* Simply prompt for confirmation, then edit away. */
995     if (msgYesNo("Configuration of system TTYs requires editing the /etc/ttys file.\n"
996                  "Typical configuration activities might include enabling getty(8)\n"
997                  "on the first serial port to allow login via serial console after\n"
998                  "reboot, or to enable xdm.  The default ttys file enables normal\n"
999                  "virtual consoles, and most sites will not need to perform manual\n"
1000                  "configuration.\n\n"
1001                  "To load /etc/ttys in the editor, select [Yes], otherwise, [No].")) {
1002     } else {
1003         configTtys();
1004         sprintf(cmd, "%s /etc/ttys", variable_get(VAR_EDITOR));
1005         dialog_clear();
1006         systemExecute(cmd);
1007     }
1008
1009     restorescr(w);
1010     return DITEM_SUCCESS;
1011 }