#!/usr/bin/perl5.003 ############################################################################### # # CONFIGURABLE THINGS # ############################################################################### system("echo $0: 1 >> /tmp/progname"); # The value of this variable is a colon-separated list of directories # where Perl5 will look for required files. The files this program uses # are msgs.pl and tfr.pl. So find those files and put their directories # between the quotes - separating them by colons if they are in more than # one location. $main::localpl_dir = "/usr/local/lib/perl5"; # What's the location of the master configuration file. There is no way # to specify an alternative file. You must put it in here. (Of course # your free to change the contents of this file to point to other files, # if you want to change your configuration on a regular basis. See the manual # page for more details.) $main::master_config_file = "/usr/local/lib/ppp/master.cfg"; ############################################################################### # # DON'T CHANGE ANYTHING BELOW HERE # ############################################################################### use strict; use FileHandle; use Sys::Hostname; ($main::progname = $0) =~ s/^.*\/([^\/]+)/$1/; $main::modvers{'thisprogram'} = "MARKER"; ($main::modvers{'thisprogram'} =~ /^M.*R$/) && ($main::modvers{'thisprogram'} = '$Id: ppp-on,v 1.16 1997/01/02 17:51:32 alexis Exp $') =~ s/^.*,v (\S+) .*$/$1/; $ENV{'LOCALPLDIR'} && ($main::localpl_dir = $ENV{'LOCALPLDIR'}); unshift(@INC,split(/:/, $main::localpl_dir)); # Functions used by this file require "msgs.pl"; ($main::modvers{'msgs.pl'} ne "1.12") && (!$ENV{'IGNORELOCALPLVERS'}) && &msgs::error("configuration error: wrong version of msgs.pl"); require "tfr.pl"; ($main::modvers{'tfr.pl'} ne "1.2") && (!$ENV{'IGNORELOCALPLVERS'}) && &msgs::error("configuration error: wrong version of tfr.pl"); # Lock file $main::lock_file = "/var/lock/ppp_on"; # Message level $msgs::verboselevel = 100; # Facility to which all messages are logged $msgs::facility = 'local0'; # Run in bg or fg? $main::background = 1; sub load_config { my($config_file, $level) = @_; my $fh; defined($config_file) || ($config_file = $main::master_config_file); defined($level) ? $level++ : ($level = 0); &msgs::debug(5, "load_config: config file is $config_file, level is $level"); ($fh = new FileHandle $config_file) || &msgs::error("can't open $config_file: $!"); while (<$fh>) { chop; if (/^\s*$/ || /^\s*#.*$/) { next; } elsif (/^newsrunning: (.+)$/) { $main::newsrunning_cmd = $1; } elsif (/^newsrun: (.+)$/) { $main::newsrun_cmd = $1; } elsif (/^sendmail: (.+)$/) { $main::sendmail_cmd = $1; } elsif (/^xmitnews: (.+)$/) { $main::xmitnews_cmd = $1; } elsif (/^slurp: (.+)$/) { $main::slurp_cmd = $1; } elsif (/^chat: (.+)$/) { $main::chat_cmd = $1; } elsif (/^nnmaster: (.+)$/) { $main::nnmaster_cmd = $1; } elsif (/^include: (.+)$/) { &msgs::debug(5, "load_config: about to include $_\n"); &load_config($1, $level); # &msgs::debug(5, "load_config: done including $_\n"); } elsif (/^pppd: (.+)$/) { $main::pppd_cmd = $1; } elsif (/^chatline: (.+)$/) { push @main::chat_lines, $1; } elsif (/^chatscript: (.+)$/) { open(CHAT_HANDLE, $1) || &msgs::error("can't open $1: $!"); while () { chop; if (/^\s*$/ || /^\s*#.*$/) { next; } else { push @main::chat_lines, $_; } } close CHAT_HANDLE; } elsif (/^password: (.+)$/) { $main::password = $1; } elsif (/^login: (.+)$/) { $main::login = $1; } elsif (/^telno: (.+)$/) { $main::telno = $1; } elsif (/^netmask: (.+)$/) { $main::netmask = $1; } elsif (/^up: (.+)$/) { $main::up_cmd = $1; if (!defined($main::announce_flg)) { $main::announce_flg = 1; } } elsif (/^down: (.+)$/) { $main::down_cmd = $1; if (!defined($main::announce_flg)) { $main::announce_flg = 1; } } elsif (/^port: (.+)$/) { if (!defined($main::port_file)) { $main::port_file = $1; } } elsif (/^speed: (.+)$/) { if (!defined($main::port_speed)) { $main::port_speed = $1; } } elsif (/^idle: (.+)$/) { if (!defined($main::max_idle_interval)) { $main::max_idle_interval = $1; } } elsif (/^getnews: (.+)$/) { if (!defined($main::getnews_flg)) { $main::getnews_flg = $1; } } elsif (/^quality: (.+)$/) { if (!defined($main::qualt_flg)) { $main::qualt_flg = $1; } } elsif (/^nntpserver: (.+)$/) { if (!defined($main::nntp_server)) { $main::nntp_server = $1; } } else { &msgs::error("invalid configuration file entry: $_"); } } $fh->close; $level && return; defined($main::newsrunning_cmd) || &msgs::error("newsrunning command not defined in any config file"); defined($main::newsrun_cmd) || &msgs::error("newsrun command not defined in any config file"); defined($main::sendmail_cmd) || &msgs::error("sendmail command not defined in any config file"); defined($main::chat_cmd) || &msgs::error("chat command not defined in any config file"); defined($main::xmitnews_cmd) || &msgs::error("xmitnews command not defined in any config file"); defined($main::slurp_cmd) || &msgs::error("slurp command not defined in any config file"); defined($main::nnmaster_cmd) || &msgs::error("nnmaster command not defined in any config file"); defined($main::pppd_cmd) || &msgs::error("pppd command not defined in any config file"); defined($main::port_file) || &msgs::error("port not defined in any config file"); defined($main::port_speed) || &msgs::error("speed not defined in any config file"); defined($main::max_idle_interval) || &msgs::error("idle not defined in any config file"); defined($main::getnews_flg) || &msgs::error("getnews not defined in any config file"); defined(@main::chat_lines) || &msgs::error("no chat lines defined in any config file"); defined($main::netmask) || &msgs::error("netmask not defined in any config file"); defined($main::nntp_server) || &msgs::error("nntpserver not defined in any config file"); defined($main::qualt_flg) || &msgs::error("quality not defined in any config file"); foreach (@main::chat_lines) { if (/%T/ && !defined($main::telno)) { &msgs::error("telno not defined in any config file but %T is used"); } elsif (/%L/ && !defined($main::login)) { &msgs::error("login not defined in any config file but %L is used"); } elsif (/%P/ && !defined($main::password)) { &msgs::error("password not defined in any config file but %P is used"); } elsif (/%I/ && !defined($main::max_idle_interval)) { &msgs::error("idle time not defined in any config file but %I is used"); } } &msgs::debug(5, "load_config: newsrunning command is $main::newsrunning_cmd"); &msgs::debug(5, "load_config: newsrun command is $main::newsrun_cmd"); &msgs::debug(5, "load_config: sendmail command is $main::sendmail_cmd"); &msgs::debug(5, "load_config: chat command is $main::chat_cmd"); &msgs::debug(5, "load_config: xmitnews command is $main::xmitnews_cmd"); &msgs::debug(5, "load_config: slurp command is $main::slurp_cmd"); &msgs::debug(5, "load_config: nnmaster command is $main::nnmaster_cmd"); &msgs::debug(5, "load_config: pppd command is $main::pppd_cmd"); &msgs::debug(5, "load_config: up command is $main::up_cmd"); &msgs::debug(5, "load_config: down command is $main::down_cmd"); &msgs::debug(5, "load_config: port is $main::port_file"); &msgs::debug(5, "load_config: speed is $main::port_speed"); &msgs::debug(5, "load_config: idle is $main::max_idle_interval"); &msgs::debug(5, "load_config: news flag is $main::getnews_flg"); # This lines contains all sorts of funny characters and it screws 'logger'! # &msgs::debug(5, "load_config: chat script is " . join("\n", @main::chat_lines)); &msgs::debug(5, "load_config: netmask is $main::netmask"); &msgs::debug(5, "load_config: nntp server is $main::nntp_server"); &msgs::debug(5, "load_config: min quality is $main::qualt_flg"); &msgs::debug(5, "load_config: password is $main::password"); &msgs::debug(5, "load_config: login is $main::login"); &msgs::debug(5, "load_config: telno is $main::telno"); &msgs::debug(5, "load_config: announce flag is $main::announce_flg"); } sub chgstate { my($newpid, $newstate) = @_; my($tmplock_file) = "$main::lock_file.$$"; my($oldpid, $oldstate, $holding_pid, $line, $forkreqpid); # Check if there is a fork request if ($main::progname eq "ppp-on") { &msgs::debug(10, "chgstate: checking for fork requests"); if (-f "/tmp/pleasefork") { &msgs::debug(10, "chgstate: found a fork request"); open(FORKREQ_HANDLE, "/tmp/pleasefork") || &msgs::error("can't open forkrequest file: $!"); chop($line = ); close FORKREQ_HANDLE; if ($forkreqpid = fork) { &msgs::debug(10, "chgstate: parent returning"); } elsif (defined $forkreqpid) { &msgs::debug(10, "chgstate: child continuing"); if ($line =~ /ip-up/) { &msgs::debug(10, "chgstate: child calling ip_up"); $0 = 'ip-up-f'; $main::progname = $0; &ip_up; } elsif ($line =~ /ip-down/) { &msgs::debug(10, "chgstate: child calling ip_down"); $0 = 'ip-down-f'; $main::progname = $0; &ip_down; } elsif ($line =~ /news-xfer/) { &msgs::debug(10, "chgstate: child calling news_xfer"); $0 = 'news-xfer-f'; $main::progname = $0; &news_xfer; } elsif ($line =~ /news-flush/) { &msgs::debug(10, "chgstate: child calling news_flush"); $0 = 'news-flush-f'; $main::progname = $0; &news_flush; } else { &msgs::error("being asked to fork $line"); } exit 0; } else { &msgs::error("fork failed: $!"); } unlink "/tmp/pleasefork"; } else { &msgs::debug(10, "chgstate: no fork requests"); } } # newpid > 0 means lock with newpid and newstate if ($newpid > 0) { open(TMPLOCK_HANDLE, ">$tmplock_file") || &msgs::error("can't open temporary lock: $!"); print TMPLOCK_HANDLE join(' ', $newpid, $newstate), "\n"; close TMPLOCK_HANDLE; if (link($tmplock_file, $main::lock_file)) { &msgs::debug(100, "chgstate: lock mode, locked"); unlink $tmplock_file; return(0); } open(LOCK_HANDLE, $main::lock_file) || &msgs::error("can't read lock file: $!"); ($holding_pid) = ( =~ /^([0-9]+) .*$/); close LOCK_HANDLE; if ($holding_pid && -d "/proc/$holding_pid") { &msgs::debug(100, "chgstate: lock mode, busy"); unlink $tmplock_file; return($holding_pid); } unlink $main::lock_file; if (link($tmplock_file, $main::lock_file)) { &msgs::debug(100, "chgstate: lock mode, locked after stale"); unlink $tmplock_file; return(0); } return(-1); } elsif (! -f $main::lock_file) { return(0, "NO-PROC"); } elsif ($newpid < 0) { &msgs::debug(100, "chgstate: mode: unlock mode"); unlink $main::lock_file; return(0); # no pid or 0 } elsif ($newstate ne "0") { open(LOCK_HANDLE, $main::lock_file) || &msgs::error("can't read lock file: $!"); chop($line = ); ($oldpid, $oldstate) = split(/ /, $line); close LOCK_HANDLE; open(LOCK_HANDLE, ">$main::lock_file") || &msgs::error("can't write lock file: $!"); print LOCK_HANDLE join(' ', $oldpid, $newstate), "\n"; close LOCK_HANDLE; &msgs::debug(100, "chgstate: write state mode: $oldstate to $newstate"); return(0); } else { &msgs::debug(100, "chgstate: mode: reading state ..."); open(LOCK_HANDLE, $main::lock_file) || &msgs::error("can't read lock file: $!"); chop($line = ); ($oldpid, $oldstate) = split(/ /, $line); close LOCK_HANDLE; if (-d "/proc/$oldpid") { &msgs::debug(100, "chgstate: mode: read state mode: $oldstate"); return($oldpid, $oldstate); } else { &msgs::debug(100, "chgstate: mode: read state mode: stale lock"); return(0, "NO-PROC"); } } } sub bg_pppd { my($pppd_cmd, $port_file, $port_speed, $chat_cmd, $netmask, $hostname, $ipparam, @chat_lines) = @_; my($pid, $cmd_str); $main::tmp_chat_script_file = "/tmp/$main::progname.$$.chat"; &msgs::debug(10, "bg_pppd: sof"); open(TMP_CHAT_HANDLE, ">$main::tmp_chat_script_file") || &msgs::error("can't open $main::tmp_chat_script_file: $!"); foreach (@chat_lines) { # &msgs::debug(10, "bg_pppd: current line is $_"); s/\%I/$main::max_idle_interval/g; s/\%P/$main::password/g; s/\%L/$main::login/g; s/\%T/$main::telno/g; print TMP_CHAT_HANDLE "$_\n"; } close TMP_CHAT_HANDLE; &msgs::debug(10, "bg_pppd: after rewriting"); $cmd_str = "$pppd_cmd $port_file $port_speed connect \"$chat_cmd -v -f $main::tmp_chat_script_file\" crtscts defaultroute lock netmask $netmask $hostname: asyncmap 0x00000000 mru 576 mtu 576 lcp-echo-interval 180 -detach ipparam $ipparam"; if ($pid = fork) { return($pid); } elsif (defined $pid) { &msgs::debug(8, "bg_pppd: about to exec: $cmd_str"); exec($cmd_str) || &msgs::error("exec failed: $!"); } else { &msgs::error("fork failed: $!"); } } sub sub1 { $SIG{'CHLD'} = 'sub1'; &msgs::debug(6, "sub1: caught SIGCHLD"); (-f $main::tmp_chat_script_file) && unlink $main::tmp_chat_script_file; wait; } sub sub4 { $SIG{'ALRM'} = 'sub4'; &msgs::debug(6, "sub4: caught SIGALRM"); } sub sub3 { $SIG{'USR1'} = 'sub3'; &msgs::debug(6, "sub3: caught SIGUSR1"); } sub sub2 { my($pid, $state); $SIG{'INT'} = 'IGNORE'; $SIG{'TERM'} = 'IGNORE'; &msgs::debug(6, "sub2: caught SIGINT or SIGTERM"); ($pid, $state) = &chgstate(0, 0); if (defined $main::pppd_pid && $main::pppd_pid > 0) { &chgstate(0, "PD-USERREQ"); kill 'INT', $main::pppd_pid; wait; } } sub announce { my($cmd) = @_; if (! -x $cmd) { &msgs::warning("missing announce command: $cmd"); } else { &msgs::debug(10, "announce: announcing with command $cmd"); system($cmd); &msgs::debug(10, "announce: announcing done"); } } sub xfercnt { my($xfercnt) = 0; open(PROC_HANDLE, "/proc/net/dev") || &msgs::error("can't open /proc/net/dev: $!"); while () { if (/^\s+ppp0:\s+(\d+)\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)\s+.*\n$/) { $xfercnt += $1 + $2; } } close PROC_HANDLE; # $xfercnt = int(rand(6) + 1); &msgs::debug(12, "xfercnt: total use $xfercnt"); return($xfercnt); } sub ppp_on { my($state, $idle_start_time, $last_use_count, $this_use_count); my($rc, $idle_check_interval, $pid, $hostname); $hostname = hostname; &msgs::debug(10, "hostname is $hostname"); &load_config(); if ($main::background) { # Check that the child background process will (probably) be able to # lock successfully in a moment. $msgs::msgs_mode = $msgs::MSGS_STD; ($pid, $state) = &chgstate(0, 0); if ($state ne "NO-PROC") { &msgs::error("process $rc has control!"); } $msgs::msgs_mode = $msgs::MSGS_SYS; fork && exit 0; } &msgs::info("version $main::modvers{'thisprogram'} started"); close STDIN; if (($rc = &chgstate($$, "C")) > 0) { &msgs::error("process $rc has control!"); } elsif ($rc < 0) { &msgs::error("no process has control but can't lock"); } # Very necessary line! # $SIG{'CHLD'} = 'IGNORE'; $SIG{'USR1'} = 'sub3'; $SIG{'ALRM'} = 'sub4'; $SIG{'INT'} = 'sub2'; $SIG{'TERM'} = 'sub2'; if ($main::getnews_flg) { &msgs::debug(8, "ppp_on: calling newsrunning"); system("su - news -c \"$main::newsrunning_cmd on\""); &msgs::debug(8, "ppp_on: newsrunning done"); &msgs::debug(8, "ppp_on: calling newsrun"); system("su - news -c $main::newsrun_cmd"); &msgs::debug(8, "ppp_on: newsrun done"); } else { &msgs::debug(10, "ppp_on: no news processing"); } $last_use_count = 0; $idle_start_time = time; # Check the idle status every quarter of the total idle timeout period $idle_check_interval = int($main::max_idle_interval / 4); &msgs::debug(10, "ppp_on: timeout is $main::max_idle_interval, check every $idle_check_interval"); $main::pppd_pid = &bg_pppd($main::pppd_cmd, $main::port_file, $main::port_speed, $main::chat_cmd, $main::netmask, $hostname, "$main::getnews_flg:$msgs::verboselevel:$main::announce_flg:$main::qualt_flg", @main::chat_lines); $SIG{'CHLD'} = 'sub1'; for (;;) { ($pid, $state) = &chgstate(0, 0); &msgs::debug(100, "ppp_on: state is $state"); if ($state eq "A" || $state eq "D") { last; } elsif ($state eq "C") { if (-d "/proc/$main::pppd_pid") { &msgs::debug(10, "ppp_on: pppd[$main::pppd_pid] is running"); } else { &msgs::info("restarting pppd"); $main::pppd_pid = &bg_pppd($main::pppd_cmd, $main::port_file, $main::port_speed, $main::chat_cmd, $main::netmask, $hostname, "$main::getnews_flg:$msgs::verboselevel:$main::announce_flg:$main::qualt_flg", @main::chat_lines); &msgs::debug(10, "ppp_on: pppd[$main::pppd_pid] started"); } } elsif ($state eq "S1") { if (-d "/proc/$main::pppd_pid") { &msgs::debug(10, "ppp_on: waiting for ip_up to give permission to kill pppd"); } else { &msgs::debug(10, "ppp_on: pppd did not get to run ip-up"); &chgstate(0, "A"); next; } } elsif ($state eq "UC") { ; } elsif ($state eq "OC") { if ($main::max_idle_interval != 0) { if ($last_use_count != ($this_use_count = &xfercnt("ppp0"))) { $idle_start_time = time; &msgs::debug(12, "ppp_on: interface in use"); $last_use_count = $this_use_count; } elsif (time - $idle_start_time > $main::max_idle_interval) { &msgs::info("idle timeout elapsed"); &chgstate(0, "PD-IDLE"); kill 15, $main::pppd_pid; } else { &msgs::debug(12, "ppp_on: idle time rising"); } alarm($idle_check_interval); } } elsif ($state eq "PA-WAS-UC" || $state eq "PD-USERREQ" || $state eq "PR-USERREQ" || $state eq "PD-IDLE" || $state eq "PD-BADQ") { kill 15, $main::pppd_pid; } else { &msgs::internal(1, $main::modvers{'thisprogram'}, "S $state"); } # This should not be necessary but perhaps it will help: $SIG{'CHLD'} = 'sub1'; &msgs::debug(8, "ppp_on: going to sleep"); sleep 3600; &msgs::debug(8, "ppp_on: woken up, going to top of loop"); } &chgstate(-1, 0); return(0); } sub ip_down { my($pid, $state); #&load_config(); ($pid, $state) = &chgstate(0, 0); &msgs::debug(100, "ip_down: state is $state"); if ($state eq "PD-IDLE") { &msgs::info("connection down"); &msgs::syslog("disconnected (idle timeout)"); $main::announce_flg && $main::down_cmd && &announce($main::down_cmd); &chgstate(0, "D"); } elsif ($state eq "PD-USERREQ") { &msgs::info("connection down"); &msgs::syslog("disconnected (by request)"); $main::announce_flg && $main::down_cmd && &announce($main::down_cmd); &chgstate(0, "D"); } elsif ($state eq "PR-USERREQ") { &msgs::info("connection down"); &msgs::syslog("disconnected (redialling by request)"); $main::announce_flg && $main::down_cmd && &announce($main::down_cmd); &chgstate(0, "C"); } elsif ($state eq "PA-WAS-UC") { &chgstate(0, "A"); } elsif ($state eq "PR-BADQ") { &chgstate(0, "C"); } elsif ($state eq "OC") { &msgs::info("remote end hung up"); &msgs::syslog("disconnected (remote hung up)"); $main::announce_flg && $main::down_cmd && &announce($main::down_cmd); &chgstate(0, "D"); } else { &msgs::internal(2, $main::modvers{'thisprogram'}, "S $state"); } &wake_ppp_on; return(0); } sub wake_ppp_on { my ($pid, $state); &msgs::debug(8, "wake_ppp_on: waking ppp_on"); # the chgstate call just gets the pid of the ppp_on process, the # state shouldn't get written ($pid, $state) = &chgstate(0, 0); kill 'USR1', $pid; } sub ppp_off { my($pid, $state); &msgs::debug(10, "ppp_off: start"); ($pid, $state) = &chgstate(0, 0); &msgs::debug(100, "ppp_off: state is $state"); if ($state eq "OC") { &chgstate(0, "PD-USERREQ"); } elsif ($state eq "C") { &chgstate(0, "S1"); } elsif ($state eq "UC") { &chgstate(0, "PA-WAS-UC"); } elsif ($state eq "S1" || $state eq "PD-USERREQ" || $state eq "PA-WAS-UC") { &msgs::error("an abandon request is pending"); } elsif ($state eq "NO-PROC") { &msgs::error("no process running!"); } else { &msgs::internal(3, $main::modvers{'thisprogram'}, "S $state"); } &wake_ppp_on; return(0); } sub ppp_info { my($state, $pid); ($pid, $state) = &chgstate(0, 0); if ($state eq "NO-PROC") { print "ppp-on not running\n"; return(0); } print "process number is $pid\n"; if ($state eq "C") { print "Connecting\n"; } elsif ($state eq "UC") { print "Connecting, quality tests pending\n"; } elsif ($state eq "PR-BADQ") { print "Connecting, quality reconnection request pending\n"; } elsif ($state eq "OC") { print "Connected\n"; } elsif ($state eq "PD-USERREQ") { print "Connected, user disconnection request pending\n"; } elsif ($state eq "PR-USERREQ") { print "Connected, user reconnection request pending\n"; } elsif ($state eq "PD-IDLE") { print "Connected, idle timeout disconnection request pending\n"; } elsif ($state eq "D") { print "Disconnected\n"; } elsif ($state eq "S1") { print "Abandonning connection attempt\n"; } elsif ($state eq "PA-WAS-UC") { print "Abandonning connection attempt\n"; } elsif ($state eq "A") { print "Abandonned\n"; } else { &msgs::internal(4, $main::modvers{'thisprogram'}, "S $state"); } } sub ppp_redial { my($pid, $state); ($pid, $state) = &chgstate(0, 0); &msgs::debug(100, "ppp_redial: state is $state"); if ($state eq "OC") { &chgstate(0, "PR-USERREQ"); &wake_ppp_on; } elsif ($state eq "NO-PROC") { &msgs::error("no process running!"); } else { &msgs::internal(5, $main::modvers{'thisprogram'}, "S $state"); } return(0); } sub getlinequality { &msgs::debug(10, "getlinequality: checking line"); sleep(10); return(100); } sub news_xfer { my($backoff, $gotnews, $state, $linequality, $pid, $starttime); ($pid, $state) = &chgstate(0, 0); if ($state ne "OC") { &msgs::error("not connected"); } #&load_config(); &news_xfer_real(); } sub news_xfer_real { my($backoff, $gotnews, $state, $linequality, $pid, $starttime); &msgs::debug(8, "news_xfer_real: calling newsrunning"); system("su - news -c \"$main::newsrunning_cmd off\""); &msgs::debug(8, "news_xfer_real: newsrunning done"); &msgs::debug(8, "news_xfer_real: calling xmitnews"); system("su - news -c \"$main::xmitnews_cmd -d -h $main::nntp_server -f /var/spool/news/out.going/$main::nntp_server/togo\""); &msgs::debug(8, "news_xfer_real: xmitnews done"); # fix kacky file &msgs::debug(10, "news_xfer_real: fixing kacky file"); truncate("/usr/local/lib/nntp/slurp.news.demon.co.uk", 14); &msgs::debug(10, "news_xfer_real: kacky file fixed"); &msgs::debug(10, "news_xfer_real: backoff give up period is $main::getnews_flg"); for ($starttime=time,$backoff=1,$gotnews=0; !$gotnews && time<($starttime+$main::getnews_flg); $backoff *= 2) { &msgs::debug(8, "news_xfer_real: retrieving new news articles: $backoff"); if (system("su - news -c \"$main::slurp_cmd -d $main::nntp_server\"") / 256 == 0) { &msgs::debug(8, "news_xfer_real: new news articles retrieved"); $gotnews = 1; } else { &msgs::info("news retrieval failed, retrying in $backoff seconds"); sleep $backoff; } } if ($gotnews) { &msgs::debug(8, "news_xfer_real: calling newsrunning"); system("su - news -c \"$main::newsrunning_cmd on\""); &msgs::debug(8, "news_xfer_real: newsrunning done"); &msgs::debug(8, "news_xfer_real: calling newsrun"); system("su - news -c $main::newsrun_cmd"); &msgs::debug(8, "news_xfer_real: newsrun done"); &msgs::debug(8, "news_xfer_real: calling nnmaster"); system("su - news -c $main::nnmaster_cmd"); &msgs::debug(8, "news_xfer_real: nnmaster done"); } else { &msgs::debug(10, "news_xfer_real: transfer failed or pppd orphaned me"); } } sub ip_up { my($backoff, $gotnews, $state, $linequality, $pid, $starttime); #&load_config(); ($pid, $state) = &chgstate(0, 0); &msgs::debug(100, "ip_up: state: $state, news: $main::getnews_flg"); if ($state eq "S1") { &chgstate(0, "PA-WAS-UC"); &wake_ppp_on; return(0); } elsif ($state eq "C") { ; } else { &msgs::internal(6, $main::modvers{'thisprogram'}, "S $state"); } &chgstate(0, "UC"); &wake_ppp_on; &msgs::debug(10, "ip_up: now unofficially connected"); &msgs::info("unoffically connected"); if ($main::qualt_flg) { &msgs::debug(10, "ip_up: quality check"); &msgs::info("checking line quality"); $linequality = &getlinequality; ($pid, $state) = &chgstate(0, 0); if ($state eq "PA-WAS-UC") { &msgs::debug(10, "ip_up: spotted that we have been asked to abandon"); return(0); } elsif ($state eq "UC") { if ($linequality < $main::qualt_flg) { &msgs::info("bad quality connection, redial requested"); &chgstate(0, "PR-BADQ"); &wake_ppp_on; return(0); } } else { &msgs::internal(7, $main::modvers{'thisprogram'}, "S $state"); } } else { &msgs::debug(10, "ip_up: acceptable quality is $main::qualt_flg, therefore no check"); } &chgstate(0, "OC"); $main::announce_flg && $main::up_cmd && &announce($main::up_cmd); &msgs::debug(10, "ip_up: done announcing"); &msgs::syslog("connected"); &msgs::debug(10, "ip_up: done syslogging"); &wake_ppp_on; &msgs::debug(10, "ip_up: woken ppp_on"); &msgs::info("officially connected, post connection processing follows"); &msgs::debug(8, "ip_up: running sendmail"); system("$main::sendmail_cmd -q &"); &msgs::debug(8, "ip_up: sendmail in background"); if (defined($main::getnews_flg) && $main::getnews_flg) { &news_xfer_real(); } else { &msgs::debug(10, "ip_up: no news processing"); } &msgs::info("post-connection processing complete"); return(0); } sub news_flush { #&load_config(); &msgs::info("newsrunning on ..."); system("su - news -c \"$main::newsrunning_cmd on\""); &msgs::info("newsrun ..."); system("su - news -c $main::newsrun_cmd"); &msgs::info("nnmaster ..."); system("su - news -c $main::nnmaster_cmd"); &msgs::info("done"); return(0); } sub usage_ppp_on { print STDERR "Usage: $main::progname [ -v | -d ] [ -fg | -bg ] [ -p ] [ -b ] [ -s ] [ -ni | -i ] [ -na | -a ] [ -nq | -q ] [ -nn | -n ]\n"; print STDERR " $main::progname -V\n"; exit 1; } sub usage_ip_up_down { print STDERR "Usage: $main::progname [ ]\n"; exit 1; } sub usage_no_args { print STDERR "Usage: $main::progname\n"; exit 1; } sub show_version { print "$main::progname version ", $main::modvers{'thisprogram'}, "\n"; exit 0; } sub forkreq { my($prog) = @_; &msgs::debug(10, "forkreq: called with parameter $prog"); open(FORKREQ_HANDLE, ">/tmp/pleasefork") || &msgs::error("can't open /tmp/pleasefork: $!"); print FORKREQ_HANDLE "$prog\n"; close FORKREQ_HANDLE; &msgs::debug(10, "forkreq: request submitted, now waking ppp_on"); &wake_ppp_on; &msgs::debug(10, "forkreq: woken ppp_on, all done"); return 0; } sub main { my(@ARGV) = @_; my($rc) = 0; $0 = $main::progname . ' '. join(' ', @ARGV); $msgs::msgs_mode = $msgs::MSGS_SYS; &msgs::debug(10, "main: top, progname is $main::progname"); if ($main::progname ne "ppp-on" && $main::progname ne "ppp-off" && $main::progname ne "ip-up" && $main::progname ne "ip-down" && $main::progname ne "ppp-redial" && $main::progname eq "news-flush" && $main::progname ne "ppp-info" && $main::progname eq "news-xfer") { &msgs::error("program incorrectly named"); } # if ($main::progname eq "ip-up" || $main::progname eq "ip-down") { # $msgs::msgs_mode = $msgs::MSGS_SYS; # } ($> != 0) && &msgs::warning("you are not root!"); # Process the options or split the ipparam parameter - depending on the # name of this program if ($main::progname eq "ip-up" || $main::progname eq "ip-down") { # &msgs::debug(100, "6th cmd line arg is $ARGV[5]"); # if (defined $ARGV[5] && $ARGV[5] && !defined $ARGV[6]) { # ($main::getnews_flg, $msgs::verboselevel, $main::announce_flg, $main::qualt_flg) = split(/:/, $ARGV[5]); # &msgs::debug(10, "getnews: $main::getnews_flg, msgs::verboselevel: $msgs::verboselevel, wall: $main::announce_flg, qualt: $main::qualt_flg"); # } else { # &usage_ip_up_down; # } ; } elsif ($main::progname eq "ppp-on" || $main::progname eq "news-xfer") { while (defined($ARGV[0]) && $ARGV[0] =~ /^-./) { $_ = shift @ARGV; # -V is print the version number if (/^-V$/) { &show_version; # -d is turn on debug at the specified level } elsif (/^-d(.*)/) { $msgs::verboselevel = ($1 ? $1 : shift @ARGV); # -v is be verbose } elsif (/^-v$/) { $msgs::verboselevel = 3; # -fg is run in foreground (useful for shells) } elsif (/^-fg$/) { $main::background = 0; # -bg is run in background } elsif (/^-bg$/) { $main::background = 1; # -p is set port } elsif (/^-p(.*)/) { $main::port_file = ($1 ? $1 : shift @ARGV); # -b is set port speed } elsif (/^-b(.*)/) { $main::port_speed = ($1 ? $1 : shift @ARGV); # -s is for an alternative NNTP server } elsif (/^-s(.*)/) { $main::nntp_server = ($1 ? $1 : shift @ARGV); # -i is set idle timeout in seconds } elsif (/^-i(.*)/) { $main::max_idle_interval = ($1 ? $1 : shift @ARGV); # -ni is set idle timeout in seconds } elsif (/^-ni$/) { $main::max_idle_interval = 0; # -a is announce } elsif (/^-a$/) { $main::announce_flg = 1; # -na is don't announce } elsif (/^-na$/) { $main::announce_flg = 0; # -q is check quality } elsif (/^-q(.*)$/) { $main::qualt_flg = ($1 ? $1 : shift @ARGV); # -nq is don't check quality } elsif (/^-nq$/) { $main::qualt_flg = 0; # -nn is don't get news } elsif (/^-nn$/) { $main::getnews_flg = 0; # Check this last! It interferes with previous options! # -n is get news } elsif (/^-n(.*)$/) { $main::getnews_flg = ($1 ? $1 : shift @ARGV); # otherwise the user has typed something daft } else { &usage_ppp_on; } } defined($ARGV[0]) && &usage_ppp_on; } elsif ($main::progname eq "ppp-down" || $main::progname eq "ppp-redial" || $main::progname eq "ppp-info" || $main::progname eq "news-flush" || $main::progname eq "ppp-off") { defined($ARGV[0]) && &usage_no_args; } # if ($main::progname eq "ppp-on") { # $msgs::msgs_mode = $msgs::MSGS_SYS; # } # tmp file registration services #$SIG{'INT'} = 'sighandler'; #$SIG{'TERM'} = 'sighandler'; if ($main::progname eq "ppp-on") { return(&ppp_on); } elsif ($main::progname eq "ppp-off") { return(&ppp_off); } elsif ($main::progname eq "ip-up") { system("echo $0: calling forkreq now >> /tmp/progname"); return(&forkreq($main::progname)); } elsif ($main::progname eq "ip-down") { return(&forkreq($main::progname)); } elsif($main::progname eq "ppp-redial") { return(&ppp_redial); } elsif($main::progname eq "news-flush") { return(&forkreq($main::progname)); } elsif($main::progname eq "news-xfer") { return(&forkreq($main::progname)); } elsif($main::progname eq "ppp-info") { return(&ppp_info); } } umask 077; exit(&main(@ARGV));