summaryrefslogtreecommitdiff
path: root/release
diff options
context:
space:
mode:
Diffstat (limited to 'release')
-rw-r--r--release/sysinstall/anonFTP.c487
-rw-r--r--release/sysinstall/apache.c604
-rw-r--r--release/sysinstall/doc.c100
-rw-r--r--release/sysinstall/freebsd.cfg58
-rw-r--r--release/sysinstall/help/anonftp.hlp19
-rw-r--r--release/sysinstall/help/apache.hlp51
-rw-r--r--release/sysinstall/help/upgrade.hlp38
-rw-r--r--release/sysinstall/index.c569
-rw-r--r--release/sysinstall/installFinal.c223
-rw-r--r--release/sysinstall/installPreconfig.c221
-rw-r--r--release/sysinstall/installUpgrade.c396
-rw-r--r--release/sysinstall/lndir.c217
-rw-r--r--release/sysinstall/options.c289
-rw-r--r--release/sysinstall/package.c280
-rw-r--r--release/sysinstall/power.uu121
-rw-r--r--release/sysinstall/version.h1
16 files changed, 3674 insertions, 0 deletions
diff --git a/release/sysinstall/anonFTP.c b/release/sysinstall/anonFTP.c
new file mode 100644
index 0000000000000..389f48b569fa8
--- /dev/null
+++ b/release/sysinstall/anonFTP.c
@@ -0,0 +1,487 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last program in the `sysinstall' line - the next
+ * generation being essentially a complete rewrite.
+ *
+ * $Id: anonFTP.c,v 1.5 1995/11/11 11:56:40 jkh Exp $
+ *
+ * Copyright (c) 1995
+ * Coranth Gryphon. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Coranth Gryphon
+ * for the FreeBSD Project.
+ * 4. The name of Coranth Gryphon or the FreeBSD project may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CORANTH GRYPHON ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CORANTH GRYPHON OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <string.h>
+#include <dialog.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include "ui_objects.h"
+#include "dir.h"
+#include "dialog.priv.h"
+#include "colors.h"
+#include "sysinstall.h"
+
+/* This doesn't change until FTP itself changes */
+
+#define FTP_NAME "ftp"
+#define MOTD_FILE "ftpmotd"
+
+/* These change if we want to use different defaults */
+
+#define FTP_UID 14
+#define FTP_GID 5
+#define FTP_GROUP "operator"
+#define FTP_UPLOAD "incoming"
+#define FTP_COMMENT "Anonymous FTP Admin"
+#define FTP_HOMEDIR "/usr/ftp"
+
+#define ANONFTP_HELPFILE "anonftp"
+
+/* Set up the structure to hold configuration information */
+/* Note that this is only what we could fit onto the one screen */
+
+typedef struct
+{
+ char homedir[64]; /* Home Dir for Anon FTP */
+ char group[32]; /* Group */
+ char uid[8]; /* UID */
+ char comment[64]; /* PWD Comment */
+ char upload[32]; /* Upload Dir */
+} FTPConf;
+
+static FTPConf tconf;
+
+#define ANONFTP_HOMEDIR_LEN 64
+#define ANONFTP_COMMENT_LEN 64
+#define ANONFTP_UPLOAD_LEN 32
+#define ANONFTP_GROUP_LEN 32
+#define ANONFTP_UID_LEN 8
+
+static int okbutton, cancelbutton;
+
+/* What the screen size is meant to be */
+#define ANONFTP_DIALOG_Y 0
+#define ANONFTP_DIALOG_X 8
+#define ANONFTP_DIALOG_WIDTH COLS - 16
+#define ANONFTP_DIALOG_HEIGHT LINES - 2
+
+/* The screen layout structure */
+typedef struct _layout {
+ int y; /* x & Y co-ordinates */
+ int x;
+ int len; /* The size of the dialog on the screen */
+ int maxlen; /* How much the user can type in ... */
+ char *prompt; /* The string for the prompt */
+ char *help; /* The display for the help line */
+ void *var; /* The var to set when this changes */
+ int type; /* The type of the dialog to create */
+ void *obj; /* The obj pointer returned by libdialog */
+} Layout;
+
+static Layout layout[] = {
+{ 2, 3, 8, ANONFTP_UID_LEN - 1,
+ "UID:", "What user ID to assign to FTP Admin",
+ tconf.uid, STRINGOBJ, NULL },
+#define LAYOUT_UID 1
+
+{ 2, 15, 15, ANONFTP_GROUP_LEN - 1,
+ "Group:", "Group name that ftp process belongs to",
+ tconf.group, STRINGOBJ, NULL },
+#define LAYOUT_GROUP 2
+
+{ 2, 35, 24, ANONFTP_COMMENT_LEN - 1,
+ "Comment:", "Password file comment for FTP Admin",
+ tconf.comment, STRINGOBJ, NULL },
+#define LAYOUT_COMMENT 3
+
+{ 9, 10, 43, ANONFTP_HOMEDIR_LEN - 1,
+ "FTP Root Directory:",
+ "The top directory to chroot to when doing anonymous ftp",
+ tconf.homedir, STRINGOBJ, NULL },
+#define LAYOUT_HOMEDIR 4
+
+{ 14, 20, 22, ANONFTP_UPLOAD_LEN - 1,
+ "Upload Subdirectory:", "Designated sub-directory that holds uploads",
+ tconf.upload, STRINGOBJ, NULL },
+#define LAYOUT_UPLOAD 5
+
+{ 19, 15, 0, 0,
+ "OK", "Select this if you are happy with these settings",
+ &okbutton, BUTTONOBJ, NULL },
+#define LAYOUT_OKBUTTON 6
+
+{ 19, 35, 0, 0,
+ "CANCEL", "Select this if you wish to cancel this screen",
+ &cancelbutton, BUTTONOBJ, NULL },
+#define LAYOUT_CANCELBUTTON 7
+{ NULL },
+};
+
+int createFtpUser()
+{
+ struct passwd *tpw;
+ struct group *tgrp;
+ char pwline[256];
+ char *tptr;
+ int gid;
+ FILE *fptr;
+
+ if ((gid = atoi(tconf.group)) <= 0) {
+ if (!(tgrp = getgrnam(tconf.group))) {
+ /* group does not exist, create it by name */
+
+ tptr = msgGetInput("14", "What group ID to use for group %s ?", tconf.group);
+ if (tptr && *tptr && ((gid = atoi(tptr)) > 0)) {
+ if ((fptr = fopen(_PATH_GROUP,"a"))) {
+ fprintf(fptr,"%s:*:%d:%s\n",tconf.group,gid,FTP_NAME);
+ fclose(fptr);
+ }
+ }
+ else
+ gid = FTP_GID;
+ }
+ else
+ gid = tgrp->gr_gid;
+ }
+ else if (!getgrgid(gid)) {
+ /* group does not exist, create it by number */
+
+ tptr = msgGetInput("14", "What group name to use for gid %d ?", gid);
+ if (tptr && *tptr) {
+ strcpy(tconf.group, tptr);
+ if ((tgrp = getgrnam(tconf.group))) {
+ gid = tgrp->gr_gid;
+ }
+ else if ((fptr = fopen(_PATH_GROUP,"a"))) {
+ fprintf(fptr,"%s:*:%d:%s\n",tconf.group,gid,FTP_NAME);
+ fclose(fptr);
+ }
+ }
+ }
+
+ if ((tpw = getpwnam(FTP_NAME))) {
+ if (tpw->pw_uid != FTP_UID)
+ msgConfirm("FTP user already exists with a different uid.");
+
+ return (RET_SUCCESS); /* succeeds if already exists */
+ }
+
+ sprintf(pwline, "%s::%s:%d::0:0:%s:%s:/bin/date\n", FTP_NAME, tconf.uid, gid, tconf.comment, tconf.homedir);
+
+ fptr = fopen(_PATH_MASTERPASSWD,"a");
+ if (! fptr) {
+ msgConfirm("Could not open master password file.");
+ return (RET_FAIL);
+ }
+ fprintf(fptr, pwline);
+ fclose(fptr);
+ msgNotify("Remaking password file: %s", _PATH_MASTERPASSWD);
+ vsystem("pwd_mkdb -p %s", _PATH_MASTERPASSWD);
+
+ return (RET_SUCCESS);
+}
+
+/* This is it - how to get the setup values */
+int
+anonftpOpenDialog()
+{
+ WINDOW *ds_win;
+ ComposeObj *obj = NULL;
+ ComposeObj *first, *last;
+ int n=0, quit=FALSE, cancel=FALSE, ret;
+ int max;
+ char help[FILENAME_MAX];
+ char title[80];
+
+ /* We need a curses window */
+ ds_win = newwin(LINES, COLS, 0, 0);
+ if (ds_win == 0)
+ {
+ beep();
+ msgConfirm("Cannot open anonymous ftp dialog window!!");
+ return(RET_SUCCESS);
+ }
+
+ /* Say where our help comes from */
+ systemHelpFile(ANONFTP_HELPFILE, help);
+ use_helpfile(help);
+
+ /* Setup a nice screen for us to splat stuff onto */
+ draw_box(ds_win, ANONFTP_DIALOG_Y, ANONFTP_DIALOG_X, ANONFTP_DIALOG_HEIGHT, ANONFTP_DIALOG_WIDTH, dialog_attr, border_attr);
+ wattrset(ds_win, dialog_attr);
+ mvwaddstr(ds_win, ANONFTP_DIALOG_Y, ANONFTP_DIALOG_X + 20, " Anonymous FTP Configuration ");
+
+ draw_box(ds_win, ANONFTP_DIALOG_Y + 7, ANONFTP_DIALOG_X + 8, ANONFTP_DIALOG_HEIGHT - 11, ANONFTP_DIALOG_WIDTH - 17,
+ dialog_attr, border_attr);
+ wattrset(ds_win, dialog_attr);
+ sprintf(title, " Path Configuration ");
+ mvwaddstr(ds_win, ANONFTP_DIALOG_Y + 7, ANONFTP_DIALOG_X + 22, title);
+
+ /** Initialize the config Data Structure **/
+
+ bzero(&tconf, sizeof(tconf));
+
+ strcpy(tconf.group, FTP_GROUP);
+ strcpy(tconf.upload, FTP_UPLOAD);
+ strcpy(tconf.comment, FTP_COMMENT);
+ strcpy(tconf.homedir, FTP_HOMEDIR);
+ sprintf(tconf.uid, "%d", FTP_UID);
+
+ /* Loop over the layout list, create the objects, and add them
+ onto the chain of objects that dialog uses for traversal*/
+
+ n = 0;
+#define lt layout[n]
+
+ while (lt.help != NULL) {
+ switch (lt.type) {
+ case STRINGOBJ:
+ lt.obj = NewStringObj(ds_win, lt.prompt, lt.var,
+ lt.y + ANONFTP_DIALOG_Y, lt.x + ANONFTP_DIALOG_X,
+ lt.len, lt.maxlen);
+ break;
+
+ case BUTTONOBJ:
+ lt.obj = NewButtonObj(ds_win, lt.prompt, lt.var,
+ lt.y + ANONFTP_DIALOG_Y, lt.x + ANONFTP_DIALOG_X);
+ break;
+
+ default:
+ msgFatal("Don't support this object yet!");
+ }
+ AddObj(&obj, lt.type, (void *) lt.obj);
+ n++;
+ }
+ max = n - 1;
+
+ /* Find the last object we can traverse to */
+ last = obj;
+ while (last->next)
+ last = last->next;
+
+ /* Find the first object in the list */
+ first = obj;
+ while (first->prev)
+ first = first->prev;
+
+ /* Some more initialisation before we go into the main input loop */
+ n = 0;
+ cancelbutton = 0;
+ cancel = FALSE;
+ okbutton = 0;
+
+ /* Incoming user data - DUCK! */
+ while (!quit) {
+ char help_line[80];
+ int i, len = strlen(lt.help);
+
+ /* Display the help line at the bottom of the screen */
+ for (i = 0; i < 79; i++)
+ help_line[i] = (i < len) ? lt.help[i] : ' ';
+ help_line[i] = '\0';
+ use_helpline(help_line);
+ display_helpline(ds_win, LINES - 1, COLS - 1);
+
+ /* Ask for libdialog to do its stuff */
+ ret = PollObj(&obj);
+
+ /* Handle special case stuff that libdialog misses. Sigh */
+ switch (ret) {
+ /* Bail out */
+ case SEL_ESC:
+ quit = TRUE, cancel=TRUE;
+ break;
+
+ /* This doesn't work for list dialogs. Oh well. Perhaps
+ should special case the move from the OK button ``up''
+ to make it go to the interface list, but then it gets
+ awkward for the user to go back and correct screw up's
+ in the per-interface section */
+
+ case KEY_UP:
+ if (obj->prev !=NULL ) {
+ obj = obj->prev;
+ --n;
+ } else {
+ obj = last;
+ n = max;
+ }
+ break;
+
+ case KEY_DOWN:
+ if (obj->next != NULL) {
+ obj = obj->next;
+ ++n;
+ } else {
+ obj = first;
+ n = 0;
+ }
+ break;
+
+ case SEL_TAB:
+ if (n < max)
+ ++n;
+ else
+ n = 0;
+ break;
+
+ /* The user has pressed enter over a button object */
+ case SEL_BUTTON:
+ quit = TRUE;
+ if (cancelbutton)
+ cancel = TRUE;
+ break;
+
+ /* Generic CR handler */
+ case SEL_CR:
+ if (n < max)
+ ++n;
+ else
+ n = 0;
+ break;
+
+ case SEL_BACKTAB:
+ if (n)
+ --n;
+ else
+ n = max;
+ break;
+
+ case KEY_F(1):
+ display_helpfile();
+
+ /* They tried some key combination we don't support - tell them! */
+ default:
+ beep();
+ }
+
+ }
+
+ /* Clear this crap off the screen */
+ dialog_clear();
+ refresh();
+ use_helpfile(NULL);
+
+ if (cancel)
+ return RET_FAIL;
+ return RET_SUCCESS;
+}
+
+int
+configAnonFTP(char *unused)
+{
+ int i;
+
+ /* Be optimistic */
+ i = RET_SUCCESS;
+
+ dialog_clear();
+ i = anonftpOpenDialog();
+ if (i != RET_SUCCESS) {
+ dialog_clear();
+ msgConfirm("Configuration of Anonymous FTP cancelled per user request.");
+ return i;
+ }
+
+ /*** Use defaults for any invalid values ***/
+ if (atoi(tconf.uid) <= 0)
+ sprintf(tconf.uid, "%d", FTP_UID);
+
+ if (!tconf.group[0])
+ strcpy(tconf.group, FTP_GROUP);
+
+ if (!tconf.upload[0])
+ strcpy(tconf.upload, FTP_UPLOAD);
+
+ /*** If the user did not specify a directory, use default ***/
+
+ if (tconf.homedir[strlen(tconf.homedir)-1] == '/')
+ tconf.homedir[strlen(tconf.homedir)-1] = '\0';
+
+ if (!tconf.homedir[0])
+ strcpy(tconf.homedir, FTP_HOMEDIR);
+
+ /*** If HomeDir does not exist, create it ***/
+
+ if (!directoryExists(tconf.homedir)) {
+ vsystem("mkdir -p %s" ,tconf.homedir);
+ }
+
+ if (directoryExists(tconf.homedir)) {
+ msgNotify("Configuring %s for use by anon FTP.", tconf.homedir);
+ vsystem("chmod 555 %s && chown root.%s %s", tconf.homedir, tconf.group, tconf.homedir);
+ vsystem("mkdir %s/bin && chmod 555 %s/bin", tconf.homedir, tconf.homedir);
+ vsystem("cp /bin/ls %s/bin && chmod 111 %s/bin/ls", tconf.homedir, tconf.homedir);
+ vsystem("cp /bin/date %s/bin && chmod 111 %s/bin/date", tconf.homedir, tconf.homedir);
+ vsystem("mkdir %s/etc && chmod 555 %s/etc", tconf.homedir, tconf.homedir);
+ vsystem("mkdir -p %s/pub", tconf.homedir);
+ vsystem("mkdir -p %s/%s", tconf.homedir, tconf.upload);
+ vsystem("chmod 1777 %s/%s", tconf.homedir, tconf.upload);
+
+ if (createFtpUser() == RET_SUCCESS) {
+ msgNotify("Copying password information for anon FTP.");
+ vsystem("cp /etc/pwd.db %s/etc && chmod 444 %s/etc/pwd.db", tconf.homedir, tconf.homedir);
+ vsystem("cp /etc/passwd %s/etc && chmod 444 %s/etc/passwd",tconf.homedir, tconf.homedir);
+ vsystem("cp /etc/group %s/etc && chmod 444 %s/etc/group", tconf.homedir, tconf.homedir);
+ vsystem("chown -R %s.%s %s/pub", FTP_NAME, tconf.group, tconf.homedir);
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Unable to create FTP user! Anonymous FTP setup failed.");
+ i = RET_FAIL;
+ }
+
+ dialog_clear();
+ if (!msgYesNo("Create a welcome message file for anonymous FTP users?")) {
+ char cmd[256];
+
+ dialog_clear();
+ msgNotify("Uncompressing the editor - please wait..");
+ vsystem("echo Your welcome message here. > %s/etc/%s", tconf.homedir, MOTD_FILE);
+ sprintf(cmd, "/stand/ee %s/etc/%s", tconf.homedir, MOTD_FILE);
+ systemExecute(cmd);
+ }
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Invalid Directory: %s\n"
+ "Anonymous FTP will not be set up.", tconf.homedir);
+ i = RET_FAIL;
+ }
+ return i;
+}
diff --git a/release/sysinstall/apache.c b/release/sysinstall/apache.c
new file mode 100644
index 0000000000000..9e2c80b1f3c2e
--- /dev/null
+++ b/release/sysinstall/apache.c
@@ -0,0 +1,604 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last program in the `sysinstall' line - the next
+ * generation being essentially a complete rewrite.
+ *
+ * $Id: apache.c,v 1.11 1995/11/05 01:00:27 jkh Exp $
+ *
+ * Copyright (c) 1995
+ * Coranth Gryphon. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Coranth Gryphon
+ * for the FreeBSD Project.
+ * 4. The name of Coranth Gryphon or the FreeBSD project may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CORANTH GRYPHON ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CORANTH GRYPHON OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <string.h>
+#include <dialog.h>
+#include "ui_objects.h"
+#include "dir.h"
+#include "dialog.priv.h"
+#include "colors.h"
+#include "sysinstall.h"
+
+#define APACHE_HELPFILE "apache"
+#define APACHE_PACKAGE "apache-0.8.14"
+#define FREEBSD_GIF "/stand/power.gif"
+
+/* These change if the package uses different defaults */
+
+#define APACHE_BASE "/usr/local/www"
+#define DATA_SUBDIR "data"
+#define CONFIG_SUBDIR "config"
+
+/* Set up the structure to hold configuration information */
+/* Note that this is only what we could fit onto the one screen */
+
+typedef struct
+{
+ char docroot[128]; /* DocumentRoot */
+ char userdir[128]; /* UserDir */
+ char welcome[32]; /* Welcome Doc */
+ char email[64]; /* ServerAdmin */
+ char hostname[64]; /* ServerName */
+ char user[32]; /* User */
+ char group[32]; /* Group */
+ char maxcon[8]; /* Max Connections */
+} ApacheConf;
+
+static ApacheConf tconf;
+
+#define APACHE_DOCROOT_LEN 128
+#define APACHE_USERDIR_LEN 128
+#define APACHE_WELCOME_LEN 32
+#define APACHE_EMAIL_LEN 64
+#define APACHE_HOSTNAME_LEN 64
+#define APACHE_USER_LEN 32
+#define APACHE_GROUP_LEN 32
+#define APACHE_MAXCON_LEN 8
+
+static int okbutton, cancelbutton;
+
+/* What the screen size is meant to be */
+#define APACHE_DIALOG_Y 0
+#define APACHE_DIALOG_X 8
+#define APACHE_DIALOG_WIDTH COLS - 16
+#define APACHE_DIALOG_HEIGHT LINES - 2
+
+/* The screen layout structure */
+typedef struct _layout {
+ int y; /* x & Y co-ordinates */
+ int x;
+ int len; /* The size of the dialog on the screen */
+ int maxlen; /* How much the user can type in ... */
+ char *prompt; /* The string for the prompt */
+ char *help; /* The display for the help line */
+ void *var; /* The var to set when this changes */
+ int type; /* The type of the dialog to create */
+ void *obj; /* The obj pointer returned by libdialog */
+} Layout;
+
+static Layout layout[] = {
+{ 1, 2, 24, HOSTNAME_FIELD_LEN - 1,
+ "Host Name:",
+ "What name to report this host as to client browsers",
+ tconf.hostname, STRINGOBJ, NULL },
+#define LAYOUT_HOSTNAME 0
+
+{ 1, 30, 30, APACHE_EMAIL_LEN - 1,
+ "Email Address:",
+ "The email address of the site maintainer, e.g. webmaster@bar.com",
+ tconf.email, STRINGOBJ, NULL },
+#define LAYOUT_EMAIL 1
+
+{ 5, 3, 15, APACHE_USER_LEN - 1,
+ "Default User:", "Default username for access to web pages",
+ tconf.user, STRINGOBJ, NULL },
+#define LAYOUT_USER 2
+
+{ 5, 22, 15, APACHE_GROUP_LEN - 1,
+ "Default Group:", "Default group name for access to web pages",
+ tconf.group, STRINGOBJ, NULL },
+#define LAYOUT_GROUP 3
+
+{ 5, 46, 13, APACHE_MAXCON_LEN - 1,
+ "Max Connect:", "Maximum number of concurrent http connections",
+ tconf.maxcon, STRINGOBJ, NULL },
+#define LAYOUT_MAXCON 4
+
+{ 10, 10, 43, APACHE_DOCROOT_LEN - 1,
+ "Root Document Path:",
+ "The top directory that holds the system web pages",
+ tconf.docroot, STRINGOBJ, NULL },
+#define LAYOUT_DOCROOT 5
+
+{ 14, 10, 18, APACHE_USERDIR_LEN - 1,
+ "User Directory:",
+ "Personal sub-directory that holds users' web pages (eg. ~/Web)",
+ tconf.userdir, STRINGOBJ, NULL },
+#define LAYOUT_USERDIR 6
+
+{ 14, 35, 18, APACHE_WELCOME_LEN - 1,
+ "Default Document:",
+ "The name of the default document found in each directory",
+ tconf.welcome, STRINGOBJ, NULL },
+#define LAYOUT_WELCOME 7
+
+{ 19, 15, 0, 0,
+ "OK", "Select this if you are happy with these settings",
+ &okbutton, BUTTONOBJ, NULL },
+#define LAYOUT_OKBUTTON 8
+
+{ 19, 35, 0, 0,
+ "CANCEL", "Select this if you wish to cancel this screen",
+ &cancelbutton, BUTTONOBJ, NULL },
+#define LAYOUT_CANCELBUTTON 9
+{ NULL },
+};
+
+DMenu MenuApacheLanguages = {
+DMENU_MULTIPLE_TYPE | DMENU_SELECTION_RETURNS,
+"Apache Languages Menu",
+"This allows you to specify which languages are known by your httpd server.",
+NULL,
+NULL,
+{
+{ "English", "English",
+ DMENU_SET_VARIABLE, "APACHE_English=en", 0, 0 },
+{ "French", "French",
+ DMENU_SET_VARIABLE, "APACHE_French=fr", 0, 0 },
+{ "German", "German",
+ DMENU_SET_VARIABLE, "APACHE_German=de", 0, 0 },
+{ "Italian", "Italian",
+ DMENU_SET_VARIABLE, "APACHE_Italian=it", 0, 0 },
+{ "Japanese", "Japanese",
+ DMENU_SET_VARIABLE, "APACHE_Japanese=jp", 0, 0 },
+{ NULL } },
+};
+
+/* This is it - how to get Apache setup values */
+int
+apacheOpenDialog()
+{
+ WINDOW *ds_win;
+ ComposeObj *obj = NULL;
+ ComposeObj *first, *last;
+ int n=0, quit=FALSE, cancel=FALSE, ret;
+ int max;
+ char *tmp;
+ char help[FILENAME_MAX];
+ char title[80];
+
+ /* We need a curses window */
+ ds_win = newwin(LINES, COLS, 0, 0);
+ if (ds_win == 0)
+ {
+ beep();
+ msgConfirm("Cannot open apache dialog window!!");
+ return(RET_SUCCESS);
+ }
+
+ /* Say where our help comes from */
+ systemHelpFile(APACHE_HELPFILE, help);
+ use_helpfile(help);
+
+ /* Setup a nice screen for us to splat stuff onto */
+ draw_box(ds_win, APACHE_DIALOG_Y, APACHE_DIALOG_X, APACHE_DIALOG_HEIGHT, APACHE_DIALOG_WIDTH, dialog_attr, border_attr);
+ wattrset(ds_win, dialog_attr);
+ mvwaddstr(ds_win, APACHE_DIALOG_Y, APACHE_DIALOG_X + 20, " Apache HTTPD Configuration ");
+
+ draw_box(ds_win, APACHE_DIALOG_Y + 9, APACHE_DIALOG_X + 8, APACHE_DIALOG_HEIGHT - 13, APACHE_DIALOG_WIDTH - 17,
+ dialog_attr, border_attr);
+ wattrset(ds_win, dialog_attr);
+ sprintf(title, " Path Configuration ");
+ mvwaddstr(ds_win, APACHE_DIALOG_Y + 9, APACHE_DIALOG_X + 22, title);
+
+ /** Initialize the config Data Structure **/
+
+ bzero(&tconf, sizeof(tconf));
+
+ tmp = variable_get(VAR_DOMAINNAME);
+ if (tmp)
+ {
+ sprintf(tconf.email, "webmaster@%s", tmp);
+ sprintf(tconf.hostname, "www.%s", tmp);
+ }
+
+ strcpy(tconf.user, "guest");
+ strcpy(tconf.group, "guest");
+ strcpy(tconf.userdir, "public_html");
+ strcpy(tconf.welcome, "index.html");
+ strcpy(tconf.maxcon, "150");
+ sprintf(tconf.docroot, "%s/%s", APACHE_BASE, DATA_SUBDIR);
+
+ /* Loop over the layout list, create the objects, and add them
+ onto the chain of objects that dialog uses for traversal*/
+
+ n = 0;
+#define lt layout[n]
+
+ while (lt.help != NULL) {
+ switch (lt.type) {
+ case STRINGOBJ:
+ lt.obj = NewStringObj(ds_win, lt.prompt, lt.var,
+ lt.y + APACHE_DIALOG_Y, lt.x + APACHE_DIALOG_X,
+ lt.len, lt.maxlen);
+ break;
+
+ case BUTTONOBJ:
+ lt.obj = NewButtonObj(ds_win, lt.prompt, lt.var,
+ lt.y + APACHE_DIALOG_Y, lt.x + APACHE_DIALOG_X);
+ break;
+
+ default:
+ msgFatal("Don't support this object yet!");
+ }
+ AddObj(&obj, lt.type, (void *) lt.obj);
+ n++;
+ }
+ max = n - 1;
+
+ /* Find the last object we can traverse to */
+ last = obj;
+ while (last->next)
+ last = last->next;
+
+ /* Find the first object in the list */
+ first = obj;
+ while (first->prev)
+ first = first->prev;
+
+ /* Some more initialisation before we go into the main input loop */
+ n = 0;
+ cancelbutton = 0;
+ cancel = FALSE;
+ okbutton = 0;
+
+ /* Incoming user data - DUCK! */
+ while (!quit) {
+ char help_line[80];
+ int i, len = strlen(lt.help);
+
+ /* Display the help line at the bottom of the screen */
+ for (i = 0; i < 79; i++)
+ help_line[i] = (i < len) ? lt.help[i] : ' ';
+ help_line[i] = '\0';
+ use_helpline(help_line);
+ display_helpline(ds_win, LINES - 1, COLS - 1);
+
+ /* Ask for libdialog to do its stuff */
+ ret = PollObj(&obj);
+
+
+ /* We are in the Hostname field - calculate the e-mail addr */
+
+ if (n == LAYOUT_HOSTNAME) {
+ if ((tmp = index(tconf.hostname, '.')) != NULL) {
+ sprintf(tconf.email,"webmaster@%s",tmp+1);
+ RefreshStringObj(layout[LAYOUT_EMAIL].obj);
+ }
+ }
+
+ /* Handle special case stuff that libdialog misses. Sigh */
+ switch (ret) {
+ /* Bail out */
+ case SEL_ESC:
+ quit = TRUE, cancel=TRUE;
+ break;
+
+ /* This doesn't work for list dialogs. Oh well. Perhaps
+ should special case the move from the OK button ``up''
+ to make it go to the interface list, but then it gets
+ awkward for the user to go back and correct screw up's
+ in the per-interface section */
+
+ case KEY_UP:
+ if (obj->prev !=NULL ) {
+ obj = obj->prev;
+ --n;
+ } else {
+ obj = last;
+ n = max;
+ }
+ break;
+
+ case KEY_DOWN:
+ if (obj->next != NULL) {
+ obj = obj->next;
+ ++n;
+ } else {
+ obj = first;
+ n = 0;
+ }
+ break;
+
+ case SEL_TAB:
+ if (n < max)
+ ++n;
+ else
+ n = 0;
+ break;
+
+ /* The user has pressed enter over a button object */
+ case SEL_BUTTON:
+ quit = TRUE;
+ if (cancelbutton)
+ cancel = TRUE;
+ break;
+
+ /* Generic CR handler */
+ case SEL_CR:
+ if (n < max)
+ ++n;
+ else
+ n = 0;
+ break;
+
+ case SEL_BACKTAB:
+ if (n)
+ --n;
+ else
+ n = max;
+ break;
+
+ case KEY_F(1):
+ display_helpfile();
+
+ /* They tried some key combination we don't support - tell them! */
+ default:
+ beep();
+ }
+
+ }
+
+ /* Clear this crap off the screen */
+ dialog_clear();
+ refresh();
+ use_helpfile(NULL);
+
+ if (cancel)
+ return RET_FAIL;
+ return RET_SUCCESS;
+}
+
+int
+configApache(char *unused)
+{
+ int i, maxcon;
+ char company[64], file[128];
+ char *tptr;
+ FILE *fptr;
+
+ /* Be optimistic */
+ i = RET_SUCCESS;
+
+ dialog_clear();
+ msgConfirm("Since you elected to install the WEB server, we'll now add the\n"
+ "Apache HTTPD package and set up a few configuration files.");
+ i = package_add(APACHE_PACKAGE);
+ if (i != RET_SUCCESS) {
+ dialog_clear();
+ msgConfirm("Hmmmmm. Looks like we weren't able to fetch the Apache WEB server\n"
+ "package. You may wish to fetch and configure it by hand by looking\n"
+ "in /usr/ports/net/apache (in the ports collection) or looking for the\n"
+ "precompiled apache package in packages/networking/%s.", APACHE_PACKAGE);
+ return (i);
+ }
+
+ i = apacheOpenDialog();
+ if (i != RET_SUCCESS) {
+ dialog_clear();
+ msgConfirm("Configuration of the Apache WEB server was cancelled per\n"
+ "user request.");
+ return i;
+ }
+ /*** Fix defaults for invalid value ***/
+ maxcon = atoi(tconf.maxcon);
+ if (maxcon <= 0)
+ maxcon = 150;
+
+ if (! tconf.group[0])
+ strcpy(tconf.group, "guest");
+ if (! tconf.user[0])
+ strcpy(tconf.user, "nobody");
+
+ if (! tconf.welcome[0])
+ strcpy(tconf.welcome, "index.html");
+ if (! tconf.userdir[0])
+ strcpy(tconf.userdir, "public_html");
+
+ /*** If the user did not specify a directory, use default ***/
+
+ if (tconf.docroot[strlen(tconf.docroot)-1] == '/')
+ tconf.docroot[strlen(tconf.docroot)-1] = '\0';
+
+ if (!tconf.docroot[0])
+ sprintf(tconf.docroot,"%s/%s",APACHE_BASE, DATA_SUBDIR);
+
+ /*** If DocRoot does not exist, create it ***/
+
+ if (!directoryExists(tconf.docroot))
+ vsystem("mkdir -p %s", tconf.docroot);
+
+ if (directoryExists(tconf.docroot))
+ {
+ sprintf(file,"%s/index.html", tconf.docroot);
+ if (!file_readable(file))
+ {
+ dialog_clear();
+ tptr = msgGetInput(NULL,
+ "What is your company name?");
+ if (tptr && strlen(tptr))
+ strcpy(company, tptr);
+ else
+ strcpy(company, "our Web Page");
+
+ msgNotify("Creating sample web page...");
+ fptr = fopen(file,"w");
+ if (fptr)
+ {
+ fprintf(fptr,"<CENTER>\n<TITLE>Welcome Page</TITLE>\n");
+ fprintf(fptr,"<H1>Welcome to %s </H1>\n</CENTER>\n",company);
+ fprintf(fptr,"<P><HR SIZE=4>\n<CENTER>\n");
+ fprintf(fptr,"<A HREF=\"http://www.FreeBSD.org/What\">\n");
+ fprintf(fptr,"<IMG SRC=\"./power.gif\" ALIGN=CENTER BORDER=0 ");
+ fprintf(fptr," ALT=\"Powered by FreeBSD\"></A>\n");
+ if (! tconf.email[0])
+ {
+ if ((tptr = variable_get(VAR_DOMAINNAME)))
+ sprintf(tconf.email,"root@%s",tptr);
+ }
+ if (tconf.email[0])
+ {
+ fprintf(fptr,"<ADDRESS><H4>\n");
+ fprintf(fptr," For questions or comments, please send mail to:\n");
+ fprintf(fptr," <A HREF=\"mailto:%s\">%s</A>\n",
+ tconf.email, tconf.email);
+ fprintf(fptr,"</H4></ADDRESS>\n");
+ }
+ fprintf(fptr,"</CENTER>\n\n");
+ fclose(fptr);
+ if (file_readable(FREEBSD_GIF))
+ vsystem("cp %s %s", FREEBSD_GIF, tconf.docroot);
+ }
+ else {
+ msgConfirm("Unable to create sample Web Page.");
+ i = RET_FAIL;
+ }
+ }
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Unable to create Document Root Directory.");
+ i = RET_FAIL;
+ }
+
+ msgNotify("Writing configuration files....");
+
+ (void)vsystem("mkdir -p %s/config", APACHE_BASE);
+ sprintf(file, "%s/%s/access.conf", APACHE_BASE,CONFIG_SUBDIR);
+ if (file_readable(file))
+ vsystem("mv -f %s %s.ORIG", file, file);
+
+ fptr = fopen(file,"w");
+ if (fptr)
+ {
+ fprintf(fptr,"<Directory %s/cgi-bin>\n", APACHE_BASE);
+ fprintf(fptr,"Options Indexes FollowSymLinks\n</Directory>\n\n");
+ fprintf(fptr,"<Directory %s>\n", tconf.docroot);
+ fprintf(fptr,"Options Indexes FollowSymLinks\nAllowOverride All\n");
+ fprintf(fptr,"</Directory>\n\n");
+ fclose(fptr);
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Could not create %s",file);
+ i = RET_FAIL;
+ }
+
+ sprintf(file, "%s/%s/httpd.conf", APACHE_BASE,CONFIG_SUBDIR);
+ if (file_readable(file))
+ vsystem("mv -f %s %s.ORIG", file, file);
+
+ fptr = fopen(file,"w");
+ if (fptr)
+ {
+ fprintf(fptr,"ServerType standalone\nPort 80\nTimeOut 400\n");
+ fprintf(fptr,"ErrorLog logs/error_log\nTransferLog logs/access_log\n");
+ fprintf(fptr,"PidFile /var/run/httpd.pid\n\nStartServers 5\n");
+ fprintf(fptr,"MinSpareServers 5\nMaxSpareServers 10\n");
+ fprintf(fptr,"MaxRequestsPerChild 30\nMaxClients %d\n\n",maxcon);
+ fprintf(fptr,"User %s\nGroup %s\n\n",tconf.user,tconf.group);
+
+ if (tconf.email[0])
+ fprintf(fptr,"ServerAdmin %s\n",tconf.email);
+ if (tconf.hostname[0])
+ fprintf(fptr,"ServerName %s\n",tconf.hostname);
+
+ fclose(fptr);
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Could not create %s",file);
+ i = RET_FAIL;
+ }
+
+ sprintf(file, "%s/%s/srm.conf", APACHE_BASE,CONFIG_SUBDIR);
+ if (file_readable(file))
+ vsystem("mv -f %s %s.ORIG", file, file);
+ fptr = fopen(file,"w");
+ if (fptr)
+ {
+ fprintf(fptr,"FancyIndexing on\nDefaultType text/plain\n");
+ fprintf(fptr,"IndexIgnore */.??* *~ *# */HEADER* */README* */RCS\n");
+ fprintf(fptr,"HeaderName HEADER\nReadmeName README\n");
+ fprintf(fptr,"AccessFileName .htaccess\n\n");
+ fprintf(fptr,"AddEncoding x-compress Z\nAddEncoding x-gzip gz\n");
+ fprintf(fptr,"DefaultIcon /icons/unknown.gif\n\n");
+ fprintf(fptr,
+ "AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip\n");
+ fprintf(fptr,"AddIconByType (TXT,/icons/text.gif) text/*\n");
+ fprintf(fptr,"AddIconByType (IMG,/icons/image2.gif) image/*\n");
+ fprintf(fptr,"AddIconByType (SND,/icons/sound2.gif) audio/*\n");
+ fprintf(fptr,"AddIconByType (VID,/icons/movie.gif) video/*\n\n");
+
+ fprintf(fptr,"AddIcon /icons/text.gif .ps .shtml\n");
+ fprintf(fptr,"AddIcon /icons/movie.gif .mpg .qt\n");
+ fprintf(fptr,"AddIcon /icons/binary.gif .bin\n");
+ fprintf(fptr,"AddIcon /icons/burst.gif .wrl\n");
+ fprintf(fptr,"AddIcon /icons/binhex.gif .hqx .sit\n");
+ fprintf(fptr,"AddIcon /icons/uu.gif .uu\n");
+ fprintf(fptr,"AddIcon /icons/tar.gif .tar\n");
+ fprintf(fptr,"AddIcon /icons/back.gif ..\n");
+ fprintf(fptr,"AddIcon /icons/dir.gif ^^DIRECTORY^^\n");
+ fprintf(fptr,"AddIcon /icons/blank.gif ^^BLANKICON^^\n\n");
+
+ fprintf(fptr,"ScriptAlias /cgi_bin/ %s/cgi_bin/\n",APACHE_BASE);
+ fprintf(fptr,"Alias /icons/ %s/icons/\n",APACHE_BASE);
+ fprintf(fptr,"DocumentRoot %s\n",tconf.docroot);
+ fprintf(fptr,"UserDir %s\nDirectoryIndex %s\n\n", tconf.userdir,
+ tconf.welcome);
+
+ fclose(fptr);
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Could not create %s",file);
+ i = RET_FAIL;
+ }
+ if (i != RET_FAIL)
+ variable_set2("apache_httpd", "YES");
+ return i;
+}
diff --git a/release/sysinstall/doc.c b/release/sysinstall/doc.c
new file mode 100644
index 0000000000000..187362ddc64d8
--- /dev/null
+++ b/release/sysinstall/doc.c
@@ -0,0 +1,100 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last program in the `sysinstall' line - the next
+ * generation being essentially a complete rewrite.
+ *
+ * $Id: doc.c,v 1.9 1995/11/04 08:47:22 jkh Exp $
+ *
+ * Jordan Hubbard
+ *
+ * My contributions are in the public domain.
+ *
+ */
+
+#include "sysinstall.h"
+
+/*
+ * This is called from the main menu. Try to find a copy of Lynx from somewhere
+ * and fire it up on the first copy of the handbook we can find.
+ */
+int
+docBrowser(char *junk)
+{
+ char *browser = variable_get(VAR_BROWSER_PACKAGE);
+
+ if (RunningAsInit && !strstr(variable_get(SYSTEM_STATE), "install")) {
+ msgConfirm("This option may only be used after the system is installed, sorry!");
+ return RET_FAIL;
+ }
+
+ /* Make sure we have media available */
+ if (!mediaVerify())
+ return RET_FAIL;
+
+ /* First, make sure we have whatever browser we've chosen is here */
+ if (package_add(browser) != RET_SUCCESS) {
+ dialog_clear();
+ msgConfirm("Unable to install the %s HTML browser package. You may\n"
+ "wish to verify that your media is configured correctly and\n"
+ "try again.", browser);
+ return RET_FAIL;
+ }
+ if (!file_executable(variable_get(VAR_BROWSER_BINARY))) {
+ dialog_clear();
+ if (!msgYesNo("Hmmm. The %s package claims to have installed, but I can't\n"
+ "find its binary in %s! You may wish to try a different\n"
+ "location to load the package from (go to Media menu) and see if that\n"
+ "makes a difference.\n\n"
+ "I suggest that we remove the version that was extracted since it does\n"
+ "not appear to be correct. Would you like me to do that now?"))
+ vsystem("pkg_delete %s %s", !strcmp(variable_get(VAR_CPIO_VERBOSITY), "high") ? "-v" : "", browser);
+ return RET_FAIL;
+ }
+
+ /* Run browser on the appropriate doc */
+ dmenuOpenSimple(&MenuHTMLDoc);
+ return RET_SUCCESS;
+}
+
+/* Try to show one of the documents requested from the HTML doc menu */
+int
+docShowDocument(char *str)
+{
+ char tmp[512], target[512];
+ char *where = NULL;
+ char *browser = variable_get(VAR_BROWSER_BINARY);
+
+ if (!file_executable(browser)) {
+ dialog_clear();
+ msgConfirm("Can't find the browser in %s! Please ensure that it's\n"
+ "properly set in the Options editor.", browser);
+ return RET_FAIL;
+ }
+ if (!strcmp(str, "Home"))
+ where = "http://www.freebsd.org";
+ else if (!strcmp(str, "Other"))
+ where = msgGetInput("http://www.freebsd.org", "Please enter the URL of the location you wish to visit.");
+ else if (!strcmp(str, "FAQ")) {
+ strcpy(target, "/usr/share/doc/FAQ/freebsd-faq.html");
+ if (!file_readable(target))
+ strcpy(target, "http://www.freebsd.org/FAQ");
+ where = target;
+ }
+ else if (!strcmp(str, "Handbook")) {
+ strcpy(target, "/usr/share/doc/handbook/handbook.html");
+ if (!file_readable(target))
+ strcpy(target, "http://www.freebsd.org/handbook");
+ where = target;
+ }
+ if (where) {
+ sprintf(tmp, "%s %s", browser, where);
+ systemExecute(tmp);
+ return RET_SUCCESS;
+ }
+ else {
+ msgConfirm("Hmmmmm! I can't seem to access the documentation you selected!\n"
+ "Have you loaded the bin distribution? Is your network connected?");
+ return RET_FAIL;
+ }
+}
diff --git a/release/sysinstall/freebsd.cfg b/release/sysinstall/freebsd.cfg
new file mode 100644
index 0000000000000..4652d1fc03ad9
--- /dev/null
+++ b/release/sysinstall/freebsd.cfg
@@ -0,0 +1,58 @@
+# This is the installation configuration file for my laptop, fat.cdrom.com.
+# It is included here merely as a sort-of-documented example.
+
+# Turn on extra debugging.
+debug=yes
+
+# My host specific data
+hostname=fat.cdrom.com
+domainname=cdrom.com
+nameserver=192.216.222.3
+defaultrouter=192.216.222.225
+ipaddr=192.216.222.227
+netmask=255.255.255.240
+
+# Which installation device to use - ftp is pointed directly at my local
+# machine and the installation device is my PC CARD ethernet interface.
+# the "script" keyword lets mediaSetFTP know that it's being run from
+# a script and shouldn't prompt the user for extra details. If you *want*
+# it to prompt, you can pass it either "express", "novice" or "custom"
+# to set the level of detail for such prompting. This is a general convention
+# which you'll see elsewhere in this script file.
+ftp=ftp://time.cdrom.com/pub
+mediaSetFTP=script
+tcpInstallDevice=ze0
+
+# Select which distributions we want.
+distSetUser
+
+# Now set the parameters for the partition editor. Set to use all remaining
+# free space (could also be "all" or "existing" to use all the disk or an
+# existing FreeBSD slice). Pass the script parameter to diskPartitionEditor
+# so it's not interactive, as described above.
+disk=wd0
+diskSpace=free
+bootManager=booteasy
+diskPartitionEditor=script
+
+# It's bogus that we have to re-enter the label editor for each partition
+# we want to create, but it was easier to do it this way (from a programming
+# standpoint, not a user standpoint!). This assumes that slice 1 is a DOS
+# partition and mounts it as /dos, which is the case on my laptop.
+# We can also create a root partition of 20MB in size on the same pass since
+# it's in a different slice (s2). All sizes are expressed in 512 byte blocks!
+wd0s1=/dos N
+wd0s2=partition 40960 /
+diskLabelEditor=script
+
+# Now make a 20MB swap partition in the second slice.
+wd0s2=swap 40960 none
+diskLabelEditor=script
+
+# Size of 0 means allocate the rest of the space to /usr
+wd0s2=partition 0 /usr
+diskLabelEditor=script
+
+# OK, everything is set. Do it!
+installCommit=script
+
diff --git a/release/sysinstall/help/anonftp.hlp b/release/sysinstall/help/anonftp.hlp
new file mode 100644
index 0000000000000..e90985e235fe3
--- /dev/null
+++ b/release/sysinstall/help/anonftp.hlp
@@ -0,0 +1,19 @@
+This screen allows you to configure the anonymous FTP user.
+
+The following configuration values are editable:
+
+UID: The user ID you wish to assign to the anonymous FTP user.
+ All files uploaded will be owned by this ID.
+
+Group: Which group you wish the anonymous FTP user to be in.
+
+Comment: String describing this user in /etc/passwd
+
+
+FTP Root Directory:
+
+ Where files available for anonymous FTP will be kept.
+
+Upload subdirectory:
+
+ Where files uploaded by anonymous FTP users will go.
diff --git a/release/sysinstall/help/apache.hlp b/release/sysinstall/help/apache.hlp
new file mode 100644
index 0000000000000..3880dddb2ba67
--- /dev/null
+++ b/release/sysinstall/help/apache.hlp
@@ -0,0 +1,51 @@
+There are two sets of options that the Apache HTTP Server needs.
+
+The first set covers how it operates. These are as follows:
+
+ The "HostName" field is the name of this host, as it is
+ reported to each client connection. Normally, the fully
+ qualified domain name of the host running the server is
+ returned. If you want this set to something else, however,
+ (usually "www.my.domain") then this can be entered here.
+
+ Additionally, the server needs to know how many connections
+ are allowed at one time - this is the "Max Connections"
+ field. If more than this number of clients attempt to connect
+ at once, the additional connections will be refused. This is
+ used to limit how much system load will be imposed by the HTTP
+ server.
+
+ The "Email Address" field is the address of the person (or
+ system alias) who is the administrator for this web site. In
+ addition to being used by the Apache Server itself, it is also
+ put at the bottom of the sample web page that is created.
+
+ Finally, the "Default User" and "Default Group" fields specify
+ what user id and group id should be used by the server for
+ remote connections. Local connections are kept as the UID and
+ GID of the local process.
+
+The second set of options determine what information is made available
+to each client:
+
+ The "Document Root Path" is the top of the tree of documents
+ that are made avaliable. For example, if the value is
+ "/usr/web", then the URL "http://www.foo.com/doc.html" would
+ translate as "/usr/web/doc.html".
+
+ Similarly, the "User Directory" is the location in each user's
+ home directory where their public web documents are
+ stored. Thus if the value if this is "Public", then the URL
+ "http://www.foo.com/~joe/doc" would translate to the path
+ "~joe/Public/doc".
+
+ Finally, if the URL points to a directory, there is always a
+ "Default Document" that Apache will use. This field holds the
+ name (not the path) of this document. By default, Apache uses
+ the file "index.html". However, some sites may be more used to
+ using the file "welcome.html".
+
+There are a number of other options that can be configured with
+Apache, such as path aliases, masquerading as multiple hosts, server
+child process parameters, and so forth. For more information on these,
+consult the Apache man pages at http://www.apache.org.
diff --git a/release/sysinstall/help/upgrade.hlp b/release/sysinstall/help/upgrade.hlp
new file mode 100644
index 0000000000000..5cba594a9c9c5
--- /dev/null
+++ b/release/sysinstall/help/upgrade.hlp
@@ -0,0 +1,38 @@
+Welcome to the 2.0.5 -> 2.1 upgrade procedure!
+
+It must first be said that this upgrade DOES NOT take a particularly
+sophisticated approach to the upgrade problem, it being more a question
+of providing what seemed "good enough" at the time. A truly polished
+upgrade that deals properly with the broad spectrum of installed 2.0.5
+systems would be nice to have, but until that gets written what you get is
+this - the brute-force approach!
+
+What this upgrade will attempt to do is best summarized thusly:
+
+ 1. fsck and mount all file systems chosen in the label editor.
+ 2. Ask for a location to preserve your /etc directory into and do so.
+ 3. Extract all selected distributions on top of your existing system.
+ 4. Copy certain obvious files back from the preserved /etc, leaving the
+ rest of the /etc file merge up to the user.
+ 5. Drop user in a shell so that they may perform that merge before
+ rebooting into the new system.
+
+And that's it! This "upgrade" is not going to hold your hand in all
+major respects, it's simply provided to make one PART of the upgrade
+easier.
+
+IMPORTANT NOTE: What this upgrade procedure may also do, in fact, is
+completely destroy your system (though much more quickly than you
+would have been able to destroy it yourself). It is simply impossible
+to guarantee that this procedure's crude form of upgrade automation
+will work in all cases and if you do this upgrade without proper
+BACKUPS for any important data then you really must like living life
+close to the edge, that's all we can say!
+
+NOTE to 2.0 users: We're sorry, but the "slice" changes that were
+added in FreeBSD 2.0.5 made automated upgrades pretty difficult due to
+the fact that a complete reinstall is pretty much called for. Things
+may still *work* after a 2.1 upgrade, but you will also no doubt
+receive many warnings at boot time about non-aligned slices and such;
+we really do recommend a fresh installation for 2.0 systems! (But
+back up your user data first :-).
diff --git a/release/sysinstall/index.c b/release/sysinstall/index.c
new file mode 100644
index 0000000000000..6198a5eaf1eda
--- /dev/null
+++ b/release/sysinstall/index.c
@@ -0,0 +1,569 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last program in the `sysinstall' line - the next
+ * generation being essentially a complete rewrite.
+ *
+ * $Id: index.c,v 1.19 1995/11/06 22:26:28 jkh Exp $
+ *
+ * Copyright (c) 1995
+ * Jordan Hubbard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jordan Hubbard
+ * for the FreeBSD Project.
+ * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ncurses.h>
+#include <dialog.h>
+#include "sysinstall.h"
+
+/* Macros and magic values */
+#define MAX_MENU 13
+#define _MAX_DESC 62
+
+/* Smarter strdup */
+inline char *
+_strdup(char *ptr)
+{
+ return ptr ? strdup(ptr) : NULL;
+}
+
+static char *descrs[] = {
+ "Package Selection", "To mark a package or select a category, move to it and press SPACE.\n"
+ "To unmark a package, press SPACE again. When you want to commit your\n"
+ "marks, press [ENTER]. To go to a previous menu, select UP item or Cancel.\n"
+ "To search for a package by name, press ESC. To extract packages, you\n"
+ "should Cancel all the way out of any submenus and finally this menu.",
+ "Package Targets", "These are the packages you've selected for extraction.\n\n"
+ "If you're sure of these choices, select OK.\n"
+ "If not, select Cancel to go back to the package selection menu.\n",
+ "All", "All available packages in all categories.",
+ "applications", "User application software.",
+ "archivers", "Utilities for archiving and unarchiving data.",
+ "audio", "Audio utilities - most require a supported sound card.",
+ "benchmarks", "Utilities for measuring system performance.",
+ "benchmarking", "Utilities for measuring system performance.",
+ "cad", "Computer Aided Design utilities.",
+ "comms", "Communications utilities.",
+ "databases", "Database software.",
+ "devel", "Software development utilities and libraries.",
+ "development", "Software development utilities and libraries.",
+ "documentation", "Document preparation utilities.",
+ "editors", "Common text editors.",
+ "emulation", "Utilities for emulating other OS types.",
+ "emulators", "Utilities for emulating other OS types.",
+ "games", "Various and sundry amusements.",
+ "graphics", "Graphics libraries and utilities.",
+ "japanese", "Ported software for the Japanese market.",
+ "lang", "Computer languages.",
+ "languages", "Computer languages.",
+ "libraries", "Software development libraries.",
+ "mail", "Electronic mail packages and utilities.",
+ "math", "Mathematical computation software.",
+ "net", "Networking utilities.",
+ "networking", "Networking utilities.",
+ "news", "USENET News support software.",
+ "numeric", "Mathematical computation software.",
+ "orphans", "Packages without a home elsewhere.",
+ "plan9", "Software from the plan9 Operating System.",
+ "print", "Utilities for dealing with printing.",
+ "printing", "Utilities for dealing with printing.",
+ "programming", "Software development utilities and libraries.",
+ "russian", "Ported software for the Russian market.",
+ "security", "System security software.",
+ "shells", "Various shells (tcsh, bash, etc).",
+ "sysutils", "Various system utilities.",
+ "troff", "TROFF Text formatting utilities.",
+ "utils", "Various user utilities.",
+ "utilities", "Various user utilities.",
+ "x11", "X Window System based utilities.",
+ NULL, NULL,
+};
+
+static char *
+fetch_desc(char *name)
+{
+ int i;
+
+ for (i = 0; descrs[i]; i += 2) {
+ if (!strcmp(descrs[i], name))
+ return descrs[i + 1];
+ }
+ return "No description provided";
+}
+
+static PkgNodePtr
+new_pkg_node(char *name, node_type type)
+{
+ PkgNodePtr tmp = safe_malloc(sizeof(PkgNode));
+
+ tmp->name = _strdup(name);
+ tmp->type = type;
+ return tmp;
+}
+
+static IndexEntryPtr
+new_index(char *name, char *pathto, char *prefix, char *comment, char *descr, char *maint)
+{
+ IndexEntryPtr tmp = safe_malloc(sizeof(IndexEntry));
+
+ tmp->name = _strdup(name);
+ tmp->path = _strdup(pathto);
+ tmp->prefix = _strdup(prefix);
+ tmp->comment = _strdup(comment);
+ tmp->descrfile = _strdup(descr);
+ tmp->maintainer = _strdup(maint);
+ return tmp;
+}
+
+static void
+index_register(PkgNodePtr top, char *where, IndexEntryPtr ptr)
+{
+ PkgNodePtr p, q;
+
+ for (q = NULL, p = top->kids; p; p = p->next) {
+ if (!strcmp(p->name, where)) {
+ q = p;
+ break;
+ }
+ }
+ if (!p) {
+ /* Add new category */
+ q = new_pkg_node(where, PLACE);
+ q->desc = fetch_desc(where);
+ q->next = top->kids;
+ top->kids = q;
+ }
+ p = new_pkg_node(ptr->name, PACKAGE);
+ p->desc = ptr->comment;
+ p->data = ptr;
+ p->next = q->kids;
+ q->kids = p;
+}
+
+static int
+copy_to_sep(char *to, char *from, int sep)
+{
+ char *tok;
+
+ tok = strchr(from, sep);
+ if (!tok) {
+ fprintf(stderr, "missing '%c' token.\n", sep);
+ *to = '\0';
+ return 0;
+ }
+ *tok = '\0';
+ strcpy(to, from);
+ return tok + 1 - from;
+}
+
+static int
+readline(int fd, char *buf, int max)
+{
+ int rv, i = 0;
+ char ch;
+
+ while ((rv = read(fd, &ch, 1)) == 1 && ch != '\n' && i < max)
+ buf[i++] = ch;
+ if (i < max)
+ buf[i] = '\0';
+ return rv;
+}
+
+int
+index_parse(int fd, char *name, char *pathto, char *prefix, char *comment, char *descr, char *maint,
+ char *cats, char *keys)
+{
+ char line[1024];
+ char *cp;
+ int i;
+
+ i = readline(fd, line, 1024);
+ if (i <= 0)
+ return EOF;
+ cp = line;
+ cp += copy_to_sep(name, cp, '|');
+ cp += copy_to_sep(pathto, cp, '|');
+ cp += copy_to_sep(prefix, cp, '|');
+ cp += copy_to_sep(comment, cp, '|');
+ cp += copy_to_sep(descr, cp, '|');
+ cp += copy_to_sep(maint, cp, '|');
+ cp += copy_to_sep(cats, cp, '|');
+ strcpy(keys, cp);
+ return 0;
+}
+
+int
+index_get(char *fname, PkgNodePtr papa)
+{
+ int i, fd;
+
+ fd = open(fname, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Unable to open index file `%s' for reading.\n", fname);
+ i = -1;
+ }
+ else
+ i = index_read(fd, papa);
+ close(fd);
+ return i;
+}
+
+int
+index_read(int fd, PkgNodePtr papa)
+{
+ char name[127], pathto[255], prefix[255], comment[255], descr[127], maint[127], cats[511], keys[511];
+
+ while (index_parse(fd, name, pathto, prefix, comment, descr, maint, cats, keys) != EOF) {
+ char *cp, *cp2, tmp[511];
+ IndexEntryPtr idx;
+
+ idx = new_index(name, pathto, prefix, comment, descr, maint);
+ /* For now, we only add things to menus if they're in categories. Keywords are ignored */
+ for (cp = strcpy(tmp, cats); (cp2 = strchr(cp, ' ')) != NULL; cp = cp2 + 1) {
+ *cp2 = '\0';
+ index_register(papa, cp, idx);
+ }
+ index_register(papa, cp, idx);
+
+ /* Add to special "All" category */
+ index_register(papa, "All", idx);
+ }
+ return 0;
+}
+
+void
+index_init(PkgNodePtr top, PkgNodePtr plist)
+{
+ top->next = top->kids = NULL;
+ top->name = "Package Selection";
+ top->type = PLACE;
+ top->desc = fetch_desc(top->name);
+ top->data = NULL;
+
+ plist->next = plist->kids = NULL;
+ plist->name = "Package Targets";
+ plist->type = PLACE;
+ plist->desc = fetch_desc(plist->name);
+ plist->data = NULL;
+}
+
+void
+index_entry_free(IndexEntryPtr top)
+{
+ safe_free(top->name);
+ safe_free(top->path);
+ safe_free(top->prefix);
+ safe_free(top->comment);
+ safe_free(top->descrfile);
+ safe_free(top->maintainer);
+ free(top);
+}
+
+void
+index_node_free(PkgNodePtr top, PkgNodePtr plist)
+{
+ PkgNodePtr tmp;
+
+ tmp = plist;
+ while (tmp) {
+ PkgNodePtr tmp2 = tmp->next;
+
+ safe_free(tmp);
+ tmp = tmp2;
+ }
+
+ for (tmp = top; tmp; tmp = tmp->next) {
+ free(tmp->name);
+ if (tmp->type == PACKAGE && tmp->data)
+ index_entry_free((IndexEntryPtr)tmp->data);
+ if (tmp->kids)
+ index_node_free(tmp->kids, NULL);
+ }
+}
+
+void
+index_print(PkgNodePtr top, int level)
+{
+ int i;
+
+ while (top) {
+ for (i = 0; i < level; i++) putchar('\t');
+ printf("name [%s]: %s\n", top->type == PLACE ? "place" : "package", top->name);
+ for (i = 0; i < level; i++) putchar('\t');
+ printf("desc: %s\n", top->desc);
+ if (top->kids)
+ index_print(top->kids, level + 1);
+ top = top->next;
+ }
+}
+
+/* Swap one node for another */
+static void
+swap_nodes(PkgNodePtr a, PkgNodePtr b)
+{
+ PkgNode tmp;
+
+ tmp = *a;
+ *a = *b;
+ a->next = tmp.next;
+ tmp.next = b->next;
+ *b = tmp;
+}
+
+/* Use a disgustingly simplistic bubble sort to put our lists in order */
+void
+index_sort(PkgNodePtr top)
+{
+ PkgNodePtr p, q;
+
+ /* Sort everything at the top level */
+ for (p = top->kids; p; p = p->next) {
+ for (q = top->kids; q; q = q->next) {
+ if (q->next && strcmp(q->name, q->next->name) > 0)
+ swap_nodes(q, q->next);
+ }
+ }
+
+ /* Now sub-sort everything n levels down */
+
+ for (p = top->kids; p; p = p->next) {
+ if (p->kids)
+ index_sort(p);
+ }
+}
+
+/*
+ * No, we don't free n because someone else is still pointing at it.
+ * It's just clone linked from another location, which we're adjusting.
+ */
+void
+index_delete(PkgNodePtr n)
+{
+ if (n->next)
+ *n = *(n->next);
+ else /* Kludgy end sentinal */
+ n->name = NULL;
+}
+
+PkgNodePtr
+index_search(PkgNodePtr top, char *str, PkgNodePtr *tp)
+{
+ PkgNodePtr p, sp;
+
+ for (p = top->kids; p && p->name; p = p->next) {
+ /* Subtract out the All category from searches */
+ if (!strcmp(p->name, "All"))
+ continue;
+
+ /* If tp == NULL, we're looking for an exact package match */
+ if (!tp && !strcmp(p->name, str))
+ return p;
+
+ /* If tp, we're looking for both a package and a pointer to the place it's in */
+ if (tp && strstr(p->name, str)) {
+ *tp = top;
+ return p;
+ }
+
+ /* The usual recursion-out-of-laziness ploy */
+ if (p->kids)
+ if ((sp = index_search(p, str, tp)) != NULL)
+ return sp;
+ }
+ if (p && !p->name)
+ p = NULL;
+ return p;
+}
+
+/* Work function for seeing if name x is in result string y */
+static Boolean
+is_selected_in(char *name, char *result)
+{
+ Boolean ret = FALSE;
+
+ while (*result) {
+ char *cp;
+
+ cp = index(result, '\n');
+ if (!cp) {
+ ret = !strcmp(name, result);
+ break;
+ }
+ else {
+ ret = !strncmp(name, result, cp - result - 1);
+ if (ret)
+ break;
+ }
+ result = cp + 1;
+ }
+ return ret;
+}
+
+int
+index_menu(PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll)
+{
+ int n, rval, maxname;
+ int curr, max;
+ PkgNodePtr sp, kp;
+ char **nitems;
+ char result[4096];
+ Boolean hasPackages;
+
+ hasPackages = FALSE;
+ nitems = NULL;
+
+ n = maxname = 0;
+ /* Figure out if this menu is full of "leaves" or "branches" */
+ for (kp = top->kids; kp && kp->name; kp = kp->next) {
+ int len;
+
+ ++n;
+ if (kp->type == PACKAGE && plist) {
+ hasPackages = TRUE;
+ if ((len = strlen(kp->name)) > maxname)
+ maxname = len;
+ }
+ }
+ if (!n && plist) {
+ dialog_clear();
+ msgConfirm("The %s menu is empty.", top->name);
+ return RET_DONE;
+ }
+
+ dialog_clear();
+ while (1) {
+ n = 0;
+ curr = max = 0;
+ kp = top->kids;
+ if (!hasPackages && kp && kp->name && plist) {
+ nitems = item_add_pair(nitems, "UP", "<RETURN TO PREVIOUS MENU>", &curr, &max);
+ ++n;
+ }
+ while (kp && kp->name) {
+ /* Brutally adjust description to fit in menu */
+ if (strlen(kp->desc) > (_MAX_DESC - maxname))
+ kp->desc[_MAX_DESC - maxname] = '\0';
+ nitems = item_add_pair(nitems, kp->name, kp->desc, &curr, &max);
+ if (hasPackages) {
+ if (kp->type == PACKAGE && plist)
+ nitems = item_add(nitems, index_search(plist, kp->name, NULL) ? "ON" : "OFF", &curr, &max);
+ else
+ nitems = item_add(nitems, "OFF", &curr, &max);
+ }
+ ++n;
+ kp = kp->next;
+ }
+ nitems = item_add(nitems, NULL, &curr, &max);
+
+ if (hasPackages)
+ rval = dialog_checklist(top->name, top->desc, -1, -1, n > MAX_MENU ? MAX_MENU : n, n,
+ (unsigned char **)nitems, result);
+ else /* It's a categories menu */
+ rval = dialog_menu(top->name, top->desc, -1, -1, n > MAX_MENU ? MAX_MENU : n, n,
+ (unsigned char **)nitems, result, pos, scroll);
+ if (!rval && plist && strcmp(result, "UP")) {
+ for (kp = top->kids; kp; kp = kp->next) {
+ if (kp->type == PACKAGE) {
+ sp = index_search(plist, kp->name, NULL);
+ if (is_selected_in(kp->name, result)) {
+ if (!sp) {
+ PkgNodePtr np = (PkgNodePtr)safe_malloc(sizeof(PkgNode));
+
+ *np = *kp;
+ np->next = plist->kids;
+ plist->kids = np;
+ standout();
+ mvprintw(23, 0, "Selected packages were added to selection list\n", kp->name);
+ standend();
+ refresh();
+ }
+ }
+ else if (sp) {
+ standout();
+ mvprintw(23, 0, "Deleting unselected packages from selection list\n", kp->name);
+ standend();
+ refresh();
+ index_delete(sp);
+ }
+ }
+ else if (!strcmp(kp->name, result)) { /* Not a package, must be a directory */
+ int p, s;
+
+ p = s = 0;
+ index_menu(kp, plist, &p, &s);
+ }
+ }
+ }
+ else if (rval == -1 && plist) {
+ static char *cp;
+ PkgNodePtr menu;
+
+ /* Search */
+ if ((cp = msgGetInput(cp, "Search by package name. Please enter search string:")) != NULL) {
+ PkgNodePtr p = index_search(top, cp, &menu);
+
+ if (p) {
+ int pos, scroll;
+
+ /* These need to be set to point at the found item, actually. Hmmm! */
+ pos = scroll = 0;
+ index_menu(menu, plist, &pos, &scroll);
+ }
+ else {
+ msgConfirm("Search string: %s yielded no hits.", cp);
+ }
+ }
+ }
+ else {
+ dialog_clear();
+ items_free(nitems, &curr, &max);
+ return rval ? RET_FAIL : RET_SUCCESS;
+ }
+ }
+}
+
+int
+index_extract(Device *dev, PkgNodePtr plist)
+{
+ PkgNodePtr tmp;
+ int status = RET_SUCCESS;
+
+ for (tmp = plist->kids; tmp; tmp = tmp->next) {
+ if (package_extract(dev, tmp->name) != RET_SUCCESS)
+ status = RET_FAIL;
+ }
+ return status;
+}
diff --git a/release/sysinstall/installFinal.c b/release/sysinstall/installFinal.c
new file mode 100644
index 0000000000000..050e86ed31053
--- /dev/null
+++ b/release/sysinstall/installFinal.c
@@ -0,0 +1,223 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last program in the `sysinstall' line - the next
+ * generation being essentially a complete rewrite.
+ *
+ * $Id: installFinal.c,v 1.20 1995/11/12 11:12:25 jkh Exp $
+ *
+ * Copyright (c) 1995
+ * Jordan Hubbard & Coranth Gryphon. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the authors listed above
+ * for the FreeBSD Project.
+ * 4. The names of the authors or the FreeBSD project may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR THEIR PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "sysinstall.h"
+#include <sys/disklabel.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mount.h>
+
+/* This file contains all the final configuration thingies */
+
+static DMenu MenuSamba = {
+ DMENU_MULTIPLE_TYPE | DMENU_SELECTION_RETURNS,
+ "Samba Services Menu",
+ "This allows you to configure various aspects of your Samba server.",
+ NULL,
+ NULL,
+{ { "Homes", "Make home directories available to users.",
+ DMENU_SET_VARIABLE, "SAMBA_homes=YES", 0, 0, dmenuVarCheck },
+ { "Printers", "Allows for sharing of local printers.",
+ DMENU_SET_VARIABLE, "SAMBA_printers=YES", 0, 0, dmenuVarCheck},
+ { "Export Paths", "Specify local directories to make available.",
+ DMENU_SET_VARIABLE, "SAMBA_export=YES", 0, 0, dmenuVarCheck },
+ { NULL } },
+};
+
+/* These probably shouldn't be hard-coded, but making them options might prove to be even more confusing! */
+#define SMB_CONF "./smb.conf"
+
+
+/* Load gated package */
+int
+configGated(char *unused)
+{
+ if (package_add("gated-3.5a11") == RET_SUCCESS)
+ variable_set2("gated", "YES");
+ return RET_SUCCESS;
+}
+
+/* Load pcnfsd package */
+int
+configPCNFSD(char *unused)
+{
+ if (package_add("pcnfsd-93.02.16") == RET_SUCCESS)
+ variable_set2("pcnfsd", "YES");
+ return RET_SUCCESS;
+}
+
+int
+configSamba(char *unused)
+{
+ int i = RET_SUCCESS;
+
+ if (!dmenuOpenSimple(&MenuSamba))
+ i = RET_FAIL;
+ else if (package_add("samba-1.9.14") != RET_SUCCESS)
+ i = RET_FAIL;
+ else {
+ FILE *fptr;
+ char tbuf[256], *tptr;
+ int tval;
+
+ fptr = fopen("/tmp/smb.conf","w");
+ if (fptr) {
+ strcpy(tbuf,"FreeBSD - Samba %v");
+ if (variable_get("SAMBA_string")) {
+ tptr = msgGetInput("FreeBSD - Samba %%v", "What should this server list as its description?\n"
+ "Note that the \"%%v\" refers to the samba version number.");
+ if (tptr && *tptr)
+ strcpy(tbuf, tptr);
+ }
+
+ fprintf(fptr, "[global]\n");
+ fprintf(fptr, "comment = %s\n", tbuf);
+ fprintf(fptr, "log file = /var/log/samba.log\n");
+ fprintf(fptr, "dont descend = /dev,/proc,/root,/stand\n\n");
+
+ fprintf(fptr, "printing = bsd\n");
+ fprintf(fptr, "map archive = no\n");
+ fprintf(fptr, "status = yes\n");
+ fprintf(fptr, "public = yes\n");
+ fprintf(fptr, "read only = no\n");
+ fprintf(fptr, "preserve case = yes\n");
+ fprintf(fptr, "strip dot = yes\n");
+ fprintf(fptr, "security = share\n");
+ fprintf(fptr, "guest ok = yes\n\n");
+
+ if (variable_get("SAMBA_homes")) {
+ fprintf(fptr, "[homes]\n");
+ fprintf(fptr, "browseable = no\n");
+ fprintf(fptr, "comment = User Home Directory\n");
+ fprintf(fptr, "create mode = 0775\n");
+ fprintf(fptr, "public = no\n\n");
+ }
+
+ if (variable_get("SAMBA_printers")) {
+ fprintf(fptr, "[printers]\n");
+ fprintf(fptr, "path = /var/spool\n");
+ fprintf(fptr, "comment = Printers\n");
+ fprintf(fptr, "create mode = 0700\n");
+ fprintf(fptr, "browseable = no\n");
+ fprintf(fptr, "printable = yes\n");
+ fprintf(fptr, "read only = yes\n");
+ fprintf(fptr, "public = no\n\n");
+ }
+
+ if (variable_get("SAMBA_export")) {
+ for (tval = 0; ! tval; tval = msgYesNo("Another?")) {
+ tptr = msgGetInput(NULL,"What directory to export?");
+ if (tptr && *tptr && (tptr[0] == '/')) {
+ int len = strlen(tbuf);
+
+ strcpy(tbuf, tptr);
+ if (tbuf[len - 1] == '/')
+ tbuf[len - 1] = '\0';
+ if (directoryExists(tbuf)) {
+ tptr = msgGetInput(pathBaseName(tbuf), "What do you want to call this share?");
+ if (tptr && *tptr) {
+ fprintf(fptr, "[%s]\npath = %s\n", tptr, tbuf);
+ tptr = msgGetInput(NULL, "Enter a short description of this share?");
+ if (tptr && *tptr)
+ fprintf(fptr, "comment = %s\n", tptr);
+ if (msgYesNo("Do you want this share to be read only?"))
+ fprintf(fptr, "read only = no\n\n");
+ else
+ fprintf(fptr, "read only = yes\n\n");
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Invalid Share Name.");
+ }
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Directory does not exist.");
+ }
+ } /* end if (tptr) */
+ } /* end for loop */
+ } /* end if (SAMBA_export) */
+ fclose(fptr);
+ vsystem("mv -f /tmp/smb.conf %s", SMB_CONF);
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Unable to open temporary smb.conf file.\n"
+ "Samba will have to be configured by hand.");
+ }
+ }
+ return i;
+}
+
+int
+configNFSServer(char *unused)
+{
+ /* If we're an NFS server, we need an exports file */
+ if (!file_readable("/etc/exports")) {
+ dialog_clear();
+ msgConfirm("Operating as an NFS server means that you must first configure\n"
+ "an /etc/exports file to indicate which hosts are allowed certain\n"
+ "kinds of access to your local file systems.\n"
+ "Press [ENTER] now to invoke an editor on /etc/exports (the editor\n"
+ "may take a little while to uncompress the first time - please be\n"
+ "patient!)");
+ vsystem("echo '#The following examples export /usr to 3 machines named after ducks,' > /etc/exports");
+ vsystem("echo '#/home and all directories under it to machines named after dead rock stars' >> /etc/exports");
+ vsystem("echo '#and, finally, /a to 2 privileged machines allowed to write on it as root.' >> /etc/exports");
+ vsystem("echo '#/usr huey louie dewie' >> /etc/exports");
+ vsystem("echo '#/home -alldirs janice jimmy frank' >> /etc/exports");
+ vsystem("echo '#/a -maproot=0 bill albert' >> /etc/exports");
+ vsystem("echo '#' >> /etc/exports");
+ vsystem("echo '# You should replace these lines with your actual exported filesystems.' >> /etc/exports");
+ vsystem("echo >> /etc/exports");
+ dialog_clear();
+ systemExecute("/stand/ee /etc/exports");
+ }
+ variable_set2("nfs_server", "YES");
+ return RET_SUCCESS;
+}
diff --git a/release/sysinstall/installPreconfig.c b/release/sysinstall/installPreconfig.c
new file mode 100644
index 0000000000000..e5f323223c7ea
--- /dev/null
+++ b/release/sysinstall/installPreconfig.c
@@ -0,0 +1,221 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last program in the `sysinstall' line - the next
+ * generation being essentially a complete rewrite.
+ *
+ * $Id: installPreconfig.c,v 1.16 1995/10/27 17:00:23 jkh Exp $
+ *
+ * Copyright (c) 1995
+ * Jordan Hubbard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jordan Hubbard
+ * for the FreeBSD Project.
+ * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "sysinstall.h"
+#include <ctype.h>
+#include <sys/disklabel.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#define MSDOSFS
+#include <sys/mount.h>
+#undef MSDOSFS
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mount.h>
+
+static struct _word {
+ char *name;
+ int (*handler)(char *str);
+} resWords[] = {
+ { "configAnonFTP", configAnonFTP },
+ { "configApache", configApache },
+ { "configGated", configGated },
+ { "configNFSServer", configNFSServer },
+ { "configSamba", configSamba },
+ { "diskPartitionEditor", diskPartitionEditor },
+ { "diskPartitionWrite", diskPartitionWrite },
+ { "diskLabelEditor", diskLabelEditor },
+ { "diskLabelCommit", diskLabelCommit },
+ { "distReset", distReset },
+ { "distSetCustom", distSetCustom },
+ { "distSetDeveloper", distSetDeveloper },
+ { "distSetXDeveloper", distSetXDeveloper },
+ { "distSetKernDeveloper", distSetKernDeveloper },
+ { "distSetUser", distSetUser },
+ { "distSetXUser", distSetXUser },
+ { "distSetMinimum", distSetMinimum },
+ { "distSetEverything", distSetEverything },
+ { "distSetDES", distSetDES },
+ { "distSetSrc", distSetSrc },
+ { "distSetXF86", distSetXF86 },
+ { "distExtractAll", distExtractAll },
+ { "docBrowser", docBrowser },
+ { "docShowDocument", docShowDocument },
+ { "installCommit", installCommit },
+ { "installExpress", installExpress },
+ { "installUpgrade", installUpgrade },
+ { "installPreconfig", installPreconfig },
+ { "installFixup", installFixup },
+ { "installFilesystems", installFilesystems },
+ { "mediaSetCDROM", mediaSetCDROM },
+ { "mediaSetFloppy", mediaSetFloppy },
+ { "mediaSetDOS", mediaSetDOS },
+ { "mediaSetTape", mediaSetTape },
+ { "mediaSetFTP", mediaSetFTP },
+ { "mediaSetFTPActive", mediaSetFTPActive },
+ { "mediaSetFTPPassive", mediaSetFTPPassive },
+ { "mediaSetUFS", mediaSetUFS },
+ { "mediaSetNFS", mediaSetNFS },
+ { "mediaSetFtpUserPass", mediaSetFtpUserPass },
+ { "mediaSetCPIOVerbosity", mediaSetCPIOVerbosity },
+ { "mediaGetType", mediaGetType },
+ { "msgConfirm", msgSimpleConfirm },
+ { "msgNotify", msgSimpleNotify },
+ { "packageAdd", package_add },
+ { "system", (int (*)(char *))vsystem },
+ { "systemInteractive", systemExecute },
+ { "tcpInstallDevice", tcpInstallDevice },
+ { NULL, NULL },
+};
+
+static int
+call_possible_resword(char *name, char *value, int *status)
+{
+ int i, rval;
+
+ rval = 0;
+ for (i = 0; resWords[i].name; i++) {
+ if (!strcmp(name, resWords[i].name)) {
+ *status = resWords[i].handler(value);
+ rval = 1;
+ break;
+ }
+ }
+ return rval;
+}
+
+/* From the top menu - try to mount the floppy and read a configuration file from it */
+int
+installPreconfig(char *str)
+{
+ struct ufs_args u_args;
+ struct msdosfs_args m_args;
+ int fd, i;
+ char buf[128];
+ char *cfg_file;
+
+ memset(&u_args, 0, sizeof(u_args));
+ u_args.fspec = "/dev/fd0";
+ Mkdir("/mnt2", NULL);
+
+ memset(&m_args, 0, sizeof(m_args));
+ m_args.fspec = "/dev/fd0";
+ m_args.uid = m_args.gid = 0;
+ m_args.mask = 0777;
+
+ i = RET_FAIL;
+ while (1) {
+ if (!(cfg_file = variable_get_value(VAR_CONFIG_FILE,
+ "Please insert the floppy containing this configuration file\n"
+ "into drive A now and press [ENTER].")))
+ break;
+
+ if (mount(MOUNT_UFS, "/mnt2", MNT_RDONLY, (caddr_t)&u_args) == -1) {
+ if (mount(MOUNT_MSDOS, "/mnt2", MNT_RDONLY, (caddr_t)&m_args) == -1) {
+ dialog_clear();
+ if (msgYesNo("Unable to mount the configuration floppy - do you want to try again?"))
+ break;
+ else
+ continue;
+ }
+ }
+ fnord:
+ if (!cfg_file)
+ break;
+ sprintf(buf, "/mnt2/%s", cfg_file);
+ msgDebug("Attempting to open configuration file: %s\n", buf);
+ fd = open(buf, O_RDONLY);
+ if (fd == -1) {
+ dialog_clear();
+ if (msgYesNo("Unable to find the configuration file: %s\n"
+ "Do you want to try again?", buf)) {
+ unmount("/mnt2", MNT_FORCE);
+ break;
+ }
+ else
+ goto fnord;
+ }
+ else {
+ Attribs *cattr = safe_malloc(sizeof(Attribs) * MAX_ATTRIBS);
+ int i, j;
+
+ if (attr_parse(cattr, fd) == RET_FAIL) {
+ dialog_clear();
+ msgConfirm("Cannot parse configuration file %s! Please verify your media.", cfg_file);
+ }
+ else {
+ i = RET_SUCCESS;
+ for (j = 0; cattr[j].name[0]; j++) {
+ int status;
+
+ if (call_possible_resword(cattr[j].name, cattr[j].value, &status)) {
+ if (status != RET_SUCCESS) {
+ msgDebug("macro call to %s(%s) returns %d status!\n", cattr[j].name, cattr[j].value,
+ status);
+ i = status;
+ }
+ }
+ else
+ variable_set2(cattr[j].name, cattr[j].value);
+ }
+ if (i == RET_SUCCESS) {
+ dialog_clear();
+ msgConfirm("Configuration file %s loaded successfully!\n"
+ "Some parameters may now have new default values.", buf);
+ }
+ else if (i == RET_FAIL) {
+ dialog_clear();
+ msgConfirm("Configuration file %s loaded with some errors.", buf);
+ }
+ }
+ close(fd);
+ safe_free(cattr);
+ unmount("/mnt2", MNT_FORCE);
+ break;
+ }
+ }
+ return i;
+}
diff --git a/release/sysinstall/installUpgrade.c b/release/sysinstall/installUpgrade.c
new file mode 100644
index 0000000000000..2a2d19b217ec1
--- /dev/null
+++ b/release/sysinstall/installUpgrade.c
@@ -0,0 +1,396 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last program in the `sysinstall' line - the next
+ * generation being essentially a complete rewrite.
+ *
+ * $Id: installUpgrade.c,v 1.17 1995/11/08 07:09:27 jkh Exp $
+ *
+ * Copyright (c) 1995
+ * Jordan Hubbard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jordan Hubbard
+ * for the FreeBSD Project.
+ * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "sysinstall.h"
+#include <sys/disklabel.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/wait.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/mount.h>
+
+typedef struct _hitList {
+ enum { JUST_COPY, CALL_HANDLER } action ;
+ char *name;
+ Boolean optional;
+ void (*handler)(struct _hitList *self);
+} HitList;
+
+/* cop-out function for files we can't handle */
+static void
+doByHand(HitList *h)
+{
+ dialog_clear();
+ msgConfirm("/etc/%s is one of those files that this upgrade procedure just isn't\n"
+ "smart enough to deal with right now. You'll need to merge the old and\n"
+ "new versions by hand when the option to do so manually is later\n"
+ "presented (in the meantime, you might want to write the name of\n"
+ "this file down! - the holographic shell on VTY4 is a good place for\n"
+ "this).", h->name);
+}
+
+static void
+yellSysconfig(HitList *h)
+{
+ dialog_clear();
+ msgConfirm("/etc/sysconfig is one of those files that this upgrade procedure just isn't\n"
+ "smart enough to deal with right now. Unfortunately, your system\n"
+ "will also come up with a very different \"personality\" than it had\n"
+ "before if you do not merge at LEAST the hostname and ifconfig lines\n"
+ "from the old one! This is very important, so please do this merge\n"
+ "even if you do no others before the system is allowed to reboot.");
+}
+
+/* These are the only meaningful files I know about */
+static HitList etc_files [] = {
+ { JUST_COPY, "Xaccel.ini", TRUE, NULL },
+ { JUST_COPY, "adduser.conf", TRUE, NULL },
+ { JUST_COPY, "aliases", TRUE, NULL },
+ { JUST_COPY, "aliases.db", TRUE, NULL },
+ { JUST_COPY, "amd.map", TRUE, NULL },
+ { JUST_COPY, "crontab", TRUE, NULL },
+ { JUST_COPY, "csh.cshrc", TRUE, NULL },
+ { JUST_COPY, "csh.login", TRUE, NULL },
+ { JUST_COPY, "csh.logout", TRUE, NULL },
+ { JUST_COPY, "daily", TRUE, NULL },
+ { JUST_COPY, "disktab", TRUE, NULL },
+ { JUST_COPY, "dm.conf", TRUE, NULL },
+ { JUST_COPY, "exports", TRUE, NULL },
+ { JUST_COPY, "fbtab", TRUE, NULL },
+ { CALL_HANDLER, "fstab", FALSE, doByHand },
+ { JUST_COPY, "ftpusers", TRUE, NULL },
+ { JUST_COPY, "gnats", TRUE, NULL },
+ { JUST_COPY, "group", FALSE, NULL },
+ { JUST_COPY, "host.conf", TRUE, NULL },
+ { JUST_COPY, "hosts", TRUE, NULL },
+ { JUST_COPY, "hosts.equiv", TRUE, NULL },
+ { JUST_COPY, "hosts.lpd", TRUE, NULL },
+ { CALL_HANDLER, "inetd.conf", FALSE, doByHand },
+ { CALL_HANDLER, "kerberosIV", TRUE, doByHand },
+ { JUST_COPY, "localtime", TRUE, NULL },
+ { JUST_COPY, "login.access", TRUE, NULL },
+ { JUST_COPY, "mail.rc", TRUE, NULL },
+ { JUST_COPY, "make.conf", TRUE, NULL },
+ { JUST_COPY, "manpath.config", TRUE, NULL },
+ { JUST_COPY, "master.passwd", TRUE, NULL },
+ { JUST_COPY, "mib.txt", TRUE, NULL },
+ { JUST_COPY, "modems", TRUE, NULL },
+ { JUST_COPY, "monthly", TRUE, NULL },
+ { JUST_COPY, "motd", TRUE, NULL },
+ { JUST_COPY, "namedb", TRUE, NULL },
+ { CALL_HANDLER, "netstart", FALSE, doByHand },
+ { JUST_COPY, "networks", TRUE, NULL },
+ { JUST_COPY, "passwd", FALSE, NULL },
+ { JUST_COPY, "phones", TRUE, NULL },
+ { JUST_COPY, "ppp", TRUE, NULL },
+ { JUST_COPY, "printcap", TRUE, NULL },
+ { JUST_COPY, "profile", TRUE, NULL },
+ { JUST_COPY, "protocols", TRUE, NULL },
+ { JUST_COPY, "pwd.db", TRUE, NULL },
+ { CALL_HANDLER, "rc", FALSE, doByHand },
+ { CALL_HANDLER, "rc.i386", TRUE, doByHand },
+ { JUST_COPY, "rc.local", TRUE, NULL },
+ { CALL_HANDLER, "rc.serial", TRUE, doByHand },
+ { JUST_COPY, "remote", TRUE, NULL },
+ { JUST_COPY, "resolv.conf", TRUE, NULL },
+ { JUST_COPY, "rmt", TRUE, NULL },
+ { JUST_COPY, "security", TRUE, NULL },
+ { JUST_COPY, "sendmail.cf", TRUE, NULL },
+ { CALL_HANDLER, "services", TRUE, doByHand },
+ { JUST_COPY, "shells", TRUE, NULL },
+ { JUST_COPY, "skeykeys", TRUE, NULL },
+ { JUST_COPY, "spwd.db", TRUE, NULL },
+ { JUST_COPY, "supfile", TRUE, NULL },
+ { CALL_HANDLER, "sysconfig", FALSE, yellSysconfig },
+ { JUST_COPY, "syslog.conf", TRUE, NULL },
+ { JUST_COPY, "termcap", TRUE, NULL },
+ { JUST_COPY, "ttys", TRUE, NULL },
+ { JUST_COPY, "uucp", TRUE, NULL },
+ { JUST_COPY, "weekly", TRUE, NULL },
+ { 0 },
+};
+
+void
+traverseHitlist(HitList *h)
+{
+ while (h->name) {
+ if (!file_readable(h->name)) {
+ if (!h->optional) {
+ dialog_clear();
+ msgConfirm("Unable to find an old /etc/%s file! That is decidedly non-standard and\n"
+ "your upgraded system may function a little strangely as a result.");
+ }
+ }
+ else {
+ if (h->action == JUST_COPY) {
+ /* Nuke the just-loaded copy thoroughly */
+ vsystem("rm -rf /etc/%s", h->name);
+
+ /* Copy the old one into its place */
+ msgNotify("Resurrecting %s..", h->name);
+ /* Do this with tar so that symlinks and such are preserved */
+ if (vsystem("tar cf - %s | tar xpf - -C /etc", h->name)) {
+ dialog_clear();
+ msgConfirm("Unable to resurrect your old /etc/%s! Hmmmm.", h->name);
+ }
+ }
+ else /* call handler */
+ h->handler(h);
+ }
+ ++h;
+ }
+}
+
+int
+installUpgrade(char *str)
+{
+ char *saved_etc = NULL;
+ Boolean extractingBin = TRUE;
+ struct termios foo;
+
+ if (!RunningAsInit) {
+ dialog_clear();
+ msgConfirm("You can only perform this procedure when booted off the installation\n"
+ "floppy.");
+ return RET_FAIL;
+ }
+
+ systemDisplayHelp("upgrade");
+
+ if (msgYesNo("Given all that scary stuff you just read, are you sure you want to\n"
+ "risk it all and proceed with this upgrade?"))
+ return RET_FAIL;
+
+ if (!Dists) {
+ dialog_clear();
+ msgConfirm("You haven't specified any distributions yet. The upgrade procedure will\n"
+ "only upgrade those portions of the system for which a distribution has\n"
+ "been selected. In the next screen, we'll go to the Distributions menu\n"
+ "to select those portions of 2.1 you wish to install on top of your 2.0.5\n"
+ "system.");
+ if (!dmenuOpenSimple(&MenuDistributions))
+ return RET_FAIL;
+ }
+
+ /* No bin selected? Not much of an upgrade.. */
+ if (!(Dists & DIST_BIN)) {
+ dialog_clear();
+ if (msgYesNo("You didn't select the bin distribution as one of the distributons to load.\n"
+ "This one is pretty vital to a successful 2.1 upgrade. Are you SURE you don't\n"
+ "want to select the bin distribution? Chose _No_ to bring up the Distributions\n"
+ "menu.")) {
+ (void)dmenuOpenSimple(&MenuDistributions);
+ }
+ }
+
+ /* Still?! OK! They must know what they're doing.. */
+ if (!(Dists & DIST_BIN))
+ extractingBin = FALSE;
+
+ if (!mediaDevice) {
+ dialog_clear();
+ msgConfirm("Now you must specify an installation medium for the upgrade.");
+ if (!dmenuOpenSimple(&MenuMedia) || !mediaDevice)
+ return RET_FAIL;
+ }
+
+ dialog_clear();
+ msgConfirm("OK. First, we're going to go to the disk label editor. In this editor\n"
+ "you will be expected to *Mount* any partitions you're interested in\n"
+ "upgrading. Don't set the Newfs flag to Y on anything in the label editor\n"
+ "unless you're absolutely sure you know what you're doing! In this\n"
+ "instance, you'll be using the label editor as little more than a fancy\n"
+ "screen-oriented filesystem mounting utility, so think of it that way.\n\n"
+ "Once you're done in the label editor, press Q to return here for the next\n"
+ "step.");
+
+ if (diskLabelEditor(NULL) == RET_FAIL) {
+ dialog_clear();
+ msgConfirm("The disk label editor failed to work properly! Upgrade operation\n"
+ "aborted.");
+ return RET_FAIL;
+ }
+
+ /* Don't write out MBR info */
+ variable_set2(DISK_PARTITIONED, "written");
+ if (diskLabelCommit("upgrade") == RET_FAIL) {
+ dialog_clear();
+ msgConfirm("Not all file systems were properly mounted. Upgrade operation\n"
+ "aborted.");
+ variable_unset(DISK_PARTITIONED);
+ return RET_FAIL;
+ }
+
+ if (!copySelf()) {
+ dialog_clear();
+ msgConfirm("Couldn't clone the boot floppy onto the root file system.\n"
+ "Aborting.");
+ return RET_FAIL;
+ }
+
+ if (chroot("/mnt") == RET_FAIL) {
+ dialog_clear();
+ msgConfirm("Unable to chroot to /mnt - something is wrong with the\n"
+ "root partition or the way it's mounted if this doesn't work.");
+ variable_unset(DISK_PARTITIONED);
+ return RET_FAIL;
+ }
+
+ chdir("/");
+ systemCreateHoloshell();
+
+ if (!rootExtract()) {
+ dialog_clear();
+ msgConfirm("Failed to load the ROOT distribution. Please correct\n"
+ "this problem and try again (the system will now reboot).");
+ reboot(0);
+ }
+
+ if (extractingBin) {
+ while (!saved_etc) {
+ saved_etc = msgGetInput("/usr/tmp/etc", "Under which directory do you wish to save your current /etc?");
+ if (!saved_etc || !*saved_etc || Mkdir(saved_etc, NULL)) {
+ dialog_clear();
+ if (msgYesNo("Directory was not specified, was invalid or user selected Cancel.\n\n"
+ "Doing an upgrade without first backing up your /etc directory is a very\n"
+ "bad idea! Do you want to go back and specify the save directory again?"))
+ break;
+ }
+ }
+
+ if (saved_etc) {
+ msgNotify("Preserving /etc directory..");
+ /* cp returns a bogus status, so we can't check the status meaningfully. Bleah. */
+ (void)vsystem("cp -pr /etc/* %s", saved_etc);
+ }
+ if (file_readable("/kernel")) {
+ msgNotify("Moving old kernel to /kernel.205");
+ if (system("chflags noschg /kernel && mv /kernel /kernel.205")) {
+ dialog_clear();
+ if (!msgYesNo("Hmmm! I couldn't move the old kernel over! Do you want to\n"
+ "treat this as a big problem and abort the upgrade? Due to the\n"
+ "way that this upgrade process works, you will have to reboot\n"
+ "and start over from the beginning. Select Yes to reboot now")) {
+ reboot(0);
+ }
+ }
+ }
+ }
+
+ msgNotify("Beginning extraction of distributions..");
+ if (distExtractAll("upgrade") == RET_FAIL) {
+ if (extractingBin && (Dists & DIST_BIN)) {
+ dialog_clear();
+ msgConfirm("Hmmmm. We couldn't even extract the bin distribution. This upgrade\n"
+ "should be considered a failure and started from the beginning, sorry!\n"
+ "The system will reboot now.");
+ reboot(0);
+ }
+ dialog_clear();
+ msgConfirm("The extraction process seems to have had some problems, but we got most\n"
+ "of the essentials. We'll treat this as a warning since it may have been\n"
+ "only non-essential distributions which failed to load.");
+ }
+
+ if (extractingBin) {
+ msgNotify("OK, now it's time to go pound on your root a little bit to create all the\n"
+ "/dev entries and such that a 2.1 system expects to see. I'll also perform a\n"
+ "few \"fixup\" operations to repair the effects of splatting a bin distribution\n"
+ "on top of an existing system..");
+ if (installFixup("upgrade") == RET_FAIL) {
+ dialog_clear();
+ msgConfirm("Hmmmmm. The fixups don't seem to have been very happy.\n"
+ "You may wish to examine the system a little more closely when\n"
+ "it comes time to merge your /etc customizations back.");
+ }
+ }
+
+ dialog_clear();
+ msgConfirm("First stage of upgrade completed successfully!\n\n"
+ "Next comes stage 2, where we attempt to resurrect your /etc\n"
+ "directory!");
+
+ if (chdir(saved_etc)) {
+ dialog_clear();
+ msgConfirm("Unable to go to your saved /etc directory in %s?! Argh!\n"
+ "Something went seriously wrong! It's quite possible that\n"
+ "your former /etc is toast. I hope you didn't have any\n"
+ "important customizations you wanted to keep in there.. :(");
+ }
+ else {
+ /* Now try to resurrect the /etc files */
+ traverseHitlist(etc_files);
+ }
+
+ dialog_clear();
+ msgConfirm("OK! At this stage, we've resurrected all the /etc files we could\n"
+ "(and you may have been warned about some that you'll have to merge\n"
+ "yourself by hand) and we're going to drop you into a shell to do\n"
+ "the rest yourself (sorry about this!). Once the system looks good\n"
+ "to you, exit the shell to reboot the system.");
+
+ chdir("/");
+ dialog_clear();
+ dialog_update();
+ end_dialog();
+ DialogActive = FALSE;
+
+ signal(SIGTTOU, SIG_IGN);
+ if (tcgetattr(0, &foo) != -1) {
+ foo.c_cc[VERASE] = '\010';
+ if (tcsetattr(0, TCSANOW, &foo) == -1)
+ msgDebug("Unable to set the erase character.\n");
+ }
+ else
+ msgDebug("Unable to get the terminal attributes!\n");
+ printf("Well, good luck! When you're done, please type \"reboot\" or exit\n"
+ "the shell to reboot the new system.\n");
+ execlp("sh", "-sh", 0);
+ msgDebug("Was unable to execute sh for post-upgrade shell!\n");
+ reboot(0);
+ /* NOTREACHED */
+ return 0;
+}
diff --git a/release/sysinstall/lndir.c b/release/sysinstall/lndir.c
new file mode 100644
index 0000000000000..665f3627d3438
--- /dev/null
+++ b/release/sysinstall/lndir.c
@@ -0,0 +1,217 @@
+/* $XConsortium: lndir.c,v 1.14 95/01/09 20:08:20 kaleb Exp $ */
+/* $XFree86: xc/config/util/lndir.c,v 3.3 1995/01/28 15:41:09 dawes Exp $ */
+/* Create shadow link tree (after X11R4 script of the same name)
+ Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */
+
+/* Hacked somewhat by Jordan Hubbard, The FreeBSD Project, to make it */
+/* an invokable function from sysinstall rather than a stand-alone binary */
+
+/*
+Copyright (c) 1990, X Consortium
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the X Consortium shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from the X Consortium.
+
+*/
+
+/* From the original /bin/sh script:
+
+ Used to create a copy of the a directory tree that has links for all
+ non-directories (except those named RCS, SCCS or CVS.adm). If you are
+ building the distribution on more than one machine, you should use
+ this technique.
+
+ If your master sources are located in /usr/local/src/X and you would like
+ your link tree to be in /usr/local/src/new-X, do the following:
+
+ % mkdir /usr/local/src/new-X
+ % cd /usr/local/src/new-X
+ % lndir ../X
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdarg.h>
+#include "sysinstall.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 2048
+#endif
+
+static char *rcurdir;
+static char *curdir;
+
+static int
+equivalent(char *lname, char *rname)
+{
+ char *s;
+
+ if (!strcmp(lname, rname))
+ return 1;
+ for (s = lname; *s && (s = strchr(s, '/')); s++) {
+ while (s[1] == '/')
+ strcpy(s+1, s+2);
+ }
+ return !strcmp(lname, rname);
+}
+
+
+/* Recursively create symbolic links from the current directory to the "from"
+ directory. Assumes that files described by fs and ts are directories. */
+
+static int
+dodir(char *fn, struct stat *fs, struct stat *ts, int rel)
+{
+ DIR *df;
+ struct dirent *dp;
+ char buf[MAXPATHLEN + 1], *p;
+ char symbuf[MAXPATHLEN + 1];
+ struct stat sb, sc;
+ int n_dirs;
+ int symlen;
+ char *ocurdir;
+
+ if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino))
+ return 1;
+
+ if (rel)
+ strcpy (buf, "../");
+ else
+ buf[0] = '\0';
+ strcat (buf, fn);
+
+ if (!(df = opendir (buf))) {
+ msgDebug("%s: Cannot opendir\n", buf);
+ return 1;
+ }
+
+ p = buf + strlen (buf);
+ *p++ = '/';
+ n_dirs = fs->st_nlink;
+ while ((dp = readdir (df)) != NULL) {
+ if (dp->d_name[strlen(dp->d_name) - 1] == '~')
+ continue;
+ strcpy (p, dp->d_name);
+
+ if (n_dirs > 0) {
+ if (stat (buf, &sb) < 0) {
+ msgDebug("Can't stat: %s\n", buf);
+ continue;
+ }
+
+ if (S_ISDIR(sb.st_mode)) {
+ /* directory */
+ n_dirs--;
+ if (dp->d_name[0] == '.' &&
+ (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+ continue;
+ if (!strcmp (dp->d_name, "RCS"))
+ continue;
+ if (!strcmp (dp->d_name, "SCCS"))
+ continue;
+ if (!strcmp (dp->d_name, "CVS"))
+ continue;
+ if (!strcmp (dp->d_name, "CVS.adm"))
+ continue;
+ ocurdir = rcurdir;
+ rcurdir = buf;
+ curdir = isDebug() ? buf : (char *)0;
+ if (isDebug())
+ msgDebug("%s:\n", buf);
+ if ((stat(dp->d_name, &sc) < 0) && (errno == ENOENT)) {
+ if (mkdir(dp->d_name, 0777) < 0 ||
+ stat (dp->d_name, &sc) < 0) {
+ msgDebug("Unable to make or stat: %s\n", dp->d_name);
+ curdir = rcurdir = ocurdir;
+ continue;
+ }
+ }
+ if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
+ msgDebug("%s: is a link instead of a directory\n", dp->d_name);
+ curdir = rcurdir = ocurdir;
+ continue;
+ }
+ if (chdir (dp->d_name) < 0) {
+ msgDebug("Unable to chdir to: %s\n", dp->d_name);
+ curdir = rcurdir = ocurdir;
+ continue;
+ }
+ (void)dodir(buf, &sb, &sc, (buf[0] != '/'));
+ if (chdir ("..") < 0) {
+ msgDebug("Unable to get back to ..\n");
+ return RET_FAIL;
+ }
+ curdir = rcurdir = ocurdir;
+ continue;
+ }
+ }
+
+ /* non-directory */
+ symlen = readlink (dp->d_name, symbuf, sizeof(symbuf) - 1);
+ if (symlen >= 0) {
+ symbuf[symlen] = '\0';
+ if (!equivalent (symbuf, buf))
+ msgDebug("%s: %s\n", dp->d_name, symbuf);
+ } else if (symlink (buf, dp->d_name) < 0)
+ msgDebug("Unable to create symlink: %s\n", dp->d_name);
+ }
+
+ closedir (df);
+ return 0;
+}
+
+int
+lndir(char *from, char *to)
+{
+ struct stat fs, ts;
+
+ if (!to)
+ to = ".";
+
+ /* to directory */
+ if (stat(to, &ts) < 0) {
+ msgDebug("Destination directory doesn't exist: %s\n", to);
+ return RET_FAIL;
+ }
+ if (!(S_ISDIR(ts.st_mode))) {
+ msgDebug ("%s: Not a directory\n", to);
+ return RET_FAIL;
+ }
+ if (chdir(to) < 0) {
+ msgDebug("Unable to chdir to %s\n", to);
+ return RET_FAIL;
+ }
+ /* from directory */
+ if (stat(from, &fs) < 0) {
+ msgDebug("From directory doesn't exist: %s\n", from);
+ return RET_FAIL;
+ }
+ if (!(S_ISDIR(fs.st_mode))) {
+ msgDebug ("%s: Not a directory\n", from);
+ return RET_FAIL;
+ }
+ return dodir(from, &fs, &ts, 0);
+}
diff --git a/release/sysinstall/options.c b/release/sysinstall/options.c
new file mode 100644
index 0000000000000..c9c099afe766a
--- /dev/null
+++ b/release/sysinstall/options.c
@@ -0,0 +1,289 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last attempt in the `sysinstall' line, the next
+ * generation being slated for what's essentially a complete rewrite.
+ *
+ * $Id: options.c,v 1.26 1995/11/03 12:02:44 jkh Exp $
+ *
+ * Copyright (c) 1995
+ * Jordan Hubbard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jordan Hubbard
+ * for the FreeBSD Project.
+ * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "sysinstall.h"
+#include <ctype.h>
+
+static char *
+varCheck(Option opt)
+{
+ char *cp = NULL;
+
+ if (opt.aux)
+ cp = variable_get((char *)opt.aux);
+ if (!cp)
+ return "<not set>";
+ return cp;
+}
+
+/* Show our little logo */
+static char *
+resetLogo(char *str)
+{
+ return "[WHAP!]";
+}
+
+static char *
+mediaCheck(Option opt)
+{
+ if (mediaDevice) {
+ switch(mediaDevice->type) {
+ case DEVICE_TYPE_UFS:
+ case DEVICE_TYPE_DISK:
+ return "File system";
+
+ case DEVICE_TYPE_FLOPPY:
+ return "Floppy";
+
+ case DEVICE_TYPE_FTP:
+ return "FTP";
+
+ case DEVICE_TYPE_CDROM:
+ return "CDROM";
+
+ case DEVICE_TYPE_TAPE:
+ return "Tape";
+
+ case DEVICE_TYPE_DOS:
+ return "DOS";
+
+ case DEVICE_TYPE_NFS:
+ return "NFS";
+
+ case DEVICE_TYPE_NONE:
+ case DEVICE_TYPE_NETWORK:
+ case DEVICE_TYPE_ANY:
+ default:
+ return "<unknown>";
+ }
+ }
+ return "<unset>";
+}
+
+#define TAPE_PROMPT "Please enter the tape block size in 512 byte blocks:"
+#define RELNAME_PROMPT "Please specify the release you wish to load:"
+#define BPKG_PROMPT "Please specify the name of the HTML browser package:"
+#define BBIN_PROMPT "Please specify a full pathname to the HTML browser binary:"
+#define RETRY_PROMPT "Please specify the number of times to retry an FTP request:"
+#define PKG_PROMPT "Please specify a temporary directory with lots of free space:"
+
+static Option Options[] = {
+{ "NFS Secure", "NFS server talks only on a secure port",
+ OPT_IS_VAR, NULL, VAR_NFS_SECURE, varCheck },
+{ "NFS Slow", "User is using a slow PC or ethernet card",
+ OPT_IS_VAR, NULL, VAR_SLOW_ETHER, varCheck },
+{ "Debugging", "Emit extra debugging output on VTY2 (ALT-F2)",
+ OPT_IS_VAR, NULL, VAR_DEBUG, varCheck },
+{ "Yes to All", "Assume \"Yes\" answers to all non-critical dialogs",
+ OPT_IS_VAR, NULL, VAR_NO_CONFIRM, varCheck },
+{ "FTP OnError", "What to do when FTP requests fail: abort, retry, reselect.",
+ OPT_IS_FUNC, mediaSetFtpOnError, VAR_FTP_ONERROR, varCheck },
+{ "FTP Retries", "If FTP OnError == retry, this is the number of times to try.",
+ OPT_IS_VAR, RETRY_PROMPT, VAR_FTP_RETRIES, varCheck },
+{ "FTP username", "Username and password to use instead of anonymous",
+ OPT_IS_FUNC, mediaSetFtpUserPass, VAR_FTP_USER, varCheck },
+{ "Tape Blocksize", "Tape media block size in 512 byte blocks",
+ OPT_IS_VAR, TAPE_PROMPT, VAR_TAPE_BLOCKSIZE, varCheck },
+{ "Extract Detail", "How verbosely to display file name information during extractions",
+ OPT_IS_FUNC, mediaSetCPIOVerbosity, VAR_CPIO_VERBOSITY, varCheck },
+{ "Release Name", "Which release to attempt to load from installation media",
+ OPT_IS_VAR, RELNAME_PROMPT, VAR_RELNAME, varCheck },
+{ "Browser Pkg", "This is the browser package that will be used for viewing HTML docs",
+ OPT_IS_VAR, BPKG_PROMPT, VAR_BROWSER_PACKAGE, varCheck },
+{ "Browser Exec", "This is the path to the main binary of the browser package",
+ OPT_IS_VAR, BBIN_PROMPT, VAR_BROWSER_BINARY, varCheck },
+{ "Media Type", "The current installation media type.",
+ OPT_IS_FUNC, mediaGetType, VAR_MEDIA_TYPE, mediaCheck },
+{ "Package Temp", "The directory where package temporary files should go",
+ OPT_IS_VAR, PKG_PROMPT, "PKG_TMPDIR", varCheck },
+{ "Use Defaults", "Reset all values to startup defaults",
+ OPT_IS_FUNC, installVarDefaults, 0, resetLogo },
+{ NULL },
+};
+
+#define OPT_START_ROW 4
+#define OPT_END_ROW 20
+#define OPT_NAME_COL 0
+#define OPT_VALUE_COL 16
+#define GROUP_OFFSET 40
+
+static char *
+value_of(Option opt)
+{
+ static char ival[40];
+
+ switch (opt.type) {
+ case OPT_IS_STRING:
+ return (char *)opt.data;
+
+ case OPT_IS_INT:
+ sprintf(ival, "%d", (int)opt.data);
+ return ival;
+
+ case OPT_IS_FUNC:
+ case OPT_IS_VAR:
+ if (opt.check)
+ return opt.check(opt);
+ else
+ return "<*>";
+ }
+ return "<unknown>";
+}
+
+static void
+fire(Option opt)
+{
+ if (opt.type == OPT_IS_FUNC) {
+ int (*cp)(char *) = opt.data;
+
+ cp(NULL);
+ }
+ else if (opt.type == OPT_IS_VAR) {
+ if (opt.data) {
+ (void)variable_get_value(opt.aux, opt.data);
+ dialog_clear();
+ }
+ else if (variable_get(opt.aux))
+ variable_unset(opt.aux);
+ else
+ variable_set2(opt.aux, "YES");
+ }
+ if (opt.check)
+ opt.check(opt);
+ clear();
+ refresh();
+}
+
+int
+optionsEditor(char *str)
+{
+ int i, optcol, optrow, key;
+ static int currOpt = 0;
+
+ dialog_clear();
+ clear();
+
+ while (1) {
+ /* Whap up the header */
+ attrset(A_REVERSE); mvaddstr(0, 0, "Options Editor"); attrset(A_NORMAL);
+ for (i = 0; i < 2; i++) {
+ mvaddstr(OPT_START_ROW - 2, OPT_NAME_COL + (i * GROUP_OFFSET), "Name");
+ mvaddstr(OPT_START_ROW - 1, OPT_NAME_COL + (i * GROUP_OFFSET), "----");
+
+ mvaddstr(OPT_START_ROW - 2, OPT_VALUE_COL + (i * GROUP_OFFSET), "Value");
+ mvaddstr(OPT_START_ROW - 1, OPT_VALUE_COL + (i * GROUP_OFFSET), "-----");
+ }
+ /* And the footer */
+ mvprintw(OPT_END_ROW + 0, 0, "Use SPACE to select/toggle an option, arrow keys to move,");
+ mvprintw(OPT_END_ROW + 1, 0, "? or F1 for more help. When you're done, type Q to Quit.");
+
+ optrow = OPT_START_ROW;
+ optcol = OPT_NAME_COL;
+ for (i = 0; Options[i].name; i++) {
+ /* Names are painted somewhat gratuitously each time, but it's easier this way */
+ mvprintw(optrow, OPT_NAME_COL + optcol, Options[i].name);
+ if (currOpt == i) standout();
+ mvprintw(optrow++, OPT_VALUE_COL + optcol, value_of(Options[i]));
+ if (currOpt == i) standend();
+ if (optrow == OPT_END_ROW) {
+ optrow = OPT_START_ROW;
+ optcol += GROUP_OFFSET;
+ }
+ clrtoeol();
+ }
+ standout();
+ mvaddstr(OPT_END_ROW + 3, 0, Options[currOpt].desc);
+ standend();
+ clrtoeol();
+ move(0, 14);
+
+ /* Start the edit loop */
+ key = toupper(getch());
+ switch (key) {
+ case KEY_F(1):
+ case '?':
+ systemDisplayHelp("options");
+ break;
+
+ case KEY_UP:
+ if (currOpt)
+ --currOpt;
+ else
+ beep();
+ continue;
+
+ case KEY_DOWN:
+ if (Options[currOpt + 1].name)
+ ++currOpt;
+ else
+ beep();
+ continue;
+
+ case KEY_HOME:
+ currOpt = 0;
+ continue;
+
+ case KEY_END:
+ while (Options[currOpt + 1].name)
+ ++currOpt;
+ continue;
+
+ case ' ':
+ dialog_clear();
+ fire(Options[currOpt]);
+ dialog_clear();
+ clear();
+ continue;
+
+ case 'Q':
+ clear();
+ dialog_clear();
+ return RET_SUCCESS;
+
+ default:
+ beep();
+ }
+ }
+ /* NOTREACHED */
+ return RET_SUCCESS;
+}
diff --git a/release/sysinstall/package.c b/release/sysinstall/package.c
new file mode 100644
index 0000000000000..cd75c084f720a
--- /dev/null
+++ b/release/sysinstall/package.c
@@ -0,0 +1,280 @@
+/*
+ * The new sysinstall program.
+ *
+ * This is probably the last program in the `sysinstall' line - the next
+ * generation being essentially a complete rewrite.
+ *
+ * $Id: package.c,v 1.26 1995/11/12 11:02:43 jkh Exp $
+ *
+ * Copyright (c) 1995
+ * Jordan Hubbard. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jordan Hubbard
+ * for the FreeBSD Project.
+ * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/errno.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include "sysinstall.h"
+
+static char *make_playpen(char *pen, size_t sz);
+
+/* Like package_extract, but assumes current media device */
+int
+package_add(char *name)
+{
+ if (!mediaVerify())
+ return RET_FAIL;
+ return package_extract(mediaDevice, name);
+}
+
+/* Extract a package based on a namespec and a media device */
+int
+package_extract(Device *dev, char *name)
+{
+ char path[511];
+ char pen[FILENAME_MAX];
+ char *where;
+ int fd, ret;
+
+ /* If necessary, initialize the ldconfig hints */
+ if (!file_readable("/var/run/ld.so.hints"))
+ vsystem("ldconfig /usr/lib /usr/local/lib /usr/X11R6/lib");
+
+ /* Check to make sure it's not already there */
+ if (!vsystem("pkg_info -e %s", name)) {
+ msgDebug("package %s marked as already installed - return SUCCESS.\n", name);
+ return RET_SUCCESS;
+ }
+
+ if (!dev->init(dev)) {
+ dialog_clear();
+ msgConfirm("Unable to initialize media type for package extract.");
+ return RET_FAIL;
+ }
+
+ ret = RET_FAIL;
+ /* Make a couple of paranoid locations for temp files to live if user specified none */
+ if (!variable_get("PKG_TMPDIR")) {
+ Mkdir("/usr/tmp", NULL);
+ Mkdir("/var/tmp", NULL);
+ }
+
+ sprintf(path, "packages/All/%s%s", name, strstr(name, ".tgz") ? "" : ".tgz");
+ msgNotify("Adding %s\nfrom %s", path, dev->name);
+ fd = dev->get(dev, path, TRUE);
+ if (fd >= 0) {
+ pen[0] = '\0';
+ if ((where = make_playpen(pen, 0)) != NULL) {
+ if (mediaExtractDist(pen, fd)) {
+ if (file_readable("+CONTENTS")) {
+ /* Set some hints for pkg_add so that it knows how we got here in case of any depends */
+ switch (mediaDevice->type) {
+ case DEVICE_TYPE_FTP:
+ if (variable_get(VAR_FTP_PATH)) {
+ char ftppath[512];
+
+ /* Special case to leave hint for pkg_add that this is an FTP install */
+ sprintf(ftppath, "%spackages/All/", variable_get(VAR_FTP_PATH));
+ variable_set2("PKG_ADD_BASE", ftppath);
+ }
+ break;
+
+ case DEVICE_TYPE_DOS:
+ variable_set2("PKG_PATH", "/dos/freebsd/packages/All:/dos/packages/All");
+ break;
+
+ case DEVICE_TYPE_CDROM:
+ variable_set2("PKG_PATH", "/cdrom/packages/All:/cdrom/usr/ports/packages/All");
+ break;
+
+ default:
+ variable_set2("PKG_PATH", "/dist/packages/All:/dist/freebsd/packages/All");
+ break;
+ }
+
+ if (vsystem("(pwd; cat +CONTENTS) | pkg_add %s-S",
+ !strcmp(variable_get(VAR_CPIO_VERBOSITY), "high") ? "-v " : "")) {
+ dialog_clear();
+ if (!variable_get(VAR_NO_CONFIRM))
+ msgConfirm("An error occurred while trying to pkg_add %s.\n"
+ "Please check debugging screen for possible further details.", name);
+ else
+ msgNotify("An error occurred while trying to pkg_add %s.", name);
+ }
+ else {
+ msgNotify("Package %s added successfully!", name);
+ ret = RET_SUCCESS;
+ }
+ }
+ else {
+ dialog_clear();
+ if (!variable_get(VAR_NO_CONFIRM))
+ msgConfirm("The package specified (%s) has no CONTENTS file. This means\n"
+ "that there was either a media error of some sort or the package\n"
+ "file itself is corrupted. It is also possible that you simply\n"
+ "ran out of temporary space and need to go to the options editor\n"
+ "to select a package temp directory with more space. Either way,\n"
+ "you may wish to look into the problem and try again.", name);
+ else
+ msgNotify("The package specified (%s) has no CONTENTS file. Skipping.", name);
+ }
+ }
+ else {
+ ret = RET_FAIL;
+ if (!variable_get(VAR_NO_CONFIRM))
+ msgConfirm("Unable to extract the contents of package %s. This means\n"
+ "that there was either a media error of some sort or the package\n"
+ "file itself is corrupted.\n"
+ "You may wish to look into this and try again.", name);
+ else
+ msgNotify("Unable to extract the contents of package %s. Skipping.", name);
+ }
+ if (chdir(where) == -1)
+ msgFatal("Unable to get back to where I was before, Jojo! (That was: %s)", where);
+ vsystem("rm -rf %s", pen);
+ if (isDebug())
+ msgDebug("Nuked pen: %s\n", pen);
+ }
+ else {
+ dialog_clear();
+ msgConfirm("Unable to find a temporary location to unpack this stuff in.\n"
+ "You must simply not have enough space or you've configured your\n"
+ "system oddly. Sorry!");
+ ret = RET_FAIL;
+ }
+ dev->close(dev, fd);
+ if (dev->type == DEVICE_TYPE_TAPE)
+ unlink(path);
+ }
+ else {
+ msgDebug("pkg_extract: get operation returned %d\n", fd);
+ if (variable_get(VAR_NO_CONFIRM))
+ msgNotify("Unable to fetch package %s from selected media.\n"
+ "No package add will be done.", name);
+ else {
+ dialog_clear();
+ msgConfirm("Unable to fetch package %s from selected media.\n"
+ "No package add will be done.", name);
+ }
+ }
+ return ret;
+}
+
+static size_t
+min_free(char *tmpdir)
+{
+ struct statfs buf;
+
+ if (statfs(tmpdir, &buf) != 0) {
+ msgDebug("Error in statfs, errno = %d\n", errno);
+ return -1;
+ }
+ return buf.f_bavail * buf.f_bsize;
+}
+
+/* Find a good place to play. */
+static char *
+find_play_pen(char *pen, size_t sz)
+{
+ struct stat sb;
+
+ if (pen[0] && stat(pen, &sb) != RET_FAIL && (min_free(pen) >= sz))
+ return pen;
+ else if (stat("/var/tmp", &sb) != RET_FAIL && min_free("/var/tmp") >= sz)
+ strcpy(pen, "/var/tmp/instmp.XXXXXX");
+ else if (stat("/tmp", &sb) != RET_FAIL && min_free("/tmp") >= sz)
+ strcpy(pen, "/tmp/instmp.XXXXXX");
+ else if ((stat("/usr/tmp", &sb) == RET_SUCCESS || mkdir("/usr/tmp", 01777) == RET_SUCCESS) &&
+ min_free("/usr/tmp") >= sz)
+ strcpy(pen, "/usr/tmp/instmp.XXXXXX");
+ else {
+ dialog_clear();
+ msgConfirm("Can't find enough temporary space to extract the files, please try\n"
+ "This again after your system is up (you can run /stand/sysinstall\n"
+ "directly) and you've had a chance to point /var/tmp somewhere with\n"
+ "sufficient temporary space available.");
+ return NULL;
+ }
+ return pen;
+}
+
+/*
+ * Make a temporary directory to play in and chdir() to it, returning
+ * pathname of previous working directory.
+ */
+static char *
+make_playpen(char *pen, size_t sz)
+{
+ static char Previous[FILENAME_MAX];
+
+ if (!find_play_pen(pen, sz))
+ return NULL;
+
+ if (!mktemp(pen)) {
+ dialog_clear();
+ msgConfirm("Can't mktemp '%s'.", pen);
+ return NULL;
+ }
+ if (mkdir(pen, 0755) == RET_FAIL) {
+ dialog_clear();
+ msgConfirm("Can't mkdir '%s'.", pen);
+ return NULL;
+ }
+ if (isDebug()) {
+ if (sz)
+ msgDebug("Requested space: %d bytes, free space: %d bytes in %s\n", (int)sz, min_free(pen), pen);
+ }
+ if (min_free(pen) < sz) {
+ rmdir(pen);
+ dialog_clear();
+ msgConfirm("Not enough free space to create: `%s'\n"
+ "Please try this again after your system is up (you can run\n"
+ "/stand/sysinstall directly) and you've had a chance to point\n"
+ "/var/tmp somewhere with sufficient temporary space available.");
+ return NULL;
+ }
+ if (!getcwd(Previous, FILENAME_MAX)) {
+ dialog_clear();
+ msgConfirm("getcwd");
+ return NULL;
+ }
+ if (chdir(pen) == RET_FAIL) {
+ dialog_clear();
+ msgConfirm("Can't chdir to '%s'.", pen);
+ }
+ return Previous;
+}
diff --git a/release/sysinstall/power.uu b/release/sysinstall/power.uu
new file mode 100644
index 0000000000000..0a90d3ba904dc
--- /dev/null
+++ b/release/sysinstall/power.uu
@@ -0,0 +1,121 @@
+begin 664 power.gif
+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
+.!W^@!WB=UX2M20$!`#N0
+`
+end
diff --git a/release/sysinstall/version.h b/release/sysinstall/version.h
new file mode 100644
index 0000000000000..b42c26e8937df
--- /dev/null
+++ b/release/sysinstall/version.h
@@ -0,0 +1 @@
+#define RELEASE_NAME "__RELEASE"