Hacker News new | past | comments | ask | show | jobs | submit login
Bye CUPS: Printing with Netcat (retrohacker.substack.com)
417 points by r3trohack3r on Aug 3, 2021 | hide | past | favorite | 177 comments



While the article is correct, it omits most of the actual function of CUPS. Many printers are capable of accepting various types of documents directly over the network, with postscript, HP PCL, and PDF being commonly supported---and ASCII pretty much universally supported.

The problem is that few printers support _all_ of these standards. Postscript, for example, is surprisingly complex to implement in practice, which leads to a lot of inexpensive network printers actually lacking postscript support. Further, printers are very slow at rasterizing, and so while support for PDF rasterization is very common you probably don't want to use it. You can easily see a minute per page for printing modest PDFs. In-printer PDF rasterization is also of very uneven quality, and I have seen issues like completely broken kerning in documents due to the printer's poor handling of embedded fonts.

One of the key functions of something like CUPS is to address this problem: CUPS standardizes the format of all printed documents to something that is well-supported by the printer, and performs much of the rasterization ahead of time on the much faster print server. This saves time and improves reliability since you don't need to figure out if a given document is supported by the printer. For most printers these days some variant of PCL is the preferred language for jobs, as it's simpler and easier to implement than Postscript. It also presents fewer security concerns.

Of course the other major problem CUPS solves is the management of the queue, including across multiple users. That's an important feature but not one that matters in a lot of home situations. That said, if you don't use a printing system you can and will run into annoying situations where you cannot print a document because you are waiting for the previous one to complete sending, which often gets blocked on the printer's memory space or rasterization.


> Further, printers are very slow at rasterizing, and so while support for PDF rasterization is very common you probably don't want to use it.

That's interesting. Back in the day (of HP LaserJet 4L and similar), I learned that rasterizing on the PC and sending to the printer was very slow because printers had slow connections and little memory. The resolution was also limited and it looked blocky. The rule was to never print "as bitmap" if you could avoid it. OTOH printing "flat" postscript was very fast and yielded much better quality. I think the printers allowed loadable fonts and often had some of the standards (Times, Arial) pre-loaded.


The big issue is that, back when, printed documents were much simpler. Printers offer a set of embedded fonts that makes it very quick and easy to print simple text documents, if you are okay with one of the printer's embedded fonts. You just need to send a couple commands to set up the font parameters and then the text. PCL and moreso Postscript also give you some vector drawing capability that makes printing line art in vector format very efficient.

But the nature of printing has changed! People now want to print things in all kinds of arbitrary fonts, which requires either rasterizing to print resolution (which is a lot, 300-600dpi) or sending the printer all the outlines as vector instructions. Postscript and PCL take different approaches to this and sometimes different print stacks do as well. And then add graphics, and 99% of documents you encounter these days provide all graphics in raster format in the first place. The result is that something, either the host or the printer, needs to take a raster graphic (which can even just be little icons) and interpolate them to whatever dot pitch the printer is using. That tends to be the real killer... that interpolation can take a printer a very long time. Usually there's some way in the PCL (exposed via the printer driver) that you can tell the printer to interpolate to a lower DPI which will speed things up, but make your images look worse.

Unfortunately sending 600dpi graphics over the network can still be kind of slow and does contribute to the "Receiving Data..." and time to first page even with modern printers and drivers. Most laser printers have a pretty poor TTFP anyway, though, so it's not too big of a deal.


I suppose if you have a printer that doesn't support PostScript or PDF then you could pipe the output through GhostScript. This is what CUPS is relying on anyway.


Right, there's no magic pixie dust in CUPS that you can't manually reproduce using a concoction of software packages, command line incantations and maybe some scripts. But then you're just re-implementing CUPS, manually.


Is there any guide on how to make a Linux-based print server which would be autodetectable by all the major OSes? I feel like we need a dedicated print server for our office (where there are many computers running Ubuntu, Windows and MacOS) because the printer doesn't work reliably enough. I have never actually seen such a scenario in the wild - people seem to always connect to network printers directly (they also used LPT and USB printers shared via the standard means of Windows in the past).


You just want to make sure you have IPP and Bonjour enabled and it should Just Work. A quick google finds https://www.dailycupoftech.com/how-to-set-up-a-print-server-... which looks about right


What about Page Layout / Color/Mono selection etc.,?


Postscript has commands for that, you can preprocess the file appropriately.


It's very much non standardized. The standard is PPD, so you'd want a parser for that at the very least, perhaps a user interface too, and before long you want something similar to CUPS.


Hah. I had a similar moment of enlightenment with FreeBSD when somebody explained that you can just cat a wav file into /dev/audio (or /dev/dsp? forget the exact name). And that you can produce white noise by catting /dev/random to the same destination. With no barrier to the sound card like that, I was free to experiment with programming dfferent noise algorithms and figuring out how digital audio works. I eventually did things the proper way with OSS and finally sndio on OpenBSD, but direct, universal interfaces like files invite that initial exploration and help you get things done quick and easy.

netcat is also a secret weapon around the house. My girlfriend runs macOS, but it's way more reliable to just nc files to each other over wifi than deal with all the cloud and airdropping bullshit.


