|   | 
   For common configurations, you can probably ignore this section
   entirely - instead, you should jump straight to Section 9 below, or better yet, your vendor's
   documentation.  Most Linux distributions supply one or more
   "idiot-proof" tools to do everything described here for common
   printers.
      If your vendor's tool doesn't work out for you, or you'd like the
   ability to interactively control printing options when you print,
   then you should use some other system.  PDQ is a good choice; it
   provides very good functionality and is easy to setup.  APS Filter
   is another good system; it configures LPD queues and filters very
   easily on most any sort of Unix system.
      You can also use the printing system interfaces from the Linux Printing Website
   to connect many free drivers into several spooling systems.  Once
   this project is complete, these interfaces will offer the best
   functionality: all styles of free software drivers are supported,
   user-settable options are available, and most common spooling
   systems are supported.
       PDQ can be configured by either the superuser or by a joeuser.
    Root's changes are made to /etc/printrc, and
    affect everyone, while joeuser can only modify his personal
    .printrc.  Everything applies to both types
    of configuration.
        If PDQ is not available prepackaged for your distribution, you
    should obtain the source distribution from the PDQ web page and
    compile it yourself.  It is an easy compile, but you must first be
    sure to have installed the various GTK development library
    packages, the C library development package, the gcc compiler,
    make, and possibly a few other development things.
         PDQ lets users select a printer to print to.  A printer is
     defined in PDQ as the combination of a "driver" and an
     "interface".  Both drivers and interfaces are, in fact, merely
     snippets of text in the PDQ configuration file.
          A PDQ interface says everything about how to ship data out to a
     printer.  The most common interfaces, which are predefined in the
     PDQ distribution's example printrc file, are:
      - local-port
 A local port interface speaks to a parallel or serial
         port on the machine PDQ is running on.  Using this interface,
         PDQ can print directly to your parallel port.  Note that if
         you have a multiuser system this can cause confusion, and if
         you have a network the local-port interface will only apply
         to one system.  In those cases, you can define a raw
         unfiltered lpd queue for the port and print to the system's
         lpd daemon exactly the same way from all systems and accounts
         without any troubles.  This interface has a device name
         argument; the typical value would be
         /dev/lp0.
         - bsd-lpd
 A bsd lpd interface speaks over the network to an LPD
         daemon or LPD-speaking networked printer.  PDQ supports job
         submission, cancellation, and queries to LPD interfaces.
         This interface has hostname and queuename arguments.
         - appletalk
 The appletalk interface allows you to print to printers
         over the Appletalk network; if you have a printer plugged
         into your Mac this is the way to go.  This interface needs to
         have the Netatalk package installed to work.
         
  
         A PDQ driver says everything about how to massage print data into
     a format that a particular printer can handle.  For Postscript
     printers, this will include conversion from ascii into
     Postscript; for non-Postscript printers this will include
     conversion from Postscript into the printer's language with
     Ghostscript.
          If one of PDQ's included driver specifications doesn't fit your
     printer, then read the section below on how to write your own.
          To define a printer in PDQ:
      First check that you've got suitable driver and interface
        declarations in the system or your personal printrc.
        If you want to define the printer in
        /etc/printrc (for all users), then su to
        root.
        Run xpdq, and select Printer->Add
        printer.  This "wizard" will walk you through the selection of
        a driver and interface.
        
 
     That's really all there is to it; most of the work lies in
     finding or creating a suitable driver specification if you can't
     find one premade.
          Here I'll walk through an example of how to make a PDQ driver
     declaration.  Before you try that, though, there are several
     places to look for existing driver specs:
      PDQ itself comes with a collection of prewritten driver
        files.
        The Linux Printing Website's database includes a program called "PDQ-O-Matic"
        which will generate a PDQ specification from the information
        in the database.  Assuming that the database contains the
        proper information for your printer and driver, this is the
        best path if you have a non-Postscript printer.
        I've written a tool called ppdtopdq which takes a Postscript Printer
        Definition file and converts it into a PDQ driver
        specification, with about 75% success.  This is an option if
        you have a Postscript printer.
         
         There are several places to look for the information needed to
     write your own PDQ driver:
      The PDQ driver specification syntax is quite rich, and is
        fully documented in the printrc(5) man page.
                The PDQ distribution includes a few example files.  Look in
        particular at the Epson Stylus file, which demonstrates the
        structure of the definition for a Ghostscript-driven printer.
        The Printing HOWTO Database includes raw Linux driver
        information for over 600 printers.  This will tell you what
        options to give Ghostscript, or what extra program to
        run on the Ghostscript output.
         
         If you have to create your own driver specification, or if you
     enhance one from the PDQ distribution or one of the PDQ driver
     generator programs mentioned above, please share your creation
     with the world!  Send it to me (gtaylor+pht@picante.com), and I'll make sure
     that it gets found by future PDQ users with your type of printer.
          Now, let's walk through the writing of a driver specification for
     a printer listed in the Printing HOWTO's database as working, but
     for which you can't find a PDQ driver spec.  I'll use the Canon
     BJC-210 as the example printer.
          First, we look at the database entry for this printer.  Note that it is
     supported "perfectly", so we can expect to get comparable results
     (or better) to Windows users.  The important information is in
     two places in the entry:
      - Notes
 The human-readable notes will often contain useful
         information.  For some printers, there is a More Info link,
         which usually refers to a web page run by a user with this
         printer, or to the driver's home page.
         - Driver List
 Most printers have a list of drivers that are known to work.
         This is the most important part.  You can follow the driver
         links to a driver-specific page, which will often have more
         information about how to execute the driver, as well as a
         link to the driver's web page, if it has one.
         
 
     A PDQ driver spec has two logical functions: user interaction,
     and print job processing. These are represented in the file in
     three places:
      - Option Declarations
 These define what options the user can set, and declare PDQ
         variables for later parts of the driver to use.
         - Language Filters
 These process the print job from whatever format it arrived
         in (typically Postscript or ASCII) into a language the
         printer can understand (for example, PCL).  Option values are
         available here, as well as in the output filter.
         - Output Filter
 This final filter bundles up the printer data regardless of
         input type; often printer options are set here.
         
 
     Let's work on each of these for a Canon BJC-210:
           The driver list for this printer includes the bj200 and bjc600
      drivers, both of which are Ghostscript style drivers.  The notes
      suggest that we use the bj200 for black-and-white printing.
            So, as far as the user is concerned, the BJC-210 supports one
      useful option: the user should pick color or black-and-white.
      Let's declare that as choice option called "MODE":
 option {
  var = "MODE"
  desc = "Print Mode"
  # default_choice "Color"    # uncomment to default to color
  choice "BW" {
    # The value part assigns to the variable MODE whatever you 
    # want. Here we'll assign the text that varies between the 
    # two Ghostscript option sets for the two modes.
    value = "bj200"
    help = "Fast black printing with the black cartridge."
    desc = "Black-only"
  }
  choice "Color" {
    value = "bjc600"
    help = "Full-color printing."
    desc = "Color"
  }
} |  
 
      With the above choice declarations, the user will see a Color or
      BW choice in the driver options dialog when he prints from xpdq.
      In the command-line pdq tool, he may specify
       -oBW or  -oColor.  The default
      can be set from xpdq, or declared above with the
       default_choice keyword.
            PDQ normally identifies its input with the
      file(1) command.  For each type returned by
      file that you want to handle, you provide a
      language_driver clause.  The clause
      consists mostly of a script to process the printjob language, in
      any (!) scripting language you wish (the default is the usual
      Bourne shell).
            In our case, we want to print Postscript and ASCII on our
      BJC-210.  This needs two language drivers: one to run
      Ghostscript for Postscript jobs, and one to add carriage returns
      to ASCII jobs:
 # The first language_driver in the file that matches what file(1) 
