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