211 lines
9.8 KiB
HTML
211 lines
9.8 KiB
HTML
<!--startcut ==============================================-->
|
|
<!-- *** BEGIN HTML header *** -->
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
|
<HTML><HEAD>
|
|
<title>A Linux Client for the Brother Internet Print Protocol LG #68</title>
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#0000AF"
|
|
ALINK="#FF0000">
|
|
<!-- *** END HTML header *** -->
|
|
|
|
<CENTER>
|
|
<A HREF="http://www.linuxgazette.com/">
|
|
<IMG ALT="LINUX GAZETTE" SRC="../gx/lglogo.png"
|
|
WIDTH="600" HEIGHT="124" border="0"></A>
|
|
<BR>
|
|
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="ghosh.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue68/jenkins.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="mitchell.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
<P>
|
|
</CENTER>
|
|
|
|
<!--endcut ============================================================-->
|
|
|
|
<H4 ALIGN="center">
|
|
"Linux Gazette...<I>making Linux just a little more fun!</I>"
|
|
</H4>
|
|
|
|
<P> <HR> <P>
|
|
<!--===================================================================-->
|
|
|
|
<center>
|
|
<H1><font color="maroon">A Linux Client for the Brother Internet Print Protocol</font></H1>
|
|
<H4>By <a href="mailto:grahjenk@au1.ibm.com">Graham Jenkins</a></H4>
|
|
</center>
|
|
<P> <HR> <P>
|
|
|
|
<!-- END header -->
|
|
|
|
|
|
|
|
|
|
<h2>The Brother Internet Print Protocol</h2>
|
|
|
|
<p>A recent article <a href="../issue65/jenkins.html">
|
|
Internet Printing--Another Way</a> described a printing protocol which
|
|
can be used with some
|
|
<a href="http://www.brother.com">Brother</a> printers. It enables users
|
|
of Windows machines to send a multi-part base-64 encoded print file via
|
|
email directly to a Brother print server.</p>
|
|
|
|
<p>The article went on to show how the functionality of the Brother print
|
|
server can be implemented in simple Perl program which periodically polls
|
|
a POP3 server to check for jobs whose parts have all arrived. When such a
|
|
job is detected, its parts are downloaded in sequence and decoded for
|
|
printing.</p>
|
|
|
|
<h2>A Linux Client</h2>
|
|
|
|
<p>The Perl program mentioned above has been in use at my place for a few
|
|
months, and has made it a lot easier for me to print Word and other
|
|
Microsoft-format documents to a remote printer. But it hasn't made life
|
|
any easier for those at my place who use Linux workstations.</p>
|
|
|
|
<p>A brief search on the Brother website failed to reveal a Linux client,
|
|
so it was decided that I should develop one. The result is described
|
|
hereunder.</p>
|
|
|
|
<h2>Implementation</h2>
|
|
|
|
<p>Conventional wisdom probably dictates that a program which breaks a binary
|
|
input stream into chunks for feeding into a decoder in sequence - should be
|
|
implemented in Perl, or perhaps in C. In fact, the common Bourne shell and
|
|
its derivatives have all the necessary capabilities when used with a couple
|
|
of general Unix/Linux tools like 'split' and 'wc'.</p>
|
|
|
|
<h2>Program Walk-Through</h2>
|
|
|
|
<p>As shown in the listing
|
|
(<a href="misc/jenkins/BIPclient.sh.txt">text version</a>),
|
|
the program starts by checking that it has been
|
|
called with two arguments; a usage message is printed if this is not the
|
|
case. It then defines a function which will be called later to print
|
|
a header on each part as it is sent. In particular, this function will
|
|
include an address for notification, a part number, a part count, and
|
|
a job identifier.</p>
|
|
|
|
<p>The program body begins by generating an email address for the originator,
|
|
together with a timestamp. These are concatenated and used to generate a
|
|
name for a scratch directory. A trap is set to remove any directory having
|
|
that name in the event of error, and an attempt is made to create the scratch
|
|
directory.</p>
|
|
|
|
<p>The Unix/Linux 'split' utility is then used to split the program input
|
|
into parts whose size is given by the first program argument. Each of these
|
|
is fed into a base-64 encoder and mailer (with appropriate pre-amble) to
|
|
the address given by the second program argument.</p>
|
|
|
|
<p>The program ends by removing the scratch directory and returning
|
|
an exit status.</p>
|
|
|
|
<pre>
|
|
#!/bin/sh
|
|
# BIPclient.sh Brother Internet Print client program. Breaks incoming stream
|
|
# into parts of designated size, then does base-64 encoding of
|
|
# each part and emails it with appropriate preamble etc. to
|
|
# designated email address. Graham Jenkins, IBM GSA, June 2001.
|
|
|
|
[ $# -ne 2 ] && echo "Usage: `basename $0` kb-per-part destination">&2 &&
|
|
echo " e.g.: man a2ps | a2ps -o - | `basename $0` 16 lp3@acme.com">&2&& exit 2
|
|
|
|
do_header () { # Function to print header
|
|
cat <<EOF
|
|
START-BROBROBRO-START
|
|
BRO-SERVICE=ZYXWVUTSRQ980
|
|
BRO-NOTIFY=Always
|
|
BRO-REPLY=$Me
|
|
BRO-PARTIAL=$Part/$Total
|
|
BRO-UID=$Me$Now
|
|
STOP-BROBROBRO-STOP
|
|
|
|
Content-Type: application/octet-stream; name="PrintJob.PRN"
|
|
Content-Transfer-Encoding: base64
|
|
|
|
EOF
|
|
}
|
|
|
|
Me=`whoami`@`hostname`
|
|
[ -n "`domainname`" ] && [ "`domainname`" != "(none)" ] && Me=$Me.`domainname`
|
|
Now=`date '+%Y%m%d%H%M%S'` # Generate email address,
|
|
Dir=/tmp/`basename $0`.$Me$Now # timestamp and directory name
|
|
trap 'rm -rf $Dir;echo Oops>&2;exit 1' 1 2 3 15 # Set cleanup trap
|
|
|
|
mkdir $Dir || exit 1 # Create directory
|
|
split -b ${1}k - $Dir/ || exit 1 # Generate parts
|
|
Total=`ls $Dir|wc -w |tr -d ' '`|| exit 1 # Count parts
|
|
|
|
Part=0
|
|
for File in `ls $Dir/*` ; do # Encode and send parts
|
|
Part=`expr 1 + $Part`
|
|
[ -t 2 ] && echo "Sending part: $Part/"$Total" to: $2 .. $Now" >&2
|
|
( do_header
|
|
base64 $File # Use mmencode or base64
|
|
echo ) | Mail -s "Brother Internet Print Job" $2
|
|
done
|
|
|
|
rm -rf $Dir # Cleanup and exit
|
|
exit 0
|
|
</pre>
|
|
|
|
<h2>Limitations</h2>
|
|
|
|
<p>In the interests of simplicity, the 'do_header' function shown in
|
|
the listing leaves out some of the header lines which
|
|
are generated by the Windows client programs,
|
|
and uses a dummy value for 'BRO-SERVICE'. In consequence, it may not
|
|
work satisfactorily with a genuine Brother print server. If any readers
|
|
have such a device, I would be interested in their feedback.<p>
|
|
|
|
<p>The 'unique' message identifier can actually be duplicated if a user
|
|
submits two jobs within the same one-second period; this is a limitation of
|
|
the Brother identifier format. An alternative identifier format which inserts
|
|
a process number before the user's email address could be used if required.</p>
|
|
|
|
<p>And finally, the creation of a scratch directory to hold what is
|
|
effectively a duplicate of the raw print file - may be seen as a problem
|
|
if the client machine has a limited amount of temporary file-space. The
|
|
issue here is that we really have to take a copy of the raw print file
|
|
as it arrives so that we can generate a "total-parts" figure for
|
|
inclusion in the header of each mailed component.</P>
|
|
|
|
<p>It is possible (using Perl or 'dd') to generate and mail parts on the
|
|
fly, without using any temporary files - provided that the server program
|
|
is modified slightly so as not to require a "total-parts" figure in
|
|
the header of each part. I will be happy to send details to anyone who
|
|
would like to do it this way.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- *** BEGIN bio *** -->
|
|
<SPACER TYPE="vertical" SIZE="30">
|
|
<P>
|
|
<H4><IMG ALIGN=BOTTOM ALT="" SRC="../gx/note.gif">Graham Jenkins</H4>
|
|
<CITE>Graham is a Unix Specialist at IBM Global Services, Australia. He lives
|
|
in Melbourne and has
|
|
built and managed many flavors of proprietary and open systems on several
|
|
hardware platforms.</CITE>
|
|
|
|
<!-- *** END bio *** -->
|
|
|
|
<!-- *** BEGIN copyright *** -->
|
|
<P> <hr> <!-- P -->
|
|
<H5 ALIGN=center>
|
|
|
|
Copyright © 2001, Graham Jenkins.<BR>
|
|
Copying license <A HREF="../copying.html">http://www.linuxgazette.com/copying.html</A><BR>
|
|
Published in Issue 68 of <i>Linux Gazette</i>, July 2001</H5>
|
|
<!-- *** END copyright *** -->
|
|
|
|
<!--startcut ==========================================================-->
|
|
<HR><P>
|
|
<CENTER>
|
|
<!-- *** BEGIN navbar *** -->
|
|
<IMG ALT="" SRC="../gx/navbar/left.jpg" WIDTH="14" HEIGHT="45" BORDER="0" ALIGN="bottom"><A HREF="ghosh.html"><IMG ALT="[ Prev ]" SRC="../gx/navbar/prev.jpg" WIDTH="16" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="index.html"><IMG ALT="[ Table of Contents ]" SRC="../gx/navbar/toc.jpg" WIDTH="220" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../index.html"><IMG ALT="[ Front Page ]" SRC="../gx/navbar/frontpage.jpg" WIDTH="137" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="http://www.linuxgazette.com/cgi-bin/talkback/all.py?site=LG&article=http://www.linuxgazette.com/issue68/jenkins.html"><IMG ALT="[ Talkback ]" SRC="../gx/navbar/talkback.jpg" WIDTH="121" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><A HREF="../faq/index.html"><IMG ALT="[ FAQ ]" SRC="./../gx/navbar/faq.jpg"WIDTH="62" HEIGHT="45" BORDER="0" ALIGN="bottom"></A><A HREF="mitchell.html"><IMG ALT="[ Next ]" SRC="../gx/navbar/next.jpg" WIDTH="15" HEIGHT="45" BORDER="0" ALIGN="bottom" ></A><IMG ALT="" SRC="../gx/navbar/right.jpg" WIDTH="15" HEIGHT="45" ALIGN="bottom">
|
|
<!-- *** END navbar *** -->
|
|
</CENTER>
|
|
</BODY></HTML>
|
|
<!--endcut ============================================================-->
|