Subject: lpd-FAQ (Special edition)
From: [email-masked] (Brian McCauley)
Date: Fri, 28 May 1993 05:17:22 GMT
Newsgroups: comp.os.linux.announce

This is a special edition of the lpd-FAQ to incorporate some important
news about the future of lpd under Linux. I've also incorporated other
comments that I received in response to the first release. (So it
still doesn't have nice things like a table of contents.)

It you read the first release of this FAQ then read the revised
section "What is _the_ Linux lpr/lpd?". Note also that the /etc vs.
/usr/etc issue is handled more clearly in this version.

==================================================================

What _is_ the lpr/lpd package?

To quote the net-FAQ:

Lpr is a utility that is used to print files out to local and remote
printers. As with all networking, there are configuration files which
have to be tailored to your needs. These files are concerned with
access control, accounting and page setup of your printer(s).  Now all
control of the printer is performed by a process called lpd

Lpd is a laser printer daemon (yes I know an epson isn't a laser
printer but thats besides the point). The program lpd is normally
started in /etc/rc.local in either the forground or the background.
What happens is that lpd will sink back as a daemon, only ever being
invoked when a printer request is generated. lpd itself has some
options which are of possible intrest to some people chiefly that of
the '-l' flag which causes lpd to log requests recieved from the
network (useful for debugging). The other option is for what port lpd
should listen for data on and is generally not used.

[ Note: lp really stands for line printer but as technology has
advanced laser printer makes more sense. ]

==================================================================

What is _the_ Linux lpr/lpd ?

Up until 28th May 1993, as far as there is a definitive Linux version
of anything _the_ Linux lpr/lpd is <[email-masked]> Ross
Biro's port of the BSD sources dated 20th November 1992 (so if you're
used to AT&T's you'll find some differences).  Ross's binaries and the
diffs are found in:

tsx-11.mit.edu:pub/linux/binaries/usr.bin/lpr.tar.Z
sunsite.unc.edu:pub/Linux/system/Daemons/lpr.tar.Z

The SLS file lpr.tgz on disk b2 contains the same stuff.

However this is all about to change so from now on this version will
be called the "old" binaries. As of 28th May 1993 there appears be two
different new releases of lpd expected RSN.

In addition to the standard BSD lpr capabilities Ross Biro's port
should have had better support for serial printers (but it didn't work
in the old binaries).

Ross's port is not based on the latest BSD sources (by about 3 years,
'88 vs '91). His new release will also be based on these sources which
can be found are at:

gatekeeper.dec.com and /afs/ir.stanford.edu/src/...

Recent BSD sources are all over the place.

ftp.uu.net:systems/unix/bsd-sources/usr.sbin/lpr
src.doc.ic.ac.uk:unix/bsd-sources/usr.sbin/lpr

to name but two. The BSD sources have unGNU things in their Makefiles
so they don't compile ``out of the box'' but have now been ported by
<[email-masked]> Fred van Kempen and will be available RSN
as part of the complete overhall of the Linux Net stuff.

It's likely therefore that just like getty, ps, init and so on, there
will no longer be a single Linux lpd.

[ IMHO Fred and Ross should settle the matter with the internet
equivalent of pistols at dawn before the whole Linux community get
drawn in. ]

Once one or both of these are released this FAQ will need some major
revisions.

There are some other versions of lpd stuff about but I have to draw
the line somewhere. If anyone whants to maintain FAQ sections on these
they are welcome to do so. The other versions are plp and the ka9q lp
facility.

==================================================================

How do I get lpr to work properly other than for root? Where do the
files go and what should their permissions be?

Put /etc/lpd& in your /etc/rc or /etc/rc.local

Set the group fields of the file permissons/ownership as follows:

-rwxr-s---   1 root     daemon      37892 Nov 19 23:32 /etc/lpd
-rwx--s--x   1 root     daemon      21508 Nov 19 23:32 /usr/bin/lpc
-rws--s--x   1 root     daemon      17412 Nov 19 23:32 /usr/bin/lpq
-rwx--s--x   1 root     daemon      17412 Nov 19 23:32 /usr/bin/lpr
-rwx--s--x   1 root     daemon      17412 Nov 19 23:32 /usr/bin/lprm

...and for each of the spool directories listed in the sd fields of
/etc/printcap... 

/usr/spool/lp1:
total 5
drwxrwxr-x   2 root     daemon       1024 May 18 23:00 .
drwxr-xr-x  11 root     root         1024 Feb 19 20:56 ..
-rw-rw-r--   1 root     daemon          4 May 18 23:00 .seq
-rw-rw-r--   1 root     daemon         18 May 18 23:00 lock
-rw-rw-r--   1 root     daemon         25 May 18 23:00 status

Note these 3 files are created by lpr and lpd so if you've never
run these they could be missing so touch them into being.

