1*2264Sjacobs /* 2*2264Sjacobs * CDDL HEADER START 3*2264Sjacobs * 4*2264Sjacobs * The contents of this file are subject to the terms of the 5*2264Sjacobs * Common Development and Distribution License (the "License"). 6*2264Sjacobs * You may not use this file except in compliance with the License. 7*2264Sjacobs * 8*2264Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*2264Sjacobs * or http://www.opensolaris.org/os/licensing. 10*2264Sjacobs * See the License for the specific language governing permissions 11*2264Sjacobs * and limitations under the License. 12*2264Sjacobs * 13*2264Sjacobs * When distributing Covered Code, include this CDDL HEADER in each 14*2264Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*2264Sjacobs * If applicable, add the following below this CDDL HEADER, with the 16*2264Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying 17*2264Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner] 18*2264Sjacobs * 19*2264Sjacobs * CDDL HEADER END 20*2264Sjacobs */ 21*2264Sjacobs 22*2264Sjacobs /* 23*2264Sjacobs * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*2264Sjacobs * Use is subject to license terms. 25*2264Sjacobs * 26*2264Sjacobs */ 27*2264Sjacobs 28*2264Sjacobs /* $Id: printer.c 146 2006-03-24 00:26:54Z njacobs $ */ 29*2264Sjacobs 30*2264Sjacobs #pragma ident "%Z%%M% %I% %E% SMI" 31*2264Sjacobs 32*2264Sjacobs /*LINTLIBRARY*/ 33*2264Sjacobs 34*2264Sjacobs #include <stdlib.h> 35*2264Sjacobs #include <papi_impl.h> 36*2264Sjacobs 37*2264Sjacobs #include <config-site.h> 38*2264Sjacobs 39*2264Sjacobs void 40*2264Sjacobs papiPrinterFree(papi_printer_t printer) 41*2264Sjacobs { 42*2264Sjacobs printer_t *tmp = printer; 43*2264Sjacobs 44*2264Sjacobs if (tmp != NULL) { 45*2264Sjacobs if (tmp->attributes != NULL) 46*2264Sjacobs papiAttributeListFree(tmp->attributes); 47*2264Sjacobs free(tmp); 48*2264Sjacobs } 49*2264Sjacobs } 50*2264Sjacobs 51*2264Sjacobs void 52*2264Sjacobs papiPrinterListFree(papi_printer_t *printers) 53*2264Sjacobs { 54*2264Sjacobs if (printers != NULL) { 55*2264Sjacobs int i; 56*2264Sjacobs 57*2264Sjacobs for (i = 0; printers[i] != NULL; i++) 58*2264Sjacobs papiPrinterFree(printers[i]); 59*2264Sjacobs free(printers); 60*2264Sjacobs } 61*2264Sjacobs } 62*2264Sjacobs 63*2264Sjacobs /* 64*2264Sjacobs * Enumeration of printers is not part of the IPP specification, so many 65*2264Sjacobs * servers will probably not respond back with a list of printers, but 66*2264Sjacobs * CUPS has implemented an extension to IPP to enumerate printers and 67*2264Sjacobs * classes. the Apache/mod_ipp IPP listener module available in Solaris 68*2264Sjacobs * implements this IPP extension, so CUPS and Solaris can provide this 69*2264Sjacobs * to IPP clients. 70*2264Sjacobs */ 71*2264Sjacobs #ifndef OPID_CUPS_GET_PRINTERS /* for servers that will enumerate */ 72*2264Sjacobs #define OPID_CUPS_GET_PRINTERS 0x4002 73*2264Sjacobs #endif /* OPID_CUPS_GET_PRINTERS */ 74*2264Sjacobs #ifndef OPID_CUPS_DELETE_PRINTER /* for servers that can delete */ 75*2264Sjacobs #define OPID_CUPS_DELETE_PRINTER 0x4004 76*2264Sjacobs #endif /* OPID_CUPS_DELETE_PRINTER */ 77*2264Sjacobs #ifndef OPID_CUPS_GET_CLASSES /* for servers that will enumerate */ 78*2264Sjacobs #define OPID_CUPS_GET_CLASSES 0x4005 79*2264Sjacobs #endif /* OPID_CUPS_GET_CLASSES */ 80*2264Sjacobs 81*2264Sjacobs papi_status_t 82*2264Sjacobs papiPrintersList(papi_service_t handle, char **requested_attrs, 83*2264Sjacobs papi_filter_t *filter, papi_printer_t **printers) 84*2264Sjacobs { 85*2264Sjacobs papi_status_t status, result = PAPI_INTERNAL_ERROR; 86*2264Sjacobs service_t *svc = handle; 87*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 88*2264Sjacobs void *iter = NULL; 89*2264Sjacobs 90*2264Sjacobs if ((svc == NULL) || (printers == NULL)) 91*2264Sjacobs return (PAPI_BAD_ARGUMENT); 92*2264Sjacobs 93*2264Sjacobs /* if we are already connected, use that connection. */ 94*2264Sjacobs if (svc->connection == NULL) 95*2264Sjacobs if ((result = service_connect(svc, DEFAULT_DEST)) != PAPI_OK) 96*2264Sjacobs return (result); 97*2264Sjacobs ipp_initialize_request(svc, &request, OPID_CUPS_GET_PRINTERS); 98*2264Sjacobs 99*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 100*2264Sjacobs 101*2264Sjacobs if (requested_attrs != NULL) { 102*2264Sjacobs int i; 103*2264Sjacobs 104*2264Sjacobs for (i = 0; requested_attrs[i] != NULL; i++) 105*2264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND, 106*2264Sjacobs "requested-attributes", requested_attrs[i]); 107*2264Sjacobs } 108*2264Sjacobs 109*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 110*2264Sjacobs "operational-attributes-group", op); 111*2264Sjacobs papiAttributeListFree(op); 112*2264Sjacobs result = ipp_send_request(svc, request, &response); 113*2264Sjacobs papiAttributeListFree(request); 114*2264Sjacobs 115*2264Sjacobs op = NULL; 116*2264Sjacobs for (status = papiAttributeListGetCollection(response, &iter, 117*2264Sjacobs "printer-attributes-group", &op); 118*2264Sjacobs status == PAPI_OK; 119*2264Sjacobs status = papiAttributeListGetCollection(response, &iter, 120*2264Sjacobs NULL, &op)) { 121*2264Sjacobs printer_t *p = NULL; 122*2264Sjacobs 123*2264Sjacobs if ((p = calloc(1, sizeof (*p))) == NULL) 124*2264Sjacobs return (PAPI_TEMPORARY_ERROR); 125*2264Sjacobs 126*2264Sjacobs copy_attributes(&p->attributes, op); 127*2264Sjacobs op = NULL; 128*2264Sjacobs list_append(printers, p); 129*2264Sjacobs } 130*2264Sjacobs papiAttributeListFree(response); 131*2264Sjacobs 132*2264Sjacobs return (result); 133*2264Sjacobs } 134*2264Sjacobs 135*2264Sjacobs papi_status_t 136*2264Sjacobs papiPrinterQuery(papi_service_t handle, char *name, 137*2264Sjacobs char **requested_attrs, 138*2264Sjacobs papi_attribute_t **job_attributes, 139*2264Sjacobs papi_printer_t *printer) 140*2264Sjacobs { 141*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 142*2264Sjacobs service_t *svc = handle; 143*2264Sjacobs printer_t *p = NULL; 144*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 145*2264Sjacobs 146*2264Sjacobs if ((svc == NULL) || (name == NULL) || (printer == NULL)) 147*2264Sjacobs return (PAPI_BAD_ARGUMENT); 148*2264Sjacobs 149*2264Sjacobs /* if we are already connected, use that connection. */ 150*2264Sjacobs if (svc->connection == NULL) 151*2264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK) 152*2264Sjacobs return (result); 153*2264Sjacobs 154*2264Sjacobs if ((*printer = p = calloc(1, sizeof (*p))) == NULL) 155*2264Sjacobs return (PAPI_TEMPORARY_ERROR); 156*2264Sjacobs 157*2264Sjacobs ipp_initialize_request(svc, &request, OPID_GET_PRINTER_ATTRIBUTES); 158*2264Sjacobs 159*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 160*2264Sjacobs ipp_add_printer_uri(svc, name, &op); 161*2264Sjacobs 162*2264Sjacobs if (requested_attrs != NULL) { 163*2264Sjacobs int i; 164*2264Sjacobs 165*2264Sjacobs for (i = 0; requested_attrs[i] != NULL; i++) 166*2264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND, 167*2264Sjacobs "requested-attributes", requested_attrs[i]); 168*2264Sjacobs } 169*2264Sjacobs 170*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 171*2264Sjacobs "operational-attributes-group", op); 172*2264Sjacobs papiAttributeListFree(op); 173*2264Sjacobs result = ipp_send_request(svc, request, &response); 174*2264Sjacobs papiAttributeListFree(request); 175*2264Sjacobs 176*2264Sjacobs op = NULL; 177*2264Sjacobs papiAttributeListGetCollection(response, NULL, 178*2264Sjacobs "printer-attributes-group", &op); 179*2264Sjacobs copy_attributes(&p->attributes, op); 180*2264Sjacobs papiAttributeListFree(response); 181*2264Sjacobs 182*2264Sjacobs return (result); 183*2264Sjacobs } 184*2264Sjacobs 185*2264Sjacobs static papi_status_t 186*2264Sjacobs _printer_enable_disable_pause_resume_delete(papi_service_t handle, char *name, 187*2264Sjacobs char *message, uint16_t type) 188*2264Sjacobs { 189*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 190*2264Sjacobs service_t *svc = handle; 191*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 192*2264Sjacobs 193*2264Sjacobs if ((svc == NULL) || (name == NULL)) 194*2264Sjacobs return (PAPI_BAD_ARGUMENT); 195*2264Sjacobs 196*2264Sjacobs /* if we are already connected, use that connection. */ 197*2264Sjacobs if (svc->connection == NULL) 198*2264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK) 199*2264Sjacobs return (result); 200*2264Sjacobs 201*2264Sjacobs ipp_initialize_request(svc, &request, type); 202*2264Sjacobs 203*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 204*2264Sjacobs ipp_add_printer_uri(svc, name, &op); 205*2264Sjacobs 206*2264Sjacobs switch (type) { 207*2264Sjacobs case OPID_DISABLE_PRINTER: 208*2264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_REPLACE, 209*2264Sjacobs "printer-message-from-operator", message); 210*2264Sjacobs break; 211*2264Sjacobs case OPID_PAUSE_PRINTER: 212*2264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_REPLACE, 213*2264Sjacobs "printer-state-message", message); 214*2264Sjacobs break; 215*2264Sjacobs default: /* a message value is of no use */ 216*2264Sjacobs break; 217*2264Sjacobs } 218*2264Sjacobs 219*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 220*2264Sjacobs "operational-attributes-group", op); 221*2264Sjacobs papiAttributeListFree(op); 222*2264Sjacobs result = ipp_send_request(svc, request, &response); 223*2264Sjacobs papiAttributeListFree(request); 224*2264Sjacobs papiAttributeListFree(response); 225*2264Sjacobs 226*2264Sjacobs return (result); 227*2264Sjacobs } 228*2264Sjacobs 229*2264Sjacobs papi_status_t 230*2264Sjacobs papiPrinterEnable(papi_service_t handle, char *name) 231*2264Sjacobs { 232*2264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name, 233*2264Sjacobs NULL, OPID_ENABLE_PRINTER)); 234*2264Sjacobs } 235*2264Sjacobs 236*2264Sjacobs papi_status_t 237*2264Sjacobs papiPrinterResume(papi_service_t handle, char *name) 238*2264Sjacobs { 239*2264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name, 240*2264Sjacobs NULL, OPID_RESUME_PRINTER)); 241*2264Sjacobs } 242*2264Sjacobs 243*2264Sjacobs papi_status_t 244*2264Sjacobs papiPrinterPause(papi_service_t handle, char *name, char *message) 245*2264Sjacobs { 246*2264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name, 247*2264Sjacobs message, OPID_PAUSE_PRINTER)); 248*2264Sjacobs } 249*2264Sjacobs 250*2264Sjacobs papi_status_t 251*2264Sjacobs papiPrinterDisable(papi_service_t handle, char *name, char *message) 252*2264Sjacobs { 253*2264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name, 254*2264Sjacobs message, OPID_PAUSE_PRINTER)); 255*2264Sjacobs } 256*2264Sjacobs 257*2264Sjacobs /* 258*2264Sjacobs * there is no IPP create operation, the set-printer-attibutes operation 259*2264Sjacobs * is the closest we have, so we will assume that the server will create 260*2264Sjacobs * a printer and set attributes if there is none. 261*2264Sjacobs */ 262*2264Sjacobs papi_status_t 263*2264Sjacobs papiPrinterAdd(papi_service_t handle, char *name, 264*2264Sjacobs papi_attribute_t **attributes, papi_printer_t *printer) 265*2264Sjacobs { 266*2264Sjacobs return (papiPrinterModify(handle, name, attributes, printer)); 267*2264Sjacobs } 268*2264Sjacobs 269*2264Sjacobs papi_status_t 270*2264Sjacobs papiPrinterModify(papi_service_t handle, char *name, 271*2264Sjacobs papi_attribute_t **attributes, papi_printer_t *printer) 272*2264Sjacobs { 273*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 274*2264Sjacobs service_t *svc = handle; 275*2264Sjacobs printer_t *p = NULL; 276*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 277*2264Sjacobs 278*2264Sjacobs if ((svc == NULL) || (name == NULL) || (printer == NULL)) 279*2264Sjacobs return (PAPI_BAD_ARGUMENT); 280*2264Sjacobs 281*2264Sjacobs /* if we are already connected, use that connection. */ 282*2264Sjacobs if (svc->connection == NULL) 283*2264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK) 284*2264Sjacobs return (result); 285*2264Sjacobs 286*2264Sjacobs if ((*printer = p = calloc(1, sizeof (*p))) == NULL) 287*2264Sjacobs return (PAPI_TEMPORARY_ERROR); 288*2264Sjacobs 289*2264Sjacobs ipp_initialize_request(svc, &request, OPID_SET_PRINTER_ATTRIBUTES); 290*2264Sjacobs 291*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 292*2264Sjacobs ipp_add_printer_uri(svc, name, &op); 293*2264Sjacobs 294*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 295*2264Sjacobs "operational-attributes-group", op); 296*2264Sjacobs papiAttributeListFree(op); 297*2264Sjacobs 298*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 299*2264Sjacobs "printer-attributes-group", attributes); 300*2264Sjacobs result = ipp_send_request(svc, request, &response); 301*2264Sjacobs papiAttributeListFree(request); 302*2264Sjacobs 303*2264Sjacobs op = NULL; 304*2264Sjacobs papiAttributeListGetCollection(response, NULL, 305*2264Sjacobs "printer-attributes-group", &op); 306*2264Sjacobs copy_attributes(&p->attributes, op); 307*2264Sjacobs papiAttributeListFree(response); 308*2264Sjacobs 309*2264Sjacobs return (result); 310*2264Sjacobs } 311*2264Sjacobs 312*2264Sjacobs papi_status_t 313*2264Sjacobs papiPrinterRemove(papi_service_t handle, char *name) 314*2264Sjacobs { 315*2264Sjacobs return (_printer_enable_disable_pause_resume_delete(handle, name, 316*2264Sjacobs NULL, OPID_CUPS_DELETE_PRINTER)); 317*2264Sjacobs } 318*2264Sjacobs 319*2264Sjacobs papi_status_t 320*2264Sjacobs papiPrinterPurgeJobs(papi_service_t handle, char *name, 321*2264Sjacobs papi_job_t **jobs) 322*2264Sjacobs { 323*2264Sjacobs papi_status_t status, result = PAPI_INTERNAL_ERROR; 324*2264Sjacobs service_t *svc = handle; 325*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 326*2264Sjacobs void *iter = NULL; 327*2264Sjacobs 328*2264Sjacobs 329*2264Sjacobs if ((svc == NULL) || (name == NULL)) 330*2264Sjacobs return (PAPI_BAD_ARGUMENT); 331*2264Sjacobs 332*2264Sjacobs /* if we are already connected, use that connection. */ 333*2264Sjacobs if (svc->connection == NULL) 334*2264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK) 335*2264Sjacobs return (result); 336*2264Sjacobs 337*2264Sjacobs ipp_initialize_request(svc, &request, OPID_PURGE_JOBS); 338*2264Sjacobs 339*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 340*2264Sjacobs ipp_add_printer_uri(svc, name, &op); 341*2264Sjacobs 342*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 343*2264Sjacobs "operational-attributes-group", op); 344*2264Sjacobs papiAttributeListFree(op); 345*2264Sjacobs result = ipp_send_request(svc, request, &response); 346*2264Sjacobs papiAttributeListFree(request); 347*2264Sjacobs 348*2264Sjacobs op = NULL; 349*2264Sjacobs for (status = papiAttributeListGetCollection(response, &iter, 350*2264Sjacobs "job-attributes-group", &op); 351*2264Sjacobs status == PAPI_OK; 352*2264Sjacobs status = papiAttributeListGetCollection(response, &iter, 353*2264Sjacobs NULL, &op)) { 354*2264Sjacobs job_t *j = NULL; 355*2264Sjacobs 356*2264Sjacobs if ((j = calloc(1, sizeof (*j))) == NULL) 357*2264Sjacobs return (PAPI_TEMPORARY_ERROR); 358*2264Sjacobs 359*2264Sjacobs copy_attributes(&j->attributes, op); 360*2264Sjacobs op = NULL; 361*2264Sjacobs list_append(jobs, j); 362*2264Sjacobs } 363*2264Sjacobs papiAttributeListFree(response); 364*2264Sjacobs 365*2264Sjacobs return (result); 366*2264Sjacobs } 367*2264Sjacobs 368*2264Sjacobs papi_status_t 369*2264Sjacobs papiPrinterListJobs(papi_service_t handle, char *name, 370*2264Sjacobs char **requested_attrs, int type_mask, 371*2264Sjacobs int max_num_jobs, papi_job_t **jobs) 372*2264Sjacobs { 373*2264Sjacobs papi_status_t status, result = PAPI_INTERNAL_ERROR; 374*2264Sjacobs service_t *svc = handle; 375*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 376*2264Sjacobs void *iter = NULL; 377*2264Sjacobs 378*2264Sjacobs if ((svc == NULL) || (name == NULL)) 379*2264Sjacobs return (PAPI_BAD_ARGUMENT); 380*2264Sjacobs 381*2264Sjacobs /* if we are already connected, use that connection. */ 382*2264Sjacobs if (svc->connection == NULL) 383*2264Sjacobs if ((result = service_connect(svc, name)) != PAPI_OK) 384*2264Sjacobs return (result); 385*2264Sjacobs 386*2264Sjacobs ipp_initialize_request(svc, &request, OPID_GET_JOBS); 387*2264Sjacobs 388*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 389*2264Sjacobs ipp_add_printer_uri(svc, name, &op); 390*2264Sjacobs 391*2264Sjacobs if (requested_attrs != NULL) { 392*2264Sjacobs int i; 393*2264Sjacobs 394*2264Sjacobs for (i = 0; requested_attrs[i] != NULL; i++) 395*2264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND, 396*2264Sjacobs "requested-attributes", requested_attrs[i]); 397*2264Sjacobs } 398*2264Sjacobs 399*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 400*2264Sjacobs "operational-attributes-group", op); 401*2264Sjacobs papiAttributeListFree(op); 402*2264Sjacobs result = ipp_send_request(svc, request, &response); 403*2264Sjacobs papiAttributeListFree(request); 404*2264Sjacobs 405*2264Sjacobs op = NULL; 406*2264Sjacobs for (status = papiAttributeListGetCollection(response, &iter, 407*2264Sjacobs "job-attributes-group", &op); 408*2264Sjacobs status == PAPI_OK; 409*2264Sjacobs status = papiAttributeListGetCollection(response, &iter, 410*2264Sjacobs NULL, &op)) { 411*2264Sjacobs job_t *j = NULL; 412*2264Sjacobs 413*2264Sjacobs if ((j = calloc(1, sizeof (*j))) == NULL) 414*2264Sjacobs return (PAPI_TEMPORARY_ERROR); 415*2264Sjacobs 416*2264Sjacobs copy_attributes(&j->attributes, op); 417*2264Sjacobs op = NULL; 418*2264Sjacobs list_append(jobs, j); 419*2264Sjacobs } 420*2264Sjacobs papiAttributeListFree(response); 421*2264Sjacobs 422*2264Sjacobs return (result); 423*2264Sjacobs } 424*2264Sjacobs 425*2264Sjacobs papi_attribute_t ** 426*2264Sjacobs papiPrinterGetAttributeList(papi_printer_t printer) 427*2264Sjacobs { 428*2264Sjacobs papi_attribute_t **result = NULL; 429*2264Sjacobs printer_t *p = printer; 430*2264Sjacobs 431*2264Sjacobs if (p != NULL) 432*2264Sjacobs result = p->attributes; 433*2264Sjacobs 434*2264Sjacobs return (result); 435*2264Sjacobs } 436