/*
 *   Copyright (c) 1996-1999 David Parsons. 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.
 *  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 David Parsons
 *   (orc@pell.chi.il.us)
 *
 *  4. My name may not be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *     
 *  THIS SOFTWARE IS PROVIDED BY DAVID PARSONS ``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 DAVID
 *  PARSONS 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, 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.
 */

static const char rcsid[] = "$Id: s.loadandgo.c 1.37 00/09/01 08:06:55-00:00 orc $";

/*
 * loadandgo: Linux installer.
 *      /0a) uses SVGATextMode to set the screen to something reasonable
 * later\0b) sets the font
 * 1) checks to see if enough disk can be found to install on.
 * 2) give an inventory list, letting the user set the installation media
 *    and mouse (if any)
 *    2a) validate install method.
 *    2b) mount the install source.
 * 3) query installation configuration and partition/label disks
 * 4) builds filesystems for all the disks
 * 5) mounts the root disk on /disk
 * 6) build the mountpoint tree on /disk (if more that one partition is
 *    being used.)
 * 7) cd /disk; tar xpf /cdrom/{packages}.tar
 * 8) umounts the whatever.
 * 9) chroots to /disk
 * 10) runs Lilo to install a boot loader
 * 11a) runs the second-stage configurator
 * 11b) runs the second-stage x configurator
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include <sys/wait.h>
#include <signal.h>

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>

#include <linux/fs.h>

#include <dialog.h>
#include <ndialog.h>
#include <basis/rpopen.h>

#include "partition.h"
#include "pathnames.h"
#include "util.h"
#include "builddisk.h"
#include "part.h"
#include "media.h"
#include "packages.h"

char* mousenames[] = { "none", "Microsoft", "Logitech", "PS/2" };
char* gpmnames[]   = { "none", "ms", "mman", "ps2" };


/* various flags and indicators */
int		root_is_ide = 0;	/* use 'linear' in /etc/lilo.conf */
int		withdosC=0;		/* install around a dos C: partition */

unsigned long	memsize;		/* how much memory does this have? */
unsigned int	total_memory = 0;	/* how much memory does the user say
					 * this machine has, in megabytes
					 */
int		diskC = EOF;		/* what device to boot from */
unsigned long	diskCsize = 0;		/* how big is the root disk? */
int		mousetype = NO_MOUSE;	/* what sort of mouse does this */
					/*                 system have? */
int		mouse_was_reset = 0;	/* flag for mouse_reset() */
char*		mousedev = (char*)0;	/* and what is it attached to? */

int		nrdisks;		/* how many disks do we have? */
struct par *	mountpoints = 0;	/* desired mountable partitions */
int		nrmountpoints = 0;	/* how many of them? */
LIA		disklist;		/* list of disks */
void *		mdesc = 0;		/* pointer to install media */

char *		av0;			/* argv[0], for massaging */


extern void domount(int);
extern void dounmount();


/*
 * The installer
 */
void
main(int argc, char **argv)
{
    pid_t child;
    int method;

    stfu();

    av0 = argv[0];

    init_dialog();

    if (getpid() == 1) {
	freopen("/dev/tty7", "a", stderr);
	mount("/proc", "/proc", "proc", MS_MGC_VAL, 0);
	putenv("TERM=linux");

	mini_init_pid = mini_init();
	setHelpRoot("/usr/lib/help");
    }
    else {
	freopen("stderr", "w", stderr);
	Error("your pid is %d", getpid());
	setHelpRoot("help");
    }

    describe("Setup", "installation");

    dialog_msgbox(INSTALLER,
		    "Checking your system\n"
		    "for supported hardware",
		    -1, -1, 0);

    /* load ide card services to pick up any IDE cdroms that might
     * be attached to a laptop. (Or IDE network cards, for installing
     * across a network -- future.)
     */
    start_pcmcia();

    /* go detect-happy
     */
    nrdisks = sniff();

    if (nrdisks == 0 || diskC == EOF)
	die("   Couldn't find a hard disk to install Linux on!\n"
	    "\n"
	    "This installation CD supports IDE and EIDE disks, plus\n"
	    "BusLogic Multimaster, BusLogic Flashpoint, Advansys, NCR\n"
	    "53c8xx, and Adaptec 154x SCSI adaptors; if you're using\n"
	    "a different controller, we're sorry, but we can't deal\n"
	    "with it.");
    else if (NrMedia == 0) /* need to fix this to allow installing from
			    * a hard disk partition, a zip drive, or thea
			    * network.
			    */
	die("Couldn't find anything to install Linux from!");

    while (1) {
	mouse_reset();
	use_helpline("Use F1 for help, ESC to cancel the installation");
	/* Here we give a brief inventory and give the user the opportunity
	 * to change the install media
	 */
	give_inventory(&mdesc);

	if (mdesc == 0)
	    die("No install media detected?");

	use_helpline("Use F1 for help, ESC to return to the previos screen");

	fprintf(stderr, "installing from %s on %s\n",
			    MEDIANAME(mdesc), MEDIA(mdesc));
	if (getpid() != 1)
	    readpackagelist(PACKAGES);
	else if (open_media(mdesc) == 1) {
	    /*
	     * force the user to interact and tell us how we should do the
	     * installation.  If they want to do a CUSTOM installation, all
	     * they need to do is press [return] and it's off to the races.
	     */

	    if ((method=howtoinstall(checkdisk0(diskC))) != EOF) {
		withdosC = (method == WITHDOS);
		break;
	    }
	}
	close_media(mdesc);
    }

    /* then fire up the installer and have our way with
     * the system.
     */
    if (getpid() != 1) {
	dialog_msgbox(INSTALLER, "That's all, folks!", -1, 50, 0);
	sleep(1);
	falloverdead();
    }

    tcflush(0, TCIFLUSH);	/* flush any pending input */
    sortDevList();		/* sort the partitions list */

    installpackages();		/* Install software */

    mount("/proc", TARGET "/proc", "proc", MS_MGC_VAL, 0);
    run(1, TARGET "/tmp/Config", "Config", TARGET, 0L);
    chdir("/");

    dialog_msgbox(INSTALLER, "writing configuration to disk", -1, 50, 0);
    /* unmount, then remount, the working area to flush all
     * pending writes to the disk.
     */
    umount(TARGET "/proc");
    dounmount();
    domount(1);
    mount("/proc", TARGET "/proc", "proc", MS_MGC_VAL, 0);

    run(0, TARGET "/tmp/Xsetup", "Xsetup", TARGET, 0L);
    end_dialog();
    
    init_dialog();
    umount(TARGET "/proc");

    while ( (child = waitpid(-1, 0, WNOHANG)) > 0)
	fprintf(stderr, "reaped child %d\n", child);

    chdir("/");		/* flee the sinking TARGET */
    dounmount();
    dialog_msgbox(INSTALLER,
		     "The installation is now complete.  Please remove\n"
		     "any CD-ROMS and floppies from the machine, press\n"
		     "ENTER or the [OK] button and the computer will\n"
		     "restart so it can clean up and be ready for use.",
		     -1, 50, 1);
    use_helpline("");
    end_dialog();
    falloverdead();
} /* loadandgo */
