Базовая программа должна не только читать данные из файлов и передавать их устройствам, но и взаимодействовать с процессом qdaemon, чтобы выполнять следующие операции:
Процесс qdaemon и базовая программа взаимодействуют посредством файла состояния. В разделе Описание процедур базовых программ в libqb описан набор библиотечных подпрограмм, обеспечивающих это взаимодействие. Эти подпрограммы хранятся в библиотеке /usr/lib/libqb.a.
Когда процесс qdaemon вызывает базовую программу, он передает ей следующие параметры (в указанном порядке):
Каждому устройству и связанной с ним очереди соответствует некоторый файл состояния. Эти файлы хранятся в каталоге /var/spool/lpd/stat.
Файл состояния служит для связи между процессом qdaemon и базовой программой. Процесс qdaemon передает базовой программе информацию о дате создания файла, о том, следует ли разделять страницы, и о числе копий, которые необходимо напечатать. Базовая программа передает процессу qdaemon учетную запись только что выполненного задания. Кроме того, базовая программа периодически обновляет информацию о том, сколько страниц уже напечатано и какая часть задания в процентах уже выполнена. Эту информацию принимает команда qchk.
Примечание: Базовой программе запрещено записывать непосредственно в свой файл состояния. Для этого она должна вызывать соответствующие подпрограммы из библиотеки libqb.
Базовая программа должна вызывать эти подпрограммы по двум причинам:
Для того чтобы инициализировать данные, общие для всех библиотечных подпрограмм, базовая программа вызывает подпрограмму log_init. Дополнительная информация приведена в Описание процедур базовых программ в libqb. Формат вызова следующий:
log_init();
Цель вызова этой подпрограммы - инициализация интерфейса файла состояния. Подпрограмма log_init, как и все подпрограммы типа log_ в библиотеке, при неудачном завершении возвращает значение -1.
Команда enq -N служит для печати дополнительных копий файла. Например, для печати 5 копий файла Имя_файла введите следующую команду:
enq -N5 Имя_файла
Команда enq передает данные процессу qdaemon, который помещает их в файл состояния. Базовые программы считывают эти данные с помощью подпрограммы get_copies (Описание процедур базовых программ в libqb), которая возвращает общее число запрошенных копий.
Команда qchk выдает информацию обо всех запущенных заданиях, а именно: инициализатор, заголовок, число страниц и объем выполненной части задания в процентах. Вся информация поступает из файла состояния. Большая часть этих сведений определяется процессом qdaemon при первом запуске базовой программы, исключая данные о числе напечатанных страниц и объеме выполненной части в процентах, которые определяются базовой программой.
Для получения этой информации базовая программа должна периодически вызывать из библиотеки libqb функции, описанные в разделе Описание процедур базовых программ в libqb:
Базовая программа может вызвать эти подпрограммы в любое время; рекомендуемая частота вызовов - в конце каждой страницы.
По завершению базовой программы, процесс qdaemon просматривает учетные данные из файла состояния. При соответствующих настройках файла qconfig, учетные данные заносятся в файл, обрабатываемый программами учета. В противном случае, при отмене задания изменения не затронут уже напечатанные страницы.
Базовая программа передает учетные данные процессу qdaemon с помощью подпрограммы log_charge(charge). См. Описание процедур базовых программ в libqb. Перед завершением работы базовая программа должна вызвать эту подпрограмму. Подпрограмма также должна быть запущена вместе с функцией log_progress во время печати. Дополнительная информация приведена в Обновление информации в файле состояния. Если же это не будет сделано, то при отмене задания в файл не будут занесены учетные данные о количестве напечатанных к данному моменту страниц.
Дополнительная информация о ведении учетного протокола заданий содержится в разделе "Сведения о программе буферизации".
Дополнительная информация об учете заданий приведена в книге Глава 3, Обзор программы буферизации.
При завершении работы базовой программы процесс qdaemon анализирует код возврата и определяет, выполнено ли задание и можно ли продолжать использовать устройство. Таким образом, необходимо, чтобы все базовые программ применяли одинаковые коды возврата. Базовая программа должна содержать строку #include <IN/standard.h>, чтобы использовать стандартные значения кодов.
Допустимы следующие коды
завершения:
При возникновении ошибки базовая программа должна отправить пользователю сообщение. Прежде чем отправить сообщение, базовая программа должна проверить значение переменной среды PIO_IPCWRITEFD. Если переменной присвоено некоторое значение, сообщение передается диспетчеру печати с помощью конвейера. Диспетчер печати интерпретирует сообщение и отправляет его пользователю. Если переменной среды PIO_IPCWRITEFD не присвоено никакого значения, базовая программа отправляет сообщение пользователю с помощью подпрограммы sysnot.
Программа буферизации печати qdaemon всегда отправляет сообщения с помощью подпрограммы sysnot (Описание процедур базовых программ в libqb). Программы буферизации печати для систем, отличных от базовой оперативной системы, могут отправлять сообщения с помощью подпрограммы sysnot или с помощью конвейера.
Базовая программа может отправлять сообщения напрямую пользователю с помощью подпрограммы sysnot (Описание процедур базовых программ в libqb). Подпрограмма sysnot либо отправляет пользователю почтовое сообщение, либо пересылает сообщение на пользовательский терминал. Формат вызова подпрограммы sysnot следующий:
sysnot(пользователь, хост, сообщение, pref) char *пользователь; char *хост; char *сообщение; unsigned int *pref;
Значение параметра pref должно быть равно DOMAIL или DOWRITE. В первом случае пользователь получает сообщение по почте. Во втором - сообщение передается на пользовательский терминал, если пользователь зарегистрирован в системе. Если пользователь не зарегистрирован в системе, то сообщение будет отправлено по почте. Константы DOMAIL и DOWRITE определены в файле /usr/include/IN/backend.h. Если пользователь в настоящее время не подключен к системе, то сообщение будет отправлено по почте. Константы DOMAIL и DOWRITE описаны в файле /usr/include/IN/backend.h.
Базовая программа может отправлять сообщения пользователю, пересылая их диспетчеру печати с помощью конвейера. Таким образом обеспечивается однонаправленная связь между базовой программой принтера и диспетчером печати.
Диспетчер печати открывает конвейер без имени и запрашивает пару файловых дескрипторов - один для чтения, другой для записи. Диспетчер печати экспортирует дескриптор для записи с помощью переменной среды PIO_IPCWRITEFD, а затем вызывает базовую программу печати с помощью подпрограмм fork и exec. Если переменной среды PIO_IPCWRITEFD присвоено некоторое значение, базовая программа печати отправляет все сообщения через конвейер.
Диспетчер печати, как правило, вызывает подпрограмму select для опроса конвейера, чтобы определить наличие сообщений. Помимо проверки состояния завершения базовой программы принтера с помощью подпрограммы waitpid, диспетчер печати проверяет состояние ввода-вывода конвейера. Диспетчер печати устанавливает обработчик сигнала SIGCHLD и считывает данные по блокам с конвейера. Обработчик сигнала анализирует состояние завершения базовой программы печати и выполняет необходимые действия. Если в конвейере отсутствуют сообщения, диспетчер печати завершает работу конвейера и выполняет дальнейшую очистку.
Каждое сообщение базовой программы принтера состоит из кадра заголовка сообщения, необязательных кадров заголовков параметров, расширенного текста сообщения и необязательных параметров. В заголовке сообщения задается тип сообщения, информация о каталоге сообщений, длина расширенного текста сообщения и число переменных параметров сообщения. Переменные параметры сообщения применяются для формирования расширенного текста сообщения из основного текста сообщения, полученного из каталога сообщений. Форматы заголовков сообщения и параметров сообщения описаны в файле /usr/include/piostruct.h.
При извлечении сообщений из конвейера диспетчер печати считывает кадр заголовка сообщения, кадры заголовков параметров сообщения (от 0 до 9, согласно числу параметров, заданному в кадре заголовка сообщения). Диспетчер печати считывает расширенный текст сообщения, длина которого задается в кадре заголовка сообщения, а затем параметры, если они есть. Тип и размер параметров задаются в соответствующих кадрах заголовков параметров каждого сообщения.
Тип сообщения задается в кадре заголовка сообщения. Существует два типа параметров:
Фактический текст сообщения хранится в расширенном формате. Параметры помещаются в текст сообщения после извлечения из файла каталога сообщений, который соответствует локали сервера. Диспетчер печати использует существующий текст сообщения или самостоятельно формирует его с помощью информации из каталога сообщений и параметров сообщения. Однако базовая программа не всегда может передать информацию из каталога сообщений (номер сообщения, номер набора и имя каталога) и переменные параметры сообщения. Поэтому диспетчер печати должен проверить, задано ли значение поля Имя каталога (поле pm_catnm). Если имя каталога равно пустой строке, диспетчер печати использует полученный расширенный текст сообщения.
Если задано имя каталога, диспетчер печати может извлечь сообщение из каталога и поместить в него полученные параметры сообщения. Параметры сообщения могут быть целого или строкового типа. Но базовая программа передает все параметры сообщения как строки, соединенные в расширенный текст сообщения. Если диспетчер печати извлекает сообщение из заданного каталога и помещает в него параметры, то должны быть выполнены следующие условия:
Ошибка %8$d при открытии файла %6$s
Диспетчер печати преобразует это сообщение к следующему виду:
Ошибка %s при открытии файла %s
и присвоит первому переменному параметру указатель на восьмой параметр, второму переменному параметру - указатель на шестой параметр, а остальным переменным параметрам - указатели на пустые строки. Затем диспетчер печати вызовет подпрограмму sprintf или аналогичную функцию, передав в качестве параметров эти девять указателей.
Команда qchk показывает состояние устройства. Одна из записей в выводимой таблице соответствует текущему состоянию очереди. Эта информация поступает из файла состояния. Как правило, процесс qdaemon выполняет обновление файла состояния. В файле /usr/include/IN/backend.h приведен список состояний очередей и их описание.
Обычно, процесс qdaemon обновляет файл состояния. Тем не менее, некоторые базовые программы могут явно устанавливать состояние ОЖИДАНИЕ (#include <IN/backend.h>), если им не удается отправлять вывод на устройство, и снова устанавливать состояние ВЫПОЛНЯЕТСЯ, если вывод возобновляется. Например, базовая программа, которая приостанавливает работу после печати каждой страницы, может переводить очередь в состояние ОЖИДАНИЕ на время ожидания.
Подпрограмма log_status(status) переключает состояние задания между значениями ВЫПОЛНЕНИЕ и ОЖИДАНИЕ. Дополнительная информация приведена в Описание процедур базовых программ в libqb. Параметр задает новое состояние.
Если устройство, связанное с очередью, находится в состоянии ОЖИДАНИЕ_УСТРОЙСТВА, запустите команду enq -U -Pочередь, чтобы привести очередь в состояние готовности. Если это не сработает, переместите все задания в эту очередь и введите команду enq -G, чтобы очистить все очереди и завершить работу процесса qdaemon. Затем повторите запуск программы qdaemon.
Если пользователь отменяет задание с помощью команды qcan, эта команда передает запрос процессу qdaemon. Базовая программа прекратит печать вскоре после получения сигнала. Этого можно добиться двумя способами.
Во-первых, если базовая программа не может выполнить никаких специальных действий при получении сигнала SIGTERM, то она немедленно прекращает работу. Это самый простой вариант, но он не позволяет базовой программе выполнить никаких действий по очистке (например, сбросить быстродействие линии связи, перейти к началу формы, прервать телефонное соединение) перед завершением работы.
Во-вторых, базовая программа может перехватить сигнал SIGTERM, выполнить необходимые действия по очистке и завершить работу с кодом завершения EXITSIGNAL (#include <IN/standard.h>). Специальный код возврата сообщает процессу qdaemon об отмене задания.
Базовые программы, которые перехватывают сигнал SIGTERM, должны завершать работу через небольшой промежуток времени после получения сигнала.