#!/usr/bin/perl
# Copyright 1999-2000, Peter S. Galbraith <psg@debian.org>
# This script was made for Debian GNU/Linux but may be used by others.
# Licensed under the GNU Public License Version 2.
#--
# Quick hack that needs lots of cleaning-up.
#--
# - jazipconfig
#     -> interactive use if ran without without an option.
#
#	 - make a list of all devices/mount points already listed in
#	   /etc/jazip.conf
#	 - add devices in proc/scsi/scsi and mount points in /etc/fstab
#	 - assign each a number
#	 - prompt to add any of the above or create one from scratch
#	 - if no corresponding mount points are listed in /etc/fstab, 
#          prompt for them.
#	 - upon exiting this menu, check all mount point and prompt to
#	   create them if they don't exist.
#  
# - jazipconfig --non-interactive
#
#	 - exit if /etc/jazip.conf already exists.
#	 - exit if no detected devices are listed in /proc/scsi/scsi
#	 - create /etc/jazip.conf if any of the above devices are listed 
#          in /etc/fstab else output a warning to run jazipconfig 
#          interactively.
#--
# ChangeLog:
# V1.01 Apr 04 2000 Aaron Dewell <acd@woods.net>
#       Tweak sub jazip_list_proc_scsi's regexp to be case-insensitive to catch
#       2GB Jaz drive ID'ed in lowercase in /proc/scsi/scsi
# V1.00 May 16 1999 Peter S. Galbraith <psg@debian.org>
#       Initial release.
#--
# Random notes:
# @ConfDevice :      list to write to /etc/jazip.conf
#                    initialized once by /etc/jazip.conf content
# @DetectedDevice :  list of potential addons from /proc/scsi/scsi
#                    - first put all such devices into @zip and @jaz
#                      and then insert them into @DetectedDevice if not 
#                      already listed in @ConfDevice

#use strict;
my (@zip, @jaz, $device, $mount, @jazipconf, $c,
    $Confcount, @ConfDevice, @ConfMount, @ConfList, $reply,
    $Potcount, $PotDevice, $PotMount);

if ($#ARGV >= 0) { 
    if ($ARGV[0] eq "--non-interactive") {
	# non-interactive script
	# exit if /etc/jazip.conf exists at all
	exit 0 if (-e "/etc/jazip.conf");
	# exit if no devices in /proc/scsi/scsi
	&jazip_list_proc_scsi(@zip, @jaz);
#	&jazip_add_atapi(@zip);
	exit 0 if ((! @zip)&&(! @jaz));
	print "
jazip automatic configuration
-----------------------------
";
	&listPotentialConf;
	foreach ($c = 1; $c <= $Potcount; $c++) {
	    if (defined($PotMount[$c])&&($PotMount[$c] ne "")) {
		$Confcount++;
		$ConfDevice[$Confcount] = $PotDevice[$c];
		$ConfMount[$Confcount] = $PotMount[$c];
	    }
	}
	if (defined($Confcount)&&($Confcount > 0)) {
	    print "\nGot jazip device from /proc/scsi/scsi and mount point from /etc/fstab\n"; 
	    &jazip_write_conf;
	} else {
	    print "\nCould not get all required jazip info automatically
(the device from /proc/scsi/scsi and the mount point from /etc/fstab).

Please run /usr/sbin/jazipconfig to configure jazip interactively
"; 
        }
    exit 0;
    }
}

&initializeConf;
&listPotentialConf;

