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: