"Fossies" - the Fresh Open Source Software Archive

Member "shorewall-core-5.2.8/lib.common" (24 Sep 2020, 17751 Bytes) of package /linux/misc/shorewall/shorewall-core-5.2.8.tar.bz2:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "lib.common": 5.2.3.6_vs_5.2.6.

    1 #
    2 # Shorewall 5.2 -- /usr/share/shorewall/lib.common
    3 #
    4 #     (c) 2010-2018 - Tom Eastep (teastep@shorewall.net)
    5 #
    6 #	Complete documentation is available at https://shorewall.org
    7 #
    8 #       This program is part of Shorewall.
    9 #
   10 #	This program is free software; you can redistribute it and/or modify
   11 #	it under the terms of the GNU General Public License as published by the
   12 #       Free Software Foundation, either version 2 of the license or, at your
   13 #       option, any later version.
   14 #
   15 #	This program is distributed in the hope that it will be useful,
   16 #	but WITHOUT ANY WARRANTY; without even the implied warranty of
   17 #	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   18 #	GNU General Public License for more details.
   19 #
   20 #	You should have received a copy of the GNU General Public License
   21 #	along with this program; if not, see <http://www.gnu.org/licenses/>.
   22 #
   23 # The purpose of this library is to hold those functions used by both the CLI and by the
   24 # generated firewall scripts. To avoid versioning issues, it is copied into generated
   25 # scripts rather than loaded at run-time.
   26 #
   27 #########################################################################################
   28 #
   29 # Wrapper around logger that sets the tag according to $SW_LOGGERTAG
   30 #
   31 mylogger() {
   32     local level
   33 
   34     level=$1
   35     shift
   36 
   37     if [ -n "$SW_LOGGERTAG" ]; then
   38 	logger -p $level -t "$SW_LOGGERTAG" $*
   39     else
   40 	logger -p $level $*
   41     fi
   42 }
   43 
   44 #
   45 # Issue a message and stop
   46 #
   47 startup_error() # $* = Error Message
   48 {
   49     echo "   ERROR: $@: Firewall state not changed" >&2
   50 
   51     if [ $LOG_VERBOSITY -ge 0 ]; then
   52         timestamp="$(date +'%b %e %T') "
   53         echo "${timestamp}  ERROR: $@" >> $STARTUP_LOG
   54     fi
   55 
   56     case $COMMAND in
   57         start)
   58 	    mylogger daemon.err "ERROR:$g_product start failed:Firewall state not changed"
   59 	    ;;
   60 	restart)
   61 	    mylogger daemon.err "ERROR:$g_product restart failed:Firewall state not changed"
   62 	    ;;
   63 	restore)
   64 	    mylogger daemon.err "ERROR:$g_product restore failed:Firewall state not changed"
   65 	    ;;
   66     esac
   67 
   68     if [ $LOG_VERBOSITY -ge 0 ]; then
   69         timestamp="$(date +'%b %e %T') "
   70 
   71 	case $COMMAND in
   72 	    start)
   73 		echo "${timestamp}  ERROR:$g_product start failed:Firewall state not changed" >> $STARTUP_LOG
   74 		;;
   75 	    restart)
   76 		echo "${timestamp}  ERROR:$g_product restart failed:Firewall state not changed" >> $STARTUP_LOG
   77 		;;
   78 	    restore)
   79 		echo "${timestamp}  ERROR:$g_product restore failed:Firewall state not changed" >> $STARTUP_LOG
   80 		;;
   81 	esac
   82     fi
   83 
   84     mutex_off
   85     kill $$
   86     exit 2
   87 }
   88 
   89 #
   90 # Create the required option string and run the passed script using
   91 # $SHOREWALL_SHELL
   92 #
   93 run_it() {
   94     local script
   95     local options='-'
   96 
   97     export VARDIR
   98 
   99     script=$1
  100     shift
  101 
  102 
  103     if [ "$g_debugging" = debug ]; then
  104 	options='-D'
  105     elif [ "$g_debugging" = trace ]; then
  106 	options='-T'
  107     else
  108 	options='-';
  109     fi
  110 
  111     [ -n "$g_noroutes" ]   && options=${options}n
  112     [ -n "$g_timestamp" ]  && options=${options}t
  113     [ -n "$g_purge" ]      && options=${options}p
  114     [ -n "$g_recovering" ] && options=${options}r
  115     [ -n "$g_counters" ]   && options=${options}c
  116 
  117     options="${options}V $VERBOSITY"
  118 
  119     [ -n "$RESTOREFILE" ] && options="${options} -R $RESTOREFILE"
  120 
  121     $SHOREWALL_SHELL $script $options $@
  122 }
  123 
  124 #
  125 # Message to stderr
  126 #
  127 error_message() # $* = Error Message
  128 {
  129    echo "   $@" >&2
  130    return 1
  131 }
  132 
  133 #
  134 # Undo the effect of 'split()'
  135 #
  136 join()
  137 {
  138     local f
  139     local o
  140     o=
  141 
  142     for f in $* ; do
  143         o="${o:+$o:}$f"
  144     done
  145 
  146     echo $o
  147 }
  148 
  149 #
  150 # Return the number of elements in a list
  151 #
  152 list_count() # $* = list
  153 {
  154     return $#
  155 }
  156 
  157 #
  158 # Split a colon-separated list into a space-separated list
  159 #
  160 split() {
  161     local ifs
  162     ifs=$IFS
  163     IFS=:
  164     echo $*
  165     IFS=$ifs
  166 }
  167 
  168 #
  169 # Split a comma-separated list into a space-separated list
  170 #
  171 split_list() {
  172     local ifs
  173     ifs=$IFS
  174     IFS=,
  175     echo $*
  176     IFS=$ifs
  177 }
  178 
  179 #
  180 # Search a list looking for a match -- returns zero if a match found
  181 # 1 otherwise
  182 #
  183 list_search() # $1 = element to search for , $2-$n = list
  184 {
  185     local e
  186     e=$1
  187 
  188     while [ $# -gt 1 ]; do
  189 	shift
  190 	[ "x$e" = "x$1" ] && return 0
  191     done
  192 
  193     return 1
  194 }
  195 
  196 #
  197 # Suppress all output for a command
  198 #
  199 qt()
  200 {
  201     "$@" >/dev/null 2>&1
  202 }
  203 
  204 #
  205 # Suppress all output and input - mainly for preventing leaked file descriptors
  206 # to avoid SELinux denials
  207 #
  208 qtnoin()
  209 {
  210     "$@" </dev/null >/dev/null 2>&1
  211 }
  212 
  213 qt1()
  214 {
  215     local status
  216 
  217     while [ 1 ]; do
  218 	"$@" </dev/null >/dev/null 2>&1
  219 	status=$?
  220 	[ $status -ne 4 ] && return $status
  221     done
  222 }
  223 
  224 #
  225 # Determine if Shorewall[6] is "running"
  226 #
  227 product_is_started() {
  228     qt1 $g_tool -L shorewall -n
  229 }
  230 
  231 shorewall_is_started() {
  232     qt1 $IPTABLES -L shorewall -n
  233 }
  234 
  235 shorewall6_is_started() {
  236     qt1 $IP6TABLES -L shorewall -n
  237 }
  238 
  239 #
  240 # Echos the fully-qualified name of the calling shell program
  241 #
  242 my_pathname() {
  243     local pwd
  244     pwd=$PWD
  245     cd $(dirname $0)
  246     echo $PWD/$(basename $0)
  247     cd $pwd
  248 }
  249 
  250 #
  251 # Source a user exit file if it exists
  252 #
  253 run_user_exit() # $1 = file name
  254 {
  255     local user_exit
  256     user_exit=$(find_file $1)
  257 
  258     if [ -f $user_exit ]; then
  259 	progress_message "Processing $user_exit ..."
  260 	. $user_exit
  261     fi
  262 }
  263 
  264 #
  265 # Load a Kernel Module -- assumes that the variable 'moduledirectories' contains
  266 #                         a space-separated list of directories to search for
  267 #                         the module and that 'moduleloader' contains the
  268 #                         module loader command.
  269 #
  270 loadmodule() # $1 = module name, $2 - * arguments
  271 {
  272     local modulename
  273     modulename=$1
  274     shift
  275     local moduleoptions
  276     moduleoptions=$*
  277     local modulefile
  278     local suffix
  279 
  280     if [ -d /sys/module/ ]; then
  281 	if ! list_search $modulename $DONT_LOAD; then
  282 	    if [ ! -d /sys/module/$modulename ]; then
  283 		case $moduleloader in
  284 		    insmod)
  285 			for directory in $moduledirectories; do
  286 			    for modulefile in $directory/${modulename}.*; do
  287 				if [ -f $modulefile ]; then
  288 				    insmod $modulefile $moduleoptions
  289 				    return
  290 				fi
  291 			    done
  292 			done
  293 			;;
  294 		    *)
  295 			modprobe -q $modulename $moduleoptions
  296 			;;
  297 		esac
  298 	    fi
  299 	fi
  300     elif ! list_search $modulename $DONT_LOAD $MODULES; then
  301 	case $moduleloader in
  302 	    insmod)
  303 		for directory in $moduledirectories; do
  304 		    for modulefile in $directory/${modulename}.*; do
  305 			if [ -f $modulefile ]; then
  306 			    insmod $modulefile $moduleoptions
  307 			    return
  308 			fi
  309 		    done
  310 		done
  311 		;;
  312 	    *)
  313 		modprobe -q $modulename $moduleoptions
  314 		;;
  315 	esac
  316     fi
  317 }
  318 
  319 #
  320 # Reload the Modules
  321 #
  322 reload_kernel_modules() {
  323 
  324     local save_modules_dir
  325     save_modules_dir=$MODULESDIR
  326     local directory
  327     local moduledirectories
  328     moduledirectories=
  329     local moduleloader
  330     moduleloader=modprobe
  331     local uname
  332     local extras
  333 
  334     if ! qt mywhich modprobe; then
  335 	moduleloader=insmod
  336     fi
  337 
  338     if [ -n "$MODULESDIR" ]; then
  339 	case "$MODULESDIR" in
  340 	    +*)
  341 		extras="$MODULESDIR"
  342 		extras=${extras#+}
  343 		MODULESDIR=
  344 		;;
  345 	esac
  346     fi
  347 
  348     if [ -z "$MODULESDIR" ]; then
  349 	uname=$(uname -r)
  350 	MODULESDIR=/lib/modules/$uname/kernel/net/ipv${g_family}/netfilter:/lib/modules/$uname/kernel/net/netfilter:/lib/modules/$uname/kernel/net/sched:/lib/modules/$uname/extra:/lib/modules/$uname/extra/ipset
  351 	if [ -n "$extras" ]; then
  352 	    for directory in $(split "$extras"); do
  353 		MODULESDIR="$MODULESDIR:/lib/modules/$uname/$directory"
  354 	    done
  355 	fi
  356     fi
  357 
  358     [ -d /sys/module/ ] || MODULES=$(lsmod | cut -d ' ' -f1)
  359 
  360     for directory in $(split $MODULESDIR); do
  361 	[ -d $directory ] && moduledirectories="$moduledirectories $directory"
  362     done
  363 
  364     [ -n "$moduledirectories" ] && while read command; do
  365 	eval $command
  366     done
  367 
  368     MODULESDIR=$save_modules_dir
  369 }
  370 
  371 #
  372 # Load kernel modules required for Shorewall
  373 #
  374 load_kernel_modules() # $1 = Yes, if we are to save moduleinfo in $VARDIR
  375 {
  376     local save_modules_dir
  377     save_modules_dir=$MODULESDIR
  378     local directory
  379     local moduledirectories
  380     moduledirectories=
  381     local moduleloader
  382     moduleloader=modprobe
  383     local savemoduleinfo
  384     savemoduleinfo=${1:-Yes} # So old compiled scripts still work
  385     local uname
  386     local extras
  387 
  388     if ! qt mywhich modprobe; then
  389 	moduleloader=insmod
  390     fi
  391 
  392     if [ -n "$MODULESDIR" ]; then
  393 	case "$MODULESDIR" in
  394 	    +*)
  395 		extras="$MODULESDIR"
  396 		extras=${extras#+}
  397 		MODULESDIR=
  398 		;;
  399 	esac
  400     fi
  401 
  402     if [ -z "$MODULESDIR" ]; then
  403 	uname=$(uname -r)
  404 	MODULESDIR=/lib/modules/$uname/kernel/net/ipv${g_family}/netfilter:/lib/modules/$uname/kernel/net/netfilter:/lib/modules/$uname/kernel/net/sched:/lib/modules/$uname/extra:/lib/modules/$uname/extra/ipset
  405 	if [ -n "$extras" ]; then
  406 	    for directory in $(split "$extras"); do
  407 		MODULESDIR="$MODULESDIR:/lib/modules/$uname/$directory"
  408 	    done
  409 	fi
  410     fi
  411 
  412     for directory in $(split $MODULESDIR); do
  413 	[ -d $directory ] && moduledirectories="$moduledirectories $directory"
  414     done
  415 
  416     modules=$(find_file helpers)
  417 
  418     if [ -f $modules -a -n "$moduledirectories" ]; then
  419 	[ -d /sys/module/ ] || MODULES=$(lsmod | cut -d ' ' -f1)
  420 	progress_message "Loading Modules..."
  421 	. $modules
  422 	if [ $savemoduleinfo = Yes ]; then
  423 	    [ -d ${VARDIR} ] || mkdir -p ${VARDIR}
  424 	    echo MODULESDIR=\"$MODULESDIR\" > ${VARDIR}/.modulesdir
  425 	    cp -f $modules ${VARDIR}/.modules
  426 	fi
  427     elif [ $savemoduleinfo = Yes ]; then
  428 	[ -d ${VARDIR} ] || mkdir -p ${VARDIR}
  429 	> ${VARDIR}/.modulesdir
  430 	> ${VARDIR}/.modules
  431     fi
  432 
  433     MODULESDIR=$save_modules_dir
  434 }
  435 
  436 #
  437 #  Note: The following set of IP address manipulation functions have anomalous
  438 #        behavior when the shell only supports 32-bit signed arithmetic and
  439 #        the IP address is 128.0.0.0 or 128.0.0.1.
  440 #
  441 
  442 LEFTSHIFT='<<'
  443 
  444 #
  445 # Convert an IP address in dot quad format to an integer
  446 #
  447 decodeaddr() {
  448     local x
  449     local temp
  450     temp=0
  451     local ifs
  452     ifs=$IFS
  453 
  454     IFS=.
  455 
  456     for x in $1; do
  457 	temp=$(( $(( $temp $LEFTSHIFT 8 )) | $x ))
  458     done
  459 
  460     echo $temp
  461 
  462     IFS=$ifs
  463 }
  464 
  465 #
  466 # convert an integer to dot quad format
  467 #
  468 encodeaddr() {
  469     addr=$1
  470     local x
  471     local y
  472     y=$(($addr & 255))
  473 
  474     for x in 1 2 3 ; do
  475 	addr=$(($addr >> 8))
  476 	y=$(($addr & 255)).$y
  477     done
  478 
  479     echo $y
  480 }
  481 
  482 #
  483 # Netmask from CIDR
  484 #
  485 ip_netmask() {
  486     local vlsm
  487     vlsm=${1#*/}
  488 
  489     [ $vlsm -eq 0 ] && echo 0 || echo $(( -1 $LEFTSHIFT $(( 32 - $vlsm )) ))
  490 }
  491 
  492 #
  493 # Network address from CIDR
  494 #
  495 ip_network() {
  496     local decodedaddr
  497     decodedaddr=$(decodeaddr ${1%/*})
  498     local netmask
  499     netmask=$(ip_netmask $1)
  500 
  501     echo $(encodeaddr $(($decodedaddr & $netmask)))
  502 }
  503 
  504 #
  505 # The following hack is supplied to compensate for the fact that many of
  506 # the popular light-weight Bourne shell derivatives do not support XOR ("^").
  507 #
  508 ip_broadcast() {
  509     local x
  510     x=$(( 32 - ${1#*/} ))
  511 
  512     [ $x -eq 32 ] && echo -1 || echo $(( $(( 1 $LEFTSHIFT $x )) - 1 ))
  513 }
  514 
  515 #
  516 # Calculate broadcast address from CIDR
  517 #
  518 broadcastaddress() {
  519     local decodedaddr
  520     decodedaddr=$(decodeaddr ${1%/*})
  521     local netmask
  522     netmask=$(ip_netmask $1)
  523     local broadcast
  524     broadcast=$(ip_broadcast $1)
  525 
  526     echo $(encodeaddr $(( $(($decodedaddr & $netmask)) | $broadcast )))
  527 }
  528 
  529 #
  530 # Test for network membership
  531 #
  532 in_network() # $1 = IP address, $2 = CIDR network
  533 {
  534     local netmask
  535     netmask=$(ip_netmask $2)
  536     #
  537     # Use string comparison to work around a broken BusyBox ash in OpenWRT
  538     #
  539     test $(( $(decodeaddr $1) & $netmask)) = $(( $(decodeaddr ${2%/*}) & $netmask ))
  540 }
  541 
  542 #
  543 # Query NetFilter about the existence of a filter chain
  544 #
  545 chain_exists() # $1 = chain name, $2 = table name (optional)
  546 {
  547     qt1 $g_tool -t ${2:-filter} -L $1 -n
  548 }
  549 
  550 #
  551 # Find the interface with the passed MAC address
  552 #
  553 
  554 find_interface_by_mac() {
  555     local mac
  556     mac=$1
  557     local first
  558     local second
  559     local rest
  560     local dev
  561 
  562     $IP link list | while read first second rest; do
  563 	case $first in
  564 	    *:)
  565                 dev=$second
  566 		;;
  567 	    *)
  568 	        if [ "$second" = $mac ]; then
  569 		    echo ${dev%:}
  570 		    return
  571 		fi
  572 	esac
  573     done
  574 }
  575 
  576 #
  577 # Find interface address--returns the first IP address assigned to the passed
  578 # device
  579 #
  580 find_first_interface_address() # $1 = interface
  581 {
  582     if [ $g_family -eq 4 ]; then
  583 	#
  584 	# get the line of output containing the first IP address
  585 	#
  586 	addr=$(${IP:-ip} -f inet addr show $1 2> /dev/null | grep 'inet .* global' | head -n1)
  587 	#
  588 	# If there wasn't one, bail out now
  589 	#
  590 	[ -n "$addr" ] || startup_error "Can't determine the IP address of $1"
  591 	#
  592 	# Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link)
  593 	# along with everything else on the line
  594 	#
  595 	echo $addr | sed 's/\s*inet //;s/\/.*//;s/ peer.*//'
  596     else
  597 	#
  598 	# get the line of output containing the first IP address
  599 	#
  600 	addr=$(${IP:-ip} -f inet6 addr show dev $1 2> /dev/null | grep -F 'inet6 ' | grep -vF 'scope link' | head -n1)
  601 	#
  602 	# If there wasn't one, bail out now
  603 	#
  604 	[ -n "$addr" ] || startup_error "Can't determine the IPv6 address of $1"
  605 	#
  606 	# Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link)
  607 	# along with everything else on the line
  608 	#
  609 	echo $addr | sed 's/\s*inet6 //;s/\/.*//;s/ peer.*//'
  610     fi
  611 }
  612 
  613 find_first_interface_address_if_any() # $1 = interface
  614 {
  615     if [ $g_family -eq 4 ]; then
  616 	#
  617 	# get the line of output containing the first IP address
  618 	#
  619 	addr=$(${IP:-ip} -f inet addr show $1 2> /dev/null | grep 'inet .* global' | head -n1)
  620 	#
  621 	# Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link)
  622 	# along with everything else on the line
  623 	#
  624 	[ -n "$addr" ] && echo $addr | sed 's/\s*inet //;s/\/.*//;s/ peer.*//' || echo 0.0.0.0
  625     else
  626 	#
  627 	# get the line of output containing the first IP address
  628 	#
  629 	addr=$(${IP:-ip} -f inet6 addr show dev $1 2> /dev/null | grep -F 'inet6 ' | grep -vF 'scope link' | head -n1)
  630 	#
  631 	# Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link)
  632 	# along with everything else on the line
  633 	#
  634 	[ -n "$addr" ] && echo $addr | sed 's/\s*inet6 //;s/\/.*//;s/ peer.*//' || echo ::
  635     fi
  636 }
  637 
  638 #
  639 #Determines if the passed interface is a loopback interface
  640 #
  641 loopback_interface() { #$1 = Interface name
  642     [ "$1" = lo ] || $IP link show $1 | fgrep -q LOOPBACK
  643 }
  644 
  645 #
  646 # Find Loopback Interfaces
  647 #
  648 find_loopback_interfaces() {
  649     local interfaces
  650 
  651     [ -x "$IP" ] && interfaces=$($IP link show | fgrep LOOPBACK | sed 's/://g' | cut -d ' ' -f 2)
  652 
  653     [ -n "$interfaces" ] && echo $interfaces || echo lo
  654 }
  655 
  656 #
  657 # Internal version of 'which'
  658 #
  659 mywhich() {
  660     local dir
  661 
  662     for dir in $(split $PATH); do
  663 	if [ -x $dir/$1 ]; then
  664 	    echo $dir/$1
  665 	    return 0
  666 	fi
  667     done
  668 
  669     return 2
  670 }
  671 
  672 #
  673 # Find a File -- For relative file name, look in each ${CONFIG_PATH} then ${CONFDIR}
  674 #
  675 find_file()
  676 {
  677     local saveifs
  678     saveifs=
  679     local directory
  680 
  681     case $1 in
  682 	/*)
  683 	    echo $1
  684 	    ;;
  685 	*)
  686 	    for directory in $(split $CONFIG_PATH); do
  687 		if [ -f $directory/$1 ]; then
  688 		    echo $directory/$1
  689 		    return
  690 		fi
  691 	    done
  692 
  693 	    if [ -n "$g_shorewalldir" ]; then
  694 		echo ${g_shorewalldir}/$1
  695 	    else
  696 		echo ${g_confdir}/$1
  697 	    fi
  698 	    ;;
  699     esac
  700 }
  701 
  702 #
  703 # Set the Shorewall state
  704 #
  705 set_state () # $1 = state
  706 {
  707     if [ $# -gt 1 ]; then
  708 	echo "$1 $(date) from $2" > ${VARDIR}/state
  709     else
  710 	echo "$1 $(date)" > ${VARDIR}/state
  711     fi
  712 }
  713 
  714 #
  715 # Perform variable substitution on the passed argument and echo the result
  716 #
  717 expand() # $@ = contents of variable which may be the name of another variable
  718 {
  719     eval echo \"$@\"
  720 }
  721 
  722 #
  723 # Function for including one file into another
  724 #
  725 INCLUDE() {
  726     . $(find_file $(expand $@))
  727 }
  728 
  729 # Function to truncate a string -- It uses 'cut -b -<n>'
  730 # rather than ${v:first:last} because light-weight shells like ash and
  731 # dash do not support that form of expansion.
  732 #
  733 
  734 truncate() # $1 = length
  735 {
  736     cut -b -${1}
  737 }
  738 
  739 #
  740 # Call this function to assert mutual exclusion with Shorewall. If you invoke the
  741 # /sbin/shorewall program while holding mutual exclusion, you should pass -N as
  742 # the first argument. Example "shorewall -N refresh"
  743 #
  744 # This function uses the lockfile utility from procmail if it exists.
  745 # Otherwise, it uses a somewhat race-prone algorithm to attempt to simulate the
  746 # behavior of lockfile.
  747 #
  748 mutex_on()
  749 {
  750     local try
  751     try=0
  752     local lockf
  753     lockf=${LOCKFILE:=${VARDIR}/lock}
  754     local lockpid
  755     local lockd
  756     local lockbin
  757     local openwrt
  758 
  759     MUTEX_TIMEOUT=${MUTEX_TIMEOUT:-60}
  760 
  761     if [ -z "$g_havemutex" -a $MUTEX_TIMEOUT -gt 0 ]; then
  762 
  763 	lockd=$(dirname $LOCKFILE)
  764 
  765 	[ -d "$lockd" ] || mkdir -p "$lockd"
  766 
  767 	lockbin=$(mywhich lock)
  768 	[ -n "$lockbin" -a -h "$lockbin" ] && openwrt=Yes
  769 
  770 	if [ -f $lockf ]; then
  771 	    lockpid=`cat ${lockf} 2> /dev/null`
  772 	    if [ -z "$lockpid" ] || [ $lockpid = 0 ]; then
  773 		rm -f ${lockf}
  774 		error_message "WARNING: Stale lockfile ${lockf} removed"
  775 	    elif [ -z "$openwrt" ]; then
  776 		if [ $lockpid -eq $$ ]; then
  777                     fatal_error "Mutex_on confusion"
  778 		elif ! qt ps --pid ${lockpid}; then
  779 		    rm -f ${lockf}
  780 		    error_message "WARNING: Stale lockfile ${lockf} from pid ${lockpid} removed"
  781 		fi
  782 	    fi
  783 	fi
  784 
  785 	if [ -n "$openwrt" ]; then
  786 	    lock ${lockf} || fatal_error "Can't lock ${lockf}"
  787 	    g_havemutex="lock -u ${lockf}"
  788 	elif qt mywhich lockfile; then
  789 	    lockfile -${MUTEX_TIMEOUT} -r1 ${lockf} || fatal_error "Can't lock ${lockf}"
  790 	    g_havemutex="rm -f ${lockf}"
  791 	    chmod u+w ${lockf}
  792 	    echo $$ > ${lockf}
  793 	    chmod u-w ${lockf}
  794 	else
  795 	    while [ -f ${lockf} -a ${try} -lt ${MUTEX_TIMEOUT} ] ; do
  796 		sleep 1
  797 		try=$((${try} + 1))
  798 	    done
  799 
  800 	    if  [ ${try} -lt ${MUTEX_TIMEOUT} ] ; then
  801 	        # Create the lockfile
  802 		echo $$ > ${lockf}
  803 		g_havemutex="rm -f ${lockf}"
  804 	    else
  805 		echo "Giving up on lock file ${lockf}" >&2
  806 	    fi
  807 	fi
  808 
  809 	if [ -n "$g_havemutex" ]; then
  810 	    trap mutex_off EXIT
  811 	fi
  812     fi
  813 }
  814 
  815 #
  816 # Call this function to release mutual exclusion
  817 #
  818 mutex_off()
  819 {
  820     if [ -n "$g_havemutex" ]; then
  821 	eval $g_havemutex
  822 	g_havemutex=
  823 	trap '' exit
  824     fi
  825 }
  826