rsalz@uunet.uu.net (Rich Salz) (03/14/91)
Submitted-by: klaus u schallhorn <cnix!klaus> Posting-number: Volume 24, Issue 40 Archive-name: faxpax/part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: FaxConfig faxhost/faxfonts/diykit.c faxhost/sendfax.c # Wrapped by rsalz@litchi.bbn.com on Wed Mar 13 14:08:01 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive 2 (of 5)."' if test -f 'FaxConfig' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'FaxConfig'\" else echo shar: Extracting \"'FaxConfig'\" \(25531 characters\) sed "s/^X//" >'FaxConfig' <<'END_OF_FILE' X#!/bin/sh X# X# $Header: FaxConfig, 2.2.91, ks X# basically a [very much] stripped down and ripped off version of rn/Configure X# where it says: X# Yes, you may rip this off to use in other distribution packages. X# so I did X Xn='' Xc='' Xcontains='' X Xmodemtypes='1' X Xcharset='i' Xdevice="/dev/not_that_one" Xdevlock="LCK..nosuchdevice" Xdialstr="" Xdialtype='T' Xnet='y' Xnetwide_fax="NETWIDE_FAX" Xfaxhost="faxhost" Xfaxadmin=`whoami` Xfaxadmin="$faxadmin@"`hostname` Xfaxfmode='0644' Xfaxlib='/usr/local/lib/faxlib' Xfaxspool='/usr/local/spool/fax' Xfmtype="sierra" Xlocalbin='/usr/local/bin' Xloglevel='9' Xmanshelf='/usr/share/man' Xmaxresend='3' Xmaxage='1' Xmaxtry='5' Xtopspeed='7' Xuucplocks='/var/spool/locks' X X Xecho "Beginning of configuration questions for faxpak." Xecho " " X X: some greps do not return status, grrr. Xecho "grimblepritz" >grimble Xif grep blurfldyick grimble >/dev/null 2>&1 ; then X contains=contains Xelse X if grep grimblepritz grimble >/dev/null 2>&1 ; then X contains=grep X else X contains=contains X fi Xfi X X: sanity checks XPATH='.:/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc' Xexport PATH || (echo "OOPS, this isn't sh. Desperation time. I will feed myself to sh."; sh $0; kill $$) X Xif test ! -t 0; then X echo "Type 'sh FaxConfig', not 'sh <FaxConfig'" X exit 1 Xfi X X: first determine how to suppress newline on echo command Xecho "Checking echo to see how to suppress newlines..." X(echo "hi there\c" ; echo " ") >.echotmp Xif $contains c .echotmp >/dev/null 2>&1 ; then X echo "...using -n." X n='-n' X c='' Xelse X echo "...using \\\c." X n='' X c='\c' Xfi Xecho $n "Type carriage return to continue. Your cursor should be here-->$c" Xread ans Xrm .echotmp X X: now set up to do reads with possible shell escape X: if this does not work on your machine, 1,$s/. myread/read ans/ Xcat <<EOSC >myread Xans='!' Xwhile expr "X\$ans" : "X!" >/dev/null; do X read ans X case "\$ans" in X !) X sh X echo " " X echo $n "Your answer: $c" X ;; X !*) X set \`expr "X\$ans" : "X!\(.*\)\$"\` X sh -c "\$*" X echo " " X echo $n "Your answer: $c" X ;; X esac Xdone XEOSC X X Xcat <<EOT X X# general info X############################################################################## XThis installation shell script asks you some questions regarding the Xsetup of faxpak. Currently there is no support for hardware other than XSun Microsystems'. To port this to other machines run this script Xanyway, but then have a close look at wiring.c. Wiring.c can be used Xas a standalone test program with TESTING defined, and with TEST_DEVICE Xdefined to a port you can use for testing [you can reconfig any time], Xpreferably without interfering logins. X XThis script builds a header file faxconfig.h, a soft configuration file Xfax,config, fax.1 man pages and, if you're lucky, two faxpak fonts. X XDefault answers are shown in [brackets]. Hitting carriage return accepts Xthe defaults. Once you have faxconfig.h and fax.config you can change Xeach file by editing it without re-running this script. X XEOT X Xecho $n "[Type carriage return to continue] $c" X. myread Xecho " " X X Xcat <<EOT X X############################################################################## Xfaxpak can run on networked and standalone machines. X XIf faxpak is networked, it is assumed that one HOST has the faxmodem[s], Xwith all other machines acting as CLIENTS, spooling outgoing fax jobs to Xthe faxhost. X XThe faxhosts' duty is to convert incoming text files into group 3 fax files, Xand to do the actual transmission, to log what's going on, to report by Xmail [if requested] and to do house keeping chores. This is done by entries Xin root's crontab which calls sendfax frequently and faxcleanup once a day. X XEOT X Xdflt=$net Xecho $n "Do you expect to run faxpak on networked machines? [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac X X Xif [ $ans = y ] Xthen X X cat <<EOT X X# network info, don't really need much X###################################################################### X"client" machines find the faxhost by calling gethostbyname(FAXHOST), Xwith FAXHOST #defined in faxconfig.h on our sita as "faxhost", Xand with "faxhost" aliased in /etc/hosts to mbox. mbox is a 3/60 that Xacts as our spooling machine [printing, faxing, mail, news archive etc.]. X XEOT X X dflt=$faxhost X echo "Please enter the \"synonym\" your FAXHOST will be known by -" X echo $n "[I guess you could enter the name of a known machine]: [$dflt] $c" X . myread X echo X case $ans in X '') ans=$dflt;; X esac X faxhost=$ans Xelse X net='n' X netwide_fax="nonet" Xfi X X Xcat <<EOT X X# we need someone to blame when things go wrong X############################################################################## XThe bad news is that things DO go wrong. Therefore we may need Xsomeone to interfere by hand, or to lend a hand if a user needs help, Xor to give the default answer ["You can't to that"]. X XEOT Xdflt=$faxadmin Xecho $n "Name a patient person suitable for dealing with fax problems: [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xfaxadmin=$ans X X X# what arg do we give chmod() X############################################################################## Xdflt=$faxfmode Xecho $n "Please enter the file access perms to be enforced by faxpak: [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xfaxfmode=$ans X Xcat <<EOT X X X# where to put faxlib and the spool dir X############################################################################## XTo keep things somewhat organised we need to define a /someplace/faxlib, Xand a /somewhere/spooldir for faxpak. I prefer to keep them separate from Xdistribution libs and spool dirs. I'd also like to know where you keep you Xman pages. X XEOT Xdflt=$faxlib Xecho $n "Please enter the path to faxlib: [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xfaxlib=$ans X X Xdflt=$faxspool Xecho $n "And path to faxspool: [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xfaxspool=$ans X X Xdflt=$manshelf Xecho $n "And your Manual Shelf: [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xmanshelf=$ans X Xcat <<EOT X X# find competing uucp locks X############################################################################## XModem logins, uucp transmissions and faxes all the same time and on Xthe same modem tend become somewhat garbled. Tell me where uucp keeps Xits lock files, so that sendfax dies away instantly if uucp is active X[it knows about logins on a port]. X XEOT Xdflt=$uucplocks Xecho $n "Where does uucp create its lock files: [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xuucplocks=$ans X X Xcat <<EOT X X# local bin for fax X############################################################################## XAssuming you don't put local executables into /usr/{bin,ucb}, we need Xsort of a /local/bin to put the user interface [called fax] into. X XEOT Xdflt=$localbin Xecho $n "Where do you keep local executables: [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xlocalbin=$ans X X Xcat <<EOT X X# max no of resends within one transmission X############################################################################## XThe last hard wired bit of info is the number of resends. If a page is Xgarbled during transmission, the two hardware gizzmos, that is your Xfaxmodem on this side and the fax machine on the other end, can agree Xto resend that page. I don't know if fax machines have a built in limit Xfor the number of resent pages, I do, however, feel safer if I know Xsendfax doesn't spend all night resending a page. Having seen the different Xlevels of compliance to the CCITT specs, especially european fax machines', XI would doubt, if such a limit is enforced. X XEOT Xdflt=$maxresend Xecho $n "How often do you permit the resending of a page within one call [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xmaxresend=$ans X X X# have header info, get details for fax.config X############################################################################## X Xif [ $modemtypes = 2 ] Xthen X mtypestring="faxmodem type, currently class2 and sierra type modems are supported" Xelse X mtypestring="faxmodem type, currently only sierra type modems are supported" Xfi X Xcat <<EOT X X# soft configuration, saved in $faxlib/fax.config" X############################################################################## XMost of the configuration of faxpak can be changed after compiling faxpak. XSoftwired details are stashed into $faxlib/fax.config, allowing for easy Xalteration once you have faxpak working. The fax.config file stores: X X1: the ports to which you have faxmodems connected *) X2: literal name of lockfile for each port, in case uucp uses these ports X as well as faxpak *) X3: $mtypestring X4: Tone or Pulse dialling X5: Highest speed your faxmodems are capable of [RTFFaxmodemM] X6: an optinal string to re-enable dialins on the port after sendfax is done, X see /etc/uucp/Dialers, or the modem docs, for examples X X7: wildcarded dialcodes and times, faxes to these area codes are ok *) X X8: max no of days a fax is allowed to sit in $faxspool X9: max no of attempts to send a fax X Xlog level, 9 logs everything [huge!], 0 only some relevant info X XFaxConfig only writes a preliminary file including some comments. Feel Xfree to edit it to your liking at any time. X X*) these are best done with an editor, in fact, I don't even ask for X dialcode:time pairs. see the file fax.config when done with this script. X [you could also call this load sharing between you and me]. X XEOT X Xdflt=$device Xecho $n "Please enter the first port to be used [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xdevice=$ans X Xdflt=$devlock Xecho "Please enter lockname to block uucp while we're" Xecho $n "sending out faxes [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xdevlock=$ans X Xif [ $modemtypes = 2 ] Xthen X dflt=$fmtype X echo $n "Please enter modem type [$dflt] $c" X . myread X echo X case $ans in X '') ans=$dflt;; X esac X fmtype=$ans Xfi X Xdflt=$dialtype Xecho $n "Please enter 'P' if you want pulse dialling [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xdialtype=$ans X Xdflt=$topspeed Xecho "Please enter code for highest baud rate your modem can " Xecho $n "fax at - see modem manual [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xtopspeed=$ans X Xdflt=$dialstring Xecho "If you feel brave enough [else leave blank and do later]" Xecho $n "String to reenable dialins on ports used by faxmodems [$dflt] $c" X. myread Xecho X Xdflt=$maxage Xecho $n "How many days is a fax allowed to sit in the queue [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xmaxage=$ans X Xdflt=$maxage Xecho $n "How many attempts do you allow to connect to one phone no [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xmaxtry=$ans X Xdflt=$loglevel Xecho $n "What log level do you want sendfax [wiring for testing] to log at [$dflt] $c" X. myread Xecho Xcase $ans in X'') ans=$dflt;; Xesac Xloglevel=$ans X X X Xcat <<EOT X X# charset info X############################################################################## XAlthough I planned to support quite a few different character sets [with Xthe help of several netters] faxpak currently supports the following few. XFor those poor souls whose expression is limited to 7 bits, the decision Xmust be based on rand(). X XPlease enter the charset you want faxpak to use: X X i iso 8859.1 X p pc de facto [code page 850] standard *) X 8 pc code page 861 X X*) Some people felt strongly the ibm pc code page 850 is NOT a de facto X standard. IMHO it is insofar as the uk, germany, switzerland and some X other mid european countries are concerned, where quite a chunk of X "the action" takes place. If you still disagree, don't use faxpak. X XEOT X Xdflt=$charset Xecho $n "What charset do you want to use [$dflt] $c" X. myread Xecho Xecho copying font definition for diy font kit Xcase $ans in X'p') cp faxhost/faxfonts/diy_ibmpc.def faxhost/faxfonts/diykit.def;; X'8') cp faxhost/faxfonts/diy_codep861.def faxhost/faxfonts/diykit.def;; X*) cp faxhost/faxfonts/diy_iso.def faxhost/faxfonts/diykit.def;; Xesac X Xrm -f myread grimble X X X# have fax.config, write faxconfig.h and fax.config X################################################### X Xecho "writing faxconfig.h" X Xcat >faxconfig.h <<EOT X X/* X fax configuration header [faxconfig.h], X shared by faxclient/fax.c, and faxhost/*.c X X Copyright (C) 1991, klaus schallhorn, klaus@cnix.uucp X X Permission to use, copy, modify, and distribute this software X and its documentation for any purpose and without fee is hereby X granted, provided that the above copyright notice appear in X all copies and that both that copyright notice and this permission X notice appear in supporting documentation. X X This software is provided "as is" without express or implied warranty. X*/ X X#define $netwide_fax X X X /* some common bits 'n pieces */ X#ifndef TRUE X#define TRUE 1 X#define FALSE 0 X#define ERROR (-1) X#endif X X#ifndef min X#define min(a,b) ((a<b)?a:b) X#define max(a,b) ((a>b)?a:b) X#endif X X X /* network stuff */ X#ifdef NETWIDE_FAX X#define FAXHOST "$faxhost" /* get host by name */ X#endif X X X /* application specific stuff */ X#define FAXADMIN "$faxadmin" /* mail errors if !user */ X#define FAXFMODE $faxfmode /* for chmod */ X#define FAXSERVER "spool.fax" /* name of spool pgm */ X#define FAXLIB "$faxlib" /* needed on faxhost only */ X#define FAXSPOOL "$faxspool" /* needed on faxhost only */ X X#define UUCPLOCKS "$uucplocks" /* again host only */ X#define LOCALBIN "$localbin" /* client && host, for fax.c */ X X#define MAX_RESEND $maxresend /* don't resend a page forever */ X#define FAXLFONT "textfaxl.font" /* lores bitmap font from diykit */ X#define FAXHFONT "textfaxh.font" /* hires bitmap font from diykit */ X#define PSFONT "Courier-Bold12" /* ghostscript font */ X X#define MAX_FAX_LINES 2400 /* is a bit generous, so what */ X X#define COARSE 1 /* 204.15 by 97.79 dpi */ X#define FINE 2 /* 204.15 by 195.58 dpi */ X#define HP 3 X X#define ASCII 0 /* use hp laser jet compat font to create pbm */ X#define PBM 1 /* use as is, sort of */ X /* these aren't done yet, see wiring.c, why */ X#define DVI 2 /* dvi2ps, NOT YET DONE */ X#define GHOSTSCRIPT 3 /* ideas [not yet] stolen from mit ai labs */ X#define HPCL 4 /* hp laser jet compat output */ X X X /* fax modem specific bits */ X#define BETA_FIRMWARE /* applies to wiring.c */ X#define SIERRA /* type of fax modem */ X X X#ifdef NEED_FAXTYPES /* needed in fax.c and spool.fax.c */ Xstruct ftypes X{ X char *typename; X int typeid; X} faxtypes[] = X{ X "ascii", ASCII, X "pbm", PBM, X "dvi", DVI, X "postscript", GHOSTSCRIPT, X "hpcl" HPCL X}; X#define MAX_FTYPE sizeof(faxtypes)/sizeof(struct ftypes) X#endif /* need fax types */ X X Xstruct FAX X{ X long spooled; X char user[80]; X#ifdef JOBID X char jobid[80]; X#endif X char dname[256]; X char xname[256]; X char **phone; X int tries, X hires, X uid, X now, X mail, X pages, X type, X phone_nos; X long tpos, X ppos; X}; XEOT X Xecho "writing fax.config" X Xcat >fax.config <<EOT X# fax.config X# Copyright (C) 1991 klaus schallhorn, klaus@cnix.uucp X# X# Permission to use, copy, modify, and distribute this software X# and its documentation for any purpose and without fee is hereby X# granted, provided that the above copyright notice appear in X# all copies and that both that copyright notice and this permission X# notice appear in supporting documentation. X# X# This software is provided "as is" without express or implied warranty. X# X# X# fax devices X# =========== X# 2nd column contains the actual device for sendfax X# ie /dev/cua1 X# X# 3rd col states lock name to be used so that uucp does not even try X# to interfere while we're faxing. Stating the lock name verbatim is X# essential since there are differences between HDB uucp and older/other X# versions. X# NOTE: if you don't share faxmodems with uucp, locknames don't really X# matter as long as each port has a distinctive lockname. fred1, fred2 X# ... fredn would be acceptable. X# X# 4th col specifies the modem type connected to that port so sendfax knows X# how to talk to the hardware. X# X# 5th col is either T [as in tone dialling] or P [pulse]. X# X# 6th col is highest speed you want to connect at, see your modem manual. X# X# 7th col is a string sent to the fax modem AFTER we've used it IF you X# want to enable incoming calls/getty, for a typical string see X# /etc/uucp/Diallers, string has to be "in quotes", absence of a string X# implies nothing to send. X# X# this is what fax.config looks here X# 1st 2nd 3rd 4th 5th 6th 7th X#device /dev/cua1 LCK..cua1 sierra T 7 "ATE1M0V1X1Q0S2=127S0=4S12=255" X#device /dev/cua2 LCK..cua2 sierra T 7 "ATE1M0V1X1Q0S2=127S0=4S12=255" Xdevice $device $devlock $fmtype $dialtype $topspeed $dialstr X# X# X# phone bill saver X# ================ X# X# I do not want faxes at peak rates, except local ones. X# X# long distance call phone nos start with a zero PLUS any combination of X# digits 1 to 9 [1-9][1-9]* X# NOTE: no zeros in 2nd or 3rd digit, except if 2nd digit > 1 X# X# international ones start with 010 cty code PLUS any combination of 1 to 9 X# X# This feature can be raped to make sure faxes to specific fax numbers X# are only sent at an acceptable [for the recipient] time, as shown in the X# first "hour entry". Hard coded phone nos should come before wild card X# entries. X# X# This sample states that long distance is ok from 6 pm to 6 am, X# international ones from 8 pm to 6 am X# X#hours 0104977777777 9 - 12 # this guy can only be sent to in the morning X#hours 01049123456 8 - 10 14 16 - 19 X#hours 0[1-9][1-9]* 18 - 6 # as in 078 123 6789 X#hours 0[2-9]* 18 - 6 # as in 030 455 6748 X#hours 010[1-9]* 20 - 6 # as in 01049 30 345 6789 X# X# X# max age of files in spool dir [days], fax is supposed to be fast! X# ============================= X# Xmaxage $maxage X# X# X# max number of attempts to connect X# ================================= X# Xmaxtry $maxtry X# X# log level X# ========= X# X# 9 = everything X# 0 = errors, transmission times X# other useful levels are 3 and 5 X# Xloglevel $loglevel X# X# X# end of fax.config XEOT X X# now save fax.1 man pages X########################## X Xecho "writing faxclient/fax.1 man pages" X Xcat >faxclient/fax.1 <<EOT X.TH fax 1 "Feb 4th, 1991" X.SH NAME Xfax \- send a Group 3 fax via faxmodem. X.SH SYNOPSIS Xfax phone_no [-a -f -h -l -m -n -r -s] file X.SH DESCRIPTION XFax accepts ascii input and sends it as a group 3 fax Xusing a sierra type faxmodem. The first parameter is either Xa phone number, an alias [see aliases] or a distribution list [see lists] Xfile name. X.sp XIf the first parameter contains digits only, it is Xassumed to be a phone number. X.sp XIf your site does enforce permissions, you may have to ask your Xadministrator [$faxadmin] for permission to fax. X.SH PARAMETERS X.TP X.B -a'for the attention of...' XTo specify a recipient within an organization for internal Xrouting. The string must be quoted so it's passed as one Xargument to fax. It is then prepended to the outgoing message. X.TP X.B -f/absolute/font/path/fontfile XUse an alternative font. In addition to the default typewriter fonts Xin low and high resolution fax knows about XHP Laserjet compatible fonts [up to 30 points in height]. These are Xscaled to the resolution of the outgoing fax. Used with low resolution Xthe output is not pretty. X.TP X.B -h XUse high resolution mode [204 by 195 dots per inch]. This almost doubles Xthe transmission time. X.TP X.B -l XUse low resolution mode [204 by 97 dots per inch]. X.TP X.B -m XReport by mail as soon as the fax has been sent. Fatal errors or failure Xto deliver is reported back irrespectible of the mail flag setting. X.TP X.B -n XSend the fax "now" rather than at cheap rate, where "now" refers Xto the next time the fax daemon runs. To bypass the time restrictions [if Xany] you may need to have special permission. X.TP X.B -r'return fax number string' XThis string is prepended to the outgoing fax to specify a return Xfax number. Currently fax does not support incoming faxes. X.TP X.B -s XSave outgoing faxes in HOME/Fax.Sent/phone.date. Fax saves outgoing faxes in Xfiles whose name is a concatenation of recipient and date. If the recipient Xis not an alias and not a distribution list, the phone number is Xused for the first part of the file name. X.PP XFile is an ascii file containing a formatted message. X.SH DEFAULTS XYou can override built in defaults by creating a file ".faxrc" in Xyour home directory. This file is consulted before fax reads Xcommand line parameters. X.sp XPermitted default values in .faxrc are those that apply to Xall outgoing faxes sent by one user. Command line option override Xthese dafaults, however. X.TP X.B font XThe name of a font to be used by fax. The font has to be available Xon the machine running the fax daemon. The fontfile Xmust be accessible to the fax daemon. X.TP X.B resolution XCan be high or low [see above]. Default: low. X.TP X.B mail XSet to yes for notification by mail. Default: no. X.TP X.B now XSet to yes for sending next time the fax queue is checked Xfor outgoing faxes. Default: no. X.TP X.B retfax XA string to be prepended all your outgoing faxes. No default string. X.TP X.B save XIf set, saves files in HOME/Fax.Sent/phone.date. Default: no. X.SH ALIASES XIf the first parameter to fax contains alphabetic characters, fax first Xchecks your HOME directory for a file fax.aliases. This file contains Xa list of names, phone numbers, optionally ftao [for the attention of] Xstrings to be prepended to each outgoing fax. Anything appearing after a # Xsign is treated as a comment. X.sp XA sample fax.aliases file might look: X.sp X.nf Xfred 12345678 :For the attn of Fred Bloggs # comment Xbill 98765 Xsue 765432389 :The Lady in Pink # another comment X.fi X.SH LISTS XIf an alias is not found in fax.aliases, fax tries to open a distribution Xlist with the same name. Distribution lists are similar to alias files. XA sample distribution list might look: X.sp X.nf X12345678 :For the attn of Fred Bloggs # comment X98765 X765432389 :The Lady in Pink # another comment X.fi X.SH INTERACTIVE USE XIf fax is not given a file name on the command line, it reads Xit's standard input until a line starting with a '.' is encountered, Xor until EOF. X.sp XEntering of a fax can be aborted by hitting ^C. Entering ~v at the beginning of Xa line calls the default editor, if specified by the environment variable XEDITOR, or /usr/ucb/vi. X.sp XStarting a line with ~p prints the message entered to far. X.SH AUTHOR XKlaus Schallhorn X.SH COPYRIGHT XCopyright (C) 1991 Klaus Schallhorn, klaus@cnix.uucp X.sp XPermission to use, copy, modify, and distribute this software and its Xdocumentation for any purpose and without fee is hereby granted, provided Xthat the above copyright notice appear in all copies and that both that Xcopyright notice and this permission notice appear in supporting Xdocumentation. This software is provided "as is" without express or Ximplied warranty. XEOT X Xecho "writing Makefiles" X Xcat >Makefile <<EOT X# Makefile for faxpak X# X# Copyright (C) 1991 klaus schallhorn, klaus@cnix.uucp X# XCC = cc XCFLAGS = -O2 XLDFLAGS = -s X XFAXLIB = $faxlib XFAXFMODE = $faxfmode XLOCALBIN = $localbin XMANSHELF = $manshelf X XSHELL = /bin/sh X XSUBS = faxclient faxhost faxhost/faxfonts X X Xall: X for i in \$(SUBS) ; do \ X ( cd \$\$i ; make \$(MFLAGS) 'CC=\$(CC)' 'CFLAGS=\$(CFLAGS)' 'LDFLAGS=\$(LDFLAGS)' all ); \ X done X Xinstall: X for i in \$(SUBS) ; do \ X ( cd \$\$i ; make \$(MFLAGS) 'LOCALBIN=\$(LOCALBIN)' 'MANSHELF=\$(MANSHELF)' 'FAXLIB=\$(FAXLIB)' 'FAXFMODE=\$(FAXFMODE)' install ); \ X done X Xclean: X -rm -f Part?? *.hdr fax.config X for i in \$(SUBS) ; do \ X ( cd \$\$i ; make \$(MFLAGS) clean ); \ X done X XEOT X Xcat >faxclient/Makefile <<EOT X# Makefile for faxclient X Xall: fax X Xfax: fax.o X cc -o fax \$(LDFLAGS) fax.o X Xfax.o: fax.c X cc \$(CFLAGS) -c fax.c X Xinstall: bininstall maninstall X Xbininstall: fax X cp fax \$(LOCALBIN) X Xmaninstall: fax.1 X cp fax.1 \$(MANSHELF)/man1 X chmod 644 \$(MANSHELF)/man1/fax.1 Xclean: X -rm -f *.o *.a core fax X XEOT X Xcat >faxhost/Makefile <<EOT X# Makefile for faxhost X XFAXCLEANUP = faxcleanup.o faxlog.o XSENDFAX = sendfax.o wiring.o faxlog.o XSPOOLFAX = spool.fax.o faxlog.o XTEXTTOPBM = texttopbm.o fntwrite.o XFAXHDR = ../faxconfig.h X XPGMS = faxcleanup sendfax spool.fax texttopbm XTEXTFILES = fax.config textfaxl.font textfaxh.font X Xall: \$(PGMS) X Xfaxcleanup: \$(FAXHDR) \$(FAXCLEANUP) X cc -o faxcleanup \$(LDFLAGS) \$(FAXCLEANUP) X Xsendfax: \$(FAXHDR) sierracmd.h \$(SENDFAX) X cc -o sendfax \$(LDFLAGS) \$(SENDFAX) X Xspool.fax: \$(FAXHDR) \$(SPOOLFAX) X cc -o spool.fax \$(LDFLAGS) \$(SPOOLFAX) X Xtexttopbm: \$(FAXHDR) \$(TEXTTOPBM) X cc -o texttopbm \$(LDFLAGS) \$(TEXTTOPBM) X Xinstall: X cp \$(PGMS) \$(FAXLIB) X cp ../fax.config \$(FAXLIB) X for i in \$(TEXTFILES) ; do \ X ( chmod \$(FAXFMODE) \$(FAXLIB)/\$\$i ); \ X done X for i in \$(PGMS) ; do \ X ( chmod 0500 \$(FAXLIB)/\$\$i ); \ X done X chmod 6711 \$(FAXLIB)/spool.fax X chown root.daemon \$(FAXLIB)/* X Xclean: X -rm -f *.o *.a core \$(PGMS) X XEOT X Xcat >faxhost/faxfonts/Makefile <<EOT X# Makefile for faxhost/faxfonts X X# path for textfax?.font is hardwired into diykit [in ../../faxconfig.h] Xall: diykit lores.data hires.data \ X $faxlib/textfaxl.font $faxlib/textfaxh.font X Xdiykit: diykit.o X cc -o diykit \$(LDFLAGS) diykit.o X Xdiykit.o: ../../faxconfig.h diykit.h diykit.c X cc \$(CFLAGS) -c diykit.c X X# path for textfax?.font is hardwired into diykit [in ../../faxconfig.h] X$faxlib/textfaxl.font: lores.data X ./diykit X X$faxlib/textfaxh.font: hires.data X ./diykit X Xlores.data: lores.uue X uudecode lores.uue && uncompress lores.data.Z X Xhires.data: hires.uue X uudecode hires.uue && uncompress hires.data.Z X X Xinstall: X Xclean: X -rm -f *.o *.a *.data core diykit X XEOT X X# end of FaxConfig END_OF_FILE if test 25531 -ne `wc -c <'FaxConfig'`; then echo shar: \"'FaxConfig'\" unpacked with wrong size! fi # end of 'FaxConfig' fi if test -f 'faxhost/faxfonts/diykit.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'faxhost/faxfonts/diykit.c'\" else echo shar: Extracting \"'faxhost/faxfonts/diykit.c'\" \(5399 characters\) sed "s/^X//" >'faxhost/faxfonts/diykit.c' <<'END_OF_FILE' X#include <stdio.h> X#include <malloc.h> X#include <ctype.h> X#include "diykit.h" X X#include "../../faxconfig.h" X Xstatic char *PGM = "diykit"; Xchar charset[128]; Xint bm_len; Xextern int errno; X Xstruct FNT_BITMAP /* one for each char */ X{ X short *SH; X short active; X} font[256]; X X Xfont_init(name) Xchar *name; X{ X FILE *hp; X int i; X struct FNT_BITMAP *cf; X static int fst; X char tmp[4]; X X errno = 0; X if (!fst) X for (i=0; i<256; i++) /* just to be safe */ X { X cf = &font[i]; X cf->SH = (short *)NULL; X cf->active = 0; X } X else for (i=0; i<256; i++) /* just to be safe */ X { X cf = &font[i]; X if (cf->SH) X free(cf->SH); X cf->SH = (short *)NULL; X cf->active = 0; X } X X if ((hp = fopen(name, "r")) == NULL) X { X fprintf(stderr,"%s: can't open %s font, errno %d\n",PGM,name,errno); X return(ERROR); X } X X if (fread(tmp, sizeof(char), 3, hp) != 3) X { X fprintf(stderr,"%s: can't read fontfile %s, errno %d\n",PGM,name,errno); X return(ERROR); X } X if (!strncmp(tmp, "fxL", 3)) X bm_len = 16; X else if (!strncmp(tmp, "fxH", 3)) X bm_len = 32; X else X { X fprintf(stderr,"%s: %s is not a bitmap font\n",PGM,name); X return(ERROR); X } X X if (rd_diykit(hp)) X return(ERROR); X X fclose(hp); X ++fst; X return(0); X} Xrd_diykit(fp) XFILE *fp; X{ X int i, lastc; X struct FNT_BITMAP *cf; X short cur_char; X char curchar[8]; X X for (cur_char=0;;) X { X lastc = cur_char; X /* not all machines are big endian ones */ X /* diykit therefore stores cur_char as a */ X /* 4 byte ascii string. It is, however written */ X /* as a short. */ X if ((i = fread(curchar, 4, 1, fp)) != 1) X { X if (cur_char > 0x7e && (!i)) X break; X fprintf(stderr,"%s: read error %d in font\n",PGM,errno); X return(ERROR); X } X curchar[4] = '\0'; X cur_char = (short)atoi(curchar); X if (cur_char <= 0x20 || cur_char > 0xff) X { X fprintf(stderr,"%s: illegal curchar value %04x after char %3d\n", X PGM,cur_char,lastc); X return(ERROR); X } X cf = &font[cur_char]; X X if ((cf->SH = (short *)malloc(bm_len * sizeof(short))) == (short *)NULL) X { X fprintf(stderr,"%s: not enough memory for bitmap array char %d\n", X PGM,cur_char); X return(ERROR); X } X X if (fread(cf->SH, sizeof(short), bm_len, fp) != bm_len) X { X fprintf(stderr,"%s: read error %d for char bitmap %d\n", X PGM,errno,cur_char); X return(ERROR); X } X cf->active = TRUE; X } X return(0); X} Xwritekit(hp,kit) XFILE *hp, *kit; X{ X struct FNT_BITMAP *cf; X short cur_char, i, pos; X char tmp[4]; X X if (bm_len == 16) X strcpy(tmp, "fxL"); X else strcpy(tmp, "fxH"); X X if (fwrite(tmp, sizeof(char), 3, hp) != 3) X { X fprintf(stderr,"%s: write error %d on fontfile\n",PGM,errno); X return(ERROR); X } X X for (cur_char=33; cur_char<128; cur_char++) X { X cf = &font[cur_char]; X if (cf->active) X { X if (fwrite(&cur_char, sizeof(short), 1, hp) != 1) X { X fprintf(stderr,"%s: write error %d on font\n", X PGM,errno); X return(ERROR); X } X if (fwrite(cf->SH, sizeof(short), bm_len, hp) != bm_len) X { X fprintf(stderr,"%s: write error %d on font\n", X PGM,errno); X return(ERROR); X } X } X } X X while ((cur_char = getnext_char(&pos,kit)) != EOF) X { X cf = &font[cur_char]; X if (cf->active) X { X if (fwrite(&pos, sizeof(short), 1, hp) != 1) X { X fprintf(stderr,"%s: write error %d on font\n", X PGM,errno); X return(ERROR); X } X if (fwrite(cf->SH, sizeof(short), bm_len, hp) != bm_len) X { X fprintf(stderr,"%s: write error %d on font\n", X PGM,errno); X return(ERROR); X } X } X } X return(0); X} Xgetnext_char(pos,fp) Xshort *pos; XFILE *fp; X{ X char buf[128], charname[40]; X int found, Pos; X static int line; X X for (;;) X { X if (fgets(buf, 126, fp) == NULL) X return(EOF); X ++line; X if (buf[0] != '#') X { X if (sscanf(buf,"%d %s",&Pos,charname) < 2) X { X fprintf(stderr,"%s: def file looks wrong to me at line %d\n",PGM,line); X return(EOF); X } X *pos = Pos; X if ((found = find_def(charname)) == EOF) X { X fprintf(stderr,"%s: unknown char def {%s} at at line %d\n", X PGM,charname,line); X return(EOF); X } X return(found); X } X } X} Xfind_def(s) Xchar *s; X{ X int mid, cmp, hi,lo; X X lo=0; X hi = MAX_DEF-1; X for (; lo<=hi;) X { X mid = (lo+hi)/2; X if ((cmp = strcmp(s, diy[mid].charname)) < 0) X hi = mid-1; X else if (cmp > 0) X lo = mid+1; X else return(diy[mid].chardef); X } X return(EOF);; X} Xmain() X{ X FILE *out, *kitfp; X char destname[256]; X X errno = 0; X if ((kitfp = fopen("diykit.def", "r")) == NULL) X { X fprintf(stderr,"%s: can't open diykit.def, errno %d\n",errno); X exit(1); X } X X if (fgets(charset, 126, kitfp) == NULL) X { X fprintf(stderr,"%s: can't read charset info on 1st line, errno %d\n", X PGM,errno); X exit(1); X } X if (font_init("lores.data")) X exit(1); X X sprintf(destname, "%s/%s", FAXLIB, FAXLFONT); X if ((out = fopen(destname, "w")) == NULL) X { X fprintf(stderr,"%s: can't create %s, errno %d\n", X PGM,destname,errno); X exit(1); X } X writekit(out,kitfp); X fclose(out); X chmod(destname, 0644); X X errno = 0; X rewind(kitfp); X if (fgets(charset, 126, kitfp) == NULL) X { X fprintf(stderr,"%s: can't read charset info on 1st line, errno %d\n", X PGM,errno); X exit(1); X } X if (font_init("hires.data")) X exit(1); X X sprintf(destname, "%s/%s", FAXLIB, FAXHFONT); X if ((out = fopen(destname, "w")) == NULL) X { X fprintf(stderr,"%s: can't create %s, errno %d\n", X PGM,destname,errno); X exit(1); X } X writekit(out,kitfp); X fclose(out); X fclose(kitfp); X chmod(destname, 0644); X X exit(0); X} END_OF_FILE if test 5399 -ne `wc -c <'faxhost/faxfonts/diykit.c'`; then echo shar: \"'faxhost/faxfonts/diykit.c'\" unpacked with wrong size! fi # end of 'faxhost/faxfonts/diykit.c' fi if test -f 'faxhost/sendfax.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'faxhost/sendfax.c'\" else echo shar: Extracting \"'faxhost/sendfax.c'\" \(20157 characters\) sed "s/^X//" >'faxhost/sendfax.c' <<'END_OF_FILE' X#include <stdio.h> X#include <malloc.h> X#include <fcntl.h> X#include <errno.h> X#include <time.h> X#include <sys/types.h> X#include <dirent.h> X#include <unistd.h> X X#include "../faxconfig.h" X X/* X sendfax.c X X called frequently by cron, X inspect spool area for jobs to do - and get on with it X the actual squirting of data through the serial ports X is done in wiring.c X this file is concerned mainly with reading config info, X collecting and parsing all available x.files and X passing them on to forked copies of sendfax to share X the load X X if you have only one faxmodem, all work is done in house X without forking off slave clones X X first released version 0.99 [desperado version] X cleaned up Jan 22nd '91, X Copyright (C) 1991, klaus schallhorn, klaus@cnix.uucp X X Permission to use, copy, modify, and distribute this software X and its documentation for any purpose and without fee is hereby X granted, provided that the above copyright notice appear in X all copies and that both that copyright notice and this permission X notice appear in supporting documentation. X X This software is provided "as is" without express or implied warranty. X*/ X X#define COME_BACK 0 X#define GO_AWAY 1 X X#define ALLOWED 1 /* individual permissions, same as cron/at */ X#define DENIED 2 /* files: fax.allow, fax.deny */ X#define ROOT 3 X#define ALL 4 X Xchar faxrun[256], /* make a note that's sendfax is running */ X tmp[1024], X io[1024]; X X Xchar **faxjobs; /* list of x.files, jobs to do */ Xchar **Denied, **Allowed; /* fax permissions, same setup as cron */ Xchar **CanNow; /* in case the boss wants to override hours */ X Xstatic int pid, /* zip 'em all out to zero */ X max_age, /* days a fax may hover in spool dir */ X max_tries, /* max no of attempts to tx a fax [job] */ X faxperms, /* checking fax.allow && fax.deny */ X a_cnt, d_cnt, /* number of allowed/denied users */ X cn_cnt, /* no of unrestricted users */ X dev_cnt, /* number of devices faxable */ X todo; /* no of fax jobs in queue */ X Xint blah; /* chattynes for logging */ X Xstruct Hours /* restrict certain area/country codes to cheap hours, */ X{ /* or local faxes only between midday and noon */ X char *dialcode; X char hours[24]; X} *hour_ptr; Xstatic int h_entries; X X Xstruct config_funcs /* to read fax.config in any order */ X{ X int (*funcptr)(); /* function address */ X char *funcname; /* name used in config file */ X}; X Xint device(), incoming(), hours(), maxage(), maxtry(), loglevel(); Xchar **Devices, /* array of device names in /dev */ X **Devlocks, /* array of lock file names */ X **Faxtypes, /* array of fax modem types */ X **Wakeup, /* array of strings to revive modems */ X *Dialtyp, /* array of T's or P's [tone/pulse] */ X *Topspeed; /* array of one byte speed indicators */ X Xstruct config_funcs config_table[] = X{ X/* address funcname */ X { device, "device" }, X { incoming, "incoming" }, X { hours, "hours" }, X { maxage, "maxage" }, X { maxtry, "maxtry" }, X { loglevel, "loglevel" } X}; X#define MAX_CONFIG sizeof(config_table)/sizeof(struct config_funcs) X Xstruct FAX fax; X Xextern int errno; XFILE *popen(); X X Xmain(ac,av) Xint ac; Xchar *av[]; X{ X char *PGM; X X errno = blah = 0; X hour_ptr = NULL; X Topspeed = Dialtyp = NULL; X Allowed = Denied = CanNow = NULL; X Devices = Devlocks = Faxtypes = Wakeup = NULL; X X pid = getpid(); X X if ((PGM = strrchr(av[0], '/')) != NULL) X PGM++; X else PGM = av[0]; X X#ifndef TESTING X if (fork()) /* errs, parent, or unwanted relatives */ X exit(0); X if (setpgrp(0,0)) X { X fax_log(ERROR, "sendfax: can't create new prgp\n"); X exit(1); X } X#endif X X if (chdir(FAXSPOOL)) /* quick one, job done */ X { X fax_log(ERROR,"sendfax: can't cd to FAXSPOOL\n"); X exit(1); X } X if (read_config()) X exit(1); X X if (!strcmp(PGM, "rcvfax")) X exit(0); /*rcvfax(); when done */ X else /* sendfax */ X { /* see if sendfax is active, if so, go away */ X sprintf(faxrun, "%s/SEND.FAX.RUN",FAXLIB); X if (mklock(faxrun, FALSE, FALSE) < 0) X { X fax_log(5, "sendfax: busy\n"); X exit(0); /* last cron job of sendfax still busy */ X } X if ((todo = chk_queue()) > 0) X { X if (!blah) X fax_log(0, "sendfax: STARTUP, %d device%c, %d jobs pending\n", X dev_cnt,(dev_cnt>1)?'s':' ',todo); X else fax_log(9, "sendfax: %d jobs pending\n",todo); X runqueue(); X } X fax_log(5, "sendfax: done\n"); X unlink(faxrun); X } X exit(0); X} X Xrunqueue() X{ X int i, j, k, brk, in_use, slot, *kid_pids; X FILE *X; X X fax.phone = NULL; X X if (dev_cnt > 1) /* do this only if more than 1 faxmodem */ X { X if ((kid_pids = (int *)malloc(dev_cnt * sizeof(int))) == NULL) X { X fax_log(ERROR,"sendfax: can't allocate memory\n"); X return; X } X for (i=0; i<dev_cnt; i++) X kid_pids[i] = 0; X } X X fax.phone_nos = 0; X for (i=in_use=slot=0; i<todo; i++) X { X fax.tries = fax.uid = fax.now = X fax.mail = fax.pages = 0; X fax.user[0] = fax.dname[0] = '\0'; X#ifdef JOBID X fax.jobid[0] = '\0'; X#endif X fax.tpos = fax.ppos = fax.spooled = 0L; X X if ((X = fopen(faxjobs[i], "r+")) == NULL) X { X fax_log(ERROR,"sendfax: can't open %s\n",faxjobs[i]); X return; X } X X if (read_job(X, faxjobs[i])) X { X fax_log(ERROR,"sendfax: can't read %s\n",faxjobs[i]); X return; X } X fax_log(5, "sendfax: %s, %d fax%s, attempt %d, user %s%s\n", X faxjobs[i], fax.phone_nos, (fax.phone_nos>1)?"es":"", X fax.tries, fax.user, X (fax.tries < max_tries)?"":", CANNOT RETRY"); X X if (fax.tries >= max_tries) X { X fclose(X); X continue; X } X X if (chk_perms()) X { X fclose(X); X fax_log(ERROR,"sendfax: user %s not permitted to use fax, mailed user, unlinked files\n",fax.user); X rmjob(faxjobs[i],fax.dname,fax.pages); X sprintf(tmp,"echo 'you have no permission to fax [fax admin: %s]' | mail %s",FAXADMIN,fax.user); X system(tmp); X continue; X } X X/* X can no longer avoid the issue. X if we have just 1 faxmodem, squirt one job now, X if we're sharing the load between several devices, find X an unused one and fork a copy to do the sending. If no X faxmodems avail, wait for one to pop up. X X All this assumes uucp is not interfering, this is checked X in "wiring.c", where we just die away [or return in case X of just 1 device] if port cannot be opened X*/ X if (dev_cnt == 1) X { X sendfax(X, slot, COME_BACK); X continue; X } X X for (k=0; k<dev_cnt; k++) X if (!kid_pids[k]) X { X slot = k; X break; X } X X if ((j = fork()) == ERROR) X { X fax_log(ERROR,"sendfax: can't fork, giving up\n"); X return; X } X else if (!j) /* child */ X sendfax(X, slot, GO_AWAY); X X fclose(X); /* still open in child for read/write */ X kid_pids[slot] = j; /* associate kid's pid with dev */ X X if (++in_use < dev_cnt) X continue; X X for (brk=0; !brk;) X { X j = wait((int *)NULL); /* don't wanna know x status */ X for (k=0; k<dev_cnt; k++) X if (j == kid_pids[k]) X { /* make device recycleable */ X kid_pids[k] = 0; X --in_use; X brk = TRUE; /* have an unused device */ X break; /* brk top loop to go on */ X } X } X } X} X Xchk_queue() X{ X DIR *dirp; X struct dirent *dp; X int alloced, entries, i; X X if ((dirp = opendir(FAXSPOOL)) == NULL) X return(fax_log(ERROR,"sendfax: can't open directory %s\n",FAXSPOOL)); X X if ((faxjobs = (char **)malloc(8*sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X alloced = 8; X entries = 0; X X for (;;) X { X if (entries == alloced) X { X if ((faxjobs = (char **)realloc(faxjobs, X (alloced += 8) * sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X } X X if ((dp = readdir(dirp)) == NULL) X break; X if (strncmp(dp->d_name, "x.f", 3)) X continue; X X if ((faxjobs[entries] = malloc(1+strlen(dp->d_name))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X strcpy(faxjobs[entries++], dp->d_name); X } X closedir(dirp); X i = entries; X while (i < alloced) X faxjobs[i++] = NULL; X return(entries); X} Xread_config() X{ X FILE *cfg; X char a[256]; X int i; X X sprintf(a, "%s/fax.config", FAXLIB); X if ((cfg = fopen(a, "r")) == NULL) X { X fax_log(ERROR,"sendfax: can't open %s/fax.config\n",FAXLIB); X return(ERROR); X } X X while (fgets(io, 254, cfg) != NULL) X { X if (io[0] == '#' || (sscanf(io, "%s",a) < 1)) X continue; X for (i=0; i<MAX_CONFIG; i++) X if (!strcmp(a,config_table[i].funcname)) X { X if ((*config_table[i].funcptr) X (&io[fstbyte(io,strlen(a))])) X { X fax_log(ERROR, X "strange device spec [%s]\n",io); X return(ERROR); X } X break; X } X if (i == MAX_CONFIG) X fax_log(ERROR,"sendfax: unknown function in config: %s\n",a); X } X fclose(cfg); X if (blah >= 5) /* alternative STARTUP log is in main with blah == 0 */ X fax_log(5, "sendfax: STARTUP, %d device%c\n",dev_cnt,(dev_cnt>1)?'s':' '); X if (get_perms()) X return(ERROR); X return(0); X} Xfstbyte(s,skip) /* find fst usable item in a config line like: */ Xchar *s; /* device /dev/copperwire */ Xint skip; X{ X s += skip; X while (*s && isspace(*s)) X { X ++skip; X ++s; X } X return(skip); X} Xnxtint(s) Xchar *s; X{ X char *o; X X o = s; X while (*s && (isdigit(*s) || *s == '-')) X ++s; X while (*s && isspace(*s)) X ++s; X return((int)(s - o)); X} Xdevice(s) Xchar *s; X{ X static int d_alloced; X char dev[80], devlck[80], faxtyp[80], dial, speed, *sptr, *eptr; X X if (sscanf(s,"%s %s %s %c %c",dev,devlck,faxtyp,&dial,&speed) < 5) X return(ERROR); X X if (!d_alloced) X { X if (((Devices = (char **)malloc(4*sizeof(char *))) == NULL) X || ((Devlocks = (char **)malloc(4*sizeof(char *))) == NULL) X || ((Faxtypes = (char **)malloc(4*sizeof(char *))) == NULL) X || ((Wakeup = (char **)malloc(4*sizeof(char *))) == NULL) X || ((Dialtyp = (char *)malloc(4)) == NULL) X || ((Topspeed = (char *)malloc(4)) == NULL)) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X d_alloced = 4; X } X else if (d_alloced == dev_cnt) X { X d_alloced += 4; X if (((Devices = (char **)realloc(Devices, X d_alloced * sizeof(char *))) == NULL) X || ((Devlocks = (char **)realloc(Devlocks, X d_alloced * sizeof(char *))) == NULL) X || ((Faxtypes = (char **)realloc(Faxtypes, X d_alloced * sizeof(char *))) == NULL) X || ((Wakeup = (char **)realloc(Wakeup, X d_alloced * sizeof(char *))) == NULL) X || ((Dialtyp = (char *)realloc(Dialtyp, X d_alloced)) == NULL) X || ((Topspeed = (char *)realloc(Topspeed, X d_alloced)) == NULL)) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X } X if (((Devices[dev_cnt] = malloc(1+strlen(dev))) == NULL) X || ((Devlocks[dev_cnt] = malloc(1+strlen(devlck))) == NULL) X || ((Faxtypes[dev_cnt] = malloc(1+strlen(faxtyp))) == NULL)) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X strcpy(Devices[dev_cnt], dev); X strcpy(Devlocks[dev_cnt], devlck); X strcpy(Faxtypes[dev_cnt], faxtyp); X Dialtyp[dev_cnt] = dial; X Topspeed[dev_cnt] = speed; X X if (((sptr = strchr(s, '"')) != NULL) X && ((eptr = strrchr(s, '"')) != NULL) X && (eptr > sptr)) X { X *eptr = '\0'; X ++sptr; X if ((Wakeup[dev_cnt] = malloc(1+(int)(eptr-sptr))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X strcpy(Wakeup[dev_cnt], sptr); X } X else Wakeup[dev_cnt] = NULL; X X ++dev_cnt; X return(0); X} Xincoming(s) Xchar *s; X{ X/* haven't had time to do this X if (sscanf(s,"%s",Incoming) < 1) X*/ X return(ERROR); X} Xmaxtry(s) Xchar *s; X{ X if (sscanf(s,"%d",&max_tries) < 1) X return(ERROR); X return(0); X} Xloglevel(s) Xchar *s; X{ X if (sscanf(s,"%d",&blah) < 1) X return(ERROR); X return(0); X} Xmaxage(s) Xchar *s; X{ X if (sscanf(s,"%d",&max_age) < 1) X return(ERROR); X return(0); X} Xhours(s) Xchar *s; X{ X static int h_alloced; X int i, lasth; X char *p; X X if (sscanf(s,"%s",tmp) < 1) /* expect dial code */ X return(ERROR); X i = strlen(tmp); X s += fstbyte(s, i); /* skip him */ X X if (!h_entries) X { X if ((hour_ptr = (struct Hours *)malloc( X (h_alloced += 8) * sizeof(struct Hours))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X } X else if (h_alloced == h_entries) X { X if ((hour_ptr = (struct Hours *)realloc(hour_ptr, X (h_alloced += 8) * sizeof(struct Hours))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X } X if ((hour_ptr[h_entries].dialcode = malloc(1+i)) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X strcpy(hour_ptr[h_entries].dialcode, tmp); X X p = hour_ptr[h_entries].hours; X for (i=0; i<24; i++) X *p++ = '\0'; X X lasth = -1; X p = hour_ptr[h_entries].hours; X X while (*s && *s != '#') X { X if (isdigit(*s)) X { X if ((i = atoi(s)) < 0 || i > 23) X return(ERROR); X p[i] = '\1'; X if (lasth > -1) X { X if (lasth < i) X { X while (lasth < i) X p[lasth++] = '\1'; X } X else X { X while (lasth < 24) X p[lasth++] = '\1'; X lasth = 0; X while (lasth < i) X p[lasth++] = '\1'; X } X lasth = -1; X } X s += nxtint(s); X } X else if (*s == '-') X { X lasth = i; X s += nxtint(s); X } X } X ++h_entries; X return(0); X} X#define MATCHCMASK 0377 X#define MATCHQUOTE 0200 X#define MATCHQMASK (MATCHCMASK&~MATCHQUOTE) X#define MATCHNOT '^' X Xstatic char *cclass(); X Xmatch(s, p) Xchar *s, *p; X{ X int sc, pc; X X while ((pc = *p++ & MATCHCMASK) != '\0') X { X sc = *s++ & MATCHQMASK; X switch (pc) X { X case '[': X if ((p = cclass(p, sc)) == NULL) X return(0); X break; X case '?': X if (sc == 0) X return(0); X break; X case '*': X s--; X do X { X if (*p == '\0' || match(s, p)) X return(1); X } while (*s++ != '\0'); X return(0); X default: X if (sc != (pc & ~MATCHQUOTE)) X return(0); X } X } X return(*s == 0); X} X Xstatic char *cclass(p, sub) Xchar *p; Xint sub; X{ X int c, d, not, found; X X if ((not = *p == MATCHNOT) != 0) X p++; X found = not; X X do X { X if (*p == '\0') X return(NULL); X c = *p & MATCHCMASK; X if (p[1] == '-' && p[2] != ']') X { X d = p[2] & MATCHCMASK; X p++; X } X else d = c; X X if (c == sub || c <= sub && sub <= d) X found = !not; X } while (*++p != ']'); X X return(found ? (p+1) : NULL); X} Xget_perms() X{ X FILE *fp; X int a_alloced, d_alloced, len; X X a_alloced = d_alloced = 0; X sprintf(tmp, "%s/fax.allow", FAXLIB); X if ((fp = fopen(tmp, "r")) != NULL) X { X if ((Allowed = (char **)malloc(8*sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X a_alloced = 8; X X for (;;) X { X if (a_cnt == a_alloced) X { X if ((Allowed = (char **)realloc(Allowed, X (a_alloced += 8) * sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X } X X if (fgets(tmp, 128, fp) == NULL) X break; X if ((len = strlen(tmp)) == 0) X break; X X tmp[--len] = '\0'; X if (!len) X continue; X if ((Allowed[a_cnt] = malloc(1+len)) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X strcpy(Allowed[a_cnt++], tmp); X } X if (a_cnt) X faxperms = ALLOWED; X fclose(fp); X } X else X { X sprintf(tmp, "%s/fax.deny", FAXLIB); X if ((fp = fopen(tmp, "r")) != NULL) X { X if ((Denied = (char **)malloc(8*sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X d_alloced = 8; X X for (;;) X { X if (d_cnt == d_alloced) X { X if ((Denied = (char **)realloc(Denied, X (d_alloced += 8) * sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X } X X if (fgets(tmp, 128, fp) == NULL) X break; X if ((len = strlen(tmp)) == 0) X break; X X tmp[--len] = '\0'; X if (!len) X continue; X if ((Denied[d_cnt] = malloc(1+len)) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X strcpy(Denied[d_cnt++], tmp); X } X if (d_cnt) X faxperms = DENIED; X else faxperms = ALL; X fclose(fp); X } X } X if (!faxperms) X faxperms = ROOT; X return(get_boss_perms()); X} Xget_boss_perms() X{ X FILE *fp; X int cn_alloced, len; X X cn_alloced = 0; X sprintf(tmp, "%s/fax.always", FAXLIB); X if ((fp = fopen(tmp, "r")) != NULL) X { X if ((CanNow = (char **)malloc(8*sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X cn_alloced = 8; X X for (;;) X { X if (cn_cnt == cn_alloced) X { X if ((CanNow = (char **)realloc(CanNow, X (cn_alloced += 8) * sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X } X X if (fgets(tmp, 128, fp) == NULL) X break; X if ((len = strlen(tmp)) == 0) X break; X tmp[--len] = '\0'; X if (!len) X continue; X if ((CanNow[cn_cnt] = malloc(1+len)) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X strcpy(CanNow[cn_cnt++], tmp); X } X fclose(fp); X } X fax_log(3, "sendfax: faxperms %d, allowed %d, denied %d, always %d\n", X faxperms, a_cnt, d_cnt, cn_cnt); X return(0); X} Xread_job(fp, xn) XFILE *fp; Xchar *xn; X{ X int i; X X if (fax.phone_nos) /* has been called before, clean up */ X { X for (i=0; i<fax.phone_nos; i++) X if (fax.phone[i] != NULL) X free(fax.phone[i]); X free(fax.phone); X fax.phone = NULL; X fax.phone_nos = 0; X } X X/* X these are read in the order they're written X by the spooler, not they way the structure is designed X*/ X if (getint(fp,&fax.spooled)) /* spool timestamp */ X return(ERROR); X fax.tpos = ftell(fp); /* might need to rewrite no of attempts */ X if (getint(fp,&fax.tries) X || getstring(fp,fax.user) || getint(fp,&fax.uid) X || getint(fp,&fax.now) || getint(fp,&fax.mail) X || getint(fp,&fax.type) X || getint(fp,&fax.hires) X || getstring(fp,tmp) /* font, don't need to know this */ X || getstring(fp,tmp)) /* retfax, don't need to know either */ X return(ERROR); X fax.ppos = ftell(fp); /* if we succeed on partial phone list */ X if ((fax.phone_nos = getphone(fp)) <= 0) /* rewrite those not yet done */ X return(ERROR); X if (getstring(fp,fax.dname)) X return(ERROR); X strcpy(fax.xname, xn); X if (getint(fp,&fax.pages)) X return(ERROR); X#ifdef JOBID X if (getstring(fp,fax.jobid)) X return(ERROR); X#endif X return(0); X} Xgetstring(fp,s) XFILE *fp; Xchar *s; X{ X char buf[80]; X X if (fgets(io, 80, fp) == NULL) X return(ERROR); X if (sscanf(io, "%s %s",buf,s) != 2) X return(ERROR); X return(0); X} Xgetint(fp,n) XFILE *fp; Xint *n; X{ X long l; X X if (fgets(io, 80, fp) == NULL) X return(ERROR); X if (sscanf(io, "%s %ld",tmp,&l) != 2) X return(ERROR); X *n = l; X return(0); X} Xgetphone(fp) XFILE *fp; X{ X int i, p_entries=0, p_alloced=0; X char phone[80]; X long oldpos; X X if ((fax.phone = (char **)malloc(8*sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X p_alloced = 8; X p_entries = 0; X X for (;;) X { X oldpos = ftell(fp); X X if (p_entries == p_alloced) X { X if ((fax.phone = (char **)realloc(fax.phone, X (p_alloced += 8) * sizeof(char *))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X } X X if (fgets(io, 80, fp) == NULL) X return(ERROR); X if (io[0] == '#') X continue; X if (!strncmp(io, "data", 4)) X { X fseek(fp, oldpos, 0); X break; X } X if (sscanf(io, "%s %s",tmp,phone) < 2) X return(ERROR); X X if ((fax.phone[p_entries] = malloc(1+strlen(phone))) == NULL) X return(fax_log(ERROR,"sendfax: can't allocate memory\n")); X strcpy(fax.phone[p_entries++], phone); X } X for (i=p_entries; i<p_alloced; i++) X fax.phone[i] = NULL; X return(p_entries); X} Xchk_perms() X{ X int i; X X if (faxperms == ALL) X return(FALSE); X else if ((faxperms == ROOT) && (!fax.uid)) X return(FALSE); X else if (faxperms == ALLOWED) X { X for (i=0; i<a_cnt; i++) X if (!strcmp(fax.user, Allowed[i])) X return(FALSE); X } X else if (faxperms == DENIED) X { X for (i=0; i<d_cnt; i++) X if (!strcmp(fax.user, Denied[i])) X return(ERROR); X return(FALSE); X } X return(ERROR); X} Xnot_now(uid,now,phone) Xint uid, now; Xchar *phone; X{ X int i; X time_t cur; X struct tm *tml, *localtime(); X X if (fax.now) X { X if (!fax.uid) /* if root can edit fax.config it can fax now */ X return(FALSE); X for (i=0; i<cn_cnt; i++) X if (!strcmp(fax.user, CanNow[i])) X return(FALSE); X } X X for (i=0; i<h_entries; i++) /* check area/cty codes for restrictions */ X if (match(phone, hour_ptr[i].dialcode)) X { X (void)time(&cur); X tml = localtime(&cur); /* if not allowed at this hour */ X if (!hour_ptr[i].hours[tml->tm_hour]) X return(ERROR); X return(FALSE); X } X return(FALSE); /* no restrictions on this phone number */ X} Xrmjob(xname,dname,pages) Xchar *xname,*dname; Xint pages; X{ X char buf[256], *d; X int i; X X unlink(xname); X for (i=0; i<pages; i++) X { X sprintf(buf,"%s.g3.%d",dname,i); X unlink(buf); X } X} END_OF_FILE if test 20157 -ne `wc -c <'faxhost/sendfax.c'`; then echo shar: \"'faxhost/sendfax.c'\" unpacked with wrong size! fi # end of 'faxhost/sendfax.c' fi echo shar: End of archive 2 \(of 5\). cp /dev/null ark2isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 archives. rm -f ark[1-9]isdone else echo You still must unpack the following archives: echo " " ${MISSING} fi exit 0 exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.