#!/bin/sh
# 
# fax - script to make, send, receive, view or print a fax
# Copyright 1993-1999 by Ed Casas 
# 

# --- the name of this script

FAX=/usr/pkg/bin/fax

# --- source primary configuration file

if [ -r /usr/pkg/etc/efax.rc ]
    then
		eval "`cat /usr/pkg/etc/efax.rc`"
    else
    echo "Cannot read configuration file \`/usr/pkg/etc/efax.rc\'"
    exit 1
fi

# --- source extra configuration files (if any)

for f in $CONFIGFILES
do
	if [ -r $f ]
	then
		eval "`cat $f`"
	fi
done

# --- set any variables given on command line

while : ; do
	case $# in 0) break ;; esac
	case "$1" in [A-Z]*=*) eval $1 ; shift ;; *) break ;; esac
done

# -------- initialize 

ERR=0

$NICE true 2>/dev/null ; case $? in 0) ;; *) NICE="" ;; esac

# -------- resolve dependencies on command-line arguments

eval LOCK=\"$LOCK\"			# depends on DEV

# make device name w/o directories

case $DEV in
	*/*) DEVN=`echo $DEV|sed -e s./._.g` ;;
	*) DEVN=$DEV ;;
esac

case $PAGE in
	letter)	PAGEDIM="$PAGE_letter" ;;
	legal) 	PAGEDIM="$PAGE_legal" ;;
	a4) 	PAGEDIM="$PAGE_a4" ;;
	*) 	echo "Error: PAGE=\"${PAGE}\" not valid." ; exit 2 ;;
esac	

# --- check for a command or alias and optional flags

cmd=""
case $0 in
*/faxlpr|faxlpr) cmd=faxlpr ;; 
*) 
	while : ; do
	case $# in 0) case $cmd in '') cmd=receive ;; esac ; break ;; esac
   	case $1 in 
	-l) OPT="$OPT -l" ; RES=204x98 ; shift ;; 
	-h) OPT="$OPT -h" ; RES=204x196 ; shift ;; 
	-v) OPT="$OPT -v" ; VERB=$VERBLOG ; shift ;; 
	*) 
		case $cmd in '') cmd=$1 ; shift ;; *) break ;; esac
	;;
   	esac
	done
;; 
esac

# -------- functions

faxmail () {
   echo "Subject: fax/message from $1"
   shift
   echo "Content-Type: multipart/mixed; boundary=EFAX_MAIL"
   echo ""
   echo "--EFAX_MAIL"
   echo "Content-Type: text/plain; charset=\"us-ascii\""
   echo "Content-Transfer-Encoding: 7bit"
   echo ""
   cat $1
   shift
   for f in $*
   do
     echo "--EFAX_MAIL"
     echo "Content-Type: image/tiff"
     echo "Content-Transfer-Encoding: base64"
     echo ""
     $EFIX -M <$f
   done
}

# -------- export variables for fone script

export DEV TSTAMP

# -------- do the appropriate command

while : ; do 	# so we can use `break' to get to the end of the script

case $cmd in 

# fax answer : clean up logs and exec efax. normally run by init(8).

	answer)

	if cd $FAXDIR ; then :
	else
		echo "Error: $FAX cannot cd to $FAXDIR" >>$CONSOLE
		sleep 30
		break
	fi

	while [ -f ${DEVN}.stop ] ; do sleep 15 ; done

	umask $UMASK
	case $OWNER in '') ;; *) chown $OWNER /dev/$DEV ;; esac
	case $MODE  in '') ;; *) chmod $MODE  /dev/$DEV ;; esac

	for f in ${DEVN}.[0-9]*  	# clean up old log files
	do
	  egrep	"done, returning $NOLOG|exec'ing" $f >/dev/null 2>/dev/null
	  case $? in
	  0) 
	  	$RM $f
	  ;;
	  1)    FILES=`sed -n -e  '/received ->/s/^.*-> \(.*\)$/\1/p' $f`
		FILES=`echo $FILES`
		REMID=`sed -n -e '/remote ID ->/s/^.*-> \(.*\)$/\1/p' \
			-e tok -e b -e ':ok' -e q $f`
		case $REMID in '') REMID='?' ;; esac
		eval $NOTIFY
		echo   >>${LOGDIR}/${DEVN}.log
		cat $f >>${LOGDIR}/${DEVN}.log
	  	$RM $f
	  ;;
	  esac
	done	

	exec $NICE $EFAX -v "" -v "$VERBLOG" -d/dev/$DEV $INIT $SPKR \
	$CLASSINIT $FCINIT $RXINIT $LOCK \
	$RXCAP -l "$FROM" $RESET \
	$DATAINIT -g "$DCMD" $VOICEINIT -e "$VCMD" \
	-jS0=$ANSRINGS -w -s -r "$ANSFNAME" 2>$CONSOLE >${DEVN}.$$

	echo ERROR: $FAX answer exec failed >>$CONSOLE ; sleep 30

	break
	;;


