Frage

I need to programmatically add a printer to cups that has a System V filter installed. Right now I am using the following code to create the request to add the printer:

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);

For the sake of conversaion:

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

This appears to correctly add the printer to the cups system because I can then send print to it using the following command:

lp -d myptr test.print

My first thought was to just copy the file that I wanted to use as the filter into the /etc/cups/interfaces directory and call it myptr. I did this, gave it the correct user, group, and permissions, and it didn't seem to work. I even tried sticking a sleep 60 at the front of the script and it never showed up in ps.

I've tried adding the printer using lpadmin as follows and it works correctly:

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

I have to call cupsaccept and cupsenable afterward, but the printer works and it sends the print through my filter. lpadmin correctly copies the my.serial.filter file from /tmp into /etc/cups/interfaces and names it myptr2, just as I did in my program, and, for the life of me, I cannot find any reference to the filter in any of the cups configuration files that makes me think I'm missing a step. Nevertheless, the myptr2 printer that I add with lpadmin works correctly and the myptr printer that I add using the API, while it does print, does not print through the filter.

Among the various Google searches I have made, I have read through the CUPS Implementation and the HTTP and IPP APIs Documentation, and the closest that I have come to was that, in the former, there is a comment for the CUPS-Add-Modify-Printer Operationthat reads:

The CUPS-Add-Modify-Printer request can optionally be followed by a PPD file or System V interface script to be used for the printer. The "ppd-name" attribute overrides any file that is attached to the end of the request with a local CUPS PPD file.

This led me to try using

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

with szFilter set to both "/tmp/my.serial.filter" and "/etc/cups/interfaces/myptr" (in separate tests, of course), but to no avail.

Can anyone tell me where I might be going wrong?

War es hilfreich?

Lösung

Okay, I got ahold of the source to lpadmin from the cups source repository and the answer was much easier than I was trying to make it. Apparently, I did not include enough of my source in the initial posting. After the code snippet from above, I was calling the following:

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

(with applicable error checking, of course)

The answer to my question is in the NULL pointer that I was passing as the fourth argument to cupsDoFileRequest. As noted above, "[t]he CUPS-Add-Modify-Printer request can optionally be followed by a PPD file or System V interface script." I hadn't tied the two together, but that sentence refers to the fourth argument of cupsDoFileRequest in which, if I place the path of my filter, "/tmp/my.serial.filter", the request succeeds and my.serial.filter gets correctly copied into /etc/cups/interfaces as myptr, after which all of my print to myptr goes through the filter as expected.

Thus, the final solution is to change the pstResponse line above as follows:

pstResponse   = cupsDoFileRequest(pstHttpServer, pstRequest, "/admin/", "/tmp/my.serial.filter");
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top