while ($reply eq "") {
    print "\nAvailable commands:\n"; 
    if ($Confcount != 0) { print " (d)elete an entry from /etc/jazip.conf\n" }
    if ($Potcount != 0) { 
	print " (a)dd an entry listed from detected devices.\n";
    }
    print " (c)reate an entry from scratch.
 (q)uit without saving.
 (e)xit and save changes.
                           ? ";
    
    $reply=<STDIN>; chop($reply); 
    if (! ((($Confcount != 0)&&($reply eq "d"))||
	   (($Potcount != 0)&&($reply eq "a"))||
	   ($reply eq "c")||($reply eq "q")||($reply eq "e"))) { 
	$reply = "";
    }

    if ($reply eq "q") {
	exit 0;
    } elsif ($reply eq "e") {
	# check all mount points, prompt to create if they don't exist.
	foreach ($c = 1; $c <= $Confcount; $c++) {
	    if (! -d $ConfMount[$c]) {
		$reply = &yninput("\nMount point $ConfMount[$c] does not exist. Create it","y");
		if ($reply = "y") { 
		    mkdir("$ConfMount[$c]", 755) or
			die "can't write directory $ConfMount[$c].\nQuiting.\n";
                    system("chown root.floppy $ConfMount[$c]");
                    system("chmod 1771 $ConfMount[$c]");
		}
	    }
	}
	# Write new /etc/jazip.conf file
	&jazip_write_conf;
	exit 0;
    } elsif ($reply eq "c") {
	print "\nNote: Do not specify partition number in device.
What device do you want to add? (e.g. /dev/sda) "; 
	$device=<STDIN>; chop($device);
	if (! -b $device) {
	    print "There is no such device.  Please try again.\n";
	} else {
	    $Confcount++;
	    $ConfDevice[$Confcount] = $device;
	    $mount = jazip_list_etc_fstab($device);
	    if ($mount != 0) {
		$reply = &yninput("$device has mount point $mount in /etc/fstab.  Use it", "y");
		if ($reply eq "n") { $mount = "" }
	    }
	    $mount = "";
	    while ($mount eq "") {
		print "\nWhat mount point? (e.g. /zip) "; 
		$mount=<STDIN>; chop($mount);
	    }	    
	    $ConfMount[$Confcount] = $mount;
	}
	$reply = "";
    } elsif ($reply eq "a") {
	if ($Potcount == 1) {
	    $reply = 1;
	} else {
	    # ask which to enter
	    $reply = "";
	    while ($reply eq "") {
		print "\nWhich one do you add to add? (1 to $Potcount) "; 
		$reply=<STDIN>; chop($reply);
		$reply = "" if (! defined($PotDevice[$reply]));
	    }
	}
	$Confcount++;
	$ConfDevice[$Confcount] = $PotDevice[$reply];
	if (defined($PotMount[$reply])&&($PotMount[$reply] ne "")) {
	    $ConfMount[$Confcount] = $PotMount[$reply];
	} else {
	    $mount = "";
	    while ($mount eq "") {
		print "\nWhat mount point? (e.g. /zip) "; 
		$mount=<STDIN>; chop($mount);
	    }
	    $ConfMount[$Confcount] = $mount;
	}
	@ConfList{$PotDevice[$reply]} = $mount;
	undef($PotDevice); undef($PotMount);
	$reply = "";
    } elsif ($reply eq "d") {
	# handle which to delete
	if ($Confcount == 1) {
	    $Confcount = 0;
	    undef($ConfList{$ConfDevice[1]}); 
	    undef($ConfMount[1]); undef($ConfDevice[1]);
	} else {
	    # ask which to delete
	    $reply = "";
	    while ($reply eq "") {
		print "\nWhich entry do you add to delete? (1 to $Confcount) "; 
		$reply=<STDIN>; chop($reply);
		$reply = "" if (! defined($ConfDevice[$reply]));
	    }
	    undef($ConfList{$ConfDevice[$reply]});
	    foreach ($c = $reply; $c < $Confcount; $c++) {
		$ConfDevice[$c] = $ConfDevice[$c+1];
		$ConfMount[$c] = $ConfMount[$c+1];
	    }
	    undef($ConfDevice[$Confcount]);
	    undef($ConfMount[$Confcount]);
	    $Confcount--;
	}
	$reply = "";
    }
    &listCurrentConf;
    &listPotentialConf;
}