# says is what gets used.
language_driver ps {
  # file(1) returns "PostScript document text conforming at..."
  filetype_regx = "postscript"
  convert_exec = { 
    gs -sDEVICE=$MODE -r360x360 \     # gs options from the database
       -q -dNOPAUSE -dBATCH -dSAFER \ # the "usual" Ghostscript options
       -sOutputFile=$OUTPUT $INPUT    # process INPUT into file OUTPUT
    # Those last two lines will often be the same for gs-supported
    # printers.  The gs... line, however, will be different for each
    # printer.      
  }
}
# We declare text after postscript, because the command "file" will
# often describe a postscript file as text (which it is).
language_driver text {
  # No filetype_regx; we match the driver's name: "text"
  convert_exec = {#!/usr/bin/perl
     # a Perl program, just because we can!
     my ($in, $out) = ($ENV{'INPUT'}, $ENV{'OUTPUT'});
     open INPUT, "$in";
     open OUTPUT, ">$out";
     while(<INPUT>) {
        chomp;
        print OUTPUT, "$_\r\n";
     }
  }
} |   
           That's it!  While other printers may need output filtering (as
      described in the next section), the above clauses are it for the
      BJC-210.  We just wrap them all up in a named
      driver clause:
 driver canon-bjc210-0.1 {
  option {
    var = "MODE"
    desc = "Print Mode"
    # default_choice "Color"    # uncomment to default to color
    choice "BW" {
      # The value part assigns to the variable MODE whatever you 
      # want. Here we'll assign the text that varies between the 
      # two Ghostscript option sets for the two modes.
      value = "bj200"
      help = "Fast black printing with the black cartridge."
      desc = "Black-only"
    }
    choice "Color" {
      value = "bjc600"
      help = "Full-color printing."
      desc = "Color"
    }
  }
  # The first language_driver in the file that matches what file(1) 
  # says is what gets used.
  language_driver ps {
    # file(1) returns "PostScript document text conforming at..."
    filetype_regx = "postscript"
    convert_exec = { 
      gs -sDEVICE=$MODE -r360x360 \     # gs options from the database
         -q -dNOPAUSE -dBATCH -dSAFER \ # the "usual" Ghostscript options
         -sOutputFile=$OUTPUT $INPUT    # process INPUT into file OUTPUT
      # Those last two lines will often be the same for gs-supported
      # printers.  The gs... line, however, will be different for each
      # printer.      
    }
  }
  # We declare text after postscript, because the command "file" will
  # often describe a postscript file as text (which it is).
  language_driver text {
    # No filetype_regx; we match the driver's name: "text"
    convert_exec = {#!/usr/bin/perl
       # a Perl program, just because we can!
       my ($in, $out) = ($ENV{'INPUT'}, $ENV{'OUTPUT'});
       open INPUT, "$in";
       open OUTPUT, ">$out";
       while(<INPUT>) {
          chomp;
          print OUTPUT, "$_\r\n";
       }
    }
  }
} |   
           If you want to prepend or append something to all printjobs, or
      do some sort of transformation on all the data of all types,
      then it belongs in the filter_exec
      clause.  Our little Canon doesn't require such a clause, but
      just to have an example, here's a simple illustration showing
      how to support duplexing and resolution choice on a Laserjet or
      clone that speaks PJL:
 driver generic-ljet4-with-duplex-0.1 {
  # First, two option clauses for the user-selectable things:
  option {
    var = "DUPLEX_MODE"
    desc = "Duplex Mode"
    default_choice = "SIMPLEX"
    choice "SIMPLEX" {
      value = "OFF"
      desc = "One-sided prints"
    }
    choice "DUPLEX" {
      value = "ON"
      desc = "Two-sided prints"
    }
  }
  option { 
    var = "GS_RES"
    desc = "Resolution"
    default_choice = "DPI600"
    choice "DPI300" {
      value = "-r300x300"
      desc = "300 dpi" 
    }
    choice "DPI600" {
      value = "-r600x600"
      desc = "600 dpi" 
    }
  }
  # Now, we handle Postscript input with Ghostscript's ljet4 driver:
  language_driver ps {
    filetype_regx = "postscript"
    convert_exec = { 
       gs -sDEVICE=ljet4 $GS_RES \
          -q -dNOPAUSE -dBATCH -dSAFER \
          -sOutputFile=$OUTPUT $INPUT
    }
  }
  # Finally, we wrap the job in PJL commands:
  filter_exec {
    # requires echo with escape code ability...
    echo -ne '\33%-12345X' > $OUTPUT
    echo "@PJL SET DUPLEX=$DUPLEX_MODE"    >> $OUTPUT
    # You can add additional @PJL commands like the above line here.
    # Be sure to always append (>>) to the output file!
    cat $INPUT >> $OUTPUT
    echo -ne '\33%-12345X' >> $OUTPUT
  }
} |   
         Most Linux systems ship with LPD.  This section describes a very
    basic setup for LPD; further sections detail the creation of
    complex filters and network configuration.
         The minimal setup for lpd results in a system that can queue
     files and print them.  It will not pay any attention to wether or
     not your printer will understand them, and will probably not let
     you produce attractive output.  But we have to start somewhere.
          To add a print queue to lpd, you must add an entry in
     /etc/printcap, and make the new spool
     directory under /var/spool/lpd.
          An entry in /etc/printcap looks like:
 # LOCAL djet500
