Fast personal printing _without_ CUPS

Polytropon freebsd at
Thu Oct 27 15:29:46 UTC 2011

On Thu, 27 Oct 2011 03:42:22 -0700 (PDT), Bill Tillman wrote:
> This isn't really a question.  It's more of a semi-rant, combined with some
> information that I wanted to put on the record (so that it can be googled)
> because it may benefit some folks, other than just me.
> I'm impatient by nature, and I don't like CUPS.  (I would say that I hate
> it, but I don't actually feel that strongly.)

Let's shake hands, and allow me to add that I'm lazy. :-)

> I have two personal workstations.  When I say "personal" I mean it.  I'm
> the only one who ever touches them.
> One of them I have been bringing back up recently after a long hiatus,
> and I've just installed 8.2-RELEASE/amd64 on it.
> One of the first things I found I needed to do with it, after installing
> the OS and a bunch of my favorite ports & packages was to set it up for
> printing to a crusty/trusty old workhorse... an HP Laserjet 3015.  (This
> printer can print both plain text and Postscript, but if I just send
> it plain text the output doesn't really suit me, so I've made it prettier.
> See below.)

Using PS with a Postscript printer is the default. It's
exceptional (!) ability to also process pure ASCII text
isn't used in many cases, but can be helpful if you need
to bypass the printer spooler mechanism for some reason
and just have to print simple listings, like

	% ls /etc | awk '{ printf "%s\r\n", $0; }' > /dev/lpt0

or > /dev/u(n)lpt0 if the printer is connected locally.

> Because I've never used 8.2 before... or even any 8.x release, I naturally
> went into the Handbook and looked for _current_ guidance on setting up
> printers. 

Due to the "many standards" (correct: many deviations) in
what printer manufacturers sell to their dear customers,
there's hardly a "one size fits all" recipe. If you have
a _standard_ printer (ASCII, PS or PCL), things are quite
easy. If you haven't -- you usually have purchased a home
entertaiment ink pee sheet feeder egg-laying wool-milk-sow --
you need a more conplex solution.

> Most of that information was quite helpful, right up to the point
> where it started discussing CUPS.
> The bottom line is that CUPS is sophisticated, which is to say complex and
> convoluted. 

In my opinion, CUPS is the "Windows" way of doing things,
not the UNIX way. Hate me for having that opinion, but I
feel to say it.

> If you are impatient, then setting up CUPS properly is both
> tedious and time consuming. 

It is, I've tried it many times, and meanwhile I consider
writing my own "printer filters" the easier task!

> Of course, it _is_ essential that you properly
> set up CUPS if you are setting up a _server_ that multiple people will use,
> but for a personal workstation, the entire queueing structure is just overkill,
> in my opinion.

Setting up printer server functionality without CUPS is
very easy, given the fact that you actually bought a
real printer. :-)

> More importantly, CUPS, for me at least, seems to be quite slow.  There's a
> loooooooong pause after I queue something for printing until something actually
> comes out of the printer. 

Hmmm... In my experience, it depends on what you input
to the CUPS queue. Things like pictures may take a while
for rasterization and PS translation, other things are
out on paper much faster. I have to say that I'm using
an Ethernet-connected Laserjet 4000d here.

> Maybe that's my fault, e.g. because I didn't con-
> figure CUPS correctly, and maybe it isn't.  I don't know, and actually, I
> don't want to know, because I found a way to nicely print stuff that just
> bypasses CUPS entirely.  And it works for me, so I am a happy camper.

Isn't that what everyone wants?

BUT: CUPS seems to be hardcoded into many applications
today. They stopped working with the non-CUPS default
system tools. An example is Opera. Another one is Gimp
which works with system lp* tools, but has hardcoded
queries to "lpstat" (a CUPS program that doesn't exist
or "cannot connect to the server"). The upcoming question
here is: WHY???