# fax reanswer : switch from voice mode to fax[/data] mode

	reanswer)

	# we should already be in the fax spool directory, the
	# device locked, the modem answered and initialized in
	# voice mode and stdout/stderr redirected appropriately

	umask $UMASK

	exec $NICE $EFAX -v "" -v "$VERBLOG" -d/dev/$DEV '-i#CLS=0' \
	$CLASSINIT $FCINIT $RXINIT \
	$RXCAP -l "$FROM" $RESET \
	$DATAINIT -g "$DCMD" \
	-r "$ANSFNAME"

	echo ERROR: $FAX reanswer exec failed >>$CONSOLE ; sleep 30

	break
	;;

# fax queue : list received fax files

	q*)

 	cd $FAXDIR
 	case $? in 0) ;; *) echo "cannot cd to $FAXDIR" ; break ;; esac
 
 	for f in [0-9]*.[0-9][0-9][0-9] [0-9]*.v
	do
		if [ -r $f ]
		then
 			echo
 			echo Fax files in `pwd` :
 			echo
 			$LS -l [0-9]*.[0-9][0-9][0-9]  [0-9]*.v
 			echo
 		       	break
 		fi
	done

	break 
	;;	

# faxlpr : get phone number and user from current cf* file and run fax send 

	faxlpr)

	cd $FAXDIR		# the lpr spool directory for printer 'fax'
	case $? in 0) ;; *) echo "$0: cannot cd to $FAXDIR" ; break ;; esac

	test -r lock
	case $? in 0) ;; *) echo "$0: can't read lock file" ; break ;; esac
	
	cfile=`tail -1 lock`

	test -r $cfile
	case $? in 0) ;; *) echo "$0: can't read control file" ; break ;; esac

	cfile=`cat $cfile`

	num=` echo "$cfile" | sed -e /^[^J]/d -e s/.//`
	host=`echo "$cfile" | sed -e /^[^H]/d -e s/.//`
	user=`echo "$cfile" | sed -e /^[^P]/d -e s/.//`

	test "$num"
	case $? in 0) ;; *) echo "$0: can't read phone number" ; break ;; esac

	cat - >> fax$$			# save in a file

	l=`$FAX send "$num" fax$$`

	case $? in
	0) echo "$l" | mail -s "fax to $num succeeded" $user@$host ;;
	*) echo "$l" | mail -s "fax to $num failed   " $user@$host ;;
	esac

	$RM fax$$ fax$$.???

	break 
	;;	

# fax start/stop/status : manage fax receive daemon

	start|stop|st*)		# common section

	cd $FAXDIR ; 
	case $? in 0) ;; *) echo "cannot cd to $FAXDIR" ; break ;; esac

	n= ; for f in ${DEVN}.[0-9]* ; do logfile="$f" ; n=x$n ; done

	case $n in 
	xx*) echo Warning: multiple logs for $DEV : ; ls ${DEVN}.[0-9]* ;;
	esac

	case $logfile in 
	*\*) echo no fax answer process for device $DEV ; break ;;
	esac

	efaxpid=`echo $logfile | sed -e "s/${DEVN}\.//g"`

	case $cmd in

# fax start - remove stop file so fax answer will continue

	start)

	if [ ! -w . ] ; then echo "can't write  `pwd`" ; break ; fi
        $RM ${DEVN}.stop
	break 
	;;

# fax stop - make a stop file and kill current fax answer daemon

	stop)

	if [ ! -w . ] ; then echo "can't write `pwd`" ; break ; fi
	touch ${DEVN}.stop
	echo stopping fax daemon for ${DEV}, pid=$efaxpid
	kill -HUP $efaxpid
	break 
	;;


# fax status - display pid and log file for current daemon

	st*)

	if [ -f ${DEVN}.stop ] ; then stat="(set to stop)" ; fi

      	if ps -u $efaxpid 2>/dev/null ; then :
      	else
		echo "NOT ACTIVE (last daemon was $efaxpid)"
      	fi

	echo
	echo from: $FAXDIR/$logfile
	echo

	egrep "Warning|Error|starts|activity|opened|received -|done" $logfile

	case $# in 
	0) ;; *) echo "---------------" ; sleep $1 ; exec $FAX status $1 ;;
	esac

	break
	;;

	esac	# common section
	;;

