Глава 10. Печать

10.1. Краткий обзор

FreeBSD можно использовать для печати на широком спектре принтеров, от старых матричных до новейших лазерных, без исключений, что позволяет создавать высококачественные распечатки из используемых приложений.

FreeBSD можно также сконфигурировать для работы в качестве сервера печати в сети; в этом качестве FreeBSD может получать задания печати от множества других компьютеров, включая другие компьютеры под управлением ОС FreeBSD, хосты Windows® и Mac OS®. FreeBSD будет гарантировать печать заданий по одному и может сохранять информацию о том, какие пользователи и машины выполняют основную часть печати, выдавать страницы-"баннеры", показывающие, кому принадлежит распечатка, и многое другое.

При прочтении этой главы вы узнаете:

  • Как конфигурировать спулер печати FreeBSD.

  • Как устанавливать фильтры печати для специфической обработки определенных заданий печати, включая преобразование поступающих на печать документов в форматы, которые понимает принтер.

  • Как включить при печати колонтитулы или выдачу страниц-баннеров.

  • Как печатать на принтеры, подключенные к другим компьютерам.

  • Как печатать на принтеры, подключенные непосредственно к сети.

  • Как задавать ограничения для принтера, включая ограничение размера заданий печати и запрет печати для отдельных пользователей.

  • Как сохранять статистическую информацию о печати и учитывать использование принтера.

  • Как решать проблемы печати.

Прежде чем читать эту главу, вы должны:

10.2. Введение

Для использования принтеров в ОС FreeBSD вы можете настроить их для работы с системой спулинга печати Беркли (Berkeley line printer spooling system), также известной как система спулинга LPD. Это - стандартная система управления принтером во FreeBSD. В этой главе представлена система спулинга LPD и описано ее конфигурирование.

Если вы уже знакомы с LPD или другой системой спулинга печати, вы можете сразу перейти к разделу Базовая настройка.

LPD управляет всеми аспектами работы принтеров хоста. Она отвечает за несколько вещей:

  • Она управляет доступом к непосредственно подключенным принтерам и принтерам, подключенным к другим хостам в сети.

  • Она позволяет пользователям посылать файлы на печать; эти данные называют заданиями.

  • Она предотвращает одновременный доступ к принтеру нескольких пользователей путем поддержки очереди для каждого принтера.

  • Она позволяет печатать страницы заголовка (их также называют баннерными или начальными страницами), чтобы пользователи могли легко находить распечатанные задания в пачке распечаток.

  • Она обеспечивает установку параметров взаимодействия для принтеров, подключенных к последовательным портам.

  • Она может отправлять задания по сети спулеру LPD на другом хосте.

  • Она может применять специальные фильтры для форматирования заданий для печати на разных языках описания страниц или задействования специфических возможностей принтера.

  • Она учитывает использование принтера.

С помощью файла конфигурации (/etc/printcap) и за счет предоставления специальных программ фильтрования, можно потребовать от системы LPD выполнять все или некоторые из перечисленных выше функций на широком спектре принтерного оборудования.

10.2.1. Зачем использовать спулер

Если вы - единственный пользователь системы, вы можете спросить, зачем возиться со спулером, если управление доступом, страницы заголовка или учет использования принтера вам не нужны. Хотя можно обеспечить непосредственный доступ к принтеру, в любом случае следует использовать спулер, поскольку:

  • LPD печатает задания в фоновом режиме; вам не придется ждать, пока данные будут скопированы на принтер.

  • LPD позволяет легко пропустить задание печати через фильтры для добавления заголовков с датой/временем или преобразования специального формата файлов (такого как TeX DVI) в формат, который понимает принтер. Вам не придется выполнять эти шаги вручную.

  • Многие свободно распространяемые и коммерческие программы, обеспечивающие возможность печати, обычно предполагают взаимодействие со спулером системы. Путем настройки системы спулинга вы упростите поддержку другого программного обеспечения, которое может быть добавлено в дальнейшем или уже установлено.

10.3. Основная настройка

Для использования принтеров с системой спулинга LPD, необходимо настроить как сам принтер, так и программное обеспечение LPD. Этот документ описывает два уровня настройки:

  • См. раздел Простая настройка принтера, чтобы узнать, как подключить принтер, объяснить LPD, как с ним взаимодействовать, и отправлять на принтер простые текстовые файлы.

  • См. раздел Расширенная настройка принтера, чтобы узнать, как печатать файлы множества специальных форматов, как печатать страницы заголовка, печатать по сети, управлять доступом к принтерам и учитывать использование принтера.

10.3.1. Простая настройка принтера

В этом разделе описано, как сконфигурировать принтер и программное обеспечение LPD для использования принтера. Здесь рассматриваются следующие вопросы:

Если вы настраиваете принтер, использующий для принятия заданий печати сетевой протокол, вместо локальных интерфейсов компьютера, см. раздел Принтеры с сетевыми интерфейсами.

Хотя этот раздел и назван "Простая настройка принтера", это, на самом деле, достаточно сложно. Заставить принтер работать с компьютером и спулером LPD - самая сложная часть. Расширенные опции, вроде выдачи страниц заголовков и учета использования, установить несложно, как только принтер заработает.

10.3.1.1. Настройка оборудования

В этом разделе описаны различные способы подключения принтера к ПК. Рассматриваются различные порты и кабели, а также параметры конфигурации ядра, которые может потребоваться установить, чтобы ОС FreeBSD могла взаимодействовать с принтером.

Если вы уже подключили ваш принтер и успешно печатали на него в другой операционной системе, можете перейти к разделу Настройка программного обеспечения.

10.3.1.1.1. Порты и кабели

Принтеры, которые продаются сегодня для использования на ПК, обычно поддерживают один или несколько из следующих интерфейсов:

  • Последовательные интерфейсы, также известные как RS-232, или COM-порты, используют для посылки данных на принтер последовательный порт компьютера. Последовательные интерфейсы широко распространены в компьютерной индустрии, кабели для них легко найти и просто сделать. Для последовательных интерфейсов иногда нужны специальные кабели, и для их использования может потребоваться настраивать достаточно сложные опции взаимодействия. Большинство последовательных портов ПК имеют максимальную скорость передачи 115200 бит/сек, поэтому печатать через них большие графические задания неудобно.

  • Параллельные интерфейсы используют параллельный порт компьютера для посылки данных на принтер. Параллельные интерфейсы широко распространены на рынке ПК и работают быстрее, чем последовательные RS-232. Кабели легко найти, но сделать самостоятельно сложнее. При использовании параллельных интерфейсов опции взаимодействия обычно задавать не надо, что делает их конфигурирование существенно проще.

    Параллельные интерфейсы иногда называют интерфейсами "Centronics", по названию типа разъема на принтере.

  • Интерфейсы USB (сокращение от Universal Serial Bus - универсальная последовательная шина), могут работать на еще больших скоростях, чем параллельные или последовательные интерфейсы RS-232. Кабели для них - простые и дешевые. USB превосходит последовательный RS-232 и параллельный интерфейсы для печати, но не слишком хорошо поддерживается в UNIX®-системах. Обойти эту проблему можно, купив принтер с двумя интерфейсами, USB и параллельным, как у многих принтеров.

В общем случае, параллельные интерфейсы обычно обеспечивают только одностороннюю передачу (с компьютера на принтер), тогда как последовательные и USB поддерживают двустороннюю. Более новые параллельные порты (EPP и ECP) и принтеры могут взаимодействовать в обоих направлениях под FreeBSD, если используется кабель, соответствующий стандарту IEEE-1284.

Двустороннее взаимодействие с принтером через параллельный порт обычно выполняется одним из двух способов. Первый метод опирается на использование специально созданного драйвера принтера для FreeBSD, который поддерживает специфический язык данного принтера. Этот метод типичен для струйных принтеров и может использоваться для получения информации об уровне чернил и другой информации о состоянии. Второй метод используется, когда принтер поддерживает PostScript®.

Фактически, задания PostScript® являются программами, посылаемыми для выполнения принтеру; они вообще могут не выдавать результат на бумагу и возвращать его непосредственно компьютеру. PostScript® также использует двустороннее взаимодействие для сообщения компьютеру о проблемах, таких как ошибки в PostScript®-программе или замятие бумаги. Такая информация может пригодиться пользователям. Более того, лучший способ эффективного учета использования PostScript®-принтера требует двустороннего взаимодействия: вы запрашиваете у принтера значение счетчика страниц (сколько страниц напечатал принтер за все время существования), затем посылаете задание пользователя, затем снова запрашиваете значение его счетчика страниц. Вычитаем одно значение из другого, и узнаем, сколько бумаги потратил пользователь.

10.3.1.1.2. Параллельные порты

Для подключения принтера через параллельный интерфейс, соедините принтер и компьютер кабелем Centronics. Инструкции для принтера, для компьютера или обе должны полностью описывать эту процедуру.

Помните, какой параллельный порт компьютера вы использовали. Первый параллельный порт в ОС FreeBSD - ppc0; второй - ppc1, и так далее. Имена устройств для принтеров используют ту же схему: /dev/lpt0 для принтера на первом параллельном порту и т.д.

10.3.1.1.3. Последовательные порты

Для подключения принтера через последовательный интерфейс, соедините принтер с компьютером подходящим последовательным кабелем. Инструкции для принтера, для компьютера или обе должны полностью описывать эту процедуру.

Если вы не знаете, что такое "подходящий последовательный кабель", можете попробовать использовать один из следующих:

  • Модемный кабель соединяет каждый штырёк на одном конце кабеля напрямую с соответствующим штырьком на другом конце. Кабель такого типа также называют кабелем "DTE-to-DCE". *

    Нуль-модемный кабель соединяет часть штырьков напрямую, другие - меняет (пересылку данных на приём данных, например), а некоторые - закорачивает на каждом разъеме. Кабель такого типа также называют кабелем "DTE-to-DTE" cable.

  • Кабель последовательного принтера, необходимый для некоторых редко используемых принтеров, похож на нуль-модемный кабель, но посылает часть сигналов на соответствующие штырьки, а не закорачивает их.

Вам надо также настроить эти параметры взаимодействия с принтером, обычно - через элементы управления на лицевой панели или переключатели (DIP switches) на принтере. Выберите максимальную скорость передачи bps (бит в секунду, иногда - baud rate), которую могут поддерживать как компьютер, так и принтер. Выберите 7 или 8 битов данных; четность none, even или odd; и 1 или 2 стоп-бита. Также надо выбрать протокол управления передачей: none или XON/XOFF (также известный как "внутриполосный" или "программный"). Запомните выбранные установки для последующего конфигурирования программного обеспечения.

10.3.1.2. Настройка программного обеспечения

В этом разделе описана настройка программного обеспечения, необходимая для печати с помощью системы спулинга LPD в ОС FreeBSD.

Вот план действий, которые необходимо выполнить:

  1. При необходимости, сконфигурировать в ядре поддержку порта, к которому подключен принтер; в разделе Конфигурирование ядра описано, что надо сделать.

  2. Установить режим взаимодействия для параллельного порта, если используется параллельный порт; детали представлены в разделе Настройка режима взаимодействия для параллельного порта.

  3. Проверить, может ли операционная система посылать данные на принтер. В разделе Проверка взаимодействия с принтером даны советы, как это сделать.

  4. Настроить LPD для принтера, изменяя файл /etc/printcap. Как это сделать описано далее в этой главе.

10.3.1.2.1. Конфигурирование ядра

Ядро операционной системы компилируется для работы с конкретным набором устройств. Последовательный или параллельный интерфейс для принтера входит в этот набор. Поэтому может понадобиться добавить поддержку для дополнительного последовательного или параллельного порта, если он еще не сконфигурирован в ядре.

Чтобы узнать, поддерживает ли используемое в настоящий момент ядро последовательный интерфейс, наберите:

# grep sioN /var/run/dmesg.boot

Где N - номер последовательного порта, начиная с нуля. Если вы получаете результат, подобный следующему:

sio2 at port 0x3e8-0x3ef irq 5 on isa
sio2: type 16550A

значит, ядро поддерживает порт.

Чтобы узнать, поддерживает ли ядро параллельный интерфейс, наберите:

# grep ppcN /var/run/dmesg.boot

Где N номер параллельного порта, начиная с нуля. Если вы получаете результат, подобный следующему:

ppc0: <Parallel port> at port 0x378-0x37f irq 7 on isa0
ppc0: SMC-like chipset (ECP/EPP/PS2/NIBBLE) in COMPATIBLE mode
ppc0: FIFO with 16/16/8 bytes threshold

значит, ядро поддерживает порт.

Может потребоваться переконфигурировать ядро, чтобы операционная система распознала и использовала параллельный или последовательный порт, используемый для подключения принтера.

Чтобы добавить поддержку последовательного порта, обратитесь к разделу, посвященному конфигурированию ядра. Чтобы добавить поддержку параллельного порта, почитайте этот же раздел и следующий раздел.

10.3.1.3. Настройка режима взаимодействия для параллельного порта

При использовании параллельного интерфейса можно выбрать, должна ли ОС FreeBSD взаимодействовать с принтером на основе прерываний или путем опроса. Универсальный драйвер принтера (lpt(4)) во FreeBSD использует систему ppbus(4), которая управляет чипсетом порта с помощью драйвера ppc(4).

  • Метод взаимодействия на основе прерываний является стандартным для ядра GENERIC. По этому методу, операционная система использует линию запроса прерывания (IRQ line) для определения готовности принтера к приему данных.

  • Метод взаимодействия путем опроса требует от операционной системы постоянно запрашивать принтер, готов ли он к приему данных. Когда он отвечает, что готов, ядро посылает дополнительные данные.

Метод взаимодействия на основе прерываний обычно работает несколько быстрее, но использует ценную линию запроса прерывания. Про некоторые новые принтеры HP утверждают, что они работают некорректно в режиме взаимодействия на основе прерываний, вероятно, из-за некоторой (еще не вполне понятной) проблемы синхронизации. Для этих принтеров необходимо устанавливать режим опроса. Используйте тот режим, который работает. Некоторые принтеры будут работать в обоих режимах, но оказываются крайне медленными в режиме на основе прерываний.

Режим взаимодействия можно установить двумя способами: конфигурируя ядро или с помощью программы lptcontrol(8).

Для установки режима взаимодействия путем конфигурирования ядра:

  1. Отредактируйте файл конфигурации ядра. Найдите запись ppc0. Если вы настраиваете второй параллельный порт, ищите запись ppc1. Используйте запись ppc2 для третьего порта, и так далее.

    • Если необходимо установить режим на основе прерываний, отредактируйте следующую строку:

      hint.ppc.0.irq="N"

      в файле /boot/device.hints, заменив N соответствующим номером IRQ. Файл конфигурации ядра также должен содержать драйвер ppc(4):

      device ppc
    • Если необходимо установить режим опроса, удалите из файла /boot/device.hints следующую строку:

      hint.ppc.0.irq="N"

      В некоторых случаях, этого недостаточно для перевода порта в режим опроса под FreeBSD. Чаще всего, проблема связана с драйвером acpi(4), который может опрашивать и подключать устройства и, тем самым, управлять режимом доступа к порту принтера. Чтобы решить эту проблему, проверьте конфигурацию acpi(4).

  2. Сохраните файл. Затем сконфигурируйте, соберите и установите ядро и перезагрузите систему. Подробнее см. в разделе конфигурирование ядра.