sub initializeConf {
    # Populate @jazipconf associative array from /etc/jazip.conf entries
    &jazip_list_etc_jazipconf();
    $Confcount = 0;

    # Show list of all devices/mount points already listed in /etc/jazip.conf
    foreach $device ( keys %jazipconf ) {
	if ($Confcount == 0) {
	    print "These are entries already in /etc/jazip.conf:\n\n";
	}
	$Confcount++;
	print "  $Confcount:   Device $device   Mount point $jazipconf{$device}\n";
	$ConfDevice[$Confcount] = $device;
	$ConfMount[$Confcount] = $jazipconf{$device};
	$ConfList{$device} = $jazipconf{$device};
    }
    if ($Confcount == 0) {
	print "There are currently no entries in /etc/jazip.conf.\n";
    }
}

sub listCurrentConf {
    # Show list of all devices/mount points gathered so far.
    print "--------------------------------------------\n";
    if ($Confcount == 0) {
	print "There are currently no entries selected for /etc/jazip.conf.\n";
    } else {
	print "These are the entries currently selected for /etc/jazip.conf:\n\n";
	for ($c = 1; $c <= $Confcount; $c++) {
	    print "  $c:   Device $ConfDevice[$c]   Mount point $ConfMount[$c]\n";
	}
    }
}

sub listPotentialConf {

    undef(@zip); undef(@jaz); undef(@PotDevice); undef($PotMount);
    $Potcount = 0;
    
    # See if any other devices in /proc/scsi/scsi
    # - First get all detected devices from /proc/scsi/scsi
    &jazip_list_proc_scsi(@zip, @jaz);
#   &jazip_add_atapi(@zip);
    # - Then look at all Zip devices...
    my ($add) = 0;
    if (! @zip) { 
	print "\nThere are no Zip devices detected on the system.\n";
    } else {
	while ($#zip >= 0) {
	    my $entry = shift(@zip);
	    # See if not already listed
	    if (! defined($ConfList{$entry})) {
		if ($add == 0) { 
		    print "\nZip devices detected on the system:\n\n";
		}
		$add++;
		# See if in /etc/fstab
		$Potcount++;
		print "  $Potcount:  Device $entry";
		$PotDevice[$Potcount] = $entry;
		$mount = jazip_list_etc_fstab($entry);
		if ($mount) {
		    print "   Mount point $mount\n";
		    $PotMount[$Potcount] = $mount;
		} else {
		    print "\n";
		}
	    }
	}
	if ($add == 0) { 
	    print "\nThere are no other Zip devices detected on the system.\n";
	}
    }
    
    # - Then look at all Jaz devices...
    $add = 0;
    if (! @jaz) { 
	print "\nThere are no Jaz devices detected on the system.\n";
    } else {
	while ($#jaz >= 0) {
	    my $entry = shift(@jaz);
	    # See if not already listed
	    if (! defined($ConfList{$entry})) {
		if ($add == 0) { 
		    print "\nJaz devices detected on the system:\n\n";
		}
		$add++;
		# See if in /etc/fstab
		$Potcount++;
		print "  $Potcount:  Device $entry";
		$PotDevice[$Potcount] = $entry;
		$mount = jazip_list_etc_fstab($entry);
		if ($mount) {
		    print "   Mount point $mount\n";
		    $PotMount[$Potcount] = $mount;
		} else {
		    print "\n";
		}
	    }
	}
	if ($add == 0) { 
	    print "\nThere are no other Jaz devices detected on the system.\n";
	}
    }
}

sub jazip_list_etc_fstab { 
    my $entry = shift(@_);
# this should only be used to hunt for mount points to /proc/scsi
# devices not yet listed in /etc/jazipconf, or for devices input by
# user.

    open(CONF, "</etc/fstab");
    # if ARG doesn't end with partition number (e.g. a device name)
    # then add one to the regexp.
    while (<CONF>) {
	if ($entry =~ /.+[0-9]$/) {
	    if (/^[ \t]*$entry[ \t]+([^ \t]+)/) {
		return($1);
	    }
	} else {
	    if (/^[ \t]*$entry[0-9]+[ \t]+([^ \t]+)/) {
		return($1);
	    }
	}
    }
    return;
}

