This is a Printing-HOWTO
written by me. It was originally a short note, to remind myself of the complicated configuration of printing. Then it became longer and longer, until it finally came to this Linux Printing HOWTO
.
This article introduces the samba - LPRng - ifhp filter - ghostscript uniprint driver
printing model. If you are using other printing packages, the setting procedure may be different.
I am the only author of this article. It was not authorized by, nor disscussed with any of these package authors. It is not an official documentation of any package. If you find any bias, error or deficiency, please mail to me. Thanks.
If you share this printer only for your windows workstations, or if you are setting a print server for a windows-only network, that you does not really need linux printing, just follow these steps. If you are really setting a linux printing
, wanting to print under linux, or if you want to know more about linux printing model, bypass these part.
Connect your printer to LPT1 and do the following test:
% echo "Hello, world!" >> /dev/lp0
Your printer should start working. Eject the paper and see if Hello, world!
is properly printed. If it is, proceed to the next step. [1]
% tar xzf LPRng-x.x.x.tgz % cd LPRng-3.x.x % ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man --disable-setuid % make % make test % su $ make install
# simpliest printcap file for samba client only lp: :lp=/dev/lp0 :sd=/var/spool/lpd/%P
Your printer should start working. Eject the paper and see if$ checkpc -f $ echo "Hello, world!" | lpr
Hello, world!is properly print. If it is, go to next step. [24]
Remember to create the directory /var/spool/lpd/samba, with its owner as root and its permission as 1777.[printers] comment = Printers printable = yes browsable = no public = no valid users = @users printing = lprng path = /var/spool/lpd/samba print command = /usr/bin/lpr -P%p -r %s lpq command = /usr/bin/lpq -P%p lprm command = /usr/bin/lprm -P%p %j lppause command = /usr/sbin/lpc hold %p %j lpresume command = /usr/sbin/lpc release %p %j queuepause command = /usr/sbin/lpc -P%p stop queueresume command = /usr/sbin/lpc -P%p start
If everything is fine, restart your samba. Now you should go back to your windows workstation and reload your network neighborhood. Can you see the printer now? [26]$ /usr/local/samba/bin/testparm
Please refer the windows help and your printer manual for setting your remote printer on your windows workstation. Remember to print a test page to see if everything is OK. [27]
The basic steps of linux printing are stated below:
The dash lines are the path of the Windows/samba printing.
We go bottom-up, step by step:
Connect your printer to LPT1 and do the following test:
% echo "Hello, world!" >> /dev/lp0
Your printer should start working. Eject the paper and see if Hello, world!
is properly printed. If it is, proceed to the next step. [1]
After you have properly connected your printer and been able to print simple English text directly, we want to print some PostScript documents. If you have a PostScript printer, (which, the, means that you are very rich, or your printer might be owned by the company or the school,) and you can print PostScript documents directly, you can bypass here and proceed to the next step.
PostScript is the standard printing document format set up by Adobe, inc. at 1985. It is supported by most laser printers. But I guess yours is a cheap and poor inkjet or dot-matrix printer, so we move on.
Ghostscript is a PostScript emulator. With software emulation, it turns a non-PostScript printer to a PostScript printer and print the PostScript format documents. By doing this way, our cheap and poor inkjet printer can then be treated as a deluxe PostScript laser printer. [3]
Ghostscript translates PostScript language into all kinds of low-level printer language. The translated result is then sent to the printer. Ghostscripts needs to know all kinds of low-level printer languages, which are the so-called printer drivers
. Ghostscript is released with a bunch of printer drivers. But if your printer driver is not inside, you could look for it in the LinuxPrinting printer database and see if someone had written a Ghostscript driver for your printer before. You can then download and ultilize it. You’ll have to recompile Ghostscript unless it is a uniprint driver.
Uniprint (Unified Printer Drivers) is a Ghostscript printer driver specification that was originally designed for the Epson Stylus Color printers. It can be downloaded and used directly without recompiling Ghostscript itself. Uniprint drivers have an .upp file name suffix. [4]
Edit the Makefile and modify the installation prefix:% tar xzf gnu-gs-6.52.tar.gz or ghostscript-x.xx.tar.gz % cd gsx.xx % ln -s src/unix-gcc.mak Makefile
Runprefix = /usr
makenow:
Then, go to /usr/share/ghostscript/ and uncompress the Ghostscript fonts:% make % make test % su $ make install
$ cd /usr/share/ghostscript/ $ tar xzf ghostscript-fonts-std-x.x.tar.gz $ tar xzf ghostscript-fonts-other-x.x.tar.gz
where xxxxxxxx is your printer model. For unprint,$ cd /usr/share/ghostscript/x.xx/examples/ $ gs -sDEVICE=xxxxxxxx -sOutputFile=/dev/lp0 tiger.ps
where xxxxxxxx.upp is the file name of your uniprint driver. If Ghostscript could read your printer driver, it shall print a giant tiger now. [7] You could put this line as an alias in your ~/.bashrc:$ cd /usr/share/ghostscript/x.xx/examples/ $ gs @xxxxxxxx.upp -sOutputFile=/dev/lp0 tiger.ps
alias gs="gs -sDEVICE=xxxxxxxx -sOutputFile=/dev/lp0"
Now you can print the PostScript documents. If you have a non-PostScript document, you can convert it into PostScript format and print it. There are plenty of PostScript converters for all the existing different file formats. Their installation procedures are rather simple, so I’ll omit them here. Some of the common PostScript converters are listed below:
Don’t forget to test if you can print the converted PostScript results after you install these converters.
$ echo "Hello, world" | a2ps -o - | gs - $ html2ps < /usr/local/apache/htdocs/index.html | gs - $ gs mypdf.pdf $ giftopnm < mygif.gif | pnmtops | gs - $ jpegtopnm < myjpeg.jpg | pnmtops | gs - $ pngtopnm < mypng.png | pnmtops | gs - $ bmptoppm < mybmp.bmp | pnmtops | gs - $ tifftopnm < mytiff.tif | pnmtops | gs - $ ...
From this point on, you could print any file, as long as you can convert it into PostScript format with a proper PostScript converter. We can finally print files now.
The ability to print files is not enough. For every file we print, we need a different converter. We convert this file here, and convert that file there, here and there, here and there… It’s so troublesome! We need an intelligent agent to automatically check the file type and call the necessary converter. This, is the so-called print filter
. The basic of the print filter is very simple. You can try to write one, too, after reading the following illustrations.
There are many existing filters. Some of the common ones are: lpdomatic (LPD-O-Matic) [12], tops, magicfilter [13], apsfilter [14] and rhs-printfilters [15]. ifhp is the print filter I’m using, and it is written by the LPRng team themselves, so I use it in the following illustration.
% tar xzf ifhp-x.x.x.tgz % cd ifhp-x.x.x % ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man % make % make test % su $ make install
where xxxxxxxx.upp is the file name of your downloaded uniprint driver. By configuring this way, ifhp can locate your printer settings by the printer name.[ xxxxxxxx.upp ] status pjl@ pcl@ ps@ text gs_converter= \%s{gs_unidriver} gs_device=xxxxxxxx.upp
where \%s{string} will be replace with the previous string= settings. When it comes to print, ifhp will call /usr/bin/file to check the file type. The returned result string will be compared with these patterns, and execute the command at the right side for the matching pattern at the left side. If there’s no more command at the right side for that matching left-side pattern, the data will be treated as the final converted result and sent to the printer directly. For example,file_output_match = [ *postscript* raw \%s{gs_converter} *text* text [16] *01-* text *pcl* filter \%s{pcl_converter} *pjl* filter \%s{pjl_converter} *html* filter \%s{html_converter} *pdf* raw \%s{pdf_converter} *37)* raw \%s{pdf_converter} *jpeg* filter \%s{jpeg_converter} *gif* filter \%s{gif_converter} *png* filter \%s{png_converter} *pc_bitmap* filter \%s{bmp_converter} *tiff* filter \%s{tiff_converter} *gzip_compressed* filter \%s{gzip_decompress} *data* raw ]
% file myphoto.jpg myphoto.jpg: JPEG image data, JFIF standard
JPEG image data, JFIF standardmatches
*jpeg*(case insensitive), so ifhp will call jpeg_converter. You could design your own pattern according to the result string returned by the file command.
ifhp will execute these commands with I/O pipping: send the source data to their stdin, and obtain their converted result from their stdout.html_converter= /usr/bin/html2ps 2>/dev/null pdf_converter= \%s{gs_converter} jpeg_converter= /usr/bin/jpegtopnm | /usr/bin/pnmtops -noturn[18] gif_converter= /usr/bin/giftopnm | /usr/bin/pnmtops -noturn[19] png_converter= /usr/bin/pngtopnm | /usr/bin/pnmtops -noturn bmp_converter= /usr/bin/bmptoppm | /usr/bin/pnmtops -noturn tiff_converter= /usr/bin/tifftopnm | /usr/bin/pnmtops -noturn
If it is properly printed, your ifhp is ready. [20] We have come to an end at this point. Now we have an intelligent printing program that can print all kinds of files now. You can put the above line in your ~/.bashrc as an alias:$ /usr/libexec/filters/ifhp -Tdev=/dev/lp0,model=xxxxxxxx < /tmp/myfile
You can have yourself a cup of coffee and take a rest now. ^_*'alias ifhp="/usr/libexec/filters/ifhp -Tdev=/dev/lp0,model=xxxxxxxx"
We finally have ifhp, an intelligent print filter that can automatically assign the data conversion by file type, and send the finally output to the printer. With this ifhp we could print almost anything. Is that all?
Not yet. What we need is far more complicated than a simple printing
. We need a set of printer management
: Queue the files in a line when several files are printed at the same time, put the important files first in the line, or stop printing when the paper is jamed. Besides, the permission of /dev/lp0 is 0660. It’s not a good idea to grant everyone the privilege to write to /dev/lp0 directly. [21]
That’s why we need LPRng, the printer manager, to manage all the print jobs.
% tar xzf LPRng-x.x.x.tgz % cd LPRng-x.x.x % ./configure --prefix=/usr --sysconfdir=/etc --mandir=/usr/share/man --disable-setuid [22] % make % make test % su $ make install
%P will be replaced with the printer name, which is the lp: here on the first line. You could change it to a more meaningful name, like hpdj670c or so. The value of :sd= is the print queue directory. Be sure to create this directory if it does not exist. It should be owned by root with permission 1777, like the /tmp directory.# printcap file for ifhp filter with Ghostprint uniprint driver lp: :lp=/dev/lp0 :sd=/var/spool/lpd/%P :ifhp=model=xxxxxxxx :filter=/usr/libexec/filters/ifhp
If this printer is provided to a limited number of people, we can loosen the privilege to ease the management. Comment out the line# Reject outsiders by IP. The format is IP or IP/submask REJECT SERVICE=X NOT REMOTEIP=127.0.0.1,192.168.0.0/255.255.0.0 # Reject outsiders by domain. REJECT REMOTEHOST=X NOT REMOTEIP=localhost,*.your.domain
ACCEPT SERVICE=C LPC=lpd,status,printcap, and replace with the following one:
Also, you need to allow the administrator the priviledge to remove the broken print jobs. Locate the line# Loosen the priviledge. Let users pause/resume their print job. #ACCEPT SERVICE=C LPC=lpd,status,printcap ACCEPT SERVICE=C LPC=lpd,status,printcap,hold,release,stop,start REMOTEGROUP=users
ACCEPT SERVICE=M SERVER REMOTEUSER=root:
# allow root on server to remove a job ACCEPT SERVICE=M SERVER REMOTEUSER=root ACCEPT SERVICE=M SERVER REMOTEGROUP=lp
checkpc -f will check the settings in /etc/printcap for problems, such as non-existing :sd= directory, and correct them at its best. Then, ask lpd to reread the /etc/printcap.$ checkpc -f
Now print the /tmp/myfile again:$ lpc reread
If it is properly printed, congratulations! Everything is ready now. ^_*' [24]% lpr /tmp/myfile
Refer to LPRng-HOWTO for more infomation on how to manage the print jobs with lpr, lprm, lpc, lpq… etc.
You can bypass the following if you are not going to share this printer for your windows workstations.
Don’t forget to create the directory /var/spool/lpd/samba. It should be owned by root, with privilege 1777.[printers] comment = Printers printable = yes browsable = no public = no valid users = @users printing = lprng path = /var/spool/lpd/samba print command = /usr/bin/lpr -P%p -r %s lpq command = /usr/bin/lpq -P%p lprm command = /usr/bin/lprm -P%p %j lppause command = /usr/sbin/lpc hold %p %j lpresume command = /usr/sbin/lpc release %p %j queuepause command = /usr/sbin/lpc -P%p stop queueresume command = /usr/sbin/lpc -P%p start
If everything is fine, restart your samba. Now you should go back to your windows workstation and refresh your network neighborhood. Can you see this printer now? [26]% /usr/local/samba/bin/testparm
Refer to the windows help and your printer’s installation guide. Don’t forget to print a test page and see if it works. [27]
Hellp, world, check the following by order:
(Back)*text* filter \%s{a2ps_converter}
(Back)jpeg_converter= /usr/bin/imgtops2
We need to exit 0 because gif2ps exits an error code even for non-critical warnings, which leads ifhp to believe that the conversion was failed and to stop printing. (Back)gif_converter= /usr/bin/gif2ps; exit 0
Run#! /bin/sh file=/tmp/myfile ifhp=model=xxxxxxxx cat /dev/null >/tmp/t cat $file | /usr/libexec/filters/ifhp -Tdev=/tmp/t,trace,debug=2,${ifhp} 2> /tmp/trace
Review /tmp/trace and see what went wrong. You can enlarge the debug= value (for ex., debug=10) for more detailed debugging infomation. (Back)$ sh -x /tmp/send
spooling.
Spoolingis means to line up in a queue. When jobs may not be run instantly for various reasons (for ex., speed difference, communication problem, disconnection, unstable connection or insufficient memory… etc.) they have to line up in a queue first to wait for their turns. When this happens, you need a queue manager to manage the queue, set its order, pause the queue, or even delete a job from the queue. Mail transference need spooling, too, because it sends messages across different hosts from distance. In fact, the communications between the components of your computer (CD-ROM, floppy, hard disk, memory… etc.) needs spooling, too. But you won’t feel them because they are silently dealed by the internal spooler system. (Back)
automaticfilters, like apsfilter or rhs-printfilters, you can bypass this part and set up your filter now. (Back)
to check the printer logs. If this still doesn’t help, refer to the LPRng HOWTO for more infomation. (Back)% lpq -L
Refer to the following addresses for more infomation:
libgif, but
libungif? Read the following story: The GIF Controversy: A Software Developer’s Perspective