Для настройки режима взаимодействия с помощью утилиты lptcontrol(8):

  1. Введите команду:

    # lptcontrol -i -d /dev/lptN

    для установки режима взаимодействия на основе прерываний для lptN.

  2. Введите команду:

    # lptcontrol -p -d /dev/lptN

    для установки режима взаимодействия по опросу для lptN.

Вы можете поместить эти команды в файл /etc/rc.local для установки требуемого режима при каждой загрузке системы. Дополнительную информацию об этом ищите на странице справочного руководства lptcontrol(8).

10.3.1.4. Проверка взаимодействия с принтером

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

Для тестирования принтера мы пошлем на него текст. Для принтеров, которые могут непосредственно печатать посланные на них символы, идеально подходит программа lptest(1): она генерирует все 96 печатных символов ASCII в 96 строках.

Для PostScript®- (или основанного на другом языке) принтера, необходим более сложный тест. Подойдет небольшая PostScript®-программа, вроде следующей:

%!PS
100 100 moveto 300 300 lineto stroke
310 310 moveto /Helvetica findfont 12 scalefont setfont
(Is this thing working?) show
showpage

Представленный выше PostScript®-код можно поместить в в файл и использовать, как показано в примерах в следующих разделах.

Когда в этом документе речь идет о языке принтера, подразумевается язык типа PostScript®, а не PCL компании Hewlett Packard. Хотя PCL имеет прекрасные функциональные возможности, в нем можно смешивать обычный текст с его управляющими последовательностями. PostScript® не позволяет непосредственно печатать обычный текст, и это язык принтера именно того рода, для которого надо выполнять специальные настройки.

10.3.1.4.1. Проверка параллельного принтера

В этом разделе описано, как проверить, может ли ОС FreeBSD взаимодействовать с принтером, подключенным к параллельному порту.

Для тестирования принтера на параллельном порту:

  1. Станьте пользователем root с помощью команды su(1).

  2. Пошлите данные на принтер.

    • Если принтер может печатать обычный текст, используйте утилиту lptest(1). Введите команду:

      # lptest > /dev/lptN

      Где N - номер параллельного порта, начиная с нуля.

    • Если принтер понимает PostScript® или другой язык принтера, пошлите на принтер небольшую программу. Введите команду:

      # cat > /dev/lptN

      Затем, построчно, внимательно введите программу, поскольку вы не сможете отредактировать строку после нажатия клавиши RETURN или ENTER. По окончании ввода программы, нажмите CONTROL+D или другую комбинацию клавиш, используемую для ввода символа конца файла.

      Можно также поместить программу в файл и выполнить команду:

      # cat file > /dev/lptN

      Где file - имя файла, содержащего программу, которую вы хотите послать принтеру.

Вы должны увидеть распечатку. Не переживайте, если текст выглядит не так, как предполагалось; этими проблемами мы займемся позже.

10.3.1.4.2. Проверка последовательного принтера

В этом разделе описано, как проверить, может ли ОС FreeBSD взаимодействовать с принтером, подключенным к последовательному порту.

Для тестирования принтера на последовательном порту:

  1. Станьте пользователем root с помощью команды su(1).

  2. Отредактируйте файл /etc/remote. Добавьте следующую запись:

    printer:dv=/dev/port:br#bps-rate:pa=parity

    Где port - специальный файл устройства для последовательного порта (ttyd0, ttyd1 и т.д.), bps-rate - скорость обработки данных принтером, в битах в секунду, а parity - требуемая принтером четность (значение even, odd, none или zero).

    Вот пример записи для принтера, подключенного к третьему последовательному порту на скорости 19200 bps без четности:

    printer:dv=/dev/ttyd2:br#19200:pa=none
  3. Подключитесь к принтеру с помощью tip(1). Введите команду:

    # tip printer

    Если этот шаг не срабатывает, снова отредактируйте файл /etc/remote и попробуйте использовать устройство /dev/cuaaN вместо /dev/ttydN.

  4. Пошлите данные на принтер.

    • Если принтер может печатать обычный текст, используйте утилиту lptest(1). Введите команду:

      % $lptest
    • Если принтер понимает PostScript® или другой язык принтера, пошлите на принтер небольшую программу. Вводите программу, построчно, очень внимательно, поскольку нажатие клавиши Backspacе или других клавиш редактирования может иметь значение для принтера. Может также понадобиться нажать специальную комбинацию клавиш, обозначающую конец файла, чтобы принтер понял, что получена вся программа. Для PostScript®-принтеров нажмите CONTROL+D.

      Можно также поместить программу в файл и ввести команду:

      % >file

      Где file - имя файла, содержащего программу. После того, как утилита tip(1) пошлет файл, нажмите требуемую для ввода признака конца файла комбинацию клавиш.

Вы должны увидеть распечатку. Не переживайте, если текст выглядит не так, как предполагалось; этими проблемами мы займемся позже.

10.3.1.5. Включение спулера: файл /etc/printcap

Сейчас ваш принтер уже должен быть подключен, ядро (при необходимости) - сконфигурировано для взаимодействия с ним, и вы смогли послать на принтер простые данные. Теперь мы готовы к конфигурированию системы LPD для управления доступом к принтеру.

Система LPD конфигурируется путем редактирования файла /etc/printcap. Система спулинга LPD читает этот файл при каждом использовании спулера, так что, изменения в файле сразу же учитываются.

Формат файла printcap(5) прост. Используйте свой любимый текстовый редактор для изменения файла /etc/printcap. Формат файла идентичен формату других файлов, описывающих характеристики, например, /usr/shared/misc/termcap и /etc/remote. Полная информация о формате представлена на странице справочного руководства cgetent(3).

Простое конфигурирование спулера включает следующие шаги:

  1. Выберите имя (и несколько удобных псевдонимов) для принтера и поместите их в файл /etc/printcap; подробнее об именовании см. в разделе Именование принтера.

  2. Отключите выдачу начальных страниц (которые по умолчанию выдаются), вставив характеристику sh; подробнее об этом см. в разделе Подавление выдачи начальных страниц.

  3. Создайте каталог для спулинга и укажите его местонахождение с помощью характеристики sd; подробнее об этом см. в разделе Создание каталога спулинга.

  4. Выберите специальный файл устройства /dev для использования с принтером и укажите его в файле /etc/printcap с помощью характеристики lp; подробнее об этом см. в разделе Выбор устройства для принтера. Кроме того, если принтер подключен к последовательному порту, настройте параметры взаимодействия с помощью характеристики ms#, которая обсуждается в разделе Конфигурирование параметров взаимодействия для спулера.

  5. Установите фильтр для обычного текста; подробнее об этом см. в разделе Установка текстового фильтра.

  6. Проверьте настройку, напечатав что-нибудь с помощью команды lpr(1). Подробнее об этом см. в разделах Проверка и Выявление проблем.

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

Пользователи часто предполагают, что они могут печатать обычный текст на любом из установленных в системе принтеров. Программы, взаимодействующие для обеспечения печати с системой LPD, обычно исходят из этого же предположения. Если вы устанавливаете такой принтер и хотите иметь возможность посылать на печать задания на языке принтера и в виде обычного текста, настоятельно рекомендуется добавить дополнительный шаг к представленной выше простой последовательности настройки: установите программу автоматического преобразования обычного текста в PostScript® (или другой язык принтера). В разделе Прием заданий с обычным текстом на PostScript®-принтеры рассказано, как это сделать.

10.3.1.5.1. Именование принтера

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

По крайней мере, один из принтеров, указанных в файле /etc/printcap, должен иметь псевдоним lp. Это - стандартное имя принтера. Если пользователи не установят переменную среды PRINTER и не укажут имя принтера в командной сроке при вводе любой команды системы LPD, по умолчанию для ее выполнения будет использован принтер lp.

Также широко распространена практика в качестве последнего псевдонима для принтера задавать полное его описание, включая производителя и модель.

После выбора имени и нескольких популярных псевдонимов поместите их в файл /etc/printcap. Имя принтера должно начинаться с крайнего левого столбца. Каждый псевдоним отделяйте вертикальной чертой, а после последнего псевдонима поместите двоеточие.

В следующем примере мы начнем со скелетного файла /etc/printcap, определяющего два принтера (построчный принтер Diablo 630 и лазерный PostScript®-принтер Panasonic KX-P4455):

#
#  /etc/printcap для хоста rose
#
rattan|line|diablo|lp|Diablo 630 Line Printer:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:

В этом примере первый принтер назван rattan и ему заданы псевдонимы line, diablo, lp и Diablo 630 Line Printer. Поскольку у него есть псевдоним lp, он является стандартным принтером. Второму принтеру дано имя bamboo и ему заданы псевдонимы ps, PS, S, panasonic и Panasonic KX-P4455 PostScript v51.4.

10.3.1.5.2. Подавление выдачи начальных страниц

Система спулинга LPD будет по умолчанию печатать заголовочную страницу для каждого задания. Заголовочная страница содержит имя пользователя, отправившего задание, хост, с которого поступило задание, и имя задания, красивыми большими буквами. К сожалению, все эти дополнительные тексты мешают отладке простой настройки принтера, поэтому мы будет отключать выдачу начальных страниц.

Для подавления выдачи начальных страниц добавьте характеристику sh к записи принтера в файле /etc/printcap. Вот пример файла /etc/printcap с добавлением sh:

#
#  /etc/printcap для хоста rose - никаких начальных страниц
#
rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :sh:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:

Обратите внимание, как мы использовали правильный формат: первая строка начинается с самого левого столбца, а последующие строки смещены. Каждая строка в записи, кроме последней, завершается символом обратной косой черты.

10.3.1.5.3. Создание каталога для спулинга

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

Из-за присущих каталогам спулинга постоянных изменений, принято помещать эти каталоги в каталог /var/spool. Кроме того, не нужно создавать резервные копии содержимого каталогов спулинга. Пересоздать их можно с помощью простой команды mkdir(1).

Принято также задавать для каталога имя, совпадающее с именем принтера, как показано ниже:

# mkdir /var/spool/имя-принтера

Однако при наличии большого количества принтеров в сети может иметь смысл поместить все каталоги спулинга в один каталог, который просто резервируется для печати с помощью LPD. Мы сделаем это для наших двух принтеров, rattan и bamboo:

# mkdir /var/spool/lpd
# mkdir /var/spool/lpd/rattan
# mkdir /var/spool/lpd/bamboo

Если вас интересует конфиденциальность заданий, отправляемых пользователями на печать, можно защитить каталог спулинга, чтобы он не был общедоступным. Каталоги спулинга должны принадлежать и быть доступны на чтение, запись и просмотр содержимого пользователю daemon и группе daemon, и никому больше. Мы установим это для каталогов спулинга принтеров из нашего примера:

# chown daemon:daemon /var/spool/lpd/rattan
# chown daemon:daemon /var/spool/lpd/bamboo
# chmod 770 /var/spool/lpd/rattan
# chmod 770 /var/spool/lpd/bamboo

Наконец, надо сообщить системе LPD об этих каталогах с помощью файла /etc/printcap. Полное имя каталога спулинга задается с помощью характеристики sd:

#
#  /etc/printcap для хоста rose - добавлены каталоги спулинга
#
rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :sh:sd=/var/spool/lpd/rattan:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:sd=/var/spool/lpd/bamboo:

Обратите внимание, что имя принтера начинается с самого первого столбца, а все последующие строки смещены, и каждая строка в записи, кроме последней, завершается символом обратной косой черты.

Если вы не зададите каталог спулинга с помощью характеристики sd, система спулинга будет использовать по умолчанию каталог /var/spool/lpd.

10.3.1.5.4. Выбор устройства для принтера

Мы выяснили, какой специальный файл устройства в каталоге /dev FreeBSD будет использовать для взаимодействия с принтером. Теперь мы сообщаем эту информацию системе LPD. Когда у системы спулинга есть задание для печати, она будет открывать указанное устройство от имени программы-фильтра (которая отвечает за передачу данных на принтер).

Задайте полное имя устройства /dev в файле /etc/printcap с помощью характеристики lp.

В нашем текущем примере давайте предположим, что принтер rattan подключен к первому параллельному порту, а принтер bamboo - к шестому последовательному порту; вот что нужно добавить в файл /etc/printcap:

#
#  /etc/printcap для хоста rose - указано, какие устройства использовать
#
rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :sh:sd=/var/spool/lpd/rattan:\
        :lp=/dev/lpt0:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:sd=/var/spool/lpd/bamboo:\
        :lp=/dev/ttyd5:

Если вы не укажете характеристику lp для принтера в файле /etc/printcap, система LPD использует по умолчанию устройство /dev/lp. Устройство /dev/lp сейчас в ОС FreeBSD не существует.

Если устанавливаемый принтер подключен к параллельному порту, перейдите к разделу Установка текстового фильтра. Иначе выполните сначала инструкции, представленные в следующем разделе.

10.3.1.5.5. Конфигурирование параметров взаимодействия спулера

Для принтеров на последовательных портах система LPD может устанавливать скорость передачи, четность и другие параметры взаимодействия через последовательных порт от имени программы-фильтра, которая посылает данные на принтер. Это полезно потому, что:

  • Позволяет опробовать различные параметры взаимодействия, просто редактируя файл /etc/printcap; программу-фильтр перекомпилировать не нужно.

  • Позволяет системе спулинга использовать одну и ту же программу-фильтр для нескольких принтеров, которые могут иметь различные установки для взаимодействия через последовательный порт.

Следующие характеристики в файле /etc/printcap задают параметры взаимодействия через последовательный порт для устройства, указанного в качестве значения характеристики lp:

br#bps-rate

Устанавливает скорость взаимодействия для устройства в bps-rate, где bps-rate может иметь значение 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600 или 115200 бит в секунду.

ms#stty-mode

Устанавливает опции для терминального устройства после открытия устройства. Поддерживаемые опции описаны на странице справочного руководства stty(1).

Когда система LPD открывает устройство, заданное характеристикой lp, она устанавливает опции устройства в соответствии со значением характеристики ms#. Наибольший интерес представляют режимы parenb, parodd, cs5, cs6, cs7, cs8, cstopb, crtscts и ixon, которые описаны на странице справочного руководства stty(1).

Давайте зададим опции для нашего принтера на шестом последовательном порту. Мы установим скорость передачи 38400. В качестве режима установим режим без четности с помощью -parenb, 8-битовые символы с помощью cs8, отсутствие модемного управления с помощью clocal и аппаратное управление потоком с помощью опции crtscts:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:sd=/var/spool/lpd/bamboo:\
        :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:
10.3.1.5.6. Установка текстового фильтра

Теперь мы готовы задать системе LPD, какой текстовый фильтр использовать для посылки заданий на принтер. Текстовый фильтр, известный также как входной фильтр, - это программа, которую система LPD запускает при получении задания на печать. Когда система LPD запускает текстовый фильтр для принтера, она направляет на стандартный входной поток фильтра задание печати, а его стандартный выходной поток - на устройство принтера, заданное характеристикой lp. Предполагается, что фильтр прочитает задание из стандартного входного потока, выполнит все необходимые для принтера преобразования и выдаст результат в стандартный выходной поток, который и будет напечатан. Подробнее о текстовом фильтре см. в разделе Фильтры.

Для простой настройки принтера в качестве текстового фильтра можно задать небольшой скрипт командного интерпретатора, который просто выполняет /bin/cat для посылки задания на принтер. В составе FreeBSD поставляется другой фильтр, lpf, обрабатывающий забой и подчеркивание для принтеров, которые не слишком хорошо справляются с потоком данных, содержащих такие символы. И, конечно же, вы можете использовать любую другую необходимую программу-фильтр. Фильтр lpf детально описан в разделе lpf: текстовый фильтр.

