Linux tip: Printing DVI files with CUPS
Linux tip: Printing DVI files with CUPS
How to create a CUPS DVI print filter for Linux
Summary: Have you ever tried to print DVI or other files in Linux® and gotten an "unsupported format" message? This tip shows you how to combine existing tools to make a CUPS print filter for printing DVI files.
The Common UNIX Printing System (CUPS) is the print spooler used on many Linux and UNIX® systems today. You can use the filters provided with CUPS to format and print many types of files on a wide variety of printers. But what happens if CUPS doesn't support the kind of file you want to print? You can first convert the file to something that CUPS will print, such as PostScript or PDF. Or, you can create a filter so the CUPS printing system will recognize your file and print it correctly. This article, excerpted from the LPI exam 102 prep: Printing tutorial, shows you how to create a simple filter.
So how does CUPS determine the filter to use for formatting a particular file type? CUPS uses MIME (Multipurpose Internet Mail Extensions) types to determine the appropriate conversion filter when printing a file. Note that other printing packages may use the magic number mechanism as used by the file
command. See the man pages for file
or magic
for more details.
MIME types are used for transmitting various files as mail attachments. They consist of a type, such as text or image, and a subtype, such as html, postscript gif, or jpeg. The type and subtype are separated by a semicolon (;). Optional parameters may include information such as character set encoding or language. CUPS uses rules from /etc/cups/mime.types to determine the type of a file and then uses a suitable filter chosen from those listed in /etc/cups/conv.types for the given MIME type. MIME types are registered with IANA, the Internet Assigned Numbers Authority. If you need a type that is not registered, prefix the subtype with 'x-'. Some image type examples are shown in Listing 1.
Listing 1. Some MIME type entries from
/etc/cups/mime.types
image/gif gif string(0,GIF87a) string(0,GIF89a) image/png png string(0,<89>PNG) image/jpeg jpeg jpg jpe string(0,<FFD8FF>) &&\ (char(3,0xe0) char(3,0xe1) char(3,0xe2) char(3,0xe3)\ char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\ char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\ char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef)) image/tiff tiff tif string(0,MM) string(0,II) image/x-photocd pcd string(2048,PCD_IPI) image/x-portable-anymap pnm |
The format of the entries is beyond the scope of this article. Check the files /usr/share/mime/magic or /usr/share/file/magic for some insight on how the magic numbers are used to identify files.
Once the MIME type of a file has been determined, the correct filter is found using the /etc/cups/mime.convs file. Lines in this file have four entries: a source and destination MIME type, a cost, and the name of the filter. The least-cost filter is used. Some examples are shown in Listing 2.
Listing 2. Filter entries from
/etc/cups/mime.convs
text/plain application/postscript 33 texttops text/html application/postscript 33 texttops image/gif application/vnd.cups-postscript 66 imagetops image/png application/vnd.cups-postscript 66 imagetops image/jpeg application/vnd.cups-postscript 66 imagetops image/tiff application/vnd.cups-postscript 66 imagetops image/x-bitmap application/vnd.cups-postscript 66 imagetops |
If a suitable filter cannot be found, your attempt to print a file will result in an error message. If you are using a printer daemon other than CUPS, you may get unexpected output instead. Listing 3 shows how this works with a DVI file (the normal output from TeX and LaTex).
Listing 3. Printing an unsupported file type
[ian@attic4 ~]$ lpr samp1.dvi lpr: Unsupported format 'application/octet-stream'! |
A DVI filter for CUPS printing
Fortunately, the tetex package that provides TeX and LaTeX also provides a
conversion utility, dvips
, to convert from DVI to
PostScript. Unfortunately, it won't work as a filter because it does not know how
to handle the arguments that a CUPS filter must handle, namely, job id, user, job
title, number of copies, and job options. The first filter in a filter pipeline
will also have an additional parameter, the filename, if the input comes from a
file.
The solution is to create a wrapper script that will be the filter. The
dvips
command does not accept input from stdin, so the
script may need to create a temporary file and copy stdin to that file before
calling dvips
. A possible script is shown in Listing 4.
Listing 4. A CUPS DVI to PostScript filter script
#!/bin/bash # CUPS filter to process DVI files using dvips # Create a sandbox for working if input on stdin if [ $# -lt 6 ]; then sandbox=${TMPDIR-/tmp}/cups-dvitops.$$ (umask 077 && mkdir $sandbox) || { echo "Cannot create temporary directory! Exiting." 1>&2 exit 1 } fn="$sandbox/cups-dvitops.$$" cat > "$fn" else fn="$6" fi # Call dvips quietly, securely and with output to stdout dvips -R -q -o - "$fn" # Erase sandbox if we created one if [ $# -lt 6 ]; then rm -rf "$sandbox" fi |
Recall that CUPS uses two files in /etc/cups to determine the MIME type and filter to use. These files will be overwritten whenever you reinstall or upgrade CUPS. Fortunately, CUPS will read all files with an extension of .types or .convs whenever it starts or restarts. So you should create a pair of files for your new filter, for example /etc/cups/dvitops.types and /etc/cups/dvitops.convs. Listing 5 shows the two configuration files for the DVI filter.
Listing 5. Configuration files for CUPS dvitops
filter
[ian@attic4 ~]$ cat /etc/cups/dvitops.types # Local MIME definition for DVI files application/x-dvi dvi string(0,<F702>) [ian@attic4 ~]$ cat /etc/cups/dvitops.convs # Local DVI to PostScript filter for CUPS application/x-dvi application/postscript 50 dvitops |
Listing 5 says that DVI files are identified by having the hexadecimal digits F7 and 02 in the first two positions and that such files should be processed by the dvitops filter.
Next, as root, copy the script above in /usr/lib/cups/filter/dvitops, and make
sure it is world readable and executable (-rwxr-xr-x). The name you give the
script must match that in the /etc/cups/dvitops.convs file above. If you are
running SELinux in enforcing mode, you should also run
restorecon
in the /usr/lib/cups/filter directory to
update the security contexts. Otherwise, your lpr
command will appear to work, but your file will not print.
Finally, use the restart option with the cups script located in /etc/rc.d/init.d or /etc/init.d, to restart CUPS and use your new filter.
If you are using an older print spooler, you will probably use either the magicfilter or apsfilter as input filters to convert various input files to PostScript format for printing to a PostScript printer or, using Ghostscript, to a non-PostScript printer.
If you'd like to know more about printing in Linux, read LPI exam 102 prep: Printing tutorial, from which this article was excerpted, or see the other Resources below. Don't forget to rate this page.
Learn
-
CUPS: Common UNIX Printing System
(Sams, 2001) is a detailed reference for CUPS.
-
The Printer Working Group of the IEEE Industry
Standards and Technology Organization (IEEE-ISTO) develops standards that make
printers -- and the applications and operating systems supporting them -- work
better together.
-
Review the
LPI
exam 102 prep: Printing tutorial
for more information on printing in Linux. It is part of a larger
LPI exam prep tutorial series
covering Linux fundamentals and preparing you for system administrator
certification.
-
Find more
tutorials
for Linux developers
in the
developerWorks Linux
zone.
- Stay current with
developerWorks technical events and webcasts.
Get products and technologies
-
Order the SEK for Linux,
a two-DVD set containing the latest IBM trial software for Linux from DB2®,
Lotus®, Rational®, Tivoli®, and WebSphere®.
- Download
IBM trial software
directly from developerWorks.
Discuss
- Participate in the discussion forum.
- Read
developerWorks
blogs,
and get involved in the developerWorks community.

Ian Shields works on a multitude of Linux projects for the developerWorks Linux zone. He is a Senior Programmer at IBM at the Research Triangle Park, NC. He joined IBM in Canberra, Australia, as a Systems Engineer in 1973, and has since worked on communications systems and pervasive computing in Montreal, Canada, and RTP, NC. He has several patents and has published several papers. His undergraduate degree is in pure mathematics and philosophy from the Australian National University. He has an M.S. and Ph.D. in computer science from North Carolina State University. Learn more about Ian in in Ian's profile on My developerWorks.
链接地址:http://www.ibm.com/developerworks/linux/library/l-dvi-filter/index.html