# fax makefont : rasterize a PS font into a 256-character-wide bitmap

	makefont)

	if [ $# -lt 5 ]
	then
        	echo Usage: fax makefont fontname fontsize \
			cellwidth cellheight filename
		echo "(cellwidth and cellheight in pixels, fontsize in points)"
		echo "Example: fax makefont Courier-Bold 8 16 24 efaxfont"
		echo "will make an 8pt font (there are about 3 pixels per pt)"
        	exit 1
	fi

	FNTFMT=pbmraw	# format for font files
	# FNTFMT=tiffg3	# smaller, available with Ghostscript 3.x or later

	pelwidth=`expr 256 \* $3`
	gs -q -sDEVICE=$FNTFMT -r204x196 -g${pelwidth}x$4 \
		-sOutputFile=$5 - <<EOF
        /$1 findfont $2 scalefont setfont 
        /buf 1 string def
        /dx $3 204 div 72 mul def	% x offset per character
        0 1 255 { 
           dup dx mul 0.7 add 3 moveto
           buf exch 0 exch put 
           buf show
        } for
        showpage
EOF
	break
	;;

# fax make : convert a text or Postscript file to fax format

	m*)

	case $# in 0) echo "No files specified" ; ERR=2 ; break ;; esac

	if [ ! -r $1 ] ; then echo "Can't read $1" ; ERR=2 ; break ; fi


	read x <$1
	case $x in
	%!*|?%!*)
		echo "$1 is postscript..."
		# GS can't deal with long paths so we 'cd' 
		DIRNAME=`dirname $1` ; BASENAME=`basename $1`
		( cd $DIRNAME ; \
		$GS -q -sDEVICE=tiffg3 -r$RES -dNOPAUSE -dSAFER \
		-sOutputFile=$BASENAME.%03d \
		-sPAPERSIZE=$PAGE \
		$BASENAME </dev/null >/dev/null )
		;;
	II*|MM*|P4*)
		echo "$1 is an image file..."
		$EFIX -ve -otiffg3 -p$PAGEDIM -r$RES -n $1.%03d $1
		;;
	*)	echo "$1 is text..."
		$EFIX -ve -otiffg3 -p$PAGEDIM -r$RES -n $1.%03d $TEXTFONT $1
		;;
	esac

	break
	;;

# fax send : fax files to given number, converting first if necessary

	s*)
	
	case $# in
	0) echo "missing phone number to call" ; ERR=2 ; break ;;
	esac

	# look up names

	case $1 in 
		[A-Za-z]*) 
		for f in $DIRFILES ; do
			if [ -r $f ] ; then TELNO=`$LOOKUP` ; fi
			case "$TELNO" in '') continue ;; *) break ;; esac
		done
		case "$TELNO" in
			'') echo "Name lookup for $1 failed" ; ERR=2 ; break ;;
			*) echo "Lookup: $1 = $TELNO" ;;
		esac
		;;
		*) TELNO="$1" ;;
	esac

	shift 

	case "$TO" in '') TO="$TELNO" ;; *) ;; esac

	TELNO=`echo $TELNO|sed "s/[ 	()][ 	()]*//g"`

	# handle manual dialing and number->dial string conversions

	case "$TELNO" in
	-m*)	MANINIT="-jX3" ; TELNO="" ;;
	+*)	TELNO=`echo $TELNO | $TELCVT` ;;
	esac
	
	case $TELNO in 
	'') 	;; 
	*)	TELNO="${DIALPREFIX}${TELNO}${DIALSUFFIX}" ;; 
	esac

	# use `fax make' to convert files if they need to be updated

	FILES=""
	for f in $* ; do
		case $f in -) FILES="$FILES -" ; continue ;; esac
		if [ ! -r $f ] ; then
	      		echo "can't read file $f" ; ERR=2 ; break 2 
		fi
		case $f in
		*.[0-9][0-9][0-9]) FILES="$FILES $f" ;;	# skip image files
	   	*)	if echo ${f}.001: $f \; x | make -r -q -f - ; then
				echo ${f}.nnn is up-to-date
			else
	 			$RM ${f}.[0-9][0-9][0-9]
	 			$FAX make $OPT $f
			fi
			if [ -r $f.001 ] ; then 
                		FILES="$FILES $f.[0-9][0-9][0-9]"
	      		else		# something's wrong, catch it later
	        		FILES="$FILES $f.001"
	      		fi
			;;
		esac
        done

	# check that all files are OK

	for f in $FILES ; do
		case $f in -) continue ;; esac
		if [ ! -r $f ] ; then
	      		echo "can't read file $f" ; ERR=2 ; break 2 
   	   	fi
	done

	# send it

	for s in 0 $FAILRETRIES ; do

	case $s in
	0) ;; *) echo "Will try again in $s seconds" ; sleep $s ;;
	esac