> I just wanted to share what I did.
> In a nutshell, I moved/renamed /usr/bin/lpr to /usr/bin/lpr- and replaced
> it with this trivial script:
> ============================================================================
> #!/bin/sh
> printer='/dev/ulpt0'
> if [ $# = 0 ]; then
>   cat | /usr/local/libexec/psif > $printer
> else
>   for arg in $* ; do
>     cat $arg | /usr/local/libexec/psif > $printer
>   done
> fi
> ============================================================================

Yes, this is how many printer filters work. Collections
like apsfilter (that work WITH the system lp* tools, unlike
CUPS!) bring gs-based printer filters for PS, PCL and many
other devices.

% cat /opt/libexec/ 
printf "\033&k2G" || exit 2
        -sDEVICE=ljet4d -dDuplex=true \
        -sOutputFile=- - && exit 0
exit 2

This is one of my gs-based printer filters (derived from
apsfilter, no pretty-printing here, just PS to PCL translation,
and hooked into the /etc/printcap mechanism).

Yes, /etc/printcap. That's the mechanism for connecting
printer filters with actual printer devices.


You could remove the rm= setting and put the printer
device (like /dev/lpt0) into the lp= setting for a
parallel-connected printer.

Of course, you can _now_ use the luxury printer queue
tools of the lp* toolset, like lpq, lpr and lprm.

> My Laserjet 3015 used to be hooked up via a good old fashioned bulky "centronix"
> parallel cable, but I thought that I ought to finally get myself into this
> century, so I got a new USB 2.0 cable for it just the other day, and now it's
> name is "/dev/ulpt0" rather than "/dev/lpt0" as before.

Well, even if Centronics is considered dinosaur-like,
it _never_ failed on me, unlike the many "modern" things. :-)

> As you can see, the script above just takes whatever filnames are given on
> the cmmand line and cats them one-by-one through psif and then the output
> from that gets sent straight to /dev/ulpt0.

What port or package is psif part of?

> One little snag though... as I found out, it doesn't matter if you try to
> set the SUID bit on this script and make it owned by root.  Nowadays shell
> scripts simply do not do SUID anymore.  The only reason that's even signifi-
> cant is that you'll probably want to be able to print while logged in as
> any old user, and in order to make that work with this scheme, you have to do:
>    chmod 0666 /dev/ulpt0
> so that any user can write to the printer device file.

You could use /etc/devfs.conf for that, either by defining
the setting there, or work with group permissions (e. g.
add a group "usbprint", give +rw of the device file to
that group, and make your username member of that group).

> I only fiddled a couple of other small things in order to make this all work.
> Firstly, I created my own versions of /usr/local/libexec/psif-text and also
> /usr/local/libexec/psif-ps.  Here they are:
> /usr/local/libexec/psif-text:
> =============================================================================
> #! /bin/sh
> /usr/local/bin/textps -c 10 -l 60 -m 38 -t 46 && printf "\004" && exit 0
> =============================================================================
> /usr/local/libexec/psif-ps:
> =============================================================================
> #! /bin/sh
> /bin/cat && printf "\004" && exit 0
> =============================================================================
> The parameters for textps that I have in my psif-text file were just some
> parameters that I slapped together after running a few tests to see what
> values created output that looked good to me.  Your milage may vary.

Interesting inspiration!

> After I set up all of the above stuff, I noticed that my attempts to use the
> "lpr" command to print things from non-root user accounts was still resulting
> in very long delays before anything would print.  It took me some head scratch-
> ing but I finally found the problem.  In a nutshell, the problems was that
> at one point while I was trying to get this all going, I did in fact install
> the CUPS package (and friends).  As I learned, when you do this you get the
> following _different_ version of "lpr" installed in a place where normal user
> accounts are likely to see it in their $PATH first:
>    /usr/local/bin/lpr
> Yikes!  So we've got /usr/bin/lpr _and_ /usr/local/bin/lpr. 

There's even a configuration option to CUPS that lets
you overwrite the _system_ lp* tools. :-)

> I'm sure that at
> some point, somebody thought that it was a good idea to have two radically
> different programs in two different directories and give them both the same
> name. 

CUPS also has program names that are derived from LPR's
competitor. The "lpstat" command is such an example, and
I think "lpadmin" also is.

> Maybe there actually is some good reason for that, but it wasn't
> helping me any, so I just did:
>    cd /usr/local/bin
>    mv lpr{,-}
>    ln -s /usr/bin/lpr ./lpr
> That's all.
> Now I can print either Postscript or plain text files to my LaserJet, from
> both root and non-root accounts, and the printed output starts coming out
> of the printer within just a second or two every time.  No queueing, no
> fooling around, just push that document out lickety-split.

Very nice, I think I can benefit from your experience to
finally get rid of CUPS -- really, who _needs_ that to make
a standard PS printer work?!

> I'm sure that someone will tell me now that there are a zillion reasons
> why I should not have done any of this, and that I just don't understand
> this or that, or the fine technical reasons why CUPS is a wonderful tool
> and why I should be using it.  But this works for me, and I saved a lot
> of time by NOT having to learn all of the ins-and-outs of using CUPS or,
> more importantly, configuring it.  (I'm sure its a fine package, but I have
> other things that I need to be studying right now.)

Yes, maybe it's fine (or even the _only_ solution) if you
have some ink-pee device, but for a real printer, you
should not be forced to jump through hoops like what CUPS
requires you to.

In comparison to CUPS, the apsfilter configuration is a
day in the park! :-)