When I was first learning Linux many years ago a friend and I got intoxicated and catted /dev/hda into /dev/dsp. It was all basically static with sometimes very structured patterns that we would try to guess as to what filetype was producing them. He had download and forgotten about a long uncompressed audio recording of a piano performance on his drive that suddenly started breaking through the static in chunks of varying length. We came to the conclusion that this was probably just what the kernel source sounded like.


mplayer -demuxer rawaudio -rawaudio rate=48000 -format s16le -af volume=-20 /dev/sda

Warning, headphone users: may hurt your ears. Trust me on the volume lowering.

With 16 bit samples and (default) two channels, you can recognizeably hear small integer values in your left ear. :)


I remember when I discovered that while in engineering school. I would try to pipe all kinds of files to see which ones had interesting acoustic signatures. I remember .iso files to be particularly interesting.


for i in $(seq 1 10); do seq -120 1 120; seq 120 1 -120; done | aplay

It's for you.


Good skills.

It has never occurred to me to do that but it is actually quite an obvious thing to do when you "know" that everything is a file.

Any idea what the visual equivalent would be?


If you've got a framebuffer console, I think you can cat to /dev/fb ... Although pixels are less friendly than audio, it's kind of helpful for identifying patterns if you preprocess so everything is shades of one color, or a byte -> color map anyway.


Plan9's /dev/draw.


ffmpeg can point directly to the webcam under /dev/.


> Any idea what the visual equivalent would be?

Perhaps:

head -c800 /dev/urandom > /dev/tty

Or:

mplayer -demuxer rawvideo -rawvideo w=80:h=60 /dev/urandom


> mplayer -demuxer rawvideo -rawvideo w=80:h=60 /dev/urandom

Change that to w=720 h=576 (for pal countries) and you can relive the glory days of analog TV static. Except not - mey memory seems to tell me it's more colourful. I guess it's to do with the limited chroma resolution in pal?


As far as I understand/remember it:

Analog color television color information is sent "out of band" from the point of view of black-and-white television (as a sideband frequency, with neat analog trickery to cancel out its effect on main signal). Color TV is backwards compatible. It's unlikely that random input happens to look like meaningful properly encoded color information, so television static is largely black and white.


You can reduce the saturation as desired (0.6 below):

mplayer -vf eq2=1:1:0:0.6 -demuxer rawvideo -rawvideo pal /dev/urandom


The secret of *nix that people don't like accepting is the file approach is often the right approach.

Consider lowly embedded linux. You COULD dig down deep into the documentation of which register, which interrupt, which special memory address needs to be written to interact with the right ports on a embedded linux board. All while adding a bunch of safeguards and checks to make sure "Only you are doing this".

Or, as if often the case, you can simply find the right /dev/xxxx device and read from it or write to it.

9 times out of 10, you'd not suffer any negative consequences from using the /dev/xxx system as intended and you get the bonus ability of being able to interact with the outside world using programming languages other than C.


The file approach ignores anything that exists (at least in part) in the time domain.

Audio files are (for me) the canonical example. A text file has no inherent bit-rate. An audio file being handled without knowledge of (even just) its sample rate has its semantics distorted or destroyed.

There's an awful lot of things you can do with the file approach, and I love it. Cross into the time domain and try to retain the same approach, and I say you're making a serious mistake.

What's worse is when the actual programming APIs (as opposed to just redirecting stdout to /dev/dsp) also fail to model the time aspect, and encourage programmers to think that you can just shovel data at a device without any consequences for your software's properties (like latency).


Many character devices do in fact have a bitrate.


It's mostly syntactic though, not semantic.


I don't think this has anything to do with the file approach per se, just with using an interface at a higher abstraction level.


My favorite version of this is reading from /dev/dsp will capture audio from the mic. I would cat this audio to /dev/dsp on another host over ssh in the school lab.


You used to be able to do that on Linux when its sound system was OSS ("Open Sound System", not "Open Source Software"), the same as FreeBSD uses today (I believe Linux still has an OSS compat layer). A long time ago the project lead was employed by a company to write support for some newer sound hardware, and decided to make those changes proprietary. The Linux folks decided to do something completely different, and we got ALSA, while some BSD folks decided to fork the last fully open source version of OSS and continue developing it.

The irony, of course, is that the proprietary version of OSS failed, and it ended up going open source again.


The difference is that on Linux, only one process can open /dev/dsp, which is why you need shims like aoss or padsp to run older games or other audio-programs without stopping all other sound sources / your sound server.

IMO, /dev/dsp was the right approach and should have been extended instead of being replaced with entirely different interfaces.


ALSA has compat modules for OSS.


I remember back when ALSA was a hot new thing on Linux, and it kinda sorta solved the "only one app can play things at the same time" problem that existed with the traditional OSS.

Meanwhile, OSS on FreeBSD just worked.


Rinse & repeat when every desktop environment brought their own audio daemons, then later PulseAudio and now PipeWire.

I still roll my eyes and I don’t get surprised every couple of years when somebody releases a yet another Linux audio daemon.

Maybe it’s some kind of Linux tradition.

At least PipeWire is saner compared to PulseAudio.


> every couple of years when somebody releases a yet another Linux audio daemon.

