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.101 1997/06/21 15:45:07 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)
185 if (!RunningAsInit) {
186 if (file_readable("/etc/fstab"))
187 return DITEM_SUCCESS;
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!");
195 devs = deviceFind(NULL, DEVICE_TYPE_DISK);
197 msgConfirm("No disks found!");
198 return DITEM_FAILURE;
201 /* Record all the chunks */
203 for (i = 0; devs[i]; i++) {
204 if (!devs[i]->enabled)
206 disk = (Disk *)devs[i]->private;
208 msgFatal("No chunk list found for %s!", disk->name);
209 for (c1 = disk->chunks->part; c1; c1 = c1->next) {
210 if (c1->type == freebsd) {
211 for (c2 = c1->part; c2; c2 = c2->next) {
212 if (c2->type == part && (c2->subtype == FS_SWAP || c2->private_data))
213 chunk_list[nchunks++] = c2;
216 else if (c1->type == fat && c1->private_data)
217 chunk_list[nchunks++] = c1;
220 chunk_list[nchunks] = 0;
223 fstab = fopen("/etc/fstab", "w");
225 msgConfirm("Unable to create a new /etc/fstab file! Manual intervention\n"
226 "will be required.");
227 return DITEM_FAILURE;
230 check_rootdev(chunk_list, nchunks);
232 /* Go for the burn */
233 msgDebug("Generating /etc/fstab file\n");
234 fprintf(fstab, "# Device\t\tMountpoint\tFStype\tOptions\t\tDump\tPass#\n");
235 for (i = 0; i < nchunks; i++)
236 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]),
237 fstype(chunk_list[i]), fstype_short(chunk_list[i]), seq_num(chunk_list[i]), seq_num(chunk_list[i]));
239 fprintf(fstab, "proc\t\t\t/proc\t\tprocfs\trw\t\t0\t0\n");
241 /* Now look for the CDROMs */
242 devs = deviceFind(NULL, DEVICE_TYPE_CDROM);
243 cnt = deviceCount(devs);
245 /* Write the first one out as /cdrom */
247 if (Mkdir("/cdrom")) {
248 msgConfirm("Unable to make mount point for: /cdrom");
251 fprintf(fstab, "/dev/%s\t\t/cdrom\t\tcd9660\tro,noauto\t0\t0\n", devs[0]->name);
254 /* Write the others out as /cdrom<n> */
255 for (i = 1; i < cnt; i++) {
258 sprintf(cdname, "/cdrom%d", i);
260 msgConfirm("Unable to make mount point for: %s", cdname);
263 fprintf(fstab, "/dev/%s\t\t%s\tcd9660\tro,noauto\t0\t0\n", devs[i]->name, cdname);
267 msgDebug("Wrote out /etc/fstab file\n");
268 return DITEM_SUCCESS;
271 /* Do the work of sucking in a config file.
272 * config is the filename to read in.
273 * lines is a fixed (max) sized array of char *.
274 * returns number of lines read. line contents
275 * are malloc'd and must be freed by the caller.
278 readConfig(char *config, char **lines, int max)
284 fp = fopen(config, "r");
289 /* Read in the entire file */
290 for (i = 0; i < max; i++) {
291 if (!fgets(line, sizeof line, fp))
293 lines[nlines++] = strdup(line);
297 msgDebug("readConfig: Read %d lines from %s.\n", nlines, config);
301 #define MAX_LINES 2000 /* Some big number we're not likely to ever reach - I'm being really lazy here, I know */
303 /* Load the environment from an rc.conf file */
305 configEnvironmentRC_conf(char *config)
307 char *lines[MAX_LINES], *cp, *cp2;
310 nlines = readConfig(config, lines, MAX_LINES);
314 for (i = 0; i < nlines; i++) {
315 /* Skip the comments & non-variable settings */
316 if (lines[i][0] == '#' || !(cp = index(lines[i], '='))) {
322 if ((cp2 = index(cp, '"')) || (cp2 = index(cp, '\047'))) {
324 cp2 = index(cp, *cp2);
326 /* If valid quotes, use it */
330 variable_set2(lines[i], cp);
336 /* Load the environment from a resolv.conf file */
338 configEnvironmentResolv(char *config)
340 char *lines[MAX_LINES];
343 nlines = readConfig(config, lines, MAX_LINES);
346 for (i = 0; i < nlines; i++) {
347 Boolean name_set = FALSE;
349 if (!strncmp(lines[i], "domain", 6))
350 variable_set2(VAR_DOMAINNAME, string_skipwhite(string_prune(lines[i] + 6)));
351 else if (!strncmp(lines[i], "nameserver", 10) && !name_set) {
352 /* Only take the first nameserver setting - we're lame */
353 variable_set2(VAR_NAMESERVER, string_skipwhite(string_prune(lines[i] + 10)));
360 /* Version of below for dispatch routines */
362 configRC(dialogMenuItem *unused)
364 configRC_conf("/etc/rc.conf");
365 return DITEM_SUCCESS;
369 * This sucks in /etc/rc.conf, substitutes anything needing substitution, then
370 * writes it all back out. It's pretty gross and needs re-writing at some point.
373 configRC_conf(char *config)
376 char *lines[MAX_LINES], *cp;
380 nlines = readConfig(config, lines, MAX_LINES);
384 /* Now do variable substitutions */
385 for (v = VarHead; v; v = v->next) {
386 for (i = 0; i < nlines; i++) {
387 /* Skip the comments & non-variable settings */
388 if (lines[i][0] == '#' || !(cp = index(lines[i], '=')))
390 len = strlen(v->name);
391 if (!strncmp(lines[i], v->name, cp - lines[i]) && (cp - lines[i]) == len) {
392 char *cp2, *comment = NULL;
394 /* If trailing comment, try and preserve it */
395 if ((index(lines[i], '#')) != NULL) {
397 if ((cp2 = index(cp, '"')) || (cp2 = index(cp, '\047')))
398 cp2 = index(cp2 + 1, *cp2);
399 if (cp2 && strlen(cp2 + 1)) {
400 comment = alloca(strlen(cp2));
401 strcpy(comment, cp2 + 1);
405 lines[i] = (char *)malloc(strlen(v->name) + strlen(v->value) + (comment ? strlen(comment) : 0) + 10);
407 sprintf(lines[i], "%s=\"%s\"%s", v->name, v->value, comment);
409 sprintf(lines[i], "%s=\"%s\"\n", v->name, v->value);
414 /* Now write it all back out again */
416 msgDebug("Writing configuration changes to %s file..", config);
418 fp = fdopen(DebugFD, "w");
420 (void)vsystem("cp %s %s.previous", config, config);
421 fp = fopen(config, "w");
423 for (i = 0; i < nlines; i++) {
424 fprintf(fp, lines[i]);
425 /* Stand by for bogus special case handling - we try to dump the interface specs here */
426 if (!strncmp(lines[i], VAR_INTERFACES, strlen(VAR_INTERFACES))) {
430 devp = deviceFind(NULL, DEVICE_TYPE_NETWORK);
431 cnt = deviceCount(devp);
432 for (j = 0; j < cnt; j++) {
433 char iname[255], toadd[512];
436 if (!strncmp(devp[j]->name, "ppp", 3) || !strncmp(devp[j]->name, "tun", 3))
439 snprintf(iname, 255, "%s%s", VAR_IFCONFIG, devp[j]->name);
440 if ((cp = variable_get(iname))) {
441 snprintf(toadd, sizeof toadd, "%s=\"%s\"\n", iname, cp);
442 for (k = 0; k < nlines; k++) {
443 if (!strcmp(lines[k], toadd)) {
459 configSaver(dialogMenuItem *self)
461 variable_set((char *)self->data);
462 if (!variable_get(VAR_BLANKTIME))
463 variable_set2(VAR_BLANKTIME, "300");
464 return DITEM_SUCCESS;
468 configSaverTimeout(dialogMenuItem *self)
470 return (variable_get_value(VAR_BLANKTIME, "Enter time-out period in seconds for screen saver") ?
471 DITEM_SUCCESS : DITEM_FAILURE) | DITEM_RESTORE;
475 configRegister(dialogMenuItem *self)
477 return DITEM_STATUS(registerOpenDialog()) | DITEM_RESTORE;
481 configNTP(dialogMenuItem *self)
485 status = variable_get_value("ntpdate_flags", "Enter the name of an NTP server") ? DITEM_SUCCESS : DITEM_FAILURE;
486 if (status == DITEM_SUCCESS) {
487 static char tmp[255];
489 snprintf(tmp, 255, "ntpdate_enable=YES,ntpdate_flags=%s", variable_get("ntpdate_flags"));
491 dmenuSetVariables(self);
493 return status | DITEM_RESTORE;
497 configUsers(dialogMenuItem *self)
499 dialog_clear_norefresh();
500 dmenuOpenSimple(&MenuUsermgmt, FALSE);
502 return DITEM_SUCCESS | DITEM_RESTORE;
506 configXEnvironment(dialogMenuItem *self)
508 #ifndef USE_XIG_ENVIRONMENT
509 char *config, *execfile;
511 dialog_clear_norefresh();
512 if (!dmenuOpenSimple(&MenuXF86Config, FALSE))
513 return DITEM_FAILURE | DITEM_RESTORE;
514 systemExecute("/sbin/ldconfig /usr/lib /usr/X11R6/lib /usr/local/lib /usr/lib/compat");
515 config = variable_get(VAR_XF86_CONFIG);
517 return DITEM_FAILURE | DITEM_RESTORE;
518 execfile = string_concat("/usr/X11R6/bin/", config);
519 if (file_executable(execfile)) {
520 dialog_clear_norefresh();
521 if (!file_readable("/dev/mouse") && !msgYesNo("Does this system have a mouse attached to it?"))
522 dmenuOpenSimple(&MenuMouse, FALSE);
524 systemExecute(execfile);
525 return DITEM_SUCCESS | DITEM_RESTORE;
528 dialog_clear_norefresh();
529 msgConfirm("XFree86 does not appear to be installed! Please install\n"
530 "The XFree86 distribution before attempting to configure it.");
531 return DITEM_FAILURE | DITEM_RESTORE;
534 #else /* USE_XIG_ENVIRONMENT */
537 /* Make sure we're sane first */
538 if (!file_readable("/usr/X11R6/lib/X11/AcceleratedX/bin/Xinstall") ||
539 !file_readable("/usr/X11R6/lib/X11/AcceleratedX/bin/Xsetup")) {
540 dialog_clear_norefresh();
541 msgConfirm("Hmmm! It looks like you elected not to install the AccelleratedX\n"
542 "server package (or the installation failed somehow). If this was\n"
543 "an omission rather than an error, please go to the Distributions\n"
544 "menu, select the Custom distribution options and then choose your X11\n"
545 "distribution components from the XFree86 menu. AccelX will be selected\n"
546 "as the default server automatically.");
547 return DITEM_FAILURE | DITEM_RESTORE;
550 if (mediaDevice && mediaDevice->type != DEVICE_TYPE_CDROM) {
551 if (DITEM_STATUS(mediaSetCDROM(NULL)) != DITEM_SUCCESS || !mediaDevice || !mediaDevice->init(mediaDevice)) {
552 msgConfirm("I can't mount the CDE distribution from CDROM, sorry.\n"
553 "Please make sure you have the 1st CD of your FreeBSD Desktop/Pro\n"
554 "distribution in the drive before trying this operation.");
555 return DITEM_FAILURE | DITEM_RESTORE;
559 if (!directory_exists("/dist/CDE/")) {
560 msgConfirm("Hmmm! I can't find the CDE distribution. Please place the 1st CD of your\n"
561 "FreeBSD Desktop/Pro distribution in the drive and try this operation again.");
562 return DITEM_FAILURE | DITEM_RESTORE;
565 /* Pre-extract base sets in kludge to work around chicken-and-egg problem with CDE and Xaccel */
566 if (directory_exists("/dist/CDE/") && !file_readable("/usr/X11R6/bin/xterm")) {
567 msgNotify("Installing bootstrap X11 tools from CDE distribution.");
568 systemExecute("tar xpf /dist/CDE/FreeBSD/packages/X11-RUN/archive -C /");
569 systemExecute("tar xpf /dist/CDE/FreeBSD/packages/X11-PRG/archive -C /");
571 systemExecute("/sbin/ldconfig /usr/lib /usr/X11R6/lib /usr/dt/lib /usr/local/lib /usr/lib/compat");
573 dialog_clear_norefresh();
574 msgNotify("Running AcceleratedX 3.1 installation procedure, please wait.");
575 if ((i = vsystem("/usr/X11R6/lib/X11/AcceleratedX/bin/Xinstall"))) {
576 dialog_clear_norefresh();
577 msgConfirm("Installation procedure failed, error code %d! Please report\n"
578 "error to Walnut Creek CDROM tech support (either send email\n"
579 "to support@cdrom.com or call +1 510 603 1234). Thank you!", i);
580 return DITEM_FAILURE | DITEM_RESTORE;
584 systemExecute("/usr/X11R6/lib/X11/AcceleratedX/bin/Xsetup");
586 if (directory_exists("/dist/CDE")) {
587 dialog_clear_norefresh();
588 msgNotify("Running CDE installation - please wait (this may take awhile!).");
592 i = systemExecute("(cd /dist/CDE; sh Install)");
595 msgConfirm("/dist/CDE/dtinstall script returned an error status!\n\n"
596 "To try again, you should run this command manually after the system\n"
597 "is up (and if your CDROM is mounted in the standard location, the path\n"
598 "to it will actually be /cdrom/CDE/dtinstall when you run it later).\n");
601 if (file_readable("/dist/CDE/post-install"))
602 systemExecute("/dist/CDE/post-install");
603 /* Repair the damage done by the CDE installation */
604 msgNotify("Doing final adjustments to Xaccel distribution...");
605 systemExecute("/usr/X11R6/lib/X11/AcceleratedX/bin/Xinstall");
608 return DITEM_SUCCESS | DITEM_RESTORE;
609 #endif /* USE_XIG_ENVIRONMENT */
618 cp = variable_get(VAR_NAMESERVER);
622 fp = fopen("/etc/resolv.conf", "w");
625 if (variable_get(VAR_DOMAINNAME))
626 fprintf(fp, "domain\t%s\n", variable_get(VAR_DOMAINNAME));
627 fprintf(fp, "nameserver\t%s\n", cp);
630 msgDebug("Wrote out /etc/resolv.conf\n");
633 dp = variable_get(VAR_DOMAINNAME);
634 cp = variable_get(VAR_IPADDR);
635 hp = variable_get(VAR_HOSTNAME);
636 /* Tack ourselves into /etc/hosts */
637 fp = fopen("/etc/hosts", "w");
640 /* Add an entry for localhost */
641 fprintf(fp, "127.0.0.1\t\tlocalhost.%s localhost\n", dp ? dp : "my.domain");
642 /* Now the host entries, if applicable */
643 if (cp && cp[0] != '0' && hp) {
649 SAFE_STRCPY(cp2, hp);
650 *(index(cp2, '.')) = '\0';
652 fprintf(fp, "%s\t\t%s %s\n", cp, hp, cp2);
653 fprintf(fp, "%s\t\t%s.\n", cp, hp);
657 msgDebug("Wrote out /etc/hosts\n");
661 configRouter(dialogMenuItem *self)
665 ret = variable_get_value(VAR_ROUTER,
666 "Please specify the router you wish to use. Routed is\n"
667 "provided with the stock system and gated is provided\n"
668 "as an optional package which this installation system\n"
669 "will attempt to load if you select gated. Any other\n"
670 "choice of routing daemon will be assumed to be something\n"
671 "the user intends to install themselves before rebooting\n"
672 "the system. If you don't want any routing daemon, choose NO")
673 ? DITEM_SUCCESS : DITEM_FAILURE;
675 if (ret == DITEM_SUCCESS) {
676 char *cp = variable_get(VAR_ROUTER);
678 if (cp && strcmp(cp, "NO")) {
679 variable_set2(VAR_ROUTER_ENABLE, "YES");
680 if (!strcmp(cp, "gated")) {
681 if (package_add(variable_get(VAR_GATED_PKG)) != DITEM_SUCCESS) {
682 msgConfirm("Unable to load gated package. Falling back to no router.");
683 variable_unset(VAR_ROUTER);
684 variable_unset(VAR_ROUTERFLAGS);
685 variable_set2(VAR_ROUTER_ENABLE, "NO");
690 /* Now get the flags, if they chose a router */
691 ret = variable_get_value(VAR_ROUTERFLAGS,
692 "Please Specify the routing daemon flags; if you're running routed\n"
693 "then -q is the right choice for nodes and -s for gateway hosts.\n")
694 ? DITEM_SUCCESS : DITEM_FAILURE;
695 if (ret != DITEM_SUCCESS)
696 variable_unset(VAR_ROUTERFLAGS);
701 variable_set2(VAR_ROUTER_ENABLE, "NO");
702 variable_unset(VAR_ROUTERFLAGS);
703 variable_unset(VAR_ROUTER);
706 return ret | DITEM_RESTORE;
710 configPackages(dialogMenuItem *self)
712 static PkgNode top, plist;
713 static Boolean index_initted = FALSE;
718 return DITEM_FAILURE;
720 if (!mediaDevice->init(mediaDevice))
721 return DITEM_FAILURE;
723 if (!index_initted) {
724 msgNotify("Attempting to fetch packages/INDEX file from selected media.");
725 fp = mediaDevice->get(mediaDevice, "packages/INDEX", TRUE);
727 dialog_clear_norefresh();
728 msgConfirm("Unable to get packages/INDEX file from selected media.\n"
729 "This may be because the packages collection is not available at\n"
730 "on the distribution media you've chosen (most likely an FTP site\n"
731 "without the packages collection mirrored). Please verify media\n"
732 "(or path to media) and try again. If your local site does not\n"
733 "carry the packages collection, then we recommend either a CD\n"
734 "distribution or the master distribution on ftp.freebsd.org.");
735 mediaDevice->shutdown(mediaDevice);
736 return DITEM_FAILURE | DITEM_RESTORE;
738 msgNotify("Located INDEX, now reading package data from it...");
739 index_init(&top, &plist);
740 if (index_read(fp, &top)) {
741 msgConfirm("I/O or format error on packages/INDEX file.\n"
742 "Please verify media (or path to media) and try again.");
744 return DITEM_FAILURE | DITEM_RESTORE;
748 index_initted = TRUE;
751 int ret, pos, scroll;
753 /* Bring up the packages menu */
755 index_menu(&top, &plist, &pos, &scroll);
757 if (plist.kids && plist.kids->name) {
758 /* Now show the packing list menu */
760 ret = index_menu(&plist, NULL, &pos, &scroll);
761 if (ret & DITEM_LEAVE_MENU)
763 else if (DITEM_STATUS(ret) != DITEM_FAILURE) {
764 index_extract(mediaDevice, &top, &plist);
769 dialog_clear_norefresh();
770 msgConfirm("No packages were selected for extraction.");
776 PkgNodePtr tmp2 = tmp->next;
781 index_init(NULL, &plist);
782 return DITEM_SUCCESS | DITEM_RESTORE;
785 #ifdef NETCON_EXTENTIONS
786 /* Load novell client/server package */
788 configNovell(dialogMenuItem *self)
790 int ret = DITEM_SUCCESS;
792 if (!RunningAsInit) {
793 msgConfirm("This package can only be installed in multi-user mode.");
796 if (variable_get(VAR_NOVELL))
797 variable_unset(VAR_NOVELL);
799 ret = package_add(PACKAGE_NETCON);
800 if (DITEM_STATUS(ret) == DITEM_SUCCESS)
801 variable_set2(VAR_NOVELL, "YES");
803 return ret | DITEM_RESTORE;
807 /* Load pcnfsd package */
809 configPCNFSD(dialogMenuItem *self)
811 int ret = DITEM_SUCCESS;
813 if (variable_get(VAR_PCNFSD))
814 variable_unset(VAR_PCNFSD);
816 ret = package_add(variable_get(VAR_PCNFSD_PKG));
817 if (DITEM_STATUS(ret) == DITEM_SUCCESS) {
818 variable_set2(VAR_PCNFSD, "YES");
819 variable_set2("mountd_flags", "-n");
826 configNFSServer(dialogMenuItem *self)
830 /* If we're an NFS server, we need an exports file */
831 if (!file_readable("/etc/exports")) {
832 WINDOW *w = savescr();
834 if (file_readable("/etc/exports.disabled"))
835 vsystem("mv /etc/exports.disabled /etc/exports");
837 dialog_clear_norefresh();
838 msgConfirm("Operating as an NFS server means that you must first configure\n"
839 "an /etc/exports file to indicate which hosts are allowed certain\n"
840 "kinds of access to your local file systems.\n"
841 "Press [ENTER] now to invoke an editor on /etc/exports\n");
842 vsystem("echo '#The following examples export /usr to 3 machines named after ducks,' > /etc/exports");
843 vsystem("echo '#/home and all directories under it to machines named after dead rock stars' >> /etc/exports");
844 vsystem("echo '#and, finally, /a to 2 privileged machines allowed to write on it as root.' >> /etc/exports");
845 vsystem("echo '#/usr huey louie dewie' >> /etc/exports");
846 vsystem("echo '#/home -alldirs janice jimmy frank' >> /etc/exports");
847 vsystem("echo '#/a -maproot=0 bill albert' >> /etc/exports");
848 vsystem("echo '#' >> /etc/exports");
849 vsystem("echo '# You should replace these lines with your actual exported filesystems.' >> /etc/exports");
850 vsystem("echo >> /etc/exports");
851 sprintf(cmd, "%s /etc/exports", variable_get(VAR_EDITOR));
856 variable_set2(VAR_NFS_SERVER, "YES");
858 else if (variable_get(VAR_NFS_SERVER)) { /* We want to turn it off again? */
859 vsystem("mv -f /etc/exports /etc/exports.disabled");
860 variable_unset(VAR_NFS_SERVER);
862 return DITEM_SUCCESS;