#! /bin/bash

# You may start it with a command like:
# nohup nice ./makePPDtest 1>makePPDtest.stdout 2>makePPDtest.stderr &

# Enable for debugging:
#set -x

PPDpackages="OpenPrintingPPDs-ghostscript OpenPrintingPPDs-hpijs OpenPrintingPPDs-postscript"

# 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 to avoid side-effects
# with characters like '*' and '?' (see bnc #575056):
set -f

# Abort if another makePPDtest process is running at the same time:
if test "$( pgrep makePPDtest )" != "$$"
then echo "Aborting: Another makePPDtest is already running."
     exit 1
fi

# Abort if not root runs it:
if test "$( id -u )" != "0"
then echo "Aborting: You must be root to run makePPDtest."
     exit 1
fi

# Function to restart cupsd with new log and spool files.
# Since CUPS 1.4 'lpstat -r' results true even when scheduler is not running.
# Therefore we must now grep in its output:
restartcupsd()
{ rccups stop &>/dev/null
  sleep 1
  lpstat -h localhost -r | grep -q 'scheduler is running' && { echo "cupsd not stopped" ; exit 1 ; }
  # Re-enable bash file name globbing only for the next command:
  set +f
  rm -f /var/log/cups/* /var/spool/cups/c* /var/spool/cups/d* /var/spool/cups/tmp/*
  set -f
  rccups start &>/dev/null
  for i in $( seq 60 )
  do sleep 1
     lpstat -h localhost -r | grep -q 'scheduler is running' && break
  done
  lpstat -h localhost -r | grep -q 'scheduler is not running' && { echo "cupsd not available" ; exit 1 ; }
}

# Function to test a PPD:
testppd()
{ if file $1 | grep -q 'gzip compressed data'
  then catprogram="zcat"
  else catprogram="cat"
  fi
  if ! $catprogram $1 | cupstestppd - &>/dev/null
  then echo "Warning: cupstestppd failed: $1" | tee -a makePPDtest.failed
  fi
  restartcupsd
  lpadmin -h localhost -p PPDtest -v file:/dev/null -E -P $1
  lp -h localhost -d PPDtest $PStestpage &>/dev/null
  lp -h localhost -d PPDtest /etc/SuSE-release &>/dev/null
  for i in $( seq $MAX_JOB_WAIT )
  do sleep 1 
     lpstat -h localhost -o PPDtest | grep -q '^PPDtest' || break
  done
  if lpstat -h localhost -o PPDtest | grep -q '^PPDtest'
  then echo "printjob not finished: $1" | tee -a makePPDtest.failed
       cancel -h localhost -a PPDtest
       sleep 1
  fi
  # Wait to let the cupsd write to /var/log/cups/error_log
  sleep 1
  if cat /var/log/cups/error_log \
     | sed -e '/^E.*Unauthorized$/d' \
           -e '/^E.*Unable to bind socket for address/d' \
     | grep '^E'
  then echo "Errors while testppd: $1" | tee -a makePPDtest.failed
  else if test "2" = "$( grep 'Job completed' /var/log/cups/error_log | wc -l )"
       then echo "o.k.: $1" | tee -a makePPDtest.ok
       else "Not both jobs completed while testppd: $1" | tee -a makePPDtest.failed
       fi
  fi
  cp /var/log/cups/error_log makePPDtest.error_log.last
  lpadmin -h localhost -x PPDtest
  sleep 1
}

# Function to test all PPDs in a package:
testpackage()
{ echo "Testing $( rpm -ql $1 | egrep '\.ppd\.gz$|\.ppd$' | egrep "$2" | wc -l ) PPDs of package $1"
  for ppd in $( rpm -ql $1 | egrep '\.ppd\.gz$|\.ppd$' | egrep "$2" )
  do testppd $ppd
  done
}

# Function to report the version of some important RPMs:
packageversions()
{ for p in foomatic-filters cups-filters-foomatic-rip cups-libs cups-client $PPDpackages
  do rpm -q $p | tee -a makePPDtest.packageversions
  done
}

# Empty the output files:
>makePPDtest.packageversions
>makePPDtest.failed
>makePPDtest.ok
>makePPDtest.error_log.last

# Save cupsd.conf:
test -f /etc/cups/cupsd.conf.makePPDtest.save || cp -p /etc/cups/cupsd.conf /etc/cups/cupsd.conf.makePPDtest.save
# Set "Browsing Off":
if grep -q '^Browsing ' /etc/cups/cupsd.conf
then sed -i -e 's/^Browsing .*/Browsing Off/' /etc/cups/cupsd.conf
else if grep -q '^#.*Browsing ' /etc/cups/cupsd.conf
     then sed -i -e '/^#.*Browsing .*/aBrowsing Off' /etc/cups/cupsd.conf
     else echo "Aborting: No appropriate Browsing line found in /etc/cups/cupsd.conf"
          exit 1
     fi
fi
# Set "LogLevel debug":
if grep -q '^LogLevel ' /etc/cups/cupsd.conf
then sed -i -e 's/^LogLevel .*/LogLevel debug/' /etc/cups/cupsd.conf
else if grep -q '^#.*LogLevel ' /etc/cups/cupsd.conf
     then sed -i -e '/^#.*LogLevel .*/aLogLevel debug' /etc/cups/cupsd.conf
     else echo "Aborting: No appropriate LogLevel line found in /etc/cups/cupsd.conf"
          exit 1
     fi
fi
# Enable printing into files via "FileDevice yes":
if grep -q '^FileDevice ' /etc/cups/cupsd.conf
then sed -i -e 's/^FileDevice .*/FileDevice yes/' /etc/cups/cupsd.conf
else if grep -q '^#.*FileDevice ' /etc/cups/cupsd.conf
     then sed -i -e '/^#.*FileDevice .*/aFileDevice yes' /etc/cups/cupsd.conf
     else sed -i -e '/^LogLevel debug$/aFileDevice yes' /etc/cups/cupsd.conf
     fi
fi
# Disable log rotating via "MaxLogSize 0":
if grep -q '^MaxLogSize ' /etc/cups/cupsd.conf
then sed -i -e 's/^MaxLogSize .*/MaxLogSize 0/' /etc/cups/cupsd.conf
else if grep -q '^#.*MaxLogSize ' /etc/cups/cupsd.conf
     then sed -i -e '/^#.*MaxLogSize .*/aMaxLogSize 0' /etc/cups/cupsd.conf
     else sed -i -e '/^LogLevel debug$/aMaxLogSize 0' /etc/cups/cupsd.conf
     fi
fi
# Let the cupsd write files immediately (since CUPS 1.4):
if grep -q '^DirtyCleanInterval ' /etc/cups/cupsd.conf
then sed -i -e 's/^DirtyCleanInterval .*/DirtyCleanInterval 0/' /etc/cups/cupsd.conf
else if grep -q '^#.*DirtyCleanInterval ' /etc/cups/cupsd.conf
     then sed -i -e '/^#.*DirtyCleanInterval .*/aDirtyCleanInterval 0' /etc/cups/cupsd.conf
     else sed -i -e '/^LogLevel debug$/aDirtyCleanInterval 0' /etc/cups/cupsd.conf
     fi
fi

# Remove the PPDtest queue:
restartcupsd
lpadmin -h localhost -x PPDtest &>/dev/null

# Deterimne the PostScript testpage file according to the installed packages:
PStestpage="$( rpm -ql yast2-printer | grep 'testprint\.ps$' || rpm -ql ghostscript-library | grep 'colorcir\.ps$' || echo 'no_PostScript_testpage_found' )"
echo "Using PStestpage: $PStestpage"

# Depending on the command line parameters:
# - Test a single PPD with 'LogLevel debug2'
#   if the first parameter ends with .ppd or .ppd.gz
# - Test all PPDs in a package
#   if the first parameter is an installed package
#   and use an optional second parameter as 'egrep' search pattern
#   for the PPD file names in the package
# - Fall back to test all PPDs in all installed OpenPrintingPPDs packages
#   and show the version of the important RPMs
#   and use an optional first parameter as 'egrep' search pattern
#   for the PPD file names in the packages
MAX_JOB_WAIT=120
if echo "$1" | egrep -q '\.ppd\.gz$|\.ppd$'
then sed -i -e 's/^LogLevel .*/LogLevel debug2/' /etc/cups/cupsd.conf
     MAX_JOB_WAIT=300
     testppd $1
else if rpm -q "$1" &>/dev/null
     then testpackage $1 $2
     else packageversions
          for p in $PPDpackages
          do rpm -q $p && testpackage $p $1
          done
     fi
fi