You seem to be stuck in, oh, maybe 2008.

There hasn't been "yet another Linux audio daemon" in more than a decade. JACK came along in the early 2000's (I wrote it), and PulseAudio in 2004 or thereabouts. All that nonsense with esd, artsd etc. was over because the aughts were over.


You seem to have missed pipewire.

While it supports the same APIs as Pulseaudio, it's still a new audio (and video) daemon.


The GP is about pipewire, and was complaining that it's "just another linux audio daemon". I concluded that it wasn't necessary to mention it in the context of my comment.


Thank You For JACK.

Even though i don't do audio on Linux.


artsd.... now that's a name I haven't heard in a long time!


My problem is that all of these are incompatible. Woe be to whomever has an OSS app, an ALSA app, a JACK app, and a PulseAudio app, all of which want to run at the same time.

I don't get why this was never fixed at the kernel level. You have onions of layers.


PipeWire solves this problem. It provides ALSA, JACK, and PulseAudio emulation (no one has actually used OSS on Linux in decades).

It is the audio solution for Linux.

PipeWire does video too, and when combined with a compatible Wayland compositor, serves as a replacement for remote X11.


Replace "PipeWire" with "PulseAudio" and hey look it's 2010 all over again.

Don't worry, THIS time we got right FOR SURE.


PulseAudio never intended to replace Jack. And in fact, that's one of its biggest failings.

FWIW, I have recently switched from PulseAudio to PipeWire. I remembered how rough the switch from plain ALSA to PulseAudio was, and thus was utterly baffled how smooth the transition to PipeWire is. I just uninstalled PulseAudio, installed PipeWire, rebooted, and everything just worked, down to the Bluetooth headset that I never quite got to work well with PulseAudio.


.... Wait a minute. You got a bluetooth headset working reliably with Linux? Tell me more...


Yeah, I had the same experience. With PipeWire it (mostly) just works, and reliably. The only thing I'm missing is always presenting the microphone as an usable device and only switching codecs/profile when the microphone is being used.


Since I switched to pipewire, my audio is crackling every time the cpu is loaded (a ryzen 7...) not even jack was struggling with that on this machine


Double check that you're running PipeWire with rtkit (this is the default with PulseAudio, AFAIK it is not the default yet on PipeWire).

It is really important to run a sound daemon with realtime privileges. This is the only way to ensure no cracks.


Thanks I'll check that


Pipewire is not finished at this point. It is being deployed "early" by some distros, apparently in the belief that it will help find bugs and help them being fixed.


> At least PipeWire is saner compared to PulseAudio.

In what way?


Pipewire implements both ALSA psuedo-devices, the JACK API and the PulseAudio API. You only need a single daemon to address all possible audio I/O needs, something that PulseAudio could not do.


That doesn't sound like a recipe for sanity.


My experience with pipewire is it works better than pulseaudio, is faster, has lower latency, and fewer bugs. And it gets better all the time!


What I don't like is that audio systems on Linux are too complicated. For example, all that ALSA needs to do is to provide exclusive access to a device (only one program at a time) and send samples into it unmodified (no bit depth change, no resampling, no mixing, no volume adjustment etc). But open source developers cannot do such a simple thing. They added thousands of unnesessary features, hundreds config options and turned ALSA into a monster. When it should be just a dumb backend for PulseAudio.


It didn't, though, initially. On hardware that supported multiple streams, it worked (assuming the driver for that hardware knew how to do it), but for hardware that didn't, you had to use the ALSA dmix plugin, which for the longest time wasn't enabled by default because it was the cause of some audio artifacts.


dmix is what I meant. But you had to use ALSA to use dmix, so in practice, it was the biggest reason to switch for most.


