Hooking Postscript data from Cups Driver in Mac OS X
The aim of this document is to detail how to hook the print data using CUPS printer driver framework in Mac OS X operating system.
Introduction TO CUPS
The Common Unix Printing System (CUPS) is a modular printing subsystem for Unix like operating systems that allows a computer to act as a powerful print server. A computer running CUPS is a host which can accept print jobs from client computers which may be UNIX or Windows or something else, process them, and send them to the appropriate printer.
CUPS consists of a print spooler and print job scheduler, a filter system that converts the print data to a format that the printer will understand, and a backend system that sends this data to the print device. CUPS uses the Internet Printing Protocol (IPP) as the basis for managing print jobs and queues. The device drivers CUPS supplies can be configured by using Adobe's Postscript Printers Description (PPD) files which are simple plain text files.
CUPS Overview
CUPS provides a mechanism that allows print jobs to be sent to printers in a standard fashion. The data is sent to a scheduler, which sends jobs to a filter system that converts the print job into a format the printer will understand. The filter system then passes the data on to a backend-a special filter that sends print data to a device or network connection.
Jobs
Each file or set of files that is submitted for printing is called a job. Jobs are identified by a unique number starting at 1 and are assigned to a particular destination, usually a printer. Jobs can also have options associated with them such as media size, number of copies, and priority.
Classes
CUPS supports collections of printers known as classes. Jobs sent to a class are forwarded to the first available printer in the class.
Filters
Filters allow a user or application to print many types of files without extra effort. Print jobs sent to a CUPS server are filtered before sending them to a printer. Some filters convert job files to different formats like PCL/PS that the printer can understand. Others perform page selection, page counting and ordering tasks.
Backends
Backends perform the most important task of all - they send the filtered print data to the printer.
CUPS provides backends for printing using Line Printer Daemon (LPD) protocols. Backends are also used to determine the available devices. On startup each backend is asked for a list of devices it supports, and any information that is available.
System Architecture
When print is given via CUPS printer, print data will be prepared in a file and sent to spooler queue. From the spooler queue, files are sent to the filter layer one by one.
In Filter process print data is converted to PS/PCL/any other format. Filters are taking input from Printer Description files (.ppd). The PS/PCL file will be sent to Backend.
Backend is a module that sends the print data to the printer.
For an example, if we write a filter that will be attached to a postscript printer, the document will be provided to the filter as input (stdin) and the postscript content can be extracted from the input document. To print this postscript file, we have functions provided by the CUPS framework.
Procedure for Installing A Postscript Printer Driver
We have a configuration file for Virtual Printer Driver. In that we will be storing the following informations
- Location of the output Postscript file
- Location of the output Log files
We have to copy the configuration file virtualprinter.conf to /etc/cups directory.
By default in MAC OS X cupsd.conf file will be available in /etc/cups directory along with cups driver. This configuration file is for the cups daemon cupsd, which manages the printer and print jobs.
In order to hook the data from printer driver we have a cups backend executable. That will be stored in /usr/libexec/cups/backend directory.
In backend code we will hook the print data through port monitor which will send the output postscript file to printer.
After installing these files we have restart the cupsd daemon.
In the directory /etc/cups we have printers.conf files containing the list of printers.
printers.conf file contains the list of installed printers.
To see the list of installed printers in the system, go to System preferences... menu . Choose Print/Fax button. This will show a dialog with list of printers installed in the system.
Click in + symbol available for adding printer.
When we press on + button, Generic.ppd file will be installed (or) copied from the path.
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ FrameWorks/PrintCore.framework/Resources/English.lproj/ to /etc/cups/ppd
There are some more ways of adding printers to the CUPS framework:
- Using lpadmin utility
- Using the CUPS web interface through HTTP port 631
Programming References
Code snippet for VirtualPrinter.conf file.
Out is the Key word for specifying the output path of Postscript file. In this example we specified /var/spool/cupsps/${USER} as a path for storing postscript files.
Log is the Key word for specifying the path for storing error log information.
In this example we specified /var/log/cups as a path for storing log informations.
LogType is the Keyword to specify log information type. If LogType is 1, error will be logged. If it is 2 normal status will be logged. If it is 4 all Debug output will be logged in log file. If 7 is specified all types of error informations will be logged in log file in the path /var/log/cups.
Code Snippet for Hooking postscript data using Backend
Here Postscript data will come as input to the backend filter program.
Normally Postscript data starts like %!PS-Adobe-3.0. So we are started copying data from "%!" entry. Until we get "%!" entry we are just keep on reading the stream file. Once we got "%!" entry we are storing lines one by one in Postscript output file.
"%%EOF" is the end of Postscript data. After getting "%%EOF" we are closing the Postscript output file. If we need to convert the postscript file into PDF is it possible by the use of filter "pstopdf" available in /usr/bin directory.
Postscript PRINTER DESCRIPTION FILE (PPD)
PostScript Printer Description (PPD) files are created by vendors to describe the entire set of features and capabilities available for their Postscript printers.A PPD also contains the PostScript code (commands) used to invoke features for the print job. As such, PPDs function as drivers for all PostScript printers, by providing a unified interface for the printer's capabilities and features. For example, a generic PPD file for all models of HP Color LaserJet contains:
which specifies that the printer understands PostScript language Level 3, is a color device, and so forth. The PPD can describe allowable paper sizes, memory configurations, the minimum font set for the printer, and even specify a tree-based user interface for printer-specific configuration.
If we copy this ppd file into /etc/cups/ppd directory then printer will get added in printers list and ready to print documents.
Then we should open the printer browser dialog containing the list of available printers. There we can add a Printer for the ppd file to the printer list.
Then open any document and give print via the installed printer . When print job is given Postscript file will be stored in /var/spool/${User} directory.
Important Cups API's
If we need to print ps file, CUPS provides functions like cupsPrintFile() and cupsPrintFiles() for this purpose
Getting the Available Printers and Classes
The cupsGetDests() function can be used to get a list of the available printers, classes, and instances that a user has defined:
Each destination is stored in a cups_dest_t structure which defines the printer or class name, the instance name (if any), if it is the default destination, and the default options the user has defined for the destination
The destinations are sorted by name and instance for your convenience. Once you have the list of available destinations, you can lookup a specific destination using the cupsGetDest() function
The name string is the printer or class name. You can pass a value of NULL to get the default destination.
The instance string is the user-defined instance name. Pass NULL to select the default instance, e.g. "name" instead of "name/instance".
These are some of the functions available with cups by default.
Conclusion
As mentioned above in this document, we can create a Virtual Printer Driver using CUPS to hook postscript print data and store it in a file. Also, if we need some changes in the available print data we can edit PS/PCL file and print using functions available in Mac OS X by default.
References

