HylaFAX The world's most advanced open source fax server

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

[hylafax-users] Advice for Building HylaFax 4.1.3 on Mac OS X



Hear are my notes in building and installing HylaFax 4.1.3 on a Mac OS X 
system.
I build on Mac OS 10.1.5 and tested on 10.1.5,10.1.3 and 10.2.1 (Jaguar) 
using the
internal modem of the Mac and sent a received 1000+ faxes with only two 
failure that I attribute to phone line failures. It is now installed at 
one of our site and in production. My thanks to the HylaFAX team for 
producing a good product.

I discovered what I think may be a bug in "faxd/FaxSend.c++", it does not 
choose the correct default resolution unit (as per TIFF spec) if none is 
specified in the tiff file when sending. I made the following change in 
the method FaxServer::sendSetupParams1():

	short resunit = RESUNIT_NONE;

to

	short resunit = RESUNIT_INCH;


Also I received warning from compiler in util/StackBuffer.h when 
compiling FaxDB.c++ and
TagLine.c++:

FaxDB.c++: In method `bool FaxDB::getToken(FILE *, fxStr &)':
FaxDB.c++:205: warning: choosing `fxStackBuffer::operator char *()' over 
`fxStackBu
ffer::operator const char *() const'
FaxDB.c++:205: warning:   for conversion from `fxStackBuffer' to `const 
char *'
FaxDB.c++:205: warning:   because conversion sequence for the argument is 
better

TagLine.c++: In method `u_char * FaxModem::imageTagLine(u_char *, 
unsigned int, const Class2Params &)':
TagLine.c++:302: warning: choosing `fxStackBuffer::operator unsigned char 
*()' over `fxStackBuffer::operator const unsigned char *() const'
TagLine.c++:302: warning:   for conversion from `fxStackBuffer' to `const 
unsigned char *'
TagLine.c++:302: warning:   because conversion sequence for the argument 
is better

until I added the following to the file util/StackBuffer.h:

In class fxStackBuffer definition added:

    operator const char*();	// Return base of buffer
    operator const unsigned char*();// Return base of buffer

after definition added:

inline fxStackBuffer::operator const char*()
    { return base; }
inline fxStackBuffer::operator const unsigned char*()
    { return (unsigned char*)base; }

Notes for building on the Mac:

1.) First make sure you have installed the April 2002 or newer version of 
the Apple Developer Tools, these contain version 2.95.2 of the GNU 
compiler. The previous version generated errors because it did not 
tolerate the  Obj *p = new(x) Obj; construct. To test the version, type 
gcc -v, you should get:

Apple Computer, Inc. version gcc-937.2, based on gcc version 2.95.2 
19991024 (release)

2.) To make building on the Mac easier I would suggest to the HylaFAX 
authors to change their source file names so they will be unique on file 
systems that do not treat file names with different cases as unique - 
i.e. regex.h conflicts with RegEx.h. I realize that you can use a UFS 
disk on the Mac to solve this problem, but this is a burden to Mac users 
as standard Mac disks are all HFS which ignores case in filenames. The 
file name conflicts I found were:

faxd/faxRequest.c++ and faxd/FaxRequest.c++ (I renamed faxRequest.c++ to 
FaxRequestDefs.c++)
faxd/faxRequest.h and faxd/FaxRequest.h (I renamed faxRequest.h to 
FaxRequestDefs.h)
util/textfmt.c++ and util/TextFmt.c++ (I renamed textfmt.c++ to 
textfmtapp.c++)
util/RegEx.h and regex/regex.h (I renamed RegEx.h to RegExObj.h)
util/Syslog.h /usr/include/sys/syslog.h (I renamed Syslog.h to SyslogF.h)

Also there is an enum in ClassModem.h:

