#!/bin/sh
#
# faxrunq
#
# look for outgoing fax jobs, send them via sendfax, if succesful, remove
# them from the outgoing queue (and send a mail to the originator of the
# job)
#
# There are still a lot rough edges - but it works, and should give you an
# idea how to improve it
#
# SCCS: @(#)faxrunq.in	1.10 94/04/09 Copyright (C) 1994 Gert Doering

FAX_SPOOL=/var/spool/fax
FAX_SPOOL_OUT=/var/spool/fax/outgoing
FAX_SENDER="/usr/local/sbin/sendfax -l ttyS0:ttyS1:ttyS2:ttyS3:ttyS4:ttyS5"
FAX_ACCT=$FAX_SPOOL/acct.log

MAILER="/usr/lib/sendmail"

#
# echo program that will accept escapes (bash: "echo -e", sun: /usr/5bin/echo)
#
echo="echo"

#
# awk program that is not stone-old-brain-dead (that is, not oawk...)
#
AWK=awk

#
# command line arguments
#
usage="usage: $0 [-q]"

while :
do
    case "$1" in
# quiet operation
	-q) exec >/dev/null ; shift ;;
	-*) $echo "$0: unknown option: $1" >&2
            $echo "$usage" >&2
	    exit 1
	    ;;
	*) break
    esac
done

if [ $# -gt 0 ]
then
    $echo "$usage" >&2
    exit 1
fi

#
# go to fax spool directory, process all JOB files
#

cd $FAX_SPOOL_OUT || exit 1

jobs=`ls */JOB 2>/dev/null`
for job in $jobs
do
    cd $FAX_SPOOL_OUT/`dirname $job`
    $echo "processing $job..."
#
#   lock JOB file (by 'mv'ing it to JOB.locked)
#
    # make sure it will get moved back in case the shell aborts
    trap "mv -f JOB.locked JOB 2>/dev/null" 0
    trap "mv -f JOB.locked JOB 2>/dev/null ; exit 20" 1 2 3 15

    mv -f JOB JOB.locked 2>/dev/null
    if [ $? -ne 0 ]
    then
	$echo "already locked"
	trap 0 1 2 3 15
	continue
    fi
#
# get user to notify (->$MAIL_TO) and phone number (->$PHONE)
#
    eval `$AWK 'BEGIN { user=""; mail=""; verbto=""; }
		$1=="user" { user=$2 }
		$1=="mail" { mail=substr( $0, 6) }
		$1=="phone" { printf "PHONE=%s;", $2 }
		$1=="verbose_to" { verbto=substr($0,12) }
		END { if ( mail != "" ) printf "MAIL_TO=\"%s\";", mail
				   else printf "MAIL_TO=\"%s\";", user
		      printf "VERBOSE_TO=\"%s\"", verbto }' JOB.locked`
#
# construct command line to execute
#
    command=`$AWK 'BEGIN { phone="-"; header=""; pages=""; polling="" }
		  $1=="phone" { phone=$2 }
		  $1=="header" { header=" -h "$2 }
		  $1=="poll" { polling=" -p" }
		  $1=="pages" { for( i=2; i<=NF; i++) pages=pages$i" " }
		  END { printf "'"$FAX_SENDER"' -v%s%s %s %s",
			       polling, header, phone, pages }' JOB.locked`
#
# execute faxsend command
#
    $echo "$command"
    eval $command
#
# handle return values
#
    status=$?
    $echo "command exited with status $status"

#
# string to include in subject line
#
    if [ -z "$VERBOSE_TO" ]
    then
        subject="your fax to $PHONE"
    else
        subject="your fax to $VERBOSE_TO ($PHONE)"
    fi

#
# evaluate return codes, if success, remove fax job from queue
#
    if [ $status -eq 0 ]
    then
	# transmission successful
	$echo "Status "`date`" successfully sent" >>JOB.locked
	( $echo "To: $MAIL_TO"
	  $echo "Subject: $subject"
	  $echo "From: root (Fax Subsystem)\n"
	  $echo "Your fax has been sent successfully at: \c"
	  date
	  $echo "\n\nJob / Log file:"
	  cat JOB.locked
	  tries=`grep Status JOB.locked | sed -e '1d' | wc -l`
	  $echo "\nSending succeeded after" $tries "unsuccessful tries."
	) |
	$MAILER "$MAIL_TO"

	# update accounting log
	$echo "$MAIL_TO $PHONE "`date`" success" >>$FAX_ACCT

	# job is done -> remove it from the queue
	mv JOB.locked JOB.done

	# if you want to delete the job directory that has just been
	# processed, uncomment the following two lines.
	#
	# cd $FAX_SPOOL_OUT
	# rm -rf `dirname $job`

    elif [ $status -lt 10 ]	
    then
	# error before starting to transmit (try again)
	why="unknown" ; case $status in
	    1) why="errors in command line" ;;
	    2) why="cannot open fax device (locked?)" ;;
	    3) why="modem initialization error" ;;
	    4) why="dial failed - BUSY" ;;
	esac
	$echo "Status "`date`" failed, exit($status): $why" >>JOB.locked
    else
	# error while transmitting, considered fatal
	why="unknown" ; case $status in
	    10) why="dial failed - NO CARRIER" ;;
	    11) why="protocol failure, waiting for XON" ;;
	    12) why="protocol failure sending page" ;;
	esac
	$echo "Status "`date`" FATAL FAILURE, exit($status): $why" >>JOB.locked

	# update accounting log
	$echo "$MAIL_TO $PHONE "`date`" fail: $why" >>$FAX_ACCT

	# if failed five times, supend job
	if [ `grep "FATAL FAILURE" JOB.locked | wc -l` -gt 4 ]
	then
	    $echo "Status "`date`" job suspended: too many FATAL errors" >>JOB.locked
	    ( $echo "To: $MAIL_TO"
	      $echo "Subject: $subject failed"
	      $echo "From: root (Fax Subsystem)\n"
	      $echo "It was not possible to send your fax to $PHONE!\n"
	      $echo "The fax job is suspended, you can requeue it with the command:"
	      $echo "    cd $FAX_SPOOL_OUT/"`dirname $job`
	      $echo "    mv JOB.suspended JOB\n"
	      $echo "log file follows:"
	      cat JOB.locked ) |
	    $MAILER "$MAIL_TO"
	    #
	    # suspend job (but do not delete it)
	    #
	    mv JOB.locked JOB.suspended
	fi
    fi
#
# unlock job (ignore errors, the JOB.locked file may have been moved
#             to JOB.suspended or JOB.done)
#
    mv -f JOB.locked JOB 2>/dev/null
    trap 0 1 2 3 15
done

