#!/usr/bin/perl
#
#NAME
#  Helper - helper app for text files, based on suffix.
#
#SYNOPSIS
#  Helper file
#
#DESCRIPTION
#  This script acts as a sort of "generic helper" to browsers such as
#  netscape,  mosaic, and possibly others.  The browser calls helpers
#  by copying the data to a /tmp/ file.  We examine the file's  name,
#  picking off any suffix, and use that to decide what application to
#  run for that file.
#
#  The main reason you might want this program is: Netscape (and lynx
#  and  mosaic and probably most browsers) actually ignore the a file
#  suffix (aka extension), and use only the invisible HTTP  type  and
#  subtype to decide which helper to run. Thus if a server tells your
#  browser that foo.bar is "Content-Type:  text/plain\n\n", the  .bar
#  suffix  is  irrelevant.   Only one helper can exist for text/plain
#  files, and that same helper is run for all of them, regardless  of
#  any suffix that they may have..
#
#  What this Helper program does is look at the suffix, and with  the
#  help  of  instructions  that you put in your .helpers file, it can
#  start up different programs for different file suffixes.
#
#  This  scheme  is  needed because the browsers generally ignore the
#  suffix, although they ask you for it.  They only use the HTTP file
#  type  and subtype to choose a helper.  But they do seem to be nice
#  enough to propogate the suffix from the URL to the /tmp/ file that
#  they  pass to helpers.  So we can write a generic helper that does
#  the work of looking at the suffix and firing up the right program.
#
#SETUP
#  To use this as a netscape helper, you need to install it:
#
#  0.  First, put this script somewhere in your search path, and give
#  it one or more names.  We assume it is called "Helper"  here,  but
#  you can of course call it what you want.  Also, make sure that all
#  the programs it may need are installed. and in the search path.
#
#  1.  Use the Options ..  General Preferences menu to bring  up  the
#  general  config window.  Select the "Helper" tab to get the helper
#  config list.
#
#  2.  Scroll down to the "text/plain" entry and click to select it.
#
#  3.  Press the "New..." button to get the helper edit window.
#
#  4. Fill in "text/plain" as the Type and "abc" as the Suffix.  Fill
#  in  the Description field with something descriptive, such as "abc
#  music notation".
#
#  5.  Click the Application button to enable the  input  field,  and
#  fill in "Helper %s" in the input field.
#
#  6.  Press the OK button at the bottom.
#
#  7.  Press the OK button at the bottom of the Helpers window.
#
#  There, wasn't that easy?  ;-) Hey, if you want to see how  complex
#  it  can  be  made,  try  figuring  out  how  to configure Internet
#  Explorer to use this program.  If you figure it out, let me know.
#
#  I've also used this program as a helper for several other programs
#  and it's usually easy once you figure out how to get it called. It
#  is easiest with programs that I wrote myself ...
#
#DIAGNOSTICS
#  Out of general  paranoia,  we  direct  our  output  to  the  files
#  Helper.out  and  Helper.err.ps lead.  We write them in the $TMPDIR
#  directory if that is defined in the environment, or in the current
#  working directory if not.
#
#FILES
#  We read $HOME/.helpers and expect to find lines of the forms:
#    prog: suff: command
#          suff: command
#                command
#  where the prog, suff and command field are separated by colons. If
#  we  find  a  recognizable suffix, we run sprintf(command,file), so
#  you can use %s to represent the file name.
#
#  The prog field should contain the name of this program,  and  must
#  start  in  column  1.   You can install this program under several
#  names, and set it up as helpers for  several  HTTP  types  if  you
#  wish.  By using the different names, you can make it run different
#  commands for the same suffix (if the  server  generates  different
#  type/subtype values for the suffixes).
#
#  The suff is whatever comes after the last '.' in the URL.  For DOS
#  systems,  it is the last 3-char "extension".  For Unix systems, of
#  course, it can be anything.
#
#  The command is an arbitrary  character  string,  terminated  by  a
#  newline. It will be run by the perl "system" command, so any shell
#  variables will be expanded from your environment.  You can use  %s
#  to represent the file name.
#
#  Example:
#     Helper:  abc: abc2gv < %s
#              txt: xterm -e $EDITOR %s
#  The first line will only work if this program is called  "Helper";
#  the  second  line will work no matter what this program is called.
#  This is intentional:  It lets you set up several helpers  for  the
#  same suffix, by giving this program several different names.
#
#BUGS
#  Program names in .helpers must be in column 1, and  comments  must
#  be on separate lines (though they can start in any column).
#
#  Missing programs aren't handled as well as might be hoped.
#
#  There  seems to be no way for a helper application to discover the
#  name of the URL that delivered the data.  Sorry 'bout dat. Not much
#  we can do about it except to beg and plead with the browser makers
#  to fix the problem.
#
#  We should read .mailcap and .mime.types if  .helpers  is  missing.
#  This is probably something for a future release.
#
#AUTHOR
#  John Chambers <jc@trillian.mit.edu> 