OSS got that ability decades ago, yet we still have ALSA and then the others :(


OSS did not have the ability when it was removed from the kernel and replaced by ALSA, which did have that ability already.

There were (and are) many problems with the OSS API, a number of which continue to exist in the ALSA API too.

All serious audio APIs (plugins, or native audio I/O) use a pull model at the bottom of the stack, so that i/o is driven by the hardware. You can layer a push model (where software does blocking read/write calls whenever it wants) on top of that, but not the other way around.

And yes, OSS and ALSA both implement select/poll etc. for audio devices, but do not enforce the use of this model, resulting in the 2000s being filled with Linux (and *BSD) apps that couldn't function correctly without oodles of buffering.


I remember the mixer interface (channel volumes, mute states, routing matrix) was far superior with ALSA.

I used a script to toggle the SPDIF output stream of my Soundblaster Live to get track marks on the Mini Disc player recording the output.


At some point you may get bitten by just nc’ing files around as tcp checksums alone are not that great. A lot of transfers or large files will at some point introduce errors. This is where an application layer error check may be desirable.


Is that really the case? (I mean i know in theory, but in practise does it matter?). Its not like http has its own checksum, and i've never had problems downloading over http (yes https does have better checksums, but i suspect it would just fail and not auto retry, which has never happened to me)


I've always verified the checksums of files transmitted via netcat and occasionally I have had different checksums. It's rare, and only on gigabyte+ files, but it has happened.


You should just use rsync - its been the best tool for transfering files between UNIXoids for the last 15-20 years for me and comes preinstalled with most distros (even macOS). It will take care of transferring only the required parts, and if you supply -c (slow!) it will even perform checksumming on both ends to assert files were correctly transferred and are bit-identical.


I was primarily using Android's busybox netcat, but I agree; there's always a better tool.


TCP checksums aren't that great, but you've usually also got lower layer CRCs which are much better. Though you can still get tripped up by misbehaving network hardware that corrupts a packet and then masks it by recomputing the CRC as the packet goes out again.


> My girlfriend runs macOS, but it's way more reliable to just nc files to each other over wifi than deal with all the cloud and airdropping bullshit.

I'd never though of that, so simple!

    # On the receiver
    nc -l 9000 > output.file

    # On the sender
    nc 172.17.0.7 9000 < input.file
My only issue is that it seems to hang after it's done. What am I missing?


Probably something about EOL, end-of-feed, CRLF-translation or something similar?

Netcat has plenty of (confusing) options, but there's usually a solution.


It also depends on which netcat you use. I usually use ncat (which comes with nmap) with the following invocations, and that never gave me any encoding/EOF/CRLF trouble:

  # on sender
  ncat --send-only --listen 12345 < file.zip
  # then, on receiver
  ncat --recv-only 1.2.3.4 12345 > file.zip


Yeah I did this at work recently with netcat. Our file sharing "solution" wasn't going to work so I just thought to try it for the hell of it.

I also setup a horrible video chat in bash using just vlc and netcat. Audio works better like this


I remember back in the day when I had some old HP behemoth my dad's office was throwing out... a 4100 or something like that.

I never bothered with a printing system.. I'd just cat a ps file to /dev/lp0


Is this a Linux feature or FreeBSD magic, as like the article seems to credit it?


> Is this a Linux feature or FreeBSD magic, as like the article seems to credit it?

Being able to just send wave data to the audio device "file" is pretty common on most systems that smell like Unix.

The netcat trickery from the article works on any platforms where netcat is available, what file formats are specifically supported varies by printer. Most will take text and Postscript (though some famous printers like the LaserJet 4 still had PS as an optional addon), anything more complicated is implementation-specific.


It's Unix magic remembered in the FreeBSD Handbook.


How do the device files know what format the audio data is in?


It doesn't, it just plays the data as PCM and with whatever sample format and sample rate it is currently configured for.


I'd guess the device files just pass through the binary data to the hardware, and then it's up to the audio device/driver what their defaults are (probably PCM 16-bit 44.1khz)


FWIW, the Internet Printing Protocol (and IPP Everywhere in particular) make printer setup in CUPS far, far easier, but distributors seem reluctant to encourage it. I wrote about my experiences with IPP back in June (https://lwn.net/Articles/857502/). I expect to never have to hassle with printer drivers again...


I own a HP MFP and for several years HPLIP generally worked for several to many months at a time, until it didn't. Me and the wiff both run Arch on our laptops (she doesn't know or care).

After a particularly rubbish time trying to get HPLIP working again after a pacman -Syu I did a literature search: Mr CUPS had deprecated everything apart from IPP Everywhere. So, I tried it out.

Me and the missus send docs to print and they get printed. I cannot remember the last failure (apart from running out of paper.) I also have toner levels monitored via Home Assistant.

I also have an office with several MFPs and inkjets, accessed via Windows (Server 2019) print queues. They are not so reliable. I often have to restart the Print Spooler service on our print server. To be fair, it is generally one queue that is at fault.


>To be fair, it is generally one queue that is at fault.

Printer drivers run in process as well as the port monitor (for older printers). You might find the situation improves if you use an inbox driver (one that comes with Windows) and/or the standard port monitor.


I read your article and finally got my Brother printer working on elementary OS! Thank you!


I thought that the whole point of CUPS was to provide an IPP service.


CUPS provides an IPP service over those printers that aren't natively IPP.

Now printers integrate the IPP functionality.


keep in mind not every printer has a good http stack, especially if the device never gets restarted this can be a problem.


Probably true but why not turn it off and on again daily. While you are at it, you can restart your print queues regularly via a cronjob or Taskman.

There is no need to suffer if that will do the job.

Pragmatism is not the enemy of perfection.


Didn't know about that, you got some examples?


The point of CUPS and of server middleware in general like PulseAudio and what not is when multiple clients all want to send output streams to the same sink. Just sending the stream directly to a device with no middleman works fine provided 1) the stream is encoded in a way the device understands, and 2) no one else is trying to use it at the same time. For a shared network resource like a printer, unless you live alone and are the only user on your LAN, betting no one else is sending a job to the printer at the same time might be a rough bet.

Even when it works, there might be downsides, as some other comments are alluding to. The long print time one mentioned is likely because while you're lucky that your printer understands how to transcode pdf to ps in order to print a pdf, the onboard processor on the printer is much weaker than whatever you have on your computer. Also beware that if you're doing this on a radio network, I don't think netcat can encrypt the traffic. So don't be printing your credit card statements this way.


Hence the existence of lp(1), which at its simplest is just a queue that sends things to the network as they arrive.


Huh. So can one leverage/hack lp to serve as a generic service spooler? Has anyone done so (in a mildly documented way)?