lp|dj|deskjet:\
        :sd=/var/spool/lpd/dj:\
        :mx#0:\
        :lp=/dev/lp0:\
        :sh: |  
 
     This defines a spool called  lp,
      dj, or  deskjet, spooled
     in the directory  /var/spool/lpd/dj, with no
     per-job maximum size limit, which prints to the device
      /dev/lp0, and which does not have a banner
     page (with the name of the person who printed, etc) added to the
     front of the print job.
          Go now and read the man page for printcap.
          The above looks very simple, but there a catch - unless I send in
     files a DeskJet 500 can understand, this DeskJet will print
     strange things.  For example, sending an ordinary Unix text file
     to a deskjet results in literally interpreted newlines, and gets
     me:
 This is line one.
                 This is line two.
                                  This is line three. |  
 
     ad nauseam.  Printing a PostScript file to this spool would get a
     beautiful listing of the PostScript commands, printed out with
     this "staircase effect", but no useful output.
          
     
     Clearly more is needed, and this is the purpose of filtering.
     The more observant of you who read the printcap man page might
     have noticed the spool attributes if and
     of.  Well, if, or the
     input filter, is just what we need here.
          If we write a small shell script called filter
     that adds carriage returns before newlines, the staircasing can
     be eliminated.  So we have to add in an if
     line to our printcap entry above:
 lp|dj|deskjet:\
        :sd=/var/spool/lpd/dj:\
        :mx#0:\
        :lp=/dev/lp0:\
        :if=/var/spool/lpd/dj/filter:\
        :sh: |  
 
