Subject: lpd FAQ version 1.2
From: [email-masked] (Brian McCauley)
Date: Tue, 1 Jun 1993 22:39:02 GMT
Newsgroups: comp.os.linux.announce

OK let's call this ``lpd FAQ version 1.2''. (The previous two releases
are therfore retrospectively numbered 1.0 and 1.1) The changes from
version 1.1 to 1.2 are largely cosmetic (although there are at least
two new questions too) and this should now be ready to be made into an
offical Linux FAQ section so this is the last time I'll post this FAQ
to c.o.l as a separate entity. I'm sorry about bringing out 3 versions
in such rapid sucession but I felt compelled to release version 1.1
before I was really ready as there were important changes resulting
from a mail I got from one of the Net activists.

I have not included any statement along the lines of "Please send any
ideas for this section of the FAQ to [email-masked]" as this
goes without saying and I believe that the introduction to the FAQ as
a whole contains a list of the FAQ maintainers and a generic version
of the above statement anyhow.

-------------------------------Cut here--------------------------------
QUESTION: What _is_ the lpr/lpd package?

ANSWER: 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. ]

QUESTION: What is _the_ Linux lpr/lpd ?

ANSWER: 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 was 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
(if not now) as part of the complete overhall of the Linux Net stuff.

Ross agrees that Fred's version should be thought of as _the_ Linux
lpd package. I <[email-masked]> have not had a chance to look
at Fred's port yet (I'm waiting for the full release of 0.99pl10
before I update anything) but most of this FAQ refers to the BSD lpd
package or Linux in general so this is probably not too important.

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 include plp and the ka9q lp
facility. There are also romours of SysV spoolers being ported.

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

ANSWER: Put /etc/lpd& in your /etc/rc or /etc/rc.local (usually in
/etc/rc.local after you start syslogd (if you use syslogd)).

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.

QUESTION: Why do I sometimes see /usr/etc or /etc/inet or /usr/etc/inet?  

ANSWER: 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. Most Linux gurus advise keeping it
all in /etc.

If you really want this quirky layout:

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

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

QUESTION: Where do I get a printcap for a xxxxx?

ANSWER: This question is essentially meaningless - see next question.

QUESTION: What is the content of /etc/printcap?

ANSWER: 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 model's escape sequences
and so on 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). [Alternatively the
net-FAQ has a summary of some of the more important fileds.]. One last
point you should always specify ``suppress header'' ``:sh:'' unless
you have _text_ printer and want banners. (See the banners question
for further expanation).

QUESTION: What is the format of a /etc/printcap?

ANSWER: Ideally RTFM(termcap) (yes, I said *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 readability 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 or attribute would be a more sensible terms.) [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.]
Capabilities having string value and have a = delimiter between the
capability name and the value while those having a numeric value use a
# (actually they can use either a # or an =). Boolean ``capablilties''
are true if they appear in the list and false if they do not.

Special characters in a string value can be expressed using `\'-escape
sequences as in C; in addition, `\E' stands for ESC.  `^' is also a
kind of escape character; `^' followed by CHAR stands for the
control-equivalent of CHAR.  Thus, `^a' stands for the character
control-a, just like `\001'.  `:', `\' and `^' themselves can be
represented as `\:', `\\' and `\^'.

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/lp.df and those queued by
`lpr' through /usr/local/lib/magic-filter/lp.lf.

See also the next question.

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

ANSWER: 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.

QUESTION: What's the minimum /etc/printcap?

ANSWER: This is a silly question but it _is_ frequently asked. The
answer is ``lp:sh'' (that's 6 bytes including the linefeed character
on the end). To use this /etc/printcap you must make /dev/lp a symlink
to your printer and create your spool queue directory as
/usr/spool/lpd.  (You might think that if you wanted banner pages you
could loose the ``:sh'' but the termcap syntax requires at least one
charateristic per entry).

QUESTION: How do I prevent the `staircase effect'?