Сначала давайте создадим скрипт командного интерпретатора /usr/local/libexec/if-simple для простого тестового фильтра. Поместите в этот файл следующий текст с помощью любимого текстового редактора:

#!/bin/sh
#
# if-simple - Простой фильтр входного текста для lpd
# Установлен в /usr/local/libexec/if-simple
#
# Просто копирует stdin в stdout. Игнорирует все аргументы фильтра.

/bin/cat && exit 0
exit 2

Сделайте этот файл выполняемым:

# chmod 555 /usr/local/libexec/if-simple

А теперь потребуйте от системы LPD его использовать, указав его в качестве значения характеристики if в файле /etc/printcap. Мы добавим его для двух принтеров, имеющихся пока в примере файла /etc/printcap:

#
#  /etc/printcap для хоста rose - добавлен текстовый фильтр
#
rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :sh:sd=/var/spool/lpd/rattan:\ :lp=/dev/lpt0:\
        :if=/usr/local/libexec/if-simple:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:sd=/var/spool/lpd/bamboo:\
        :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:\
        :if=/usr/local/libexec/if-simple:

Копию скрипта if-simple можно найти в каталоге /usr/shared/examples/printing.

10.3.1.5.7. Запуск системы LPD

Даемон lpd(8) запускается из /etc/rc, а необходимость запуска задается переменной lpd_enable. Эта переменная по умолчанию имеет значение NO. Если вы еще этого не сделали, добавьте строку:

lpd_enable="YES"

в файл /etc/rc.conf, а затем либо перезапустите машину, либо просто выполните команду lpd(8).

# lpd
10.3.1.5.8. Проверка

Вы добрались до конца простой настройки системы LPD. К сожалению, поздравлять вас еще рано, поскольку надо еще проверить настройку и устранить все выявленные проблемы. Для проверки настройки, попытайтесь что-то распечатать. Для печати с помощью системы LPD используется команда lpr(1), которая посылает задание на печать.

Можно скомбинировать lpr(1) с программой lptest(1), представленной в разделе Проверка взаимодействия с принтером, генерирующей тестовый текст.

Для тестирования простой настройки LPD:

Введите команду:

# lptest 20 5 | lpr -Pprinter-name

Где printer-name - имя (или псевдоним) принтера, заданное в файле /etc/printcap. Для проверки стандартного принтера, введите команду lpr(1) без аргумента -P. Как уже отмечалось, если тестируется принтер, предполагающий использование PostScript®, пошлите ему PostScript®-программу вместо использования утилиты lptest(1). Это можно сделать, поместив программу в файл и выполнив команду lpr file.

Для PostScript®-принтера вы должны получить результаты выполнения программы. Если вы используете lptest(1), ваши результаты должны иметь такой вид:

!"#$%&'()*+,-./01234
"#$%&'()*+,-./012345
#$%&'()*+,-./0123456
$%&'()*+,-./01234567
%&'()*+,-./012345678

Для дальнейшего тестирования принтера, попытайтесь загрузить программы побольше (для принтеров, поддерживающих определенный язык) или выполните команду lptest(1) с другими аргументами. Например, команда lptest 80 60 выдаст 60 строк по 80 символов в каждой.

Если принтер не работает, см. раздел Выявление проблем.

10.4. Расширенная настройка принтера

В этом разделе описаны фильтры для печати специально сформатированных файлов, начальных страниц, печати по сети, ограничения и учета использования принтера.

10.4.1. Фильтры

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

Однако, чтобы обеспечить преобразования формата, учет использования принтера и индивидуальных особенностей отдельных принтеров и т.п., надо разобраться, как работают фильтры. В конечном итоге, всеми этими аспектами печати должен заниматься фильтр. А плохая новость состоит в том, что, в большинстве случаев, вы сами должны предоставить соответствующие фильтры. Хорошая новость состоит в том, что многие фильтры общедоступны; а если подходящих нет, их обычно легко написать.

Кроме того, в составе ОС FreeBSD поставляется один фильтр, /usr/libexec/lpr/lpf, работающий со многими принтерами, которые могут печатать обычный текст. (Он обрабатывает символы забоя и табуляции в файле, выполняет учет использования, но и не более того.) Есть также ряд фильтров и компонентов фильтров в наборе портов FreeBSD.

Вот что вы найдете в этом разделе:

  • В разделе Как работают фильтры сделана попытка дать обзор роли фильтра в процессе печати. Прочтите этот раздел, чтобы понять, что происходит "за кадром", когда система LPD использует фильтры. Это понимание поможет предвидеть и решать проблемы, с которыми вы можете столкнуться при добавлении дополнительных фильтров для каждого из принтеров.

  • Система LPD предполагает, что каждый принтер, по умолчанию, может печатать обычный текст. Это проблематично для PostScript®-принтеров (или принтеров на базе другого языка), поскольку они не могут печатать обычный текст непосредственно. В разделе Прием заданий с обычным текстом на PostScript®-принтеры описано, что нужно сделать, чтобы решить эту проблему. Прочтите этот раздел, если используете PostScript®-принтер.

  • PostScript® - популярный формат выдачи для многих программ. Некоторые люди даже пишут PostScript®-код непосредственно. К сожалению, PostScript®-принтеры дороги. В разделе Имитация PostScript® на не-PostScript® принтерах описано, как можно дополнительно изменить текстовый фильтр принтера для приема и печати данных PostScript® не не-PostScript® принтере. Прочтите этот раздел, если ваш принтер не поддерживает PostScript®.

  • В разделе Фильтры преобразования описан способ автоматизации преобразования определенных форматов файлов, например, графики или данных для печатного станка, в форматы, которые может обработать ваш принтер. После чтения этого раздела вы сможете настроить свои принтеры так, что пользователи смогут выполнять команду lpr -t для печати данных troff, или lpr -d для печати данных TeX DVI, или lpr -v - для печати растровых изображений, и так далее. Я рекомендую прочитать этот раздел.

  • В разделе Выходные фильтры описана не часто используемая возможность задавать выходные фильтры в системе LPD. Если только вы не печатаете начальные страницы (см. Начальные страницы), можно, пожалуй, вообще пропустить этот раздел.

  • В разделе lpf: текстовый фильтр описана команда lpf, - достаточно полный, хотя и простой текстовый фильтр для строчных принтеров (и лазерных принтеров, работающих как строчные), поставляемый в составе ОС FreeBSD. Если надо быстро настроить учет использования принтера для обычного текста или если используется принтер, из которого при получении символов забоя идет дым, несомненно, стоит подумать об использовании lpf.

Различные скрипты, описанные далее, можно найти в каталоге /usr/shared/examples/printing.

10.4.1.1. Как работают фильтры

Как уже упоминалось, фильтр - это выполняемая программа, запускаемая системой LPD для поддержки специфических особенностей устройства при взаимодействии с принтером.

Когда системе LPD надо напечатать входящий в задание файл, она запускает программу-фильтр. Стандартный входной поток фильтра связывается с файлом, который надо распечатать, его стандартный выходной поток - с принтером, а стандартный поток ошибок перенаправляется в файл регистрации ошибок (задается характеристикой lf в файле /etc/printcap, или используется стандартное устройство /dev/console).

Запускаемый системой LPD фильтр и его аргументы зависят от того, что указано в файле /etc/printcap, и какие аргументы указал пользователь для задания в команде lpr(1). Например, если пользователь ввел команду lpr -t, система LPD должна запустить фильтр troff, заданный характеристикой tf для соответствующего принтера. Если пользователь хочет печатать обычный текст, система должна запустить фильтр if (это верно в большинстве случаев: подробнее см. в разделе Выходные фильтры).

В файле /etc/printcap можно задавать три вида фильтров:

  • Текстовый фильтр, который в документации LPD двусмысленно называют входным фильтром, обеспечивает печать обычного текста. Рассматривайте его как стандартный фильтр. Система LPD предполагает, что любой принтер может по умолчанию печатать обычный текст, а на текстовый фильтр возлагается задача обеспечить, чтобы символы забоя, табуляции или другие специальные символы не сбивали принтер с толку. Если вы работаете в среде, где надо учитывать использование принтера, текстовый фильтр должен также учитывать количество напечатанных страниц, обычно, подсчитывая количество напечатанных строк и сравнивая их с количеством строк на страницу, поддерживаемых принтером. Текстовый фильтр запускается со следующим списком аргументов:

    имя-фильтра [-c] -wширина -lдлина -iсдвиг -n имя-пользователя -h хост учетный-файл

    -c

    указывается, если задание послано командой lpr -l

    ширина

    значение из характеристики pw (page width - ширина страницы), указанной в файле /etc/printcap, по умолчанию - 132

    длина

    значение из характеристики pl (page length - длина страницы), по умолчанию - 66

    сдвиг

    сдвиг, заданный командой lpr -i, по умолчанию - 0

    имя-пользователя

    регистрационное имя пользователя, печатающего файл

    хост

    имя хоста, с которого было послано задание

    учетный-файл

    имя учетного файла, задаваемое характеристикой af.

  • Фильтр преобразования преобразует специфичный формат файла в то, что принтер может воспроизвести на бумаге. Например, данные системы набора ditroff нельзя печатать непосредственно, но можно установить фильтр преобразования для файлов ditroff, чтобы преобразовывать данные ditroff в тот вид, который принтер может воспринять и напечатать. В разделе Фильтры преобразования написано всё об этих фильтрах. Фильтры преобразования также необходимы для учета, если предполагается учет использования принтера. Фильтры преобразования запускаются со следующими аргументами:

    имя-фильтра -xширина-пиксела -yвысота-пиксела -n имя-пользователя -h хост учетный-файл где ширина-пиксела - значение характеристики px (по умолчанию - 0), а высота-пиксела - значение характеристики py (по умолчанию - 0).

  • Выходной фильтр используется только если нет текстового фильтра или если включена выдача начальных страниц. Судя по моему опыту, выходные фильтры используются редко. Они описаны в разделе Выходные фильтры. У выходного фильтра есть всего два аргумента:

    имя-фильтра -wширина -lдлина которые идентичны аргументам -w и -l текстового фильтра.

Фильтры также должны завершать работу со следующим статусом выхода:

exit 0

Если фильтр успешно напечатал файл.

exit 1

Если фильтр не смог напечатать файл, но хочет, чтобы система LPD попыталась распечатать файл ещё раз. Система LPD перезапустит фильтр, если его работа завершена с этим статусом.

exit 2

Если фильтр не смог напечатать файл и не хочет, чтобы система LPD пыталась его печатать еще раз. Система LPD удалит файл.

Поставляемый в составе FreeBSD текстовый фильтр /usr/libexec/lpr/lpf использует аргументы, задающие ширину и длину страницы для определения того, когда посылать символ прогона страницы (form feed) и как учитывать использование принтера. Он использует переданные в качестве аргументов имя пользователя, хост и учетный файл для внесения учетных записей.

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

10.4.1.2. Прием заданий с обычным текстом на PostScript®-принтеры

Если вы - единственный пользователь компьютера и PostScript®-принтера (или принтера на основе другого языка), и вы обещаете никогда не посылать на принтер обычный текст и никогда не использовать возможностей различных программ, требующих посылки на принтер обычного текста, вам можно не заботиться о том, что описано в этом разделе.

Но, если вы хотите посылать на принтер как задания PostScript®, так и обычный текст, рекомендуется дополнить настройку принтера. Для этого надо, чтобы текстовый фильтр определял, является ли поступающее задание обычным текстом или программой на языке PostScript®. Все PostScript®-задания должны начинаться с %! (для других языков принтеров обратитесь к соответствующей документации). Если первые два символа в задании - именно эти, речь идет о PostScript®, и мы можем остальную часть задания передавать непосредственно. Если же первые два символа в файле - другие, фильтр будет преобразовывать текст в PostScript® и печатать результат.

Как нам это сделать?

Если вы используете последовательный принтер, хороший способ достичь поставленной цели состоит в установке lprps. lprps - это фильтр для PostScript®-принтера, выполняющий двустороннее взаимодействие с принтером. Он обновляет файл состояния принтера, помещая в него подробную информацию, выданную принтером, так что пользователи и администраторы могут узнать, в каком именно состоянии (например, toner low или paper jam) находится принтер. Но еще важнее, что он включает программу psif, которая определяет, является ли входящее задание обычным текстом, и вызывает textps (еще одну программу, поставляемую вместе с lprps) для преобразования его в PostScript®. Затем lprps посылает преобразованное задание на принтер.

lprps входит в набор портов FreeBSD (см. Набор портов). Вы, конечно, можете загрузить, собрать и установить его самостоятельно. После установки lprps просто укажите путь к программе psif, входящей в состав пакета lprps. Если вы установили lprps из Коллекции Портов, используйте следующий текст в записи для последовательного PostScript®-принтера в файле /etc/printcap:

:if=/usr/local/libexec/psif:

Надо также задать характеристику rw; она требует от системы LPD открывать принтер в режиме чтения и записи.

При использовании параллельного PostScript®-принтера (что не позволяет обеспечить двустороннее взаимодействие с принтером, необходимое для системы lprps), можно использовать в качестве текстового фильтра следующий скрипт командного интерпретатора:

#!/bin/sh
#
#  psif - Печать PostScript или обычного текста на PostScript-принтере
#  Скрипт, а НЕ версия, входящая в состав lprps
#  Установлен в /usr/local/libexec/psif
#

IFS="" read -r first_line
first_two_chars=`expr "$first_line" : '\(..\)'`

if [ "$first_two_chars" = "%!" ]; then
    #
    #  Задание PostScript, печатать его.
    #
    echo "$first_line" && cat && printf "\004" && exit 0
    exit 2
else
    #
    #  Обычный текст, преобразовать его, а затем напечатать.
    #
    ( echo "$first_line"; cat ) | /usr/local/bin/textps && printf "\004" && exit 0
    exit 2
fi

В представленном выше скрипте, textps - отдельно установленная программа для преобразования обычного текста в PostScript®. Можно использовать любую программу преобразования текста в PostScript®. Коллекция Портов FreeBSD (см. материал о Коллекции Портов) включает полнофункциональную программу преобразования текста в PostScript® под названием a2ps, которую тоже можно попробовать использовать.

10.4.1.3. Имитация PostScript® на не-PostScript® принтерах

PostScript® является фактическим стандартом для высококачественного набора и печати. PostScript®, однако, - дорогой стандарт. К счастью, благодаря компании Aladdin Enterprises есть свободный аналог PostScript® под названием Ghostscript, который работает с FreeBSD. Ghostscript может читать большинство PostScript®-файлов и выдавать соответствующие страницы на множество устройств, включая многие моделей не-PostScript принтеров. Установив Ghostscript и используя специальный текстовый фильтр для принтера, можно заставить ваш не-PostScript® принтер работать фактически как PostScript®-принтер.

Ghostscript входит в набор портов FreeBSD, если вы хотите устанавливать его оттуда. Вы можете также легко загрузить, собрать и установить его самостоятельно.

Для имитации PostScript® надо, чтобы текстовый фильтр определял, печатается ли PostScript®-файл. Если нет, фильтр будет передавать файл на принтер непосредственно; в противном случае, он будет использовать Ghostscript, чтобы сначала преобразовать файл в формат, который поймет принтер.