#	logfile=`$TSTAMP`.log
        logfile="$TELNO".log

	for t in 0 $BUSYRETRIES ; do

		case $t in 
		0) ;; *) echo "Will try again in $t seconds" ; sleep $t ;;
		esac

		DATE=`eval "$DATECMD"`
		eval HDR=\"$HDR\"

		$NICE $EFAX -v "$VERB" -v "$VERBLOG" \
		-d/dev/$DEV $LOCK $INIT $SPKR \
		$CLASSINIT $FCINIT $TXINIT \
		$TXCAP -l "$FROM" $RESET $HDRFONT -h "$HDR" \
		$MANINIT -t "$TELNO" $FILES >$logfile

		ERR=$?

		case $ERR in
		0)	$RM $logfile ; break 2 ;;
		1)	echo Busy... ;;
		*)	echo "There were errors (see ${logfile})." ; break ;;
		esac

	done

	SENT=` sed -n -e '/sent ->/s/^.*-> \([^ ]*\).*/\1/p' $logfile`
	FILES=`sed -n -e '/failed ->/s/^.*-> \([^ ]*\).*/\1/p' $logfile`
	case $SENT  in '') break ;; esac
	case $FILES in '') break ;; esac
	echo Failed...

	done

	break 
	;;

# fax hangup : hang up the phone

	hangup*)
	$NICE exec $EFAX -v $VERB -d/dev/$DEV $LOCK -iZ -T 
	break
	;;

# fax fone : open modem device and exec fone script

	fone)
	
 	cd $FAXDIR
 	case $? in 0) ;; *) echo "cannot cd to $FAXDIR" ; break ;; esac
 
	$NICE exec $EFAX -v $VERB -d/dev/$DEV $LOCK $INIT \
		-j#CLS=8 -a#VLS=1 -e "$VCMD $*"

	break
	;;

# fax (rm|print|view) commands possibly on files in spool directory

	rm|p*|v*)	# common code

	# switch to spool directory if first file is found there

	for f in $FAXDIR/$1 ; do 
		if test -r $f ; then cd $FAXDIR ; break ; fi
	done
	
	for f in $* ; do
		case $cmd in 

		rm)	# fax rm : delete files
		if $RM $f ; then echo deleted $f ; fi
		;;

	        p*) 	# fax print : print files
  		echo "$f ... "
		eval "$PRINT | $PRCMD"
		;;
		
		v*)	# fax view : display images
  		echo "$f ... "
		eval "$VIEW | $VIEWCMD"
		;;

		esac
	done

	break
	;;

# fax [receive] : answer phone now and receive fax files

	r*)
	
	case $1 in '') file=`$TSTAMP` ;; *) file=$1 ;; esac
	logfile=${file}.log

	$NICE $EFAX -v "$VERB" -v "$VERBLOG" -d/dev/$DEV $LOCK $INIT $SPKR \
	$CLASSINIT $FCINIT $RXINIT \
	$RXCAP -l "$FROM" $RESET \
	-r $file >$logfile

	ERR=$?

	case $ERR in
	0)	$RM $logfile ; break ;;
	1)	echo Busy... ;;
	*)	echo "There were errors (see ${logfile})." ; break ;;
	esac

	break
	;;

# fax new : create a cover page for a fax (needs work)

	new)

	fname=${1-new.fax}
	DATE=`date "+%B %d %Y"`
	cat >$fname 2>/dev/null << EOF

	________________________________________________

			 FAX COVER PAGE
	________________________________________________

	 To:	x
	fax:

	________________________________________________

	From:	$NAME
	 fax:	$FROM

	Date:	$DATE

	Pages:	1 (including this page)

	________________________________________________

EOF
	${VISUAL-${EDITOR-vi}} $fname

	break
	;;

# fax help : show command arguments

	-\?|\?|-h*|h*)

cat 1>&2 <<EOF
 Usage: 

   fax [ r[eceive] [-v] [filename-prefix] ]
   fax m[ake] [-l] { postscript-file-name | text-file-name }
   fax s[end] [-l] [-v] { -m | telephone-number } filename...
   fax { p[rint] | v[iew] | rm } [-l] filename...

   fax [ stop | start | st[atus] | q[ueue] ]
   fax answer

 use -l to create low resolution (98 lpi) faxes
 use -m if the number has been dialed manually 	
 use -v for verbose output 

 if given no arguments, answers the phone and receives a fax.

 use VAR=value to set variables (e.g. "fax DEV=cua2 receive")

 session logs are written to a file with the date/time as the
 file name and extension of .log (except for automatic reception).

 fax device is /dev/$DEV, incoming spool directory is $FAXDIR

EOF

	ERR=1
	break
	;;

	*)
	echo "Error. Invalid command ($cmd)" ; ERR=2 ; break
	;;

esac	
done

exit $ERR
