Printing under Linux has historically been a problem because of, well, the history of Linux. Since Linux is based on Unix, which has a history stretching back to the middle-ages (1960's), the printing arrangements which most systems come with are geared, or at least have elements from, the Unix printing needs of that time.
These needs can be summed up as: Either very high or very low quality printing for large organisations. In the days before laser printing became cheap many systems had "draft" printers and "final" printers which varied in quality and cost.
Today many homes and small offices have Unix/Linux systems attached to a single inkjet which is operated in several modes, and sometimes also to a black and white laser printer.
Two problems arise with this setup and current Linux printing methods. One is the basic issue of getting good drivers for inkjet printers, which is now largely solved, and the other is the fact that Linux's traditional print services do not understand the idea of multiple virtual printers on the same physical printer (i.e., a single inkjet which can print in various radically different modes).
Many, many, many solutions have been proposed for fixing Linux printing but most have concentrated on large organisations and their security and bulk issues. I run a very small IT Department with two printers and four machines behind a firewall. I am thus more interested in utility than security so implementing eight RFC's is right out!
Other issues with current systems include the inability to handle TrueType fonts (CUPS, for example is based on a buggy version of Ghostscript and dies when ComicSans or Verdana is used in a job), and the difficulty of users manipulating the settings of the printer from within programs which have no understanding of the print control system being used.
Ironically, this last point is the key to getting a decent system running: by using the ignorance of StarOffice, Dvips, Mozilla, or Opera it is possible to construct a print daemon which actually allows the normal user to access all their printers' settings without any special permissions or resorting to GUI tools which fail when accessing the print server over telnet or which require root permissions to set the paper size.
The solution, which I will call CPS (Coherent Printing System), is a set of Perl scripts called "lpr", "lpd", "lprm", and "lpq". These replace the programs of the same name which come with many Linux systems.
The basis of my approach is this: EVERYTHING IS POSTSCRIPT OR RAW.
By "raw" I mean already converted into a data format that the printer actually understands directly. The output from The Gimp's print command is raw, for example.
Most other printing systems try to guess what to do by looking at a print job and applying "magic filters" to convert it to the printer's internal format. This is a nightmare of configuration and maintenance which serves no purpose in many cases. Put bluntly, I know if my file is Postscript or not and I generally have a better idea of how to get it into that format than any "smart" filter program.
In practise things are even better, almost all Linux programs can output Postscript of a very high standard. We just send this to the print system! In the case of plain text, also, it is trivial to convert this to Postscript automatically. Everything else should be under the user's control.
This means that the printer driver must understand PostScript and be able to output the raw printer format. This means Ghostscript, a free program for translating PostScript to various other printer languages. Since Ghostscript (from version 6.5 onwards) also understands TrueType fonts even a genuine PostScript printer can benefit from its use in embedding fonts into print jobs. This is a subject covered by a future item on this site.
One big bonus of this approach is that each client machine to a remote print server needs nothing more than the client software; the driver and print daemon are centralised on the server which makes maintenance very simple; a printer can be replaced at the server end without affecting remote machines which are printing using the global defaults. In particular, in a situation (as in our office) where there is a printer on the Linux server and another on a Windows machine, the server is set up to use the Windows printer via Samba and the clients still just send their jobs to the Linux server; they need never know that the job ends up being sent to the Windows machine.
Apart from Perl itself, you will also need the Perl modules IO::Socket, Fcntl, and Getopt::Long. As far as I know these are all included with the base Perl distribution. Foomatic version 3.0.0+ is also required (see below).
When removing old versions of the following software bear in mind that you will be replacing it again with more up-to-date versions so you can ignore dependency errors from your package manager, if you have one.
If your printer is not on the list as at least "Partially" supported then go no further; I don't know what you can do.
You will probably be best off just removing any of the following if you have installed them from binary formats such as RPM or even DEB.
This is included in the pre-patched, pre-compiled version of Ghostscript mentioned below, which you'll only use if you have to, right?
If your printer needs gimp-print (see the list of supported printers at the Linux printing site then get the source code for it, after removing any existing version. You should get at least version 4.2.0 (at the time of writing this is the latest stable release, but version 4.2.1-pre1 has just been announced).
NEVER USE GHOSTSCRIPT VERSIONS PRIOR TO 6. These are obsolete and have too many problems with no advantages. Except for this, you do not need a new version of Ghostscript unless you are using the Gimp-print driver.
Assuming that you need a new version of Ghostscript then, if you have not got the source code for the most up to date version of Ghostscript that you can use, delete any version you have installed (remembering to keep your Fontmap.GS file if you have modified it).
Forget about using RPMs or packages which claim to cover all the requirements here; my experience is that Linux printing is moving too fast for packagers to keep up and the only way to get an up to date system is to build from source.
Don't even use the pre-patched, pre-compiled version mentioned at the Linux printing site unless you really, really can't face compiling your own copy.
Foomatic's source is downloadable from the Linux printing site. The particular version we will use is the "directomatic" version, also referred to as the "no spooler" option. I used this as it makes no assumptions about the spooler (other than there not being one) which made it easier to write a new spooler for it.
Again, if you have an older version of Foomatic delete it. Particularly the RedHat 7.x RPMs which are garbage (as is just about everything connected with printing in RedHat after version 6.0).
The next step is to build a version of Ghostscript that understands the Gimp-print driver, if needed. Versions 7.05 and later do include detection of Gimp-print when compiled from source.
One other big hint is that compiling Ghostscript requires the source for the jpeg library from Independent JPEG Group's website and this needs to be placed inside the Ghostscript source tree in its own directory called "jpeg", i.e., its full path will be something like /usr/src/ghostscript-6.52/jpeg.
Next, download and install the latest version of Foomatic. Again, I'll leave detailed instructions until later, the important thing to watch out for is that you have told the makefile the correct place to install the Perl modules.
Okay, if you've been reading from the start you'll have everything you need to use Foomatic and Ghostscript to convert Postscript into whatever it is that your printer uses.
The system now needs to know about the printer(s) you have connected so that the correct output can be generated.
Current versions of Foomatic include the program
foomatic-datafilewhich is used to generate the configuration files we need. We need one of these for each type of printer connected to the server. Client machines do not need Foomatic or any of its files. This .ppd file is used to control the options passed to ghostscript.
The foomatic datafile program needs to know two things: what type of printer you are using and what driver you want to use it with. To find out what the options are and what the "official" name of you printer is use the line:
foomatic-configure -O|lessand search through the output (hint: try using "/" and input the printer's model) for your printer's details. For example, I have an Epson Stylus Photo 1290 here and searching for "1290" twice (the first hit was the Sharp 212905) gets the following information:
<printer> <id>Epson-Stylus_Photo_1290</id> <make>Epson</make> <model>Stylus Photo 1290</model> <functionality>A</functionality> <driver>gimp-print</driver> <autodetect> <!--no known parport probe information--></autodetect> <drivers> <driver>gimp-print</driver> <driver>omni</driver> </drivers> </printer>which tells me that the printer's name is Epson-Stylus_Photo_1290 (from the "id" tag, NOT the make or model tags, this may be a number completely unrelated to name on the actual printer) and that there are two drivers, gimp-print and omni, of which the recommended one is the gimp-print one (the "driver" tag).
This information is fed into foomatic-datafile like this:
foomatic-datafile -t ppd -d gimp-print -p Epson-Stylus_Photo_1290 > epson.ppdThese files (epson.ppd and epson.foo) are named for the physical printer, you don't have to use the long-winded name from the foomatic database. In fact, if you have two printers of the same type you can't use the same name; call them Laural and Hardy or something.
In the file epson.foo (or whatever yours is called) there are various samples of "postpipe" lines. For CPS local printing this line should be uncommented and set to:
$postpipe="| cat >$LPDDEV";Ignore the comment in the file to the effect that local printing does not need this, it does under CPS.
The files go into the directory
/etc/foomatic/directand are as usual owned by lp and chmod'ed 700.
Once the files are in place you should be able to type the line
LPDDEV='/dev/lp';echo "" | directomatic -P epson -o docsand get a printout of all the options your printer understands. Keep this.
In the directory '/etc' lives a file called printcap which has, since the early bronze age, defined the operating parameters of Unix printing systems. CPS uses this file but I've not bothered too much about keeping all the arcane options from older systems.
In brief, printcap consists of one entry per virtual printer, each such entry starts on a line with no leading spaces and continues to the end of the file or to the next line with no leading spaces (i.e., the next printer definition).
Each printer definition is divided into fields by colons (":") and a field may consist of a keyword or a keyword and a value (e.g., "sd=/var/spool/lpd/epson/"). The first field in a definition must be the virtual printer's name (with any aliases separated by a "|").
Definitions that go onto another line should have the previous line terminated with a "\" and the continuation must start with an indent of whitespace.
All lines starting with a "#" are discarded and ignored. In CPS the set of keywords is much smaller than the dozens understood by traditional systems:
Keyword | Purpose | Example |
---|---|---|
lp | The device that the physical printer is connected to. This is duplicated for each virtual printer which maps to the same actual printer. | /dev/usb/lp0 |
sd | The directory where jobs for this virtual printer
are spooled to. This should be the same for each virtual printer
on a particular real printer for clarity, although it does not have to
be.
Not used for remote printers. | /var/spool/lpd/epson/ |
rm | The name of the machine running the print spooler if printing is not done on this machine | beta.ourdomain.co.uk |
rp | The name of the virtual printer to use for a remote print job. | lino |
More will be added, in particular maximum job size and accounting data.
Here's an example:
#A Comment. grey:\ :sd=/var/spool/lpd/epson:\ :lp=/dev/lp: a3grey:sd=/var/spool/lpd/epson:lp=/dev/lp: a3bw|big:sd=/var/spool/lpd/epson:lp=/dev/lp: lp|colour:\ :sd=/var/spool/lpd/epson:\ :lp=/dev/lp: draft|bw:\ :sd=/var/spool/lpd/epson:\ :lp=/dev/lp: photo:\ :sd=/var/spool/lpd/epson:\ :lp=/dev/lp: #Final film setter photoset:\ :rm=ariel:\ :rp=deepthought:
Still as root make a directory called /var/spool/lpd/printername
for each physical printer on your system. These directories
should also be owned by lp. They should be globally writable and have
the sticky bit set (chmod 1777 Aside: The sticky bit is poorly documented (indeed, wrongly
documented) on many Linux systems. What it actually means is that
the owner of a directory is allowed to rename or remove any file
within it, regardless of the owner. They may still not change the
contents of files they do not own (unless they are root, of
course). The owners of the files within the directory have their
normal permissions but may not remove the directory itself (unless they are root, of
course).
If you want to simply have a single virtual printer running on a
single physical printer using all the default settings for that
printer then there are no further configuration files to create.
To create a virtual printer you first create the entry for the
virtual printer in printcap as described previously.
Next, using the printer documentation you printed out even more previously put
the options you want set for this printer and their values one line at
a time into a file called 'printername.options' in the spool directory
for the physical printer.
As an example here's the option file for my Stylus Photo when
called as the virtual printer 'draft' (by typing lpr -Pdraft):
This is stored in a file called "draft.options" in the directory
/var/spool/lpd/epson. Another example from the same directory, called
"photo.options" contains the options for printing high quality output
onto photo-quality paper:
As usual, these files should be owned by lp and only writable by lp
too, although everyone should be able to read them.
Normal users may also have these option files in their home
directory, where they are prefixed with ".", e.g., ".lp.options"
These override the values set in the spool
directory. Currently there is no restriction on what can be overridden
but there will be in future releases.
Unless you're the sort of person that clicks on every link you'll
now need to download the actual CPS
Perl files. Put them in /tmp and uncompress with
Make sure these files are executable and then, as root, change
their ownership to lp:lp and their flags to 755 except for lpd which
should be 700. Then move them to somewhere where they can be found by
everyone's PATH variable, such as /usr/local/bin/.
e.g., The final ownership change is to set the owner of the devices which
are connected to the printers as lp:lp. On most single printer systems
this involves typing "chown lp:lp /dev/lp".
The program 'lpd' should be started on the print server by the user
'root' with something like:
This can be arranged using a startup script which will feature in a
future release. I would also like a future release to run as the user
'lp' but I have not managed to get Perl to cooperate in this yet.
Note that lpd needs only to be installed on the machine doing the
actual printing; client machines do not need a copy of lpd.
The program 'lpr' sends jobs to a print queue and can be executed
by any user in the form:
If no file name is given then input is taken from standard input.
The print daemon (lpd) does not need to be running to queue local
print jobs, but a remote printer must have a listening daemon.
The program 'lprm' is used to remove items from a queue and is
invoked in the following way:
The printer daemon (lpd) does not need to be running for lprm to
work on local queues.
The program 'lpq' outputs a list of jobs currently in the queue of
a physical printer, with the currently printing job at the top
and the job at the back of the queue at the bottom of the list.
It is assumed that the user is interested in how long
it will be before a job is printed rather than just in what jobs are
being sent to a particular virtual printer. The virtual printer associated with each job is also listed. Other output
details are subject to change.
Samba is a system for sharing files and printers with Windows
machines on a local network.
CPS treats a Samba printer on a Windows machine in the same way
as any other local physical printer, i.e., it should have its own spool
directory and .foo file, and each mode that the printer can operate in is defined
using the virtual printer system in the same way as any other printer.
The 'lp' entry in /etc/printcap should contain the Samba path to
the printer, e.g., '//ourworkgroup/paulsmachine/bigbertha' to print to
a printer shared as "bigbertha" on a machine called "paulsmachine" in
the workgroup "ourworkgroup", which the print spooler should be a
member of.
The $postpipe line in the .foo file for this printer should be set
to
Printing from Windows to a CPS system is trivial, assuming that
samba is running on the print spooler. The printer being shared should
be listed as a postscript printer in the Samba configuration file.
First download the Adobe Generic
PostScript driver. Install this using the .ppd file for the
printer, generated by Foomatic.
If you don't have the generic PostScript driver then just install
it as a "Linotronic 100"; this usually works well for me.
Until the following items are dealt with CPS is in alpha release:
Until the following items are resolved CPS will not leave Beta:
The Coherent Printing Ssytem is copyright 2002 Thomas Worthington. Permission is given to
use the code in any way or to modify and reuse the code in any way
provided the result is not distributed under a name which abbreviates
to "CPS" without prior permission from the author.
This is the ALPHA release of CPS and very little attention
has been spent to security. I run the system in several locations, all
of which are behind firewalls and have a small number of trusted
users. If you are not at least behind a firewall which prevents
outside access to the LPD port (515), I don't think you should use
this or any other networked printing software on your machine(s).
You have been warned.
Printer Options
PageSize=A4
Quality=360sw
GSResolution=360x360DPI
ImageType=Photographs
OutputType=BlackAndWhite
Dither=Fast
PageSize=A4
Quality=1440x720sw
GSResolution=1440x720DPI
ImageType=Photographs
OutputType=Color
MediaType=Photo
Local Options
The Download
tar xzvf cps.tgz
This will create the files lpr, lpd, lprm, and lpq inside a directory
"cps", along with a copy of this documentation.
Ownership
chown lp:lp *
chmod 755 *
chmod 700 lpd
cp * /usr/local/bin/
LPD
lpd&
exit
LPR
lpr [-P <virtualprinter>] [-J|-T <jobname>] [-s] [-o <otheroption>...] [filename]
LPRM
lprm [-P <virtualprinter>] [jobnumber]
LPQ
lpq [-P <virtualprinter>]
Samba Printing
Linux to Windows
$postpipe='| smbspool smb:$LPDDEV '."$$ $< cpsJob 1 ''";
Most of the parameters in this line do nothing but smbspool fails on
me when they are left out.
Windows to Linux
To Do
Alphas
Betas
Others
Licence
Security Alert!