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: job.c 148 2006-04-25 16:54:17Z 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 <errno.h> 36*2264Sjacobs #include <string.h> 37*2264Sjacobs #include <papi_impl.h> 38*2264Sjacobs 39*2264Sjacobs #ifndef OPID_CUPS_MOVE_JOB 40*2264Sjacobs #define OPID_CUPS_MOVE_JOB 0x400D 41*2264Sjacobs #endif 42*2264Sjacobs 43*2264Sjacobs void 44*2264Sjacobs papiJobFree(papi_job_t job) 45*2264Sjacobs { 46*2264Sjacobs job_t *tmp = (job_t *)job; 47*2264Sjacobs 48*2264Sjacobs if (tmp != NULL) { 49*2264Sjacobs if (tmp->attributes != NULL) 50*2264Sjacobs papiAttributeListFree(tmp->attributes); 51*2264Sjacobs free(tmp); 52*2264Sjacobs } 53*2264Sjacobs } 54*2264Sjacobs 55*2264Sjacobs void 56*2264Sjacobs papiJobListFree(papi_job_t *jobs) 57*2264Sjacobs { 58*2264Sjacobs if (jobs != NULL) { 59*2264Sjacobs int i; 60*2264Sjacobs 61*2264Sjacobs for (i = 0; jobs[i] != NULL; i++) 62*2264Sjacobs papiJobFree(jobs[i]); 63*2264Sjacobs free(jobs); 64*2264Sjacobs } 65*2264Sjacobs } 66*2264Sjacobs 67*2264Sjacobs papi_attribute_t ** 68*2264Sjacobs papiJobGetAttributeList(papi_job_t job) 69*2264Sjacobs { 70*2264Sjacobs papi_attribute_t **result = NULL; 71*2264Sjacobs job_t *j = job; 72*2264Sjacobs 73*2264Sjacobs if (j != NULL) 74*2264Sjacobs result = j->attributes; 75*2264Sjacobs 76*2264Sjacobs return (result); 77*2264Sjacobs } 78*2264Sjacobs 79*2264Sjacobs char * 80*2264Sjacobs papiJobGetPrinterName(papi_job_t job) 81*2264Sjacobs { 82*2264Sjacobs char *result = NULL; 83*2264Sjacobs job_t *j = job; 84*2264Sjacobs 85*2264Sjacobs if (j != NULL) 86*2264Sjacobs (void) papiAttributeListGetString(j->attributes, NULL, 87*2264Sjacobs "printer-name", &result); 88*2264Sjacobs 89*2264Sjacobs return (result); 90*2264Sjacobs } 91*2264Sjacobs 92*2264Sjacobs int32_t 93*2264Sjacobs papiJobGetId(papi_job_t job) 94*2264Sjacobs { 95*2264Sjacobs int32_t result = -1; 96*2264Sjacobs job_t *j = job; 97*2264Sjacobs 98*2264Sjacobs if (j != NULL) 99*2264Sjacobs (void) papiAttributeListGetInteger(j->attributes, NULL, 100*2264Sjacobs "job-id", &result); 101*2264Sjacobs 102*2264Sjacobs return (result); 103*2264Sjacobs } 104*2264Sjacobs 105*2264Sjacobs papi_job_ticket_t * 106*2264Sjacobs papiJobGetJobTicket(papi_job_t job) 107*2264Sjacobs { 108*2264Sjacobs papi_job_ticket_t *result = NULL; 109*2264Sjacobs 110*2264Sjacobs return (result); 111*2264Sjacobs } 112*2264Sjacobs 113*2264Sjacobs static void 114*2264Sjacobs populate_job_request(service_t *svc, papi_attribute_t ***request, 115*2264Sjacobs papi_attribute_t **attributes, char *printer, uint16_t type) 116*2264Sjacobs { 117*2264Sjacobs papi_attribute_t **operational = NULL, **job = NULL; 118*2264Sjacobs static char *operational_names[] = { 119*2264Sjacobs "job-name", "ipp-attribute-fidelity", "document-name", 120*2264Sjacobs "compression", "document-format", "document-natural-language", 121*2264Sjacobs "job-k-octets", "job-impressions", "job-media-sheets", NULL 122*2264Sjacobs }; 123*2264Sjacobs 124*2264Sjacobs /* create the base IPP request */ 125*2264Sjacobs ipp_initialize_request(svc, request, type); 126*2264Sjacobs 127*2264Sjacobs /* create an operational attributes group */ 128*2264Sjacobs ipp_initialize_operational_attributes(svc, &operational, NULL); 129*2264Sjacobs ipp_add_printer_uri(svc, printer, &operational); 130*2264Sjacobs 131*2264Sjacobs /* split up the attributes into operational and job attributes */ 132*2264Sjacobs split_and_copy_attributes(operational_names, attributes, 133*2264Sjacobs &operational, &job); 134*2264Sjacobs 135*2264Sjacobs /* add the operational attributes group to the request */ 136*2264Sjacobs papiAttributeListAddCollection(request, PAPI_ATTR_REPLACE, 137*2264Sjacobs "operational-attributes-group", operational); 138*2264Sjacobs papiAttributeListFree(operational); 139*2264Sjacobs 140*2264Sjacobs /* add the job attributes group to the request */ 141*2264Sjacobs if (job != NULL) { 142*2264Sjacobs papiAttributeListAddCollection(request, PAPI_ATTR_REPLACE, 143*2264Sjacobs "job-attributes-group", job); 144*2264Sjacobs papiAttributeListFree(job); 145*2264Sjacobs } 146*2264Sjacobs } 147*2264Sjacobs 148*2264Sjacobs static papi_status_t 149*2264Sjacobs send_document_uri(service_t *svc, char *file, papi_attribute_t **attributes, 150*2264Sjacobs char *printer, int32_t id, char last, uint16_t type) 151*2264Sjacobs { 152*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 153*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 154*2264Sjacobs 155*2264Sjacobs /* create the base IPP request */ 156*2264Sjacobs ipp_initialize_request(svc, &request, type); 157*2264Sjacobs 158*2264Sjacobs /* create an operational attributes group */ 159*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 160*2264Sjacobs ipp_add_printer_uri(svc, printer, &op); 161*2264Sjacobs 162*2264Sjacobs papiAttributeListAddInteger(&op, PAPI_ATTR_REPLACE, "job-id", 163*2264Sjacobs id); 164*2264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_REPLACE, "document-name", 165*2264Sjacobs file); 166*2264Sjacobs papiAttributeListAddBoolean(&op, PAPI_ATTR_REPLACE, "last-document", 167*2264Sjacobs (last ? PAPI_TRUE : PAPI_FALSE)); 168*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 169*2264Sjacobs "operational-attributes-group", op); 170*2264Sjacobs papiAttributeListFree(op); 171*2264Sjacobs 172*2264Sjacobs /* send the IPP request to the server */ 173*2264Sjacobs result = ipp_send_request_with_file(svc, request, &response, file); 174*2264Sjacobs papiAttributeListFree(request); 175*2264Sjacobs papiAttributeListFree(response); 176*2264Sjacobs 177*2264Sjacobs return (result); 178*2264Sjacobs } 179*2264Sjacobs 180*2264Sjacobs typedef enum {_WITH_DATA, _BY_REFERENCE, _VALIDATE} call_type_t; 181*2264Sjacobs 182*2264Sjacobs papi_status_t 183*2264Sjacobs internal_job_submit(papi_service_t handle, char *printer, 184*2264Sjacobs papi_attribute_t **job_attributes, 185*2264Sjacobs papi_job_ticket_t *job_ticket, 186*2264Sjacobs char **files, papi_job_t *job, 187*2264Sjacobs call_type_t call_type) 188*2264Sjacobs { 189*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 190*2264Sjacobs service_t *svc = handle; 191*2264Sjacobs job_t *j = NULL; 192*2264Sjacobs int i; 193*2264Sjacobs uint16_t req_type = OPID_PRINT_JOB; 194*2264Sjacobs uint16_t data_type = OPID_SEND_DOCUMENT; 195*2264Sjacobs papi_attribute_t **request = NULL, **response = NULL; 196*2264Sjacobs 197*2264Sjacobs if ((svc == NULL) || (printer == NULL) || (job == NULL)) 198*2264Sjacobs return (PAPI_BAD_ARGUMENT); 199*2264Sjacobs 200*2264Sjacobs switch (call_type) { 201*2264Sjacobs case _BY_REFERENCE: 202*2264Sjacobs #ifdef SOME_DAY_WE_WILL_BE_ABLE_TO_USE_URIS_FOR_JOB_DATA 203*2264Sjacobs /* 204*2264Sjacobs * For the time being, this is disabled. There are a number 205*2264Sjacobs * of issues to be dealt with before we can send a URI 206*2264Sjacobs * across the network to the server. For example, the file 207*2264Sjacobs * name(s) passed in are most likely relative to the current 208*2264Sjacobs * hosts filesystem. They also most likely will require some 209*2264Sjacobs * form of authentication information to be passed with the 210*2264Sjacobs * URI. 211*2264Sjacobs */ 212*2264Sjacobs req_type = OPID_PRINT_URI; 213*2264Sjacobs req_type = OPID_SEND_URI; 214*2264Sjacobs #endif 215*2264Sjacobs /* fall-through */ 216*2264Sjacobs case _WITH_DATA: 217*2264Sjacobs if ((files == NULL) || (files[0] == NULL)) 218*2264Sjacobs return (PAPI_BAD_ARGUMENT); 219*2264Sjacobs 220*2264Sjacobs if (files[1] != NULL) /* more than 1 file */ 221*2264Sjacobs req_type = OPID_CREATE_JOB; 222*2264Sjacobs 223*2264Sjacobs break; 224*2264Sjacobs case _VALIDATE: 225*2264Sjacobs req_type = OPID_VALIDATE_JOB; 226*2264Sjacobs /* if we have files, validate access to them */ 227*2264Sjacobs if (files != NULL) { 228*2264Sjacobs for (i = 0; files[i] != NULL; i++) 229*2264Sjacobs if (access(files[i], R_OK) < 0) { 230*2264Sjacobs detailed_error(svc, "%s: %s", files[i], 231*2264Sjacobs strerror(errno)); 232*2264Sjacobs return (PAPI_DOCUMENT_ACCESS_ERROR); 233*2264Sjacobs } 234*2264Sjacobs files = NULL; 235*2264Sjacobs } 236*2264Sjacobs break; 237*2264Sjacobs } 238*2264Sjacobs 239*2264Sjacobs /* if we are already connected, use that connection. */ 240*2264Sjacobs if (svc->connection == NULL) 241*2264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 242*2264Sjacobs return (result); 243*2264Sjacobs 244*2264Sjacobs if ((*job = j = calloc(1, sizeof (*j))) == NULL) 245*2264Sjacobs return (PAPI_TEMPORARY_ERROR); 246*2264Sjacobs 247*2264Sjacobs /* create IPP request */ 248*2264Sjacobs populate_job_request(svc, &request, job_attributes, printer, req_type); 249*2264Sjacobs 250*2264Sjacobs switch (req_type) { 251*2264Sjacobs case OPID_PRINT_JOB: 252*2264Sjacobs result = ipp_send_request_with_file(svc, request, &response, 253*2264Sjacobs files[0]); 254*2264Sjacobs break; 255*2264Sjacobs case OPID_CREATE_JOB: 256*2264Sjacobs case OPID_VALIDATE_JOB: 257*2264Sjacobs case OPID_PRINT_URI: 258*2264Sjacobs result = ipp_send_request(svc, request, &response); 259*2264Sjacobs break; 260*2264Sjacobs } 261*2264Sjacobs papiAttributeListFree(request); 262*2264Sjacobs 263*2264Sjacobs if (result == PAPI_OK) { 264*2264Sjacobs papi_attribute_t **op = NULL; 265*2264Sjacobs 266*2264Sjacobs /* retrieve the job attributes */ 267*2264Sjacobs papiAttributeListGetCollection(response, NULL, 268*2264Sjacobs "job-attributes-group", &op); 269*2264Sjacobs copy_attributes(&j->attributes, op); 270*2264Sjacobs 271*2264Sjacobs if (req_type == OPID_CREATE_JOB) { 272*2264Sjacobs int32_t id = 0; 273*2264Sjacobs 274*2264Sjacobs papiAttributeListGetInteger(j->attributes, NULL, 275*2264Sjacobs "job-id", &id); 276*2264Sjacobs /* send each document */ 277*2264Sjacobs for (i = 0; ((result == PAPI_OK) && (files[i] != NULL)); 278*2264Sjacobs i++) 279*2264Sjacobs result = send_document_uri(svc, files[i], 280*2264Sjacobs job_attributes, 281*2264Sjacobs printer, id, (files[i+1]?0:1), 282*2264Sjacobs data_type); 283*2264Sjacobs } 284*2264Sjacobs } 285*2264Sjacobs papiAttributeListFree(response); 286*2264Sjacobs 287*2264Sjacobs return (result); 288*2264Sjacobs } 289*2264Sjacobs 290*2264Sjacobs papi_status_t 291*2264Sjacobs papiJobSubmit(papi_service_t handle, char *printer, 292*2264Sjacobs papi_attribute_t **job_attributes, 293*2264Sjacobs papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) 294*2264Sjacobs { 295*2264Sjacobs return (internal_job_submit(handle, printer, job_attributes, 296*2264Sjacobs job_ticket, files, job, _WITH_DATA)); 297*2264Sjacobs } 298*2264Sjacobs 299*2264Sjacobs papi_status_t 300*2264Sjacobs papiJobSubmitByReference(papi_service_t handle, char *printer, 301*2264Sjacobs papi_attribute_t **job_attributes, 302*2264Sjacobs papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) 303*2264Sjacobs { 304*2264Sjacobs return (internal_job_submit(handle, printer, job_attributes, 305*2264Sjacobs job_ticket, files, job, _BY_REFERENCE)); 306*2264Sjacobs } 307*2264Sjacobs 308*2264Sjacobs papi_status_t 309*2264Sjacobs papiJobValidate(papi_service_t handle, char *printer, 310*2264Sjacobs papi_attribute_t **job_attributes, 311*2264Sjacobs papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) 312*2264Sjacobs { 313*2264Sjacobs return (internal_job_submit(handle, printer, job_attributes, 314*2264Sjacobs job_ticket, files, job, _VALIDATE)); 315*2264Sjacobs } 316*2264Sjacobs 317*2264Sjacobs papi_status_t 318*2264Sjacobs papiJobStreamOpen(papi_service_t handle, char *printer, 319*2264Sjacobs papi_attribute_t **job_attributes, 320*2264Sjacobs papi_job_ticket_t *job_ticket, papi_stream_t *stream) 321*2264Sjacobs { 322*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 323*2264Sjacobs papi_attribute_t **request = NULL; 324*2264Sjacobs service_t *svc = handle; 325*2264Sjacobs 326*2264Sjacobs if ((svc == NULL) || (printer == NULL) || (stream == NULL)) 327*2264Sjacobs return (PAPI_BAD_ARGUMENT); 328*2264Sjacobs 329*2264Sjacobs /* if we are already connected, use that connection. */ 330*2264Sjacobs if (svc->connection == NULL) 331*2264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 332*2264Sjacobs return (result); 333*2264Sjacobs 334*2264Sjacobs /* create job request */ 335*2264Sjacobs populate_job_request(svc, &request, job_attributes, printer, 336*2264Sjacobs OPID_PRINT_JOB); 337*2264Sjacobs 338*2264Sjacobs *stream = svc->connection; 339*2264Sjacobs 340*2264Sjacobs result = ipp_send_initial_request_block(svc, request, 0); 341*2264Sjacobs papiAttributeListFree(request); 342*2264Sjacobs 343*2264Sjacobs return (result); 344*2264Sjacobs } 345*2264Sjacobs 346*2264Sjacobs papi_status_t 347*2264Sjacobs papiJobStreamWrite(papi_service_t handle, 348*2264Sjacobs papi_stream_t stream, void *buffer, size_t buflen) 349*2264Sjacobs { 350*2264Sjacobs papi_status_t result = PAPI_OK; 351*2264Sjacobs service_t *svc = handle; 352*2264Sjacobs size_t rc; 353*2264Sjacobs 354*2264Sjacobs #ifdef DEBUG 355*2264Sjacobs printf("papiJobStreamWrite(0x%8.8x, 0x%8.8x, 0x%8.8x, %d)\n", 356*2264Sjacobs handle, stream, buffer, buflen); 357*2264Sjacobs httpDumpData(stdout, "papiJobStreamWrite:", buffer, buflen); 358*2264Sjacobs #endif 359*2264Sjacobs 360*2264Sjacobs if ((svc == NULL) || (stream == NULL) || (buffer == NULL) || 361*2264Sjacobs (buflen == 0)) 362*2264Sjacobs return (PAPI_BAD_ARGUMENT); 363*2264Sjacobs 364*2264Sjacobs while ((result == PAPI_OK) && (buflen > 0)) { 365*2264Sjacobs rc = ipp_request_write(svc, buffer, buflen); 366*2264Sjacobs if (rc < 0) 367*2264Sjacobs result = PAPI_TEMPORARY_ERROR; 368*2264Sjacobs else { 369*2264Sjacobs buffer = (char *)buffer + rc; 370*2264Sjacobs buflen -= rc; 371*2264Sjacobs } 372*2264Sjacobs } 373*2264Sjacobs 374*2264Sjacobs #ifdef DEBUG 375*2264Sjacobs printf("papiJobStreamWrite(): %s\n", papiStatusString(result)); 376*2264Sjacobs #endif 377*2264Sjacobs 378*2264Sjacobs return (result); 379*2264Sjacobs } 380*2264Sjacobs 381*2264Sjacobs papi_status_t 382*2264Sjacobs papiJobStreamClose(papi_service_t handle, 383*2264Sjacobs papi_stream_t stream, papi_job_t *job) 384*2264Sjacobs { 385*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 386*2264Sjacobs http_status_t status = HTTP_CONTINUE; 387*2264Sjacobs service_t *svc = handle; 388*2264Sjacobs papi_attribute_t **response = NULL; 389*2264Sjacobs job_t *j = NULL; 390*2264Sjacobs 391*2264Sjacobs if ((svc == NULL) || (stream == NULL) || (job == NULL)) 392*2264Sjacobs return (PAPI_BAD_ARGUMENT); 393*2264Sjacobs 394*2264Sjacobs if ((*job = j = calloc(1, sizeof (*j))) == NULL) 395*2264Sjacobs return (PAPI_TEMPORARY_ERROR); 396*2264Sjacobs 397*2264Sjacobs (void) ipp_request_write(svc, "", 0); 398*2264Sjacobs 399*2264Sjacobs /* update our connection info */ 400*2264Sjacobs while (status == HTTP_CONTINUE) 401*2264Sjacobs status = httpUpdate(svc->connection); 402*2264Sjacobs 403*2264Sjacobs if (status != HTTP_OK) 404*2264Sjacobs return (http_to_papi_status(status)); 405*2264Sjacobs httpWait(svc->connection, 1000); 406*2264Sjacobs 407*2264Sjacobs /* read the IPP response */ 408*2264Sjacobs result = ipp_read_message(&ipp_request_read, svc, &response, 409*2264Sjacobs IPP_TYPE_RESPONSE); 410*2264Sjacobs if (result == PAPI_OK) 411*2264Sjacobs result = ipp_status_info(svc, response); 412*2264Sjacobs 413*2264Sjacobs if (result == PAPI_OK) { 414*2264Sjacobs papi_attribute_t **op = NULL; 415*2264Sjacobs 416*2264Sjacobs papiAttributeListGetCollection(response, NULL, 417*2264Sjacobs "job-attributes-group", &op); 418*2264Sjacobs copy_attributes(&j->attributes, op); 419*2264Sjacobs } 420*2264Sjacobs papiAttributeListFree(response); 421*2264Sjacobs 422*2264Sjacobs return (result); 423*2264Sjacobs } 424*2264Sjacobs 425*2264Sjacobs papi_status_t 426*2264Sjacobs papiJobQuery(papi_service_t handle, char *printer, int32_t job_id, 427*2264Sjacobs char **requested_attrs, 428*2264Sjacobs papi_job_t *job) 429*2264Sjacobs { 430*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 431*2264Sjacobs service_t *svc = handle; 432*2264Sjacobs job_t *j = NULL; 433*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 434*2264Sjacobs 435*2264Sjacobs if ((svc == NULL) || (printer == NULL)) 436*2264Sjacobs return (PAPI_BAD_ARGUMENT); 437*2264Sjacobs 438*2264Sjacobs /* if we are already connected, use that connection. */ 439*2264Sjacobs if (svc->connection == NULL) 440*2264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 441*2264Sjacobs return (result); 442*2264Sjacobs 443*2264Sjacobs if ((*job = j = calloc(1, sizeof (*j))) == NULL) 444*2264Sjacobs return (PAPI_TEMPORARY_ERROR); 445*2264Sjacobs 446*2264Sjacobs ipp_initialize_request(svc, &request, OPID_GET_JOB_ATTRIBUTES); 447*2264Sjacobs 448*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 449*2264Sjacobs ipp_add_printer_uri(svc, printer, &op); 450*2264Sjacobs 451*2264Sjacobs papiAttributeListAddInteger(&op, PAPI_ATTR_REPLACE, "job-id", job_id); 452*2264Sjacobs if (requested_attrs != NULL) { 453*2264Sjacobs int i; 454*2264Sjacobs 455*2264Sjacobs for (i = 0; requested_attrs[i] != NULL; i++) 456*2264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND, 457*2264Sjacobs "requested-attributes", requested_attrs[i]); 458*2264Sjacobs } 459*2264Sjacobs 460*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 461*2264Sjacobs "operational-attributes-group", op); 462*2264Sjacobs papiAttributeListFree(op); 463*2264Sjacobs result = ipp_send_request(svc, request, &response); 464*2264Sjacobs papiAttributeListFree(request); 465*2264Sjacobs 466*2264Sjacobs op = NULL; 467*2264Sjacobs papiAttributeListGetCollection(response, NULL, 468*2264Sjacobs "job-attributes-group", &op); 469*2264Sjacobs copy_attributes(&j->attributes, op); 470*2264Sjacobs papiAttributeListFree(response); 471*2264Sjacobs 472*2264Sjacobs return (result); 473*2264Sjacobs } 474*2264Sjacobs 475*2264Sjacobs /* papiJob{Cancel|Hold|Release|Restart|Promote} are all the same */ 476*2264Sjacobs static papi_status_t 477*2264Sjacobs _job_cancel_hold_release_restart_promote(papi_service_t handle, 478*2264Sjacobs char *printer, int32_t job_id, uint16_t type) 479*2264Sjacobs { 480*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 481*2264Sjacobs service_t *svc = handle; 482*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 483*2264Sjacobs 484*2264Sjacobs if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 485*2264Sjacobs return (PAPI_BAD_ARGUMENT); 486*2264Sjacobs 487*2264Sjacobs /* if we are already connected, use that connection. */ 488*2264Sjacobs if (svc->connection == NULL) 489*2264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 490*2264Sjacobs return (result); 491*2264Sjacobs 492*2264Sjacobs ipp_initialize_request(svc, &request, type); 493*2264Sjacobs 494*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 495*2264Sjacobs ipp_add_printer_uri(svc, printer, &op); 496*2264Sjacobs 497*2264Sjacobs papiAttributeListAddInteger(&op, PAPI_ATTR_REPLACE, "job-id", job_id); 498*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 499*2264Sjacobs "operational-attributes-group", op); 500*2264Sjacobs papiAttributeListFree(op); 501*2264Sjacobs result = ipp_send_request(svc, request, &response); 502*2264Sjacobs papiAttributeListFree(request); 503*2264Sjacobs papiAttributeListFree(response); 504*2264Sjacobs 505*2264Sjacobs return (result); 506*2264Sjacobs } 507*2264Sjacobs 508*2264Sjacobs papi_status_t 509*2264Sjacobs papiJobCancel(papi_service_t handle, char *printer, int32_t job_id) 510*2264Sjacobs { 511*2264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 512*2264Sjacobs job_id, OPID_CANCEL_JOB)); 513*2264Sjacobs } 514*2264Sjacobs 515*2264Sjacobs 516*2264Sjacobs papi_status_t 517*2264Sjacobs papiJobHold(papi_service_t handle, char *printer, int32_t job_id) 518*2264Sjacobs { 519*2264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 520*2264Sjacobs job_id, OPID_HOLD_JOB)); 521*2264Sjacobs } 522*2264Sjacobs 523*2264Sjacobs papi_status_t 524*2264Sjacobs papiJobRelease(papi_service_t handle, char *printer, int32_t job_id) 525*2264Sjacobs { 526*2264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 527*2264Sjacobs job_id, OPID_RELEASE_JOB)); 528*2264Sjacobs } 529*2264Sjacobs 530*2264Sjacobs papi_status_t 531*2264Sjacobs papiJobRestart(papi_service_t handle, char *printer, int32_t job_id) 532*2264Sjacobs { 533*2264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 534*2264Sjacobs job_id, OPID_RESTART_JOB)); 535*2264Sjacobs } 536*2264Sjacobs 537*2264Sjacobs papi_status_t 538*2264Sjacobs papiJobPromote(papi_service_t handle, char *printer, int32_t job_id) 539*2264Sjacobs { 540*2264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 541*2264Sjacobs job_id, OPID_PROMOTE_JOB)); 542*2264Sjacobs } 543*2264Sjacobs 544*2264Sjacobs papi_status_t 545*2264Sjacobs papiJobMove(papi_service_t handle, char *printer, int32_t job_id, 546*2264Sjacobs char *destination) 547*2264Sjacobs { 548*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 549*2264Sjacobs service_t *svc = handle; 550*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 551*2264Sjacobs 552*2264Sjacobs if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 553*2264Sjacobs (destination == NULL)) 554*2264Sjacobs return (PAPI_BAD_ARGUMENT); 555*2264Sjacobs 556*2264Sjacobs /* if we are already connected, use that connection. */ 557*2264Sjacobs if (svc->connection == NULL) 558*2264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 559*2264Sjacobs return (result); 560*2264Sjacobs 561*2264Sjacobs ipp_initialize_request(svc, &request, OPID_CUPS_MOVE_JOB); 562*2264Sjacobs 563*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 564*2264Sjacobs ipp_add_printer_uri(svc, printer, &op); 565*2264Sjacobs 566*2264Sjacobs papiAttributeListAddInteger(&op, PAPI_ATTR_REPLACE, "job-id", job_id); 567*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 568*2264Sjacobs "operational-attributes-group", op); 569*2264Sjacobs papiAttributeListFree(op); 570*2264Sjacobs 571*2264Sjacobs op = NULL; 572*2264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_EXCL, 573*2264Sjacobs "job-printer-uri", destination); 574*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 575*2264Sjacobs "job-attributes-group", op); 576*2264Sjacobs papiAttributeListFree(op); 577*2264Sjacobs 578*2264Sjacobs result = ipp_send_request(svc, request, &response); 579*2264Sjacobs papiAttributeListFree(request); 580*2264Sjacobs papiAttributeListFree(response); 581*2264Sjacobs 582*2264Sjacobs return (result); 583*2264Sjacobs } 584*2264Sjacobs 585*2264Sjacobs papi_status_t 586*2264Sjacobs papiJobModify(papi_service_t handle, char *printer, int32_t job_id, 587*2264Sjacobs papi_attribute_t **attributes, papi_job_t *job) 588*2264Sjacobs { 589*2264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 590*2264Sjacobs service_t *svc = handle; 591*2264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 592*2264Sjacobs job_t *j = NULL; 593*2264Sjacobs 594*2264Sjacobs if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 595*2264Sjacobs (attributes == NULL)) 596*2264Sjacobs return (PAPI_BAD_ARGUMENT); 597*2264Sjacobs 598*2264Sjacobs if ((*job = j = calloc(1, sizeof (*j))) == NULL) 599*2264Sjacobs return (PAPI_TEMPORARY_ERROR); 600*2264Sjacobs 601*2264Sjacobs /* if we are already connected, use that connection. */ 602*2264Sjacobs if (svc->connection == NULL) 603*2264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 604*2264Sjacobs return (result); 605*2264Sjacobs 606*2264Sjacobs ipp_initialize_request(svc, &request, OPID_SET_JOB_ATTRIBUTES); 607*2264Sjacobs 608*2264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 609*2264Sjacobs ipp_add_printer_uri(svc, printer, &op); 610*2264Sjacobs 611*2264Sjacobs papiAttributeListAddInteger(&op, PAPI_ATTR_REPLACE, "job-id", job_id); 612*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 613*2264Sjacobs "operational-attributes-group", op); 614*2264Sjacobs papiAttributeListFree(op); 615*2264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 616*2264Sjacobs "job-attributes-group", attributes); 617*2264Sjacobs result = ipp_send_request(svc, request, &response); 618*2264Sjacobs papiAttributeListFree(request); 619*2264Sjacobs 620*2264Sjacobs op = NULL; 621*2264Sjacobs papiAttributeListGetCollection(response, NULL, 622*2264Sjacobs "job-attributes-group", &op); 623*2264Sjacobs copy_attributes(&j->attributes, op); 624*2264Sjacobs papiAttributeListFree(response); 625*2264Sjacobs 626*2264Sjacobs return (result); 627*2264Sjacobs } 628