$| = 1;
$" = ' ';
($me = $0) =~ s'.*/'';		# What's my name?
$V = $ENV{"V_$me"} || $ENV{"T_$me"} || $ENV{"D_$me"} || 3;
$D = $ENV{'TMPDIR'} || '.';

# Set up our default command:
$ed  = $ENV{EDITOR} || $ENV{VISUAL} || 'vi';
$dfl = 'xterm -e $ed %s';

open(STDERR,">$D/$me.err") || die "$0: Can't write $D/$me.err ($!)\n";
open(STDOUT,">$D/$me.out") || die "$0: Can't write $D/$me.out ($!)\n";
if ($V>1) {for $e (sort keys %ENV) {print "ENV{$e}=\"$ENV{$e}\"\n"}}

for $i (0 .. @ARGV) {
	print "ARGV[$i]=\"$a\"\n" if $V>1;
	next if !($a = $ARGV[$i]);	# This happens!
	if (($p,$s) = ($a =~ /(.*)\.([^.]+)$/)) {
		print "$me: Prefix \"$p\" Suffix \"$s\"\n" if $V>1;
		$path = $a;		# Full path to file.
		$suff = $s;
		if (($d,$r) = ($p =~ '^(.+)/(.+)$')) {
			print "$me: Dir \"$d\" Root \"$r\"\n" if $V>1;
		} else {
			$d = '.';
			$r = $p;
			print "$me: dir \"$d\" root \"$r\"\n" if $V>1;
		}
	} else {
		print "$me: No suffix in \"$a\"\n" if $V>1;
		$path = $a;
	}
}
print "$me: path=\"$path\"\n" if $V>2;

$h = "$ENV{HOME}/.helpers";
if (-f $h) {
	if (open(H,$h)) {
		for $line (<H>) {
			chomp $line;
			if ($line =~ m/\s*#/) {
				print "$me: Ignore \"$line\" (comment)\n" if $V>5;
			} elsif (($nam,$suf,$app) = ($line =~ m/^(\w+)\s*:\s*(\S*)\s*:\s*(.*)$/)) {
				print "$me: \"$nam\": \"$suf\" => \"$app\"\n" if $V>2;
				if ($nam eq $me) {
					$App{$suf} = $app;
				} else {
					print "$me: Ignore \"$line\" (wrong program)\n" if $V>1;
				}
			} elsif (($suf,$app) = ($line =~ m/^\s*(\S*)\s*:\s*(.*)$/)) {
				print "$me: \"$suf\" => \"$app\"\n" if $V>2;
				$App{$suf} = $app;
			} else {
				($dfl = $line) =~ s/^\s*//;
				print "$me: Default \"$dfl\"\n" if $V>1;
			}
		}
	} else {
		printf STDERR "$0: Can't read $h ($!)\n";
	}
}

if ($suff) {
	if ($app = $App{$suff}) {
		print "$me: \"$suf\" is \"$app\"\n" if $V>2;
		$cmd = sprintf($app,$path);
		print "$me: cmd=\"$cmd\"\n" if $V>1;
#		system "$cmd & wait";
		exec $cmd;
		exit;
	} else {
		print "$me: No helper found for \"$suff\"\n" if $V>0;
	}
} else {
	print "$me: No suffix found in \"$path\"\n" if $V>0;
}

print "$me: Using default command \"$dfl\"\n" if $V>0;
$cmd = sprintf($dfl,$path);
print "$me: cmd=\"$cmd\"\n" if $V>1;
#system "$cmd & wait";
exec $cmd;
exit;