Рассмотрим пример: следующий сценарий представляет собой текстовый фильтр для принтеров Hewlett Packard DeskJet 500. Для других принтеров замените аргумент -sDEVICE в команде gs (Ghostscript). (Введите команду gs -h для получения списка устройств, поддерживаемых установленной версией Ghostscript.)

#!/bin/sh
#
#  ifhp - Печать Ghostscript-эмулированного PostScript на DeskJet 500
#  Установлен в /usr/local/libexec/ifhp

#
#  Обрабатывать LF как CR+LF (чтобы избежать "эффекта ступенек"
#  на принтерах HP/PCL:
#
printf "\033&k2G" || exit 2

#
#  Прочитать первые два символа файла
#
IFS="" read -r first_line
first_two_chars=`expr "$first_line" : '\(..\)'`

if [ "$first_two_chars" = "%!" ]; then
    #
    #  Это PostScript; используем Ghostscript для чтения, преобразования и печати.
    #
    /usr/local/bin/gs -dSAFER -dNOPAUSE -q -sDEVICE=djet500 \
        -sOutputFile=- - && exit 0
else
    #
    #  Обычный текст или HP/PCL, поэтому просто печатаем его напрямую; печатаем в
    #  конце символ прогона страницы, чтобы была выдана последняя страница.
    #
    echo "$first_line" && cat && printf "\033&l0H" &&
exit 0
fi

exit 2

Наконец, надо указать системе LPD, какой фильтр использовать, задав характеристику if:

:if=/usr/local/libexec/ifhp:

Вот и все. Теперь можно выполнять lpr plain.text и lpr whatever.ps, и обе команды должны успешно печатать.

10.4.1.4. Фильтры преобразования

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

10.4.1.4.1. Зачем устанавливать фильтры преобразования?

Фильтры преобразования упрощают печать различного рода файлов. В качестве примера, предположим, что активно используется издательская система TeX и имеется PostScript®-принтер. При каждой генерации DVI-файла из TeX, мы не можем печатать его непосредственно, пока не преобразуем в PostScript®. Для этого используется такая последовательность команд:

% dvips seaweed-analysis.dvi
% lpr seaweed-analysis.ps

Установив фильтр преобразования для файлов DVI, мы можем не конвертировать файл каждый раз вручную, возложив эту задачу на систему LPD. Теперь при каждом получении DVI-файла нас от его распечатки отделяет только один шаг:

% lpr -d seaweed-analysis.dvi

Мы заставили систему LPD автоматически преобразовывать DVI-файл, указав опцию -d. Все опции преобразования представлены в разделе Опции форматирования и преобразования.

Для каждой из опций преобразования, которая должна поддерживаться принтером, установите фильтр преобразования и укажите его полное имя в файле /etc/printcap. Фильтр преобразования аналогичен текстовому фильтру для простой настройки принтера (см. раздел Установка текстового фильтра), но вместо печати обычного текста он преобразует файл в формат, который может понять принтер.

10.4.1.4.2. Какие фильтры преобразования следует устанавливать?

Устанавливать надо те фильтры преобразования, которые предполагается использовать. Если вы часто печатаете файлы DVI, значит, фильтр преобразования DVI необходим. Если вам часто приходится печатать результаты работы troff, может потребоваться фильтр troff.

В следующей таблице представлены фильтры, с которыми работает система LPD, их соответствующие характеристики для файла /etc/printcap, а также способ их вызова в команде lpr:

Тип файлаХарактеристика /etc/printcapОпция lpr

cifplot

cf

-c

DVI

df

-d

plot

gf

-g

ditroff

nf

-n

Текст на языке FORTRAN

rf

-f

troff

tf

-f

растровое изображение

vf

-v

обычный текст

if

никакой, -p или -l

В нашем примере использование lpr -d означает, что для принтера должна быть задана характеристика df в записи в файле /etc/printcap.

Вопреки мнению многих, форматы вроде текста на языке FORTRAN и plot, вероятно, устарели. У себя на машине вы можете дать новые значения этим или любым другим опциям форматирования, установив соответствующие специализированные фильтры. Например, пусть необходимо напрямую печатать файлы Printerleaf (файлы настольной издательской системы Interleaf), но вообще вы не собираетесь печатать файлы типа plot. Можно установить фильтр преобразования Printerleaf в качестве значения характеристики gf и научить своих пользователей, что команда lpr -g означает "печатать файлы Printerleaf".

10.4.1.4.3. Установка фильтров преобразования

Поскольку фильтры преобразования представляют собой программы, не входящие в базовую поставку FreeBSD, их, видимо, надо помещать в каталоге /usr/local. Популярное местонахождение - каталог /usr/local/libexec, поскольку эти фильтры являются специализированными программами для выполнения системой LPD; обычным пользователям никогда не понадобится их выполнять.

Для включения фильтра преобразования, укажите его полное имя в качестве значения соответствующей характеристики для принтера в файле /etc/printcap.

В качестве примера, давайте добавим фильтр преобразования DVI в запись для принтера bamboo. Вот опять пример файла /etc/printcap, с новой характеристикой df для принтера bamboo.

#
#  /etc/printcap для хоста rose - добавлен фильтр df для bamboo
#
rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :sh:sd=/var/spool/lpd/rattan:\
        :lp=/dev/lpt0:\
        :if=/usr/local/libexec/if-simple:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:sd=/var/spool/lpd/bamboo:\
        :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:\
        :if=/usr/local/libexec/psif:\
        :df=/usr/local/libexec/psdf:

Фильтр DVI - скрипт командного интерпретатора по имени /usr/local/libexec/psdf. Вот его текст:

#!/bin/sh
#
#  psdf - фильтр принтера, преобразующий DVI в PostScript
#  Установлен в /usr/local/libexec/psdf
#
# Вызывается системой lpd при выполнении пользователем команды lpr -d
#
exec /usr/local/bin/dvips -f | /usr/local/libexec/lprps "$@"

Это скрипт выполняет команду dvips в режиме фильтрования (аргумент -f) входного потока, представляющего собой задание для печати. Затем запускается фильтр PostScript®-принтера lprps (см. раздел Прием заданий с обычным текстом на PostScript®-принтеры) с аргументами, переданными системой LPD этому скрипту. Команда lprps будет использовать эти аргументы для учета распечатанных страниц.

10.4.1.4.4. Дополнительные примеры фильтров преобразования

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

Следующий пример фильтра преобразует растровый файл (точнее, GIF-файл) для печати на принтере Hewlett Packard LaserJet III-Si:

#!/bin/sh
#
#  hpvf - Преобразовать GIF-файлы в HP/PCL и напечатать
#  Установлен в /usr/local/libexec/hpvf

PATH=/usr/X11R6/bin:$PATH; export PATH
giftopnm | ppmtopgm | pgmtopbm | pbmtolj -resolution 300 \
    && exit 0 \
    || exit 2

Он работает путем преобразования GIF-файла в переносимый формат anymap, его - в переносимый формат graymap, затем - в переносимый bitmap, а уже его - в данные, подходящие для LaserJet/PCL.

Вот файл /etc/printcap с записью для принтера, в которой используется представленный выше фильтр:

#
#  /etc/printcap для хоста orchid
#
teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
        :lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\
        :if=/usr/local/libexec/hpif:\
        :vf=/usr/local/libexec/hpvf:

Следующий скрипт является фильтром преобразования для печати данных troff, получаемых из системы набора groff, на PostScript®-принтере bamboo:

#!/bin/sh
#
#  pstf - Преобразует выдаваемые groff данные troff в PS и печатает.
#  Установлен в /usr/local/libexec/pstf
#
exec grops | /usr/local/libexec/lprps "$@"

Представленный выше скрипт снова использует команду lprps для взаимодействия с принтером. Если принтер подключен к параллельному порту, придется использовать следующий скрипт:

#!/bin/sh
#
#  pstf - Преобразует выдаваемые groff данные troff в PS и печатает.
#  Установлен в /usr/local/libexec/pstf
#
exec grops

Вот и все. Вот какую запись надо добавить в файл /etc/printcap, чтобы включить этот фильтр:

:tf=/usr/local/libexec/pstf:

Вот пример, который пригодится старым специалистам по языку FORTRAN. Это фильтр для печати текста программы на языке FORTRAN на любом принтере, который может непосредственно печатать обычный текст. Мы установим его для принтера teak:

#!/bin/sh
#
# hprf - Фильтр текста на языке FORTRAN для LaserJet 3si:
# Установлен в /usr/local/libexec/hprf
#

printf "\033&k2G" && fpr && printf "\033&l0H" &&
 exit 0
exit 2

Надо добавить следующую строку к записи в файле /etc/printcap для принтера teak, чтобы включить этот фильтр:

:rf=/usr/local/libexec/hprf:

Перейдем к последнему, более сложному примеру. Мы добавим фильтр DVI для уже использовавшегося принтера LaserJet по имени teak. Сначала простая часть: изменить файл /etc/printcap, указав местонахождение фильтра DVI:

:df=/usr/local/libexec/hpdf:

А теперь - часть посложнее: создать фильтр. Для этого нам понадобится программа преобразования DVI в LaserJet/PCL. Набор портов FreeBSD (см. Набор портов) содержит одну: соответствующий пакет называется dvi2xx. Установка этого пакета дает нам необходимую программу, dvilj2p, которая преобразует DVI в коды, подходящие для LaserJet IIp, LaserJet III и LaserJet 2000.

Команда dvilj2p требует создания достаточно сложного фильтра hpdf, поскольку она не может читать стандартный входной поток. Она хочет работать с именем файла. Что еще хуже, имя файла должно завершаться расширением .dvi, так что использование стандартного входного потока /dev/fd/0 тоже проблематично. Мы можем обойти эту проблему, создав (символическую) связь (с именем, завершающимся суффиксом .dvi) с устройством /dev/fd/0, тем самым, заставив команду dvilj2p читать из стандартного входного потока.

Единственная оставшаяся проблема состоит в том, что мы не можем создавать временную связь в каталоге /tmp. Символьные связи принадлежат пользователю и группе bin. Фильтр же работает от имени пользователя daemon. А у каталога /tmp установлен sticky bit. Фильтр сможет создать связь, но не сможет почистить за собой и удалить ее, поскольку связь будет принадлежать другому пользователю.

Вместо этого, фильтр будет создавать символическую связь в текущем рабочем каталоге, которым является каталог спулинга (задаваемый характеристикой sd в файле /etc/printcap). Это отличное место для выполнения фильтрами своих действий, особенно потому, что (иногда) в каталоге спулинга места больше, чем в /tmp.

Вот, наконец, и сам фильтр:

#!/bin/sh
#
#  hpdf - Печать данных DVI на принтере HP/PCL
#  Установлен в /usr/local/libexec/hpdf

PATH=/usr/local/bin:$PATH; export PATH

#
#  Определяем функцию для удаления временных файлов. Они существуют
#  в текущем каталоге - в каталоге спулинга для принтера.
#
cleanup() {
   rm -f hpdf$$.dvi
}

#
#  Определяем функцию для обработки критических ошибок: напечатать заданное
#  сообщение и выйти с кодом 2. Код выхода 2 сообщает системе LPD, что не
#  надо повторно пытаться печатать задание.
#
fatal() {
    echo "$@" 1>&2
    cleanup
    exit 2
}

#
#  Если пользователь удаляет задание, система LPD будет посылать сигнал SIGINT,
#  поэтому перехватываем SIGINT (и пару других сигналов), чтобы убрать за собой.
#
trap cleanup 1 2 15

#
#  Гарантируем, что не конфликтуем с существующими файлами.
#
cleanup

#
#  Связываем входной файл DVI со стандартным входным потоком (файлом для печати).
#
ln -s /dev/fd/0 hpdf$$.dvi || fatal "Cannot symlink /dev/fd/0"

#
#  Заменяем LF = CR+LF
#
printf "\033&k2G" || fatal "Cannot initialize printer"

#
#  Преобразуем и печатаем. Значение, возвращаемое программой dvilj2p, не надежно,
#  так что мы его игнорируем.
#
dvilj2p -M1 -q -e- dfhp$$.dvi

#
#  Убираем за собой и завершаем работу
#
cleanup
exit 0
10.4.1.4.5. Автоматизированное преобразование: альтернатива фильтрам преобразования

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

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

В наборе портов FreeBSD есть текстовый фильтр, выполняющий автоматическое преобразование; это apsfilter. Он может выявлять обычный текст, PostScript® и файлы DVI, выполнять соответствующие преобразования и печатать результат.

10.4.1.5. Выходные фильтры

Система спулинга LPD поддерживает еще один тип фильтров, который мы еще не рассматривали: выходные фильтры. Выходной фильтр предназначен только для печати обычного текста, как текстовый фильтр, но с множеством упрощений. Если вы используете выходной фильтр, а текстовый фильтр не задан, то:

  • Система LPD запускает выходной фильтр один раз для всего задания, а не для каждого файла задания.

  • Система LPD не пытается определить начало или конец файлов в задании для выходного фильтра.

  • Система LPD не передает выходному фильтру имя пользователя или хоста, так что этот фильтр не предназначен для учета использования принтера. Фактически, он получает всего два аргумента:

    имя-фильтра -wширина -lдлина

    Где ширина берется из характеристики pw, а длина - из характеристики pl для соответствующего принтера.

Не соблазняйтесь простотой выходного фильтра. Если вы хотите, чтобы каждый файл в задании начинал печататься с новой страницы, выходной фильтр не поможет. Используйте текстовый фильтр (также известный как входной); см. раздел Установка текстового фильтра. Более того, выходной фильтр, фактически, - более сложный, поскольку он должен проверять посылаемый ему поток байтов в поисках специальных символов-флагов и посылать себе сигналы от имени системы LPD.

Однако выходной фильтр необходим, если надо выдавать начальные страницы и требуется посылать управляющие последовательности или другие строки инициализации, чтобы можно было напечатать начальную страницу. (Но он не поможет, если необходимо учитывать начальные страницы для пользователя, поскольку система LPD не передает выходному фильтру никакой информации о пользователе или хосте.)

На одном принтере система LPD позволяет совместно с выходным использовать текстовый или другие фильтры. В таких случаях, система LPD будет запускать выходной фильтр только для печати начальной страницы (см. раздел Начальные страницы). Система LPD затем предполагает, что выходной фильтр остановится, посылая ему два байта: ASCII 031 и ASCII 001. Когда выходной фильтр видит эти два байта (031, 001), он должен остановиться, посылая себе сигнал SIGSTOP. Когда система LPD закончит выполнение остальных фильтров, она перезапускает выходной фильтр, посылая ему сигнал SIGCONT.

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

Программа lpf, которую мы представили ранее как текстовый фильтр, может также работать как выходной фильтр. Если срочно необходим простой выходной фильтр, но вы не хотите писать код для выявления байтов и посылки сигнала, попробуйте использовать lpf. Можно также поместить lpf в скрипт командного интерпретатора для обработки любых кодов инициализации, которые может потребовать принтер.

10.4.1.6. lpf: текстовый фильтр

Программа /usr/libexec/lpr/lpf, поставляемая в составе двоичного дистрибутива FreeBSD, представляет собой текстовый (входной) фильтр, который может печатать с отступом (если задание послано командой lpr -i), пропускать все символы на печать (если задание послано командой lpr -l), настраивать позицию печати при получении в задании символов забоя и табуляции, а также учитывать количество напечатанных страниц. Она может также использоваться как выходной фильтр.

