#!/usr/bin/perl -w
#do not even think about running this with a uncontrolled environment
#(suid without sudo) 
#$Id: scsidev2,v 1.3 2001/07/17 09:56:16 andi Exp $

%types = (
	"CD-ROM" => "sr",
	"Processor" => "sg",
	"WORM" => "sg",     # ?? sr
	"Printer" => "sg",
	"Scanner" => "sg", 
	"Optical" => "sr",  # ?? sd
	"Changer" => "sd",
	"Communication" => "sg",
	"Direct" => "sd",
	"Sequential" => "st",
);

%majors = ( 
	"sd" => 8,  
	"sr" => 11,  
	"st" => 9,
	"sg" => 21,
);

$tmpmount = 0;
@devices = ();

print "mkdir -m 0644 /dev/scsi\n" unless (-d "/dev/scsi");   

if (!open(F, "</proc/scsi/scsi")) {
	if ( ! -d "/proc/scsi" ) { ## mount it temporarily
		system("/bin/mount -t proc proc /proc");
		$tmpmount = 1;
	}
	open(F, "</proc/scsi/scsi") || &out("open of /proc/scsi/scsi");
}

print "cd /dev/scsi\n"; 
L: while (<F>) { 
	next unless 
	@n = /^Host: (\S+) Channel: (\d+) Id: (\d+) Lun: (\d+)/;

	my ($type, $major, $minor) = ("g", 0, 0);
	while (<F>) { 
		next L unless /^\s/;
		if (/Type:\s+(\S+)/) { 
			$type = $1;
			last;
		}
	}

	($type, $major, $minor) = &engine($type,@n);  
}
&ende(0);  

sub ende { 
	my ($r) = (@_);
	system("umount /proc") if $tmpmount;
	exit($r);
}

sub out { 
	my ($msg) = (@_);
	print STDERR "$0: $msg: $!\n";
	&ende(1);
}

sub make { 
	my ($type, $major, $minor, @n) = (@_);
	
	my $dev = "$n[0]_${type}_$n[1]$n[2]$n[3]";

	my $cmd = "mknod $dev b $major $minor";

	print "$cmd\n"; 
}

sub magic { 
	my ($type, $major,@n) = (@_);
	my $minor;
	$minor = 0 unless $minor = $devices[$major]; 
	my $running = $minor; 

	# XXX: support RAID controllers
	if ($major == 8 || ($major >= 65 && $major <= 71)) {  #disk
		$running += 16;
		$major += ($minor / 256) - 1 + 65 if ($minor >= 256);  
	} elsif ($major == 9) {  #tape	      
	    	&make("nst", $major, $minor + 128, @n); 
	    	&make("nstl", $major, $minor + 128 + 16, @n); 
	    	&make("nstm", $major, $minor + 128 + 2*16, @n); 
	    	&make("nsta", $major, $minor + 128 + 3*16, @n); 
	    	&make("stl", $major, $minor + 16, @n); 
	    	&make("stm", $major, $minor + 2*16, @n); 
	    	&make("sta", $major, $minor + 3*16, @n); 
		$running++;	      
	} else {
		$running++;
	}

	&make($type, $major, $minor, @n);
	$devices[$major] = $running;
} 

sub engine {
	my ($t,@n) = (@_);
	my ($type, $major); 

	$type = "g"; 
	foreach $k (keys %types) { 
		$type = $types{$k} if ($t =~ /$k/i); 
	}
	unless ($major = $majors{$type}) { 
		$major = $majors{"sg"};
	}

	&magic($type, $major, @n);  
}
