Как добавить фильтр System V с помощью API cups?

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

pstRequest = ippNew();

pstRequest->request.op.operation_id = CUPS_ADD_PRINTER;
pstRequest->request.any.request_id  = 1;

ippAddString(pstRequest, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, "us-ascii");
ippAddString(pstRequest, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, "en");

ippAddString(pstRequest, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
ippAddString(pstRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "device-uri", NULL, szUri);
ippAddString(pstRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, szPrinterUri);
ippAddInteger(pstRequest, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", IPP_PRINTER_IDLE);
ippAddBoolean(pstRequest, IPP_TAG_PRINTER, "printer-is-accepting-jobs", true);

Ради разговора:

szUri        = "serial:/dev/pts/12?baud=2400+bits=7+parity=none+flow=none";
szPrinterUri = "ipp://localhost/printers/myptr";

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

lp -d myptr test.print

Моей первой мыслью было просто скопировать файл, который я хотел использовать в качестве фильтра, в каталог /etc/cups/interfaces и назвать его myptr. Я сделал это, дал ему правильного пользователя, группу и разрешения, и, похоже, это не сработало. Я даже пытался вставить sleep 60 в начале сценария, но он так и не появился в ps.

Я попытался добавить принтер с помощью lpadmin следующим образом, и он работает правильно:

lpadmin -h localhost -p myptr2 -v "serial:/dev/pts/12?baud=2400+bits=7+parity=none+flow=none" -i /tmp/my.serial.filter

После этого я должен позвонить cupsaccept и cupsenable, но принтер работает и отправляет печать через мой фильтр. lpadmin правильно копирует файл my.serial.filter из /tmp в /etc/cups/interfaces и называет его myptr2, так же, как я сделал это в своей программе, и, хоть убей, я не могу найти ни одной ссылки на фильтр ни в одном из файлов конфигурации cups, что заставляет меня задуматься Я пропускаю шаг. Тем не менее, принтер myptr2, который я добавляю с помощью lpadmin, работает корректно, а принтер myptr, который я добавляю с помощью API, хоть и печатает, но не печатает через фильтр.

Среди различных поисков в Google, которые я сделал, я прочитал Реализация CUPS и Документация по HTTP и IPP API, и самое близкое, что у меня есть пришел к выводу, что в первом есть комментарий для CUPS- Операция добавления-изменения-принтера, которая гласит:

За запросом CUPS-Add-Modify-Printer может дополнительно следовать файл PPD или сценарий интерфейса System V, который будет использоваться для принтера. Атрибут «ppd-name» переопределяет любой файл, прикрепленный к концу запроса, с помощью локального файла CUPS PPD.

Это побудило меня попробовать использовать

ippAddString(pstRequest, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name", NULL, szFilter);

с szFilter, установленным как на "/tmp/my.serial.filter", так и на "/etc/cups/interfaces/myptr" (конечно, в отдельных тестах), но безрезультатно.

Может ли кто-нибудь сказать мне, где я могу ошибаться?


person William    schedule 19.07.2012    source источник


Ответы (1)


Хорошо, я получил исходный код lpadmin из репозитория исходного кода cups, и ответ оказался намного проще, чем я пытался это сделать. Судя по всему, я не указал достаточно своего источника в первоначальном сообщении. После приведенного выше фрагмента кода я вызывал следующее:

pstHttpServer = httpConnectEncrypt("localhost", ippPort(), cupsEncryption());
pstResponse   = cupsDoFileRequest(pstHttpServer, pstRequest, "/admin/", NULL);
ippDelete(pstResponse);
httpClose(pstHttpServer);

(с применимой проверкой ошибок, конечно)

Ответ на мой вопрос находится в указателе NULL, который я передал в качестве четвертого аргумента cupsDoFileRequest. Как отмечалось выше, «запрос CUPS-Add-Modify-Printer может дополнительно сопровождаться файлом PPD или сценарием интерфейса System V». Я не связывал их вместе, но это предложение относится к четвертому аргументу cupsDoFileRequest, в котором, если я помещу путь моего фильтра, "/tmp/my.serial.filter", запрос будет выполнен успешно, и my.serial.filter будет правильно скопировано в /etc/cups/interfaces как myptr, после чего все моя печать на myptr проходит через фильтр, как и ожидалось.

Таким образом, окончательное решение состоит в том, чтобы изменить строку pstResponse выше следующим образом:

pstResponse   = cupsDoFileRequest(pstHttpServer, pstRequest, "/admin/", "/tmp/my.serial.filter");
person William    schedule 19.07.2012