Программа lpf подходит для многих сред печати. И хотя она не позволяет посылать на принтер инициализационные последовательности, легко написать скрипт командного интерпретатора, который будет выполнять необходимую инициализацию, а затем вызывать lpf.

Чтобы программа lpf корректно выполняла учет страниц, ей необходимо указать корректные значения характеристик pw и pl в файле /etc/printcap. Она использует эти значения для определения того, сколько текста может поместиться на странице и сколько страниц было в задании пользователя. Подробнее об учете использования принтера см. в разделе Учет использования принтера.

10.4.2. Начальные страницы

При наличии множества пользователей, использующих различные принтеры, вероятно, можно считать начальные страницы неизбежным злом.

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

Система LPD может выдавать заголовочные страницы для ваших распечаток автоматически, если ваш принтер может непосредственно печатать обычный текст. Если используется PostScript®-принтер, потребуется внешняя программа для генерации начальной страницы; см. Начальные страницы на PostScript®-принтерах.

10.4.2.1. Включение выдачи начальных страниц

В разделе Простая настройка принтера мы отключили выдачу начальных страниц, задав характеристику sh (что означает "suppress header") в файле /etc/printcap. Для включения выдачи начальных страниц на принтер, просто удалите характеристику sh.

Кажется слишком просто, правда?

Вы правы. Может потребоваться задать выходной фильтр для посылки строк инициализации на принтер. Вот пример выходного фильтра для Hewlett Packard PCL-совместимых принтеров:

#!/bin/sh
#
#  hpof - Выходной фильтр для Hewlett Packard PCL-совместимых принтеров
#  Установлен в /usr/local/libexec/hpof

printf "\033&k2G" || exit 2
exec /usr/libexec/lpr/lpf

Задайте полное имя выходного фильтра в качестве значения характеристики of. Подробнее об этом см. в разделе Выходные фильтры.

Вот пример файла /etc/printcap для принтера teak, который мы представили ранее; мы включили выдачу начальных страниц и добавили показанный выше выходной фильтр:

#
#  /etc/printcap для хоста orchid
#
teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
        :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\
        :if=/usr/local/libexec/hpif:\
        :vf=/usr/local/libexec/hpvf:\
        :of=/usr/local/libexec/hpof:

Теперь, когда пользователи выдают задания на принтер teak, они получают начальную страницу с каждым заданием. Если пользователи хотят тратить время на поиск своих распечаток, они могут подавить вывод начальных страниц, посылая задание с опцией lpr -h; другие опции lpr(1) см. в разделе Опции начальных страниц.

Система LPD выдает символ прогона страницы (form feed) после начальной страницы. Если ваш принтер использует другой символ или последовательность символов для выброса напечатанной страницы, укажите их в качестве значения характеристики ff в файле /etc/printcap.

10.4.2.2. Управление начальными страницами

Включая выдачу начальных страниц, система LPD будет выдавать длинный длинный заголовок, целую страницу с большими буквами, идентифицирующими пользователя, хост и задание. Ниже представлен пример (kelly напечатала задание по имени outline с хоста rose):

      k                   ll       ll
      k                    l        l
      k                    l        l
      k   k     eeee       l        l     y    y
      k  k     e    e      l        l     y    y
      k k      eeeeee      l        l     y    y
      kk k     e           l        l     y    y
      k   k    e    e      l        l     y   yy
      k    k    eeee      lll      lll     yyy y
                                               y
                                          y    y
                                           yyyy

                                   ll
                          t         l        i
                          t         l
       oooo    u    u   ttttt       l       ii     n nnn     eeee
      o    o   u    u     t         l        i     nn   n   e    e
      o    o   u    u     t         l        i     n    n   eeeeee
      o    o   u    u     t         l        i     n    n   e
      o    o   u   uu     t  t      l        i     n    n   e    e
       oooo     uuu u      tt      lll      iii    n    n    eeee

      r rrr     oooo     ssss     eeee
      rr   r   o    o   s    s   e    e
      r        o    o    ss      eeeeee
      r        o    o      ss    e
      r        o    o   s    s   e    e
      r         oooo     ssss     eeee

                                              Job:  outline
                                              Date: Sun Sep 17 11:04:58 1995

Система LPD добавляет прогон страницы после этого текста, чтобы задание начиналось с новой страницы (если только вы не указали характеристику sf (suppress form feeds) в записи соответствующего принтера в файле /etc/printcap).

Если вы предпочитаете, чтобы система LPD создавала короткий заголовок, укажите характеристику sb (short banner) в файле /etc/printcap. Начальная страница будет иметь следующий вид:

rose:kelly  Job: outline  Date: Sun Sep 17 11:07:51 1995

Также по умолчанию система LPD печатает начальную страницу перед заданием. Для изменения порядка на обратный, укажите характеристику hl (header last) в файле /etc/printcap.

10.4.2.3. Учет начальных страниц

Использование встроенных начальных страниц системы LPD порождает определенную парадигму учета использования принтера: начальные страницы пользователи не должны оплачивать.

Почему?

Поскольку выходной фильтр - единственная внешняя программа, управляющая выдачей начальных страниц, которая может выполнять учет, а ей не передают информацию о пользователе или хосте и учётный файл, так что, она не имеет никакого представления о том, на чей счет отнести использование принтера. Также недостаточно просто "добавлять одну страницу" в текстовом фильтре или в любом из фильтров преобразований (которые имеют информацию о пользователе и хосте), поскольку пользователи могут подавлять выдачу начальных страниц с помощью опции lpr -h. И их заставят оплачивать начальные страницы, которые они не печатали. Понятно, что опцию lpr -h будут использовать в большинстве случаев те, кто озабочен проблемами окружающей среды, но вы никак не можете стимулировать ее использование.

Также недостаточно, чтобы каждый из фильтров генерировал собственные начальные страницы (и, тем самым, мог их учитывать). Если пользователи захотят отказаться от выдачи начальных страниц и укажут опцию lpr -h, они все равно их получат, и будут вынуждены оплатить, поскольку система LPD не передает информации о наличии опции -h ни одному из этих фильтров.

Итак, что же вы можете сделать?

Вы можете:

  • Принять парадигму системы LPD и сделать начальные страницы бесплатными.

  • Установить альтернативную систему вместо LPD, такую как LPRng. В разделе Альтернативы стандартному спулеру представлена дополнительная информация о других системах спулинга, которые можно использовать вместо LPD.

  • Написать умный выходной фильтр. Обычно выходной фильтр не предназначен для выполнения чего-то кроме инициализации принтера и простых преобразований символов. Он подходит для начальных страниц и заданий с обычным текстом (когда нет текстового (входного) фильтра). Но, если есть текстовый фильтр для заданий с обычным текстом, то система LPD будет запускать выходной фильтр только для начальных страниц. И выходной фильтр может анализировать текст начальной страницы, которую генерирует система LPD, чтобы определить, на счет какого пользователя и хоста отнести начальную страницу. Единственная проблема этого метода в том, что выходной фильтр все равно не знает, какой учетный файл использовать (ему не передают имя файла, заданное в качестве значения характеристики af), но при наличии хорошо известного учетного файла, его имя можно явно указать в выходном фильтре. Для упрощения этапа анализа задайте характеристику sh (short header) в файле /etc/printcap. Повторимся, что это может оказаться слишком сложным, и пользователи, несомненно, больше оценят великодушного системного администратора, который сделает начальные страницы бесплатными.

10.4.2.4. Начальные страницы на PostScript®-принтерах

Как было описано выше, система LPD может генерировать начальную страницу в виде обычного текста, что подходит для многих принтеров. Конечно, PostScript®-принтеры не могут непосредственно печатать обычный текст, так что, для них возможность выдачи начальных страниц системы LPD бесполезна - или почти бесполезна.

Один очевидный способ получить начальные страницы - заставить каждый фильтр преобразования и текстовый фильтр генерировать начальную страницу. Эти фильтры должны использовать аргументы имя пользователя и хост для генерации соответствующей начальной страницы. Недостаток этого метода состоит в том, что пользователи будут всегда получать начальные страницы, даже если будут посылать задания с помощью команды lpr -h.

Давайте рассмотрим этот метод детально. Следующий сценарий принимает три аргумента (регистрационное имя пользователя, имя хоста и имя задания) и создает простую начальную страницу на языке PostScript®:

#!/bin/sh
#
#  make-ps-header - выдать начальную страницу на языке PostScript в stdout
#  Установлен в /usr/local/libexec/make-ps-header
#

#
#  Это единицы измерения PostScript (72 на дюйм). Измените значения для A4 или
#  другого используемого формата бумаги:
#
page_width=612
page_height=792
border=72

#
#  Проверяем аргументы
#
if [ $# -ne 3 ]; then
    echo "Usage: `basename $0` <user> <host> <job>" 1>&2
    exit 1
fi

#
#  Сохраняем значения в переменных, в основном, для упрощения понимания
#  последующего PostScript-кода.
#
user=$1
host=$2
job=$3
date=`date`

#
#  Посылаем PostScript-код в stdout.
#
exec cat <<EOF
%!PS

%
%  Гарантируем, что не будем влиять на следующее далее задание пользователя
%
save

%
%  Делаем тонкую некрасивую рамку по краям бумаги.
%
$border $border moveto
$page_width $border 2 mul sub 0 rlineto
0 $page_height $border 2 mul sub rlineto
currentscreen 3 -1 roll pop 100 3 1 roll setscreen
$border 2 mul $page_width sub 0 rlineto closepath
0.8 setgray 10 setlinewidth stroke 0 setgray

%
%  Выдаем регистрационное имя пользователя, красивыми, большими и рельефными буквами
%
/Helvetica-Bold findfont 64 scalefont setfont
$page_width ($user) stringwidth pop sub 2 div $page_height 200 sub moveto
($user) show

%
%  Теперь выдаем всякие детали
%
/Helvetica findfont 14 scalefont setfont
/y 200 def
[ (Job:) (Host:) (Date:) ] {
200 y moveto show /y y 18 sub def }
forall

/Helvetica-Bold findfont 14 scalefont setfont
/y 200 def
[ ($job) ($host) ($date) ] {
        270 y moveto show /y y 18 sub def
} forall

%
% Вот и все
%
restore
showpage
EOF

Теперь, каждый из фильтров преобразования и текстовый фильтр может вызвать этот сценарий, чтобы сначала сгенерировать начальную страницу, а затем напечатать задание пользователя. Вот фильтр преобразования DVI, представленный ранее в этом документе, измененный для выдачи начальной страницы:

#!/bin/sh
#
#  psdf - фильтр преобразования DVI в PostScript
#  Установлен в /usr/local/libexec/psdf
#
#  Вызывается системой lpd при выполнении пользователем команды lpr -d
#

orig_args="$@"

fail() {
    echo "$@" 1>&2
    exit 2
}

while getopts "x:y:n:h:" option; do
    case $option in
        x|y)  ;; # Ignore
        n)    login=$OPTARG ;;
        h)    host=$OPTARG ;;
        *)    echo "LPD started `basename $0` wrong." 1>&2
              exit 2
              ;;
    esac
done

[ "$login" ] || fail "No login name"
[ "$host" ] || fail "No host name"

( /usr/local/libexec/make-ps-header $login $host "DVI File"
  /usr/local/bin/dvips -f ) | eval /usr/local/libexec/lprps $orig_args

Обратите внимание, как фильтр должен анализировать список аргументов, чтобы определить имя пользователя и имя хоста. Анализ аргументов в других фильтрах аргументов выполняется точно так же. Текстовый фильтр принимает, однако, немного другой набор аргументов (см. раздел Как работают фильтры).

Как уже упоминалось, представленная выше схема хотя и достаточно проста, но не позволяет учесть опцию "подавить вывод начальной страницы" (опция -h) команды lpr. Если пользователи хотят сберечь деревья (или несколько копеек, если вы берете деньги и за начальные страницы), они не смогут этого сделать, поскольку каждый фильтр будет выдавать начальную страницу для каждого задания.

Чтобы позволить пользователям отключать выдачу начальной страницы для отдельного задания, надо будет использовать прием, представленный в разделе Учет начальных страниц: написать выходной фильтр, который анализирует сгенерированную системой LPD начальную страницу и выдает ее PostScript®-версию. Если пользователь посылает задание командой lpr -h, система LPD не будет генерировать начальную страницу, как и ваш выходной фильтр. В противном случае, ваш выходной фильтр будет читать текст, полученный от системы LPD, и посылать на принтер соответствующий PostScript®-код для начальной страницы.

Если вы используете PostScript®-принтер с последовательным интерфейсом, можно использовать систему lprps, которая включает выходной фильтр, psof, делающий то, что описано выше. Помните, что программа psof не учитывает напечатанные пользователями начальные страницы.

10.4.3. Печать по сети

FreeBSD поддерживает печать по сети: посылку заданий на удаленные принтеры. Печатью по сети обычно называют две разные ситуации:

  • Работа с принтером, подключенным к удаленному хосту. Вы устанавливаете принтер с обычным последовательным или параллельным интерфейсом на одном хосте. Затем, вы настраиваете систему LPD для обеспечения доступа к принтеру с других хостов в сети. В разделе "Принтеры, установленные на удаленных хостах" описано, как это сделать.

  • Работа с принтером, подключенным непосредственно к сети. Принтер имеет сетевой интерфейс, кроме (или вместо) более традиционного последовательного или параллельного. Такой принтер может работать следующим образом:

    • Он может понимать протокол LPD и даже поддерживать очереди заданий с удаленных хостов. В этом случае, он работает просто как обычный хост с системой LPD. Для настройки такого принтера следуйте той же процедуре, которая описана в разделе "Принтеры, установленные на удаленных хостах".

    • Он может поддерживать получение потока данных по сети. В этом случае, вы "подключаете" принтер к одному из хостов в сети, делая этот хост ответственным за поддержку очередей заданий и их посылку на принтер. В разделе Принтеры с сетевыми интерфейсами представлен ряд советов по установке таких принтеров.

10.4.3.1. Принтеры, установленные на удаленных хостах

Система спулинга LPD имеет встроенную поддержку посылки заданий на другие хосты, на которых тоже работает система LPD (или совместимая с LPD). Это позволяет установить принтер на одном хосте и сделать его доступным с других хостов. Она также работает с принтерами, имеющими сетевые интерфейсы и понимающими протокол LPD.

Для обеспечения такого рода удаленной печати, сначала установите принтер на одном хосте, хосте принтера, с помощью процедуры, описанной в разделе Простая настройка принтера. Выполните любые необходимые дополнительные настройки, как описано в разделе Расширенная настройка принтера. Не забудьте протестировать принтер и убедиться, обеспечивает ли он заданные возможности системы LPD. Также проверьте, что локальный хост имеет право использовать службу LPD на удаленном хосте (см. раздел Ограничение приема заданий с удаленных хостов).

Если вы используете принтер с сетевым интерфейсом, совместимый с системой LPD, упомянутым в обсуждении выше хостом принтера будет сам принтер, а в качестве имени принтера будет выступать имя, которое вы сконфигурировали для принтера. См. документацию, поставляемую с принтером и/или сетевым интерфейсом принтера.

Если вы используете Hewlett Packard Laserjet, то при задании принтеру имени text будет автоматически выполняться преобразование символа LF в последовательность CRLF, так что, сценарий hpif не понадобится.

