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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 ** 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