Yes, at OpenBSD hackathons they used lpd as a queue for mp3s so all the devs could submit music to be played for the room.

https://patrick.wagstrom.net/weblog/2003/05/23/lpdforfunandm...


>2) no one else is trying to use it at the same time.

Printers are fine with accepting jobs from multiple clients and have been for a long time. After all this is pretty much standard practice for any small office without a server.


> Also beware that if you're doing this on a radio network, I don't think netcat can encrypt the traffic. So don't be printing your credit card statements this way.

Of course netcat does not encrypt anything. But if your printer accepts encrypted traffic you can send that over netcat. The question is what encryptions do the printers support? What protocol (stack) CUPS uses in the end? I have never heard that a printer certificate has expired, so my first guess would be it's all in cleartext.


Terrible idea on several levels.

Avoid jetdirect (9100) port like the plague. Partial files? Errors parsing the postscript? Outputting to the jetdirect port will result in printing every bit of that trash out, no questions asked. Walked up to a printer and found Nearly blank pages with one PCL or Postscript line telling you there's an error? That's jetdirect printing for you, and there's no good reason for it. LPD and IPP have actual protocols signaling start and end of jobs, so nothing comes out if something in the process fails, saving paper, toner and frustration. Yeah, you can't just use netcat, but you can easily use lp: lp -h 192.168.0.30 file.ps

Printing raw to a printer without drivers is also a terrible idea, it happens to work some of the time, but leaves you at the mercy of printer defaults. Printing a US Letter page on a printer which defaults to A4 (or vise versa)? Say goodbye to part of your print job. Now, yeah, you could program the correct command sequences into your postscript document, but why would you want to? Plenty of other things used in documents will cause errors if sent to a printer without being sanitized by CUPS (or filters to lpng, or whatnot).

CUPS isn't great. It makes printing so much harder than it needs to be. I absolutely hate having to remember the exact syntax to select B&W on my color printer: lp -o ColorMode=Monochrome It's very difficult to track down how it's mangling your print jobs, when there's a problem and you need to do so. Having to do an old apache style allow,deny reverse polish notation logic to configure who you want to access the printer and admin interface is user-hostile to be sure. And more. But it certainly has made it much easier to go from nothing to up and printing quickly, it's certainly got every feature you could need, and it's certainly reliable. I've done it in the old days, and I certainly don't want to go back to configuring printcaps manually with inscrutable invocation of ghostscript and many other print filters.


I used to do this at home all the time (from Linux though): networked printer with its own IP address and then good old netcat. I'd do it with PostScript files and send them to HP LaserJet 4M+: not only do these beauties speak PostScript natively, they can also be made to display the infamous "PC LOAD LETTER" message.

I'd try to find these printers used then I'd upgrade them: more RAM, more fonts, adding a network card inside the printer etc.

I still have several of these printers in a garage, some of them have printed more than 300 000 pages. They probably still work: some things were that good back then.

And, yup, there's something feeling magical when netcat'ing a .ps file (or another format) directly to the printer.


I recently tried that with my Epson Ecotank, but instead of rendering the document, it just printed out the literal source code. It then held the paper halfway through the machine until I sent enough newlines.

I was only half disappointed.


>It then held the paper halfway through the machine until I sent enough newlines.

That is what a form feed character is for (ASCII 0x0C).


How did you add network cards? Do some printers have PCI expansion slots?


Proprietary, not PCI, but expansion slots, yes. On HPs it was called the MIO slot and later the EIO slot. If your printer came with a MIO card that only did serial and parallel, you could swap it for one that added networking.


And if it stops working, try re-soldering it in an oven before throwing away. Some infamous batches had bad soldering problems that can be fixed. See i.e. [0]

[0] https://community.spiceworks.com/how_to/2077-how-to-bake-an-...


If you have a single host, and a single printer, or your printer itself is both network-enabled and can manage its own print spool, direct TCP/IP printing may indeed work for you.