Затем, на других хостах, для которых вы хотите обеспечить доступ к принтеру, создайте запись в их файлах /etc/printcap со следующими компонентами:

  1. Дайте записи любое подходящее имя. Для простоты, однако, имеет смысл задавать такое же имя и псевдонимы, как и на хосте принтера.

  2. Характеристику lp оставьте пустой, указав это явно (:lp=:).

  3. Создайте каталог спулинга и укажите его местонахождение в характеристике sd. Система LPD будет сохранять задания в нем, прежде чем они будут посланы на хост принтера.

  4. Укажите имя хоста принтера в качестве значения характеристики rm.

  5. Укажите имя принтера на хосте принтера в качестве значения характеристики rp.

Вот и все. Не нужно перечислять фильтры преобразования, размеры страницы и вообще ничего больше в файле /etc/printcap.

Рассмотрим пример. На хосте rose есть два принтера, bamboo и rattan. Мы позволим пользователям хоста orchid печатать на эти принтеры. Вот файл /etc/printcap для хоста orchid (из раздела Включение выдачи начальных страниц). В нем уже есть запись для принтера teak; мы добавили две записи для принтеров на хосте rose:

#
#  /etc/printcap для хоста orchid - добавлены (удаленные) принтеры на rose
#

#
#  teak - локальный принтер; он подключен непосредственно к orchid:
#
teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
        :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:\
        :if=/usr/local/libexec/ifhp:\
        :vf=/usr/local/libexec/vfhp:\
        :of=/usr/local/libexec/ofhp:

#
#  rattan подключен к rose; посылать задания для rattan на хост rose:
#
rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan:

#
#  bamboo тоже подключен к rose:
#
bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:

Затем достаточно только создать каталоги спулинга на orchid:

# mkdir -p /var/spool/lpd/rattan /var/spool/lpd/bamboo
# chmod 770 /var/spool/lpd/rattan /var/spool/lpd/bamboo
# chown daemon:daemon /var/spool/lpd/rattan /var/spool/lpd/bamboo

Теперь пользователи хоста orchid могут печатать на принтеры rattan и bamboo. Если, например, пользователь на orchid выполнит команду

% lpr -P bamboo -d sushi-review.dvi

система LPD на orchid будет копировать задание в каталог спулинга /var/spool/lpd/bamboo и учтет, что печатается задание DVI. Как только на хосте rose появится место в каталоге спулинга принтера bamboo, две системы LPD передадут файл на хост rose. Файл будет ждать в очереди на rose пока, наконец, не будет напечатан. Он будет преобразован из формата DVI в PostScript® (поскольку bamboo является PostScript®-принтером) на хосте rose.

10.4.3.2. Принтеры с сетевыми интерфейсами

Часто при покупке сетевой карты для принтера можно приобрести две версии: эмулирующую спулер (более дорогая версия) или просто позволяющую принимать на принтер данные так, как если бы использовался последовательный или параллельный порт (более дешевая версия). В этом разделе описано, как использовать более дешёвую версию. Использование более дорогой версии описано в предыдущем разделе "Принтеры, установленные на удаленных хостах".

Формат файла /etc/printcap позволяет указывать, какой последовательный или параллельный интерфейс использовать, и (при использовании последовательного интерфейса), какую установить скорость, использовать ли управление потоком, размер отступов для табуляций, преобразование символов новой строки и другие параметры. Но нет способа указать подключение к принтеру, прослушивающему TCP/IP или другой сетевой порт.

Для посылки данных на подключенный к сети принтер, надо разработать программу взаимодействия, которую могут вызывать текстовый фильтр и фильтры преобразований. Вот один из примеров: скрипт netprint принимает все данные со стандартного входного потока и посылает их на принтер, подключенный к сети. Мы указываем имя хоста принтера в качестве первого аргумента, а номер порта, к которому надо подключаться - в качестве второго аргумента команды netprint. Учтите, что поддерживается только одностороннее взаимодействие (с ОС FreeBSD на принтер); многие сетевые принтеры поддерживают двустороннее взаимодействие, и вы можете захотеть его использовать (для получения состояния принтера, учета и т.п.).

#!/usr/bin/perl
#
#  netprint - Текстовый фильтр для принтера, подключенного к сети
#  Установлен в /usr/local/libexec/netprint
#
$#ARGV eq 1 || die "Usage: $0 <printer-hostname> <port-number>";

$printer_host = $ARGV[0];
$printer_port = $ARGV[1];

require 'sys/socket.ph';

($ignore, $ignore, $protocol) = getprotobyname('tcp');
($ignore, $ignore, $ignore, $ignore, $address)
    = gethostbyname($printer_host);

$sockaddr = pack('S n a4 x8', &AF_INET, $printer_port, $address);

socket(PRINTER, &PF_INET, &SOCK_STREAM, $protocol)
    || die "Can't create TCP/IP stream socket: $!";
connect(PRINTER, $sockaddr) || die "Can't contact $printer_host: $!";
while (<STDIN>) { print PRINTER; }
exit 0;

Затем можно использовать этот сценарий в различных фильтрах. Пусть у нас есть строчный принтер Diablo 750-N, подключенный к сети. Принтер принимает данные на печать через порт 5100. Имя хоста для принтера - scrivener. Вот текстовый фильтр для этого принтера:

#!/bin/sh
#
#  diablo-if-net - Текстовый фильтр для принтера Diablo `scrivener',
#  прослушивающего порт 5100. Установлен в /usr/local/libexec/diablo-if-net
#
exec /usr/libexec/lpr/lpf "$@" | /usr/local/libexec/netprint scrivener 5100

10.4.4. Ограничение использования принтера

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

10.4.4.1. Ограничение количества копий

Система LPD позволяет пользователям легко печатать несколько копий файла. Пользователи могут печатать задания с помощью команды lpr -#5 (например) и получать пять копий каждого файла в задании. Хорошо это или нет - решать вам.

Если вы считаете, что многочисленные копии только изнашивают ваши принтеры, можете отключить опцию - команды lpr(1), добавив характеристику sc в файл /etc/printcap. Когда пользователи пошлют задания с опцией -#, они увидят:

lpr: multiple copies are not allowed

Учтите, что если вы настроили удаленный доступ к принтеру (см. раздел "Принтеры, установленные на удаленных хостах"), необходимо задать характеристику sc также и в файлах /etc/printcap удаленных хостов, иначе пользователи все равно смогут посылать задания с несколькими копиями с других хостов.

Рассмотрим пример. Вот файл /etc/printcap для хоста rose. Принтер rattan вполне надежен, поэтому мы разрешим печатать на него несколько копий, но лазерный принтер bamboo несколько более изношен, поэтому мы отключим для него печать нескольких копий, добавив характеристику sc:

#
#  /etc/printcap для хоста rose - запрещает печать нескольких копий на bamboo
#
rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :sh:sd=/var/spool/lpd/rattan:\
        :lp=/dev/lpt0:\
        :if=/usr/local/libexec/if-simple:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:sd=/var/spool/lpd/bamboo:sc:\
        :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:\
        :if=/usr/local/libexec/psif:\
        :df=/usr/local/libexec/psdf:

Теперь нам также нужно добавить характеристику sc в файле /etc/printcap на хосте orchid (и раз уж мы его меняем, давайте отключим печать нескольких копий для принтера teak):

#
#  /etc/printcap для хоста orchid - отключена печать нескольких копий на
#  локальном принтере teak и на удаленном принтере bamboo
teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
        :lp=/dev/lpt0:sd=/var/spool/lpd/teak:mx#0:sc:\
        :if=/usr/local/libexec/ifhp:\
        :vf=/usr/local/libexec/vfhp:\
        :of=/usr/local/libexec/ofhp:

rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :lp=:rm=rose:rp=rattan:sd=/var/spool/lpd/rattan:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :lp=:rm=rose:rp=bamboo:sd=/var/spool/lpd/bamboo:sc:

С помощью характеристики sc мы предотвращаем использование команды lpr -#, но это не мешает пользователям просто выполнить команду lpr(1) несколько раз или просто послать один и тот же файл несколько раз в одном задании следующим образом:

% lpr forsale.sign forsale.sign forsale.sign forsale.sign forsale.sign

Есть много способов предотвратить такое некорректное использование (включая его игнорирование), которые вы можете разработать самостоятельно.

10.4.4.2. Ограничение доступа к принтерам

Вы можете управлять тем, кто и на какие принтеры может печатать, с помощью механизма групп UNIX® и характеристики rg в файле /etc/printcap. Просто поместите пользователей, которым необходимо предоставить доступ к принтеру, в определенную группу, a затем укажите эту группу в качестве значения характеристики rg.

Пользователи, не входящие в эту группу (включая root) будут получать уведомление lpr: Not a member of the restricted group при попытке печатать на контролируемый принтер.

Как и в случае с характеристикой sc (подавить выдачу нескольких копий), при необходимости, надо указывать характеристику rg и на удаленных хостах, имеющих доступ к вашим принтерам (см. раздел "Принтеры, установленные на удаленных хостах").

Например, давайте разрешим всем обращаться к принтеру rattan, но только пользователи группы artists смогут использовать принтер bamboo. Вот знакомый уже файл /etc/printcap для хоста rose:

#
#  /etc/printcap для хоста rose - ограничение группы для bamboo
#
rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :sh:sd=/var/spool/lpd/rattan:\
        :lp=/dev/lpt0:\
        :if=/usr/local/libexec/if-simple:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:\
        :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:\
        :if=/usr/local/libexec/psif:\
        :df=/usr/local/libexec/psdf:

Давайте не будем менять другой рассматриваемый файл /etc/printcap (для хоста orchid). Конечно, в результате, любой пользователь orchid может печатать на bamboo. Возможно, на хосте orchid учетных записей и так немного, и вы хотите, чтобы все они имели доступ к принтеру. Или нет.

Для принтера может быть только одна ограниченная группа.

10.4.4.3. Контроль размеров посылаемых заданий

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

Система LPD ограничить максимально допустимый размер файла в задании с помощью характеристики mx. Размер задается в блоках, размер которых, BUFSIZ, составляет 1024 байта. Если задать этой характеристике значение ноль, размер файла ограничиваться не будет; однако, если характеристика mx вообще не задана, то будет использоваться стандартное ограничение - 1000 блоков.

Ограничение применяется к файлам в задании, а не к общему размеру задания.

Система LPD не откажется печатать файл больше максимально допустимого для принтера размера. Вместо этого, она поставит в очередь часть файла до заданного предела, и она будет напечатана. Остальное не будет напечатано. Правильность такого поведения не бесспорна.

Давайте установим ограничения для принтеров из наших примеров, rattan и bamboo. Поскольку PostScript®-файлы этих художников обычно бывают весьма большими, мы ограничим их размер пятью мегабайтами. Мы не будем ограничивать использование обычного текстового строчного принтера:

#
#  /etc/printcap для хоста rose
#

#
#  Без ограничения на размер задания:
#
rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :sh:mx#0:sd=/var/spool/lpd/rattan:\
        :lp=/dev/lpt0:\
        :if=/usr/local/libexec/if-simple:

#
#  Размер файла - не более пяти мегабайт:
#
bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\
        :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:\
        :if=/usr/local/libexec/psif:\
        :df=/usr/local/libexec/psdf:

Опять таки, ограничения применяются только для локальных пользователей. Если вы настроили удаленный доступ к принтерам, для удаленных пользователей эти ограничения не действуют. Надо задать характеристику mx и в файлах /etc/printcap удаленных хостов. Более детальную информацию по удаленной печати см. в разделе "Принтеры, установленные на удаленных хостах".

Есть еще один специализированный способ ограничить размер заданий печати с удаленных принтеров; см. раздел Ограничение печати заданий с удаленных хостов.

10.4.4.4. Ограничение печати заданий с удаленных хостов

Система спулинга LPD обеспечивает несколько способов ограничить посылку заданий с удаленных хостов:

Ограничения хостов

Вы можете управлять тем, с каких удаленных хостов локальная система LPD принимает запросы, с помощью файлов /etc/hosts.equiv и /etc/hosts.lpd. Система LPD проверяет, поступает ли входящий запрос с хоста, указанного в одном из этих файлов. Если нет, система LPD отвергает запрос.

Формат этих файлов простой: по одному имени хоста в строке. Учтите, что файл /etc/hosts.equiv также используется протоколом ruserok(3) и влияет на программы rsh(1) и rcp(1), так что, будьте внимательны.

Например, вот файл /etc/hosts.lpd для хоста rose:

orchid
violet
madrigal.fishbaum.de

Это означает, что хост rose будет принимать запросы с хостов orchid, violet и madrigal.fishbaum.de. Если любой другой хост попытается обратиться к системе LPD хоста rose, его задание будет отвергнуто.

Ограничения размера

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

Это позволяет гарантировать, что удаленные пользователи не заполнят вашу файловую систему. Можно также использовать этот механизм для предоставления определенного преимущества локальным пользователям: они смогут ставить задания в очередь еще долго после того, как свободного места на диске станет меньше, чем указано в файле minfree.

Например, давайте добавим файл minfree для принтера bamboo. Найдем в файле /etc/printcap каталог спулинга для этого принтера; вот запись для принтера bamboo:

bamboo|ps|PS|S|panasonic|Panasonic KX-P4455 PostScript v51.4:\
        :sh:sd=/var/spool/lpd/bamboo:sc:rg=artists:mx#5000:\
        :lp=/dev/ttyd5:ms#-parenb cs8 clocal crtscts:rw:mx#5000:\
        :if=/usr/local/libexec/psif:\
        :df=/usr/local/libexec/psdf:

Каталог спулинга задается характеристикой sd. Укажем, что в файловой системе должно быть три мегабайта (что составляет 6144 блоков диска) свободного места, чтобы система LPD принимала удаленные задания:

# echo 6144 > /var/spool/lpd/bamboo/minfree
Ограничения пользователей

Вы можете управлять тем, какие удаленные пользователи смогут печатать на локальные принтеры, задавая характеристику rs в файле /etc/printcap. Когда характеристика rs указана в записи для локально подключенного принтера, система LPD будет принимать задания с удаленных хостов, если пользователь, посылающий задание, также имеет учетную запись с тем же именем на локальном хосте. В противном случае, система LPD отвергает задание.

Эта возможность особенно полезна в среде, где есть, например, несколько отделов, совместно использующих сеть, и некоторые пользователи могут переходить из отдела в отдел. Если дать им учетные записи в системах, они смогут использовать принтеры из систем в своих отделах. Если вы хотели бы позволить им использовать только принтеры, но не остальные ресурсы вашего компьютера, можно дать им "формальные" учетные записи, без начального каталога и с бесполезным начальным командным интерпретатором вроде /usr/bin/false.

10.4.5. Учет использования принтера

Итак, вам надо брать деньги за распечатки. А почему нет? Бумага и чернила стоят денег. А есть еще и затраты на поддержку в работоспособном состоянии - принтеры имеют множество движущихся частей и склонны к поломкам. Вы проанализировали состояние принтеров, объемы использования и затраты на их эксплуатацию, и получили определенную стоимость страницы (или фута, метра или чего угодно). Теперь, как же начать реально учитывать распечатки?

Итак, плохая новость состоит в том, что система спулинга LPD в этом не сильно поможет. Учет сильно зависит от типа используемого принтера, форматов распечаток и ваших требований к оплате использования принтеров.

Для реализации учета надо изменить текстовый фильтр принтера (чтобы учитывать обычные текстовые задания) и фильтры преобразования (чтобы учитывать другие форматы файлов), для подсчета страниц или запроса количества напечатанных страниц у принтера. Не получится обойтись использованием простого выходного фильтра, поскольку он не может выполнять учет. См. раздел Фильтры.