class ClassModem {
public:
    enum {			// ClassModem::CallStatus
	OK	   = 0,		// phone answered & carrier received
	BUSY	   = 1,		// destination phone busy
	NOCARRIER  = 2,		// no carrier from remote
	NOANSWER   = 3,		// no answer from remote
	NODIALTONE = 4,		// no local dialtone (phone not plugged in?)
	ERROR	   = 5,		// error in dial command
	FAILURE	   = 6,		// other problem (e.g. modem turned off)
	NOFCON	   = 7,		// carrier established, but phase a failure
	DATACONN   = 8,		// data carrier established
	RING	   = 9		// glare - ring detected after dial
    };

Which fails to compile because of a #define in /usr/include/arpa/ftp.h -
 #define ERROR           5       /* permanent negative completion */
 
The name "ERROR" seemed likely to be used elsewhere so I changed it to a 
more specific name that was less likely to conflict with system includes 
- "MODEM_ERROR". This change was needed in the files:

faxd/ClassModem.h faxd/Class0.c++ faxd/Class1Send.c++ faxd/Class2Send.c++ 
faxd/ClassModem.c++ faxd/ServerConfig.c++ faxd/FaxSend.c++ 
faxd/pageSendApp.c++



I used the following shell script to fix the file naming and change the 
enum member "ERROR" to MODEMERROR where necessary. I ran this script 
after uncompressing the downloaded tar archive and running the configure 
script (this script can be run twice without damaging the files):

#!/bin/sh

# Rename file if not already renamed
# usage: fixname oldname newname
fixname()
{
	if [ -f $1 ]; then
		mv $1 $2
	fi
}

# Replace string within file
# usage: strrpl "s/old/new/" file1 file2 file3 ...
strrpl()
{
	repstr=$1
	shift
    for filen in "$@"; do
		sed -e "$repstr" <$filen >/tmp/macfix$$
		cp  /tmp/macfix$$ $filen
    done
}
		
umask 022
fixname faxd/faxRequest.c++.1 faxd/FaxRequestDefs.c++
fixname faxd/faxRequest.h.1 faxd/FaxRequestDefs.h
strrpl "s/faxRequest\.h/FaxRequestDefs.h/" faxd/FaxRequest.h
strrpl "s/faxRequest\./FaxRequestDefs./" faxd/Makefile hfaxd/Makefile 
distrules

fixname util/textfmt.c++.1 util/textfmtapp.c++
strrpl "s/textfmt\./textfmtapp./" util/Makefile distrules

fixname util/RegEx.h util/RegExObj.h
strrpl "s/RegEx\.h/RegExObj.h/" faxd/DestControl.h hfaxd/SNPPServer.c++ 
hfaxd/User.c++ util/FaxDB.c++ \
      util/RegEx.c++ util/RegExArray.h util/RegExDict.h distrules

fixname util/Syslog.h util/SyslogF.h 
strrpl "s/Syslog\.h/SyslogF.h/" faxd/faxApp.h util/Syslog.c++ 
hfaxd/HylaFAXServer.h distrules

strrpl "s/\([	]\)ERROR/\1MODEM_ERROR/" faxd/ClassModem.h
strrpl "s/(ERROR)/(MODEM_ERROR)/" faxd/Class0.c++ faxd/Class1Send.c++ 
faxd/Class2Send.c++ 
strrpl "s/ClassModem::ERROR/ClassModem::MODEM_ERROR/" faxd/ClassModem.c++ 
faxd/ServerConfig.c++ faxd/FaxSend.c++ faxd/pageSendApp.c++ 
faxd/ServerConfig.c++
strrpl "s#// ERROR#// MODEM_ERROR#" faxd/ClassModem.c++

# End of script

3.)  I used the device "/dev/cu.modem" (the Mac internal mode) using the 
basic class 2 configuration with the additional changes in the 
config.cu.modem file as follows:

ModemFlowControl:       rtscts          # was XON/XOFF flow control
ModemSetupDTRCmd:       AT&D3           # setup so DTR drop resets modem
Class2RecvDataTrigger:  "\022"          # character sent to modem to 
start recv
Class2XmitWaitForXON:   no              # if true, wait for XON before 
send

The Class2XmitWaitForXON when set to yes caused the modem to hang when 
sending, the
ModemFlowControl was xonxoff and this caused errors in sending and 
receiving faxes. I am not sure if the other two changes made any 
difference, I just made them based on the differences between the 
RockWell-K56 and the class 2 modem. When I tested the modem using 'cu' I 
got the following responses (cu is not shipped on Mac so I had write my 
own):