ANSWER: Unix terminates each line of a file with a linefeed but not a
carriage return so taken literally a Unix text file printed on an
ASCII device will start each line below the end of the previous line.
Some printers can be set to treat "linefeed" as "carriage return,
linefeed", 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. The test of $1
allows the isertion of carriage returns to be switched off by the `-l'
switch on lpr.

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. ]

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

ANSWER: Define the `tr' ``capability'' in /etc/printcap to be your
printer's font reset command. For details of the format of this string
see the question on the format of printcap. This may not work if a
printout crashes in the middle of an escape sequence - putting a lot
of ^@ on the front may help but this probably won't be enough it you
were printing raster graphics when the filter died.

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

ANSWER: If you don't have an `if' specified in /etc/printcap 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 a 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 

QUESTION: How do I get burst/banner pages?

ANSWER: For a simple text printer (in particular not postscript) and a
simple text 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 cusomised banner (or have a postscript 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
call the code to print the banners from the config script. ]

QUESTION: How do I print text on a ps printer?

ANSWER: You need a filter based on a program called enscript. I don't
know where you can get enscript for Linux.

QUESTION: Why do files with a lot of graphics get truncated?

ANSWER: 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.

QUESTION: Why doesn't `lpr -i' work?

ANSWER: 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.

QUESTION: Why doesn't `lpr -p' work?

ANSWER: 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.

QUESTION: Why does lprm say `too many users'?

ANSWER: 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

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

ANSWER: There's one lpd process 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.

QUESTION: How do I print over a Network?

ANSWER: 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). See also the net FAQ ]

QUESTION: Which /dev/lp* is my printer?

ANSWER: On an XT bus system LPT1: becomes /dev/lp0 (major=6, minor=0),
on an AT LPT1: becomes /dev/lp1 (major=6, minor=1). To be more
precise:

Name Major Minor I/O address
 lp0   6     0       0x3bc
 lp1   6     1       0x378
 lp2   6     2       0x278

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

ANSWER: Yes the latest kernels support parrallel port IRQs but to
enable them you must use `lpcntl'. The interrupt driver uses less
processor time and gives a faster throughput but sometimes one may
choose sacrifice this to free up an IRQ line. If your printer is
/dev/lp1 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

QUESTION: What's the difference between the polling driver and an the
interrupt driven one?

ANSWER: A polling sits in a loop repeatedly reading the port hardware
to see if it is ready for another character and then gives it one. An
interrupt driver goes to sleep and is woken by the port hardware
(using a hardware interrupt) when it wants another character. Polling
drivers are easier to write but in multitasking environments they are
a bad thing.)

QUESTION: How do I write filters?

ANSWER: In normal Unix terminology, filters are just programs (so they
must have execute permission) that read a stream from their standard
input and write to their standard output.

lpd filters are filters in the sense that thay read from their STDIN
and write to their STDOUT but 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.

All lpd filters must conform to a particular command line syntax (or
more often simply ignore command line parameters). For details of the
command line parameters RTFM(printcap).

It's easier to debug filters if you test them in an immediate shell
before you install them. (If your filter make use of its command line
arguments you'll have to specify them too).

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

If you want to write a shell script filter it must have a #!/bin/sh
header.  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=- -

QUESTION: 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?

ANSWER: 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.

QUESTION: When should I define an `of' filter?

ANSWER: 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.)

QUESTION: Where do I get filters for given printers?

ANSWER: 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 a matter of writting trivial shell
script - see this FAQ. If the program you are using insists on reading
a names file as input see the next question. 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.

QUESTION: How do I get a program that won't read from STDIN to act as
a filter?

ANSWER: For example dvilj2p insists on a named file as its input (and
what's more expects one with a .dvi suffix). To make a dvi filter for
a laserjet you'll have to capture the STDIN into a temporary file.

#!/bin/sh
cat >/tmp/$$.dvi
dvilj2p /tmp/$$
rm /tmp/$$.dvi

The problem with this kludge is that is may have a very high disk
overhead. (In the long term dvilj2p should be fixed).

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

ANSWER: History. You can, in fact, 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. If you are on a network remember that the filter
setups go on the print server so you will need to consider other
people's needs too. To avoid running out of possible types use magic
filters.

QUESTION: What are magic filters?

ANSWER: 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 (and
existing separate dvi and ps filters) 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
it's 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 or nroff file.
-------------------------------Cut here--------------------------------
-- 
    \\   ( )   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