Henry Griggs Rambling
Recent TopicsVisit to Australia 2002
Sydney house 2002
Circular Quay 2004
Circular Quay 2002
Centrepoint Tower 2004
Oz Birds 2004
Oz Birds 2002
Bridge Climb 2002
Popular TopicsGallbladder removal
Photo of the day
Geek Alaska 2003
UK in 2003
Geek Caribbean 2002
Photo Of The Day
Printing with a Linux System
30th August 2001
Printing under Linux has caused me some grief in the past and I wrote some notes so I could remember what to do. I've cleaned up those notes and put them here. I find them useful, and if anyone else does too, it's a bonus.
If you want more generic information, have a look at www.linuxprinting.org.
[Note 3rd July 2003] I have changed from this method to using CUPS for my printing. See my CUPS Notes.
I started with an early Slackware in 1994, and had no problems with printing. I worked for a company that wrote a Unix typesetting system and they had recompiled it for Linux. It was called TopSet and was a very neat system. You could edit with your flavour of editor, and then typeset and print with their typesetting engine. While I worked for the company, they were moving the typesetting system support SGML and it was a very interesting and fun time. I really liked the typesetting system. I ran the Linux version of the typesetting system at home on my Slackware box and it worked until about 1997 or 1998 when Slackware introduced a new print system called lprNG. That's what me memory tells me, but it could be wrong. When I upgraded to the next version of Slackware, typesetting stopped. The new print mechanism would not accept the sort of output coming from TopSet. I spent a lot of time working out why printing had stopped, and in the meantime, I learnt how printing worked. I was greatly helped by a large cheap book called The Linux Bible, which was a printing of a bunch of HOW-TOs and FAQs. There were as an excellent article in there about the basic BSD style print mechanism.
When I learnt what the problem was, I pondered my options and tried a few things and fiddled with Slackware, but I finally decided to move to RedHat 5.2. The print mechanism was much slicker with RedHat and quite easy to configure, with their GUI or by editing the config files. So I continued to print quite happily until 2000, when for various reasons, I switched back from RedHat to Slackware. I found that lprNG was gone and the standard lpr system was back again. By this time I had a network print server and the Slackware print system didn't appear to like it. Probably more to the point, I didn't have the patience to learn a new print system. I wanted something easy like the RedHat system. So I analysed the RedHat system and found that I couldn't copy it directly. Rather than do any work myself, I looked on freshmeat to see if someone else had done something. Sure enough, someone had. Mike Petullo had written print_filter, a simple script that does what the RedHat system did. The initial version used a RedHat utility called rewindstdin, but later versions removed the need for that. I installed it, modified it a bit to suit my tastes, and it works very well. In setting it up, I had to re-learn those earlier lessons about the way printing works, and I wrote fresh notes on it.
Printing on most versions of Linux is fairly simple. The print mechanism that I am describing is often called the BSD-style Printing Mechanism. There are four major parts.
Using lpr is pretty easy. It comes standard with almost every Linux distribution. If everything is set up right, to use it to print something, you just type "lpr filename". If your print mechanism is working properly, you will see your hard disk lights flicker, and then your printer will start printing. It should all happen transparently. If your system is not set up right, then nothing will happen.
lpr has many options. You don't normally need any. But if you want to get fancy, do "man lp" and see what you can do.
You should never have to worry about lpd. It's installed for you, and it starts running at boot time. If you want to check if it's running, type "ps -ef | grep lpd" and confirm that it's there.
If you want to see where it gets started, you have to look in the startup directories. With Slackware, look in the file /etc/rc.d/rc.M and search for lpd. There's a single command that starts your print daemon.
/etc/printcap for a local printer
This is the file that controls your print setup. Generally, a sample version is created for you when a Linux distribution is installed.
Here is an early version of my /etc/printcap file.
lp|lj:\ :lp=/dev/lp0:\ :sd=/var/spool/lpd/lp:\ :if=/var/spool/lpd/lp/print_filter.sh:\ :mx#0:\ :sh:
Basically, it's one printer per line. You can have any number of printers specified in the file. However the one printer per line rule makes it clumsy to read and maintain, so the single line for a printer is usually broken into its various components by escaping each line (using a backslash on the end of each line to indicate that the line continues to the next line). The line must start with the printer name (and aliases), but after that, the components can be in any order. The components take this form: ":key=value:". The key is a two character abbreviation.
The first line specifies the name of the printer. The default name is lp. If you use lpr without specifying a printer, then it assumes you want the printer called "lp". So you should always specify a printer in /etc/printcap called "lp". It means less typing. You can give aliases for lp if you want. Here, I've used the alias "lj", a tiny abbreviation of Hewlett-Packard LaserJet 6L. If I wanted, I could include other aliases on the same line by adding them after lj and separating them with the pipe symbol (|). Example: lp|lj|hplj6l. So I could print to this printer using the aliases, as in "lpr -Plj" or "lpr -Phplj6l". These would produce exactly the same result as "lpr", with my /etc/printcap. I normally have no need to include other aliases. I don't even need or use one alias. I just include it because I can.
A lot of different things can be specified. If you do "man printcap", you'll see a heap of components that can be specified. I use a very simple set of components, just enough to do the job for me. If I was setting up a print server for a big corporation with many printers and many users, I would use a lot more of the options. Have a read through the man page and see what's available.
lp - line printer
This specifies the hardware device where the printer is located. "lp=/dev/lp0". Check the /dev directory and make sure the device lp has been created for you, and it has the right permissions. If you want to test that the printer is attached and the connection works, copy a file to the device.
sd - spool directory
You have to specify where the print files get queued or spooled. You do this with the "sd" component. Often, they are kept in /var/spool/lpd. At various times, I have had more than one printer attached, so I have kept them in different directories. I usually use a directory off /var/spool/lpd, and to keep things straight, I make it the name of the printer. So I keep the queue files for print lp in /var/spool/lpd/lp. If I had another printer attached called lexcol (Lexmark Colour for example), then I would set up a directory called /var/spool/lpd/lexcol.
Once you set this up in printcap, you have to ensure that the directories exist and have the right ownership and permissions. Because lpd runs as root, the directories should be owned by root and have rwxr-xr-x permission.
Once printing starts, three files will be created in the directory you specified.
From now on, all the action for your printer will take place in the directory specified with "sd".
Each time lpr gives a file to lpd, several files are written to the spool directory. One of these files is the contents of the file to be printed, another contains the details of the print request. If your print mechanism stops and you have a large number of files in the queue and you want to get rid of them, you can always come here, check out which files are which and manually remove them. Check the filenames and check the contents before you start deleting everything.
if - input filter
This specifies your input filter. The input filter is a magical device that transforms the file you want printed into output suitable for the printer. The input filter does a very complex job and is the hardest thing to set up. In my example, "if=/var/spool/lpd/lp/print_filter.sh", I am storing a shell script called print_filter.sh in my spool directory and using it as the input filter. I notice that lately, some input filters are no longer stored in the spool directory, but in more common places like /usr/local/bin. Either way is fine.
The input filter is used like this:
If you want to test if the whole print mechanism is working, you can do it manually, step by step. I do this when I am debugging my input filter.
The input filter is the most important part of your print setup. It converts input files into a format like Postscript or PCL so your printer can understand it and know how to print it. You can also use it to do pretty printing of text, or special effects on images, and a wide range of other things. See below for a description of what I use, and some variants.
mx - maximum file size
This is used to control paper wastage. It's best used for non-home setups, or to control accidental printer mistakes. You can specify 0, as I do, to allow files of any size to be printed. Or you can specify a number. The number represents how many BUFSIZ blocks will be allowed to be printed. If the input file size is greater than this size, it will be thrown away. I don't know how big BUFSIZ is. I don't know what the default is. I specify 0 to allow unlimited file sizes, and that suits me fine.
sh - suppress header
If you omit this component, each print job will get an extra page at the front with details of the print job. This is probably nice in a large multi-person environment, but at home it just wastes paper. I use ":sh:" to suppress the header.
/etc/printcap for a remote printer
I use a Hewlett-Packard JetDirect EX Plus3 network print server. This is a small device that attaches to the network and has an IP address. I can have up to 3 printers attached to this device, although at this stage, I only have one printer attached. Anyone on my network can print to the printer. Sure, I could attach the printer to my computer and people could still print from my printer, but only while my computer is turned on. The print server is always on.
To access the print server, I use this /etc/printcap:
lp|lj:\ :lp=:\ :rm=netprinter:\ :rp=raw:\ :if=/var/spool/lpd/lp/print_filter.sh:\ :sd=/var/spool/lpd/lp:\ :mx#0:\ :sh:
You'll notice that most of the components are the same. if, sd, mx and sh are still the same. lp is empty. And I use two new components.
rm - remote printer
Here I specify the name of the remote printer. In my /etc/hosts file, I have this line:
My print server has IP address 192.168.30.10. So print jobs are not sent to my local device of /dev/lp0, they are sent to the IP address 192.168.30.10, and I trust that something is there at that IP address to grab the file and do something with it. And it is.
rp - remote printer name
This is used by my print server. I can have three printers attached. So I have one IP address for the three printers, and this field, the remote printer name, is what determines which printer to use. My print server accepts these names - raw (raw1), text (text1), raw2, text2, raw3, text3. Basically, there are two modes of printing. If I specify "raw", it pumps the data straight to the printer without any modification, assuming it to be already PCL or Postscript. If I specify "text", it will add a carriage return to each line before sending it to the printer. I use "raw" mode.
This is the core of your printing system. It converts input files of one format and converts them to a format suitable for your printer. It can be a compiled program, a Perl script, or a shell script. These days it's mostly a shell script.
Many years ago when I was experimenting with Linux printing, I wrote a Perl script that accepted text files with tags, and produced output that was suitable for a Hewlett-Packard LaserJet 5L printer. It basically threw a few PCL commands around the text. It's Perl 4, and written when I was new to Perl, so it's a bit rough. Here's that old Perl program.
As you can see, it fulfills the requirements of a basic input filter. It accepts input from STDIN, modifies it, and spits the result out through STDOUT. It worked back then, and did a pleasant job of preparing text for me. Nowadays, my needs are greater.
I use a shell script now that uses a number of utilities to modify the input file. Here's a copy of the shell script I use now.
Have a look at the file. It works like this:
That's a very simple script that handles a few input formats. If you look at the input filter on the average RedHat or Mandrake system, you'll see that they handle many more formats and do much more processing. They also use a lot more environment variables for the options, whereas I have hardcoded many of them into the script. This script suits my purposes. It handles everything I use now, including output from Netscape, Mozilla, StarOffice, and Gimp. It works. If something stops working, or I change my hardware, I will change my script. I do have plans for it. Eventually, I will move it to /usr/local/bin, and include a print_filter.conf in /etc. These are changes that the original author, Mike Petullo, has made. See the latest version of his script at print_filter. He has also done away with the dependency on RedHat's rewindstdin, by dumping the file to /tmp, using "file" on it there, then feeding the file in through STDIN to a2ps. His approach is now much better than the one I am using, and eventually, when the need takes me, I shall follow his lead.
BSD style printing with Linux is a long chain of commands. Every step of the way can be made simple, or can be made very complex, depending on your needs. When you understand the full flow of data, you can easily debug your printing when you are setting it up. Once it's set up, you can leave it alone for a long time. If you do customise your setup, make sure you back the files up.