AT+FMFR?
CONEXANT

AT+FMDL?
AC/K56

AT+FCLASS=?
0,1,2,1.0

Not all Mac internal modems are the same. These changes worked for two 
single processor G4 Macs and an iMac, but the internal modem on a dual 
processor G4 (the silver doors model) I tested did not support class 2 so 
I configured it as a class 1 modem. The configuration generated by 
faxaddmodem stated the modem was "Rockwell RC288DPi-based Class 1 modem 
", but did not work until I appended all the "Class1Cmd:" settings from 
the 'class1' configuration file. The responses of the modem using cu were:

AT+FMFR?
ERROR

AT+FMDL?
ERROR

AT+FCLASS=?
0,1,1.0

!Rockwell
!Rockwell

!RC288DPi
!RC288DPi

ATI3
2.0.4

4.) I created a script for creating the necessary users and the 
/Library/StartupItems/{HylaFAX,StartupParameters.plist} files needed to 
start the fax deamon at startup. An improved "HylaFAX" startup script 
that meets the apple spec of responding to an argument of 'start','stop', 
or 'restart'  is:

#!/bin/sh
. /etc/rc.common
if [ "$1" = "stop" -o  "$1" = "restart" ]; then
        ConsoleMessage "Stopping HylaFAX server processes"
        /sbin/mount -t devfs ~fax/dev /var/spool/hylafax/dev
        /usr/local/sbin/hylafax stop
        ConsoleMessage "HylaFAX server processes stopped"
fi
if [ "$1" = "start" -o "$1" = "restart" ]; then
        ConsoleMessage "Starting HylaFAX server processes"
        /sbin/mount -t devfs ~fax/dev /var/spool/hylafax/dev
        /usr/local/sbin/hylafax start
        ConsoleMessage "HylaFAX server processes started"
fi

Adding the need users using the "NetInfo Manager" utility on the Mac is a 
slow and painful process, so I created a script to create the needed 
users, add the 4559,tcp HylaFax service to /etc/services, creates the 
~fax/dev directory, the /var/spool/uucp directory, and adds the 
'faxqclean' operation to the daily operations run by 'cron' is shown 
below. On the Mac the default installation has a crontab that runs 
"/etc/daily" and 3 AM daily, and runs "/etc/daily.local" if it exists, so 
the script adds the 'faxqclean' operation to "/etc/daily.local" if it is 
not already there.


#!/bin/sh
#
#
# Deduce the effective user id:
#
euid=`id|sed -e 's/.*uid=[0-9]*(\([^)]*\)).*/\1/'`
if [ "$euid" != "root" ]; then
    echo "Sorry, but you must run this script as the super-user!"
    exit 1
fi
echo "Creating uucp,fax and bin users"
niutil -create . /users/uucp
niload -v -r /users/uucp . <<EOF
{
  "expire" = ( "0" );
  "home" = ( "/var/spool/uucp" );
  "name" = ( "uucp" );
  "passwd" = ( "*" );
  "shell" = ( "/dev/null" );
  "change" = ( "0" );
  "realname" = ( "UUCP User" );
  "uid" = ( "10" );
  "gid" = ( "60" );
}
EOF
niutil -create . /users/bin
niload -v -r /users/bin . <<EOF
{
  "expire" = ( "0" );
  "realname" = ( "Bin User" );
  "name" = ( "bin" );
  "passwd" = ( "*" );
  "uid" = ( "499" );
  "change" = ( "0" );
  "shell" = ( "/dev/null" );
  "home" = ( "/usr/local/sbin" );
  "gid" = ( "60" );
}
EOF
niutil -create . /users/fax
niload -v -r /users/fax . <<EOF
{
  "expire" = ( "0" );
  "shell" = ( "/dev/null" );
  "name" = ( "fax" );
  "passwd" = ( "*" );
  "home" = ( "/var/spool/hylafax" );
  "change" = ( "0" );
  "uid" = ( "10" );
  "realname" = ( "Fax User" );
  "gid" = ( "60" );
}
EOF
chpass -a "uucp:*:10:66::0:0:uucp:/var/spool/uucp:"
chpass -a "fax:*:10:66::0:0:Facsimile Agent:/var/spool/hylafax:"
echo "Adding Hylafax 4559,tcp to services"
niutil -create . /services/hylafax
niload -v -r /services/hylafax . <<EOF
{
  "name" = ( "hylafax" );
  "port" = ( "4559" );
  "protocol" = ( "tcp" );
}
EOF

