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 51static Chunk *chunk_list[MAX_CHUNKS]; 52static int nchunks; 53static int rootdev_is_od; 54 55/* arg to sort */ 56static int 57chunk_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 75static void 76chunk_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 92static void 93check_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 107static char * 108name_of(Chunk *c1) 109{ 110 return c1->name; 111} 112 113static char * 114mount_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 123static char * 124fstype(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 137static char * 138fstype_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 162static int 163seq_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 176int 177configFstab(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 %s then they may NOT\n" 191 "be found by this run!", ProgName); 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 */ 271static int 272readConfig(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 297static void 298readConfigFile(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) */ 331void 332configEnvironmentRC_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 */ 352void 353configEnvironmentResolv(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 */ 375int 376configRC(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 */ 392void 393configRC_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 if (variable_get(VAR_KEEPRCCONF) != NULL) 433 fprintf(rcSite, "%s", line); 434 else 435 fprintf(rcSite, "#REMOVED: %s", line); 436 } 437 } 438 fclose(rcOld); 439 } else if (write_header) { 440 fprintf(rcSite, "# This file now contains just the overrides from /etc/defaults/rc.conf.\n"); 441 fprintf(rcSite, "# Please make all changes to this file, not to /etc/defaults/rc.conf.\n\n"); 442 fprintf(rcSite, "# Enable network daemons for user convenience.\n"); 443 if ((t_loc = time(NULL)) != -1 && (cp = ctime(&t_loc))) 444 fprintf(rcSite, "# Created: %s", cp); 445 } 446 447 /* Now do variable substitutions */ 448 for (v = VarHead; v; v = v->next) { 449 if (v->dirty) { 450 if (!did_marker) { 451 time(&tp); 452 fprintf(rcSite, "# -- sysinstall generated deltas -- # " 453 "%s", ctime(&tp)); 454 did_marker = 1; 455 } 456 fprintf(rcSite, "%s=\"%s\"\n", v->name, v->value); 457 v->dirty = 0; 458 } 459 } 460 fclose(rcSite); 461 462 if(do_merge) { 463 if(rename("/etc/rc.conf.new", "/etc/rc.conf") != 0) { 464 msgError("Error renaming temporary rc.conf: %s (%u)", strerror(errno), errno); 465 return; 466 } 467 } 468 469 /* Tidy up the resulting file if it's late enough in the installation 470 for sort and uniq to be available */ 471 if (do_sort) { 472 (void)vsystem("sort /etc/rc.conf | uniq > /etc/rc.conf.new && mv /etc/rc.conf.new /etc/rc.conf"); 473 } 474} 475 476int 477configSaver(dialogMenuItem *self) 478{ 479 variable_set((char *)self->data, 1); 480 if (!variable_get(VAR_BLANKTIME)) 481 variable_set2(VAR_BLANKTIME, "300", 1); 482 return DITEM_SUCCESS; 483} 484 485int 486configSaverTimeout(dialogMenuItem *self) 487{ 488 return (variable_get_value(VAR_BLANKTIME, 489 "Enter time-out period in seconds for screen saver", 1) ? 490 DITEM_SUCCESS : DITEM_FAILURE); 491} 492 493int 494configNTP(dialogMenuItem *self) 495{ 496 int status; 497 498 status = variable_get_value(VAR_NTPDATE_HOSTS, 499 "Enter the name of an NTP server", 1) 500 ? DITEM_SUCCESS : DITEM_FAILURE; 501 if (status == DITEM_SUCCESS) { 502 static char tmp[255]; 503 504 snprintf(tmp, sizeof(tmp), "ntpdate_enable=YES,ntpdate_hosts=%s", 505 variable_get(VAR_NTPDATE_HOSTS)); 506 self->data = tmp; 507 dmenuSetVariables(self); 508 } 509 return status; 510} 511 512int 513configCountry(dialogMenuItem *self) 514{ 515 int choice, scroll, curr, max; 516 517 WINDOW *w = savescr(); 518 519 dialog_clear_norefresh(); 520 dmenuSetDefaultItem(&MenuCountry, NULL, NULL, 521 VAR_COUNTRY "=" DEFAULT_COUNTRY, &choice, &scroll, &curr, &max); 522 dmenuOpen(&MenuCountry, &choice, &scroll, &curr, &max, FALSE); 523 restorescr(w); 524 return DITEM_SUCCESS; 525} 526 527int 528configUsers(dialogMenuItem *self) 529{ 530 WINDOW *w = savescr(); 531 532 dialog_clear_norefresh(); 533 dmenuOpenSimple(&MenuUsermgmt, FALSE); 534 restorescr(w); 535 return DITEM_SUCCESS; 536} 537 538int 539configSecurelevel(dialogMenuItem *self) 540{ 541 WINDOW *w = savescr(); 542 543 dialog_clear_norefresh(); 544 dmenuOpenSimple(&MenuSecurelevel, FALSE); 545 restorescr(w); 546 return DITEM_SUCCESS; 547} 548 549int 550configSecurelevelDisabled(dialogMenuItem *self) 551{ 552 553 variable_set2("kern_securelevel_enable", "NO", 1); 554 return DITEM_SUCCESS; 555} 556 557int 558configSecurelevelSecure(dialogMenuItem *self) 559{ 560 561 variable_set2("kern_securelevel_enable", "YES", 1); 562 variable_set2("kern_securelevel", "1", 1); 563 return DITEM_SUCCESS; 564} 565 566int 567configSecurelevelHighlySecure(dialogMenuItem *self) 568{ 569 570 variable_set2("kern_securelevel_enable", "YES", 1); 571 variable_set2("kern_securelevel", "2", 1); 572 return DITEM_SUCCESS; 573} 574 575int 576configSecurelevelNetworkSecure(dialogMenuItem *self) 577{ 578 579 variable_set2("kern_securelevel_enable", "YES", 1); 580 variable_set2("kern_securelevel", "3", 1); 581 return DITEM_SUCCESS; 582} 583 584int 585configResolv(dialogMenuItem *ditem) 586{ 587 FILE *fp; 588 char *cp, *c6p, *dp, *hp; 589 590 cp = variable_get(VAR_NAMESERVER); 591 if (!cp || !*cp) 592 goto skip; 593 Mkdir("/etc"); 594 fp = fopen("/etc/resolv.conf", "w"); 595 if (!fp) 596 return DITEM_FAILURE; 597 if (variable_get(VAR_DOMAINNAME)) 598 fprintf(fp, "domain\t%s\n", variable_get(VAR_DOMAINNAME)); 599 fprintf(fp, "nameserver\t%s\n", cp); 600 fclose(fp); 601 if (isDebug()) 602 msgDebug("Wrote out /etc/resolv.conf\n"); 603 604skip: 605 dp = variable_get(VAR_DOMAINNAME); 606 cp = variable_get(VAR_IPADDR); 607 c6p = variable_get(VAR_IPV6ADDR); 608 hp = variable_get(VAR_HOSTNAME); 609 /* Tack ourselves into /etc/hosts */ 610 fp = fopen("/etc/hosts", "w"); 611 if (!fp) 612 return DITEM_FAILURE; 613 /* Add an entry for localhost */ 614 if (dp) { 615 fprintf(fp, "::1\t\t\tlocalhost localhost.%s\n", dp); 616 fprintf(fp, "127.0.0.1\t\tlocalhost localhost.%s\n", dp); 617 } else { 618 fprintf(fp, "::1\t\t\tlocalhost\n"); 619 fprintf(fp, "127.0.0.1\t\tlocalhost\n"); 620 } 621 /* Now the host entries, if applicable */ 622 if (((cp && cp[0] != '0') || (c6p && c6p[0] != '0')) && hp) { 623 char cp2[255]; 624 625 if (!index(hp, '.')) 626 cp2[0] = '\0'; 627 else { 628 SAFE_STRCPY(cp2, hp); 629 *(index(cp2, '.')) = '\0'; 630 } 631 if (c6p && c6p[0] != '0') { 632 fprintf(fp, "%s\t%s %s\n", c6p, hp, cp2); 633 fprintf(fp, "%s\t%s.\n", c6p, hp); 634 } 635 if (cp && cp[0] != '0') { 636 fprintf(fp, "%s\t\t%s %s\n", cp, hp, cp2); 637 fprintf(fp, "%s\t\t%s.\n", cp, hp); 638 } 639 } 640 fclose(fp); 641 if (isDebug()) 642 msgDebug("Wrote out /etc/hosts\n"); 643 return DITEM_SUCCESS; 644} 645 646int 647configRouter(dialogMenuItem *self) 648{ 649 int ret; 650 651 ret = variable_get_value(VAR_ROUTER, 652 "Please specify the router you wish to use. Routed is\n" 653 "provided with the stock system and gated is provided\n" 654 "as an optional package which this installation system\n" 655 "will attempt to load if you select gated. Any other\n" 656 "choice of routing daemon will be assumed to be something\n" 657 "the user intends to install themselves before rebooting\n" 658 "the system. If you don't want any routing daemon, choose NO", 1) 659 ? DITEM_SUCCESS : DITEM_FAILURE; 660 661 if (ret == DITEM_SUCCESS) { 662 char *cp = variable_get(VAR_ROUTER); 663 664 if (cp && strcmp(cp, "NO")) { 665 variable_set2(VAR_ROUTER_ENABLE, "YES", 1); 666 if (!strcmp(cp, "gated")) { 667 if (package_add("gated") != DITEM_SUCCESS) { 668 msgConfirm("Unable to load gated package. Falling back to no router."); 669 variable_unset(VAR_ROUTER); 670 variable_unset(VAR_ROUTERFLAGS); 671 variable_set2(VAR_ROUTER_ENABLE, "NO", 1); 672 cp = NULL; 673 } 674 } 675 if (cp) { 676 /* Now get the flags, if they chose a router */ 677 ret = variable_get_value(VAR_ROUTERFLAGS, 678 "Please Specify the routing daemon flags; if you're running routed\n" 679 "then -q is the right choice for nodes and -s for gateway hosts.\n", 1) 680 ? DITEM_SUCCESS : DITEM_FAILURE; 681 if (ret != DITEM_SUCCESS) 682 variable_unset(VAR_ROUTERFLAGS); 683 } 684 } 685 else { 686 /* No router case */ 687 variable_set2(VAR_ROUTER_ENABLE, "NO", 1); 688 variable_unset(VAR_ROUTERFLAGS); 689 variable_unset(VAR_ROUTER); 690 } 691 } 692 else { 693 variable_set2(VAR_ROUTER_ENABLE, "NO", 1); 694 variable_unset(VAR_ROUTERFLAGS); 695 variable_unset(VAR_ROUTER); 696 } 697 return ret; 698} 699 700/* Shared between us and index_initialize() */ 701extern PkgNode Top, Plist; 702 703int 704configPackages(dialogMenuItem *self) 705{ 706 int i, restoreflag = 0; 707 PkgNodePtr tmp; 708 709 /* Did we get an INDEX? */ 710 i = index_initialize("packages/INDEX"); 711 if (DITEM_STATUS(i) == DITEM_FAILURE) 712 return i; 713 714 while (1) { 715 int ret, pos, scroll; 716 int current, low, high; 717 718 /* Bring up the packages menu */ 719 pos = scroll = 0; 720 index_menu(&Top, &Top, &Plist, &pos, &scroll); 721 722 if (Plist.kids && Plist.kids->name) { 723 /* Now show the packing list menu */ 724 pos = scroll = 0; 725 ret = index_menu(&Plist, &Plist, NULL, &pos, &scroll); 726 if (ret & DITEM_LEAVE_MENU) 727 break; 728 else if (DITEM_STATUS(ret) != DITEM_FAILURE) { 729 dialog_clear(); 730 restoreflag = 1; 731 if (have_volumes) { 732 low = low_volume; 733 high = high_volume; 734 } else 735 low = high = 0; 736 for (current = low; current <= high; current++) 737 for (tmp = Plist.kids; tmp && tmp->name; tmp = tmp->next) 738 (void)index_extract(mediaDevice, &Top, tmp, FALSE, current); 739 break; 740 } 741 } 742 else { 743 msgConfirm("No packages were selected for extraction."); 744 break; 745 } 746 } 747 tmp = Plist.kids; 748 while (tmp) { 749 PkgNodePtr tmp2 = tmp->next; 750 751 safe_free(tmp); 752 tmp = tmp2; 753 } 754 index_init(NULL, &Plist); 755 return DITEM_SUCCESS | (restoreflag ? DITEM_RESTORE : 0); 756} 757 758/* Load pcnfsd package */ 759int 760configPCNFSD(dialogMenuItem *self) 761{ 762 int ret; 763 764 ret = package_add("pcnfsd"); 765 if (DITEM_STATUS(ret) == DITEM_SUCCESS) { 766 variable_set2(VAR_PCNFSD, "YES", 0); 767 variable_set2("mountd_flags", "-n", 1); 768 } 769 return ret; 770} 771 772int 773configInetd(dialogMenuItem *self) 774{ 775 char cmd[256]; 776 777 WINDOW *w = savescr(); 778 779 if (msgYesNo("The Internet Super Server (inetd) allows a number of simple Internet\n" 780 "services to be enabled, including finger, ftp, and telnetd. Enabling\n" 781 "these services may increase risk of security problems by increasing\n" 782 "the exposure of your system.\n\n" 783 "With this in mind, do you wish to enable inetd?\n")) { 784 variable_set2("inetd_enable", "NO", 1); 785 } else { 786 /* If inetd is enabled, we'll need an inetd.conf */ 787 variable_set2("inetd_enable", "YES", 1); 788 if (!msgYesNo("inetd(8) relies on its configuration file, /etc/inetd.conf, to determine\n" 789 "which of its Internet services will be available. The default FreeBSD\n" 790 "inetd.conf(5) leaves all services disabled by default, so they must be\n" 791 "specifically enabled in the configuration file before they will\n" 792 "function, even once inetd(8) is enabled. Note that services for\n" 793 "IPv6 must be separately enabled from IPv4 services.\n\n" 794 "Select [Yes] now to invoke an editor on /etc/inetd.conf, or [No] to\n" 795 "use the current settings.\n")) { 796 sprintf(cmd, "%s /etc/inetd.conf", variable_get(VAR_EDITOR)); 797 dialog_clear(); 798 systemExecute(cmd); 799 } 800 } 801 restorescr(w); 802 return DITEM_SUCCESS; 803} 804 805int 806configNFSServer(dialogMenuItem *self) 807{ 808 char cmd[256]; 809 int retval = 0; 810 811 /* If we're an NFS server, we need an exports file */ 812 if (!file_readable("/etc/exports")) { 813 WINDOW *w = savescr(); 814 815 if (file_readable("/etc/exports.disabled")) 816 vsystem("mv /etc/exports.disabled /etc/exports"); 817 else { 818 dialog_clear_norefresh(); 819 msgConfirm("Operating as an NFS server means that you must first configure\n" 820 "an /etc/exports file to indicate which hosts are allowed certain\n" 821 "kinds of access to your local file systems.\n" 822 "Press [ENTER] now to invoke an editor on /etc/exports\n"); 823 vsystem("echo '#The following examples export /usr to 3 machines named after ducks,' > /etc/exports"); 824 vsystem("echo '#/usr/src and /usr/obj read-only to machines named after trouble makers,' >> /etc/exports"); 825 vsystem("echo '#/home and all directories under it to machines named after dead rock stars' >> /etc/exports"); 826 vsystem("echo '#and, /a to a network of privileged machines allowed to write on it as root.' >> /etc/exports"); 827 vsystem("echo '#/usr huey louie dewie' >> /etc/exports"); 828 vsystem("echo '#/usr/src /usr/obj -ro calvin hobbes' >> /etc/exports"); 829 vsystem("echo '#/home -alldirs janis jimi frank' >> /etc/exports"); 830 vsystem("echo '#/a -maproot=0 -network 10.0.1.0 -mask 255.255.248.0' >> /etc/exports"); 831 vsystem("echo '#' >> /etc/exports"); 832 vsystem("echo '# You should replace these lines with your actual exported filesystems.' >> /etc/exports"); 833 vsystem("echo \"# Note that BSD's export syntax is 'host-centric' vs. Sun's 'FS-centric' one.\" >> /etc/exports"); 834 vsystem("echo >> /etc/exports"); 835 sprintf(cmd, "%s /etc/exports", variable_get(VAR_EDITOR)); 836 dialog_clear(); 837 systemExecute(cmd); 838 } 839 variable_set2(VAR_NFS_SERVER, "YES", 1); 840 retval = configRpcBind(NULL); 841 restorescr(w); 842 } 843 else if (variable_get(VAR_NFS_SERVER)) { /* We want to turn it off again? */ 844 vsystem("mv -f /etc/exports /etc/exports.disabled"); 845 variable_unset(VAR_NFS_SERVER); 846 } 847 return DITEM_SUCCESS | retval; 848} 849 850/* 851 * Extend the standard dmenuToggleVariable() method to also check and set 852 * the rpcbind variable if needed. 853 */ 854int 855configRpcBind(dialogMenuItem *self) 856{ 857 char *tmp, *tmp2; 858 int retval = 0; 859 int doupdate = 1; 860 861 if (self != NULL) { 862 retval = dmenuToggleVariable(self); 863 tmp = strdup(self->data); 864 if ((tmp2 = index(tmp, '=')) != NULL) 865 *tmp2 = '\0'; 866 if (strcmp(variable_get(tmp), "YES") != 0) 867 doupdate = 0; 868 free(tmp); 869 } 870 871 if (doupdate && strcmp(variable_get(VAR_RPCBIND_ENABLE), "YES") != 0) { 872 variable_set2(VAR_RPCBIND_ENABLE, "YES", 1); 873 retval |= DITEM_REDRAW; 874 } 875 876 return retval; 877} 878 879int 880configEtcTtys(dialogMenuItem *self) 881{ 882 char cmd[256]; 883 884 WINDOW *w = savescr(); 885 886 /* Simply prompt for confirmation, then edit away. */ 887 if (msgYesNo("Configuration of system TTYs requires editing the /etc/ttys file.\n" 888 "Typical configuration activities might include enabling getty(8)\n" 889 "on the first serial port to allow login via serial console after\n" 890 "reboot, or to enable xdm. The default ttys file enables normal\n" 891 "virtual consoles, and most sites will not need to perform manual\n" 892 "configuration.\n\n" 893 "To load /etc/ttys in the editor, select [Yes], otherwise, [No].")) { 894 } else { 895 configTtys(); 896 sprintf(cmd, "%s /etc/ttys", variable_get(VAR_EDITOR)); 897 dialog_clear(); 898 systemExecute(cmd); 899 } 900 901 restorescr(w); 902 return DITEM_SUCCESS; 903} 904 905#ifdef __i386__ 906int 907checkLoaderACPI(void) 908{ 909 char val[4]; 910 911 if (kenv(KENV_GET, "loader.acpi_disabled_by_user", &val[0], 4) <= 0) { 912 return (0); 913 } 914 915 if (strtol(&val[0], NULL, 10) <= 0) { 916 return (0); 917 } 918 919 return (1); 920} 921 922int 923configLoaderACPI(int disable) 924{ 925 FILE *ldconf; 926 927 ldconf = fopen("/boot/loader.conf", "a"); 928 if (ldconf == NULL) { 929 msgConfirm("Unable to open /boot/loader.conf. Please consult the\n" 930 "FreeBSD Handbook for instructions on disabling ACPI"); 931 return DITEM_FAILURE; 932 } 933 934 fprintf(ldconf, "# --- Generated by sysinstall ---\n"); 935 fprintf(ldconf, "hint.acpi.0.disabled=%d\n", disable); 936 fclose(ldconf); 937 938 return DITEM_SUCCESS; 939} 940#endif 941 942int 943configMTAPostfix(dialogMenuItem *self) 944{ 945 int ret; 946 FILE *perconf; 947 948 if(setenv("POSTFIX_DEFAULT_MTA", "YES", 1) != 0) 949 msgError("Error setting the enviroment variable POSTFIX_DEFAULT_MTA: %s (%u)", 950 strerror(errno), errno); 951 952 ret = package_add("postfix-2.4"); 953 unsetenv("POSTFIX_DEFAULT_MTA"); 954 955 if(DITEM_STATUS(ret) == DITEM_FAILURE) { 956 msgConfirm("An error occurred while adding the postfix package\n" 957 "Please change installation media and try again."); 958 return ret; 959 } 960 961 variable_set2(VAR_SENDMAIL_ENABLE, "YES", 1); 962 variable_set2("sendmail_flags", "-bd", 1); 963 variable_set2("sendmail_outbound_enable", "NO", 1); 964 variable_set2("sendmail_submit_enable", "NO", 1); 965 variable_set2("sendmail_msp_queue_enable", "NO", 1); 966 967 perconf = fopen("/etc/periodic.conf", "a"); 968 if (perconf == NULL) { 969 msgConfirm("Unable to open /etc/periodic.conf.\n" 970 "The daily cleanup scripts might generate errors when\n" 971 "trying to run some sendmail only cleanup scripts.\n" 972 "Please consult the documentation for the postfix port on how to\n" 973 "fix this."); 974 975 /* Not really a serious problem, so we return success */ 976 return DITEM_SUCCESS; 977 } 978 979 fprintf(perconf, "# --- Generated by sysinstall ---\n"); 980 fprintf(perconf, "daily_clean_hoststat_enable=\"NO\"\n"); 981 fprintf(perconf, "daily_status_mail_rejects_enable=\"NO\"\n"); 982 fprintf(perconf, "daily_status_include_submit_mailq=\"NO\"\n"); 983 fprintf(perconf, "daily_submit_queuerun=\"NO\"\n"); 984 fclose(perconf); 985 986 msgConfirm("Postfix is now installed and enabled as the default MTA.\n" 987 "Please check that the configuration works as expected.\n" 988 "See the Postfix documentation for more information.\n" 989 "The documentation can be found in /usr/local/share/doc/postfix/\n" 990 "or on the Postfix website at http://www.postfix.org/."); 991 992 return DITEM_SUCCESS; 993} 994 995int 996configMTAExim(dialogMenuItem *self) 997{ 998 int ret; 999 FILE *perconf, *mailerconf, *newsyslogconf; 1000 1001 ret = package_add("exim"); 1002 1003 if(DITEM_STATUS(ret) == DITEM_FAILURE) { 1004 msgConfirm("An error occurred while adding the exim package\n" 1005 "Please change installation media and try again."); 1006 return ret; 1007 } 1008 1009 variable_set2(VAR_SENDMAIL_ENABLE, "NONE", 1); 1010 variable_set2("exim_enable", "YES", 1); 1011 1012 /* Update periodic.conf */ 1013 perconf = fopen("/etc/periodic.conf", "a"); 1014 if (perconf == NULL) { 1015 /* Not really a serious problem, so we do not abort */ 1016 msgConfirm("Unable to open /etc/periodic.conf.\n" 1017 "The daily cleanup scripts might generate errors when\n" 1018 "trying to run some sendmail only cleanup scripts.\n" 1019 "Please consult the documentation for the exim port on how to\n" 1020 "fix this."); 1021 } else { 1022 fprintf(perconf, "# --- Generated by sysinstall ---\n"); 1023 fprintf(perconf, "daily_clean_hoststat_enable=\"NO\"\n"); 1024 fprintf(perconf, "daily_status_include_submit_mailq=\"NO\"\n"); 1025 fprintf(perconf, "daily_status_mail_rejects_enable=\"NO\"\n"); 1026 fprintf(perconf, "daily_submit_queuerun=\"NO\"\n"); 1027 fclose(perconf); 1028 } 1029 1030 /* Update mailer.conf */ 1031 vsystem("mv -f /etc/mail/mailer.conf /etc/mail/mailer.conf.old"); 1032 mailerconf = fopen("/etc/mail/mailer.conf", "w"); 1033 if (mailerconf == NULL) { 1034 /* Not really a serious problem, so we do not abort */ 1035 msgConfirm("Unable to open /etc/mailer.conf.\n" 1036 "Some programs which use the sendmail wrappers may not work.\n" 1037 "Please consult the documentation for the exim port on how\n" 1038 "to correct this."); 1039 } else { 1040 fprintf(mailerconf, "# --- Generated by sysinstall ---\n"); 1041 fprintf(mailerconf, "# Execute exim instead of sendmail\n"); 1042 fprintf(mailerconf, "#\n"); 1043 fprintf(mailerconf, "sendmail /usr/local/sbin/exim\n"); 1044 fprintf(mailerconf, "send-mail /usr/local/sbin/exim\n"); 1045 fprintf(mailerconf, "mailq /usr/local/sbin/exim\n"); 1046 fprintf(mailerconf, "newaliases /usr/local/sbin/exim\n"); 1047 fprintf(mailerconf, "hoststat /usr/bin/true\n"); 1048 fprintf(mailerconf, "purgestat /usr/bin/true\n"); 1049 fclose(mailerconf); 1050 } 1051 1052 /* Make newsyslog rotate exim logfiles */ 1053 newsyslogconf = fopen("/etc/newsyslog.conf", "a"); 1054 if (newsyslogconf == NULL) { 1055 /* Not really a serious problem, so we do not abort */ 1056 msgConfirm("Unable to open /etc/newsyslog.conf.\n" 1057 "The exim logfiles will not be rotated.\n" 1058 "Please consult the documentation for the exim port on how to\n" 1059 "rotate the logfiles."); 1060 } else { 1061 fprintf(newsyslogconf, "# --- Generated by sysinstall ---\n"); 1062 fprintf(newsyslogconf, "/var/log/exim/mainlog mailnull:mail 640 7 * @T00 ZN\n"); 1063 fprintf(newsyslogconf, "/var/log/exim/rejectlog mailnull:mail 640 7 * @T00 ZN\n"); 1064 fclose(newsyslogconf); 1065 } 1066 1067 msgConfirm("Exim is now installed and enabled as the default MTA.\n" 1068 "Please check that the configuration works as expected.\n" 1069 "See the Exim documentation for more information.\n" 1070 "The documentation can be found in /usr/local/share/doc/exim/\n" 1071 "or on the Exim website at http://www.exim.org/."); 1072 1073 return DITEM_SUCCESS; 1074} 1075