sub jazip_list_etc_jazipconf {
    open(CONF, "</etc/jazip.conf");
    while (<CONF>) {
	# Parse strings like:
	# /dev/sda              /zip
	if (/(\/dev\/[^ \t]+)[ \t]+([^ \t]+)/) {
	    @jazipconf{$1} = $2;
	}
    }
}

sub jazip_add_atapi {
    if (&jazip_add_atapi_from("dmesg |")) {
        if (&jazip_add_atapi_from("< /var/log/messages")) {
            &jazip_add_atapi_from("< /var/log/messages.0");
        }
    }
}

sub jazip_add_atapi_from {
    my $file = shift @_;
    open (LOG, $file); 
    my $counter = 1;
    my $c = 0;
    my $returnCode = 1;
    while (<LOG>) {
        $data[$counter] = $_;
        $counter ++;
    }
    for ($c = $counter; $c >= 1; $c--) {
        if ($data[$c] =~ /(...): IOMEGA ZIP .* ATAPI/) {
            $zip[$#zip + 1] = "/dev/$1";
            $returnCode = 0;
        }
        if ($data[$c] =~ /.*Linux version /) {
            $c = 0;
        }
    }
    return($returnCode);
}

sub jazip_list_proc_scsi {
    my @devices = ("",  "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", 
		   "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", 
		   "x", "y", "z");
    my $zipcount = 0;
    my $jazcount = 0;
    my $count = 0;
    open(PROC, "</proc/scsi/scsi");
    while (<PROC>) {
	# Parse strings like:
	#    Host: scsi0 Channel: 00 Id: 06 Lun: 00
	#      Vendor: IOMEGA   Model: ZIP 100          Rev: D.09
	#      Type:   Direct-Access                    ANSI SCSI revision: 02
	$count++ if (/^Host:/);

	if (/Vendor: IOMEGA   Model: ZIP/i) {
	    $zip[$zipcount] = "/dev/sd$devices[$count]";
	    $zipcount++;
	}
	if (/Vendor: IOMEGA   Model: JAZ/i) {
	    $jaz[$jazcount] = "/dev/sd$devices[$count]";
	    $jazcount++;
	}
	$count-- if (/^ +Type/ && !/Direct-Access/ && !/Optical Device/);
    }
#    print "Got $zipcount\n";
#    for ($i = 0; $i < $zipcount; $i++) {
#	print "  $zip[$i]\n";
#    }
}

sub jazip_write_conf {
    if ($Confcount == 0) {
	print "No configured devides to write to /etc/jazip.conf.
Exiting.\n";
    } else {
	if (-f "/etc/jazip.conf") {
	    print "\nRenaming /etc/jazip.conf to /etc/jazip.conf-previous
and creating new /etc/jazip.conf.\n";
	    rename("/etc/jazip.conf", "/etc/jazip.conf-previous") or 
		die "Can't rename /etc/jazip.conf to /etc/jazip.conf-previous
Quiting.\n";
	} else {
	    print "Creating /etc/jazip.conf\n";
	}
	open(CONF, ">/etc/jazip.conf") or 
	    die "Cant create /etc/jazip.conf.\nQuiting.\n";
	print CONF "# Configuration file for jaZip
#
# Raw Device         Mount Point                  Read but ignored
";
	foreach ($c = 1; $c <= $Confcount; $c++) {
	    print CONF "  $ConfDevice[$c]              $ConfMount[$c]                      auto    auto        0 0\n";
	}
	close(CONF);
    }
}

sub input {
  my($message)=$_[0];
  my($defanswer)=$_[1];
  my($reply);

  printf "%-45s [%-15s]: ",$message,$defanswer; 
  $reply=<STDIN>; chop($reply); if ($reply eq "") { $reply=$defanswer; }
 
  return $reply;
}

sub yninput {
  my($message)=$_[0];
  my($defanswer)=$_[1];
  my($reply);

  while ($reply eq "") {
      printf "%s? (y/n) [%s]: ",$message,$defanswer; 
      $reply=<STDIN>; chop($reply); if ($reply eq "") { $reply=$defanswer; }
      if (($reply ne "y")&&($reply ne "n")) { $reply = "" }
  }
  return $reply;
}
