Cover V06, I03
Article
Figure 1
Listing 1
Listing 2
Table 1
Table 2
Table 3
Table 4

mar97.tar


Supporting PostScript Printing Under System V

Tim Cera

PostScript is a widely adopted page description language within the printer market, providing extensive features for the printing of text and graphics, in either color or black and white. Within both the PC and Macintosh environments, a PostScript printer is configured with information from a PPD (PostScript Printer Description) file. In the UNIX realm, however, configuration of the printer can be handled by directly editing the print file, creating a shell script to insert the proper printer codes, or setting up the filter service to edit the print file on the fly. This article discusses how to configure features on a PostScript printer using System V print filters and supplies a rough overview of the System V print service. The computer for which these filters were developed is a SUN SPARCstation running Solaris 2.5.1.

The examples and the majority of the article focus on PostScript printing and printers, but the work described could be applied to other print languages. Specifically this article will show how to do the following:

  • create a printer that prints to a file (useful for debugging)

  • address issues with JetAdmin software, and NetPort print servers

  • create print filters that

  • choose the correct paper tray

  • change orientation

  • print to non-PostScript printers (using GhostScript)

  • print compressed files

    Postscript And Postscript Printer Description

    PostScript is a page description language developed by Adobe and used by many different computers and printers. Unfortunately, there is no uniform standard within the PostScript language to access printer specific functions like paper tray selection, orientation, and resolution. Adobe developed another system to standardize an interface to configure features for a particular printer. This interface is supplied with a PPD file. A PPD file is a text file that describes all of the potential features for a printer and a description for a user interface to choose those features. It also includes the PostScript code to activate the chosen functions.

    PPD files are usually developed by the printer manufacturer and sent with the printer. If not, there is a huge archive of PPD files available from Adobe (see Table 1). The DOS and Macintosh archives have some differences, so you may have to look in each one to find the PPD file you need. The PPD archives from Adobe are compressed for their respective platforms, so you will need access to an Internet-capable DOS or Macintosh computer to download the files, uncompress them (self-extracting on DOS; StuffIt and Binhex on Macintosh), then ftp the PPD files to the UNIX computer. If needed, I have included a short Perl script to change DOS or Macintosh formatted files to UNIX (see Listing 1).

    The PPD file format is arcane, so here are some general guidelines on what to look for. A detailed description can be found in the PPD specification document from Adobe (see Table 1). Keywords that start with *? can be ignored for our purposes, because they supply PostScript code that can query the printer about which options are installed or what the current default is set to. We are interested in the Postscript code that alters the printer's behavior. A small part of an example PPD file is shown in Listing 2. This is a snippet from the Adobe PPD specification document. If this were the PPD file for the printer and I wanted the paper to draw from the lower tray, I would insert 1 statusdict /setpapertray get exec after the first line in the PostScript file.

    After trying to figure out the PPD format from the specification document and looking at the PPD code, you can manually insert interesting PostScript code from the PPD file into a test print file. Print it and see if it does what you want. The PPD specification lists several requirements about where to insert the code from the PPD file in the PostScript file, but the only functional requirements are that the code is inserted after the first line in the PostScript file and before any other PostScript code. After you have found the PostScript code that activates a particular feature, you can create a filter to insert the code into the PostScript file when it is printed.

    The *LandscapeOrientation keyword in the PPD file tells the direction that you must rotate the page to change to landscape. Table 2 shows how the commands are affected. The units for page height and page width are in points (72 points to an inch). The actual code is not present in the PPD for rotating the page because it is about the only thing that is standard between printers.

    There are two other potential sources for acquiring the PostScript code. The first is that the activation code for the different options may be in the printer documentation. The second is to write your own PostScript code. This could be daunting or easy; it depends entirely on what documentation is available for your printer.

    System V Print Filters

    The basic process for setting up a System V printer is the following (or you could use whatever graphical interface comes with your system):

    lpsystem - (remote systems only) establish the computer that services the queue

    lpadmin - create and manage queues for both local and remote printers

    enable/disable - enable/disable queue

    accept/reject - accept/reject new print jobs

    lpfilter (optional) - list, create, modify, and delete filters

    System V print filters can be set up to perform many different tasks. An important step in understanding how the filters work is that they are chosen by the print service when a file is printed, so there is a chain of matching input and output types. Another way to envision this process is to think of the file to be printed, the print filters, and the printer as puzzle pieces that the print service fits together on the fly (see Figure 1).

    Filters can be made from any program that accepts standard input and writes to standard output. Because the print filters do not inherit any environment variables from the shell, it is necessary to use statically compiled programs. A potential way around this requirement is to put multiple lines in the filter command, but I advise that the filter program not rely on other programs or files on the system.

    A user accesses the filters, not by name, but by specifying a file content type. The print service uses the input file content type and the input/output types associated with a filter to choose the filters needed to get a correctly formatted file to the printer. The file content type is specified by the user and is not checked by the print service. A very nice improvement would be a file content determination similar to that which the file command uses, but for now, the user must specify the file content. The user must know what the file content is so that unfiltered PostScript is not sent to non-PostScript printers or other format mismatches. You can force a particular filter to only be used only for a particular printer, but a user can still identify the print file content incorrectly. I recommend both a paper and electronic document explaining the different content types, installed filters, and what can be printed to which printers. Table 3 shows the print commands to access the different features of the printers that are installed on my machine.

    There are several filters that come as part of the system (Solaris 2.5). One of the more useful ones is postprint. This is a text-to-PostScript formatted text filter. If you do not have postprint, the functionality can be found in mpage.

    The print filter system is managed with the lpfilter command, which lists or modifies existing filters and creates new filters.

    # list the characteristics of filter_name
    lpfilter -f filter_name -l
    
    # list the characteristics of all installed filters -
    # gives good examples of how to setup new filters
    lpfilter -f all -l
    
    # create or modify filter_name with the contents of
    # filter_description_file
    lpfilter -f filter_name -F filter_description_file

    The filter description file is a text file that contains the following lines:

    Input types: put_input_types_here
    Output types: put_output_types_here
    Printer types: put_printer_types_here
    Printers: put_printers_here
    Filter type: put_filter_type_here
    Command: put_command_to_be_run
    Options: put_options_here
    

    Example filter description files from my system are presented in Table 4. The word "any" is a valid type for input types, output types, printer types, and printers. Multiple types are separated by a comma. You can have multiple Options lines or none. I have not used the options lines, but that would allow parameters to be passed to the filter command to change its behavior. My scripts are not that complex yet, and I find it easier to just create a new filter than to add options. Example 6 in Table 4 illustrates the usage of the options lines.

    The most important fields in the filter description file are the "Input types:" and "Output types:" fields. The names entered in these fields define when and if the puzzle piece will be added when the print service chooses filters. For many of the filters, the "Printer types:" and "Printers:" fields are set to "any." This means that the filter can print to any printer type and any printer. You can confine the filter to print only to specific printer types (from termlib) or printers in order to have tighter control over the print process. As an example, the filter in Example 5 in Table 4 will only print to the "hplaser" printer. The "Filter type:" can be set to "fast" or "slow." The "fast" option implies direct connection and control over the printer, whereas the "slow" option will indicate that the filter process may take some time and require the creation of temporary files.

    To insert the PostScript code, you can use any text processing program, such as awk or Perl. Currently all my filters that insert code are based on awk, but this has a serious limitation in that only UNIX-formatted print files can be processed. I will likely move the filters to Perl and use a test similar to that in Listing 1 to evaluate the end of line character(s). If you look at the examples that use awk (Examples 1 and 2), the awk script will print each line and when the second record is reached will also print the PostScript code.

    The HP JetAdmin program is a very nice tool for setting up remote HP printers that use the JetDirect card. Part of the installation creates a print filter that must be changed if any other filter is used with that printer. This is because the input type is set to "any," which accepts all input types and therefore bypasses whatever filter you install. You should change the input type for the filter JetAdmin installs to "simple" and install any other filters for that printer you want with different input types (see Example 5 in Table 4).

    There is an excellent description on the Internet of how to set up System V printers with NetPort print servers that support lpr printing (see Table 1). You will also need the TCP/IP print manual that came with the NetPort. There is also a print utility that Intel sends with the NetPort, but it was not available for my UNIX.

    The lpfilter command is used to establish the input and output file types for each filter. The most important file content type is what the printer will accept. The printer file content type is set by the lpadmin command. An example would be something like lpadmin -p printername -I lj4,simple. This would set the content type for printername to be lj4 and simple.

    Testing and Debugging

    A useful tool for debugging the filters that you set up is being able to print to a file. The lp print service uses an interface program to control the queue and physical port where the printer is attached. Changing the interface program allows the print output to go to a file. The procedure is as follows:

    1. Create a file somewhere that makes sense to you and is in a permanent location. I put my new interface file at /usr/lib/lp/model/tofile. The file contains just two lines:

    #!/bin/sh
    /usr/bin/cat $6 > /tmp/printout.$$

    Set the ownership and permissions to match the standard interface file (mine is at /usr/lib/lp/model/standard).

    -r-xr-xr-x   1 lp     lp     26030 May  3  1996 standard*

    2. Use lpadmin to create the "tofile" printer. Set the port to be /dev/null and the interface file to be the program created in the step above. Enable the queue and accept print jobs.

    lpadmin -p tofile -v /dev/null -i /usr/lib/lp/model/tofile
    enable tofile
    accept tofile 

    To test your handiwork, you can now type lp -d tofile -T filter_name printfile and a file will be written to /tmp. You can look at this file to make sure that the intended changes did occur.

    Conclusion

    In this article I showed how to create, apply, and use System V print filters and provide a general overview of the System V print process. I presented some examples of filters that I use and showed how to set up the printer to accept different file type content. There is much room for improvement, and even within the context of the filters that I currently use, I would like to use Perl for more of the scripts and add options.

    About the Author

    Tim Cera works as a geographic information systems analyst and water resources engineer for Golder Associates, Inc., an international environmental engineering services company. His UNIX and system administration skills come from long nights trying to convince the computer to do what he wanted it to do. Outside of his day job, his family has not had a TV for a decade, which gives him time to do things like play with his son, take a walk, read a book, or write an article for Sys Admin.


     



  •