The value of CUPS is that it enables the CUPS-serving computer to run as a print server. This means not only print drivers (document format support --- typically plain text, Postscript, and one or more PDL (printer definition languages) & PCL (Printer Control Language), but status on the printer, queue management, job control, and access control. Note that if your printer is generally available on your local WiFi network, you might want to give more thought to that last element.

If those are overkill for you and your printer Just Works with generated output, then yes, you can get by without the complexity.

Note that you can also often telnet directly to the printer port.

Be aware of what you're trading off, though, and whether or not you actually need what CUPS, or direct network access, offers.


The CUPS web front-end also has rough edges; Apple maintains CUPS these days and OS X now ships with the web interface on :631 disabled.

If you still need a print server, it can be well worth the extra $100 or so to buy a business-class printer with an IPP server in it, so that CUPS runs on a chip inside the printer instead of on a separate computer. (Generally anything that supports "Airprint" will do this, and also at the mid range you avoid the "printers whose ink cartridges are more expensive than the printer" zone.)


> Apple maintains CUPS these days

Apple never really maintained CUPS. They hired the author, Michael Sweet, and he pretty much served as the printing team. He left Apple a couple years ago, and basically stalled their printing department.

He’s recently become head of the Printer Working Group, and they’re all pushing IPP Everywhere towards greater adoption. It’s a laudable effort.


After he left, all his cups commits to Apple's public CUPS repo stopped[1] and his work continued in the OpenPrinting fork of CUPS[2]. Interestingly though, it seems he resumed committing to the Apple repo in March. I'm glad CUPS on macOS isn't going to be left behind, but I'm curious what happened there.

1. https://github.com/apple/cups/graphs/contributors 2. https://github.com/OpenPrinting/cups/graphs/contributors


Apple moved to IPP (branded as AirPrint) a decade ago.

Google shut down Google Cloud Print in 2020 and moved to IPP.

Microsoft announced that they were moving to IPP (branded as Universal Print) in 2020 as well.

CUPS still exists because legacy printers don't have built in IPP support.


My first introduction to the internet was downloading Magic the Gathering card lists as postscript files via FTP and then FTPing them to a postscript printer. Would have been 1994 and they were some sort of Sun machine at LMU. Internet has been all downhill since then.


A few years later (2002-ish), I setup a Zebra barcode/label printer that had a similar mechanism. I’d write the code for the label in the printers language (ZPL?) and then FTP a file to the printer.

I was in grad school in a wetlab, so I had to label a ton of microcentrifuge tubes. Having a quick web interface e to generate the ZPL files that would be FTP’d to the printer let me avoid writing all of that out by hand.

It was such a simple system. And the FTP server was basically a queue, so you could print a bunch of labels at a time.


...all downhill since then. Well said greybeard, well said. https://dilbert.com/strip/1995-06-24


This is how this Hackernews printed several pages worth of the plaintext representation of a PDF on an office printer a few years ago before figuring out how to cancel the job.


So how did you cancel it? I assume killing the nc process wasn't enough because it had buffered the whole file, so you had to do it at the printer?


Happens all the time when something goes wrong, like malformed files, wrong driver loaded, etc. All printers have an internal buffer, so when one goes crazy printing pages of gibberish, the only solution is to kill the job directly on the printer, or turn it off asap, then go to the computer and empty the print queue should something exist there as well, then do the same at the print server, if there is one. The point is that once a print is started, all buffer will eventually end up to the printer, so it's the 1st device we must stop and the last one to restart once we're sure no data to print is left between the application and the paper, that is, not before all spoolers have been emptied.


[Smiles in n-gate]


What if you put CUPS... in the printer? And made it a network device?

Unix printing was designed in an era when most printers were dumb serial or parallel devices chained directly to a computer. Or if they had an ethernet jack, had some bizarro proprietary system that was very minimal and included no memory, queueing, or ability to interpret complex formats like PDF. That is the environment CUPS was designed for. And it was a huge improvement over the old lp system. The "l" in "lp" literally means "line".

Like everything else in the computer world printers have gotten a lot more capable. They may literally be running CUPS. That's why you don't need another complex print spooler and format convertor on your client machine.


I once did something similar to that on my previous job. A colleague came by asking who printed several pages of garbage. Me: "Sorry, I just inferred every reputable printer supported postscript". The problem: the job was an outsource for a pinter vendor. They obviously did not like my comment.


YMMV as the printer needs to support PCL/PDL and not all HP network servers have it built-in. HP chose to save some money by making dumb network cards that forced the PCL/PDL rendering on the Windows computer which made using Linux difficult.

http://danieru.com/2013/06/06/what-is-port-9100-how-to-print...

While you're at it you may as well try out the printer exploit kit https://github.com/RUB-NDS/PRET


I used to dread setting up printers on any operating system. I've done it countless of times with Linux, Windows and macOS, and it's been quite common to have some kind of fight with the printer until I get my paper out.

Only recently, by buying a Brother laser printer at home, and setting all my machines to use NixOS, I haven't been needing to think about printer problems anymore. All I need is this piece of config, and the printer will Just Work with the new computer:

https://github.com/pimeys/nixos/blob/main/modules/home-servi...


Your config files make we wanna learn NixOs, but i'm in the process of backing up this one and installing Tumbleweed on it.

Thank you for sharing.


I immediately tried it...

Aaand this is how I made my printer spit out dozens of garbage pages with just one to two lines of gibberish on each (the PDF source code, admirably giving up the page at each occurrence of the corresponding char)...


Turns out that's the same result on Windows when using Ncat /shrug


I'm on Linux (Arch) and I had no more luck with PS than with PDF...

My printer is a Brother HL-2270DW... seems to be quite a dumb one...


CUPS exist because not all printers are HP.

Magic in printing is still an arcanum. PPD files. Windows 10 as a print server. (some print devices are not networked)

Prelude files. in-printing logic like line reversal, density adjustments for photos. Double sided printing meta-signalling, n-up..

"oh, I don't need that stuff" fine, fine, nc is going to work for you, at the end of a bumpy road to a printer which supports it. And, right up until its 2am, you want to colour print that late birthday card for your favourite aunt, and the printer is stuck on nc...


I guess some people need CUPS but.. I have a $90 Brother laser printer and it has support for all kinds of protocols, and I can send multiple text files (9100 is the "raw data" port, not anything else) to it at the same time on port 9100 and it figures everything out and doesn't get confused.

I can send stuff to it over FTP, too.

$90!

I will never use CUPS again. I'll need a printer driver, yes, but I'll never need CUPS.


Been doing this for years since when I accidentally opened my printer's IP address in my browser and it printed a page starting with

    GET / HTTP/1.1


Well, seems to be missing that for many, the point of CUPS is to take a regular, non-network enabled printer (parallel port, USB etc) and turn it into a networked printer...

https://www.freedomit.co.nz/kb-centos/76-using-port-9100-to-...


That's definitely not true. That is a side-effect of CUPS, but CUPS exists very much in the same realm as PulseAudio and other service-enabling frameworks around hardware. It allows software/clients to interface with printers in a seamless and safe manner.


I just tried this and while it worked, it was very slow. It takes a minute to start printing a page in a PDF, meanwhile nc is still hanging and sending the data, seemingly very slowly. The printer is constantly showing "Receiving Data" on its screen. The PDF is only 450KB.

Edit: It took about 5 mins to print a 3-page document, with long pauses between each page.


I suspect it's the printer doing the pdf->ps conversion. I have a beefy printer, so only run into this for large documents. But I'll cat through `gs` then to `nc` to do the pdf->ps conversion locally, and it is much faster.


That makes sense. That's why you want to do print spooling on client devices, which run on extremely fast CPUs in comparison. I guess that is why we don't send documents directly to printers.



Kinda similar, we could use LPT1 on DOS as a file and write to it or even just do a "copy" on the command line ( remember "copy CON LPT1" ?). This was pretty much the default way to print, with applications sending ESC sequences to pretty up the page.

The problems were to do with handling problems like printer jams, out of paper etc which require, in essence, a partial resend and was tricky. Print spoolers on all platforms managed some of this complexity.

The greater memory on printers and the ability to locally retry a page make it simpler today, but only in the most casual settings. If you want to print anything substantial, treating a printer as a file is not really a good idea.


>The problems were to do with handling problems like printer jams, out of paper etc which require, in essence, a partial resend and was tricky. Print spoolers on all platforms managed some of this complexity.

The only system I'm aware of that managed that was AFP on IBM mainframes. Certainly the Windows print spooler doesn't. It assumes the printer handles a paper jam and just waits until it is ready to accept more data.


Two downsides to being able to send PDF bytes direct to TCP port 9100 hosted directly by the printer firmware on the printer's own network interface...

* That's not encrypted.

* (More importantly) You might look at the printer firmware's complexity, excessive IoT/cloud-friendliness, and hints from the printer brand about their current engineering standards... and become uneasy about plugging that into your LAN, even if you firewall it to heck.

Partial solution: for my modern laser printer, I've left its NIC unconnected, and put my own print server in front of it, on a VLAN, and connected via USB. And I still strongly suspect at least a couple classes of vulnerability still present, but no time to look into it or mitigate.

Variation for the article's needs: you can make a one-line script TLS/SSL tunnel from a local port on your workstation host(s), to a thin isolating host (old RasPi?) in front of the printer. So content is encrypted over the LAN, and the printer is more isolated than it would be normally.

Another variation: plug the printer directly into a single host that needs it (such as via USB or a dedicated Ethernet NIC), and then decide what to do about any other hosts that want to use the printer.


All *nix does this. Also try piping to lp then a device.

Sorry to be cheeky, but welcome to 1977. ;)


