2 * The new sysinstall program.
4 * This is probably the last program in the `sysinstall' line - the next
5 * generation being essentially a complete rewrite.
7 * $Id: config.c,v 1.103 1997/08/18 21:47:31 jkh Exp $
10 * Jordan Hubbard. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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
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.
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
37 #include "sysinstall.h"
38 #include <sys/disklabel.h>
40 #include <sys/errno.h>
41 #include <sys/ioctl.h>
42 #include <sys/fcntl.h>
43 #include <sys/param.h>
46 #include <sys/mount.h>
48 static Chunk *chunk_list[MAX_CHUNKS];
50 static int rootdev_is_od;
54 chunk_compare(Chunk *c1, Chunk *c2)
62 else if (!c1->private_data && !c2->private_data)
64 else if (c1->private_data && !c2->private_data)
66 else if (!c1->private_data && c2->private_data)
69 return strcmp(((PartInfo *)(c1->private_data))->mountpoint, ((PartInfo *)(c2->private_data))->mountpoint);
77 for (i = 0; i < nchunks; i++) {
78 for (j = 0; j < nchunks; j++) {
79 if (chunk_compare(chunk_list[j], chunk_list[j + 1]) > 0) {
80 Chunk *tmp = chunk_list[j];
82 chunk_list[j] = chunk_list[j + 1];
83 chunk_list[j + 1] = tmp;
90 check_rootdev(Chunk **list, int n)
96 for (i = 0; i < n; i++) {
98 if (c->type == part && (c->flags & CHUNK_IS_ROOT)
99 && strncmp(c->disk->name, "od", 2) == 0)
107 static char rootname[32];
109 /* Our boot blocks can't deal with root partitions on slices - need the compatbility name */
110 if (c1->type == part && c1->flags & CHUNK_IS_ROOT) {
111 sprintf(rootname, "%sa", c1->disk->name);
119 mount_point(Chunk *c1)
121 if (c1->type == part && c1->subtype == FS_SWAP)
123 else if (c1->type == part || c1->type == fat)
124 return ((PartInfo *)c1->private_data)->mountpoint;
133 else if (c1->type == part) {
134 if (c1->subtype != FS_SWAP)
143 fstype_short(Chunk *c1)
145 if (c1->type == part) {
146 if (c1->subtype != FS_SWAP) {
147 if (rootdev_is_od == 0 && strncmp(c1->name, "od", 2) == 0)
155 else if (c1->type == fat) {
156 if (strncmp(c1->name, "od", 2) == 0)
167 if (c1->type == part && c1->subtype != FS_SWAP) {
168 if (rootdev_is_od == 0 && strncmp(c1->name, "od", 2) == 0)
170 else if (c1->flags & CHUNK_IS_ROOT)
187 if (!RunningAsInit) {
188 if (file_readable("/etc/fstab"))
189 return DITEM_SUCCESS;
191 msgConfirm("Attempting to rebuild your /etc/fstab file. Warning: If you had\n"
192 "any CD devices in use before running sysinstall then they may NOT\n"
193 "be found by this run!");
197 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
199 msgConfirm("No disks found!");
200 return DITEM_FAILURE;
203 /* Record all the chunks */
205 for (i = 0; devs[i]; i++) {
206 if (!devs[i]->enabled)
208 disk = (Disk *)devs[i]->private;
210 msgFatal("No chunk list found for %s!", disk->name);
211 for (c1 = disk->chunks->part; c1; c1 = c1->next) {
212 if (c1->type == freebsd) {
213 for (c2 = c1->part; c2; c2 = c2->next) {
214 if (c2->type == part && (c2->subtype == FS_SWAP || c2->private_data))
215 chunk_list[nchunks++] = c2;
218 else if (c1->type == fat && c1->private_data)
219 chunk_list[nchunks++] = c1;
222 chunk_list[nchunks] = 0;
225 fstab = fopen("/etc/fstab", "w");
227 msgConfirm("Unable to create a new /etc/fstab file! Manual intervention\n"
228 "will be required.");
229 return DITEM_FAILURE;
232 check_rootdev(chunk_list, nchunks);
234 /* Go for the burn */
235 msgDebug("Generating /etc/fstab file\n");
236 fprintf(fstab, "# Device\t\tMountpoint\tFStype\tOptions\t\tDump\tPass#\n");
237 for (i = 0; i < nchunks; i++)
238 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]),
239 fstype(chunk_list[i]), fstype_short(chunk_list[i]), seq_num(chunk_list[i]), seq_num(chunk_list[i]));
241 fprintf(fstab, "proc\t\t\t/proc\t\tprocfs\trw\t\t0\t0\n");
243 /* Now look for the CDROMs */
244 devs = deviceFind(NULL, DEVICE_TYPE_CDROM);
245 cnt = deviceCount(devs);
247 /* Write the first one out as /cdrom */
249 if (Mkdir("/cdrom")) {
250 msgConfirm("Unable to make mount point for: /cdrom");
253 fprintf(fstab, "/dev/%s\t\t/cdrom\t\tcd9660\tro,noauto\t0\t0\n", devs[0]->name);
256 /* Write the others out as /cdrom<n> */
257 for (i = 1; i < cnt; i++) {
260 sprintf(cdname, "/cdrom%d", i);
262 msgConfirm("Unable to make mount point for: %s", cdname);
265 fprintf(fstab, "/dev/%s\t\t%s\tcd9660\tro,noauto\t0\t0\n", devs[i]->name, cdname);
269 msgDebug("Wrote out /etc/fstab file\n");
270 return DITEM_SUCCESS;
273 /* Do the work of sucking in a config file.
274 * config is the filename to read in.
275 * lines is a fixed (max) sized array of char *.
276 * returns number of lines read. line contents
277 * are malloc'd and must be freed by the caller.
280 readConfig(char *config, char **lines, int max)
286 fp = fopen(config, "r");
291 /* Read in the entire file */
292 for (i = 0; i < max; i++) {
293 if (!fgets(line, sizeof line, fp))
295 lines[nlines++] = strdup(line);
299 msgDebug("readConfig: Read %d lines from %s.\n", nlines, config);
303 #define MAX_LINES 2000 /* Some big number we're not likely to ever reach - I'm being really lazy here, I know */
305 /* Load the environment from an rc.conf file */
307 configEnvironmentRC_conf(char *config)
309 char *lines[MAX_LINES], *cp, *cp2;
312 nlines = readConfig(config, lines, MAX_LINES);
316 for (i = 0; i < nlines; i++) {
317 /* Skip the comments & non-variable settings */
318 if (lines[i][0] == '#' || !(cp = index(lines[i], '='))) {
324 if ((cp2 = index(cp, '"')) || (cp2 = index(cp, '\047'))) {
326 cp2 = index(cp, *cp2);
328 /* If valid quotes, use it */
332 variable_set2(lines[i], cp);
338 /* Load the environment from a resolv.conf file */
340 configEnvironmentResolv(char *config)
342 char *lines[MAX_LINES];
345 nlines = readConfig(config, lines, MAX_LINES);
348 for (i = 0; i < nlines; i++) {
349 Boolean name_set = FALSE;
351 if (!strncmp(lines[i], "domain", 6))
352 variable_set2(VAR_DOMAINNAME, string_skipwhite(string_prune(lines[i] + 6)));
353 else if (!strncmp(lines[i], "nameserver", 10) && !name_set) {
354 /* Only take the first nameserver setting - we're lame */
355 variable_set2(VAR_NAMESERVER, string_skipwhite(string_prune(lines[i] + 10)));
362 /* Version of below for dispatch routines */
364 configRC(dialogMenuItem *unused)
366 configRC_conf("/etc/rc.conf");
367 return DITEM_SUCCESS;
371 * This sucks in /etc/rc.conf, substitutes anything needing substitution, then
372 * writes it all back out. It's pretty gross and needs re-writing at some point.
375 configRC_conf(char *config)
378 char *lines[MAX_LINES], *cp;
382 nlines = readConfig(config, lines, MAX_LINES);
386 /* Now do variable substitutions */
387 for (v = VarHead; v; v = v->next) {
388 for (i = 0; i < nlines; i++) {
389 /* Skip the comments & non-variable settings */
390 if (lines[i][0] == '#' || !(cp = index(lines[i], '=')))
392 len = strlen(v->name);
393 if (!strncmp(lines[i], v->name, cp - lines[i]) && (cp - lines[i]) == len) {
394 char *cp2, *comment = NULL;
396 /* If trailing comment, try and preserve it */
397 if ((index(lines[i], '#')) != NULL) {
399 if ((cp2 = index(cp, '"')) || (cp2 = index(cp, '\047')))
400 cp2 = index(cp2 + 1, *cp2);
401 if (cp2 && strlen(cp2 + 1)) {
402 comment = alloca(strlen(cp2));
403 strcpy(comment, cp2 + 1);
407 lines[i] = (char *)malloc(strlen(v->name) + strlen(v->value) + (comment ? strlen(comment) : 0) + 10);
409 sprintf(lines[i], "%s=\"%s\"%s", v->name, v->value, comment);
411 sprintf(lines[i], "%s=\"%s\"\n", v->name, v->value);
416 /* Now write it all back out again */
418 msgDebug("Writing configuration changes to %s file..", config);
420 fp = fdopen(DebugFD, "w");
422 (void)vsystem("cp %s %s.previous", config, config);
423 fp = fopen(config, "w");
425 for (i = 0; i < nlines; i++) {
426 fprintf(fp, lines[i]);
427 /* Stand by for bogus special case handling - we try to dump the interface specs here */
428 if (!strncmp(lines[i], VAR_INTERFACES, strlen(VAR_INTERFACES))) {
432 devp = deviceFind(NULL, DEVICE_TYPE_NETWORK);
433 cnt = deviceCount(devp);
434 for (j = 0; j < cnt; j++) {
435 char iname[255], toadd[512];
438 if (!strncmp(devp[j]->name, "ppp", 3) || !strncmp(devp[j]->name, "tun", 3))
441 snprintf(iname, 255, "%s%s", VAR_IFCONFIG, devp[j]->name);
442 if ((cp = variable_get(iname))) {
443 snprintf(toadd, sizeof toadd, "%s=\"%s\"\n", iname, cp);
444 for (k = 0; k < nlines; k++) {
445 if (!strcmp(lines[k], toadd)) {
461 configSaver(dialogMenuItem *self)
463 variable_set((char *)self->data);
464 if (!variable_get(VAR_BLANKTIME))
465 variable_set2(VAR_BLANKTIME, "300");
466 return DITEM_SUCCESS;
470 configSaverTimeout(dialogMenuItem *self)
472 return (variable_get_value(VAR_BLANKTIME,
473 "Enter time-out period in seconds for screen saver") ?
474 DITEM_SUCCESS : DITEM_FAILURE) | DITEM_RESTORE;
478 configRegister(dialogMenuItem *self)
480 return DITEM_STATUS(registerOpenDialog()) | DITEM_RESTORE;
484 configNTP(dialogMenuItem *self)
488 status = variable_get_value(VAR_NTPDATE_FLAGS,
489 "Enter the name of an NTP server")
490 ? DITEM_SUCCESS : DITEM_FAILURE;
491 if (status == DITEM_SUCCESS) {
492 static char tmp[255];
494 snprintf(tmp, sizeof(tmp), "ntpdate_enable=YES,ntpdate_flags=%s",
495 variable_get(VAR_NTPDATE_FLAGS));
497 dmenuSetVariables(self);
499 return status | DITEM_RESTORE;
503 configUsers(dialogMenuItem *self)
505 dialog_clear_norefresh();
506 dmenuOpenSimple(&MenuUsermgmt, FALSE);
508 return DITEM_SUCCESS | DITEM_RESTORE;
512 configXEnvironment(dialogMenuItem *self)
514 #ifndef USE_XIG_ENVIRONMENT
515 char *config, *execfile;
517 dialog_clear_norefresh();
518 if (!dmenuOpenSimple(&MenuXF86Config, FALSE))
519 return DITEM_FAILURE | DITEM_RESTORE;
520 systemExecute("/sbin/ldconfig /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
521 config = variable_get(VAR_XF86_CONFIG);
523 return DITEM_FAILURE | DITEM_RESTORE;
524 execfile = string_concat("/usr/X11R6/bin/", config);
525 if (file_executable(execfile)) {
526 dialog_clear_norefresh();
527 if (!file_readable("/dev/mouse") && !msgYesNo("Does this system have a mouse attached to it?"))
528 dmenuOpenSimple(&MenuMouse, FALSE);
530 systemExecute(execfile);
531 return DITEM_SUCCESS | DITEM_RESTORE;
534 dialog_clear_norefresh();
535 msgConfirm("XFree86 does not appear to be installed! Please install\n"
536 "The XFree86 distribution before attempting to configure it.");
537 return DITEM_FAILURE | DITEM_RESTORE;
540 #else /* USE_XIG_ENVIRONMENT */
543 /* Make sure we're sane first */
544 if (!file_readable("/usr/X11R6/lib/X11/AcceleratedX/bin/Xinstall") ||
545 !file_readable("/usr/X11R6/lib/X11/AcceleratedX/bin/Xsetup")) {
546 dialog_clear_norefresh();
547 msgConfirm("Hmmm! It looks like you elected not to install the AccelleratedX\n"
548 "server package (or the installation failed somehow). If this was\n"
549 "an omission rather than an error, please go to the Distributions\n"
550 "menu, select the Custom distribution options and then choose your X11\n"
551 "distribution components from the XFree86 menu. AccelX will be selected\n"
552 "as the default server automatically.");
553 return DITEM_FAILURE | DITEM_RESTORE;
556 if (mediaDevice && mediaDevice->type != DEVICE_TYPE_CDROM) {
557 if (DITEM_STATUS(mediaSetCDROM(NULL)) != DITEM_SUCCESS || !mediaDevice || !mediaDevice->init(mediaDevice)) {
558 msgConfirm("I can't mount the CDE distribution from CDROM, sorry.\n"
559 "Please make sure you have the 1st CD of your FreeBSD Desktop/Pro\n"
560 "distribution in the drive before trying this operation.");
561 return DITEM_FAILURE | DITEM_RESTORE;
565 if (!directory_exists("/dist/CDE/")) {
566 msgConfirm("Hmmm! I can't find the CDE distribution. Please place the 1st CD of your\n"
567 "FreeBSD Desktop/Pro distribution in the drive and try this operation again.");
568 return DITEM_FAILURE | DITEM_RESTORE;
571 /* Pre-extract base sets in kludge to work around chicken-and-egg problem with CDE and Xaccel */
572 if (directory_exists("/dist/CDE/") && !file_readable("/usr/X11R6/bin/xterm")) {
573 msgNotify("Installing bootstrap X11 tools from CDE distribution.");
574 systemExecute("tar xpf /dist/CDE/FreeBSD/packages/X11-RUN/archive -C /");
575 systemExecute("tar xpf /dist/CDE/FreeBSD/packages/X11-PRG/archive -C /");
577 systemExecute("/sbin/ldconfig /usr/lib /usr/X11R6/lib /usr/dt/lib /usr/local/lib /usr/lib/compat");
579 dialog_clear_norefresh();
580 msgNotify("Running AcceleratedX 3.1 installation procedure, please wait.");
581 if ((i = vsystem("/usr/X11R6/lib/X11/AcceleratedX/bin/Xinstall"))) {
582 dialog_clear_norefresh();
583 msgConfirm("Installation procedure failed, error code %d! Please report\n"
584 "error to Walnut Creek CDROM tech support (either send email\n"
585 "to support@cdrom.com or call +1 510 603 1234). Thank you!", i);
586 return DITEM_FAILURE | DITEM_RESTORE;
590 systemExecute("/usr/X11R6/lib/X11/AcceleratedX/bin/Xsetup");
592 if (directory_exists("/dist/CDE")) {
593 dialog_clear_norefresh();
594 msgNotify("Running CDE installation - please wait (this may take awhile!).");
598 i = systemExecute("(cd /dist/CDE; sh Install)");
601 msgConfirm("/dist/CDE/dtinstall script returned an error status!\n\n"
602 "To try again, you should run this command manually after the system\n"
603 "is up (and if your CDROM is mounted in the standard location, the path\n"
604 "to it will actually be /cdrom/CDE/dtinstall when you run it later).\n");
607 if (file_readable("/dist/CDE/post-install"))
608 systemExecute("/dist/CDE/post-install");
609 /* Repair the damage done by the CDE installation */
610 msgNotify("Doing final adjustments to Xaccel distribution...");
611 systemExecute("/usr/X11R6/lib/X11/AcceleratedX/bin/Xinstall");
614 return DITEM_SUCCESS | DITEM_RESTORE;
615 #endif /* USE_XIG_ENVIRONMENT */
624 cp = variable_get(VAR_NAMESERVER);
628 fp = fopen("/etc/resolv.conf", "w");
631 if (variable_get(VAR_DOMAINNAME))
632 fprintf(fp, "domain\t%s\n", variable_get(VAR_DOMAINNAME));
633 fprintf(fp, "nameserver\t%s\n", cp);
636 msgDebug("Wrote out /etc/resolv.conf\n");
639 dp = variable_get(VAR_DOMAINNAME);
640 cp = variable_get(VAR_IPADDR);
641 hp = variable_get(VAR_HOSTNAME);
642 /* Tack ourselves into /etc/hosts */
643 fp = fopen("/etc/hosts", "w");
646 /* Add an entry for localhost */
647 fprintf(fp, "127.0.0.1\t\tlocalhost.%s localhost\n", dp ? dp : "my.domain");
648 /* Now the host entries, if applicable */
649 if (cp && cp[0] != '0' && hp) {
655 SAFE_STRCPY(cp2, hp);
656 *(index(cp2, '.')) = '\0';
658 fprintf(fp, "%s\t\t%s %s\n", cp, hp, cp2);
659 fprintf(fp, "%s\t\t%s.\n", cp, hp);
663 msgDebug("Wrote out /etc/hosts\n");
667 configRouter(dialogMenuItem *self)
671 ret = variable_get_value(VAR_ROUTER,
672 "Please specify the router you wish to use. Routed is\n"
673 "provided with the stock system and gated is provided\n"
674 "as an optional package which this installation system\n"
675 "will attempt to load if you select gated. Any other\n"
676 "choice of routing daemon will be assumed to be something\n"
677 "the user intends to install themselves before rebooting\n"
678 "the system. If you don't want any routing daemon, choose NO")
679 ? DITEM_SUCCESS : DITEM_FAILURE;
681 if (ret == DITEM_SUCCESS) {
682 char *cp = variable_get(VAR_ROUTER);
684 if (cp && strcmp(cp, "NO")) {
685 variable_set2(VAR_ROUTER_ENABLE, "YES");
686 if (!strcmp(cp, "gated")) {
687 if (package_add(variable_get(VAR_GATED_PKG)) != DITEM_SUCCESS) {
688 msgConfirm("Unable to load gated package. Falling back to no router.");
689 variable_unset(VAR_ROUTER);
690 variable_unset(VAR_ROUTERFLAGS);
691 variable_set2(VAR_ROUTER_ENABLE, "NO");
696 /* Now get the flags, if they chose a router */
697 ret = variable_get_value(VAR_ROUTERFLAGS,
698 "Please Specify the routing daemon flags; if you're running routed\n"
699 "then -q is the right choice for nodes and -s for gateway hosts.\n")
700 ? DITEM_SUCCESS : DITEM_FAILURE;
701 if (ret != DITEM_SUCCESS)
702 variable_unset(VAR_ROUTERFLAGS);
707 variable_set2(VAR_ROUTER_ENABLE, "NO");
708 variable_unset(VAR_ROUTERFLAGS);
709 variable_unset(VAR_ROUTER);
712 return ret | DITEM_RESTORE;
716 configPackages(dialogMenuItem *self)
718 static PkgNode top, plist;
719 static Boolean index_initted = FALSE;
724 return DITEM_FAILURE;
726 if (!mediaDevice->init(mediaDevice))
727 return DITEM_FAILURE;
729 if (!index_initted) {
730 msgNotify("Attempting to fetch packages/INDEX file from selected media.");
731 fp = mediaDevice->get(mediaDevice, "packages/INDEX", TRUE);
733 dialog_clear_norefresh();
734 msgConfirm("Unable to get packages/INDEX file from selected media.\n"
735 "This may be because the packages collection is not available at\n"
736 "on the distribution media you've chosen (most likely an FTP site\n"
737 "without the packages collection mirrored). Please verify media\n"
738 "(or path to media) and try again. If your local site does not\n"
739 "carry the packages collection, then we recommend either a CD\n"
740 "distribution or the master distribution on ftp.freebsd.org.");
741 mediaDevice->shutdown(mediaDevice);
742 return DITEM_FAILURE | DITEM_RESTORE;
744 msgNotify("Located INDEX, now reading package data from it...");
745 index_init(&top, &plist);
746 if (index_read(fp, &top)) {
747 msgConfirm("I/O or format error on packages/INDEX file.\n"
748 "Please verify media (or path to media) and try again.");
750 return DITEM_FAILURE | DITEM_RESTORE;
754 index_initted = TRUE;
757 int ret, pos, scroll;
759 /* Bring up the packages menu */
761 index_menu(&top, &plist, &pos, &scroll);
763 if (plist.kids && plist.kids->name) {
764 /* Now show the packing list menu */
766 ret = index_menu(&plist, NULL, &pos, &scroll);
767 if (ret & DITEM_LEAVE_MENU)
769 else if (DITEM_STATUS(ret) != DITEM_FAILURE) {
770 index_extract(mediaDevice, &top, &plist);
775 dialog_clear_norefresh();
776 msgConfirm("No packages were selected for extraction.");
782 PkgNodePtr tmp2 = tmp->next;
787 index_init(NULL, &plist);
788 return DITEM_SUCCESS | DITEM_RESTORE;
791 #ifdef NETCON_EXTENTIONS
792 /* Load novell client/server package */
794 configNovell(dialogMenuItem *self)
796 int ret = DITEM_SUCCESS;
798 if (!RunningAsInit) {
799 msgConfirm("This package can only be installed in multi-user mode.");
802 if (variable_get(VAR_NOVELL))
803 variable_unset(VAR_NOVELL);
805 ret = package_add(PACKAGE_NETCON);
806 if (DITEM_STATUS(ret) == DITEM_SUCCESS)
807 variable_set2(VAR_NOVELL, "YES");
809 return ret | DITEM_RESTORE;
813 /* Load pcnfsd package */
815 configPCNFSD(dialogMenuItem *self)
817 int ret = DITEM_SUCCESS;
819 if (variable_get(VAR_PCNFSD))
820 variable_unset(VAR_PCNFSD);
822 ret = package_add(variable_get(VAR_PCNFSD_PKG));
823 if (DITEM_STATUS(ret) == DITEM_SUCCESS) {
824 variable_set2(VAR_PCNFSD, "YES");
825 variable_set2("mountd_flags", "-n");
832 configNFSServer(dialogMenuItem *self)
836 /* If we're an NFS server, we need an exports file */
837 if (!file_readable("/etc/exports")) {
838 WINDOW *w = savescr();
840 if (file_readable("/etc/exports.disabled"))
841 vsystem("mv /etc/exports.disabled /etc/exports");
843 dialog_clear_norefresh();
844 msgConfirm("Operating as an NFS server means that you must first configure\n"
845 "an /etc/exports file to indicate which hosts are allowed certain\n"
846 "kinds of access to your local file systems.\n"
847 "Press [ENTER] now to invoke an editor on /etc/exports\n");
848 vsystem("echo '#The following examples export /usr to 3 machines named after ducks,' > /etc/exports");
849 vsystem("echo '#/home and all directories under it to machines named after dead rock stars' >> /etc/exports");
850 vsystem("echo '#and, finally, /a to 2 privileged machines allowed to write on it as root.' >> /etc/exports");
851 vsystem("echo '#/usr huey louie dewie' >> /etc/exports");
852 vsystem("echo '#/home -alldirs janice jimmy frank' >> /etc/exports");
853 vsystem("echo '#/a -maproot=0 bill albert' >> /etc/exports");
854 vsystem("echo '#' >> /etc/exports");
855 vsystem("echo '# You should replace these lines with your actual exported filesystems.' >> /etc/exports");
856 vsystem("echo >> /etc/exports");
857 sprintf(cmd, "%s /etc/exports", variable_get(VAR_EDITOR));
862 variable_set2(VAR_NFS_SERVER, "YES");
864 else if (variable_get(VAR_NFS_SERVER)) { /* We want to turn it off again? */
865 vsystem("mv -f /etc/exports /etc/exports.disabled");
866 variable_unset(VAR_NFS_SERVER);
868 return DITEM_SUCCESS;