> The only thing that worries me about my rather ad-hoc way of setting up
> a "personal" printer (as describe above) is that I sort of wonder what
> will happen if I ever try to print something when something else is
> currently printing.  (I did something similar to what I've described
> above, but still rather different, back on my old 7.0-RELEASE system,
> and I think that there, if the printer was already busy and I went to
> print something else, then that second print attempt would just error
> out right away. 

Depends on how the printer receives data. If two "streams
of PS" get merged, you'll get unexpected surprising results. :-)

> Obviously, if you want to stack up a whole set of
> documents for printing and then go out for lunch while they all print,
> my cheap-man's approach to setiing up a printer, as described here, will
> fail to give you the advantages of a real spooling/queueing system.  But
> given that I personally rarely need to do that, for me it is pretty much
> of a non-issue.)

No, you just have to make sure that you use the system's queueing
mechanism, i. e. /etc/printcap plus lp* toolset. This will handle
all print requests and process them one after the other. Your
printer filter will be addressed in a "serial way", leading to
correct PS "streams" for each job.

> That's all folks.  I hope this all may be of some help to somebody.

At least for me, yes. Thanks!

> I'm not persuaded that giving these both the same name was really all that
> good a choice, from a user-interace/human-factors perspective. 

On one hand, CUPS wanted to stay with the default names
for printing stuff, on the other hand, they used names
from "the other system", so a conglomerate of both worlds
did emerge.

The more programs, environments and application sets do
hardcode calls to CUPS for printing stuff (instead of just
piping it to whatever is present, be it BSD's lpr, CUPS,
or a home-made filter mechanism), the more problems will
occur when you decide _not_ to use CUPS. It will then
become mandatory at some point, even if you intendedly
state that you don't need it.

> But I suppose
> that it is far too late to do anything about those choices now.  Too much
> other stuff has probably already been built assuming that things are this way.

Yes, and I'm afraid there will be more and more of such
stuff, due to low-quality "rapid application development"
and the exxagerated use of libraries of layers of abstraction
of abstraction of layers of libraries of layers of interfaces
of abstractions of libraries... you get the idea. :-)

Oops, at this point I see that I malquoted or malreplied.
Sorry for that. :-)

> Kudos for your persistence and for sharing this experience
> with us. I too found CUPS a big waste of time for my uses.

Just try to add a parallel dotmatrix printer that's currently
not connected to your system. I think you'll see that this
still is impossible with CUPS. :-)

> I have two networked laser printers. One of them is an HP 4
> (talk about your old workhorses) with a JetDirect card.

Oh you're lucky. My LJ 4 (more than 15 years old, still in
perfectly working state) is parallel-only. And _still_ does
a good job.

> That of course is self explanatory. But the other is a
> Brother HL2040 laserjet which used to run on a parallel
> cable but I converted it over to USB about a year ago with
> the help of the nice folks in this mailing list. This
> printer is driven by a FreeBSD-8.2-STABLE server using
> lpd and a relatively simple filter which envokes
> ghostscript to convert the PS files it receives into
> the correct format. The driver is part of ghostscript's
> library and it all works well.

Yes, gs comes with many converters, so it's like CUPS
without web interface and without own printer spooler,
just as it should be. :-)

> When I setup a M$ windows client I install a simple PS
> printer (there are many of them available in a standard
> Windows machine). I do have to add Unix Printing Features
> on the M$ clients and setup an lpr port but that again
> is built-in and you don't even need the original OEM CD
> to do this.

Some network printers even have their own printer spooler
included, so you just have to address them per IP and with
PS data from any "Windows" PC.

> The print jobs come out quickly and in all the years I've
> been using it I never have problems.

As it should be - and has been 10, 20 years ago with all
that "old-fashioned" stuff. :-)

> I'm sure there are many justifications for CUPS but so
> far I haven't needed it. 

As I said, it seems to be mandatory for "modern" USB driven

Still I have to admit that I'm confused by the many parts
that may be involved in getting a "simple" printer working.
On one hand, there's CUPS, oh and let's forget about the
system lp* tools for now. Then, there's Gutenprint. What's
the difference? And then there's Foomatic. And zjs. And PPD.
And hpijs. What exactly are these? Why is a functionality like
printing distributed across so many different things?

How about _one_ printing system with "plug-ins" intended for
classes, like "PS printers" (no stuff needed), "PCL
printers", "dotmatrix and daisywheel", "inkpee", and
finally "inkpee with scanner and fax and music box".
And maybe finally a "make your own filter" module.

I'm not sure if it already exists. I just fear someone will
tell me that CUPS is supposed to be exactly that. :-)

Magdeburg, Germany
Happy FreeBSD user since 4.0
Andra moi ennepe, Mousa, ...

More information about the freebsd-questions mailing list