12264Sjacobs /*
22264Sjacobs * CDDL HEADER START
32264Sjacobs *
42264Sjacobs * The contents of this file are subject to the terms of the
52264Sjacobs * Common Development and Distribution License (the "License").
62264Sjacobs * You may not use this file except in compliance with the License.
72264Sjacobs *
82264Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
92264Sjacobs * or http://www.opensolaris.org/os/licensing.
102264Sjacobs * See the License for the specific language governing permissions
112264Sjacobs * and limitations under the License.
122264Sjacobs *
132264Sjacobs * When distributing Covered Code, include this CDDL HEADER in each
142264Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
152264Sjacobs * If applicable, add the following below this CDDL HEADER, with the
162264Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying
172264Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner]
182264Sjacobs *
192264Sjacobs * CDDL HEADER END
202264Sjacobs */
212264Sjacobs
222264Sjacobs /*
23*3917Sjacobs * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
242264Sjacobs * Use is subject to license terms.
252264Sjacobs *
262264Sjacobs */
272264Sjacobs
282264Sjacobs /* $Id: printer.c 146 2006-03-24 00:26:54Z njacobs $ */
292264Sjacobs
302264Sjacobs #pragma ident "%Z%%M% %I% %E% SMI"
312264Sjacobs
322264Sjacobs /*LINTLIBRARY*/
332264Sjacobs
342264Sjacobs #include <stdlib.h>
352264Sjacobs #include <papi_impl.h>
362264Sjacobs
372264Sjacobs #include <config-site.h>
382264Sjacobs
392264Sjacobs void
papiPrinterFree(papi_printer_t printer)402264Sjacobs papiPrinterFree(papi_printer_t printer)
412264Sjacobs {
422264Sjacobs printer_t *tmp = printer;
432264Sjacobs
442264Sjacobs if (tmp != NULL) {
452264Sjacobs if (tmp->attributes != NULL)
462264Sjacobs papiAttributeListFree(tmp->attributes);
472264Sjacobs free(tmp);
482264Sjacobs }
492264Sjacobs }
502264Sjacobs
512264Sjacobs void
papiPrinterListFree(papi_printer_t * printers)522264Sjacobs papiPrinterListFree(papi_printer_t *printers)
532264Sjacobs {
542264Sjacobs if (printers != NULL) {
552264Sjacobs int i;
562264Sjacobs
572264Sjacobs for (i = 0; printers[i] != NULL; i++)
582264Sjacobs papiPrinterFree(printers[i]);
592264Sjacobs free(printers);
602264Sjacobs }
612264Sjacobs }
622264Sjacobs
632264Sjacobs /*
642264Sjacobs * Enumeration of printers is not part of the IPP specification, so many
652264Sjacobs * servers will probably not respond back with a list of printers, but
662264Sjacobs * CUPS has implemented an extension to IPP to enumerate printers and
672264Sjacobs * classes. the Apache/mod_ipp IPP listener module available in Solaris
682264Sjacobs * implements this IPP extension, so CUPS and Solaris can provide this
692264Sjacobs * to IPP clients.
702264Sjacobs */
712264Sjacobs #ifndef OPID_CUPS_GET_PRINTERS /* for servers that will enumerate */
722264Sjacobs #define OPID_CUPS_GET_PRINTERS 0x4002
732264Sjacobs #endif /* OPID_CUPS_GET_PRINTERS */
742264Sjacobs #ifndef OPID_CUPS_DELETE_PRINTER /* for servers that can delete */
752264Sjacobs #define OPID_CUPS_DELETE_PRINTER 0x4004
762264Sjacobs #endif /* OPID_CUPS_DELETE_PRINTER */
772264Sjacobs #ifndef OPID_CUPS_GET_CLASSES /* for servers that will enumerate */
782264Sjacobs #define OPID_CUPS_GET_CLASSES 0x4005
792264Sjacobs #endif /* OPID_CUPS_GET_CLASSES */
802264Sjacobs
812264Sjacobs papi_status_t
papiPrintersList(papi_service_t handle,char ** requested_attrs,papi_filter_t * filter,papi_printer_t ** printers)822264Sjacobs papiPrintersList(papi_service_t handle, char **requested_attrs,
832264Sjacobs papi_filter_t *filter, papi_printer_t **printers)
842264Sjacobs {
852264Sjacobs papi_status_t status, result = PAPI_INTERNAL_ERROR;
862264Sjacobs service_t *svc = handle;
872264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
882264Sjacobs void *iter = NULL;
892264Sjacobs
902264Sjacobs if ((svc == NULL) || (printers == NULL))
912264Sjacobs return (PAPI_BAD_ARGUMENT);
922264Sjacobs
932264Sjacobs /* if we are already connected, use that connection. */
942264Sjacobs if (svc->connection == NULL)
952264Sjacobs if ((result = service_connect(svc, DEFAULT_DEST)) != PAPI_OK)
962264Sjacobs return (result);
972264Sjacobs ipp_initialize_request(svc, &request, OPID_CUPS_GET_PRINTERS);
982264Sjacobs
99*3917Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL, -1);
1002264Sjacobs
1012264Sjacobs if (requested_attrs != NULL) {
1022264Sjacobs int i;
1032264Sjacobs
1042264Sjacobs for (i = 0; requested_attrs[i] != NULL; i++)
1052264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND,
1062264Sjacobs "requested-attributes", requested_attrs[i]);
1072264Sjacobs }
1082264Sjacobs
1092264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
1102264Sjacobs "operational-attributes-group", op);
1112264Sjacobs papiAttributeListFree(op);
1122264Sjacobs result = ipp_send_request(svc, request, &response);
1132264Sjacobs papiAttributeListFree(request);
1142264Sjacobs
1152264Sjacobs op = NULL;
1162264Sjacobs for (status = papiAttributeListGetCollection(response, &iter,
1172264Sjacobs "printer-attributes-group", &op);
1182264Sjacobs status == PAPI_OK;
1192264Sjacobs status = papiAttributeListGetCollection(response, &iter,
1202264Sjacobs NULL, &op)) {
1212264Sjacobs printer_t *p = NULL;
1222264Sjacobs
1232264Sjacobs if ((p = calloc(1, sizeof (*p))) == NULL)
1242264Sjacobs return (PAPI_TEMPORARY_ERROR);
1252264Sjacobs
1262264Sjacobs copy_attributes(&p->attributes, op);
1272264Sjacobs op = NULL;
1282264Sjacobs list_append(printers, p);
1292264Sjacobs }
1302264Sjacobs papiAttributeListFree(response);
1312264Sjacobs
1322264Sjacobs return (result);
1332264Sjacobs }
1342264Sjacobs
1352264Sjacobs papi_status_t
papiPrinterQuery(papi_service_t handle,char * name,char ** requested_attrs,papi_attribute_t ** job_attributes,papi_printer_t * printer)1362264Sjacobs papiPrinterQuery(papi_service_t handle, char *name,
1372264Sjacobs char **requested_attrs,
1382264Sjacobs papi_attribute_t **job_attributes,
1392264Sjacobs papi_printer_t *printer)
1402264Sjacobs {
1412264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR;
1422264Sjacobs service_t *svc = handle;
1432264Sjacobs printer_t *p = NULL;
1442264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
1452264Sjacobs
1462264Sjacobs if ((svc == NULL) || (name == NULL) || (printer == NULL))
1472264Sjacobs return (PAPI_BAD_ARGUMENT);
1482264Sjacobs
1492264Sjacobs /* if we are already connected, use that connection. */
1502264Sjacobs if (svc->connection == NULL)
1512264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK)
1522264Sjacobs return (result);
1532264Sjacobs
1542264Sjacobs if ((*printer = p = calloc(1, sizeof (*p))) == NULL)
1552264Sjacobs return (PAPI_TEMPORARY_ERROR);
1562264Sjacobs
1572264Sjacobs ipp_initialize_request(svc, &request, OPID_GET_PRINTER_ATTRIBUTES);
1582264Sjacobs
159*3917Sjacobs ipp_initialize_operational_attributes(svc, &op, name, -1);
1602264Sjacobs
1612264Sjacobs if (requested_attrs != NULL) {
1622264Sjacobs int i;
1632264Sjacobs
1642264Sjacobs for (i = 0; requested_attrs[i] != NULL; i++)
1652264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND,
1662264Sjacobs "requested-attributes", requested_attrs[i]);
1672264Sjacobs }
1682264Sjacobs
1692264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
1702264Sjacobs "operational-attributes-group", op);
1712264Sjacobs papiAttributeListFree(op);
1722264Sjacobs result = ipp_send_request(svc, request, &response);
1732264Sjacobs papiAttributeListFree(request);
1742264Sjacobs
1752264Sjacobs op = NULL;
1762264Sjacobs papiAttributeListGetCollection(response, NULL,
1772264Sjacobs "printer-attributes-group", &op);
1782264Sjacobs copy_attributes(&p->attributes, op);
1792264Sjacobs papiAttributeListFree(response);
1802264Sjacobs
1812264Sjacobs return (result);
1822264Sjacobs }
1832264Sjacobs
1842264Sjacobs static papi_status_t
_printer_enable_disable_pause_resume_delete(papi_service_t handle,char * name,char * message,uint16_t type)1852264Sjacobs _printer_enable_disable_pause_resume_delete(papi_service_t handle, char *name,
1862264Sjacobs char *message, uint16_t type)
1872264Sjacobs {
1882264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR;
1892264Sjacobs service_t *svc = handle;
1902264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
1912264Sjacobs
1922264Sjacobs if ((svc == NULL) || (name == NULL))
1932264Sjacobs return (PAPI_BAD_ARGUMENT);
1942264Sjacobs
1952264Sjacobs /* if we are already connected, use that connection. */
1962264Sjacobs if (svc->connection == NULL)
1972264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK)
1982264Sjacobs return (result);
1992264Sjacobs
2002264Sjacobs ipp_initialize_request(svc, &request, type);
2012264Sjacobs
202*3917Sjacobs ipp_initialize_operational_attributes(svc, &op, name, -1);
2032264Sjacobs
2042264Sjacobs switch (type) {
2052264Sjacobs case OPID_DISABLE_PRINTER:
2062264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_REPLACE,
2072264Sjacobs "printer-message-from-operator", message);
2082264Sjacobs break;
2092264Sjacobs case OPID_PAUSE_PRINTER:
2102264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_REPLACE,
2112264Sjacobs "printer-state-message", message);
2122264Sjacobs break;
2132264Sjacobs default: /* a message value is of no use */
2142264Sjacobs break;
2152264Sjacobs }
2162264Sjacobs
2172264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
2182264Sjacobs "operational-attributes-group", op);
2192264Sjacobs papiAttributeListFree(op);
2202264Sjacobs result = ipp_send_request(svc, request, &response);
2212264Sjacobs papiAttributeListFree(request);
2222264Sjacobs papiAttributeListFree(response);
2232264Sjacobs
2242264Sjacobs return (result);
2252264Sjacobs }
2262264Sjacobs
2272264Sjacobs papi_status_t
papiPrinterEnable(papi_service_t handle,char * name)2282264Sjacobs papiPrinterEnable(papi_service_t handle, char *name)
2292264Sjacobs {
2302264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name,
2312264Sjacobs NULL, OPID_ENABLE_PRINTER));
2322264Sjacobs }
2332264Sjacobs
2342264Sjacobs papi_status_t
papiPrinterResume(papi_service_t handle,char * name)2352264Sjacobs papiPrinterResume(papi_service_t handle, char *name)
2362264Sjacobs {
2372264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name,
2382264Sjacobs NULL, OPID_RESUME_PRINTER));
2392264Sjacobs }
2402264Sjacobs
2412264Sjacobs papi_status_t
papiPrinterPause(papi_service_t handle,char * name,char * message)2422264Sjacobs papiPrinterPause(papi_service_t handle, char *name, char *message)
2432264Sjacobs {
2442264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name,
2452264Sjacobs message, OPID_PAUSE_PRINTER));
2462264Sjacobs }
2472264Sjacobs
2482264Sjacobs papi_status_t
papiPrinterDisable(papi_service_t handle,char * name,char * message)2492264Sjacobs papiPrinterDisable(papi_service_t handle, char *name, char *message)
2502264Sjacobs {
2512264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name,
2522264Sjacobs message, OPID_PAUSE_PRINTER));
2532264Sjacobs }
2542264Sjacobs
2552264Sjacobs /*
2562264Sjacobs * there is no IPP create operation, the set-printer-attibutes operation
2572264Sjacobs * is the closest we have, so we will assume that the server will create
2582264Sjacobs * a printer and set attributes if there is none.
2592264Sjacobs */
2602264Sjacobs papi_status_t
papiPrinterAdd(papi_service_t handle,char * name,papi_attribute_t ** attributes,papi_printer_t * printer)2612264Sjacobs papiPrinterAdd(papi_service_t handle, char *name,
2622264Sjacobs papi_attribute_t **attributes, papi_printer_t *printer)
2632264Sjacobs {
2642264Sjacobs return (papiPrinterModify(handle, name, attributes, printer));
2652264Sjacobs }
2662264Sjacobs
2672264Sjacobs papi_status_t
papiPrinterModify(papi_service_t handle,char * name,papi_attribute_t ** attributes,papi_printer_t * printer)2682264Sjacobs papiPrinterModify(papi_service_t handle, char *name,
2692264Sjacobs papi_attribute_t **attributes, papi_printer_t *printer)
2702264Sjacobs {
2712264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR;
2722264Sjacobs service_t *svc = handle;
2732264Sjacobs printer_t *p = NULL;
2742264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
2752264Sjacobs
2762264Sjacobs if ((svc == NULL) || (name == NULL) || (printer == NULL))
2772264Sjacobs return (PAPI_BAD_ARGUMENT);
2782264Sjacobs
2792264Sjacobs /* if we are already connected, use that connection. */
2802264Sjacobs if (svc->connection == NULL)
2812264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK)
2822264Sjacobs return (result);
2832264Sjacobs
2842264Sjacobs if ((*printer = p = calloc(1, sizeof (*p))) == NULL)
2852264Sjacobs return (PAPI_TEMPORARY_ERROR);
2862264Sjacobs
2872264Sjacobs ipp_initialize_request(svc, &request, OPID_SET_PRINTER_ATTRIBUTES);
2882264Sjacobs
289*3917Sjacobs ipp_initialize_operational_attributes(svc, &op, name, -1);
2902264Sjacobs
2912264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
2922264Sjacobs "operational-attributes-group", op);
2932264Sjacobs papiAttributeListFree(op);
2942264Sjacobs
2952264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
2962264Sjacobs "printer-attributes-group", attributes);
2972264Sjacobs result = ipp_send_request(svc, request, &response);
2982264Sjacobs papiAttributeListFree(request);
2992264Sjacobs
3002264Sjacobs op = NULL;
3012264Sjacobs papiAttributeListGetCollection(response, NULL,
3022264Sjacobs "printer-attributes-group", &op);
3032264Sjacobs copy_attributes(&p->attributes, op);
3042264Sjacobs papiAttributeListFree(response);
3052264Sjacobs
3062264Sjacobs return (result);
3072264Sjacobs }
3082264Sjacobs
3092264Sjacobs papi_status_t
papiPrinterRemove(papi_service_t handle,char * name)3102264Sjacobs papiPrinterRemove(papi_service_t handle, char *name)
3112264Sjacobs {
3122264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name,
3132264Sjacobs NULL, OPID_CUPS_DELETE_PRINTER));
3142264Sjacobs }
3152264Sjacobs
3162264Sjacobs papi_status_t
papiPrinterPurgeJobs(papi_service_t handle,char * name,papi_job_t ** jobs)3172264Sjacobs papiPrinterPurgeJobs(papi_service_t handle, char *name,
3182264Sjacobs papi_job_t **jobs)
3192264Sjacobs {
3202264Sjacobs papi_status_t status, result = PAPI_INTERNAL_ERROR;
3212264Sjacobs service_t *svc = handle;
3222264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
3232264Sjacobs void *iter = NULL;
3242264Sjacobs
3252264Sjacobs
3262264Sjacobs if ((svc == NULL) || (name == NULL))
3272264Sjacobs return (PAPI_BAD_ARGUMENT);
3282264Sjacobs
3292264Sjacobs /* if we are already connected, use that connection. */
3302264Sjacobs if (svc->connection == NULL)
3312264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK)
3322264Sjacobs return (result);
3332264Sjacobs
3342264Sjacobs ipp_initialize_request(svc, &request, OPID_PURGE_JOBS);
3352264Sjacobs
336*3917Sjacobs ipp_initialize_operational_attributes(svc, &op, name, -1);
3372264Sjacobs
3382264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
3392264Sjacobs "operational-attributes-group", op);
3402264Sjacobs papiAttributeListFree(op);
3412264Sjacobs result = ipp_send_request(svc, request, &response);
3422264Sjacobs papiAttributeListFree(request);
3432264Sjacobs
3442264Sjacobs op = NULL;
3452264Sjacobs for (status = papiAttributeListGetCollection(response, &iter,
3462264Sjacobs "job-attributes-group", &op);
3472264Sjacobs status == PAPI_OK;
3482264Sjacobs status = papiAttributeListGetCollection(response, &iter,
3492264Sjacobs NULL, &op)) {
3502264Sjacobs job_t *j = NULL;
3512264Sjacobs
3522264Sjacobs if ((j = calloc(1, sizeof (*j))) == NULL)
3532264Sjacobs return (PAPI_TEMPORARY_ERROR);
3542264Sjacobs
3552264Sjacobs copy_attributes(&j->attributes, op);
3562264Sjacobs op = NULL;
3572264Sjacobs list_append(jobs, j);
3582264Sjacobs }
3592264Sjacobs papiAttributeListFree(response);
3602264Sjacobs
3612264Sjacobs return (result);
3622264Sjacobs }
3632264Sjacobs
3642264Sjacobs papi_status_t
papiPrinterListJobs(papi_service_t handle,char * name,char ** requested_attrs,int type_mask,int max_num_jobs,papi_job_t ** jobs)3652264Sjacobs papiPrinterListJobs(papi_service_t handle, char *name,
3662264Sjacobs char **requested_attrs, int type_mask,
3672264Sjacobs int max_num_jobs, papi_job_t **jobs)
3682264Sjacobs {
3692264Sjacobs papi_status_t status, result = PAPI_INTERNAL_ERROR;
3702264Sjacobs service_t *svc = handle;
3712264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL;
3722264Sjacobs void *iter = NULL;
3732264Sjacobs
3742264Sjacobs if ((svc == NULL) || (name == NULL))
3752264Sjacobs return (PAPI_BAD_ARGUMENT);
3762264Sjacobs
3772264Sjacobs /* if we are already connected, use that connection. */
3782264Sjacobs if (svc->connection == NULL)
3792264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK)
3802264Sjacobs return (result);
3812264Sjacobs
3822264Sjacobs ipp_initialize_request(svc, &request, OPID_GET_JOBS);
3832264Sjacobs
384*3917Sjacobs ipp_initialize_operational_attributes(svc, &op, name, -1);
3852264Sjacobs
3862264Sjacobs if (requested_attrs != NULL) {
3872264Sjacobs int i;
3882264Sjacobs
3892264Sjacobs for (i = 0; requested_attrs[i] != NULL; i++)
3902264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND,
3912264Sjacobs "requested-attributes", requested_attrs[i]);
3922264Sjacobs }
3932264Sjacobs
3942264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE,
3952264Sjacobs "operational-attributes-group", op);
3962264Sjacobs papiAttributeListFree(op);
3972264Sjacobs result = ipp_send_request(svc, request, &response);
3982264Sjacobs papiAttributeListFree(request);
3992264Sjacobs
4002264Sjacobs op = NULL;
4012264Sjacobs for (status = papiAttributeListGetCollection(response, &iter,
4022264Sjacobs "job-attributes-group", &op);
4032264Sjacobs status == PAPI_OK;
4042264Sjacobs status = papiAttributeListGetCollection(response, &iter,
4052264Sjacobs NULL, &op)) {
4062264Sjacobs job_t *j = NULL;
4072264Sjacobs
4082264Sjacobs if ((j = calloc(1, sizeof (*j))) == NULL)
4092264Sjacobs return (PAPI_TEMPORARY_ERROR);
4102264Sjacobs
4112264Sjacobs copy_attributes(&j->attributes, op);
4122264Sjacobs op = NULL;
4132264Sjacobs list_append(jobs, j);
4142264Sjacobs }
4152264Sjacobs papiAttributeListFree(response);
4162264Sjacobs
4172264Sjacobs return (result);
4182264Sjacobs }
4192264Sjacobs
4202264Sjacobs papi_attribute_t **
papiPrinterGetAttributeList(papi_printer_t printer)4212264Sjacobs papiPrinterGetAttributeList(papi_printer_t printer)
4222264Sjacobs {
4232264Sjacobs papi_attribute_t **result = NULL;
4242264Sjacobs printer_t *p = printer;
4252264Sjacobs
4262264Sjacobs if (p != NULL)
4272264Sjacobs result = p->attributes;
4282264Sjacobs
4292264Sjacobs return (result);
4302264Sjacobs }
431