Обычно есть два способа выполнения учета:

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

  • Постоянный учет используется реже, вероятно, потому, что сложнее в реализации. Этот метод требует от фильтров выставлять пользователям суммы за распечатки сразу после использования принтеров. Как и проверка дисковых квот, этот учет выполняется немедленно. Вы можете не давать пользователям печатать, если баланс на их счету стал отрицательным, а также предоставить им способ проверить и изменить свои "квоты печати". Но этот метод требует поддержки базы данных для отслеживания пользователей и квот.

Система спулинга LPD легко поддерживает оба метода: поскольку вы (в большинстве случаев) должны предоставить фильтры, вам придется предоставить и код для учета. Но есть и положительный момент: методы учета могут быть сколько угодно гибкими. Например, можно выбрать периодический или постоянный учет. Можно выбрать, какую именно информацию регистрировать: имена пользователей, имена хостов, типы заданий, количество напечатанных страниц, квадратные метры использованной бумаги, продолжительность печати заданий, и т.д. Это делается путем изменения фильтров так, чтобы они сохраняли соответствующую информацию.

10.4.5.1. Простая система учета использования принтера

В составе FreeBSD поставляется две программы, которые можно сразу использовать для организации простой системы периодического учета. Речь идет о текстовом фильтре lpf, описанном в разделе lpf: текстовый фильтр, и о программе pac(8), обеспечивающей сбор и суммирование записей из учетных файлов принтеров.

Как уже упоминалось в разделе, посвященном фильтрам (Фильтры), система LPD при запуске текстового фильтра и фильтров преобразований передает им имя учетного файла в командной строке. Фильтры могут использовать соответствующий аргумент, чтобы определить, куда записывать учетную информацию. Имя этого файла берется из значения характеристики af в файле /etc/printcap и, если не заданно как абсолютное, интерпретируется относительно каталога спулинга.

Система LPD запускает lpf с аргументами ширины и длины страницы (которые берутся из характеристик pw и pl). Программа lpf использует эти аргументы для определения количества бумаги, которая будет использована. После посылки файла на принтер она вносит запись в учетный файл. Эти записи имеют следующий вид:

2.00 rose:andy
3.00 rose:kelly
3.00 orchid:mary
5.00 orchid:mary
2.00 orchid:zhang

Следует использовать отдельный учетный файл для каждого принтера, поскольку программа lpf не реализует механизм блокирования файлов, и два экземпляра lpf могут повредить записи друг друга, если записывают одновременно в один и тот же файл. Простой способ выделить отдельный учетный файл для каждого принтера - использовать характеристику af=acct в файле /etc/printcap. Тогда каждый учетный файл окажется в каталоге спулинга соответствующего принтера и будет назван acct.

Когда вы будете готовы выставить пользователям счет за распечатки, запустите программу pac(8). Просто перейдите в каталог спулинга принтера, учетную информацию которого вы хотите обработать, и введите команду pac. Вы получите итоговые суммы в долларах, как показано ниже:

  Login	       pages/feet   runs    price
orchid:kelly                5.00    1   $  0.10
orchid:mary                31.00    3   $  0.62
orchid:zhang                9.00    1   $  0.18
rose:andy                   2.00    1   $  0.04
rose:kelly                177.00  104   $  3.54
rose:mary                  87.00   32   $  1.74
rose:root                  26.00   12   $  0.52

total                     337.00  154   $  6.74

Команда pac(8) принимает следующие аргументы:

-P принтер

По какому принтеру подсчитывать итоговые суммы. Эта опция работает, только если в качестве значения характеристики af в файле /etc/printcap указано абсолютное имя.

-c

Сортировать отчет по сумме, а не по имени пользователя в алфавитном порядке.

-m

Игнорировать имя хоста в учетных файлах. При указании этой опции, пользователь smith на хосте alpha считается тем же, что и пользователь smith на хосте gamma. Обычно эти пользователи считаются разными.

-p стоимость

Вычислять суммы из расчета стоимость долларов за страницу или за фут, вместо использования значения характеристики pc в файле /etc/printcap, или двух центов (как принято по умолчанию). Можно задавать стоимость как число с плавающей запятой.

-r

Изменить порядок сортировки.

-s

Создать итоговый учетный файл и очистить учетный файл.

имя…​

Выдать учетную информацию только для пользователей с заданными именами.

В стандартном отчете, который создает команда pac(8), выдается количество страниц, напечатанное каждым из пользователей с различных хостов. Если для вас хосты не имеют значения (поскольку пользователи могут работать на любом хосте), выполните команду pac -m для получения следующих итогов:

  Login	       pages/feet   runs    price
andy                        2.00    1   $  0.04
kelly                     182.00  105   $  3.64
mary                      118.00   35   $  2.36
root                       26.00   12   $  0.52
zhang                       9.00    1   $  0.18

total                     337.00  154   $  6.74

Для получения сумм в долларах программа pac(8) использует значение характеристики pc в файле /etc/printcap (по умолчанию - 200, или 2 цента за страницу). Укажите в качестве значения этой характеристики, в сотых долях цента, стоимость страницы или фута, исходя из которой вы хотите брать деньги за распечатки. Это значение можно переопределить при вызове команды pac(8) с помощью опции -p. Но при использовании опции -p стоимость надо указывать в долларах, а не в сотых долях цента. Например, команда

# pac -p1.50

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

Наконец, при выполнении команды pac -s итоговая информация будет сохранена в итоговом учетном файле, имя которого строится как имя учетного файла принтера с суффиксом _sum. Затем учетный файл принтера очищается. Когда команда pac(8) выполняется повторно, она перечитывает итоговый файл для получения начальных сумм, а затем добавляет информацию из обычного учетного файла.

10.4.5.2. Как можно подсчитать количество напечатанных страниц?

Для выполнения хоть отдаленно точного учета надо уметь определять, сколько бумаги использовано для печати задания. Это - основная проблема учета использования принтеров.

Для обычных текстовых заданий решить эту проблему не сложно: надо считать, сколько строк входит в задание, и сравнивать с количеством строк на страницу, которые поддерживает принтер. Не забывайте учитывать символы забоя в файлах, которые приводят к перепечатке строк поверх, а также длинные логические строки, которые переносятся на несколько физических.

Текстовый фильтр lpf (представленный в разделе lpf: текстовый фильтр) учитывает эти вещи при выполнении учета. Если вы пишете текстовый фильтр, который должен осуществлять учет, может иметь смысл просмотреть исходный код программы lpf.

Но как обрабатывать файлы других форматов?

Ну, для преобразования из DVI в формат LaserJet или из DVI в PostScript®, можно в фильтре анализировать диагностические результаты команды dvilj или dvips, чтобы определить, сколько страниц было преобразовано. Может оказаться возможным применить этот прием и для других форматов файлов и программ преобразования.

Но эти методы несовершенны из-за того, что принтер мог фактически и не напечатать все эти страницы. Например, он мог замять бумагу, в нем мог закончиться тонер или он мог вообще взорваться - и пользователю все равно пришлось бы платить.

Так что же делать?

Есть только один надежный способ точного учета. Купите принтер, который может сообщать, сколько бумаги он использовал, и подключите его через последовательный порт или по сети. Практически все PostScript®-принтеры поддерживают такую возможность. Другие модели - тоже (сетевые лазерные принтеры Imagen, например). Измените фильтры для этих принтеров так, чтобы получать количество использованных страниц после печати каждого задания, и пусть они записывают учетную информацию только на основе этого значения. Не надо ни считать строки, ни выполнять чреватую ошибками обработку файла.

Конечно, всегда можно поступить великодушно и не брать денег за распечатки.

10.5. Использование принтеров

В этом разделе описано, как использовать настроенные принтеры в ОС FreeBSD. Вот сводка команд пользовательского уровня:

lpr(1)

Печать заданий

lpq(1)

Проверка очередей принтеров

lprm(1)

Удаление заданий из очередей принтеров

Есть также административная команда, lpc(8), описанная в разделе Администрирование принтеров, используемая для управления принтерами и их очередями.

Все три команды, lpr(1), lprm(1) и lpq(1), поддерживают опцию -P имя-принтера, позволяющую указать, с каким принтером/очередью из указанных в файле /etc/printcap работать. Это позволяет посылать, удалять и проверять задания на разных принтерах. Если вы не используете опцию -P, эти команды используют принтер, указанный в качестве значения переменной среды PRINTER. Наконец, если переменная среды PRINTER не задана, эти команды по умолчанию направляются на принтер по имени lp.

Далее термин стандартный принтер означает принтер, указанный переменной среды PRINTER или принтер по имени lp, если переменная среды PRINTER не задана.

10.5.1. Задания печати

Для печати файлов, выполните команду:

% lpr имя-файла ...

Эта команда печатает каждый из перечисленных файлов на стандартный принтер. Если файлы не указаны, команда lpr(1) читает данные для печати со стандартного входного потока. Например, следующая команда печатает некоторые важные системные файлы:

% lpr /etc/host.conf /etc/hosts.equiv

Для выбора конкретного принтера, введите:

% lpr -P имя-принтера имя-файла ...

Следующая команда печатает подробный листинг текущего каталога на принтере rattan:

% ls -l | lpr -P rattan

Поскольку для команды lpr(1) файлы не указаны, команда lpr читает данные для печати из стандартного входного потока, который содержит результат выполнения команды ls -l.

Команда lpr(1) может также принимать множество опций для управления форматированием, применения преобразований, печати нескольких копий и т.д. Дополнительную информацию см. в разделе Опции печати.

10.5.2. Проверка заданий

При печати с помощью команды lpr(1), данные, которые надо напечатать, помещаются вместе в пакет, который называют "заданием печати", и посылаются системе спулинга LPD. Каждый принтер имеет очередь заданий, и ваше задание ждет в этой очереди вместе с другими вашими заданиями и заданиями других пользователей. Принтер печатает эти задания по принципу первым пришло, первым выполнено.

Для получения очереди стандартного принтера, введите команду lpq(1). Чтобы указать конкретный принтер, используйте опцию -P. Например, команда

% lpq -P bamboo

показывает очередь для принтера по имени bamboo. Вот пример результатов выполнения команды lpq:

bamboo is ready and printing
Rank   Owner    Job  Files                              Total Size
active kelly    9    /etc/host.conf, /etc/hosts.equiv   88 bytes
2nd    kelly    10   (standard input)                   1635 bytes
3rd    mary     11   ...                                78519 bytes

Показано, что в очереди bamboo есть три задания. Первое задание, посланное пользователем kelly, получило "номер задания" 9. Каждое задание для принтера получает уникальный номер задания. В большинстве случаев номер задания можно игнорировать, но он потребуется, если надо будет отменить задание; подробнее об этом см. в разделе Удаление заданий.

Задание номер 9 состоит из двух файлов; несколько файлов, указанных в командной строке lpr(1), считаются частью одного задания. Это задание является текущим активным (обратите внимание на слово active в столбце "Rank"), т.е. принтер должен сейчас печатать это задание. Второе задание состоит из данных, передаваемых в качестве стандартного входного потока команде lpr(1). Третье задание послано пользователем mary; оно намного больше по объему. Полное имя файла, который печатается, слишком длинное и не помещается, поэтому команда lpq(1) просто выдает три точки.

Самая первая строка результатов команды lpq(1) тоже полезна: она говорит о том, что сейчас делает принтер (или, по крайней мере, что он делает по мнению системы LPD).

Команда lpq(1) также поддерживает опцию -l для генерации подробного длинного листинга. Вот пример результатов выполнения команды lpq -l:

waiting for bamboo to become ready (offline ?)
kelly: 1st                 [job 009rose]
       /etc/host.conf                    73 bytes
       /etc/hosts.equiv                  15 bytes

kelly: 2nd                 [job 010rose]
       (standard input)                  1635 bytes

mary: 3rd                                [job 011rose]
      /home/orchid/mary/research/venus/alpha-regio/mapping 78519 bytes

10.5.3. Удаление заданий

Если вы передумали печатать задание, можно удалить его из очереди заданий с помощью команды lprm(1). Часто можно использовать lprm(1) для удаления активного задания, но часть задания или даже все задание все равно может быть напечатано.

Для удаления задания со стандартного принтера сначала используйте команду lpq(1) для поиска номера задания. Затем введите команду:

% lprm номер-задания

Для удаления задания с указанного принтера, задайте опцию -P option. Следующая команда удаляет задание номер 10 из очереди заданий принтера bamboo:

% lprm -P bamboo 10

Для команды lprm(1) есть ряд сокращений:

lprm -

Удаляет все задания (со стандартного принтера), принадлежащие пользователю, который выполнил команду.

lprm пользователь

Удаляет все задания (для стандартного принтера), принадлежащие указанному пользователю. Суперпользователь может удалять задания других пользователей; обычный пользователь может удалять только собственные задания.

lprm

Если в командной строке не указаны номер задания, имя пользователя, или указана опция -, команда lprm(1) удаляет текущее активное задание на стандартном принтере, если оно принадлежит вам. Суперпользователь может удалять любое активное задание.

Добавьте опцию -P для любого из перечисленных выше сокращений, чтобы работать с любым необходимым принтером вместо стандартного. Например, следующая команда удаляет все задания текущего пользователя из очереди принтера по имени rattan:

% lprm -P rattan -

Если вы работаете в сетевой среде, команда lprm(1) позволит вам удалять задания только с хоста, с которого они были посланы, даже если тот же принтер доступен и с других хостов. Следующая последовательность команд демонстрирует это:

% lpr -P rattan myfile
% rlogin orchid
% lpq -P rattan
Rank   Owner      Job  Files                          Total Size
active seeyan      12    ...                           49123 bytes
2nd    kelly      13   myfile                         12 bytes
% lprm -P rattan 13
rose: Permission denied
% logout
% lprm -P rattan 13
dfA013rose dequeued
cfA013rose dequeued

10.5.4. Не только обычный текст: опции печати

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

10.5.4.1. Опции форматирования и преобразования

Следующие опции команды lpr(1) управляют форматированием файлов в задании. Используйте эти опции, если задание содержит не простой текст или если вы хотите сформатировать простой текст с помощью утилиты pr(1).

Например, следующая команда печатает файл DVI (из системы верстки TeX) по имени fish-report.dvi на принтере bamboo:

% lpr -P bamboo -d fish-report.dvi

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

Все эти опции, кроме -p и -T, требуют наличия установленных для целевого принтера фильтров преобразования. Например, опция -d требует фильтра преобразования DVI. Подробнее см. в разделе Фильтры преобразования.

-c

Печать файлов cifplot.

-d

Печать файлов DVI.

-f

Печать текстовых файлов на языке FORTRAN.

-g

Печать графиков.

-i число

Сдвинуть результат вправо на число столбцов; если число не указано, сдвиг выполняется на 8 столбцов. Эта опция работает только с определенными фильтрами преобразования.

Не помещайте пробелы между -i и числом.

-l

Печать текстовых данных буквально, включая управляющие символы.

-n

Печать данных ditroff (device independent troff).

-p

Форматировать обычный текст перед печатью утилитой pr(1). Подробнее см. pr(1).

-T заголовок

Использовать указанный заголовок в колонтитуле pr(1) вместо имени файла. Эта опция учитывается только при использовании вместе с опцией -p.

-t

Печать данных troff.

-v

Печать растровых данных.

