#! /bin/bash
#
# Listen on UDP port 631 for incoming CUPS network server broadcasts
# and if so extract the CUPS network server name
#
# Exits:   0 doesn't seem to have a problem
#          1 local UDP port 631 not available (perhaps cupsd is running?)
#          2 cannot create temporary file
#         11 netcat not executable (no netcat RPM installed?)
#         12 fuser not executable (no psmisc RPM installed?)
#         13 mktemp not executable (no mktemp RPM installed?)
#         14 sed not executable (no sed RPM installed?)
# The programs head, rm, sleep, sort are in the coreutils RPM and therefore assumed to exist.

#set -x

# Make sure to have a clean environment:
export PATH="/sbin:/usr/sbin:/usr/bin:/bin"
export LC_ALL="POSIX"
export LANG="POSIX"
umask 022

# Use the binaries of the operating system (no aliases, functions, /usr/local/):
export NETCAT=$( type -ap netcat | head -n 1 )
[ -z "$NETCAT" ] && { echo -en "\nnetcat not executable\n" 1>&2 ; exit 11 ; }
export FUSER=$( type -ap fuser | head -n 1 )
[ -z "$FUSER" ] && { echo -en "\nfuser not executable\n" 1>&2 ; exit 12 ; }
export MKTEMP=$( type -ap mktemp | head -n 1 )
[ -z "$MKTEMP" ] && { echo -en "\nmktemp not executable\n" 1>&2 ; exit 13 ; }
export SED=$( type -ap sed | head -n 1 )
[ -z "$SED" ] && { echo -en "\nsed not executable\n" 1>&2 ; exit 14 ; }

YAST_OUTPUT="/var/lib/YaST2/cups_network_server_name"
# The minimum timeout is 31 seconds because by default a
# CUPS server broadcasts every 30 seconds.
MINIMUM_TIMEOUT=31

cleanup()
{ EXIT_CODE=$?
  kill $NETCAT_PID &>/dev/null
  rm -f $OUTPUT &>/dev/null
  rm -f $PID_FILE &>/dev/null
  exit $EXIT_CODE
}
trap 'cleanup' 0 2 3 15
# Use SIGHUP to stop the additional waiting
trap 'SIGHUP_RECEIVED=1' 1

MY_NAME=${0##*/}
PID_FILE="/var/run/${MY_NAME}.pid"
echo $$ 1>$PID_FILE

# An additional timeout may be set
ADDITIONAL_TIMEOUT="$1"
[ -z "$ADDITIONAL_TIMEOUT" ] && ADDITIONAL_TIMEOUT=1

# Test whether local UDP port 631 is not available for connecting
$FUSER -n udp 631 &>/dev/null && { echo -en "\nUDP port 631 already in use\n" 1>&2 ; exit 1 ; }

# Create temporary file
OUTPUT=$( $MKTEMP -u /tmp/$MY_NAME.XXXXXX ) || { echo -en "\nCannot create temporary file\n" 1>&2 ; exit 2 ; }

# Listen on UDP port 631 for CUPS network server packages
$NETCAT -u -l -p 631 1>$OUTPUT 2>/dev/null &
NETCAT_PID=$!

# sleep is not interrupted by signals (except SIGKILL)
sleep $MINIMUM_TIMEOUT

# if SIGHUP was sent during "sleep $MINIMUM_TIMEOUT"
# then "SIGHUP_RECEIVED=1" is set by the signal handler
# if SIGHUP is sent during "sleep $ADDITIONAL_TIMEOUT &"
# then "wait $!" would be interrupted
[ -z "$SIGHUP_RECEIVED" ] && sleep $ADDITIONAL_TIMEOUT & wait $!

# as "netcat -w" does not work together with "-u" we send SIGKILL
kill -9 $NETCAT_PID &>/dev/null

# extract the CUPS network server names from the output
# and store them to be available for YaST
$SED -n -e 's/^.*ipp:\/\/\(.*\):.*$/\1/p' $OUTPUT | sort -u 1>$YAST_OUTPUT
exit 0

