#!/usr/bin/perl

#file locations
# can be passed as parameters for use from overall system-build script
#this is where the cf device appears on your system
#e.g. /dev/sdn if using usb or /dev/hdc or hda if using an IDE converter 
$cfdev2 = @ARGV[0] || "/dev/sda2";
#dirs to be used to mount the filesystems on the card. 
$mntpath2 = @ARGV[1] ||  "/mnt/flash2";
#set this parameter true if you don't want any questions - just install the defaults
$dodefault = @ARGV[2] || 0;

#temp dir
$tmpdir = "/tmp/psilinux";
$ipkgpath = "/cdimages/mirror/psilinux/PFN";

@defaultpkgs = ("basesystem", "libc6", "bash", "gzip",
               "e2fsprogs", "fileutils", "grep", "ipkg", "ldconfig",
               "libstdc++", "modutils", "ncurses", "procps", "psmisc",
               "sed", "shadow", "sysvinit", "tar", "textutils", "util-linux",
               "sh-utils", "findutils", "zlibg", "less",
                "irdautils", "libglib", "netkit-base",
               "net-tools", "pppd", "wget",
                "openssl", "openssh",
                  "proftpd","lynx", "jove",
		  "perl", "libgdbmg",
             "vim","ae","slang1","manpages", "mandb", "bzip2", "groff", 
             "fbset","xfree86", "xlibs", "xutils", "xfonts", "xvt","cpp", "libxaw",
             "matchbox", "gtk-menu", "python", "menu-tiny", "libgtk", "libdb2",  
             "xpsitouch",
             "dillo", "libungif","libtiff", "libjpeg", "libpng",
             "gvim","microemacs",
	     "ipatience", "libfltk1", "gsoko" , "mixer", "rsync",
	     "strace", "pikpak", "toad", "sambaclient", 
	     "qiv", "gdk-imlib1" ,"pyditor", "madplay", 
	     "pygps", "libglade0", "mingle", "clerk", "z",
	     "xstroke", "xstroke-help");

@pkgorder = ("Base system", "Networking", "SSH client+server", 
             "ProFTPd FTP server", "Console web browser", 
             "Perl 5.005", "Console VIM", "Man pages", "Frame buffer tools",
             "PicoGUI", "XFree86", "Matchbox windowmanager", "XPsiTouch", "X web browser",
             "GTK-VIM", "X MicroEmacs", "System Call Tracing", "C Development",
             "C++ Development");
%depends = ("Networking" => ["Base system"],
            "SSH client+server" => ["Base system", "Networking"],
            "ProFTPd FTP server" => ["Base system", "Networking"],
            "Console web browser" => ["Base system", "Networking"],
            "Perl 5.005" => ["Base system"],
            "Console VIM" => ["Base system"],
            "Man pages" => ["Base system"],
            "Frame buffer tools" => ["Base system"],
            "PicoGUI" => ["Base system"],
            "XFree86" => ["Base system"],
            "Window Maker" => ["Base system", "XFree86"],
	    "Matchbox windowmanager" => ["Base system", "XFree86"],
            "XPsiTouch" => ["Base System", "XFree86", "Matchbox windowmanager"],
            "X web browser" => ["Base System", "XFree86", "Matchbox windowmanager"],
            "GTK-VIM" => ["Base System", "XFree86", "Matchbox windowmanager"],
            "X MicroEmacs" => ["Base System", "XFree86", "Matchbox windowmanager"],
	    "ae editor" => ["Base System", "XFree86", ],
            "System Call Tracing" => ["Base System"],
            "C Development" => ["Base System"],
            "C++ Development" => ["Base System", "C Developement"]);
