#!/usr/bin/env perl
# -*- perl -*-
#	pod - an aide to setting search paths using structured software areas
#
#	Christopher Alexander North-Keys
#	0.1 Sun Aug 29 03:59:36 CDT 1993 (begun)
#	0.2 Mon Aug 30 09:15:07 CDT 1993
#	0.3 Mon Sep 20 03:54:56 CDT 1993 (added LD_LIBRARY_PATH)
#	0.4 Mon Sep 20 10:09:04 CDT 1993 (rewrite)
#	0.5 Wed Jun 14 04:39:33 CDT 1995 (another rewrite, in perl)
#	0.6 Tue Apr 23 11:55:40 CDT 1996 (add catman support)
#	0.7 Fri Aug 16 12:19:53 CDT 1996 (backwards compat with perl4)
#	0.8 Wed Nov 19 11:56:23 CST 1997 (added strict, $format, multiple outputs)

use strict;

my $version = '0.9 Wed Nov 19 16:17:13 CST 1997';

my @pods = ();
my $pod = '/pod';				# dir in which all pods are located
my $env = 'PODS';				# envvar listing pod to prefix to default pods
my $nis = 'auto.pod';			# default pods
my $etc = '/etc/pods';			# default pods
my $path_delim = ':';			# delimiter for paths upon output
my $path_delim_frenzied = 0;	# replace ':' with $path_delim in %e
my $cull = 1;					# whether to cull nonextant path components
my $format = "%p%n";

my %PathVar;
$PathVar{'bin'}     = 'PATH';
$PathVar{'man'}     = 'MANPATH';
$PathVar{'lib'}     = 'LDPATH';	# should be copied to LD_LIBRARY_PATH as well
$PathVar{'include'} = 'INCPATH';

sub Version
{
	print("pod Copyright (c) 1993-1997 C. Alex. North-Keys "
		  . '<erlkonig@talisman.org>'. "\n"
		  . "Version: $version\n");
	print("Prehistory:\n"
		  . "\tConceptualized in 1989 as a way of handling large software\n"
		  . "\tcollections in a standard way that retained their package\n"
		  . "\tidentity.  At that time, most admins were simply putting\n"
		  . "\teverything in /usr/local.  First used with /vol at the Freie\n"
		  . "\tUniversität Berlin (math.fu-berlin.de), then later on /pod\n"
		  . "\tat Origin Systems (origin.ea.com).  These prototypes showed\n"
		  . "\tgreat potential when used in combination with the\n"
		  . "\tautomounter, since packages were now accessed by package\n"
		  . "\tname, and the underlying location of the data both hidden\n"
		  . "\tand dynamically modifiable by the admin.  Basically this\n"
		  . "\tmeans admins may move packages around the net w/o warning.\n"
		  );
	print("Notes:\n"
		  . "\tThis version is designed to allow sufficient output control\n"
		  . "\tso as to generate all the needed eval(1)-able output for any\n"
		  . "\tshell with only one call to pod(1).\n"
		  );
}

sub Help
{
	print("Syntax:\n"
		  . "  pod [ -h | -v | -p ]\n"
		  . "  pod [-s <podlist>] [-k] [-[d|D] <delim>] -[b|i|l|m] [--] "
		  . "[<cmd...>]"
		  . "\n"
		  . "\t-h    help, output this help (the default) and exit\n"
		  . "\t-v    version, output version information/commentary and exit\n"
		  . "\t-p    pods, output the current pod list and exit\n"
		  . "\n"
		  . "\t-s    set pod list to <podlist> (delimited by \":\" or \" \")\n"
		  . "\t-k    keep nonextant path elements, which normally are culled\n"
		  . "\n"
		  . "\t-d    delim, set the path delimiter to be <delim> (not \"@\")\n"
		  . "\t-D    like -d, but also replaces \":\" in %e (for *csh users)\n"
		  . "\t-f    format, set format string for path outputs.  Escapes:\n"
		  . "\n"
		  . "\t-b    bins, output the pod command (bin) search path\n"
		  . "\t-i    incs, output the pod include search path\n"
		  . "\t-l    libs, output the pod library search path\n"
		  . "\t-m    mans, output the pod manual search path\n"
		  . "\t      %p - full path\n"
		  . "\t      %t - path type (ie: 'bin', 'man', 'lib', 'inc')\n"
		  . "\t      %v - path variable (ie: PATH, MANPATH, LDPATH, INCPATH)\n"
		  . "\t      %e - pre-existing environment value of corresponding %v\n"
		  . "\t      %n - newline\n"
		  . "\t--    no more options (anything following is <cmd>)\n"
		  . "\tWith <cmd>, runs a cmd with PATH, MANPATH, LDPATH, INCPATH,\n"
		  . "\t      LD_LIBRARY_PATH, and INCPATH variables, modified to\n"
		  . "\t      include elements as would be seen by -b, -l, and -m.\n"
		  . "\tMultiple path requests are output one per line,\n"
		  . "\t      each formatted as directed by -f (default \"%p\\n\"\n"
		  . "\tpod catenates available pods (unless overriden by -s) from:\n"
		  . "\t      the PODS environment variable, if it exists\n"
		  . "\t      the ", $etc, " file (or output of, if executable)\n"
		  . "\t      the ", $nis, " NIS map\n"
		  . "\n"
		  . "Example for sh family:\n"
		  . "\t" . 'eval `pod \\' . "\n"
		  . "\t\t" . '-f "%v=$HOME/bin:%e:/usr/games:%p\n" -b \\' . "\n"
		  . "\t\t" . '-f "%v=/usr/man:/usr/local/man:%p\n" -m \\' . "\n"
		  . "\t\t" . '-f "%v=/usr/lib:/usr/local/lib:%p\n" -l \\' . "\n"
		  . "\t\t" . '-f "%v=/usr/include:/usr/local/include:%p\n" -i`' . "\n"
		  . "\t" . 'LD_LIBARY_PATH=$LDPATH	# compatibility' . "\n"
		  . "\texport PATH MANPATH LDPATH LD_LIBRARY_PATH INCPATH\n"
		  );
	return 0;
}

