Monday, 20 May 2013

You'll need a tray

I needed (ok, i wanted) to print a few configuration files from the command line (Linux/OSX). While Unix may provide us the command lpr, the path i wanted to follow was nc (ie netcat). This turned out, shall i say, into a Learning Experience&tm;.

Gear involved: a Mac, a Linux server, a HP printer, patience and google.

The problems i encountered were:

  • Line endings. My files ended in a \n newline, whereas the printer wanted \r\n carriage return + newlines.
  • The printer wanting me to press the green checkmark button that i indeed wanted to print the file
  • nc which seemed to hang (but didn't)

Transforming one kind of line endings to another seems like a trivial thing. That's why we have the unix2dos and dos2unix utilities. Except they weren't installed on my Mac or on the Linux server i was going to print from. But hey, that's why you have sed. Except that sed seems to care for lines, not for files, so i ended up transforming the files with perl, thusly:

for F in *.conf; do perl -p -e 's/\n/\n\r/g' $F > $F.lpr ; done

This created seemingly identical files from the original ones, but with linefeeds changed to cr+lf. To validate, i ran my new favourite spell: od -a filename.conf.lpr, which dumps out all characters, including the "invisible" ones, in a geekly manner.

I then tried to print a file, by chanting cat somefile.conf.lpr | nc printer 9100. Three things did not happen. Netcat seemed to hang, the printer didn't print, and ... well, the printer didn't print. It felt like three things anyway. The printer didn't print because a) it didn't know which tray to print from, b) it was probably confused of the paper size, and c) when i tried sending the printer all the files, it threw away all but the first. Or last. The result was that to print the files, i had to netcat them one at a time, then run to the printer, press the green button twice, get my hardcopy, walk back to my terminal, press ^C and netcat the next one. Which was neither convenient nor elegant.

To remedy, i tried adding a form feed to each document:

for F in *.lpr; do echo -e '\f' >> $F ; done

Not sure it did anything though, because the above problem remained.

Problem one: the paper must automagically come from the right tray. Problem two: netcat must do its thing in a netcatly manner, ie deliver the payload and quit.

In my search for an answer to problem two, i came upon the answer to problem one. When one talks with the printer (in a Jetdirect manner, so to speak), the printer waits for more data until we politely tell it that that'll be all thank you very much and close the door. Which is nice and all, but not very productive.

The solution is to tell netcat to deliver the stuff, wait a second, and then hang up. Thusly:

cat somefile.lpr | nc -q 1 printer 9100

This restored normality in one second flat. Nice.

The final trick was the hardest, and it involved PJL. To prepare a spell to switch to tray four, speak thusly:

echo -e "\033echo -e "\033%-12345X@PJL
@PJL SET MEDIASOURCE = TRAY4
@PJL ENTER LANGUAGE = PCL
" > select-tray4.pjl

To have the page print, cast the following:

(cat select-tray4.pjl & cat somefile.lpr ) | nc -q 1 printer 9100

As always, there is probably a More Elegant way to do this, but hey, it works on my machine :)

works on my machine, starburst