UNIX printing with CUPS server

The FreeBSD print and file server, chrome, was working well at printing for Windows clients (through Samba), but not, as I discovered recently, for UNIX clients.

chrome's printer is an HP LaserJet 5N, a PCL5-capable printer. When chrome had been a Windows95 machine, the setup of printing from the (then) Redhat machine had been relatively simple.

Since then, Windows 95 had been replaced by FreeBSD, and Redhat by debian. Obviously, client printing on debian had never been setup. To rectify this, the cupsys-clientpackage was installed on the UNIX client. The /etc/cups/client.conf file needs to be modified, inserting the name of the default CUPS print server (chrome). On testing, with lp, I was told:

  lp: error - scheduler is not responding!

This seemed to be because because the default cupsd.conf file only allows access from 127.0.0.1. I modified the Location stanza to:

  <Location />
  Order Deny,Allow
  Deny From All
  Allow From 127.0.0.1
  Allow From @LOCAL
  </Location>

Now that access was permitted, I tried again. No error was returned at the command line, but still nothing was printed. In the CUPS error_log file (located in /var/log/cups), the error message Unable to convert file 0... was posted against the test print, followed by a hint about ESP GhostScript. The CUPS FAQ repeats this advice; the error occurs if you attempt to print a file to a non-PostScript printer when you do not have ESP Ghostscript installed.

Even I could take the hint. I installed (from ports) cups-pstoraster and cups-lpr (the latter gives you the CUPS versions of lp, cancel, enable etc - note that these binaries are located in /usr/local/bin and will be hidden by the normal BSD lp* commands (in /usr/bin), unless you use the CUPS_OVERWRITE_BASE option). Using lpadmin, the default printer was set as HPLaserJet5N, with a command of the form:

  lpadmin -d HPLaserJet5N

The final change was to edit the ppd file, located in /usr/local/etc/cups/ppd/HPLaserJet5N.ppd, to set the default paper size to A4. OK, now I could print postscript and plain text files using the FreeBSD box as both client and server. The only problem was the default font for plain text files was Courier, 12pt. Courier was OK, but 12pt was just too large. I put this problem off, until I had client printing from the debian box sorted out.

Astonishingly enough, this worked straightaway. I therefore had no excuse to hold off researching the font size for plain text files problem.

Default font size setting for plain text files to CUPS

I could find no way of informing CUPS that I wanted a specific font size default in the ppd file. Perhaps there was another route. Back in the Windows 95 days, I had sent plain text files to the Windows printer, but prefixed by a PCL command string to cause 10pt font to be the default. Perhaps I could do the same with CUPS?

There are two ways to inform CUPS that already formatted print data is being sent. One is the lpr -l command (you need the cupsys-bsd package to get hold of the CUPS version of this command), or the lp -oraw command. The latter method is probably best, as you get a message confirming the print job has been sent. lpr is silent

I tried this method, and found a problem: the output stepped its way across the page - the driver obviously needed carriage returns (octal 15) at the end of each line. I'm sure that wasn't a problem with the Windows 95 setup, but maybe I had always printed DOS format files (or maybe Windows 95 fixed things up - seems unlikely). To fix this, I wrote a filter in python to top and tail a set of data with PCL commands, and to add a carriage return to every line. I also gave it an -o option, to set the left offset. The code for pcl.py is here:

#!/usr/bin/python
"""
 NAME
    pcl.py

 SYNOPSIS
    pcl.py [-o n]

 DESCRIPTION
    Converts file into text file suitable to send to a PCL printer.

    The -o command argument sets the left offset to n. The default is zero.

    The printer initialisation string is for a PCL5 printer, setting the
	default font (courier) to 10 point text.

    The ESC E string resets the printer (both before and after printing as
    belt and braces).

    Each line has a CR (octal 15) appended, as the PCL printer seems
    to require it.

 MODIFICATION HISTORY
 Mnemonic        Rel  Date     Who
 pcl.py          1.0  20041010 mpw
    Created

    
"""

import sys
import getopt


#+++++++++++++++++++++++++++++++++++++++++++++++++
# start of program
#+++++++++++++++++++++++++++++++++++++++++++++++++

offset = 0

# read command line arguments, if any
try:
    opts,args = getopt.getopt(sys.argv[1:],'o:')
    for o,v in opts:
        if o == '-o': offset  = int(v)
except getopt.GetoptError:
    print >>sys.stderr, "pcl.py: illegal argument"
    sys.exit(1)

pad = " "*offset

print "\033E\033(s12.00h10.00V\015",
for line in sys.stdin:
    print pad+line.rstrip()+"\015"

print "\033E\015",

Plain text files can now be printed from UNIX clients of the print server by commands of the form:

  cat file|pcl.py -o 5|lp -oraw -

Naturally, this should be wrapped by a convenient script...

Addendum - 21st January, 2005

By chance, I discovered that the Debian system on chrome (maintained on a separate disk to FreeBSD to provide yet another backup) would not allow printing for Windows clients. I was sure this used to work in the past. However, I think Samba had been upgraded (to 2.2.3a-14.1) some time after I last checked the printing capabilities. At a cursory glance, the smb.conf file looked OK; printing was set to "cups".

Clients trying to print to HPLaserJet5N were being told "Access denied, unable to connect". By trying to add a new printer in the Windows client, I found that chrome was offering an printer called "lp", not "HPLaserJet5N" as it should do. The printer "lp" was defined in /etc/printcap, while "HPLaserJet5N" was defined in /etc/printcap.cups. The smb.conf file defined printcap=/etc/printcap. I changed the Samba configuration file to use printcap=/etc/printcap.cups. OK, that stopped the "Access denied" message for "HPLaserJet5N", and the client was allowed to print. My warm glow of success was dampened by the fact that no printing job ever hit the cups daemon.

The samba log file showed that the commands used to print were the BSD-style commands of lpq and lpr. These commands were returning a value of "1". If I issued these commands manually, they errored with a message that printer "HPLaserJet5N" did not exist. A quick look at the installed packages showed that cupsys-bsd, which provides the cups versions of the bsd printing commands, was not installed. I installed that package, and printing started working again.

The unanswered question is why samba had stopped printing via cups. My feeling is that setting printing=cups in the smb.conf file was being ignored. This would explain why /etc/printcap was being referenced instead of /etc/printcap.cups and the BSD style commands were being issued whether printing=cups or printing=bsd was specified.