sub SetPods
{
	return if(0 + @pods);

	my (@nis_pods, @etc_pods, @env_pods);

	@env_pods = split(/:/, $ENV{$env});

	if(open(ETC, (-x $etc ? "$etc |" : $etc)))
	{
		my $line;
		while($line = <ETC>)
		{
			push(@etc_pods, split(' ', $line));
		}
		close(ETC);
		chomp(@etc_pods);
	}

	if(open(NIS, 'ypcat -k ' . $nis . ' 2>/dev/null |' ))
	{
		@nis_pods = <NIS>;
		close(NIS);
		chomp(@nis_pods);
		@nis_pods = grep(s/^(\w*)\W.*$/\1/, @nis_pods);
		@nis_pods = sort(@nis_pods);
	}

	@pods = (@env_pods, @etc_pods, @nis_pods);
}

sub Path						# arg:subdir ret:0 out:pathtext 
{
	my(@subs) = @_;			# sought subdirectories
	&SetPods();
	my($dirs, $pod, $sub, $dir);
	for $pod (@pods)
	{
		for $sub (@subs)
		{
			my $dir = "/pod/" . $pod . "/" . $sub;
			if( (!$cull) || -d $dir )
			{
				$dirs = $dirs . $path_delim if ($dirs);
				$dirs = $dirs . $dir;
			}
		}
	}
	return $dirs;
}

sub PathSetAll
{
	$ENV{'PATH'} =
		join($path_delim, (&Path('bin'), $ENV{'PATH'}));
	$ENV{'MANPATH'} =
		join($path_delim, (&Path('man'), $ENV{'MANPATH'}));
	$ENV{'LDPATH'} =
	$ENV{'LD_LIBRARY_PATH'} =
		join($path_delim, (&Path('lib'), $ENV{'LD_LIBRARY_PATH'}));
	$ENV{'INCPATH'} =
		join($path_delim, (&Path('include'), $ENV{'INCPATH'}));
}

sub PathOutput	# 'bin'|'lib'|'include'|'man' 
{
	my (@types) = @_;

	if(@types[0] eq 'man')
	{
		my (@mandirs) = 'man';
		splice(@mandirs, @mandirs, @mandirs, 'catman')
			if(-d '/usr/catman' || -d '/usr/share/catman');
		@types = @mandirs;
	}
	my $output = $format;
	my $p_replacement = &Path(@types);
	my $t_replacement = $types[0];
	my $v_replacement = $PathVar{$t_replacement};
	my $e_replacement = $ENV{$v_replacement};
	$e_replacement =~ s/:/$path_delim/g	if($path_delim_frenzied); #csh
	$output =~ s/%p/$p_replacement/g;
	$output =~ s/%t/$t_replacement/g;
	$output =~ s/%v/$v_replacement/g;
	$output =~ s/%e/$e_replacement/g;
	$output =~ s/%n/\n/g;
	print($output);
}

sub main
{
	my(@argv) = @_;
	my($i);
	my($sought);				# what sought: bin lib man, (etc)?

	if (0 == @argv) { return ! &Help; } # should use stderr
	for($i = 0 ; $argv[$i] =~ /^-/ ; ++$i) 
	{
		my    ($x) = $argv[$i];
		if    ($x =~ /^-h/) { return &Help; }
		elsif ($x =~ /^-v/) { return &Version; }
		elsif ($x =~ /^-k/) { $cull = 0; }
		elsif ($x =~ /^-s/) { @pods = split('[: ]', $argv[++$i]); }
		elsif ($x =~ /^-d/) { $path_delim = $argv[++$i];
							  $path_delim_frenzied = 0;}
		elsif ($x =~ /^-D/) { $path_delim = $argv[++$i];
							  $path_delim_frenzied = 1;}
		elsif ($x =~ /^-p/) { &SetPods; return print(join(' ', @pods), "\n"); }
		elsif ($x =~ /^-b/) { &PathOutput('bin'); }
		elsif ($x =~ /^-l/) { &PathOutput('lib'); }
		elsif ($x =~ /^-i/) { &PathOutput('include'); }
		elsif ($x =~ /^-m/) { &PathOutput('man'); }
		elsif ($x =~ /^-f/) { $format = $argv[++$i]; }
		elsif ($x =~ /^--/) { ++$i; last; }
		else                { return ! &Help; } 		# oops
	}
	if($i < @argv)
	{
		&PathSetAll;
		splice(@argv, 0, $i);
		print(join(' ', @argv) . "\n");
		exec(@argv);
		print("pod - exec: requested execution could not be accomplished.\n");
	}
}

&main(@ARGV);

# Local Variables: #
# tab-width: 4 #
# End: #
#-----------------------------eof
