#!/usr/bin/perl

use strict;

# Version 1.3

#---------------------------------------------------------#
# CHANGE THIS IF YOU PLACED THE FILES WITH FROM/TO ARRAYS #
# SOMEWHERE ELSE (default is /usr/local/etc)    #
my $sysdir='';
#---------------------------------------------------------#

my $pwd_program='pwd';
my $ls_program='ls -R ';
my @args=();
my ($i,$l,$n);
my $arg='';
my $fromfile='';
my $tofile='';
my $pref='';
my $path='';
my $s='';
my $file='';
my @files=();
my $fromstr='';
my $tostr='';
my $key='';
my $value='';
my %cvt=();
my @pa=();
my $t='';
my $c='';
my @str=();
my $VERSION='1.3';
my $silent=0;
my $fileexpected=0;
my %proc=();
##############################################################################

sub Warn{
  warn $_[0]."\n" unless $silent;
}

if ($sysdir eq '') {
  $sysdir='/usr/local/etc';
}

@args=split(' ',join(' ',@ARGV));
for ($i=0;$i<scalar(@args);$i++) {
  $arg=$args[$i];
  if ($arg eq '--from' || $arg eq '-f') {
    $fromfile=$args[$i+1];
    if ($tofile ne '') {
      $fileexpected=1;
    }
    $i++;
  } elsif ($arg eq '--to' || $arg eq '-t') {
    $tofile=$args[$i+1];
    if ($fromfile ne '') {
      $fileexpected=1;
    }
    $i++;
  } elsif ($arg eq '--silent' || $arg eq '-s') {
    $silent=1;	
  } elsif ($fileexpected) {
    # we expect file only if $from and to file are specified
    # put all file masks into a single array
    for ($l=$i;$l<scalar(@args);$l++) {
      if (-d $args[$l]) {
	$pref=`$pwd_program`;
	chomp($pref);
	$path=$pref.'/'.$args[$l].'/';
	open(DATA,"$ls_program $args[$l] |");
	$path=~s|//|/|ig;

	while ($s=<DATA>) {
	  chomp($s);
	  if ($s=~m|:$|) {
	    $path=$pref.'/'.$s.'/';
	    $path=~s|//|/|ig;
	    $path=~s|:||ig;
	    next;
	  }
	  $path=~s|//|/|ig;
	  $file=$path.$s;
	  if (-e $file && -f $file) {
	    push(@files,$file);
	  }
	}
	close(DATA);
      } else {
	push(@files,<$args[$l]>);
      }
    }
    $file.=$arg;
    last;
  } else {
    Usage();
  }
}

if ($fromfile eq '' || $tofile eq '') {
  Usage();
}

Warn "MTC - Multifile Text encoding Converter $VERSION";
Warn "(C)1998-2001 Artem Koutchine, Alexander Trapeznikov";
Warn "Converting from $fromfile to $tofile";

if ($file eq '') {
  Warn "Reading from standard input";
  @files=('-');
}

open (FROMFILE,"$sysdir/$fromfile");
open (TOFILE,"$sysdir/$tofile");
$fromstr=<FROMFILE>;
$tostr=<TOFILE>;
close FROMFILE;
close TOFILE;
$fromstr=~s/[\n\r]//g;
$tostr=~s/[\n\r]//g;

# construct an associative array where array{from} = to
for ($i=0;$i<length($fromstr);$i++) {
  $key=substr($fromstr,$i,1);
  $value=substr($tostr,$i,1);
  if ($value ne '') {
    $cvt{$key}=$value;
  }
}

# now process the input file(s)
# we must keep owner and mode untouched
# and we also process ONLY plain files
for ($n=0;$n<scalar(@files);$n++){
$proc{$files[$n]}=1;
}
@files=keys (%proc);
@files=sort @files;
foreach $file (@files) {  
  if (-f $file || $file eq '-') {
    if ($file ne '-') {
      Warn "Processing: $file";
      # make a backup copy of it
      unless (rename $file,"$file.tmp") {
        Warn "Cannot rename $file into $file.tmp";
        exit 2;
      }
      ;
      unless (open (FILE,"$file.tmp")){
        Warn "Cannot process $file (.tmp)";
        unless (rename "$file.tmp","$file"){
	  Warn "Cannot rename $file.tmp back to $file. Do it yourself.";
        }
        exit 3;
      }
      unless (@pa=stat("$file.tmp")){
        Warn "Cannot obtain file information for $file because $!";
        exit 4;
      }
      unless (open RFILE, ">".$file){
        Warn "Cannot create resulting file $file  : $!";
        unlink ($file);
        unless (rename "$file.tmp","$file"){
	  Warn "Cannot rename $file.tmp back to $file. Do it yourself.";
        }
        exit 5;
      }
      truncate(RFILE,0);
      seek(RFILE,0,0);
    } else {
      unless (open (FILE,"$file")){
        Warn "Cannot read from standard input.";
        exit 6;
      }
      unless (open RFILE, ">".$file){
        Warn "Cannot write to standard output.";
        exit 7;
      }
    }
    @str=<FILE>;
    close(FILE);
    for ($n=0;$n<scalar(@str);$n++) {
      $t=$str[$n];
      # convert only the ones from $fromstr, others leave alone
      for ($i=0;$i<length($t);$i++) {
	$c=substr($t,$i,1);
	if ($cvt{$c} ne '') {
	  print RFILE "$cvt{$c}";
	} else {
	  print RFILE "$c";
	}
      }
    }
    close RFILE;
    if ($file ne '-') {
      unless (unlink "$file.tmp") {
	Warn "Warning: Cannot delete $file.tmp";
      }
      chown $pa[4],$pa[5],$file;
      chmod $pa[2],$file;
    }
  }
}

exit 0;

sub Usage {
  warn <<TEND;
MTC - Multifile Text encoding Converter 
(C)1998-2001 Artem Koutchine, Alexander Trapeznikov 
Version: $VERSION

Usage:
    mtc --from <fromcp> --to <tocp> [--silent] [filemask1] [ffilemask2] ...
Where:
    filemask - a file/directory or a wildcard file mask (e.g. *.html)
               if filemask is not specified, mtc works as pipe
    fromcp   - codepage to convert from
    tocp     - codepage to convert to
    --silent - turns off all information messages

    --from = -f, --to = -t, --silent=-s
    Available codepage with this release:
        koi8, win1251, dos866
Examples:
    mtc --from koi8 --to win1251 handbook.txt faq.txt ./etc
    mtc --from win1251 --to koi8 *.html *.htm
    mtc -f koi8 -t dos866 printdoc.txt
    cat printdoc | mtc -f koi8 -t dos866 -s | lpr -Rsmb
TEND
exit 1;
}