echo "Adding Hylafax cleanup to cron file /etc/daily.local"
## Add entries to cleanup fax queue  to /etc/daily.local which is run 
daily by cron
## avoid error if file does not exist
touch /etc/daily.local
## remove previously added entries
awk '/##### Start Added by HylaFax/,/##### End Added by HylaFax/ { next } 
{ print $
0 }' /etc/daily.local >/tmp/daily.local
cat >/tmp/daily.local <<EOF
##### Start Added by HylaFax

echo ""
echo "Cleaning up HylaFax directories"
sh /usr/local/sbin/faxcron
/usr/local/sbin/faxqclean

##### End Added by HylaFax
EOF
mv -f /tmp/daily.local /etc/daily.local
chmod 0622 /etc/daily.local

echo "Creating HylaFax startup script in /Library/StartupItems"
if [ ! -d /var/spool/uucp ]; then
        mkdir /var/spool/uucp
fi
chown uucp.uucp /var/spool/uucp
chmod 0775 /var/spool/uucp
if [ ! -d ~fax/dev ]; then
        mkdir ~fax/dev
fi
chown uucp.uucp ~fax/dev
chmod 0775 ~fax/dev
if [ ! -d /Library/StartupItems ]; then
        mkdir /Library/StartupItems >&/dev/null
fi
chown root.admin /Library/StartupItems
chmod 0775 /Library/StartupItems
if [ ! -d /Library/StartupItems/HylaFAX ]; then
        mkdir /Library/StartupItems/HylaFAX
fi
chown root.admin /Library/StartupItems/HylaFAX
chmod 775 /Library/StartupItems/HylaFAX
cat >/Library/StartupItems/HylaFax/HylaFAX <<EOF
#!/bin/sh
. /etc/rc.common
if [ "\$1" = "stop" -o  "\$1" = "restart" ]; then
        ConsoleMessage "Stopping HylaFAX server processes"
        /sbin/mount -t devfs ~fax/dev /var/spool/hylafax/dev
        /usr/local/sbin/hylafax stop
        ConsoleMessage "HylaFAX server processes stopped"
fi
if [ "\$1" = "start" -o "\$1" = "restart" ]; then
        ConsoleMessage "Starting HylaFAX server processes"
        /sbin/mount -t devfs ~fax/dev /var/spool/hylafax/dev
        /usr/local/sbin/hylafax start
        ConsoleMessage "HylaFAX server processes started"
fi
EOF
chown root.admin /Library/StartupItems/HylaFAX/HylaFAX
chmod 0775 /Library/StartupItems/HylaFAX/HylaFAX
cat >/Library/StartupItems/HylaFAX/StartupParameters.plist <<EOF
{
          Description     = "HylaFAX daemon";
          Provides        = ("HylaFAX Server");
          OrderPreference = "Last";
          Messages =
          {
            start = "Starting HylaFAX Server";
            stop  = "Stopping HylaFAX Server";
          };
}
EOF
chown root.admin /Library/StartupItems/HylaFAX/StartupParameters.plist
chmod 0775 /Library/StartupItems/HylaFAX/StartupParameters.plist

# End of script

5.) Since I am only sending faxes from TIFF files of the proper format 
generated from scanning and receiving TIFF files, I had no need for a 
postscript RIP, I modified the faxsetup script to tolerate no postscript 
rip. It would be nice if this script tolerated no PS rip as it is not 
necessary for all installations.

Regards,
Chris
 

____________________ HylaFAX(tm) Users Mailing List _______________________
  To subscribe/unsubscribe, click http://lists.hylafax.org/cgi-bin/lsg2.cgi
 On UNIX: mail -s unsubscribe hylafax-users-request@hylafax.org < /dev/null
  *To learn about commercial HylaFAX(tm) support, mail sales@hylafax.org.*




Project hosted by iFAX Solutions