Linux-клиент для Интернет-протокола печати Brother

  Автор: © Graham Jenkins
Перевод: © Павел В. Ступин (Кобальт).


 

Brother - Интернет-протокол печати.

В моей недавней статье Печать через Интернет -- альтернатива я рассказал о протоколе печати, который можно использовать с принтерами Brother. Протокол позволяет пользователям Windows-машин посылать многочастные файлы, закодированные в base-64, по электронной почте напрямую к серверу печати Brother.

Здесь вы найдете логическое продолжение, в котором вам, в частности, продемонстрируется, как функциональность сервера печати Brother может быть реализована в простой программе на Perl, которая периодически обращается к POP3-серверу и проверяет ящик на предмет прибытия новых заданий для печати (определяется целостность задания, и в дальнейшем работа идет только с теми, все части которых прибыли на POP3-сервер). Когда задание обнаруживается, все его части последовательно скачиваются и декодируются для печати.

Клиентская программа для Linux

Вышеупомянутая программа на Perl эксплуатируется у меня уже несколько месяцев, и она существенно упростила для меня работу по распечатке документов Word и других файлов в специфических форматах Microsoft на удаленном принтере. Однако от этого жизнь тех, кто в моей сети пользуется Linux, легче не стала.

Непродолжительные поиски клиента для Linux на сайте Brother не увенчались успехом, поэтому я решил самостоятельно написать такую программу. То, чем это закончилось, описывается ниже.

Реализация

Если руководствоваться здравым смысом, то, вероятно, программа, разбивающая бинарный поток данных на части, для дальнейшего последовательного скармливания частей декодеру, должна быть написана на Perl или C. Но реальность такова, что обычная командная оболочка Bourne shell и ее потомки обладают всеми необходимыми инструментами для решения задачи, когда параллельно еще используются такие классические для Unix/Linux инструменты, как 'split' и 'wc'.

Небольшой анализ программы.

Как видно из листига (текстовая версия программы), программа начинается проверкой того, была ли она вызвана с двумя аргументами; в случае, если это не так, то выводится сообщение о синтаксисе команды. Затем программа определяет функцию, которая будет вызываться позже для печати заголовка на каждой из частей задания, которые затем отсылаются. В частности, эта функция вставляет адрес для уведомления, номер части, размер части и идентификатор задания.

Тело программы начинается генерацией почтового адреса отправителя и "почтового штемпеля" с датой отправки. Эти параметры объединяются и используются для генерации имени временной директории. Здесь установлена специальная ловушка, которая удаляет директории, имеющие аналогичное имя, а затем пытается создать новую временную директорию.

Затем используется Unix/Linux утилита 'split' для разбиения входных данных на части, чей размер задается первым аргументом при запуске программы. Каждая из них скармливается кодировщику base-64 и почтовой программе (с соответствующей преамбулой), направляющей данные на адрес, заданный вторым аргументом.

Программа заканчивается удалением временной директории и возвращением статуса завершения работы.

#!/bin/sh
# BIPclient.sh  Клиентская программа для Интернет-протокола печати Brother.
#               Разбивает входной поток данных на части заданного размера,
#               затем кодирует их в base-64 и посылает по почте с
#               соответствующей преамбулой на заданный почтовый адрес.
#               Graham Jenkins, IBM GSA, Июнь 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 () {                                  # Функция для печати заголовка
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'`                      # Генерирует почтовый адрес,
Dir=/tmp/`basename $0`.$Me$Now                  # дату отправки и имя директории
trap 'rm -rf $Dir;echo Oops>&2;exit 1' 1 2 3 15 # Устанавливает "ловушку" для очистки

mkdir $Dir                      || exit 1       # Создает каталог
split -b ${1}k - $Dir/          || exit 1       # Создает части
Total=`ls $Dir|wc -w |tr -d ' '`|| exit 1       # Считает части

Part=0
for File in `ls $Dir/*` ; do                    # Кодирует и отсылает части
  Part=`expr 1 + $Part`
  [ -t 2 ] && echo "Sending part: $Part/"$Total"  to: $2 .. $Now" >&2
  ( do_header
    base64 $File                                # Использует mmencode или base64
    echo ) | Mail -s "Brother Internet Print Job" $2 
done

rm -rf $Dir                                     # Удаляет рабочий каталог и выходит
exit 0

Ограничения

Ради простоты, функия 'do_header', показанная в листинге, игнорирует некоторые из строк заголовка, которые генерируются Windows-клиентом, и использует значение по умолчанию для параметра 'BRO-SERVICE'. Следовательно, результаты работы программы с настоящим сервером печати Brother. Если у кого-то из читателей есть такой, мне будет интересно узнать, как у них работала программа и какие есть идеи по этому поводу.

Так называемый уникальный идентификатор почтового сообщения на самом деле может дублироваться, если пользователь передаст два задания за одну секунду; это ограничение формата идентификаторов самого Brother. Если необходимо, то можно использовать альтернативный формат, который вставляет номер процесса перед пользовательским почтовым адресом.

И, наконец, создание временной (рабочей) директории для хранения копии файла, который необходимо распечатать, становится проблематичным, если на клиентской машине дисковое пространство для временных файлов явлется ограниченным. Проблема в том, что нам действительно необходимо создавать копию оригинального файла по мере его прибытия так, чтобы в заголовок каждой отправляемой части вставлять корректные данные о том, где находится эта часть в целом файле.

Используя Perl или 'dd', можно создавать и отправлять части сразу же, без использования временных файлов - с учетом того, что в серверную часть программы будут внесены изменения так, чтобы она не требовала того пресловутого представления о том, каково место части в целом файле в заговлоке сообщения. Я с удовольствием поделюсь деталями со всеми, кто заинтересуется таким решением.

Graham Jenkins

Graham является специалистом по UNIX в IBM Global Services, Australia. Он живет в Мельбурне. За свою жизнь он конфигурировал и администрировал широчайший спектр патентованных и открытых систем на различных аппаратных платформах.

 


Copyright © 2001, Graham Jenkins.
Copying license http://www.linuxgazette.com/copying.html
Published in Issue 68 of Linux Gazette, July 2001

Вернуться на главную страницу