]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/sade/config.c
This commit was generated by cvs2svn to compensate for changes in r102550,
[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     fclose(fstab);
250     if (isDebug())
251         msgDebug("Wrote out /etc/fstab file\n");
252     return DITEM_SUCCESS;
253 }
254
255 /* Do the work of sucking in a config file.
256  * config is the filename to read in.
257  * lines is a fixed (max) sized array of char*
258  * returns number of lines read.  line contents
259  * are malloc'd and must be freed by the caller.
260  */
261 int
262 readConfig(char *config, char **lines, int max)
263 {
264     FILE *fp;
265     char line[256];
266     int i, nlines;
267
268     fp = fopen(config, "r");
269     if (!fp)
270         return -1;
271
272     nlines = 0;
273     /* Read in the entire file */
274     for (i = 0; i < max; i++) {
275         if (!fgets(line, sizeof line, fp))
276             break;
277         lines[nlines++] = strdup(line);
278     }
279     fclose(fp);
280     if (isDebug())
281         msgDebug("readConfig: Read %d lines from %s.\n", nlines, config);
282     return nlines;
283 }
284
285 #define MAX_LINES  2000 /* Some big number we're not likely to ever reach - I'm being really lazy here, I know */
286
287 static void
288 readConfigFile(char *config, int marked)
289 {
290     char *lines[MAX_LINES], *cp, *cp2;
291     int i, nlines;
292
293     nlines = readConfig(config, lines, MAX_LINES);
294     if (nlines == -1)
295         return;
296
297     for (i = 0; i < nlines; i++) {
298         /* Skip the comments & non-variable settings */
299         if (lines[i][0] == '#' || !(cp = index(lines[i], '='))) {
300             free(lines[i]);
301             continue;
302         }
303         *cp++ = '\0';
304         /* Find quotes */
305         if ((cp2 = index(cp, '"')) || (cp2 = index(cp, '\047'))) {
306             cp = cp2 + 1;
307             cp2 = index(cp, *cp2);
308         }
309         /* If valid quotes, use it */
310         if (cp2) {
311             *cp2 = '\0';
312             /* If we have a legit value, set it */
313             if (strlen(cp))
314                 variable_set2(lines[i], cp, marked);
315         }
316         free(lines[i]);
317     }
318 }
319
320 /* Load the environment from rc.conf file(s) */
321 void
322 configEnvironmentRC_conf(void)
323 {
324     static struct {
325         char *fname;
326         int marked;
327     } configs[] = {
328         { "/etc/defaults/rc.conf", 0 },
329         { "/etc/rc.conf", 0 },
330         { "/etc/rc.conf.local", 0 },
331         { NULL, 0 },
332     };
333     int i;
334
335     for (i = 0; configs[i].fname; i++) {
336         if (file_readable(configs[i].fname))
337             readConfigFile(configs[i].fname, configs[i].marked);
338     }
339 }
340
341 /* Load the environment from a resolv.conf file */
342 void
343 configEnvironmentResolv(char *config)
344 {
345     char *lines[MAX_LINES];
346     int i, nlines;
347
348     nlines = readConfig(config, lines, MAX_LINES);
349     if (nlines == -1)
350         return;
351     for (i = 0; i < nlines; i++) {
352         Boolean name_set = variable_get(VAR_NAMESERVER) ? 1 : 0;
353
354         if (!strncmp(lines[i], "domain", 6) && !variable_get(VAR_DOMAINNAME))
355             variable_set2(VAR_DOMAINNAME, string_skipwhite(string_prune(lines[i] + 6)), 0);
356         else if (!name_set && !strncmp(lines[i], "nameserver", 10)) {
357             /* Only take the first nameserver setting - we're lame */
358             variable_set2(VAR_NAMESERVER, string_skipwhite(string_prune(lines[i] + 10)), 0);
359         }
360         free(lines[i]);
361     }
362 }
363
364 /* Version of below for dispatch routines */
365 int
366 configRC(dialogMenuItem *unused)
367 {
368     configRC_conf();
369     return DITEM_SUCCESS;
370 }
371
372 void
373 configRC_conf(void)
374 {
375     FILE *rcSite;
376     Variable *v;
377     int write_header;
378     time_t t_loc;
379     char *cp;
380     static int did_marker = 0;
381     time_t tp;
382
383     configTtys();
384     write_header = !file_readable("/etc/rc.conf");
385     rcSite = fopen("/etc/rc.conf", "a");
386     if (!rcSite)
387         return;
388     if (write_header) {
389         fprintf(rcSite, "# This file now contains just the overrides from /etc/defaults/rc.conf.\n");
390         fprintf(rcSite, "# Please make all changes to this file, not to /etc/defaults/rc.conf.\n\n");
391         fprintf(rcSite, "# Enable network daemons for user convenience.\n");
392         if ((t_loc = time(NULL)) != -1 && (cp = ctime(&t_loc)))
393             fprintf(rcSite, "# Created: %s", cp);
394     }
395
396     /* Now do variable substitutions */
397     for (v = VarHead; v; v = v->next) {
398         if (v->dirty) {
399             if (!did_marker) {
400                 time(&tp);
401                 fprintf(rcSite, "# -- sysinstall generated deltas -- # "
402                     "%s", ctime(&tp));
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 configSecurity(dialogMenuItem *self)
480 {
481     WINDOW *w = savescr();
482
483     dialog_clear_norefresh();
484     dmenuOpenSimple(&MenuSecurity, FALSE);
485     restorescr(w);
486     return DITEM_SUCCESS;
487 }
488
489 int
490 configSecurityProfile(dialogMenuItem *self)
491 {
492     WINDOW *w = savescr();
493
494     dialog_clear_norefresh();
495     dmenuOpenSimple(&MenuSecurityProfile, FALSE); 
496     restorescr(w);
497     return DITEM_SUCCESS;
498 }
499
500 /* Use the most extreme security settings */
501 int
502 configSecurityExtreme(dialogMenuItem *self)
503 {
504     WINDOW *w = savescr();
505
506     variable_set2("nfs_server_enable", "NO", 1);
507     variable_set2("sendmail_enable", "NO", 1);
508     variable_set2("sshd_enable", "NO", 1);
509     variable_set2("kern_securelevel_enable", "YES", 1);
510     variable_set2("kern_securelevel", "2", 1);
511
512     if (self)
513         msgConfirm("Extreme security settings have been selected.\n\n"
514             "Sendmail, sshd, and NFS services have been disabled, and\n"
515             "securelevels have been enabled.\n\n"
516             "PLEASE NOTE that this still does not save you from having\n"
517             "to properly secure your system in other ways or exercise\n"
518             "due diligence in your administration, this simply picks\n"
519             "a more secure set of out-of-box defaults to start with.\n\n"
520             "To change any of these settings later, edit /etc/rc.conf");
521
522     restorescr(w);
523     return DITEM_SUCCESS;
524 }
525
526 int
527 configSecurityModerate(dialogMenuItem *self)
528 {
529     WINDOW *w = savescr();
530
531     variable_set2("sendmail_enable", "YES", 1);
532     variable_set2("sshd_enable", "YES", 1);
533     variable_set2("kern_securelevel_enable", "NO", 1);
534
535     if (self)
536         msgConfirm("Moderate security settings have been selected.\n\n"
537             "Sendmail and sshd have been enabled, securelevels are\n"
538             "disabled, and NFS server settings have been left intact.\n\n"
539             "PLEASE NOTE that this still does not save you from having\n"
540             "to properly secure your system in other ways or exercise\n"
541             "due diligence in your administration, this simply picks\n"
542             "a standard set of out-of-box defaults to start with.\n\n"
543             "To change any of these settings later, edit /etc/rc.conf");
544
545     restorescr(w);
546     return DITEM_SUCCESS;
547 }
548
549 static void
550 write_root_xprofile(char *str)
551 {
552     FILE *fp;
553     int len;
554     char **cp;
555     static char *flist[] = { /* take care of both xdm and startx */
556         "/root/.xinitrc",
557         "/root/.xsession",
558         "/usr/share/skel/dot.xinitrc",
559         "/usr/share/skel/dot.xsession",
560         NULL,
561     };
562
563     len = strlen(str);
564     for (cp = flist; *cp; cp++) {
565         fp = fopen(*cp, "w");
566         if (fp) {
567             fwrite(str, 1, len, fp);
568             fchmod(fileno(fp), 0755);
569             fclose(fp);
570         }
571     }
572 }
573
574 static int
575 gotit(char *fname)
576 {
577     char tmp[FILENAME_MAX];
578
579     snprintf(tmp, sizeof tmp, "/usr/X11R6/bin/%s", fname);
580     if (file_executable(tmp))
581         return TRUE;
582     snprintf(tmp, sizeof tmp, "/usr/local/bin/%s", fname);
583     return file_executable(tmp);
584 }
585
586 int
587 configXDesktop(dialogMenuItem *self)
588 {
589     char *desk;
590     int ret = DITEM_SUCCESS;
591     WINDOW *w = savescr();
592     
593     dialog_clear_norefresh();
594     if (!dmenuOpenSimple(&MenuXDesktops, FALSE) || !(desk = variable_get(VAR_DESKSTYLE))) {
595         restorescr(w);
596         return DITEM_FAILURE;
597     }
598     if (!strcmp(desk, "kde")) {
599         ret = package_add("kde");
600         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("startkde"))
601             write_root_xprofile("exec startkde\n");
602     }
603     else if (!strcmp(desk, "gnome")) {
604         ret = package_add("gnomecore");
605         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("gnome-session")) {
606             ret = package_add("sawfish-gnome");
607             if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("sawfish"))
608                 write_root_xprofile("exec gnome-session\n");
609         }
610     }
611     else if (!strcmp(desk, "enlightenment")) {
612         ret = package_add("gnomecore");
613         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("gnome-session")) {
614             ret = package_add("enlightenment");
615             if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("enlightenment"))
616                 write_root_xprofile("exec gnome-session\n");
617         }
618     }
619     else if (!strcmp(desk, "afterstep")) {
620         ret = package_add("afterstep");
621         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("afterstep"))
622             write_root_xprofile("exec afterstep\n");
623     }
624     else if (!strcmp(desk, "windowmaker")) {
625         ret = package_add("windowmaker");
626         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("wmaker.inst")) {
627             write_root_xprofile("xterm &\n[ ! -d $HOME/GNUstep/Library/WindowMaker ] && /usr/X11R6/bin/wmaker.inst\nexec /usr/X11R6/bin/wmaker\n");
628         }
629     }
630     else if (!strcmp(desk, "fvwm2")) {
631         ret = package_add("fvwm");
632         if (DITEM_STATUS(ret) != DITEM_FAILURE && gotit("fvwm"))
633             write_root_xprofile("exec fvwm\n");
634     }
635     if (DITEM_STATUS(ret) == DITEM_FAILURE)
636         msgConfirm("An error occurred while adding the package(s) required\n"
637                    "by this desktop type.  Please change installation media\n"
638                    "and/or select a different, perhaps simpler, desktop\n"
639                    "environment and try again.");
640     restorescr(w);
641     return ret;
642 }
643
644 int
645 configXSetup(dialogMenuItem *self)
646 {
647     char *config, *execfile, *execcmd, *style, *tmp;
648     char *moused;
649     WINDOW *w = savescr();
650     
651     setenv("XWINHOME", "/usr/X11R6", 1);
652 tryagain:
653     variable_unset(VAR_DESKSTYLE);
654     variable_unset(VAR_XF86_CONFIG);
655     dialog_clear_norefresh();
656     if (!dmenuOpenSimple(&MenuXF86Config, FALSE)) {
657         restorescr(w);
658         return DITEM_FAILURE;
659     }
660     config = variable_get(VAR_XF86_CONFIG);
661     style = variable_get(VAR_DESKSTYLE);
662     if (!config) {
663         if (style)
664             goto config_desktop;
665         else {
666             restorescr(w);
667             return DITEM_FAILURE;
668         }
669     }
670
671     if (file_readable("/var/run/ld-elf.so.hints"))
672         vsystem("/sbin/ldconfig -m /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
673     else
674         vsystem("/sbin/ldconfig /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
675     if (file_readable("/var/run/ld.so.hints"))
676         vsystem("ldconfig -m -aout /usr/lib/aout /usr/lib/compat/aout /usr/local/lib/aout /usr/X11R6/lib/aout");
677     else
678         vsystem("ldconfig -aout /usr/lib/aout /usr/lib/compat/aout /usr/local/lib/aout /usr/X11R6/lib/aout");
679
680     vsystem("/sbin/ifconfig lo0 127.0.0.1");
681
682     /* 
683      * execcmd may have been passed in as a command name with
684      * arguments.  Therefore, before determining if it is suitable for
685      * execution, we must split off the filename component from the
686      * command line arguments.
687      */
688
689     execcmd = string_concat("/usr/X11R6/bin/", config);
690     execfile = strdup(execcmd);
691     if ((tmp = strchr(execfile, ' ')))
692             *tmp = '\0';
693     if (file_executable(execfile)) {
694         free(execfile);
695         moused = variable_get(VAR_MOUSED);
696         while (!moused || strcmp(moused, "YES")) {
697             if (msgYesNo("The X server may access the mouse in two ways: direct access\n"
698                          "or indirect access via the mouse daemon.  You have not\n"
699                          "configured the mouse daemon.  Would you like to configure it\n"
700                          "now?  If you intend to let the X server access the mouse\n"
701                          "directly, choose \"No\" at this time."))
702                 break;
703             dialog_clear_norefresh();
704             dmenuOpenSimple(&MenuMouse, FALSE); 
705             moused = variable_get(VAR_MOUSED);
706         }
707         if (moused && !strcmp(moused, "YES"))
708             msgConfirm("You have configured and are now running the mouse daemon.\n"
709                        "Choose \"/dev/sysmouse\" as the mouse port and \"SysMouse\" or\n"
710                        "\"MouseSystems\" as the mouse protocol in the X configuration\n"
711                        "utility.");
712         Mkdir("/etc/X11");      /* XXX:Remove this later after we are happy mtree will have created this for us. */
713         systemExecute(execcmd);
714         if (!file_readable("/etc/X11/XF86Config")) {
715             if (!msgYesNo("The XFree86 configuration process seems to have\nfailed.  Would you like to try again?"))
716                 goto tryagain;
717             else {
718                 restorescr(w);
719                 return DITEM_FAILURE;
720             }
721         }
722 config_desktop:
723         configXDesktop(self);
724         restorescr(w);
725         return DITEM_SUCCESS;
726     }
727     else {
728         free(execfile);
729         msgConfirm("The XFree86 setup utility you chose does not appear to be installed!\n"
730                    "Please install this before attempting to configure XFree86.");
731         restorescr(w);
732         return DITEM_FAILURE;
733     }
734 }
735
736 int
737 configResolv(dialogMenuItem *ditem)
738 {
739     FILE *fp;
740     char *cp, *c6p, *dp, *hp;
741
742     cp = variable_get(VAR_NAMESERVER);
743     if (!cp || !*cp)
744         goto skip;
745     Mkdir("/etc");
746     fp = fopen("/etc/resolv.conf", "w");
747     if (!fp)
748         return DITEM_FAILURE;
749     if (variable_get(VAR_DOMAINNAME))
750         fprintf(fp, "domain\t%s\n", variable_get(VAR_DOMAINNAME));
751     fprintf(fp, "nameserver\t%s\n", cp);
752     fclose(fp);
753     if (isDebug())
754         msgDebug("Wrote out /etc/resolv.conf\n");
755
756 skip:
757     dp = variable_get(VAR_DOMAINNAME);
758     cp = variable_get(VAR_IPADDR);
759     c6p = variable_get(VAR_IPV6ADDR);
760     hp = variable_get(VAR_HOSTNAME);
761     /* Tack ourselves into /etc/hosts */
762     fp = fopen("/etc/hosts", "w");
763     if (!fp)
764         return DITEM_FAILURE;
765     /* Add an entry for localhost */
766     if (!variable_cmp(VAR_IPV6_ENABLE, "YES")) {
767         if (dp)
768             fprintf(fp, "::1\t\t\tlocalhost.%s localhost\n", dp);
769         else
770             fprintf(fp, "::1\t\t\tlocalhost\n");
771     }
772     if (dp)
773         fprintf(fp, "127.0.0.1\t\tlocalhost.%s localhost\n", dp);
774     else
775         fprintf(fp, "127.0.0.1\t\tlocalhost\n");
776     /* Now the host entries, if applicable */
777     if (((cp && cp[0] != '0') || (c6p && c6p[0] != '0')) && hp) {
778         char cp2[255];
779
780         if (!index(hp, '.'))
781             cp2[0] = '\0';
782         else {
783             SAFE_STRCPY(cp2, hp);
784             *(index(cp2, '.')) = '\0';
785         }
786         if (c6p && c6p[0] != '0') {
787             fprintf(fp, "%s\t%s %s\n", c6p, hp, cp2);
788             fprintf(fp, "%s\t%s.\n", c6p, hp);
789         }
790         if (cp && cp[0] != '0') {
791             fprintf(fp, "%s\t\t%s %s\n", cp, hp, cp2);
792             fprintf(fp, "%s\t\t%s.\n", cp, hp);
793         }
794     }
795     fclose(fp);
796     if (isDebug())
797         msgDebug("Wrote out /etc/hosts\n");
798     return DITEM_SUCCESS;
799 }
800
801 int
802 configRouter(dialogMenuItem *self)
803 {
804     int ret;
805
806     ret = variable_get_value(VAR_ROUTER,
807                              "Please specify the router you wish to use.  Routed is\n"
808                              "provided with the stock system and gated is provided\n"
809                              "as an optional package which this installation system\n"
810                              "will attempt to load if you select gated.  Any other\n"
811                              "choice of routing daemon will be assumed to be something\n"
812                              "the user intends to install themselves before rebooting\n"
813                              "the system.  If you don't want any routing daemon, choose NO", 1)
814       ? DITEM_SUCCESS : DITEM_FAILURE;
815   
816     if (ret == DITEM_SUCCESS) {
817         char *cp = variable_get(VAR_ROUTER);
818     
819         if (cp && strcmp(cp, "NO")) {
820             variable_set2(VAR_ROUTER_ENABLE, "YES", 1);
821             if (!strcmp(cp, "gated")) {
822                 if (package_add("gated") != DITEM_SUCCESS) {
823                     msgConfirm("Unable to load gated package.  Falling back to no router.");
824                     variable_unset(VAR_ROUTER);
825                     variable_unset(VAR_ROUTERFLAGS);
826                     variable_set2(VAR_ROUTER_ENABLE, "NO", 1);
827                     cp = NULL;
828                 }
829             }
830             if (cp) {
831                 /* Now get the flags, if they chose a router */
832                 ret = variable_get_value(VAR_ROUTERFLAGS, 
833                                          "Please Specify the routing daemon flags; if you're running routed\n"
834                                          "then -q is the right choice for nodes and -s for gateway hosts.\n", 1)
835                   ? DITEM_SUCCESS : DITEM_FAILURE;
836                 if (ret != DITEM_SUCCESS)
837                     variable_unset(VAR_ROUTERFLAGS);
838             }
839         }
840         else {
841             /* No router case */
842             variable_set2(VAR_ROUTER_ENABLE, "NO", 1);
843             variable_unset(VAR_ROUTERFLAGS);
844             variable_unset(VAR_ROUTER);
845         }
846     }
847     else {
848         variable_set2(VAR_ROUTER_ENABLE, "NO", 1);
849         variable_unset(VAR_ROUTERFLAGS);
850         variable_unset(VAR_ROUTER);
851     }
852     return ret;
853 }
854
855 /* Shared between us and index_initialize() */
856 extern PkgNode Top, Plist;
857
858 int
859 configPackages(dialogMenuItem *self)
860 {
861     int i, restoreflag = 0;
862     PkgNodePtr tmp;
863
864     /* Did we get an INDEX? */
865     i = index_initialize("packages/INDEX");
866     if (DITEM_STATUS(i) == DITEM_FAILURE)
867         return i;
868
869     while (1) {
870         int ret, pos, scroll;
871
872         /* Bring up the packages menu */
873         pos = scroll = 0;
874         index_menu(&Top, &Top, &Plist, &pos, &scroll);
875
876         if (Plist.kids && Plist.kids->name) {
877             /* Now show the packing list menu */
878             pos = scroll = 0;
879             ret = index_menu(&Plist, &Plist, NULL, &pos, &scroll);
880             if (ret & DITEM_LEAVE_MENU)
881                 break;
882             else if (DITEM_STATUS(ret) != DITEM_FAILURE) {
883                 dialog_clear();
884                 restoreflag = 1;
885                 for (tmp = Plist.kids; tmp && tmp->name; tmp = tmp->next)
886                     (void)index_extract(mediaDevice, &Top, tmp, FALSE);
887                 break;
888             }
889         }
890         else {
891             msgConfirm("No packages were selected for extraction.");
892             break;
893         }
894     }
895     tmp = Plist.kids;
896     while (tmp) {
897         PkgNodePtr tmp2 = tmp->next;
898            
899         safe_free(tmp);
900         tmp = tmp2;
901     }
902     index_init(NULL, &Plist);
903     return DITEM_SUCCESS | (restoreflag ? DITEM_RESTORE : 0);
904 }
905
906 /* Load pcnfsd package */
907 int
908 configPCNFSD(dialogMenuItem *self)
909 {
910     int ret;
911
912     ret = package_add("pcnfsd");
913     if (DITEM_STATUS(ret) == DITEM_SUCCESS) {
914         variable_set2(VAR_PCNFSD, "YES", 0);
915         variable_set2("mountd_flags", "-n", 1);
916     }
917     return ret;
918 }
919
920 int
921 configInetd(dialogMenuItem *self)
922 {
923     char cmd[256];
924
925     WINDOW *w = savescr();
926
927     if (msgYesNo("The Internet Super Server (inetd) allows a number of simple Internet\n"
928                  "services to be enabled, including finger, ftp, and telnetd.  Enabling\n"
929                  "these services may increase risk of security problems by increasing\n"
930                  "the exposure of your system.\n\n"
931                  "With this in mind, do you wish to enable inetd?\n")) {
932         variable_set2("inetd_enable", "NO", 1);
933     } else {
934         /* If inetd is enabled, we'll need an inetd.conf */
935
936         if (!msgYesNo("inetd(8) relies on its configuration file, /etc/inetd.conf, to determine\n"
937                    "which of its Internet services will be available.  The default FreeBSD\n"
938                    "inetd.conf(5) leaves all services disabled by default, so they must be\n"
939                    "specifically enabled in the configuration file before they will\n"
940                    "function, even once inetd(8) is enabled.  Note that services for\n"
941                    "IPv6 must be separately enabled from IPv4 services.\n\n"
942                    "Select [Yes] now to invoke an editor on /etc/inetd.conf, or [No] to\n"
943                    "use the current settings.\n")) {
944             sprintf(cmd, "%s /etc/inetd.conf", variable_get(VAR_EDITOR));
945             dialog_clear();
946             systemExecute(cmd);
947             variable_set2("inetd_enable", "YES", 1);
948         }
949     }
950     restorescr(w);
951     return DITEM_SUCCESS;
952 }
953
954 int
955 configNFSServer(dialogMenuItem *self)
956 {
957     char cmd[256];
958
959     /* If we're an NFS server, we need an exports file */
960     if (!file_readable("/etc/exports")) {
961         WINDOW *w = savescr();
962
963         if (file_readable("/etc/exports.disabled"))
964             vsystem("mv /etc/exports.disabled /etc/exports");
965         else {
966             dialog_clear_norefresh();
967             msgConfirm("Operating as an NFS server means that you must first configure\n"
968                        "an /etc/exports file to indicate which hosts are allowed certain\n"
969                        "kinds of access to your local file systems.\n"
970                        "Press [ENTER] now to invoke an editor on /etc/exports\n");
971             vsystem("echo '#The following examples export /usr to 3 machines named after ducks,' > /etc/exports");
972             vsystem("echo '#/usr/src and /usr/ports read-only to machines named after trouble makers' >> /etc/exports");
973             vsystem("echo '#/home and all directories under it to machines named after dead rock stars' >> /etc/exports");
974             vsystem("echo '#and, /a to a network of privileged machines allowed to write on it as root.' >> /etc/exports");
975             vsystem("echo '#/usr                   huey louie dewie' >> /etc/exports");
976             vsystem("echo '#/usr/src /usr/obj -ro  calvin hobbes' >> /etc/exports");
977             vsystem("echo '#/home   -alldirs       janice jimmy frank' >> /etc/exports");
978             vsystem("echo '#/a      -maproot=0  -network 10.0.1.0 -mask 255.255.248.0' >> /etc/exports");
979             vsystem("echo '#' >> /etc/exports");
980             vsystem("echo '# You should replace these lines with your actual exported filesystems.' >> /etc/exports");
981             vsystem("echo '# Note that BSD's export synatx is \"host-centric\" vs. Sun\'s \"FS-centric\" one.' >> /etc/exports");
982             vsystem("echo >> /etc/exports");
983             sprintf(cmd, "%s /etc/exports", variable_get(VAR_EDITOR));
984             dialog_clear();
985             systemExecute(cmd);
986         }
987         variable_set2(VAR_NFS_SERVER, "YES", 1);
988         restorescr(w);
989     }
990     else if (variable_get(VAR_NFS_SERVER)) { /* We want to turn it off again? */
991         vsystem("mv -f /etc/exports /etc/exports.disabled");
992         variable_unset(VAR_NFS_SERVER);
993     }
994     return DITEM_SUCCESS;
995 }
996
997 int
998 configEtcTtys(dialogMenuItem *self)
999 {
1000     char cmd[256];
1001
1002     WINDOW *w = savescr();
1003
1004     /* Simply prompt for confirmation, then edit away. */
1005     if (msgYesNo("Configuration of system TTYs requires editing the /etc/ttys file.\n"
1006                  "Typical configuration activities might include enabling getty(8)\n"
1007                  "on the first serial port to allow login via serial console after\n"
1008                  "reboot, or to enable xdm.  The default ttys file enables normal\n"
1009                  "virtual consoles, and most sites will not need to perform manual\n"
1010                  "configuration.\n\n"
1011                  "To load /etc/ttys in the editor, select [Yes], otherwise, [No].")) {
1012     } else {
1013         configTtys();
1014         sprintf(cmd, "%s /etc/ttys", variable_get(VAR_EDITOR));
1015         dialog_clear();
1016         systemExecute(cmd);
1017     }
1018
1019     restorescr(w);
1020     return DITEM_SUCCESS;
1021 }