How would you get an application, such as Firefox or Chrome, to know to use netcat to print?


Today I: CTRL+P -> Save to PDF.

If I want to print multiple pages per sheet: Open PDF in Firefox, CTRL+P -> Save to PDF and configure the document. You can also pipe through `gs` to do this.

For _huge_ documents (100s of pages), I'll pipe through `gs` first to do the pdf->ps conversion on my laptops CPU. The printer can do it, it just takes a lot longer.


Choose Jetdirect/Appsocket in the printer add menu and it will do the same thing.

There is nothing magic about netcat. You are just dumping Postscript/PDF data on a TCP port the printer is listening on.


Oh fascinating. If I use the system dialogue, I can choose the application to print to. There is an `lpr` option, and I can specify the application it invokes in a "Command Line" field.

I can put `nc [printer_ip] 9100` there and it will just print. I just printed your comment this way.

That's cool! Thank you for teaching me something!


Back in the day I opened telnet on that port. Typed some stuff and was fascinated that it got print.


You'd need to set up a system printer using the JetDirect/socket protocol, then you could print via normal print dialog.


I wrote once a escpos emulator[1] that takes in escpos code and turns it into a bitmap image. I failed to get this bitmap image to print properly with cups so I ended up writing my own printing routines as well for that certain receipt printer[2].

1: https://git.cloudef.pw/escpos2raster.git/tree/ 2: https://git.cloudef.pw/escpos2raster.git/tree/src/bin/starpb...


That’s why you should only buy printers that support standard formats. Preferably PDF and PCL.

They also don’t turn into junk, after the next OS update, when the manufacture decided not to provide driver updates anymore.


I've been using netcat for 4 years to print in my office. I'm on linux, and i convert non-text files to postscript via the firefox "Print to file" functionality (save as *.ps), and then netcat that postscript to the printers IP port 9100. This requires the -N option of netcat to work correctly.

I did not realize this was an exotic thing to do?

