< Day Day Up > |
Printing ToolsYou already have some printing capability from the Terminal application's printing menu options and built in to the rest of your Mac OS X system. The command line, however, has its own printing facility, allowing you to direct the output of commands to a printer without having to select that output in the terminal and use the menu options to print. These command-line tools are actually fairly sophisticated, although they provide only a minimalist interface to the printing architecture. Print queuing, job-status notification, and print-job logging are all part of the standard Unix lpr printing system. Since Mac OS X 10.2, Mac OS X has included Common Unix Printing System (CUPS) software. This package includes versions of print commands traditionally found on BSD systems as well as versions of print commands traditionally found on System V machines. Mac OS X 10.1 and earlier include only versions of BSD print commands. If you are running Mac OS X 10.1 or earlier, you do not have all the commands listed in this section. The first command listed in each subsection is the BSD-compatible command, and the one that you can find in Mac OS X 10.2 as well as earlier versions. The second command listed in each subsection is the System V compatible command and is found only in the 10.2 and more recent distributions of Mac OS X. Sending Jobs to the Printer: lprThe command to send a job to the printer is lpr. Although there are a number of options to lpr, the most common forms that you will probably use are lpr <filename> lpr -P<printer> <filename> The first example sends <filename> to the system's default printer. The second example sends <filename> to an alternative printer named <printer>. If your system has more than one printer available to it at the command line, the second form might be of use. Note that there is no space between the -P and <printer>. This is an example of traditional lpr syntax, which we are mentioning in case you encounter it on another system. The lpr that ships with Mac OS X 10.2 documents a space between the -P and <printer>, but the traditional syntax also works. If you are using Mac OS X 10.0 or 10.1, the lpr that ships with it documents only the traditional syntax; however, the nontraditional syntax also works. You can send multiple jobs to the printer at once, and they will be queued and printed in sequence. The command provides no feedback other than a return to your prompt: brezup:ray testing $ lpr my-test brezup:ray testing $ Despite this, it's sent the file my-test off to be printed on my default printer. If I want to send the file to a printer other than my default printer, the -P <printername> option allows me to specify any printer configured on my system by name. Table 13.13 shows the syntax and important options for lpr.
The other command that you can use to send a job to the printer is lp. The syntax that you will most commonly use is similar to that of lpr, but supports a number of additional options: lp <filename> lp -d <printer> <filename> Here is a sample of the command in use: brezup:ray testing $ lp term-window-1.tiff request id is HP_Color_LaserJet_4550-4 (1 file(s)) Notice that the command responds by providing the job number, HP_Color_LaserJet_4550-4, in this case. The job number consists of the printer name and a number. Table 13.14 shows the syntax and important options for lp.
Checking the Print Queue: lpqBecause lpr provides no feedback other than a return to your prompt, you might sometimes find it useful to check the print queue to check on the status of your print job. The lpq command displays the print queue: brezup:ray testing $ lpq HP_Color_LaserJet_4550 is ready and printing Rank Owner Job File(s) Total Size active ray 4 term-window-1.tiff 921600 bytes This actually provides quite a bit of information. From the HP_Color_LaserJet_4550 line you get the printer's name. You might see anything here, depending on how the printer has been named. For example, you might even see location and printer model number. The output displays each print job on one line. In this example, there is only one print job. The line describing the print job includes a print job number and the filename, size, and owner. If multiple jobs were queued on the printer, however, each would be listed here, along with the job owner, making it convenient to track down who's hogging all the printer time! Table 13.15 is the command documentation table for lpq.
The other command that you can use to check the print queue is lpstat: brezup:ray testing $ lpstat HP_Color_LaserJet_4550-4 ray 1080320 Wed Jan 5 22:36:32 2005 The output of lpstat is similar to that of lpq. It includes the job number, owner, file size, and date. Table 13.16 shows the syntax and important options for lpstat.
Removing Printer Jobs: lprmIf you decide that you want like to remove a print job from the queue, use the lprm command. You might find it useful to use in conjunction with lpq. Here is an example of using lprm: brezup:sage Documents $ lpq _192_168_1_3 is ready and printing Rank Owner Job File(s) Total Size active sage 27 view8.tiff 472064 bytes 1st sage 28 view9.tiff 422912 bytes 2nd sage 29 view7.tiff 424960 bytes brezup:sage Documents $ lprm 28 brezup:sage Documents $ lpq _192_168_1_3 is ready and printing Rank Owner Job File(s) Total Size active sage 27 view8.tiff 472064 bytes 1st sage 29 view7.tiff 424960 bytes In this example, we used lpq to get a print job number and then used lprm to cancel a specific job number. Because this version of lprm does not provide feedback on the job cancellation, we again used lpq to verify the job's cancellation. Table 13.17 is the command documentation table for lprm.
The other command that you can use to remove a print job from the queue is cancel. Because the lp command provides the print job name when you issue the command, you might not necessarily need to check the queue. However, the cancel command does not provide output, so you might want to use cancel in conjunction with lpstat to verify the job cancellation, as shown in the following example: brezup:sage Documents $ lpstat _192_168_1_3-31 sage 424960 Wed Jan 5 22:38:54 2005 _192_168_1_3-32 sage 472064 Wed Jan 5 22:39:04 2005 _192_168_1_3-33 sage 422912 Wed Jan 5 22:39:11 2005 brezup:sage Documents $ cancel _192_168_1_3-32 brezup:sage Documents $ lpstat _192_168_1_3-31 sage 424960 Wed Jan 5 22:38:54 2005 _192_168_1_3-33 sage 422912 Wed Jan 5 22:39:11 2005 Table 13.18 is the command documentation table for cancel.
Controlling CUPS from the Command Line: lpoptions, lpadmin, lpinfoAlthough not strictly part of the command-line suite of printing tools, the CUPS system includes command-line management software that provides administration and control capabilities far beyond what is currently available from either Apple's Print Center or the CUPS web interface. The most important of these, lpadmin, lpoptions, and lpinfo, allow you to create, configure, examine, and delete printers that can be accessed through the standard command-line printing interface (lpr) and through GUI applications via the Print dialog. Configuring a CUPS Printer from the Command LineHere we will duplicate our example of adding a serial-port-based Apple ImageWriter printer that we used in Chapter 6, "Printer, Fax, and Font Management." It's assumed that the correct PPD file has been downloaded and placed in /usr/share/cups/model/, and that the foomatic-rip filter is installed in /usr/libexec/cups/filter/. The file type dummy back end shouldn't be needed, but it shouldn't hurt anything by being present either. (It's necessary for the GUI interface because it generates the list of valid device URIs from the output from the collection of backend scripts. If there isn't a file script, the GUI doesn't know that it can do file printing. But the CUPS printing system knows about file output innately, so the command-line tools simply believe whatever you tell them and don't look in the backend directory to determine what's available.)
In Chapter 6, we specified the printer as printer name test; gave it a location and description; picked a connection type for it; specified the device URI; and finally selected a PPD. These are exactly the same steps we'll take here, only we aren't going to take them on five separate web pages or via dialog box entries. Instead, all this goes onto a single command line.
Using the -p option to specify a printer that doesn't already exist causes lpadmin to create it. Using the -D option allows the provision of a description. The -L option allows the provision of a location. The -v specification of a device URI provides both the connection type and the specific connection location information. The -m option allows you to pick a PPD from the model directory, and, finally, the -E option enables the printer for access. The command needs to be run as root. lpadmin -p test_again -D "My ImageWriter Again" -L "Still in the Attic" -v file:/dev/tty .USA28X21P1.1 -m Imagewriter.ppd -E It might look a bit long, but it's really no more than a compound of what we did via the GUI into a single command. After executing this command, you could check your Print Center application, and you would see that a new printer had been added and activated. It will appear in the Print Center as My ImageWriter Again and be available from the command line as printer test_again. Writing Your Own Simple Printer Driver for CUPSAs a matter of fact, from the command line, we've got considerably more power available in configuring the printer. From the Apple Print Center interface and from the CUPS administration web pages, we have only basic options available as to how to get data to the printer. I actually had to cheat a tiny bit in constructing the Chapter 6 demonstration for how to use the Print Center and CUPS interface with my ImageWriter. My serial interface currently refuses to accept any sort of flow control, and it's much faster than my poor old ImageWriter. Because of this, on large pages and images, the end of the page gets garbled because the printer can't keep up with the data stream. I cheated by making a small modification to the foomatic-rip Perl script to throttle the speed down to something my printer can handle. Still, this is inelegant because I might have several printers that use the foomatic-rip filter, and I won't necessarily want to throttle them all down to ImageWriter speeds. The lpadmin command-line tool, however, gives me the option of saying "chuck all that automagic stuff; I'll run my printer myself, thank you very much," and allows me to specify a driver of my own creation. This comes at the cost of me having to write code to pass my data through Ghostscript (gs) for PostScript processing, if I want that functionality, and having to handle spooling the data to the printer myself. This isn't a particularly appealing portion of the operating system to be messing around with, but it's not that difficult either. And it means that if you have any command-line software that can be made to speak to your printer, you can use it as glue between your printer and the CUPS system. For example, although only a basic vestige of a print spooler, the following code works nicely for passing PostScript code through Ghostscript (a PostScript interpreter) to format it for my ImageWriter, and for spooling the data to the serial port slowly enough that it doesn't overrun the printer's buffer. #!/usr/local/bin/perl use Time::HiRes qw ( time alarm sleep ); $thispid = $$; open devfile, (">"."/dev/tty.USA28X1913P1.1"); while(<>) { $infile .= $_; } $tmppsname = "/tmp/tempps".$thispid.".ps"; $tmpprnname = "/tmp/tempprint".$thispid.".prn"; open temppsfile, (">".$tmppsname); print temppsfile $infile; close temppsfile; system "/usr/local/bin/gs -q -dNOPAUSE -dBATCH -sDEVICE=iwhi -sOutputFile=$tmpprnname $tmppsname"; open tempprnfile, ("<",$tmpprnname); while(read(tempprnfile,$line,128)) { print devfile $line; $line = "; sleep(.4); } close tmpprnfile; close devfile; system "rm -f $tmppsname"; system "rm -f $tmpprnname"; exit; If I've named it /usr/local/bin/myspooler.pl, I can load it up as the driver for a CUPS printer named testsomemore by using the command line: lpadmin -p testsomemore -D "Ye Olde Printer" -L "Cobweb City" -i /usr/local/bin/myspooler .pl -E The script isn't smart enough to handle data types other than PostScript, and some data streams have sections that still overrun the buffer even with a 0.4 second sleep embedded between every 128 characters (for example, the printer can't feed 128 blank lines in 0.4 seconds), but it's a solid beginning on which you could build a driver for any printer that you know how to access through the command line. If your serial interface (or other printing interface to which your printer is connected) handles flow control, you can safely do away with the makeshift sleep command and let the printer worry about pausing the interface when it needs time to catch up. Don't struggle too hard trying to understand what that code does right now. You'll learn everything you need to know to modify it for your purposes in Chapter 18, "Using Scripting Languages," in the section on Perl programming. For now, simply understand that it does the following:
This method (using -i scripts to process data) is unfortunately not entirely satisfactory for all users at this time because it appears that GUI printing does not always interact cleanly with printers specified in this fashion. The testsomemore printer created in the previous example is completely functional at the command line. Under some versions of Mac OS X, it's an apparent black hole for data printed by GUI applications. Under version 10.3 and later, it appears to work, but on versions on which it's a problem, GUI applications think that they're printing, but the printer spool never sees the data. I suspect that this is a symptom of some portion of the CUPS system being misconfigured on older versions of Mac OS X, and it deciding that the target printer does not know how to handle the data type output by the application (as in, CUPS doesn't understand that the printer can handle PostScript, and so trashes the printing job rather than passing it on to the printing script). Lack of documentation prevents a complete diagnosis and correction for 10.2 versions, but Apple seems to have corrected the problem in 10.3 and 10.4. If you wanted to extend a script like this to handle non-PostScript data, a possible solution would be to hack on a PPD like the Imagewriter.ppd file and on the foomatic-rip.pl script. Duplicating the foomatic-rip.pl script and adding the spooling functionality from this script should be fairly simple. Because foomatic-rip.pl already understands how to properly convert each input data format into PostScript for output, this is an easier solution than trying to write your own processing filters around the minimal spooler we've constructed here. A more complex printing script might not be so easy to integrate. We leave the investigation of both of these solutions to the creativity of the reader, should anyone other than myself be interested in whether a 1984 ImageWriter works with a 2005 Mac Mini while using a buggy serial driver that doesn't understand flow control. Although lpadmin is useful for creating and managing printers at the command line, lpoptions is useful for examining and setting print configurations. For example, lpoptions -d testsomemore sets the default printer for command line lp and lpr printing requests to the testsomemore printer configured in the previous example. This command does not affect the default printer for GUI printing. Finally, lpinfo is useful for querying the CUPS system about currently installed printing devices and drivers. lpinfo -m is particularly useful for determining the correct model information to hand to the -m option of the lpadmin command. The syntax and important options for lpadmin, lpoptions, and lpinfo are shown in Tables 13.19, 13.20, and 13.21, respectively.
|
< Day Day Up > |