#! /usr/bin/perl -w
###############################################################################
#
#  Run-Mailcap:  Run a program specified in the mailcap file based on a mime
#  type.
#
#  Written by Brian C. White <bcwhite@pobox.com>
#  This file has been placed in the public domain (the only true "free").
#


$debug=0;
$etcmailcap="/etc/mailcap";
$usrmailcap="$ENV{HOME}/.mailcap";


sub Usage {
	my($error) = @_;
	print STDERR $error,"\n\n" if $error;

	print STDERR "Use: $0 <--options=values> [...] <mime-type:filename> [...]\n\n";
	print STDERR "Options:\n";
	print STDERR "  action        specify what action to do on these files (manditory)\n";
	print STDERR "  debug         be verbose about what's going on (any non-zero value)\n";
	print STDERR "\n";

	exit ($error ? 1 : 0);
}


sub SaveStdin {
	my($match) = @_;

	my $tmpfile;
	$tmpfile = $ENV{TMPDIR};
	$tmpfile = "/tmp" unless $tmpfile;
	$tmpfile.= "/run-mailcap-$$";
	if ($match =~ m/nametemplate=(.*?)\s*($|;)/) {
		my $tmp = $1;
		$tmp =~ s|%s|$tmpfile|;
		$tmpfile = $tmp;
	}
	open(TMPFILE,">$tmpfile") || die "Error: could not write '$tmpfile' -- $!\n";
	while (<STDIN>) {
		print TMPFILE $_;
	}
	close(TMPFILE);

	return $tmpfile;
}


foreach (@ARGV) {
	if (m/^--(.*?)=(.*)$/) {
		print STDERR "Warning: definition of '$1=$2' overrides value '${$1}'\n" if $ {$1};
		$ {$1}=$2;
	} elsif (m/:/) {
		push @files,$_;
	} else {
		Usage "Error: unrecognized option '$_'";
	}
}

Usage "Error: no action specified" unless $action;


if (open(MAILCAP,"<$usrmailcap")) {
	while (<MAILCAP>) {
		chomp;
		next unless $_;
		next if m/^#/;
		push @mailcap,$_;
	}
	close MAILCAP;
}

open(MAILCAP,"<$etcmailcap") || die "Error: could not read '$etcmailcap' -- $!\n";
while (<MAILCAP>) {
	chomp;
	next unless $_;
	next if m/^#/;
	push @mailcap,$_;
}
close MAILCAP;


foreach (@files) {
	my($type,$file) = m/^(.*?):(.*)$/;
	print "Processing file '$file' of type '$type'...\n" if $debug;

	my @matches;
	@matches = grep(/^\Q$type\E;/,@mailcap);
	@matches = grep(/\Q$action\E=/,@matches) unless $action eq "view";

	my $done=0;
	foreach $match (@matches) {
		my $comm;
		if ($action eq "view") {
			($comm) = ($match =~ m/^.*?;\s*(.*?)\s*($|;)/);
		} else {
			($comm) = ($match =~ m/\Q$action\E=(.*?)\s*($|;)/);
		}
		next unless $comm;
		print " - program to execute: $comm\n" if $debug;

		if ($match =~ m/;\s*test=(.*?)\s*;/) {
			print " - running test: $1\n" if $debug;
			next if (system $1);
		}

		my $tmpfile;
		if ($match =~ m/;\s*needsterminal\s*($|;)/ && ! -t STDOUT) {
			if ($file eq "-") {
				$tmpfile = SaveStdin($match);
				$file    = $tmpfile;
			}

			$comm = "/usr/bin/X11/xterm -T '$file ($type)' -e $0 --action=$action ${type}:${file}";

#			exec "/usr/bin/X11/xterm", "-T" ,"$0 @ARGV", "-e", $0, @ARGV;
#			$comm = "/usr/bin/X11/xterm -T '$file ($type)' -e /bin/sh -c ".'"'.$comm.'"';
#			system "/usr/bin/X11/xterm","-T","$file ($type)","-e",$0,"--action=$action","${type}:${file}";
#
#			unlink $tmpfile if $tmpfile;
#			last;
		}

		if ($file ne "-") {
			if ($comm =~ m/%s/) {
				$comm =~ s/%s/$file/g;
			} else {
				$comm.= " <$file";
			}
		} else {
			if ($comm =~ m/%s/) {
				$tmpfile = SaveStdin($match);
				$comm =~ s/%s/$tmpfile/g;
			} else {
				# no name means same as "-"... read from stdin
			}
		}

		print " - executing: $comm\n" if $debug;
		system $comm;
		$done=1;
		unlink $tmpfile if $tmpfile;
		last;
	}

	print STDERR "Error: no mailcap rule for action '$action' for type '$type'\n" unless ($done);
}
