[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

new handling of /etc/ppp/ip-{up,down}.d



I have been working on improving the handling of the above directories.  I
believe I have finally got everything working.

All files in ip-{up,down}.d are relative symlinks into /etc/ppp/scripts.d.
The symlinks are updated with ppp-update.d.
ip-up and ip-down source ppp-functions, which does most of the processing.
rc is called by ppp-functions.

chime was installed like this: ppp-update.d chime start 0 up down
exim was installed like this: ppp-update.d chime start 0 up
fetchmail was installed like this: ppp-update.d chime defaults

Each package provides a file that goes into /etc/ppp/scripts.d.  Included in
the script are two functions, ${package}_up, and ${package}_down.  They are
called when the link goes up, or down, respectively.  One option is passed to
each function, start or stop, depending on the name of the link(S* or K*).

The way it is setup, you could have some daemon(program) running when offline.
Upon connection, this program could be stopped with a K* script in ip-up.d,
and restarted with a S* script in ip-down.d.  This, however, is a little
unusual.  Or, as which chime, a program could be started on going up and on
going down.

Also included with ppp-functions are two functions that can start/stop a
program on a tty.  I use this for running tcpdump on tty11, pppstats on tty10,
and mirror on tty9.  Each function will only let the program be started once.

I hope I have explained everything here well enough.  I use this setup here,
YMMV.  It would be nice if pppd could be enhanced, so that there could be a
pre-ip-up.d, and a pre-ip-down.d.

Adam
#!/bin/sh
. /etc/ppp/ppp-functions

CMD=exim

function exim_up(){
	/usr/sbin/exim -qf
}

function exim_down(){
        echo >/dev/null
}

scripts_hook $*
#!/bin/sh
. /etc/ppp/ppp-functions
CMD=fetchmail

function fetchmail_up(){
	fetchmail -d 300 --invisible
}

function fetchmail_down(){
	fetchmail -q
}

scripts_hook $*
#!/bin/sh
#
# Play a chime
#
# Adam Heath <adam.heath@usa.net>
. /etc/ppp/ppp-functions

CMD=chime
wav_up=/dos/c/windows/media/chimes.wav
wav_down=/dos/c/windows/media/chord.wav

function chime_up(){
	bplay $wav_up
}
function chime_down(){
	bplay $wav_down
}

scripts_hook $*
#! /bin/bash
#
# rc		This file is responsible for starting/stopping
#		services when the runlevel changes.
#
#		Optimization feature:
#		A startup script is _not_ run when the service was
#		running in the previous runlevel and it wasn't stopped
#		in the runlevel transition (most Debian services don't
#		have K?? links in rc{1,2,3,4,5} )
#
# Author:	Miquel van Smoorenburg <miquels@cistron.nl>
#		Bruce Perens <Bruce@Pixar.com>
#
# Version:	@(#)rc  2.73  26-Nov-1997  miquels@cistron.nl
#

# Un-comment the following for debugging.
# debug=echo

#
# Start script or program.
#
startup() {
  case "$1" in
	*.sh)
		$debug sh "$@"
		;;
	*)
		$debug "$@"
		;;
  esac
}

  # Ignore CTRL-C only in this shell, so we can interrupt subprocesses.
  trap ":" INT QUIT TSTP

  # Set onlcr to avoid staircase effect.
  stty onlcr 0>&1

  [ "$1" = "up" ] && runlevel=$1 && previous=down
  [ "$1" = "down" ] && runlevel=$1 && previous=up
  [ ! "$runlevel" ] && exit

  # Is there an rc directory for this new runlevel?
  if [ -d /etc/ppp/ip-$runlevel.d ]
  then
	# First, run the KILL scripts.
	if [ $previous != N ]
	then
		for i in /etc/ppp/ip-$runlevel.d/K[0-9][0-9]*
		do
			# Check if the script is there.
			[ ! -f $i ] && continue

			# Stop the service.
			startup $i $runlevel stop
		done
	fi
	# Now run the START scripts for this runlevel.
	for i in /etc/ppp/ip-$runlevel.d/S*
	do
		[ ! -f $i ] && continue

		if [ $previous != N ]
		then
			#
			# Find start script in previous runlevel and
			# stop script in this runlevel.
			#
			suffix=${i#/etc/ppp/ip-$runlevel.d/S[0-9][0-9]}
			stop=/etc/ppp/ip-$runlevel.d/K[0-9][0-9]$suffix
			previous_start=/etc/ppp/ip-$previous.d/S[0-9][0-9]$suffix
			#
			# If there is a start script in the previous level
			# and _no_ stop script in this level, we don't
			# have to re-start the service.
			#
#			[ -f $previous_start ] && [ ! -f $stop ] && continue
		fi
		startup $i $runlevel start
	done
  fi
# eof /etc/init.d/rc
#! /usr/bin/perl
#
# update-rc.d	Update the links in /etc/rc[0-9S].d/
#
# Version:	@(#)update-rc.d.pl  2.02  05-Mar-1998  miquels@cistron.nl
#

$initd = "/etc/ppp/scripts.d";
$etcd  = "/etc/ppp/ip-";
$notreally = 0;

# Print usage message and die.

sub usage {
	print STDERR "update-rc.d: error: @_\n" if ($#_ >= 0);
	print STDERR <<EOF;
usage: ppp-update.d [-n] [-f] <basename> remove
       ppp-update.d [-n] [-f] <basename> defaults [NN | sNN kNN]
       ppp-update.d [-n] [-f] <basename> start|stop NN runlvl runlvl .  ...
		-n: not really
		-f: force
EOF
	exit (1);
}

# Check out options.

while($#ARGV >= 0 && ($_ = $ARGV[0]) =~ /^-/) {
	shift @ARGV;
	if (/^-n$/) { $notreally++; next }
	if (/^-f$/) { $force++; next }
	if (/^-h|--help$/) { &usage; }
	&usage("unknown option");
}

# Action.

&usage() if ($#ARGV < 1);
$bn = shift @ARGV;
if ($ARGV[0] ne 'remove') {
    if (! -f "$initd/$bn") {
	print STDERR "ppp-update.d: $initd/$bn: file does not exist\n";
	exit (1);
    }
} elsif (-f "$initd/$bn") {
    if (!$force) {
	printf STDERR "ppp-update.d: $initd/$bn exists during rc.d purge (use -f to force)\n";
	exit (1);
    } else {
	printf STDERR "ppp-update.d: $initd/$bn exists during rc.d purge (continuing)\n";
    }
}

$_ = $ARGV[0];
if    (/^remove$/)     { &checklinks ("remove"); }
elsif (/^defaults$/)   { &defaults; &makelinks }
elsif (/^start|stop$/) { &startstop; &makelinks; }
else                   { &usage; }

exit (0);

# Check if there are links in /etc/ppp/ip-[up,down].d/ 
# Remove if the first argument is "remove" and the links 
# point to $bn.

sub is_link () {
    my ($op, $fn, $bn) = @_;
    if (! -l $fn) {
	print STDERR "ppp-update.d: warning: $fn is not a symbolic link\n";
	return 0;
    } else {
	$linkdst = readlink ($fn);
	if (! defined $linkdst) {
	    die ("ppp-update.d: error reading symbolic link: $!\n");
	}
	if (($linkdst ne "../scripts.d/$bn") && ($linkdst ne "../scripts.d/$bn")) {
	    print STDERR "ppp-update.d: warning: $fn is not a link to ../scripts.d/$bn\n";
	    return 0;
	}
    }
    return 1;
}

sub checklinks {
    my ($i, $found, $fn, $islnk);

    print " Removing any system startup links for $initd/$bn ...\n"
	if ($_[0] eq 'remove');

    $found = 0;

    foreach $i (up, down) {
	unless (chdir ("$etcd$i.d")) {
	    next if ($i =~ m/^[789S]$/);
	    die("ppp-update.d: chdir $etcd$i.d: $!\n");
	}
	opendir(DIR, ".");
	foreach $_ (readdir(DIR)) {
	    next unless (/^[S|K][0-9]*$bn$/);
	    $fn = "$etcd$i.d/$_";
	    $found = 1;
	    $islnk = &is_link ($_[0], $fn, $bn);
	    next if ($_[0] ne 'remove');
	    if (! $islnk) {
		print "   $fn is not a link to ../scripts.d/$bn; not removing\n"; 
		next;
	    }
	    print "   $etcd$i.d/$_\n";
	    next if ($notreally);
	    unlink ("$etcd$i.d/$_") ||
		die("ppp-update.d: unlink: $!\n");
	}
	closedir(DIR);
    }
    $found;
}

# Process the arguments after the "defaults" keyword.

sub defaults {
    my ($start, $stop) = (20, 20);

    &usage ("defaults takes only one or two codenumbers") if ($#ARGV > 2);
    $start = $stop = $ARGV[1] if ($#ARGV >= 1);
    $stop  =         $ARGV[2] if ($#ARGV >= 2);
    &usage ("codenumber must be a number")
	if ($start !~ /^[0-9]+$/ || $stop  !~ /^[0-9]+$/);

    $start = sprintf("%02d", $start);
    $stop  = sprintf("%02d", $stop);

    $startlinks[0] = "S$start";
    $stoplinks[1] = "K$stop";
    $l[0] = "up";
    $l[1] = "down";
    1;
}

# Process the arguments after the start or stop keyword.

sub startstop {

    my($letter, $NN, $level);

    while ($#ARGV >= 0) {
	if    ($ARGV[0] eq 'start') { $letter = 'S'; }
	elsif ($ARGV[0] eq 'stop')  { $letter = 'K' }
	else {
	    &usage("expected start|stop");
	}

	if ($ARGV[1] !~ /^[0-9]+$/) {
	    &usage("expected NN after $ARGV[0]");
	}
	$NN = sprintf("%02d", $ARGV[1]);

	shift @ARGV; shift @ARGV;
	$level = shift @ARGV;
	print STDERR "ppp-update.d: level=$level\n";
	my ($lvl);
	$lvl = 0;
	do {
	print STDERR "ppp-update.d: {etcd}{level}.d=$etcd$level.d \n";
	    if (! -d "$etcd$level.d") {
		print STDERR
		    "ppp-update.d: $etcd$level.d: no such directory\n";
		exit(1);
	    }
	    $level = 99 if ($level eq 'S');
	    $startlinks[$lvl] = "$letter$NN" if ($letter eq 'S');
	    $stoplinks[$lvl]  = "$letter$NN" if ($letter eq 'K');
	    $l[$lvl] = $level;
	print STDERR "ppp-update.d: {etcd}{level}.d=$etcd$level.d $lvl $l[$lvl] \n";
	    $lvl = $lvl + 1;
	} while (($level = shift @ARGV) ne '.');
	&usage("action with list of runlevels not terminated by \`.'")
	    if ($level ne '.');
    }
    1;
}

# Create the links.

sub makelinks {
    my($t, $i);
    my @links;

    if (&checklinks) {
	print " System startup links for $initd/$bn already exist.\n";
	exit (0);
    }
    print " Adding system startup for $initd/$bn ...\n";

    # nice unreadable perl mess :)

    for($t = 0; $t < 2; $t++) {
	@links = $t ? @startlinks : @stoplinks;
	for($i = 0; $i <= $#links; $i++) {
	    $lvl = $l[$i];
	    $lvl = 'S' if ($i == 99);
	    next if ($links[$i] eq '');
	    print " $t  $etcd$lvl.d/$links[$i]$bn -> ../scripts.d/$bn\n";
	    next if ($notreally);
	    symlink("../scripts.d/$bn", "$etcd$lvl.d/$links[$i]$bn")
		|| die("ppp-update.d: symlink: $!\n");
	}
    }

    1;
}
#!/bin/sh

function start_it(){
	local prog=$1 tty=$2;shift;shift
	file=$runpath/pid-$prog
	if [ ! -e $file ]; then
		$prog $*>/dev/$tty &
		echo $!>$file
		logger -t $id START $prog\[$!\] $tty \"$*\";
	else
		logger -t $id START $prog is already running.;
	fi
}

function stop_it(){
	local prog=$1 tty=$2;shift;shift
	file=$runpath/pid-$prog
	if [ -e $file ]; then
		logger -t $id STOP $prog\[`cat $file`\]
		kill -KILL `cat $file`
		rm $file;
	else
		logger -t $id STOP $prog isn\'t running.;
	fi
}

function scripts_default() {
	echo "$0 scripts_default($*)"
	[ ! "$CMD" -a ! "$TTY" -a ! "$OPT" ] && return
	case $1 in
		up|down)
			[ "$2" = "start" -o "$2" = "stop" ] && eval ${2}_it $CMD $TTY $OPT
			;;
		*)
			echo "Unknown."
			;;
	esac
}
function scripts_hook() {
	echo "$0 scripts_hook($*)"
	[ ! "$CMD" ] && return
	case $1 in
		up|down)
			[ "$2" = "start" -o "$2" = "stop" ] && eval ${CMD}_${1} ${2}
			;;
		*)
			echo "Unknown."
			;;
	esac
}

script="`/usr/bin/basename $0`"
runpath=/var/run
id="${script}[$$]"

if [ "$script" = "ip-up" ];then
	cmd=start_it
else
	if [ "$script" = "ip-down" ];then
		cmd=stop_it
	else
		cmd=
	fi
fi
if [ $cmd ];then
	logger -t $id $1 $2 $3 $4 $5
	PPP_IFACE="$1" PPP_TTY="$2" PPP_SPEED="$3" PPP_LOCAL="$4" PPP_REMOTE="$5"
	PPP_TTYNAME=`/usr/bin/basename "$2"`

	$cmd tcpdump tty11 -i $1
	$cmd pppstats tty10 -r -v -w 1 $1
	#$cmd mirror tty9 -d -d -d -F -pDebian -pDebian-non-US /etc/mirror/packages/ftp.debian.org

	logger -t $id run-parts /etc/ppp/$script.d

	export script id runpath
	export PPP_IFACE PPP_TTY PPP_SPEED PPP_LOCAL PPP_REMOTE PPP_TTYNAME
	export start_it stop_it cmd

	/etc/ppp/rc ${script:3}
fi
#!/bin/sh
#
# $Id: ip-down,v 1.1 1996/01/31 21:25:59 alvar Exp $
#
# This script is run by the pppd _after_ the link is brought down.
# It should be used to delete routes, unset IP addresses etc.
#
# This script is called with the following arguments:
#    Arg  Name               Example
#    $1   Interface name     ppp0
#    $2   The tty            ttyS1
#    $3   The link speed     38400
#    $4   Local IP number    12.34.56.78
#    $5   Peer  IP number    12.34.56.99

#
# The  environment is cleared before executing this script
# so the path must be reset
#
PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
export PATH

. /etc/ppp/ppp-functions


# last line
#!/bin/sh
#
# $Id: ip-up,v 1.1 1996/01/31 21:25:59 alvar Exp $
#
# This script is run by the pppd after the link is established.
# It should be used to add routes, set IP address, run the mailq 
# etc.
#
# This script is called with the following arguments:
#    Arg  Name               Example
#    $1   Interface name     ppp0
#    $2   The tty            ttyS1
#    $3   The link speed     38400
#    $4   Local IP number    12.34.56.78
#    $5   Peer  IP number    12.34.56.99

#
# The  environment is cleared before executing this script
# so the path must be reset
#
export PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin

. /etc/ppp/ppp-functions

for file in /var/run/request-route*;
do
	logger -t $id $file
	kill `cat $file`;
done

# last line

# last line

Reply to: