HylaFAX The world's most advanced open source fax server

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

[hylafax-users] Build notes arising from a Solaris 9 / SPARC install



Title: Build notes arising from a Solaris 9 / SPARC install
Hi everybody,

I’ve just finally succeeded in getting an inbound/outbound HylaFAX server up and running on Solaris 9 / SPARC.  Along the way, I encountered some significant difficulties that I would expect others on the same/similar platforms to run across as well, so I thought I’d document them (and the solutions) to save others from similar pain.

First, the configuration:

Target Hardware:
-------------------
Sun Ultra 5
Practical Peripherals PM288MT II V.34 External modem

Software:
----------
Solaris 9 12/03
GNU coreutils 5.0 -
http://ftp.gnu.org/pub/gnu/coreutils/coreutils-5.0.tar.gz
TIFF 3.5.7 - ftp://ftp.remotesensing.org/pub/libtiff/tiff-v3.5.7.tar.gz
GNU GhostScript 7.07 - ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/gnu/gs707/ghostscript-7.07.tar.bz2
(plus JPEG 6b) - ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz
base64 1.3 - http://www.fourmilab.ch/webtools/base64/base64-1.3.tar.gz
HylaFAX 4.1.8
(all built with GNU gcc 3.3.2)

Strategy
---------
Since this system will be a production box, I wanted to build it using our standard, reproducible build process.  This means building all components from source in a standard environment and then deploying out the resulting binaries to the target platform.  Ultimately the plan has been successful but I encountered some significant challenges while I was getting everything up and running.

Here are the issues I encountered:
---------------------------------------

a) PATH assumptions – HylaFAX requires a number of additional software components to be installed before it will work (i.e. tiff, ghostscript etc.).  It also explicitly sets its own environment when you run the faxsetup utility, saving its settings in a file called setup.cache.  (In my setup, the setup.cache PATH variable was set to /usr/sbin:/usr/5bin:/bin:/usr/bin:/etc:/usr/ucb:/usr/etc which contains exactly none of the additional executables.  LD_LIBRARY_PATH was not set at all.)

The problem here was that none of the additional software was located in places that HylaFAX’s environment could see.  Consequently, neither faxgetty, /etc/init.d/hylafax nor faxrcvd would work properly, either complaining of missing libraries or returning bad results by failing to find critical executables (especially the TIFF utilities.)  I solved the problem by creating a script (/etc/hylafax-profile) that set up the required environment and adding it to HylaFAX components as necessary.

The /etc/hylafax-profile script looks like this:

# ----------- HylaFAX -------------
HYLAFAX_HOME=/usr/local/hylafax
HYLAFAX_SPOOL=${HYLAFAX_HOME}/spool/hylafax
COREUTILS_HOME=/usr/local/coreutils
TIFF_HOME=/usr/local/tiff
GS_HOME=/usr/local/ghostscript
LIBGCC_HOME=/usr/local/libgcc
LIBSTDCPP_HOME=/usr/local/libstdc++
BASE64_HOME=/usr/local/base64

PATH=${BASE64_HOME}/bin:${HYLAFAX_HOME}/bin:${HYLAFAX_SPOOL}/bin:${COREUTILS_HOME}/bin:${TIFF_HOME}/bin:${GS_HOME}/bin:${PATH}
MANPATH=${BASE64_HOME}/man:${HYLAFAX_HOME}/man:${COREUTILS_HOME}/man:${TIFF_HOME}/man:${MANPATH}
LD_LIBRARY_PATH=${LIBGCC_HOME}/lib:${LIBSTDCPP_HOME}/lib:${TIFF_HOME}/lib:${LD_LIBRARY_PATH}

export PATH MANPATH LD_LIBRARY_PATH HYLAFAX_HOME HYLAFAX_SPOOL

I then modified the /etc/init.d/hylafax and $HYLAFAX_SPOOL/bin/faxrcvd scripts to source /etc/hylafax-profile immediately after sourcing $HYLAFAX_SPOOL/etc/setup.cache.  That way, I just extend whatever HylaFAX already wanted to control.  Here’s an example from /etc/init.d/hylafax:


--- script example begins -----
...
. $SPOOL/etc/setup.cache

# --- Include custom HylaFAX environment settings -------------
. /etc/hylafax-profile
# -------------------------------------------------------------
...
--- script example ends -----


Fixing faxgetty was a little trickier, since it’s a binary, not a script.  My solution was to wrap faxgetty in a script which included the custom environment.  I called this script $HYLAFAX_HOME/lib/fax/faxgetty-launcher and it looks like this:

--- script example begins -----
#!/bin/sh
. /etc/hylafax-profile
COM_PORT=$1
$HYLAFAX_HOME/lib/fax/faxgetty $COM_PORT
--- script example ends -----


My /etc/inittab entry looks like this:

fax1:23:respawn:/usr/local/hylafax/lib/fax/faxgetty-launcher    cua/b

b) TIFF compatibility – When I was getting the source for the various components required by HylaFAX, my policy was to use the latest, stable release.  For libtiff, this was 3.6.1.  However, after much agony, I concluded that the .tif files being created by the inbound fax receiving process were being created in a corrupted fashion.  Although tiffinfo reported the files key statistics just fine, attempts to process it with tools like tiff2ps yielded a mass of unexpected EOL and incomplete line errors.  Without changing any other configuration element, I replaced 3.6.1 with a source-built 3.5.7 and magically the .tiff files were correctly created.  (I also succeeded with the 3.5.7 pre-built libtiff package from Sun Freeware but my requirements dictate that I build from source so I don’t use this solution in production.)

c) uuencode – The reason I ran into the TIIF compatibility problem was that I was trying to deliver inbound faxes as file attachments.  Once I solved the TIFF problem, I thought the rest would be plain sailing.  Wrong!  All my attachments came through unreadable.  I eventually traced this problem to the Sun-supplied uuencode utility.  If you look at the faxrcvd script, you see that the .tif or .pdf file attachments (both of which are binary), are included with Content-Transfer-Encoding: base64.  According to RFC 2405, this is absolutely correct, as it is one of the sanctioned encoding methods.  (Well done HylaFAX!).  However, the Sun-supplied uuencode is incapable of generating a base64 encoding.  It can only produce the “legacy” uuencode, which is not part of RFC 2405.  So, I was creating MIME attachments that claimed base64 encoding and putting traditional uuencode data into them.  I searched GNU, sourceforge etc. for a base64-capable uuencode solution but didn’t find any that looked right.  Eventually, I hit on the base64 utility from FourmiLab (not FermiLab) in Switzerland.  Apart from a few glitches with the build, once deployed it worked fine.

My build glitch was that it compiled fine but the make install bombed because the target directory didn’t exist and the Makefile had no defined task to create one.  Here’s what I did:

 
  ./configure —prefix=/usr/local/base64-1.3    <-- This reads your system and build the basic makefile, setting the internal prefix variable accordingly
     
  [Edit Makefile as follows]
…  
CWEAVE = cweave  
DVIPS = dvips  
INSTALL_DIR =  /usr/local/coreutils/bin/install -d      #<-- This defines the command that should be used to create a directory
INSTALL =  /usr/local/coreutils/bin/install -c  
INSTALL_PROGRAM = ${INSTALL}  
…  
## The 'DESTDIR' variable allows  you to install the program into a different  
## location, e.g., for  packaging, without affecting the compiled-in pathnames.  
DESTDIR = /usr/local/staging/base64     #<-- (Optional) Because I want to package the distribution, I divert the output file tree here.
prefix = /usr/local/base64-1.3  
exec_prefix = ${prefix}  
…  
configurator:      
    rm -f config.cache      
    $(CONFDIR)/autoconf  --macrodir $(CONFDIR)    

#   Installation    
install-man-dir:    #<-- This target creates the man directory
   $(INSTALL_DIR)  $(MAN1DIR)      #<-- Add this too

install-bin-dir:        #<-- This target creates the bin directory
   $(INSTALL_DIR)  $(BINDIR)    #<-- Add this too

install-bin: install-bin-dir base64     #<-- Change $BINDIR) to install-bin-dir
    $(INSTALL_PROGRAM)  base64 $(BINDIR)/base64    

install-man: install-man-dir base64.1           #<-- Change $MAN1DIR) to install-man-dir
    $(INSTALL_DATA)  base64.1 $(MAN1DIR)/base64$(man1ext)    