Some of these permissions may be overkill so don't be surprised if
your system works with different permissions. The fact that lpq needs
to be suid root is inelegant and may change in the future.

Alternative approach: just make lpc, lpr and lprm setuid(root) then
you can forget the file permissions on the spool queues!

You're free to choose different directories for the executables on
your system (notably lpc is often in /etc even though it has commands
that are useful to non-root). The master lpd lock file which is always
in /usr/spool/ so you must have one of those but you needn't
necessarily keep your spool queues there.

The main configuration file is /etc/printcap although the old binaries
look for it in /usr/etc/lpd.  The README says hosts.equiv and
hosts.lpd files are looked for in /etc/inet but again the more
accepted convention is to locate them in /etc.

For an simple life:

mv -i /usr/etc/inet/* /etc/inet/* /usr/etc/* /etc/
rmdir /usr/etc/inet /etc/inet /usr/etc
ln -s ../etc /usr/etc
ls -s . /etc/inet

[But make sure the files in /usr/etc and /etc/inet are not already
symlinks into /etc or you'll be in deep water.]

Eventually you'll be able to delete these symlinks once you've got rid
off all the old stuff.

===================================================================

Why /usr/etc or /etc or /etc/inet or /usr/etc/inet?  

For various reasons including the difficulties of fsck'ing / some
people like to put all things that aren't needed during bootstrap in
/usr so that / is as small as possible. Also some people like all their
internet stuff in /etc/inet.

If you really want this quirky layout:

cd /etc
ls -s ../usr/etc/* .
ls -s inet/* .

[Again make sure the files in /usr/etc and /etc/inet are not already
symlinks into /etc.]

==================================================================

Where do I get a printcap for a xxxxx?

This question is essentially meaningless - see next question.

==================================================================

What is the content of /etc/printcap?

Given the similarity in appearence and name between /etc/termcap and 
/etc/printcap one could be forgiven for assuming that they contain 
analogous infomation. This is not the case. Whereas termcap contains 
informations about terminal *types* - (mostly escape seqences) 
printcap contains information about *specific* printers (like the 
directory that holds the spool queue and the device name of the 
printer). The information about a printer's cababilities are held 
in the various filters which are programs called by lpd to drive 
the printer. /etc/printcap simply gives the locations of these 
filters. For details RTFM(printcap).

==================================================================

What is the format of a /etc/printcap?

Ideally RTFM(termcap) but since most people don't have TFM(termcap)
here are the essentials.

Lines starting # are comments (as you might have guessed).

For each printer usable from the lpr command on your system there is
one logical line in the file. For the sake of readabiliy each logical
line may be spread over several physical lines by making the last
character on all but the last physical line a backslash.

Each logical line has the following format:

name1|name2|name3:string_capability=string:\
       :numeric_capability#number:boolean_capability:

The leading spaces and colon on the second line are for readability
only.

A printer can have as many names as you like but conventionally the
final name is used as a longhand description of the printer. (Still
people are free to say `lpr -P "Fred's grotty teletype"' if that's
the description you've given.)

The list of capabilities can be as long as needed and the order is not
significant. Each ``capability'' is denoted by a two character code.
(The name ``capability'' comes form the file format's termcap heritage
- parameter would be a more sensible term.) [Note from Ross Biro:
capabilities with 3 character names don't work properly which is why
the serial port stuff in the old binaries failed.] Cababilities having
string value and have a = delimiter between the capability name and
the value while those having a numeric value use a #. Boolean
``capablilties'' are true if they appear in the list and false if they
do not.

Example:

lp|bam|BAM's Epson FX-80:lp=/dev/lp1:sd=/usr/spool/lp1:sh:mx#0:\
	:df=/usr/local/lib/magic-filter/lp.df:\
	:if=/usr/local/lib/magic-filter/lp.if:

Name is lp (this is the printer that lpr uses by default). It's also
known as bam or "BAM's Epson FX-80".

The printer is on /dev/lp1 (aka AT-bus LPT1:). I don't want a burst
page. I don't want a file length limit. Files queued by `lpr -d' are
passed through /usr/local/lib/magic-filter/epson-dvi-or-ps and those
queued by `lpr' through /usr/local/magic-filter/magic-filter.

See also the next question.

==================================================================

My /etc/printcap looks identical to someone else's but it doesn't
work - why?

See if lpc stat reports a printer called ` :'. The last character on a
continued line must be a \. If there are whitespace characters after
the \ then it doesn't register the next line as a continuation.
 
==================================================================

How
    do 
       I 
         prevent 
                 this?

Unix terminates each line of a file with a linefeed but not a carriage
return. Some printers can be set to treat LF as CRLF, others can't. If
yours can then do simply do that. If the printer cannot be fixed create
a shell script filter that reads:

#!/bin/sh
if [ $1 = -c ]; then
  cat
else
  sed -e s/$/^M/
fi
echo -ne \\f

where ^M is a carriage return character not a ^ followed by a M.  To
type ^M in emacs use the sequence C-q C-m and in vi use C-v C-m.
Conventionally this script is called /usr/lib/lpf.

Alternatively your printer may have an escape sequence that will set
the way it handles linefeed characters. A simple filter that uses an 
`echo -ne' command to send this sequence may be appropriate.

#!/bin/sh
# Filter for HP printers to treat LF as CRLF  
echo -ne \\033&k2G
cat
echo -ne \\f

[ Ross Biro's new release will include a filter called lpof that does
this. ]

======================================================================

How do I get my printer to go back to the default font after each
printout?

Define the `tr' ``capability'' to be your printer's font reset
command. Assuming princap follows termcap's convention you use \E \r
\n \t and ^H etc. for ascii-values 27, 13, 10, 9, 8 etc. If you want
to send : ^ or \ you put \: \^ or \\ respectively. This may not work
if a printout crashes in the middle of an escape sequence - putting a
lot of ^@ on the front but this probably won't be enough it you were
printing raster graphics when the filter died.

========================================================================

How do I prevent a formfeed at the end of every printout?

If you don't have an `if' then lpd will automatically put a formfeed
at the end of each file. If you're using a filter then it's up to the
filter to decide if it wants to put a formfeed. To disable formfeed
completely if you don't have an `if' put :ff=: in your /etc/printcap.
But please note this suppresses the formfeed that would usually be
printed if the filter dies. If you want formfeeds after text printouts
but not on printouts printed with `lpr -l' then create the following
`if' filter:

#!/bin/sh
cat
if [ "$1" != -c ]; then
  echo -ne \\f
fi

If you want a formfeed after `lpr -l' to be optional you can misuse the
`-i' switch to suppress the formfeed with the following trick (after
all `lpr -i -l' would usually not be implemented).

#!/bin/sh
cat
# use lpr -i -l to print raw without trailing formfeed
if [ "$1" != -c -o "$4" = -i0 ]; then 
  echo -ne \\f
fi 

======================================================================

How do I get burst/banner pages?

For a simple text printer (in particular not postscript) and a simple
banner simply take :sh: out of the printcap record. If you want to
prevent the banner comming out in whatever font was last used on the
printer then define the `tr' ``capability'' to be your printer's font
reset command.

If you want a fancy banner (or have a porstscript printer) leave :sh:
in the printcap and make each of your filters print the banner. All
the information to put on the banner is included in the filter's
positional parameters.  RTFM(printcap) for details. [ If you're using
<[email-masked]>'s magic-filter package then put the code to
print the banners in the config script. ]

======================================================================

Why do files with a lot of graphics get truncated?

Usually because you've got a limit set on the maximum size file that
can sit in the spool queue. Put `mx#0' in your printcap.

======================================================================

Why doesn't `lpr -i' work?

To get lpr -i to work you need a filter istalled as `if' that
implements it. The -i switch is simply passed on by lpd to the filter.
There is such a filter called /usr/lib/lpf that can be opdtained from
bsd source archives in the directory bsd-source/lpr/filters.

======================================================================

Why doesn't `lpr -p' work?

Because its broken in the '88 sources from which the old binaries were
compiled.  lpd always thinks that the printer is 0 characters wide
regardless of what printcap says.

======================================================================

Why does lprm say `too many users'?

This was a bug in the C library in the scandir() function which failed
when an unsorted directory list was requested. This has been fixed now
so just get a new libc.so. Alternatively there is a lprm with a
workround (by [email-masked]) in:

sunsite.unc.edu:/pub/Linux/system/Daemons/lprm-fix.tar.z

======================================================================

Why does lpc complain that it hasn't stopped a daemon?

There's one lpd that runs all the time and it spawns off children to
handle each printer as needed. These children leave lock files lying
about so lpc thinks that they are still running and tries to kill
them. This is probably a bug but it's not serious.

=====================================================================

Network printing?

To print on the printer "foo" connected to the machine "bar.baz.net"
from the machine "mine.baz.net" you put an entry like this in your
/etc/printcap (on mine.baz.net):

foo:lp=:rm=bar.baz.net:rp=foo:sd=/usr/lpd/spool/foo:

and, of course, create the spool directory /usr/lpd/spool/foo.

There's no point specitying filters and the like in
mine.baz.net:/etc/printcap as it's the one in
bar.baz.net:/etc/printcap that will get used.

On the machine bar.baz.foo, you need to put "mine.baz.net" on a line
by itself in either /etc/hosts.equiv or /etc/hosts.lpd; note that
putting it in /etc/hosts.equiv will allow for unauthenticated logins as
well as printing.  /etc/hosts.lpd is printing only.

[ Editors note: I realise there are more questions about net printing
but I don't know them. If you find any let me know (with answers if
possible) ]

=====================================================================

Which /dev file is my printer?

On an XT LPT1: becomes /dev/lp0 (major=6, minor=0), on an AT LPT1:
becomes /dev/lp1 (major=6, minor=1).

====================================================================

When the kernel boots it says `using polling driver,' is there an
interrupt driven driver?

Yes the latest kernels support parrallel port IRQs but to enable them
you must use `lpcntl'. If your printer is AT port LPT1: using IRQ 7 
put:

/etc/lpcntl /dev/lp1 7

in your /etc/rc.

If you don't have lpcntl get it from:

tsx-11.mit.edu:/pub/Linux/BETA/lp/lpirq.4.tar.Z
 
=====================================================================

How do I write filters?

Filters are just programs (so they must have execute permission), for
details RTFM(printcap). If you want to write a shell script filter it
must have a #!/bin/sh header.

lpd filters are not necessarily true filters in that they may assume
that their standard input is a file and perform lseek() operations on
it. I'm not sure that such filters are strictly conforming but they
seem to work OK.

It's easier to debug filters if you test them in an immediate shell
before you install them. To do this:

my-new-filter <file >/dev/lp1

Here for example is my Epson FX-80 dvi filter:

#!/bin/sh
/usr/TeX/bin/dvips -f | \
/usr/bin/gs -q -sDEVICE=eps9high -r120x216 -dNOPAUSE -sOutputFile=- -

======================================================================

I've written a filter in shell script which works OK when I use it
from the shell prompt but fails when I tell lpd to use it?

You may need a #!/bin/sh header. You may also need to set PATH within
the script since the daemon's PATH may not have everything you need.

======================================================================

When should I define an `of' filter?

Never. (Well strictly speaking there are circumstances but you're
unlikey to meet them until you're so familar with lpd that you won't
need this FAQ.)

======================================================================

Where do I get filters for given printers?

>From BSD source archives (I think). [Editors note: I need a better
answer here ].

If you already have a program to print say DVI on your printer then
making it into a filter is usually trivial - see this FAQ. Text mode
filters are trivial too (see this FAQ) unless you want lpr to have a
choice of fonts in which case they are slightly harder than trivial.
You will probably want to insert and `echo -ne' command at the
beginning and end of your filter to set up the font etc to your
liking.

======================================================================

The set of filters supported by lpd seem strange - why aren't there
filters for Postscript, GIF, TIFF and so on?

History. You can of course use any of the filters (with the possible
exception of the default filter) for any reason. If you're never going
to use Benson Varian raster files you could use the -v switch for GIF
files. To avoid running out of possible types use magic filters.

========================================================================

What are magic filters?

Magic filters deduce their input files' types from `magic numbers'
(distictive byte patterns at particular offsets).  Magic filters are
usually perl scripts, shell scripts or C programs that simply identify
the file type then call the appropriate non-magic filter. [ Blatent
plug:- ] I <[email-masked]> have a generic magic filter bash
script that selects the right filter to use based on the output of the
`file' command. With my magic ``dvi'' filter I can do things like:

lpr -d file1.dvi file2.div.Z file3.ps file4.ps.z

This is not yet on any anon-ftp sites so e-mail me for a copy. Once
its stable and I've had a bit of (possitive) feedback I'll upload it.

Magic filters should never specified as `of' as the output filter only
gets called once if a number of files are printed without a gap.

Magic filters as `if' can also be a problem as they may prevent you,
say, _listing_ a PostScript file.

======================================================================

    \\   ( )   No Bullshit!   | Email: [email-masked]
 .  _\\__[oo       from       | Voice: +44 21 471 3789 (home)
.__/  \\ /\@  /~)  /~[   /\/[ |        +44 21 627 2171 (work)
.  l___\\    /~~) /~~[  /   [ |   Fax: +44 21 627 2175 (work)
 # ll  l\\  ~~~~ ~   ~ ~    ~ | Snail: 197 Harborne Lane, B29 6SS, UK
###LL  LL\\ (Brian McCauley)  |  ICBM: 52.5N 1.9W
-- 
    \\   ( )   No Bullshit!   | Email: [email-masked]
 .  _\\__[oo       from       | Voice: +44 21 471 3789 (home)
.__/  \\ /\@  /~)  /~[   /\/[ |        +44 21 627 2171 (work)
.  l___\\    /~~) /~~[  /   [ |   Fax: +44 21 627 2175 (work)
 # ll  l\\  ~~~~ ~   ~ ~    ~ | Snail: 197 Harborne Lane, B29 6SS, UK
###LL  LL\\ (Brian McCauley)  |  ICBM: 52.5N 1.9W