Add Network Printer through libcups API

Azuri azuri.shah at fmr.com
Wed Aug 31 10:41:33 PDT 2011


I need to develop a different GUI just for the consitency between system,s. So I am developing an app which calls cups at back end

> There really is no way to do this in a generic way. You could potentially use the SNMP backend to probe the IP address for a preferred device-uri, make-and-model, and 1284 device ID, and then use the make-and-model and device ID information you get back as input to a CUPS_GET_PPDS request (see the lpinfo sources) which will provide suggested drivers.
>
> However, I question why you are doing this in the first place - Apple already supplies UI that does this (including the IP address) when you add a printer from the Print & Scan pref pane.  Is there some reason you need to duplicate the system-supplied UI?
>
> On Aug 31, 2011, at 9:58 AM, Azuri wrote:
>
> > Ok so can you please tell me how to do that. Only info I would have is user input IP address. So how do i create and associate PPD after that. Can you provide me with code snippet how to do it? I read ppd coumentation but not having any success. Thanks.
> >
> >> Correct, if you do not associate a PPD with the queue, it will not be visible to Mac applications.
> >>
> >> On Aug 31, 2011, at 9:38 AM, Azuri wrote:
> >>> So I dont need to use that? Also why is printer not showing up in File->print menu? is ti because I dont have ppd file?
> >>>
> >>>> As documented, cupsAddDest DOES NOT ADD A QUEUE.
> >>>>
> >>>> On Aug 31, 2011, at 8:17 AM, Azuri wrote:
> >>>>
> >>>>> I think I should be using cupsAddDest and cupsSetDest to make it visible in mac print UI list, so I added the below code. but it still doesn't show up
> >>>>> cups_dest_t *mydest;
> >>>>>  cups_dest_t *newdest;
> >>>>>  int num_new_dest;
> >>>>>  num_new_dest = cupsAddDest(printer, NULL, num_new_dest, &newdest);
> >>>>>  mydest = cupsGetDest(printer, NULL, num_new_dest, newdest);
> >>>>>  cupsSetDests2(http,num_new_dest, mydest);
> >>>>>  cupsFreeDests(num_new_dest, mydest);
> >>>>>
> >>>>>
> >>>>>> The code I am using is as below. It shows up as raw printer in cups but when I go to any file and click on print this printer doesn't show up.
> >>>>>>
> >>>>>> http_t *http ;
> >>>>>>  char *printer = "Test";
> >>>>>>  char *device = "socket://10.105.152.49:9100";
> >>>>>>  char *model = "deskjet.ppd";
> >>>>>>  ipp_t		*request,		/* IPP Request */
> >>>>>>  *response;		/* IPP Response */
> >>>>>>  ipp_t		*request_dev,		/* IPP Request */
> >>>>>>  *response_dev;		/* IPP Response */
> >>>>>>  ipp_t		*request_ppd,		/* IPP Request */
> >>>>>>  *response_ppd;		/* IPP Response */
> >>>>>>  char		uri[HTTP_MAX_URI];	/* URI for printer/class */
> >>>>>>  char        uri_dev[HTTP_MAX_URI];
> >>>>>>  char        uri_ppd[HTTP_MAX_URI];
> >>>>>>
> >>>>>>  /*
> >>>>>>   * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
> >>>>>>   * attributes:
> >>>>>>   *
> >>>>>>   *    attributes-charset
> >>>>>>   *    attributes-natural-language
> >>>>>>   *    printer-uri
> >>>>>>   */
> >>>>>>  http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
> >>>>>>
> >>>>>>  /* set printer device */
> >>>>>>  request_dev = ippNewRequest(CUPS_ADD_PRINTER);
> >>>>>>
> >>>>>>  httpAssembleURIf(HTTP_URI_CODING_ALL, uri_dev, sizeof(uri_dev), "ipp", NULL,
> >>>>>>                   "localhost", 0, "/printers/%s", printer);
> >>>>>>  ippAddString(request_dev, IPP_TAG_OPERATION, IPP_TAG_URI,
> >>>>>>               "printer-uri", NULL, uri_dev);
> >>>>>>
> >>>>>>  /*
> >>>>>>   * Add the device URI...
> >>>>>>   */
> >>>>>>
> >>>>>>  if (device[0] == '/')
> >>>>>>  {
> >>>>>>      /*
> >>>>>>       * Convert filename to URI...
> >>>>>>       */
> >>>>>>
> >>>>>>      snprintf(uri_dev, sizeof(uri_dev), "file://%s", device);
> >>>>>>      ippAddString(request_dev, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
> >>>>>>                   uri_dev);
> >>>>>>  }
> >>>>>>  else
> >>>>>>      ippAddString(request_dev, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri", NULL,
> >>>>>>                   device);
> >>>>>>
> >>>>>>  /*
> >>>>>>   * Do the request and get back a response...
> >>>>>>   */
> >>>>>>
> >>>>>>  if ((response_dev = cupsDoRequest(http, request_dev, "/admin/")) == NULL)
> >>>>>>  {
> >>>>>>      _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
> >>>>>>
> >>>>>> //        return (1);
> >>>>>>  }
> >>>>>>  else if (response_dev->request.status.status_code > IPP_OK_CONFLICT)
> >>>>>>  {
> >>>>>>      _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
> >>>>>>
> >>>>>>      ippDelete(response_dev);
> >>>>>>
> >>>>>> //      return (1);
> >>>>>>  }
> >>>>>>  else
> >>>>>>  {
> >>>>>>      ippDelete(response_dev);
> >>>>>>
> >>>>>>  //    return (0);
> >>>>>>  }
> >>>>>>
> >>>>>>
> >>>>>>  /* enable_printer */
> >>>>>>  request = ippNewRequest(CUPS_ADD_PRINTER);
> >>>>>>
> >>>>>>  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
> >>>>>>                   "localhost", 0, "/printers/%s", printer);
> >>>>>>  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
> >>>>>>               "printer-uri", NULL, uri);
> >>>>>>
> >>>>>>  ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
> >>>>>>                IPP_PRINTER_IDLE);
> >>>>>>
> >>>>>>  ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
> >>>>>>
> >>>>>>  /*
> >>>>>>   * Do the request and get back a response...
> >>>>>>   */
> >>>>>>
> >>>>>>  if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
> >>>>>>  {
> >>>>>>      _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
> >>>>>>
> >>>>>>      //return (1);
> >>>>>>  }
> >>>>>>  else if (response->request.status.status_code > IPP_OK_CONFLICT)
> >>>>>>  {
> >>>>>>      _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
> >>>>>>
> >>>>>>      ippDelete(response);
> >>>>>>
> >>>>>>      //return (1);
> >>>>>>  }
> >>>>>>  else
> >>>>>>  {
> >>>>>>      ippDelete(response);
> >>>>>>
> >>>>>>      //return (0);
> >>>>>>  }
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>>> Thanks Chad I was able to add a printer and enebale it and I can see it in cups webpage. But the problem is user doesn have PPD file or anything. And I am not doing anything for PPD file. After I add the printer I can see it on cups webpage but cant see int he print menu on any page,where it lists all the printers. So how do I make printer visible there?
> >>>>>>>
> >>>>>>> Thanks,
> >>>>>>> Azuri
> >>>>>>>
> >>>>>>>> The usage message for lpadmin indicates that -p is how you add a printer,
> >>>>>>>> which ultimately arrives at set_printer_options().  That's where you should
> >>>>>>>> be looking.
> >>>>>>>>
> >>>>>>>> -Chad
> >>>>>>>>
> >>>>>>>> On 8/30/11 4:59 PM, "Azuri" <azuri.shah at fmr.com> thusly spake:
> >>>>>>>>
> >>>>>>>>>
> >>>>>>>>> The code I am currently using from lpadmin.c file is below. I get error saying
> >>>>>>>>> can't find printer or class.
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> http_t *http ;
> >>>>>>>>>  char *printer = "socket://10.105.152.49:9100";
> >>>>>>>>>  char *pclass;
> >>>>>>>>>  int  i;   /* Looping var */
> >>>>>>>>>  ipp_t  *request,  /* IPP Request */
> >>>>>>>>>  *response;  /* IPP Response */
> >>>>>>>>>  ipp_attribute_t *attr,  /* Current attribute */
> >>>>>>>>>  *members;  /* Members in class */
> >>>>>>>>>  char  uri[HTTP_MAX_URI]; /* URI for printer/class */
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>  /*
> >>>>>>>>>   * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the
> >>>>>>>>> following
> >>>>>>>>>   * attributes:
> >>>>>>>>>   *
> >>>>>>>>>   *    attributes-charset
> >>>>>>>>>   *    attributes-natural-language
> >>>>>>>>>   *    printer-uri
> >>>>>>>>>   */
> >>>>>>>>>  http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
> >>>>>>>>>  request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
> >>>>>>>>>
> >>>>>>>>>  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
> >>>>>>>>>                   "localhost", 0, "/classes/%s", pclass);
> >>>>>>>>>  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
> >>>>>>>>>               "printer-uri", NULL, uri);
> >>>>>>>>>
> >>>>>>>>>  /*
> >>>>>>>>>   * Do the request and get back a response...
> >>>>>>>>>   */
> >>>>>>>>>
> >>>>>>>>>  response = cupsDoRequest(http, request, "/");
> >>>>>>>>>
> >>>>>>>>>  /*
> >>>>>>>>>   * Build a CUPS_ADD_CLASS request, which requires the following
> >>>>>>>>>   * attributes:
> >>>>>>>>>   *
> >>>>>>>>>   *    attributes-charset
> >>>>>>>>>   *    attributes-natural-language
> >>>>>>>>>   *    printer-uri
> >>>>>>>>>   *    member-uris
> >>>>>>>>>   */
> >>>>>>>>>
> >>>>>>>>>  request = ippNewRequest(CUPS_ADD_CLASS);
> >>>>>>>>>
> >>>>>>>>>  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
> >>>>>>>>>               "printer-uri", NULL, uri);
> >>>>>>>>>
> >>>>>>>>>  /*
> >>>>>>>>>   * See if the printer is already in the class...
> >>>>>>>>>   */
> >>>>>>>>>
> >>>>>>>>>  if (response != NULL &&
> >>>>>>>>>      (members = ippFindAttribute(response, "member-names", IPP_TAG_NAME))
> >>>>>>>>> != NULL)
> >>>>>>>>>      for (i = 0; i < members->num_values; i ++)
> >>>>>>>>>          if (strcasecmp(printer, members->values[i].string.text) == 0)
> >>>>>>>>>          {
> >>>>>>>>>
> >>>>>>>>>              ippDelete(request);
> >>>>>>>>>              ippDelete(response);
> >>>>>>>>>              //return (0);
> >>>>>>>>>          }
> >>>>>>>>>
> >>>>>>>>>  /*
> >>>>>>>>>   * OK, the printer isn't part of the class, so add it...
> >>>>>>>>>   */
> >>>>>>>>>
> >>>>>>>>>  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
> >>>>>>>>>                   "localhost", 0, "/printers/%s", printer);
> >>>>>>>>>
> >>>>>>>>>  if (response != NULL &&
> >>>>>>>>>      (members = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) !=
> >>>>>>>>> NULL)
> >>>>>>>>>  {
> >>>>>>>>>      /*
> >>>>>>>>>       * Add the printer to the existing list...
> >>>>>>>>>       */
> >>>>>>>>>
> >>>>>>>>>      attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
> >>>>>>>>>                           "member-uris", members->num_values + 1, NULL,
> >>>>>>>>> NULL);
> >>>>>>>>>      for (i = 0; i < members->num_values; i ++)
> >>>>>>>>>          attr->values[i].string.text =
> >>>>>>>>> _cupsStrAlloc(members->values[i].string.text);
> >>>>>>>>>
> >>>>>>>>>      attr->values[i].string.text = _cupsStrAlloc(uri);
> >>>>>>>>>  }
> >>>>>>>>>  else
> >>>>>>>>>      ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris",
> >>>>>>>>> NULL,
> >>>>>>>>>                   uri);
> >>>>>>>>>
> >>>>>>>>>  /*
> >>>>>>>>>   * Then send the request...
> >>>>>>>>>   */
> >>>>>>>>>
> >>>>>>>>>  ippDelete(response);
> >>>>>>>>>
> >>>>>>>>>  if ((response = cupsDoRequest(http, request, "/admin/")) == NULL)
> >>>>>>>>>  {
> >>>>>>>>>
> >>>>>>>>>  }
> >>>>>>>>>  else if (response->request.status.status_code > IPP_OK_CONFLICT)
> >>>>>>>>>  {
> >>>>>>>>>      _cupsLangPrintf(stderr, "lpadmin: %s\n", cupsLastErrorString());
> >>>>>>>>>
> >>>>>>>>>      ippDelete(response);
> >>>>>>>>>
> >>>>>>>>>  }
> >>>>>>>>>  else
> >>>>>>>>>  {
> >>>>>>>>>      ippDelete(response);
> >>>>>>>>>
> >>>>>>>>>  }
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>>> I did look at lpadmin.c file both its not working . But I am totally confusd.
> >>>>>>>>>> I did look more into add_printer_to_class method but its not working. All I
> >>>>>>>>>> want is when user enters socket://123.45.45.67 to UI, my code should go ahead
> >>>>>>>>>> and add the printer tot he mac. I have spent hello lot of time trying to
> >>>>>>>>>> figure this out using API's but no success at all so far. Your help will be
> >>>>>>>>>> appreciated.
> >>>>>>>>>>
> >>>>>>>>>> Russell,
> >>>>>>>>>>>
> >>>>>>>>>>> Just download the CUPS source and look at the lpadmin tool.
> >>>>>>>>>>>
> >>>>>>>>>>> -Chad
> >>>>>>>>>>>
> >>>>>>>>>>> On 8/30/11 4:30 PM, "Azuri" <azuri.shah at fmr.com> thusly spake:
> >>>>>>>>>>>
> >>>>>>>>>>>>> Russell Stewart wrote:
> >>>>>>>>>>>>>> Michael Sweet wrote:
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>>> You need to create an IPP request and send it using cupsDoFileRequest
> >>>>>>>>>>>>>>> (assuming you are using a PPD file or interface script for the queue)
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>> OK, I see. So I assume that ippNewRequest() is the method to call for
> >>>>>>>>>>>>>> creating the IPP request, right?
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> Yes.  See the "CUPS Implementation of IPP" document for documentation
> >>>>>>>>>>>>> on the attributes and operations:
> >>>>>>>>>>>>>
> >>>>>>>>>>>>>   http://www.cups.org/documentation.php/spec-ipp.html
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> --
> >>>>>>>>>>>>> ______________________________________________________________________
> >>>>>>>>>>>>> Michael Sweet, Easy Software Products           mike at easysw dot com
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>> Can you please provice code on how u did it? I am trying to do the same
> >>>>>>>>>>>> time
> >>>>>>>>>>>> but have no success so far. How can I use API's to add printer to my mac. I
> >>>>>>>>>>>> am
> >>>>>>>>>>>> developing a Coca app which provides GUI and takes user input to add
> >>>>>>>>>>>> printer
> >>>>>>>>>>>> using cups. Please let me know
> >>>>>>>>>>>> _______________________________________________
> >>>>>>>>>>>> cups-dev mailing list
> >>>>>>>>>>>> cups-dev at easysw.com
> >>>>>>>>>>>> http://lists.easysw.com/mailman/listinfo/cups-dev
> >>>>>>>>>>>
> >>>>>>>>>>> Chad Hulbert
> >>>>>>>>>>> Software Engineer
> >>>>>>>>>>> Xerox Corporation
> >>>>>>>>>>> 800 Phillips Rd
> >>>>>>>>>>> Webster, NY 14580
> >>>>>>>>>>>
> >>>>>>>>>>> p 585.427.3295  (8*707.3295)
> >>>>>>>>>>>
> >>>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> _______________________________________________
> >>>>>>>>> cups-dev mailing list
> >>>>>>>>> cups-dev at easysw.com
> >>>>>>>>> http://lists.easysw.com/mailman/listinfo/cups-dev
> >>>>>>>>
> >>>>>>>> Chad Hulbert
> >>>>>>>> Software Engineer
> >>>>>>>> Xerox Corporation
> >>>>>>>> 800 Phillips Rd
> >>>>>>>> Webster, NY 14580
> >>>>>>>>
> >>>>>>>> p 585.427.3295  (8*707.3295)
> >>>>>>>>
> >>>>>>>
> >>>>>>
> >>>>>
> >>>>> _______________________________________________
> >>>>> cups-dev mailing list
> >>>>> cups-dev at easysw.com
> >>>>> http://lists.easysw.com/mailman/listinfo/cups-dev
> >>>>
> >>>> __________________________________________________
> >>>> Michael Sweet, Senior Printing System Engineer, PWG Chair
> >>>>
> >>>
> >>> _______________________________________________
> >>> cups-dev mailing list
> >>> cups-dev at easysw.com
> >>> http://lists.easysw.com/mailman/listinfo/cups-dev
> >>
> >> ________________________________________________________________________
> >> Michael Sweet, Senior Printing System Engineer, PWG Chair
> >>
> >>
> >>
> >>
> >>
> >
> > _______________________________________________
> > cups-dev mailing list
> > cups-dev at easysw.com
> > http://lists.easysw.com/mailman/listinfo/cups-dev
>
> ________________________________________________________________________
> Michael Sweet, Senior Printing System Engineer, PWG Chair
>
>
>
>
>





More information about the cups-devel mailing list