Вот пример: следующая команда печатает красиво сформатированную версию справочного руководства по команде ls(1) на стандартный принтер:

% zcat /usr/shared/man/man1/ls.1.gz | troff -t -man | lpr -t

Команда zcat(1) распаковывает исходный код страницы справочного руководства ls(1) и передает его команде troff(1), которая форматирует его и выдает результат в формате GNU troff, передаваемый команде lpr(1), посылающей задание спулеру LPD. Поскольку мы использовали опцию -t команды lpr(1), спулер при печати задания будет преобразовывать результат GNU troff в формат, понятный стандартному принтеру.

10.5.4.2. Опции обработки заданий

Следующие опции команды lpr(1) требуют от системы LPD специальной обработки задания:

-# копий

Выдавать указанное количество копий каждого файла в задании вместо одной. Администратор может отключить эту опцию для уменьшения износа принтера и поощрения использования ксерокса. См. раздел Ограничение количества копий.

В следующем примере на стандартный принтер печатается три копии файла parser.c, а затем - три копии parser.h:

% lpr -#3 parser.c parser.h
-m

Посылать почту после завершения задания печати. При указании этой опции, система LPD будет посылать почту на ваше имя после завершения обработки вашего задания. В сообщении будет сказано, выполнено ли задание успешно или по ходу была ошибка, и (часто) - в чем она состояла.

-s

Не копировать файлы в каталог спулинга, а сделать там на них символические связи.

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

Есть, однако, и недостаток: поскольку система LPD будет ссылаться на исходные файлы непосредственно, вы не сможете изменять или удалять их, пока они не будут распечатаны.

Если вы печатаете на удаленный принтер, система LPD будет вынуждена, так или иначе, скопировать файлы с локального хоста на удаленный, поэтому опция -sсэкономит место только в локальном каталоге спулинга, но не в удаленном. Но, она все равно полезна.

-r

Удалять файлы в задании после копирования в каталог спулинга или после печати, если указана опция -s. Будьте внимательны при использовании этой опции!

10.5.4.3. Опции начальных страниц

Эти опции команды lpr(1) изменяют текст, который обычно выдается на начальной странице задания. Если выдача начальных страниц для целевого принтера отключена, эти опции не действуют. Информацию по настройке начальных страниц см. в разделе Начальные страницы.

-C текст

Заменить имя хоста на начальной странице текстом. Обычно на ней выдается имя хоста, с которого было послано задание.

-J текст

Заменить имя задания на начальной странице текстом. Имя задания обычно совпадает с именем первого файла в задании или имеет значение stdin, если печатается стандартный входной поток.

-h

Не выдавать начальной страницы.

В некоторых организациях эта опция может не действовать, что определяется способом генерации начальных страниц. Подробнее см. в разделе Начальные страницы.

10.5.5. Администрирование принтеров

Как администратор принтеров, вы должны их установить, настроить и протестировать. С помощью команды lpc(8) вы можете взаимодействовать с принтерами и другими способами. С помощью lpc(8) вы можете:

  • Запускать и останавливать принтеры

  • Включать и отключать их очереди

  • Изменять порядок заданий в каждой очереди.

Начнем с замечания по терминологии: если принтер остановлен, он не будет печатать ничего из своей очереди. Пользователи могут продолжать посылать задания, которые будут ждать в очереди, пока принтер не будет запущен или пока очередь не будет очищена.

Если очередь отключена, ни один пользователь (кроме root) не может посылать задания на принтер. Во включенную очередь можно посылать задания. Принтер для отключенной очереди может быть запущен; при этом он будет продолжать печатать находящиеся в очереди задания, пока очередь не станет пустой.

В общем случае, для использования команды lpc(8) необходимо иметь привилегии root. Обычные пользователи могут использовать команду lpc(8) только для получения состояния принтера и перезапуска зависшего принтера.

Далее представлена сводка команд lpc(8). Большинство команд принимает аргумент имя-принтера, задающий, с каким принтером работать. Можно использовать значение all вместо имени-принтера, означающее все принтеры, перечисленные в файле /etc/printcap.

abort имя-принтера

Снять текущее задание и остановить принтер. Пользователи могут продолжать посылать задания, если очередь включена.

clean имя-принтера

Удалить старые файлы из каталога спулинга принтера. Иногда файлы, составляющие задание, не удаляются как положено системой LPD, особенно если в ходе печати были ошибки и выполнялось много административных действий. Эта команда находит файлы, не принадлежащие каталогу спулинга, и удаляет их.

disable имя-принтера

Отключить постановку новых заданий в очередь. Если принтер работает, он продолжит печатать задания, остающиеся в очереди. Суперпользователь (root) всегда может посылать задания, даже в отключенную очередь.

Эта команда полезна при тестировании вновь установленного принтера или фильтра: отключаем очередь и посылаем задания как root. Другие пользователи не смогут посылать задания, пока вы не закончите тестирование и не включите очередь повторно командой enable.

down имя-принтера сообщение

Отключить принтер. Аналогична последовательности команд disable и stop. Указанное сообщение выдается как состояние принтера при проверке пользователем очереди принтера с помощью lpq(1) или запросе его состояния командой lpc status.

enable имя-принтера

Включить очередь для принтера. Пользователи могут посылать задания, но принтер не будет их печатать, пока не будет запущен.

help имя-команды

Выдать справочную информацию по команде имя-команды. Если имя-команды не указано, выдает сводку по имеющимся командам.

restart имя-принтера

Перезапустить принтер. Обычные пользователи могут использовать эту команду, если в результате неких чрезвычайных обстоятельств система LPD зависла, но они не могут запустить принтер, остановленный командами stop или down. Команда restart эквивалентна последовательности команд abort и start.

start имя-принтера

Запустить принтер. Принтер будет печатать задания, находящиеся в его очереди.

stop имя-принтера

Остановить принтер. Принтер закончит печать текущего задания и больше ничего из очереди печатать не будет. Хотя принтер и остановлен, пользователи могут посылать задания во включенную очередь.

topq имя-принтера задание-или-имя-пользователя

Переупорядочить очередь для указанного принтера, помещая указанные по номеру задания или задания указанного по имени пользователя в начало очереди. Для этой команды нельзя использовать all в качестве имени-принтера.

up имя-принтера

Включить принтер; команда по действию противоположна команде down. Эквивалентна последовательности команд start и enable.

Утилита lpc(8) принимает перечисленные выше команды в командной строке. Если команда не указана, утилита lpc(8) входит в интерактивный режим, в котором можно вводить команды, пока не будет введена команда exit, quit или символ конца файла.

10.6. Альтернативы стандартному спулеру

Если вы прочитали все это руководство, к этому моменту вы знаете практически все, что надо знать о системе спулинга LPD, входящей в состав ОС FreeBSD. Вы, возможно, уже осознали многие из ее недостатков, что, естественно, приводит к вопросу: "Какие еще системы спулинга существуют (и работают с ОС FreeBSD)"?

LPRng

Система LPRng, имя которой означает "LPR: the Next Generation" (LPR: следующее поколение) - это полностью переписанная система PLP. Патрик Пауэл (Patrick Powell) и Джастин Мейсон (Justin Mason) (основной специалист, занимающийся поддержкой PLP) объединили усилия для создания системы LPRng. Основной сайт по системе LPRng - http://www.lprng.org/.

CUPS

Система CUPS (сокращение от Common UNIX Printing System) предоставляет переносимый механизм печати для операционных систем, основанных на UNIX®. Она была разработана компанией Easy Software Products в качестве стандартного механизма печати для всех производителей и пользователей UNIX®.

Система CUPS использует протокол Internet Printing Protocol (IPP) для управления заданиями и очередями. Протоколы Line Printer Daemon (LPD), Server Message Block (SMB) и AppSocket (известный также как JetDirect) также поддерживаются, но с меньшими возможностями. Система CUPS добавляет поиск сетевых принтеров и опции печати на основе PostScript Printer Description (PPD), для поддержки практической печати в UNIX®.

Основной сайт по системе CUPS - http://www.cups.org/.

10.7. Выявление проблем

После выполнения простого тестирования с помощью команды lptest(1) вы можете получить один из следующих результатов вместо корректной распечатки:

Все работает, после определенной задержки; или не выдается распечатанная страница.

Принтер напечатал все, что нужно, но он на некоторое время задумывался и ничего не делал. Фактически, могло потребоваться нажать кнопку PRINT REMAINING или FORM FEED на принтере, чтобы результаты были выданы.

Если это произошло, вероятно, принтер ждал, нет ли в задании еще данных, прежде чем что бы то ни было печатать. Для решения этой проблемы можно посылать в текстовом фильтре на принтер символ FORM FEED (или любую необходимую последовательность символов). Этого обычно достаточно, чтобы принтер немедленно распечатал любой остающийся в его внутреннем буфере текст. Также полезно убедиться, что каждое задание печати заканчивается полной страницей, чтобы следующее задание не начиналось где-то с середины последней страницы предыдущего задания.

Следующий измененный скрипт командного интерпретатора /usr/local/libexec/if-simple выдает символ прогона страницы после посылки задания на принтер:

#!/bin/sh
#
# if-simple - Простой текстовый входной фильтр для lpd
# Установлен в /usr/local/libexec/if-simple
#
# Просто копирует stdin в stdout. Игнорирует все аргументы фильтра.
# Выдает символ прогона страницы (\f) после печати задания.

/bin/cat && printf "\f" && exit 0
exit 2
Принтер печатает "лесенкой".

Вы получаете на бумаге следующее:

!"#$%&'()*+,-./01234
                "#$%&'()*+,-./012345
                                 #$%&'()*+,-./0123456

Вы стали очередной жертвой эффекта лесенки, вызванного различными интерпретациями того, какие символы должны обозначать новую строку. Операционные системы UNIX®-стиля используют один символ: ASCII-код 10, перевод строки (line feed - LF). MS-DOS®, OS/2® и другие используют пару символов, ASCII-код 10 и ASCII-код 13 (возврат каретки, carriage return или CR). Многие принтеры используют соглашение MS-DOS® для представления новых строк.

При печати из FreeBSD в тексте используется только символ перевода строки. Принтер, встретив символ перевода строки, переходит на следующую строку, но оставляет ту же горизонтальную позицию на строке для следующего печатаемого символа. Вот зачем нужен символ возврата каретки: чтобы перенести следующий печатаемый символ на левый край бумаги.

Вот что ОС FreeBSD хочет от принтера:

Принтер получает CR

Принтер печатает CR

Принтер получает LF

Принтер печатает CR + LF

Вот несколько способов этого добиться:

  • Использовать переключатели конфигурации принтера или панель управления, чтобы изменить его интерпретацию этих символов. Поищите как это сделать в руководстве по своему принтеру.

    Если вы загружаете другие операционные системы, кроме FreeBSD, может иметь смысл переконфигурировать принтер для использования такой интерпретации символов CR и LF, которая принята в этих операционных системах. Затем можно использовать одно из представленных далее решений.

  • Заставить драйвер последовательного порта FreeBSD автоматически преобразовывать LF в CR+LF. Конечно, это подойдет только для принтеров, подключенных к последовательным портам. Для включения этой возможности используйте характеристику ms# и установите режим onlcr для принтера в файле /etc/printcap.

  • Послать управляющий код на принтер, заставляющий его временно обрабатывать символы LF по-другому. Управляющие коды, которые может поддерживать ваш принтер, поищите в руководстве своего принтера. Когда найдете соответствующий управляющий код, измените текстовый фильтр для посылки сначала этого кода, а затем - задания печати.

    Вот пример текстового фильтра для принтеров, понимающих управляющие последовательности языка Hewlett-Packard PCL. Этот фильтр заставляет принтер обрабатывать символы LF как LF и CR; затем он посылает задание; наконец, он посылает символ прогона страницы для выдачи последней страницы задания. Он должен работать практически со всеми принтерами Hewlett Packard.

    #!/bin/sh
    #
    # hpif - Простой текстовый входной фильтр для lpd для принтеров на базе HP-PCL
    # Установлен в /usr/local/libexec/hpif
    #
    # Просто копирует stdin в stdout. Игнорирует все аргументы фильтра.
    # Требует от принтера обрабатывать LF как CR+LF. Выдает страницу по окончании.
    
    printf "\033&k2G" && cat && printf "\033&l0H" && exit 0
    exit 2

    Вот пример файла /etc/printcap с хоста orchid. К нему через первый параллельный порт подключен один принтер, Hewlett Packard LaserJet 3Si, по имени teak. Для него в качестве текстового фильтра используется представленный выше скрипт:

    #
    #  /etc/printcap для хоста orchid
    #
    teak|hp|laserjet|Hewlett Packard LaserJet 3Si:\
            :lp=/dev/lpt0:sh:sd=/var/spool/lpd/teak:mx#0:\
            :if=/usr/local/libexec/hpif:
Строки напечатаны одна поверх другой.

Принтер так и не перешел на следующую строку. Все строки текста были напечатаны одна поверх другой, на одной строке.

Эта проблема "обратна" эффекту лесенки, описанному выше, и встречается намного реже. Каким-то образом, символы LF, которые ОС FreeBSD использует для завершения строк, обрабатывались как символы CR и вызывали перевод позиции печати на левый край бумаги, но не переход на следующую строку.

Используйте переключатели конфигурации принтера или панель управления для обеспечения следующей интерпретации символов LF и CR:

Принтер получаетПринтер печатает

CR

CR

LF

CR + LF

Принтер теряет символы.

По ходу печати принтер не печатает несколько символов в каждой строке. Проблема со временем может становиться все хуже, так что теряется все больше символов.

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

  • Если принтер поддерживает управление потоком XON/XOFF, заставить FreeBSD использовать его, указав режим ixon в характеристике ms#.

  • Если принтер поддерживает управление несущим потоком (carrier flow control), укажите режим crtscts в характеристике ms#. Убедитесь, что кабель, соединяющий принтер с компьютером, правильно распаян для управления несущим потоком.

Напечатан мусор.

Принтер напечатал нечто похожее на случайный мусор, а не требуемый текст.

Это, обычно, - еще один симптом неправильных параметров взаимодействия с последовательным принтером. Перепроверьте скорость взаимодействия в характеристике br и установку четности в характеристике ms#; проверьте, что принтер использует те же установки, которые заданы в файле /etc/printcap.

Ничего не произошло.

Если ничего не произошло, проблема, вероятно, связана с FreeBSD, а не с оборудованием. Добавьте характеристику журнального файла (lf) в файл /etc/printcap для принтера, работу с которым отлаживаете. Например, вот запись для принтера rattan с характеристикой lf:

rattan|line|diablo|lp|Diablo 630 Line Printer:\
        :sh:sd=/var/spool/lpd/rattan:\
        :lp=/dev/lpt0:\
        :if=/usr/local/libexec/if-simple:\
        :lf=/var/log/rattan.log

Затем попытайтесь напечатать снова. Поищите в журнальном файле (в нашем примере - /var/log/rattan.log) возможные сообщения об ошибках. На основе полученных сообщений попытайтесь решить проблему.

Если вы не зададите характеристику lf, система LPD использует по умолчанию /dev/console.


Этот, и другие документы, могут быть скачаны с https://download.freebsd.org/ftp/doc/

По вопросам, связанным с FreeBSD, прочитайте документацию прежде чем писать в <freebsd-questions@FreeBSD.org>.
По вопросам, связанным с этой документацией, пишите в рассылку <freebsd-doc@FreeBSD.org>.