#! /usr/bin/perl

# Maintained by Eduard Bloch <edi@ka.linux.de>
#
# "ucat" is a wrapper for zcat, bzcat, zip, tar. It runs the correct unpack
# program depending on the file extension or the detected file contents.
# 
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# -----------------------------------------------------------------------
# If you make changes to this script, please feel free to forward the new 
# version to eduard@bloch.com or Andre.Karwath@informatik.tu-chemnitz.de
# -----------------------------------------------------------------------

&load_strings;

# localisation part (only german at the moment):
if($ENV{'LANG'}=~ "^de"){
   &load_de_strings;
}

&print_usage if ($#ARGV<0 || $ARGV[0] eq "-h");
  
#from unp
sub set_command {

   my %cand;
   my $lastcmd;
   
   # test passed alternatives until an unstalled tool has been found
   for $cmd (@_) {
      $cmd =~ /^(\S+)(\s|$)/;
      my $prog=$1;
      # HACKS
      set_command("mpack") if($prog eq "formail");
      for(split(/:/,$ENV{"PATH"})) {
         if(-x "$_/$prog") {
            $command=$cmd;
            goto FIX_VARS;
         }
         $lastcmd=$cmd;
         $cand{$prog}=$prog;
      }
   }

   # no hit in $PATH, print installation hints to the user
   # override with custom package names where needed
   for(keys %cand) { $cand{$_}=$pkgmap{$_} if( defined($pkgmap{$_}) ); }
   print "$nopack ".join(" $or ", keys %cand)."\n$plzinst".join(" $or ", values %cand)."\n";

   # abort unless forced...
   $force || exit 1;
   $command=$lastcmd;

   FIX_VARS:
   $ENV{"UNP_FILE"}=$UNP_FILE;
   $ENV{"TARGET"}=$UNP_TARGET;
   $command=~s/\$UNP_FILE/"\$UNP_FILE\"/g;
   $command=~s/\$UNP_TARGET/"\$UNP_TARGET"/g;
   $command=~s/\$UNP_ARGS/"\$\@"/g;

}

# slightly modified version from unp
sub testfile {

   my $uncompcmd;
   my $UNP_FILEstr;
   if(open(fd, "-|", "file", $UNP_FILE))
   {
      while(<fd>)
      {
         if(/(gzip)/si) { $uncompcmd='zcat'; }
         elsif (/(bzip2)/si) { $uncompcmd='bzcat'; }
         elsif (/(lzop)/si) { $uncompcmd='lzop -d <'; }
         else
         {
            $UNP_FILEstr.=$_;
            next;
         }
         last;
      }
      close(fd);
   }
   if($uncompcmd)
   {
      set_command $uncompcmd.' $UNP_FILE';
      return;
   }
   
   $UNP_FILEstr=~s/^.*?://;
   if ($UNP_FILEstr =~ /RAR.*archive/i) { set_command('rar p $UNP_ARGS $UNP_FILE || rar p -av- $UNP_ARGS $UNP_FILE','unrar p $UNP_ARGS $UNP_FILE || unrar p -av- $UNP_ARGS $UNP_FILE'); }
   if ($UNP_FILEstr =~ /tar.*archive/i) { set_command 'tar -x -O $UNP_FILE $UNP_ARGS'; }
   if ($UNP_FILEstr =~ /LHa.*archive/i) { set_command 'lha p $UNP_ARGS $UNP_FILE'; }
   if ($UNP_FILEstr =~ /Zip.*archive/i) { set_command 'unzip -c $UNP_ARGS $UNP_FILE'; }
   if ($UNP_FILEstr =~ /Zoo.*archive/i) { set_command 'unzoo -x -p $UNP_ARGS $UNP_FILE'; }
   if ($UNP_FILEstr =~ /uuencoded/i) { set_command 'uudecode -o - $UNP_ARGS $UNP_FILE'; }

   # if still nothing could be found, print an error message
   if ($command eq "") {
      print $UNP_FILE.$unsup;
      next LOOP;
   }
}


LOOP: foreach $UNP_FILE (@ARGV) {

  if ((!-r $UNP_FILE) && (!$stdin)) {
     print STDERR $UNP_FILE.$not_read;
     next LOOP;
  }
  
	if (-d $UNP_FILE) {
     print STDERR $UNP_FILE.$is_dir;
     next LOOP;
  }
  &doit;
}

sub doit {
   &testfile;
   #    retry. On failure, tell user to install the packer

    if(0!=system("/bin/sh", "-c", $command, @ARGS))
   {
      $bin=((split(/\s/,$command))[0]);
      if(!length(`which $bin`)) {
         die "
         Could not locate the program $bin. Please
         install a package that provides it, for example $bin.\n";
      }
   }
}

# -----------------------------------------------------------------------------
sub print_usage {
  print $usage;
	die "\n";
}
# -----------------------------------------------------------------------------

sub load_de_strings {
   $not_found=" wurde nicht gefunden!\n";
   $not_read=" konnte nicht gelesen werden!\n";
   $unsup=": dieses Format wird nicht unterstuetzt!\n";
   $usage="
   Aufruf: ucat Datei [Datei] ...
   Datei: eine oder mehrere komprimierte Datei(en) zum entpacken und ausgeben
   ";

   $tryfile=" - Endung unbekannt, ueberpruefe mit \"file\"...
   ";
   $testbz2=" enthlt bzip2-komprimierte Daten, ueberpruefe den Datentyp...\n";
   $testgz=" enthlt gzip-komprimierte Daten, ueberpruefe den Datentyp...\n";
   $testlz=" enthlt lzop-komprimierte Daten, ueberpruefe den Datentyp...\n";
   $skip=" existiert bereits, ueberspringe...\n";
   $is_dir=" ist ein Verzeichnis\n";
}

sub load_strings {
   $usage="
   usage: ucat file [file]...
   file: compressed file(s) to expand and output
   ";

   $tryfile=" - unknown extension, checking with \"file\"\n";
   $testbz2=" contains bzip2-compressed data, determining data type...\n";
   $testgz=" contains gzip-compressed data, determining data type...\n";
   $testlz=" contains lzop-compressed data, determining data type...\n";
   $skip=" exists allready, skipping...\n";
   $is_dir=" is a directory, skipping...\n";

}
