#!/bin/bash # SpeedTouch user-mode driver hotplug script, version 8 # # This script is called by /etc/hotplug/usb.agent when the SpeedTouch modem is # (re)connected to the computer. It should be put in /etc/hotplug/usb, along # with the speedtouch.usermap file. # # This script has been developed and tested on Slackware, but should work on # other distributions as well. Please contact me if this is not the case: tell # me what is different on your distribution, so that I can correct the script # and make it more generic. # # This script is (c) 2003, Adrien Beau. This version is being released to the # general public under the GNU General Public License (GPL), version 2. You can # read it at http://www.gnu.org/licenses/gpl.txt. # # This script, and the speedtouch.usermap file, can be downloaded from # http://adrien.beau.free.fr/slackware/hotplug/ # # AB Adrien Beau, <adrien.beau@free.fr> # # 2003-04-29 AB Minimalistic version. DSL starts on computer startup, this # will do for now. Reconnections do not work, so this will # have to be vastly improved, as soon as possible. # 2003-05-08 AB Rough version. A remover is created when then modem is # connected, so reconnections work fine, now. # 2003-06-10 AB The new version of hotplug breaks this script. Added # debugging messages. Something is wrong with coldplugging. # Whatever I try, two connections happen upon startup, two # instances of this script are run in parallel, which wreaks # havoc. # 2003-06-11 AB Major cleanup. Added lockfile mechanism. Hotplug and # coldplug work fine. # 2003-06-12 AB Minor cleanup. Be smarter about killing pppd, so that other # connections (e.g. plain old modems) stay up when we # reconnect. # 2003-06-13 AB The script takes a lot of time to run, so booting takes a # lot of time. The last part of this script is now being run # in the background, as a separate substarter. Argh! It still # takes some time. What is the USB driver waiting for? Why is # it only waiting upon bootup? # 2003-06-22 AB The new version of Linux breaks this script. It runs it # three times in a row, which strangely makes expr return the # wrong exit status. Wrote the offending line another way, # which works. Since the remover is also run three times in a # row, added the lockfile mechanism to the remover. Argh! This # is a tricky timing issue, so even the rewritten line # sometimes breaks. Plus, sometimes all the tests for the # existence of the lockfile are done at the same time, so all # three instances create the lockfile anyway. # 2003-06-27 AB That should do it: added the pid to the lockfile, so that an # instance knows if another instance overwrote the lockfile. # Create the lockfile as early as possible after the test for # the existence of the lockfile. Mmm, everything seems ok now, # except for the bootup delay. Argh! The remover is erased # upon bootup, yet another problem to solve (this has the same # cause as the bootup delay). # 2003-07-06 AB Initial release to the general public. No other change, so # this is still version 8. ### This script has six settings that you might want to alter. ### # Don't read first, don't pollute the logs ("-s" means "skip"). # Use the second line for the few SpeedTouch modems that don't work with "-s". READ_FIRST="-s" #READ_FIRST="" # Location of the logfile. Use /dev/null if the logfile bothers you. #LOGFILE="/dev/null" LOGFILE="/var/log/speedtouch" # Under which hierarchy modem_run and the firmware file are located. PREFIX="/usr/local" #PREFIX="/usr" # If a lockfile is older than 60 seconds, ignore it. # Note that modem_run can take up to 30 seconds to run. Really. MAX_LOCK_AGE=60 # Name of the file in /etc/ppp/peers that contains the pppd settings for this # DSL connection. The default is /etc/ppp/peers/adsl. PEER="adsl" LOCKFILE="/var/lock/speedtouch" ### You should not need to edit anything below this line. ### function get_relevant_pppd_pids() { ps -eo pid,command | while read pid command; do if [ "$command" == "pppd call $PEER" ]; then echo -n "$pid " fi done } function log() { echo "`date '+%F %T'` starter-$$: $1" >> $LOGFILE } function create_lockfile() { log "Creating lockfile" echo "$currenttime $$" > $LOCKFILE } function read_lockfile() { unset timestamp pid read timestamp pid < $LOCKFILE # clean junk, be secure timestamp=`expr "$timestamp" : "\([0-9]*\)"` pid=`expr "$pid" : "\([0-9]*\)"` } currenttime=`date '+%s'` SUBSTARTER="/tmp/`basename $0`.$currenttime-$$.sh" # Acquire the lock. If the lock is old, go ahead anyway. Else, abort. # Note that several instances of this script will be run in parallel, # so some precautions have to be taken for this locking mechanism to # merely work. log "Trying to acquire the lock" if [ ! -e $LOCKFILE ]; then create_lockfile else if [ -f $LOCKFILE -a -r $LOCKFILE ]; then read_lockfile if [ "$timestamp" ]; then # First line fails, second line doesn't (most of the time). # Understand why, then please tell me why. # if expr $currenttime '-' $timestamp '<' $MAX_LOCK_AGE; then if [ `expr $currenttime '-' $timestamp` -lt $MAX_LOCK_AGE ]; then log "Found a recent lock, exiting" exit 0 else log "Found a stale lock" fi else log "Corrupted lockfile" fi else log "Weird lockfile" fi log "Removing lockfile" rm -f $LOCKFILE if [ $? -gt 0 ]; then log "Cannot remove lockfile, exiting" exit 1 fi create_lockfile fi sleep 2 log "Checking lockfile" read_lockfile if [ ! "$pid" ]; then log "Inexistant or corrupted lockfile, exiting" exit 1 fi if [ "$pid" -ne $$ ]; then log "Process $pid overwrote lockfile, exiting" exit 1 fi # Create /var/run/usb if it doesn't exist. if [ ! -d /var/run/usb ]; then log "Creating /var/run/usb" mkdir -p /var/run/usb chmod 0755 /var/run/usb fi # Write the remover. Make it executable. log "Writing remover" cat << EOF > $REMOVER #!/bin/bash # SpeedTouch user-mode-driver remover # Generated by /etc/hotplug/usb/speedtouch function get_relevant_pppd_pids() { ps -eo pid,command | while read pid command; do if [ "\$command" == "pppd call $PEER" ]; then echo -n "\$pid " fi done } function log() { echo "\`date '+%F %T'\` remover-$$-\$\$: \$1" >> $LOGFILE } function create_lockfile() { log "Creating lockfile" echo "\$currenttime \$\$" > $LOCKFILE } function read_lockfile() { unset timestamp pid read timestamp pid < $LOCKFILE # clean junk, be secure timestamp=\`expr "\$timestamp" : "\\([0-9]*\\)"\` pid=\`expr "\$pid" : "\\([0-9]*\\)"\` } currenttime=\`date '+%s'\` # Acquire the lock. If the lock is old, go ahead anyway. Else, abort. # Note that several instances of this script will be run in parallel, # so some precautions have to be taken for this locking mechanism to # merely work. log "Trying to acquire the lock" if [ ! -e $LOCKFILE ]; then create_lockfile else if [ -f $LOCKFILE -a -r $LOCKFILE ]; then read_lockfile if [ "\$timestamp" ]; then # First line fails, second line doesn't (most of the time). # Understand why, then please tell me why. # if expr \$currenttime '-' \$timestamp '<' $MAX_LOCK_AGE; then if [ \`expr \$currenttime '-' \$timestamp\` -lt $MAX_LOCK_AGE ]; then log "Found a recent lock, exiting" exit 0 else log "Found a stale lock" fi else log "Corrupted lockfile" fi else log "Weird lockfile" fi log "Removing lockfile" rm -f $LOCKFILE if [ \$? -gt 0 ]; then log "Cannot remove lockfile, exiting" exit 1 fi create_lockfile fi sleep 2 log "Checking lockfile" read_lockfile if [ ! "\$pid" ]; then log "Inexistant or corrupted lockfile, exiting" exit 1 fi if [ "\$pid" -ne \$\$ ]; then log "Process \$pid overwrote lockfile, exiting" exit 1 fi log "Killing all modem_run instances" killall modem_run pppd_pids=\`get_relevant_pppd_pids\` if [ "\$pppd_pids" ]; then log "Killing relevant pppd instances: \$pppd_pids" kill \$pppd_pids fi if [ -e /var/run/pppoa3-modem1.pid ]; then log "Removing stale pppoa3 pid file" rm -f /var/run/pppoa3-modem1.pid if [ \$? -gt 0 ]; then log "Could not remove pid file" fi fi # Release the lock. log "Releasing the lock" rm -f $LOCKFILE if [ \$? -gt 0 ]; then log "Could not remove lockfile" fi log "Done" EOF chmod 0755 $REMOVER # Remove the current driver instance. log "Killing all modem_run instances" killall modem_run pppd_pids=`get_relevant_pppd_pids` if [ "$pppd_pids" ]; then log "Killing relevant pppd instances: $pppd_pids" kill $pppd_pids fi if [ -e /var/run/pppoa3-modem1.pid ]; then log "Removing stale pppoa3 pid file" rm -f /var/run/pppoa3-modem1.pid if [ $? -gt 0 ]; then log "Cannot remove pid file, exiting" exit 1 fi fi # Write the substarter. Make it executable. log "Writing substarter" cat << EOF > $SUBSTARTER #!/bin/bash # SpeedTouch user-mode-driver substarter # Generated by /etc/hotplug/usb/speedtouch function log() { echo "\`date '+%F %T'\` substarter-$$-\$\$: \$1" >> $LOGFILE } # Run the user-mode driver. log "Launching modem_run" $PREFIX/sbin/modem_run -m $READ_FIRST -f $PREFIX/share/speedtouch/firmware log "Launching pppd" pppd call $PEER # Release the lock. log "Releasing the lock" rm -f $LOCKFILE if [ $? -gt 0 ]; then log "Could not remove lockfile" fi # The work is done. log "Removing myself" rm -f $SUBSTARTER log "Done" EOF chmod 0755 $SUBSTARTER # Run the substarter in the background. log "Starting substarter" $SUBSTARTER & log "Done" # vim: sts=3 sw=3 et