#!/usr/local/bin/perl
#
# nswrap --
#	wrapper to netscape to make it friendlier to the system
#
# To install:
#	- rename netscape to ns.real, and change permissions to
#	  root:cpuhogs 550
#	- install this as netscape, permissions root:cpuhogs 2555
#	- change $global::NSHOME below to the correct directory


use Sys::Hostname;
use strict;

require "sys/resource.ph";
require "sys/syscall.ph";

require "dumpvar.pl";

$global::NSHOME=	"/usr/local/pkg/navigator4.73";
$global::NSPROG=	"ns.real";
$global::NSPATH=	"${global::NSHOME}:/usr/local/bin:/bin";
$global::NSAUTOPROXY=	"http://www.cs.rmit.edu.au/proxy.pac";
$global::NSMEMCACHE=	200;
$global::NS_CPULIMIT =	3600;
$global::NSPRIORITY =	16;
%global::NSGROUPPRIO = (
		#
		# map of: gid -> priority to run at
		#
		# consequences of a user not matching:
		#	- netscape will run at $NSPRIORITY
		#	- if $NSHOME/.restricted exists, they won't be
		#	  permitted to run netscape.
		#
		#	gid	priority
		#	---	--------
			100,	10,	# staff
			104,	10,	# rpgrads
			110,	4,	# tsg
			124,	10,	# helpdesk
);

main();
exit(0);

#	------

sub
main()
{
	my ($home, $prio, $pid);

	($home, $prio) = getuserinfo();

	$ENV{'MOZILLA_HOME'} =		$global::NSHOME;
	$ENV{'PATH'} =			$global::NSPATH;
	$ENV{'MOZILLA_NO_ASYNC_DNS'} =	'true';

	$pid = find_process($home, @ARGV);

	if ($pid == -1) {		# no netscape running
		rewrite_prefs($home);
		lower_priority($prio);
		limit_resources();
	} else {			# fudge args to connect to existing
		my (@NARGV, $a, $hasurl);

		$hasurl = 0;
		while ($a = shift(@ARGV)) {
			if ($a eq "-remote") {
				push(@NARGV, $a, shift(@ARGV));
				$hasurl++;
			} elsif ($a =~
			    /^-(display|geometry|visual|ncols|xrm|id)$/) {
				push(@NARGV, $a, shift(@ARGV));
			} elsif ($a =~ /^-/) {
				push(@NARGV, $a);
			} else {
				push(@NARGV,
				    "-remote", "openURL($a,new-window)");
				$hasurl++;
			}
		}

		if (! $hasurl) {
			print "Attaching to existing netscape process\n";
			push(@NARGV,
			    "-remote", "openURL(about:blank,new-window)");
		}
		@ARGV = @NARGV;
	}
	exec { "${global::NSHOME}/${global::NSPROG}" } "netscape", @ARGV;
	die("netscape: $!\n");
}


#	get info about the user
#	returns the home directory and the priority to run as
#
sub
getuserinfo()
{
	my (@user, $home, $prio, $group, $p, $prioset);

	@user = getpwuid($<);
	if (scalar(@user) == 0) {
		die("netscape: Who are you?\n")
	}
	$home = $user[7];
	$prio = ${global::NSPRIORITY};
	$prioset = 0;
	foreach $group (split(' ', $()) {
		$p= $global::NSGROUPPRIO{$group};
		if (defined($p) && $p< $prio) {
			$prio = $p;
			$prioset = 1;
		}
	}

	if (! $prioset && -e "${global::NSHOME}/.restricted") {
		die("netscape: You are not permitted to run this version.\n");
	}

	return ($home, $prio);
}


#	determine if netscape is running on this host.
#	if so, return its pid
#	if it appears to be running on another machine, return 0
#	otherwise, return -1.
#
sub
find_process()
{
	my ($home, @NARGV) = @_;

	my ($hostname, $lock, $link, $host, $pid);
	my (@addrs, $ip, $dot, $rv);

	$hostname = hostname;
	@addrs = (gethostbyname($hostname));
	if (! scalar(@addrs)) {
		die("Can't gethostbyname $hostname - $!\n");
	}
	splice(@addrs, 0, 4);

	$lock = $home . "/.netscape/lock";
	if (! -l $lock) {
		return (-1);
	}

	$link = readlink($lock);
	if (! defined($link)) {
		die("netscape: can't readlink $lock\n");
	}
	($host, $pid) = $link =~ /(.+):(.+)/;

	$dot = "";
	foreach $ip (@addrs) {
		$dot = join('.', unpack('C4', $ip));
		if ($dot eq $host) {
			last;
		}
	}
	if ($dot ne $host) {		# running on another host
		return (0);
	}

	$rv = kill 0, $pid;
	if ($rv == 0) {
		print <<NOTRUNNING;
Removing stale lock file.
NOTRUNNING
		unlink($lock);
		return(-1);
	}

	return ($pid);
}



#	rewrite preferences to remove cache and use the proxy
#
sub
rewrite_prefs()
{
	my ($home) = @_;

	my ($prefs, $prefsorig);

	$prefs = $home . "/.netscape/preferences.js";
	if (-f $prefs) {
		$prefsorig = $prefs . ".BAK";
		rename($prefs, $prefsorig);
		open(IN, "$prefsorig") ||
		    die("netscape: can't read preferences file\n");
		open(OUT, "> $prefs") ||
		    die("netscape: can't read preferences file\n");
		while (<IN>) {
			next if /"browser.cache.disk_cache_size"/;
			next if /"browser.cache.memory_cache_size"/;
			next if /"network.proxy.autoconfig_url"/;
			next if /"network.proxy.type"/;
			print OUT;
		}
		print OUT <<BWAHAHAHA;
user_pref("browser.cache.disk_cache_size", 0);
user_pref("browser.cache.memory_cache_size", "$global::NSMEMCACHE");
user_pref("network.proxy.autoconfig_url", "$global::NSAUTOPROXY");
user_pref("network.proxy.type", 2);
BWAHAHAHA
		close(OUT);
		close(IN);
		unlink($prefsorig);
	}
}


#	lower priority if necessary
#
sub
lower_priority()
{
	my ($newprio) = @_;

	my ($prio);

	$prio = getpriority(&PRIO_PROCESS, $$);
	if ($prio == -1) {
		die("netscape: can't getpriority\n");
	}
	if ($prio < $newprio) {
		if (setpriority(&PRIO_PROCESS, $$, $newprio) == -1) {
			die("netscape: can't setpriority\n");
		}
	}
}


#	set resource limits to prevent core dumps & limit cpu time
#
sub
limit_resources()
{
	my ($lim);

	if (defined (&SYS_setrlimit)) {
		$lim = pack("LL", 0, 0);
		syscall(&SYS_setrlimit, &RLIMIT_CORE, $lim);

		$lim = pack("LL", $global::NS_CPULIMIT, $global::NS_CPULIMIT);
		syscall(&SYS_setrlimit, &RLIMIT_CPU, $lim);
	}
}