%packages = ("Base system" => ["basesystem", "libc6", "bash", "gzip",
               "e2fsprogs", "fileutils", "grep", "ipkg", "ldconfig",
               "libstdc++", "modutils", "ncurses", "procps", "psmisc",
               "sed", "shadow", "sysvinit", "tar", "textutils", "util-linux",
               "sh-utils", "findutils", "zlibg", "less"],
             "Networking" => ["irdautils", "libglib", "netkit-base",
               "net-tools", "pppd", "wget"],
             "SSH client+server" => ["openssl", "openssh"],
             "ProFTPd FTP server" => ["proftpd"],
             "Console web browser" => ["lynx"],
             "Perl 5.005" => ["perl", "libgdbmg"],
             "Console VIM" => ["vim"],
             "Man pages" => ["manpages", "mandb", "bzip2", "groff", "textutils"],
             "Frame buffer tools" => ["fbset"],
             "PicoGUI" => ["picogui", "libjpeg"],
             "XFree86" => ["xfree86", "xlibs", "xutils", "xfonts", "xvt",
               "cpp", "libxaw"],
             "Window Maker" => ["wmaker", "libwraster", "hermes", 
               "libungif", "libtiff", "libjpeg", "libpng"],
	     "Matchbox windowmanager" => ["matchbox", "gtk-menu", "python", 
	       "menu-tiny", "libgtk"],  
             "XPsiTouch" => ["xpsitouch"],
             "X web browser" => ["dillo", "libgtk", "libglib", "libungif",
               "libtiff", "libjpeg", "libpng"],
             "GTK-VIM" => ["vim", "gvim", "libgtk", "libglib"],
             "X MicroEmacs" => ["microemacs"],
	     "ae editor" => ["ae"],
             "System Call Tracing" => ["strace"],
             "C Development" => ["gcc", "libc6dev", "make", "binutils", "cpp"],
             "C++ Development" => ["g++"]);

sub ask {
    while (1) {
        print("$_[0] [$_[1]]: ");
        $response = uc <STDIN>;
        chomp $response;
        if ($response eq "") {
            $response = uc $_[1];
        }
        if ($response eq "Y" or $response eq "YES") {
            return 1;
        } elsif ($response eq "N" or $response eq "NO") {
            return 0;
        }
    }
}

sub askpath {
    print("$_[0] [$_[1]]: ");
    $response = <STDIN>;
    chomp $response;
    if ($response eq "") {
        $response = $_[1];
    }
    return $response;
}

sub showpkgs {
    my ($size, $counter, $name, @packages);
    ($name, @packages) = @_;
    print("\n $name contains the following packages :\n \n\[");
    $counter=0;
    $size = @packages; 
    foreach $pkg (@packages) {
        $counter++;
        if ($counter % 7 eq 0) {
            print ("\n  ");
        }
        if ($counter eq $size) {
            print ("$pkg\]\n\n");
        } else {
            print ("$pkg, ");
        }
    }
};

sub installpkg {
    foreach $pkg (@_) {
        #print ("Installing $pkg\n");
        $findfilecmd = "ls " . $ipkgpath . "/" . $pkg . "_*";
        $pkgname = `$findfilecmd`;
        chomp $pkgname;
        extract($pkgname, $pkg);
    }
};

sub extract {
    my $pkgname = $_[0];
    my $basename = $_[1];
    if ($alreadyinstalled{$basename}) {
        print ("  Package $basename already installed\n");
        return;
    }
    $alreadyinstalled{$basename}=1;
    if ($pkgname eq "") {
        die("Package $basename not found");
    }
    print ("  Extracting $pkgname..\n");
    system("tar xzvf $pkgname -C $tmpdir &>/dev/null");
    system("tar xzvf $tmpdir/data.tar.gz -C $tmpdir | cut --delimiter=\".\" --fields=2-100 &> $tmpdir/files");
    system("tar xzvf $tmpdir/control.tar.gz -C $tmpdir &> /dev/null");
    if (-e "$tmpdir/postinst") {
        system("mv $tmpdir/postinst $tmpdir/etc/firstboot/$basename");
    }
    system("mv $tmpdir/files $tmpdir/usr/lib/ipkg/info/$basename.list");
    my $versioncmd = "echo " . $pkgname . ' | sed "s/^[^_]*_\([^_]*\)_arm\.ipk/\1/"';
    my $version = `$versioncmd`; 
    system("echo -e \"Package: $basename\\nStatus: install ok installed\\nVersion: $version\">>$tmpdir/usr/lib/ipkg/status");
    system("rm -f $tmpdir/debian-binary $tmpdir/data.tar.gz $tmpdir/control.tar.gz $tmpdir/control $tmpdir/prerm $tmpdir/postrm $tmpdir/preinst $tmpdir/postinst");
};