A simple filter script might be:
 #!perl
# The above line should really have the whole path to perl
# This script must be executable: chmod 755 filter
while(<STDIN>){chomp $_; print "$_\r\n";};
# You might also want to end with a form feed: print "\f"; |  
 
     If we were to do the above, we'd have a spool to which we could
     print regular Unix text files and get meaningful results.  (Yes,
     there are four million better ways to write this filter, but few
     so illustrative.  You are encouraged to do this more
     efficiently.)
          The only remaining problem is that printing plain text is really
     not too hot - surely it would be better to be able to print
     PostScript and other formatted or graphic types of output.  Well,
     yes, it would, and it's easy to do.  The method is simply an
     extention of the above linefeed-fixing filter. 
          Such a filter is called a magic filter.  It
     plays the same role as the language filters of PDQ.  Don't bother
     writing one yourself unless you print strange things - there are
     a good many written for you already, and most have easy-to-use
     interactive configuration tools.  You should simply select a
     suitable pre-written filter:
      - LPD-O-Matic
 Lpdomatic is a filter designed to use data from the Linux
         Printing printer database.  It will soon support essentially
         all free software printer drivers, including regular
         Ghostscript drivers, Uniprint drivers, and the assorted
         filter programs floating around out there.  It works with
         various strains of LPD, including stock BSD, LPRng, and the
         new VA Linux LPD, to allow option selection.
         - APS Filter
 apsfilter is a filter designed for use on a wide
                  variety of Unices.  It supports essentially all
                  Ghostscript drivers.  It, too, works with
                  various strains of LPD, including stock BSD and
                  LPRng.  At the moment, this is probably the best
                  third-party system around for non-PostScript
		  printers.
         - RHS-Printfilters
 RHS-Printfilters is a filter system constructed by Red Hat.
         It shipped beginning, I think, in version 4 of Red Hat Linux,
         as the backend to the easy-to-use
         printtool GUI printer configuration tool.
         Other distributions, including Debian, now ship the
         rhs-printfilters/printool combo as a printing option.  Thus
         this filter system is arguably the most widely deployed one.
                  The rhs filter system is built on an ascii database listing
         distributed with it.  This listing supports many Ghostscript
         and Uniprint drivers, but not filter-style drivers.  The
         filters constructed also do not support much in the way of
         user-controllable options at print time.
                  The printtool places a configuration file
         named postscript.cfg in the spool
         directory.  Inside this Bourne shell-style file, each setting
         is a variable.  In unusual cases, you can make useful changes
         directly to the config file which the printtool won't allow;
         typically this would be the specification of an unusual
         Ghostscript driver, or a PPD filename for the VA
         rhs-printfilters version.
                  VA Linux has made some enhancements to the rhs-printfilters
         system under contract from HP.  With the proper versions, it
         is now possible to select options for Postscript printers
         under control of Adobe PPD files.  I cover this system in
         Section 8.2.2.
         
  
         There's one catch to such filters: older version of lpd don't run
     the if filter for remote printers, while
     most newer ones do (although often with no arguments).  The
     version of LPD shipped with modern Linux and FreeBSD
     distributions does; most commercial unices that still ship LPD
     have a version that does not.  See the section on network
     printing later in this document for more information on this.  If
     you only have locally-connected printers, then this won't affect
     you.
          While most versions of LPD don't gracefully handle PostScript
     (nevermind user options), VA Linux recently modified LPD and Red
     Hat's filtering software to support PostScript printers fairly
     well.  For the moment, this system works only with Red Hat 6.2,
     although the packages could be easily adapted for other
     distributions.
           VA's new system uses Postscript Printer Definition, or PPD,
      files.  PPD files are provided by printer manufacturers and
      declare the available options on a printer, along with the
      Postscript code needed to activate them.  With the VA system,
      the normal LPD scheme works a little differently:
       The user can specify options with the -o
         flag.  For example, you might specify -o
         MediaType:Transparency if you were about to print on
         overhead film.  Alternatively, the front-end GPR can
         be used to specify options in a dialog box; you can see
         screenshots of GPR in Section 3.3.1.
         LPR passes the options to LPD as an extended attribute in the
         LPD control file.
         A modified version of the rhs-printfilters package is given
         the extended options data in an environment variable, and
         uses ppdfilt to add these options to the print data.
          
           You can obtain RPM packages, or source tarballs, from the
      project's website
      on SourceForge.  For installation details, consult the
      project's installation
      micro-HOWTO.   In essence, you need to uninstall the Red
      Hat version of printtool, lpd, and rhs-printfilters entirely,
      and then install the VA versions, plus ppdfilt, gpr, and a few
      other utilities.
            You will also need PPD files for your Postscript printers.
      PPD files are usually fairly easy to find.  VA Linux and HP
      distribute PPD files for many Laserjet models.  Other vendors
      provide PPDs for their own printers, and Adobe distributes
      PPD files for many printers.
            At the moment, much of this is a bit difficult to install.  But
      future installation tools will build upon the printer
      configuration library libprinterconf, which
      enables both the autodetection and rhs-printfilter configuration
      of both networked and local printers.
      Note: It is possible to use GPR alone, without the modified LPD
            or even rhs-printfilters.  GPR can be compiled with
            all the logic needed to massage Postscript jobs directly.
            This may be an easier-to-install option suitable for
            people who never really need to print using lpr
            directly. 
       Once you've setup VA's Postscript-capable LPD system, you can
      control your printer's options in two ways:
       - With the GUI
 To use GPR, you first make sure that you've specified the
	  proper PPD file.  Then the printer's options will be
	  available on the `Advanced' panel.  Basic
	  ppdfilt options will be available on the
	  `Common' panel.
          - With the command line
 This lpr supports the -o
	  option.  You may specify any option/value pair from your
	  printer's PPD file with -o.  For example,
	  consider this PPD file option clause:
 *OpenUI *PrintQuality/Print Quality: PickOne
