#!/afs/athena/contrib/perl/perl
#
# scan a tape device, printing a summary of the contents.
#
# by Albert Dvornik <bert@mit.edu>
#
# $Id$

unshift(@INC, '/afs/athena.mit.edu/user/b/e/bert/project/tape');
require('pipecmd.pl');

### defaults

$DEVICE = '/dev/nrmt0h';	# tape device

### sighandler...
sub handler {
    local($sig) = @_;
    print "*** CAUGHT SIG$sig: QUITTING AFTER THIS OPERATION COMPLETES ***\n";
    print LOG "(CAUGHT SIG$sig: QUITTING AFTER THIS OPERATION COMPLETES)\n";
    $QUIT++;
    # I don't think this is needed at all, but it can't hurt.
    $SIG{$sig} = 'IGNORE';
}

### usage info

sub usage {
    local($prog) = $0;
    $prog =~ s@.*/@@g;
    print <<"EndOfUsage";

Usage: $prog [options] [tape-device]
Options:
  -d    debug
  -v    verbose
  +e    eject the tape when done

The device defaults to $DEVICE.

Ctrl-C will abort the operation *after* the operation in progress is finished.

EndOfUsage
    exit 0;
}

### main body

# Ctrl-C exits in a more controlled fashion.
# $SIG{'INT'} = $SIG{'QUIT'} = 'handler';

# arg parsing

$| = 1;

while ($ARGV[0] =~ /^-/) {
    ($ARGV[0] =~ /^-d/)  && (shift @ARGV, $debug++, next);
    ($ARGV[0] =~ /^-v/)  && (shift @ARGV, $verbose++, next);
    ($ARGV[0] =~ /^\+e/) && (shift @ARGV, $eject++, next);
    ($ARGV[0] =~ /^-e/)  && (shift @ARGV, $eject=0, next);
    &usage();
}

$DEVICE = shift(@ARGV) if @ARGV;

@ARGV && &usage();

# set up environment

%ENV = ('PATH', $ENV{'PATH'} . ":/mit/gnu/bin",
	'TAPE', $DEVICE);

# attach gnu if necessary

system('/bin/athena/attach', 'gnu') if ( ! -e '/mit/gnu' );

# rewind the tape

&check_exit_code('mt rewind', system('mt', '-f', $DEVICE, 'rewind'));

# now just read the device while we can.

while (1) {
    # if verbose, print the status
    if ($verbose) {
	$nn++;
	&check_exit_code('mt status',
			 system("mt -f $DEVICE status > /tmp/status.$nn"));
    }

    # run "dd | tar tvf", but with slightly more control
    &pipecmd'set_upstream_cmd('$quit++; @dd=($err,$sig);',
			      'dd', 'bs=10k', 'conv=nomulti', "if=$DEVICE");
    &pipecmd'set_downstream_cmd('$flako++;',
				'gtar', 'tvf', '-');
    &pipecmd'run;
    &pipecmd'wait (undef, 1);

    print "warning: tar failed, continuing with the tape" if $flako;
    die "dd failed, error code $dd[0] (signal $dd[1])\naborting" if $quit;
}

# check error return from system()

sub check_exit_code {
    local($name, $sys) = @_;
    print ">> `$name' returned $sys.\n" if $debug;
    if ($sys) {
	local($err,$sig) = ($sys >> 8, $sys & 0xFF);
	die "`$name' failed with error code $err (signal $sig)\ngiving up";
    }
}
