#! /bin/bash
#
# Johannes Meixner <jsmeix@suse.de>, 2007, 2008, 2009, 2010, 2011, 2014

#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
# Disable bash file name globbing:
set -f

# When 'localhost' or its IP-address is to be set,
# it is unified so that only 'localhost' or '127.0.0.1' are set
# (but not stuff like 'LocalHost' or '127.000.000.001').
SERVERNAME="$( echo $1 | sed -e 's/localhost/localhost/i' -e 's/127\.0*0\.0*0\.0*1/127.0.0.1/' )"

# When on a CUPS >= 1.6 client system a CUPS <= 1.5 server should be used
# there must be a "/version=1.1" suffix to enforce using IPP version 1.1
# because CUPS <= 1.5 servers reject higher IPP version requests with "Bad Request":
if zypper versioncmp $( cups-config --version ) 1.6 | grep -q 'newer'
then if test "none" != "$SERVERNAME" -a "localhost" != "$SERVERNAME" -a "127.0.0.1" != "$SERVERNAME"
     then # On a CUPS >= 1.6 system "lpstat -h cups_1.5_server -p" results on stderr:
          #   lpstat: Error - add '/version=1.1' to server name.
          if lpstat -h $SERVERNAME -p 2>&1 1>/dev/null | grep -q "add '/version=1.1' to server name"
          then SERVERNAME="${SERVERNAME}/version=1.1"
          fi
     fi
fi

if test -n "$SERVERNAME"
then # When a SERVERNAME is specified, set it in /etc/cups/client.conf
     # if SERVERNAME is not the magic word 'none' which
     # is used to only remove all active ServerName entries.
     # Note that even 'localhost' or '127.0.0.1' is a valid entry there
     # which is used to force client tools (e.g. lpadmin, lpinfo, lpstat)
     # to ask the local cupsd via the IPP port on localhost (127.0.0.1:631)
     # and not via the domain socket (/var/run/cups/cups.sock) because
     # the latter failed in the past for certain third-party clients (e.g. Java).
     # Note that (according to Michael Sweet) it is not a supported configuration
     # when a cupsd listens only on the domain socket but not on localhost so that
     # YaST can rely on that a local cupsd listens at least on localhost.
     if test -w /etc/cups/client.conf
     then # Remove all existing active ServerName entries with ignore case
          # (usually there should be at most one active ServerName entry):
          sed -i.yast2.save -e '/^ServerName/Id' /etc/cups/client.conf
          # Append the new active ServerName entry if SERVERNAME is not 'none':
          if test "none" != "$SERVERNAME"
          then echo "ServerName $SERVERNAME" >>/etc/cups/client.conf
          fi
     else # Create a new /etc/cups/client.conf with the active ServerName entry if SERVERNAME is not 'none':
          if test "none" != "$SERVERNAME" && echo "ServerName $SERVERNAME" >/etc/cups/client.conf
          then exit 0
          else echo "Failed to create /etc/cups/client.conf with 'ServerName $SERVERNAME' entry." 1>&2
               exit 1
          fi
     fi
fi

# In any case report what there might be set in /etc/cups/client.conf.
# If there is no active ServerName or when /etc/cups/client.conf does not exist,
# the output is the empty string (i.e. nothing at all - not even a '\n' character).
# The 'tr ... [:blank:]' makes sure that all active ServerName entries
# are found if there is more than one which is a broken config.
# Trailing spaces are removed and when 'localhost' or its IP-address is set,
# it is unified so that YaST only needs to test for 'localhost' and '127.0.0.1'
# (but not for stuff like 'LocalHost' or '127.000.000.001').
SERVERNAME="$( grep -i '^ServerName ' /etc/cups/client.conf | tr -s '[:blank:]' ' ' | cut -s -d' ' -f2 | tr -s '\n' ' ' | sed -e 's/ *$//' -e 's/localhost/localhost/i' -e 's/127\.0*0\.0*0\.0*1/127.0.0.1/' )"
# A possible "/version=1.1" suffix must be removed to get only the plain server name
# because both YaST and the test below only work with a plain server name:
SERVERNAME="${SERVERNAME%%/version=1.1}"
echo -n "$SERVERNAME"
# For a nicer output on a terminal where stdout and stderr is mixed up,
# output a '\n' on stderr to get subsequent stuff (e.g. the shell prompt
# or error messages because of a failed test below) on a new line:
echo 1>&2

# Test if the active ServerName is accessible, if such an entry exists.
if test -n "$SERVERNAME"
then # If the test fails, show an error message and exit with non-zero exit code.
     # The outermost subshell avoids job control messages like "[1] job_pid" and "[1]+ Done..." or "[1]+ Terminated...".
     # The hardcoded 2 seconds timeout is waited in any case so that the test needs always basically that timeout time.
     # In POSIX shells wait returns the exit code of the job even if it had already terminated when wait was started,
     # see http://pubs.opengroup.org/onlinepubs/9699919799/utilities/wait.html that reads:
     # "This volume of POSIX.1-2008 requires the implementation to keep the status
     #  of terminated jobs available until the status is requested":
     if ( ( echo -n '' >/dev/tcp/$SERVERNAME/631 ) & ECHO_PID=$! ; sleep 2s ; kill $ECHO_PID &>/dev/null ; wait $ECHO_PID )
     then echo "The server '$SERVERNAME' is accessible via port 631 (IPP/CUPS)." 1>&2
     else echo "The server '$SERVERNAME' is not accessible via port 631 (IPP/CUPS)." 1>&2
          exit 2
     fi
fi

# Exit successfully - also as fallback:
exit 0