*DefaultPrintQuality: None
*OrderDependency: 150 AnySetup *PrintQuality
*PrintQuality None/Printer Setting: ""
*PrintQuality Quick/QuickPrint:  "<< /DeviceRenderingInfo ...
*PrintQuality Normal/Normal: "<< /DeviceRenderingInfo << /...
*PrintQuality Pres/Presentation: "<< /DeviceRenderingInfo ...
*PrintQuality Image/1200 Image Quality: "<< /DeviceRenderi...
*CloseUI: *PrintQuality  |   
	  For the option PrintQuality, the possible
	  values are Quick, Normal,
	  Pres, or Image.  You might
	  give a command like:
        % lpr -o PrintQuality:Image file.ps  |   
                   There are a number of options common to all printers which
          will work in addition to the ones from your PPD.  These
          include:
           - page-ranges
 You can specify a range of pages to print.  For example,
              page-ranges:2-3.
              - page-set
 You can print only odd or even pages.  For example,
              page-set:odd.
              - number-up
 You can print multiple pages on each piece of paper.
              For example, number-up:2.
              
  
          Other options are detailed in the ppdfilt
          man page.
         
  
          By popular demand, I include below a listing of the permissions
     on interesting files on my system.  There are a number of better
     ways to do this, ideally using only SGID binaries and not making
     everything SUID root, but this is how my system came out of the
     box, and it works for me.  (Quite frankly, if your vendor can't
     even ship a working lpd you're in for a rough ride).
 -r-sr-sr-x   1 root     lp    /usr/bin/lpr*
-r-sr-sr-x   1 root     lp    /usr/bin/lprm*
-rwxr--r--   1 root     root  /usr/sbin/lpd*
-r-xr-sr-x   1 root     lp    /usr/sbin/lpc*
drwxrwxr-x   4 root     lp    /var/spool/lpd/
drwxr-xr-x   2 root     lp    /var/spool/lpd/lp/  |   
         Lpd must currently be run as root so that it can bind to the
     low-numbered lp service port.  It should probably become UID
     lp.lp or something after binding, but I don't think it does.
     This is simply one more reason to avoid the stock BSD LPD.
          PDQ uses a different, non-daemon-centric scheme, so it has
     different programs.  The only SUID root programs are the lpd
     interface programs lpd_cancel,
     lpd_print, and
     lpd_status; these are SUID because
     actual Unix print servers require print requests to originate
     from a priviledged port.  If the only printers for which you use
     PDQ's bsd-lpd interface are networked print servers (like the HP
     JetDirect or Lexmark's MarkNet adapters) then you do not need the
     SUID bit on these programs.
         Large installations, by which I mean networks including more than
    two printers or hosts, have special needs.  Below are some tips.
    For really large environments, merely distributing printcap/filter
    information becomes a difficult problem; the Cisco Enterprise Print
    System addresses this and is probably either a good starting
    point or a nearly complete solution, depending on your needs.
    Medium to large environments can be well supported by native LPRng
    features.
     Each printer should have a single point of control, where an
       administrator can pause, reorder, or redirect the queue.  To
       implement this, have everyone printing to a local server,
       which will then queue jobs and direct them to the proper
       printer.  For large campuses or distributed networks, have one
       server per building or other suitable network subset.
       Use LPRng, at least on servers; the BSD LPD is too buggy for
       "real" use.  So is CUPS, at least right now in mid-2000.
       But don't take my word for it—you should test a number of
       spoolers and see which suits you best.
       Client systems should not have unique printing configurations.
       To implement this, use LPRng's extended printcap syntax so
       that you have one printcap to use everywhere.  CEPS provides
       for this by building atop a lightweight distributed database
       instead of traditional printcap files.
       Print queues should not be named for make or model; name print
       queues for something sensible like location (floor2_nw)
       or capability (color_transparency).  Three years from
       now, when a printer breaks, you will be able to replace it
       with a different make or model without causing confusion.
       Operate a web page which shows detailed information on each
       printer, including location, capabilities, etc.  Consider
       having it show the queue and include a button to remove jobs
       from the queue.  Complex networked environments are
       unmanagable for users without proper documentation.
       On Unix systems, use PDQ or the like to allow selection of
       print job attributes such as duplex or paper size, and to force
       users to run all Ghostscript processing under the proper user
       ID.  If you have all Postscript printers (as is best), you can
       also select from the GPR or XPP front-ends; both are prettier.
       On Windows and Apple systems, use either the platform-specific
       drivers everywhere (Samba supports the
       Windows automagical driver-download mechanism) or, better, use
       generic Postscript drivers everywhere.  Do
       not mix and match; primitive word processors often produce
       different output when the installed printer driver changes;
       users cannot deal with output that vaires depending on the
       particular client/printer pair.
       If at all possible, buy a large-volume printer for
       large-volume printing.  If on a budget, use LPRng's multiple
       printers/one queue facility and assign a babysitter; printers
       are complex mechanical devices that will often jam and run out
       of paper in such configurations.
       Do not feel that printers must be plugged into workstations;
       Ethernet "print servers" now cost under $100.  The ability to
       locate printers anywhere you can network is a big improvement
       over forced location near a host; locate printers in sensible,
       central locations.
       Use any SNMP trap or other monitoring/alert facility available
       to you - someone should be tasked with running around and
       fixing printers with no ink or paper.  Npadmin (see Section 11.10.1) can be used to do some management
       operations with SNMP printers. 
        
       Regular LPD provides very little to help you with accounting.  You
    can specify the name of an accounting file in the
    af printcap attribute, but this is merely passed
    as an argument to your if filter.  It's up to you
    to make your if filter write entries to the
    accounting file, and up to you to process the accounting file
    later (the traditional format is mainly useful for line printers,
    and is nontrivial to parse in Perl, so there's no reason to
    preserve it).  Also, if you're using my
    lpdomatic program as your filter, you'll need
    to make changes, since it depends on being given a configuration
    file as the ``accounting'' file name.
        
    Ghostscript provides a PageCount operator that you can use to
    count the number of pages in each job; basically you just tack a
    few lines of postscript onto the end of the job to write an
    accounting file entry; for the best example of this see the file
    unix-lpr.sh in the Ghostscript source
    distribution.
        Note that the unix-lpr implementation of
    accounting writes to a file from the Ghostscript interpreter, and
    is thus incompatible with the recommended -dSAFER option.  A
    better solution might be to query the printer with a PJL command
    after each job, or to write a postscript snippet that prints the
    pagecount on stdout, where it can be captured without having to
    write to a file.
        
    The LPRng print spooler includes an HP-specific sample
    implementation of accounting; I assume that it queries the
    printer with PJL.  This technique should work for most PJL,
    Postscript, or SNMP printers with which you have two-way
    communications.
        If you have a networked printer that supports SNMP, you can use
    the npadmin program to query a pagecount after each job.  This
    should work properly for all print jobs.  See Section 11.10.1 for more information on npadmin.
     
 |