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