install: install-bin install-man    

#   Uninstallation    
uninstall:      
    rm -f $(BINDIR)/base64  $(MAN1DIR)/base64$(man1ext)  
…  
[Make file ends here]

Then,

make
make install

I also had to come up with a version of $HYLAFAX_SPOOL/bin/uuencode_it that used base64, not uuencode.  This is it:

-- script example begins -------
#!/bin/sh
SRC_FILE=$1
base64 -e $SRC_FILE
---- script example ends -------

d) Lastly, I had a bit of a struggle with my modem, a PM288MT II V.34 from (Im)Practical Peripherals, which appears to have one of the most broken Class 2 implementations on the planet.  If you don’t use this modem, you’ll probably not care about this section, but it you do, you’ll REALLY care.  Basically, the modem is so broken that although $HYLAFAX_SPOOL/bin/faxaddmodem detects it supports Class 1 and 2 communications, it can’t really configure either properly.  I was only able to get Class 2 to work and I did that with the modem config below (I can’t take any credit for this.  All I did was piece together the work of others I found in the supplied modem configs):

CountryCode:           1
AreaCode:              xxx
FAXNumber:             +1xxx.xxx.xxxx
LongDistancePrefix:     1
InternationalPrefix:    011
DialStringRules:        etc/dialrules
ServerTracing:          1
SessionTracing:         11
RecvFileMode:           0444
LogFileMode:           0444
DeviceMode:            0600
RingsBeforeAnswer:     1
SpeakerVolume:          low
GettyArgs:             "-h %l dx_%s"
LocalIdentifier:        "xxxxxxxxxxx"
ClocalAsRoot:           no
TagLineFont:           etc/lutRS18.pcf
TagLineFormat:          "From %%l|%c|Page %%P of %%T"
MaxRecvPages:           50

ModemType:             Class2          # use this to supply a hint

Class2Cmd:             AT+FCLASS=2    # command to enter class 2
Class2BORCmd:          AT+FBOR=0       # bit order for phase B/C/D (direct)
Class2RELCmd:          AT+FREL=1       # byte-align EOL codes on recv
Class2AbortCmd:         AT+FK           # abort session command
Class2CQCmd:           ""             # commands to enable copy quality proc.
Class2DCCQueryCmd:      AT+FDCC=?       # query for modem capabilities
Class2TBCCmd:          AT+FTBC=0       # setup stream mode
Class2CRCmd:           AT+FCR=1        # enable capability to receive
Class2PHCTOCmd:         AT+FPHCTO=30    # set phase C timeout parameter
Class2BUGCmd:          AT+FBUG=0
Class2LIDCmd:           AT+FLID        # set local identifier command
Class2DCCCmd:          AT+FDCC         # set modem capabilities command
Class2DISCmd:          AT+FDIS         # set session parameters command
Class2CIGCmd:          AT+FCIG         # set polling identifier command
Class2PTSCmd:          AT+FPTS         # set post-page status command
Class2SPLCmd:          AT+FSPL         # set polling indicator command
Class2XmitWaitForXON:   yes            # if true, wait for XON before send


# Workarounds for bugs in PMMM288MT Class 2 support
ModemAnswerFaxBeginCmd: "<19200><xon>"
Class2RecvDataTrigger:  "\022"
Class2DDISCmd:          AT+FDIS
Class2SendRTC           yes

ModemSendFillOrder:     LSB2MSB         # as expected
ModemRecvFillOrder:      MMSB2LSB     # opposite of what makes sense




I hope the above is useful to at least one person.  If so, then it’s been worth the hour to type it up.  
Enjoy


Regards,
Adrian Newby

---------------------------------

Adrian Newby
Chief Technology Officer
Prudent Rx Inc.
100 Corporate Pointe, Suite 395
Culver City, CA 90230

P: +1 (310)642-1700 x124
F: +1 (310)642-1701
e: anewby@xxxxxxxxxxxxx

**Notice of Confidentiality**
The information contained in this e-mail message is intended only for the use of the individual or entity named above. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution, or copy of the communication is prohibited.




Project hosted by iFAX Solutions