sub main {
    system("clear");
    print("                        PsiLinux system installer 0.9                \n");
    print("---------------------------------------------------------------------\n");
    print(" This program will assist you in installing PsiLinux on your psion.  \n");
    print(" You now have to choose which packages to install. Note that you     \n");
    print(" can install additional packages at any point after the installation \n");
    print(" using ipkg.\n");
    system("mkdir -p $tmpdir && rm -Rf $tmpdir/*");
    system("mkdir -p $tmpdir/usr/lib/ipkg/info && mkdir -p $tmpdir/etc/firstboot");
    system("touch $tmpdir/usr/lib/ipkg/available");
    print("You can just choose the default package set, or choose your own set.\n");

    if (!$dodefault) { $dodefault = ask("Just have the default set ?", "y"); }
    if ($dodefault) {
	print("Generating psilinux using default package list\n"); 
	installpkg(@defaultpkgs);
        print("\n  Deleting files ..\n");
        system("rm -Rf $mntpath2/*");
        print("  Copying files ..\n");
        system("cp -Rdp $tmpdir/* $mntpath2");
        print("  Syncing ..\n");
        system("sync");
    } else {
    
    foreach $key (@pkgorder) {
        my @list = @{$packages{"$key"}};
        showpkgs($key, @list);
        my @dep = @{$depends{"$key"}};
        my $size = @dep; 
        my $counter = 0;
        if (@dep) {
            print(" Depends on: \[");
            foreach $pkg (@dep) {
                $counter++;
                if ($counter eq $size) {
                    print($pkg . "\]\n\n");
                } else {
                    print($pkg . ", ");
                }
            }
        } else {
            print(" Depends on: nothing\n\n");
        }

        $install = ask("Install \"$key\"?", "y");
        if ($install) {
            printf("\n");
            $hasdeps{"$key"} = "1";
            if (@dep) {
                foreach $pkg (@dep) {
                    if (!$hasdeps{"$pkg"}) {
                        print("This package depends on \"$pkg\"! Installing it..\n\n");
                        installpkg(@{$packages{"$pkg"}});
                        print("\n");
                    }
                }
            }
            installpkg(@list);
        }
    }
    printf("\n");
    $cfpresent = &ask("Is CF Card plugged in?", "n");
    if ($cfpresent) {
	print("Mounting CF card...");
	$mounterror = system ("mount -t ext2 $cfdev2 $mntpath2");
    }
    if (!$mounterror) {
        $proceed = &ask("Everything in $mntpath2 will now be deleted. Proceed?", "n");

	if ($mntpath2 eq "/" || $mntpath2 eq "") {
	    die "Invalid install path: $mntpath2 Aborting install\n";
	}

        if ($proceed) {
            print("\n  Deleting files ..\n");
            system("rm -Rf $mntpath2/*");
            print("  Copying files ..\n");
            system("cp -Rdp $tmpdir/* $mntpath2");
            print("  Syncing ..\n");
            system("sync");
            print("  Unmounting ..\n");
            system("umount $mntpath2");
            print("\nYou can now start PsiLinux on your Psion\n\n");
        }
    } else {
        print("Mounting flash FS failed.");
        print("\nTo install PsiLinux, mount your CF card and\n");
        print("copy the directory $tmpdir onto it.\n");
        print("Afterwards, you can start PsiLinux on your Psion\n\n");
    }
    }
}

&main();