Edit: Now that im testing it, i see that firefox has recently dropped support for printing to postscript. Classic firefox. Can someone recommend me an alternative browser?


Just print to pdf and add pdftops (from poppler) to your pipeline.


This has to be the single best resource and reason to use FreeBSD: “ Off to the FreeBSD Handbook I went.” The Handbook is really well written and helpful.


PSA: If you're going to try sending odd file formats to your printer. Just leave one sheet of paper in the tray whilst experimenting.


I hated the change to CUPS. I liked both the simplicity and complexity that I had going with lpd. The system itself was simple and my filters were a beautiful mix of AWK and Ghostscript. I even had a queue to email PDFs. I guess CUPS works fine but just working out of the box is not very fun.


In a former life, I was doing tech support for UPS in the early-mid 90's I played around quite a bit with the commands to reset the various serial printers via echo and port targets. Not surprised things have moved beyond this.

Nice to see that .pdf pretty much just works.


Looks like there's a reasonably tidy script for conventional print options with a nc back-end, so to speak.

http://tkrh.co.uk/netcat.html

Untested, but code reviewed with one eye.


You can do the same with IRC and a ksh/Perl script implementing a loop and PING, Gopher, FTP, MUDs, Finger and NNTP servers.

With Plan9/9front everything involving TLS could me made a script and an Acme frontend, except for video.


KISS Linux taught me this! Once I realized I could read/write to IRC over netcat, I paired that will all the Bash magic KISS taught me and created a pure bash IRC client in 54LoC: https://github.com/retrohacker/irc-sh


I'd prefer to have one based on nc and sh as it's more portable (think busybox systems).

Also, check this for gopher:

https://github.com/hb9kns/nago

Now you can browse HN, play IF, read news, and so on over Gopher with just Busybox (sh, grep, tail and netcat requiredin the busybox build) and an internet connection:

gopher://hngopher.com

gopher://mozz.us

Altough with just less, echo and nc:

     echo / | nc mozz.us 70 | less

     echo /long/selector/to/a/text/file.txt | ncmozz.us 70 | less
Crazy but it could work on heavily tiny restricted devices such as a RetroBSD with nc, echo and less in a tiny microcontroller.


Also, I forgot, poor man's dictionary:

   dict(){ echo "define * $1\\n\\q" | nc dict.org 2628 | less ; }

   dict unix


Woah! This is awesome!


First job out of uni I worked for a company who had software that output pure HP PCL5, and yeah, you just netcat it directly to the printer IP (or configure an LP queue with no filtering to do it for you). Fun days.


It’s odd that the author does not mention that because this is FreeBSD, the recommended print spooler is the Berkeley line printer daemon, not CUPS. It’s discussed right on the page he linked to.


So.... there is this thing where I can upgrade the firmware on a Brother printer with netcat.

Equally cool and terrifying. I can dig up my notes if someone is interested.


What a surprising knowledge. I didn't know that printers support parsing PDF or even ASCII. I considered printers only support printer protocols.


Works on any OS (just tried macOS for example), but its not very convenient to set print options. Passed a jpg and it printed out the metadata.


Wait until he finds out about /dev/tcp :)

It actually blew my mind after doing Linux for 10 years. "Everything is a file" isn't a lie.


/dev/tcp is a lie though. It's not actually a file, it's implemented directly in bash.


Confronting network driverless printers with other models that needs to be supported with specific drivers doesn't seem to be very fair


That's pretty neat... But does it work with postscript files? Or maybe pdf? I also assume it only works for networked printers?


The Handbook doc linked in the article shows how you can do the same over USB.


Pipe it through through gs.


Plain ascii worked but a pdf printed garbage, on an old samsung laser. I use the generic PCL laser printer driver on mac with it.


Yeah try that with a random laser printer :) .


This is amazing. I am on Mac OS, and honestly even for me it looks enticing. I will try it!


Have fun printing a shipping label from your phone using Netcat.


Because Apple "owns" both CUPS and iPhones, you can print from an iPhone directly to a printer shared on a Linux machine if they are on the same network.

My wife (not technical) figured this out one day and I didn't believe her at first that this would all "just work".


Android hasn't needed any printer plugin to be manually installed for a while now. Since Oreo I believe.

I've printed from my phone to my pi CUPS server. Even Windows 10 understands IPP.


I have netcat in Termux. Not sure if I can access files though.


Give Termux storage permission and `cd /storage/emulated/0`.


I am printing from Ubuntoo for years withopt troubles, and don't even know is that CUPS or not. When installing Ubuntoo on new laptop I configure printing with help of internet search and forget.

Is Linux printing really such a problem?


So, network equivalent of piping text to the parallel port?


Question: is there an equivalent for printing over USB?


A lot of CUPS defenders in here, but they're all talking about the usefulness of CUPS in more complicated situations.

It seems far more friendly to mention that netcat is an option to the average home linux user.


that's great and all but not everyone has an HP...once we have better driver support, sure. Or am I misunderstanding something?


Convenient, but not very secure


I would recommend you never sniff a hospital's LAN. The print jobs that you see coming over the line, not all of them are SFW.

(Very few printers in the world seem to be setup to use secure connections unfortunately)




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: