]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/sysinstall/config.c
This commit was generated by cvs2svn to compensate for changes in r80260,
[FreeBSD/FreeBSD.git] / usr.sbin / sysinstall / 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 = (Boolean)variable_get(VAR_NAMESERVER);
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
386     configTtys();
387     write_header = !file_readable("/etc/rc.conf");
388     rcSite = fopen("/etc/rc.conf", "a");
389     if (!rcSite)
390         return;
391     if (write_header) {
392         fprintf(rcSite, "# This file now contains just the overrides from /etc/defaults/rc.conf\n");
393         fprintf(rcSite, "# please make all changes to this file.\n\n");
394         fprintf(rcSite, "# Enable network daemons for user convenience.\n");
395         if ((t_loc = time(NULL)) != -1 && (cp = ctime(&t_loc)))
396             fprintf(rcSite, "# Created: %s", cp);
397     }
398
399     /* Now do variable substitutions */
400     for (v = VarHead; v; v = v->next) {
401         if (v->dirty) {
402             if (!did_marker) {
403                 fprintf(rcSite, "# -- sysinstall generated deltas -- #\n");
404                 did_marker = 1;
405             }
406             fprintf(rcSite, "%s=\"%s\"\n", v->name, v->value);
407             v->dirty = 0;
408         }
409     }
410     fclose(rcSite);
411     /* Tidy up the resulting file if it's late enough in the installation
412         for sort and uniq to be available */
413     if (RunningAsInit && file_readable("/usr/bin/sort") && file_readable("/usr/bin/uniq"))
414         (void)vsystem("sort /etc/rc.conf | uniq > /etc/rc.conf.new && mv /etc/rc.conf.new /etc/rc.conf");
415 }
416
417 int
418 configSaver(dialogMenuItem *self)
419 {
420     variable_set((char *)self->data, 1);
421     if (!variable_get(VAR_BLANKTIME))
422         variable_set2(VAR_BLANKTIME, "300", 1);
423     return DITEM_SUCCESS;
424 }
425
426 int
427 configSaverTimeout(dialogMenuItem *self)
428 {
429     return (variable_get_value(VAR_BLANKTIME,
430             "Enter time-out period in seconds for screen saver", 1) ?
431         DITEM_SUCCESS : DITEM_FAILURE);
432 }
433
434 int
435 configNTP(dialogMenuItem *self)
436 {
437     int status;
438
439     status = variable_get_value(VAR_NTPDATE_FLAGS,
440                                 "Enter the name of an NTP server", 1)
441              ? DITEM_SUCCESS : DITEM_FAILURE;
442     if (status == DITEM_SUCCESS) {
443         static char tmp[255];
444
445         snprintf(tmp, sizeof(tmp), "ntpdate_enable=YES,ntpdate_flags=%s",
446                  variable_get(VAR_NTPDATE_FLAGS));
447         self->data = tmp;
448         dmenuSetVariables(self);
449     }
450     return status;
451 }
452
453 int
454 configUsers(dialogMenuItem *self)
455 {
456     WINDOW *w = savescr();
457
458     dialog_clear_norefresh();
459     dmenuOpenSimple(&MenuUsermgmt, FALSE); 
460     restorescr(w);
461     return DITEM_SUCCESS;
462 }
463
464 int
465 configLinux(dialogMenuItem *self)
466 {
467     WINDOW *w = savescr();
468     int i;
469
470     dialog_clear_norefresh();
471     variable_set2(VAR_LINUX_ENABLE, "YES", 1);
472     Mkdir("/compat/linux");
473     msgNotify("Installing Linux compatibility library...");
474     i = package_add("linux_base");
475     restorescr(w);
476     return i;
477 }
478
479 int
480 configSecurityProfile(dialogMenuItem *self)
481 {
482     WINDOW *w = savescr();
483
484     dialog_clear_norefresh();
485     dmenuOpenSimple(&MenuSecurityProfile, FALSE); 
486     restorescr(w);
487     return DITEM_SUCCESS;
488 }
489
490 /* Use the most fascist security settings */
491 int
492 configSecurityFascist(dialogMenuItem *self)
493 {
494     WINDOW *w = savescr();
495
496     variable_set2("inetd_enable", "NO", 1);
497     variable_set2("portmap_enable", "NO", 1);
498     variable_set2("sendmail_enable", "NO", 1);
499     variable_set2("sshd_enable", "NO", 1);
500     variable_set2("nfs_server_enable", "NO", 1);
501     variable_set2("kern_securelevel_enable", "YES", 1);
502     variable_set2("kern_securelevel", "2", 1);
503     /* More fascist stuff should go here */
504
505     if (self)
506         msgConfirm("Extreme security settings have been selected.\n\n"
507             "This means that all \"popular\" network services and\n"
508             "mechanisms like inetd(8) have been DISABLED by default.\n\n"
509             "PLEASE NOTE that this still does not save you from having\n"
510             "to properly secure your system in other ways or exercise\n"
511             "due diligence in your administration, this simply picks\n"
512             "a more secure set of out-of-box defaults to start with.\n\n"
513             "To change any of these settings later, edit /etc/rc.conf");
514
515     restorescr(w);
516     return DITEM_SUCCESS;
517 }
518
519 int
520 configSecurityHigh(dialogMenuItem *self)
521 {
522     WINDOW *w = savescr();
523
524     variable_set2("inetd_enable", "NO", 1);
525     variable_set2("sendmail_enable", "YES", 1);
526     variable_set2("sshd_enable", "YES", 1);
527     variable_set2("portmap_enable", "NO", 1);
528     variable_set2("nfs_server_enable", "NO", 1);
529     variable_set2("kern_securelevel_enable", "YES", 1);
530     variable_set2("kern_securelevel", "1", 1);
531
532     if (self)
533         msgConfirm("High security settings have been selected.\n\n"
534             "This means that most \"popular\" network services and\n"
535             "mechanisms like inetd(8) have been DISABLED by default.\n\n"
536             "PLEASE NOTE that this still does not save you from having\n"
537             "to properly secure your system in other ways or exercise\n"
538             "due diligence in your administration, this simply picks\n"
539             "a more secure set of out-of-box defaults to start with.\n\n"
540             "To change any of these settings later, edit /etc/rc.conf");
541
542     restorescr(w);
543     return DITEM_SUCCESS;
544 }
545
546 int
547 configSecurityModerate(dialogMenuItem *self)
548 {
549     WINDOW *w = savescr();
550
551     variable_set2("inetd_enable", "YES", 1);
552     if (!variable_cmp("nfs_client_enable", "YES") ||
553         !variable_cmp("nfs_server_enable", "YES"))
554         variable_set2("portmap_enable", "YES", 1);
555     if (!variable_cmp("nfs_server_enable", "YES"))
556         variable_set2("nfs_reserved_port_only", "YES", 1);
557     variable_set2("sendmail_enable", "YES", 1);
558     variable_set2("sshd_enable", "YES", 1);
559     variable_set2("kern_securelevel_enable", "NO", 1);
560
561     if (self)
562         msgConfirm("Moderate security settings have been selected.\n\n"
563             "This means that most \"popular\" network services and\n"
564             "mechanisms like inetd(8) have been enabled by default\n"
565             "for a comfortable user experience but with possible\n"
566             "trade-offs in system security.  If this bothers you and\n"
567             "you know exactly what you are doing, select one of the\n"
568             "other security profiles instead.\n\n"
569             "To change any of these settings later, edit /etc/rc.conf");
570
571     restorescr(w);
572     return DITEM_SUCCESS;
573 }
574
575 int
576 configSecurityLiberal(dialogMenuItem *self)
577 {
578     WINDOW *w = savescr();
579
580     variable_set2("inetd_enable", "YES", 1);
581     variable_set2("portmap_enable", "YES", 1);
582     variable_set2("sendmail_enable", "YES", 1);
583     variable_set2("sshd_enable", "YES", 1);
584     variable_set2("kern_securelevel_enable", "NO", 1);
585
586     if (self)
587         msgConfirm("Liberal security settings have been selected.\n\n"
588             "This means that most \"popular\" network services and\n"
589             "mechanisms like inetd(8) have been enabled by default\n"
590             "for the most comfortable user experience but with possible\n"
591             "trade-offs in system security.  If this bothers you and\n"
592             "you know exactly what you are doing, select one of the\n"
593             "other security profiles instead.\n\n"
594             "To change any of these settings later, edit /etc/rc.conf");
595
596     restorescr(w);
597     return DITEM_SUCCESS;
598 }
599
600 static void
601 write_root_xprofile(char *str)
602 {
603     FILE *fp;
604     int len;
605     char **cp;
606     static char *flist[] = { /* take care of both xdm and startx */
607         "/root/.xinitrc",
608         "/root/.xsession",
609         "/usr/share/skel/dot.xinitrc",
610         "/usr/share/skel/dot.xsession",
611         NULL,
612     };
613
614     len = strlen(str);
615     for (cp = flist; *cp; cp++) {
616         fp = fopen(*cp, "w");
617         if (fp) {
618             fwrite(str, 1, len, fp);
619             fchmod(fileno(fp), 0755);
620             fclose(fp);
621         }
622     }
623 }
624
625 static int
626 gotit(char *fname)
627 {
628     char tmp[FILENAME_MAX];
629
630     snprintf(tmp, sizeof tmp, "/usr/X11R6/bin/%s", fname);
631     if (file_executable(tmp))
632         return TRUE;
633     snprintf(tmp, sizeof tmp, "/usr/local/bin/%s", fname);
634     return file_executable(tmp);
635 }
636
637 int
638 configXDesktop(dialogMenuItem *self)
639 {
640     char *desk;
641     int ret = DITEM_SUCCESS;
642     WINDOW *w = savescr();
643     
644     dialog_clear_norefresh();
645     if (!dmenuOpenSimple(&MenuXDesktops, FALSE) || !(desk = variable_get(VAR_DESKSTYLE))) {
646         restorescr(w);
647         return DITEM_FAILURE;
648     }
649     if (!strcmp(desk, "kde")) {
650         ret = package_add("kde");
651         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("startkde"))
652             write_root_xprofile("exec startkde\n");
653     }
654     else if (!strcmp(desk, "gnome")) {
655         ret = package_add("gnomecore");
656         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("gnome-session")) {
657             ret = package_add("sawfish");
658             if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("sawfish"))
659                 write_root_xprofile("exec gnome-session\n");
660         }
661     }
662     else if (!strcmp(desk, "enlightenment")) {
663         ret = package_add("gnomecore");
664         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("gnome-session")) {
665             ret = package_add("enlightenment");
666             if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("enlightenment"))
667                 write_root_xprofile("exec gnome-session\n");
668         }
669     }
670     else if (!strcmp(desk, "afterstep")) {
671         ret = package_add("afterstep");
672         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("afterstep"))
673             write_root_xprofile("exec afterstep\n");
674     }
675     else if (!strcmp(desk, "windowmaker")) {
676         ret = package_add("windowmaker");
677         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("wmaker.inst")) {
678             write_root_xprofile("xterm &\n[ ! -d $HOME/GNUstep/Library/WindowMaker ] && /usr/X11R6/bin/wmaker.inst\nexec /usr/X11R6/bin/wmaker\n");
679         }
680     }
681     else if (!strcmp(desk, "fvwm2")) {
682         ret = package_add("fvwm");
683         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("fvwm"))
684             write_root_xprofile("exec fvwm\n");
685     }
686     if (DITEM_STATUS(ret) == DITEM_FAILURE)
687         msgConfirm("An error occurred while adding the package(s) required\n"
688                    "by this desktop type.  Please change installation media\n"
689                    "and/or select a different, perhaps simpler, desktop\n"
690                    "environment and try again.");
691     restorescr(w);
692     return ret;
693 }
694
695 int
696 configXSetup(dialogMenuItem *self)
697 {
698     char *config, *execfile, *style;
699     char *moused;
700     WINDOW *w = savescr();
701     
702     setenv("XWINHOME", "/usr/X11R6", 1);
703 tryagain:
704     variable_unset(VAR_DESKSTYLE);
705     variable_unset(VAR_XF86_CONFIG);
706     dialog_clear_norefresh();
707     if (!dmenuOpenSimple(&MenuXF86Config, FALSE)) {
708         restorescr(w);
709         return DITEM_FAILURE;
710     }
711     config = variable_get(VAR_XF86_CONFIG);
712     style = variable_get(VAR_DESKSTYLE);
713     if (!config) {
714         if (style)
715             goto config_desktop;
716         else {
717             restorescr(w);
718             return DITEM_FAILURE;
719         }
720     }
721
722     if (file_readable("/var/run/ld-elf.so.hints"))
723         vsystem("/sbin/ldconfig -m /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
724     else
725         vsystem("/sbin/ldconfig /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
726     if (file_readable("/var/run/ld.so.hints"))
727         vsystem("ldconfig -m -aout /usr/lib/aout /usr/lib/compat/aout /usr/local/lib/aout /usr/X11R6/lib/aout");
728     else
729         vsystem("ldconfig -aout /usr/lib/aout /usr/lib/compat/aout /usr/local/lib/aout /usr/X11R6/lib/aout");
730
731     vsystem("/sbin/ifconfig lo0 127.0.0.1");
732     execfile = string_concat("/usr/X11R6/bin/", config);
733     if (file_executable(execfile)) {
734         moused = variable_get(VAR_MOUSED);
735         while (!moused || strcmp(moused, "YES")) {
736             if (msgYesNo("The X server may access the mouse in two ways: direct access\n"
737                          "or indirect access via the mouse daemon.  You have not\n"
738                          "configured the mouse daemon.  Would you like to configure it\n"
739                          "now?  If you intend to let the X server access the mouse\n"
740                          "directly, choose \"No\" at this time."))
741                 break;
742             dialog_clear_norefresh();
743             dmenuOpenSimple(&MenuMouse, FALSE); 
744             moused = variable_get(VAR_MOUSED);
745         }
746         if (moused && !strcmp(moused, "YES"))
747             msgConfirm("You have configured and are now running the mouse daemon.\n"
748                        "Choose \"/dev/sysmouse\" as the mouse port and \"SysMouse\" or\n"
749                        "\"MouseSystems\" as the mouse protocol in the X configuration\n"
750                        "utility.");
751         systemExecute(execfile);
752         if (!file_readable("/etc/XF86Config")) {
753             if (!msgYesNo("The XFree86 configuration process seems to have\nfailed.  Would you like to try again?"))
754                 goto tryagain;
755             else {
756                 restorescr(w);
757                 return DITEM_FAILURE;
758             }
759         }
760 config_desktop:
761         configXDesktop(self);
762         restorescr(w);
763         return DITEM_SUCCESS;
764     }
765     else {
766         msgConfirm("The XFree86 setup utility you chose does not appear to be installed!\n"
767                    "Please install this before attempting to configure XFree86.");
768         restorescr(w);
769         return DITEM_FAILURE;
770     }
771 }
772
773 int
774 configResolv(dialogMenuItem *ditem)
775 {
776     FILE *fp;
777     char *cp, *c6p, *dp, *hp;
778
779     cp = variable_get(VAR_NAMESERVER);
780     if (!cp || !*cp)
781         goto skip;
782     Mkdir("/etc");
783     fp = fopen("/etc/resolv.conf", "w");
784     if (!fp)
785         return DITEM_FAILURE;
786     if (variable_get(VAR_DOMAINNAME))
787         fprintf(fp, "domain\t%s\n", variable_get(VAR_DOMAINNAME));
788     fprintf(fp, "nameserver\t%s\n", cp);
789     fclose(fp);
790     if (isDebug())
791         msgDebug("Wrote out /etc/resolv.conf\n");
792
793 skip:
794     dp = variable_get(VAR_DOMAINNAME);
795     cp = variable_get(VAR_IPADDR);
796     c6p = variable_get(VAR_IPV6ADDR);
797     hp = variable_get(VAR_HOSTNAME);
798     /* Tack ourselves into /etc/hosts */
799     fp = fopen("/etc/hosts", "w");
800     if (!fp)
801         return DITEM_FAILURE;
802     /* Add an entry for localhost */
803     if (!variable_cmp(VAR_IPV6_ENABLE, "YES")) {
804         if (dp)
805             fprintf(fp, "::1\t\t\tlocalhost.%s localhost\n", dp);
806         else
807             fprintf(fp, "::1\t\t\tlocalhost\n");
808     }
809     if (dp)
810         fprintf(fp, "127.0.0.1\t\tlocalhost.%s localhost\n", dp);
811     else
812         fprintf(fp, "127.0.0.1\t\tlocalhost\n");
813     /* Now the host entries, if applicable */
814     if (((cp && cp[0] != '0') || (c6p && c6p[0] != '0')) && hp) {
815         char cp2[255];
816
817         if (!index(hp, '.'))
818             cp2[0] = '\0';
819         else {
820             SAFE_STRCPY(cp2, hp);
821             *(index(cp2, '.')) = '\0';
822         }
823         if (c6p && c6p[0] != '0') {
824             fprintf(fp, "%s\t%s %s\n", c6p, hp, cp2);
825             fprintf(fp, "%s\t%s.\n", c6p, hp);
826         }
827         if (cp && cp[0] != '0') {
828             fprintf(fp, "%s\t\t%s %s\n", cp, hp, cp2);
829             fprintf(fp, "%s\t\t%s.\n", cp, hp);
830         }
831     }
832     fclose(fp);
833     if (isDebug())
834         msgDebug("Wrote out /etc/hosts\n");
835     return DITEM_SUCCESS;
836 }
837
838 int
839 configRouter(dialogMenuItem *self)
840 {
841     int ret;
842
843     ret = variable_get_value(VAR_ROUTER,
844                              "Please specify the router you wish to use.  Routed is\n"
845                              "provided with the stock system and gated is provided\n"
846                              "as an optional package which this installation system\n"
847                              "will attempt to load if you select gated.  Any other\n"
848                              "choice of routing daemon will be assumed to be something\n"
849                              "the user intends to install themselves before rebooting\n"
850                              "the system.  If you don't want any routing daemon, choose NO", 1)
851       ? DITEM_SUCCESS : DITEM_FAILURE;
852   
853     if (ret == DITEM_SUCCESS) {
854         char *cp = variable_get(VAR_ROUTER);
855     
856         if (cp && strcmp(cp, "NO")) {
857             variable_set2(VAR_ROUTER_ENABLE, "YES", 1);
858             if (!strcmp(cp, "gated")) {
859                 if (package_add("gated") != DITEM_SUCCESS) {
860                     msgConfirm("Unable to load gated package.  Falling back to no router.");
861                     variable_unset(VAR_ROUTER);
862                     variable_unset(VAR_ROUTERFLAGS);
863                     variable_set2(VAR_ROUTER_ENABLE, "NO", 1);
864                     cp = NULL;
865                 }
866             }
867             if (cp) {
868                 /* Now get the flags, if they chose a router */
869                 ret = variable_get_value(VAR_ROUTERFLAGS, 
870                                          "Please Specify the routing daemon flags; if you're running routed\n"
871                                          "then -q is the right choice for nodes and -s for gateway hosts.\n", 1)
872                   ? DITEM_SUCCESS : DITEM_FAILURE;
873                 if (ret != DITEM_SUCCESS)
874                     variable_unset(VAR_ROUTERFLAGS);
875             }
876         }
877         else {
878             /* No router case */
879             variable_set2(VAR_ROUTER_ENABLE, "NO", 1);
880             variable_unset(VAR_ROUTERFLAGS);
881             variable_unset(VAR_ROUTER);
882         }
883     }
884     else {
885         variable_set2(VAR_ROUTER_ENABLE, "NO", 1);
886         variable_unset(VAR_ROUTERFLAGS);
887         variable_unset(VAR_ROUTER);
888     }
889     return ret;
890 }
891
892 /* Shared between us and index_initialize() */
893 extern PkgNode Top, Plist;
894
895 int
896 configPackages(dialogMenuItem *self)
897 {
898     int i, restoreflag = 0;
899     PkgNodePtr tmp;
900
901     /* Did we get an INDEX? */
902     i = index_initialize("packages/INDEX");
903     if (DITEM_STATUS(i) == DITEM_FAILURE)
904         return i;
905
906     while (1) {
907         int ret, pos, scroll;
908
909         /* Bring up the packages menu */
910         pos = scroll = 0;
911         index_menu(&Top, &Top, &Plist, &pos, &scroll);
912
913         if (Plist.kids && Plist.kids->name) {
914             /* Now show the packing list menu */
915             pos = scroll = 0;
916             ret = index_menu(&Plist, &Plist, NULL, &pos, &scroll);
917             if (ret & DITEM_LEAVE_MENU)
918                 break;
919             else if (DITEM_STATUS(ret) != DITEM_FAILURE) {
920                 dialog_clear();
921                 restoreflag = 1;
922                 for (tmp = Plist.kids; tmp && tmp->name; tmp = tmp->next)
923                     (void)index_extract(mediaDevice, &Top, tmp, FALSE);
924                 break;
925             }
926         }
927         else {
928             msgConfirm("No packages were selected for extraction.");
929             break;
930         }
931     }
932     tmp = Plist.kids;
933     while (tmp) {
934         PkgNodePtr tmp2 = tmp->next;
935            
936         safe_free(tmp);
937         tmp = tmp2;
938     }
939     index_init(NULL, &Plist);
940     return DITEM_SUCCESS | (restoreflag ? DITEM_RESTORE : 0);
941 }
942
943 /* Load pcnfsd package */
944 int
945 configPCNFSD(dialogMenuItem *self)
946 {
947     int ret;
948
949     ret = package_add("pcnfsd");
950     if (DITEM_STATUS(ret) == DITEM_SUCCESS) {
951         variable_set2(VAR_PCNFSD, "YES", 0);
952         variable_set2("mountd_flags", "-n", 1);
953     }
954     return ret;
955 }
956
957 int
958 configNFSServer(dialogMenuItem *self)
959 {
960     char cmd[256];
961
962     /* If we're an NFS server, we need an exports file */
963     if (!file_readable("/etc/exports")) {
964         WINDOW *w = savescr();
965
966         if (file_readable("/etc/exports.disabled"))
967             vsystem("mv /etc/exports.disabled /etc/exports");
968         else {
969             dialog_clear_norefresh();
970             msgConfirm("Operating as an NFS server means that you must first configure\n"
971                        "an /etc/exports file to indicate which hosts are allowed certain\n"
972                        "kinds of access to your local file systems.\n"
973                        "Press [ENTER] now to invoke an editor on /etc/exports\n");
974             vsystem("echo '#The following examples export /usr to 3 machines named after ducks,' > /etc/exports");
975             vsystem("echo '#/usr/src and /usr/ports read-only to machines named after trouble makers' >> /etc/exports");
976             vsystem("echo '#/home and all directories under it to machines named after dead rock stars' >> /etc/exports");
977             vsystem("echo '#and, /a to a network of privileged machines allowed to write on it as root.' >> /etc/exports");
978             vsystem("echo '#/usr                   huey louie dewie' >> /etc/exports");
979             vsystem("echo '#/usr/src /usr/obj -ro  calvin hobbes' >> /etc/exports");
980             vsystem("echo '#/home   -alldirs       janice jimmy frank' >> /etc/exports");
981             vsystem("echo '#/a      -maproot=0  -network 10.0.1.0 -mask 255.255.248.0' >> /etc/exports");
982             vsystem("echo '#' >> /etc/exports");
983             vsystem("echo '# You should replace these lines with your actual exported filesystems.' >> /etc/exports");
984             vsystem("echo '# Note that BSD's export synatx is \"host-centric\" vs. Sun\'s \"FS-centric\" one.' >> /etc/exports");
985             vsystem("echo >> /etc/exports");
986             sprintf(cmd, "%s /etc/exports", variable_get(VAR_EDITOR));
987             dialog_clear();
988             systemExecute(cmd);
989         }
990         variable_set2(VAR_NFS_SERVER, "YES", 1);
991         restorescr(w);
992     }
993     else if (variable_get(VAR_NFS_SERVER)) { /* We want to turn it off again? */
994         vsystem("mv -f /etc/exports /etc/exports.disabled");
995         variable_unset(VAR_NFS_SERVER);
996     }
997     return DITEM_SUCCESS;
998 }