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 /* 238569SJonathan.Ca@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 242264Sjacobs * Use is subject to license terms. 252264Sjacobs * 262264Sjacobs */ 272264Sjacobs 282264Sjacobs /* $Id: job.c 148 2006-04-25 16:54:17Z njacobs $ */ 292264Sjacobs 302264Sjacobs 312264Sjacobs /*LINTLIBRARY*/ 322264Sjacobs 332264Sjacobs #include <stdlib.h> 342264Sjacobs #include <errno.h> 352264Sjacobs #include <string.h> 362264Sjacobs #include <papi_impl.h> 378569SJonathan.Ca@Sun.COM #include <fcntl.h> 388569SJonathan.Ca@Sun.COM #include <sys/types.h> 398569SJonathan.Ca@Sun.COM #include <sys/stat.h> 402264Sjacobs 412264Sjacobs #ifndef OPID_CUPS_MOVE_JOB 422264Sjacobs #define OPID_CUPS_MOVE_JOB 0x400D 432264Sjacobs #endif 442264Sjacobs 452264Sjacobs void 462264Sjacobs papiJobFree(papi_job_t job) 472264Sjacobs { 482264Sjacobs job_t *tmp = (job_t *)job; 492264Sjacobs 502264Sjacobs if (tmp != NULL) { 512264Sjacobs if (tmp->attributes != NULL) 522264Sjacobs papiAttributeListFree(tmp->attributes); 532264Sjacobs free(tmp); 542264Sjacobs } 552264Sjacobs } 562264Sjacobs 572264Sjacobs void 582264Sjacobs papiJobListFree(papi_job_t *jobs) 592264Sjacobs { 602264Sjacobs if (jobs != NULL) { 612264Sjacobs int i; 622264Sjacobs 632264Sjacobs for (i = 0; jobs[i] != NULL; i++) 642264Sjacobs papiJobFree(jobs[i]); 652264Sjacobs free(jobs); 662264Sjacobs } 672264Sjacobs } 682264Sjacobs 692264Sjacobs papi_attribute_t ** 702264Sjacobs papiJobGetAttributeList(papi_job_t job) 712264Sjacobs { 722264Sjacobs papi_attribute_t **result = NULL; 732264Sjacobs job_t *j = job; 742264Sjacobs 752264Sjacobs if (j != NULL) 762264Sjacobs result = j->attributes; 772264Sjacobs 782264Sjacobs return (result); 792264Sjacobs } 802264Sjacobs 812264Sjacobs char * 822264Sjacobs papiJobGetPrinterName(papi_job_t job) 832264Sjacobs { 842264Sjacobs char *result = NULL; 852264Sjacobs job_t *j = job; 862264Sjacobs 872264Sjacobs if (j != NULL) 882264Sjacobs (void) papiAttributeListGetString(j->attributes, NULL, 898569SJonathan.Ca@Sun.COM "printer-name", &result); 902264Sjacobs 912264Sjacobs return (result); 922264Sjacobs } 932264Sjacobs 942264Sjacobs int32_t 952264Sjacobs papiJobGetId(papi_job_t job) 962264Sjacobs { 972264Sjacobs int32_t result = -1; 982264Sjacobs job_t *j = job; 992264Sjacobs 1002264Sjacobs if (j != NULL) 1012264Sjacobs (void) papiAttributeListGetInteger(j->attributes, NULL, 1028569SJonathan.Ca@Sun.COM "job-id", &result); 1032264Sjacobs 1042264Sjacobs return (result); 1052264Sjacobs } 1062264Sjacobs 1072264Sjacobs papi_job_ticket_t * 1082264Sjacobs papiJobGetJobTicket(papi_job_t job) 1092264Sjacobs { 1102264Sjacobs papi_job_ticket_t *result = NULL; 1112264Sjacobs 1122264Sjacobs return (result); 1132264Sjacobs } 1142264Sjacobs 1152264Sjacobs static void 1162264Sjacobs populate_job_request(service_t *svc, papi_attribute_t ***request, 1172264Sjacobs papi_attribute_t **attributes, char *printer, uint16_t type) 1182264Sjacobs { 1192264Sjacobs papi_attribute_t **operational = NULL, **job = NULL; 1202264Sjacobs static char *operational_names[] = { 1212264Sjacobs "job-name", "ipp-attribute-fidelity", "document-name", 1222264Sjacobs "compression", "document-format", "document-natural-language", 1232264Sjacobs "job-k-octets", "job-impressions", "job-media-sheets", NULL 1242264Sjacobs }; 1252264Sjacobs 1262264Sjacobs /* create the base IPP request */ 1272264Sjacobs ipp_initialize_request(svc, request, type); 1282264Sjacobs 1292264Sjacobs /* create an operational attributes group */ 1303917Sjacobs ipp_initialize_operational_attributes(svc, &operational, printer, -1); 1312264Sjacobs 1322264Sjacobs /* split up the attributes into operational and job attributes */ 1332264Sjacobs split_and_copy_attributes(operational_names, attributes, 1348569SJonathan.Ca@Sun.COM &operational, &job); 1352264Sjacobs 1362264Sjacobs /* add the operational attributes group to the request */ 1372264Sjacobs papiAttributeListAddCollection(request, PAPI_ATTR_REPLACE, 1388569SJonathan.Ca@Sun.COM "operational-attributes-group", operational); 1392264Sjacobs papiAttributeListFree(operational); 1402264Sjacobs 1412264Sjacobs /* add the job attributes group to the request */ 1422264Sjacobs if (job != NULL) { 1439152SSonam.Gupta@Sun.COM /* 1449152SSonam.Gupta@Sun.COM * Add job-originating-host-name to attributes 1459152SSonam.Gupta@Sun.COM * if not already set. 1469152SSonam.Gupta@Sun.COM */ 1479152SSonam.Gupta@Sun.COM char *hostname = NULL; 1489152SSonam.Gupta@Sun.COM 1499152SSonam.Gupta@Sun.COM papiAttributeListGetString(job, NULL, 1509152SSonam.Gupta@Sun.COM "job-originating-host-name", &hostname); 1519152SSonam.Gupta@Sun.COM 1529152SSonam.Gupta@Sun.COM if (hostname == NULL) { 1539152SSonam.Gupta@Sun.COM char host[BUFSIZ]; 1549152SSonam.Gupta@Sun.COM 1559152SSonam.Gupta@Sun.COM if (gethostname(host, sizeof (host)) == 0) 1569152SSonam.Gupta@Sun.COM papiAttributeListAddString(&job, PAPI_ATTR_EXCL, 1579152SSonam.Gupta@Sun.COM "job-originating-host-name", host); 1589152SSonam.Gupta@Sun.COM } 1599152SSonam.Gupta@Sun.COM 1602264Sjacobs papiAttributeListAddCollection(request, PAPI_ATTR_REPLACE, 1618569SJonathan.Ca@Sun.COM "job-attributes-group", job); 1622264Sjacobs papiAttributeListFree(job); 1632264Sjacobs } 1642264Sjacobs } 1652264Sjacobs 1662264Sjacobs static papi_status_t 1672264Sjacobs send_document_uri(service_t *svc, char *file, papi_attribute_t **attributes, 1682264Sjacobs char *printer, int32_t id, char last, uint16_t type) 1692264Sjacobs { 1702264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 1712264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 1722264Sjacobs 1732264Sjacobs /* create the base IPP request */ 1742264Sjacobs ipp_initialize_request(svc, &request, type); 1752264Sjacobs 1762264Sjacobs /* create an operational attributes group */ 1773917Sjacobs ipp_initialize_operational_attributes(svc, &op, printer, id); 1782264Sjacobs 1792264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_REPLACE, "document-name", 1808569SJonathan.Ca@Sun.COM file); 1812264Sjacobs papiAttributeListAddBoolean(&op, PAPI_ATTR_REPLACE, "last-document", 1828569SJonathan.Ca@Sun.COM (last ? PAPI_TRUE : PAPI_FALSE)); 1832264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 1848569SJonathan.Ca@Sun.COM "operational-attributes-group", op); 1852264Sjacobs papiAttributeListFree(op); 1862264Sjacobs 1872264Sjacobs /* send the IPP request to the server */ 1882264Sjacobs result = ipp_send_request_with_file(svc, request, &response, file); 1892264Sjacobs papiAttributeListFree(request); 1902264Sjacobs papiAttributeListFree(response); 1912264Sjacobs 1922264Sjacobs return (result); 1932264Sjacobs } 1942264Sjacobs 1952264Sjacobs typedef enum {_WITH_DATA, _BY_REFERENCE, _VALIDATE} call_type_t; 1962264Sjacobs 1972264Sjacobs papi_status_t 1982264Sjacobs internal_job_submit(papi_service_t handle, char *printer, 1992264Sjacobs papi_attribute_t **job_attributes, 2002264Sjacobs papi_job_ticket_t *job_ticket, 2012264Sjacobs char **files, papi_job_t *job, 2022264Sjacobs call_type_t call_type) 2032264Sjacobs { 2042264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 2052264Sjacobs service_t *svc = handle; 2068569SJonathan.Ca@Sun.COM struct stat statbuf; 2072264Sjacobs job_t *j = NULL; 2082264Sjacobs int i; 2092264Sjacobs uint16_t req_type = OPID_PRINT_JOB; 2102264Sjacobs uint16_t data_type = OPID_SEND_DOCUMENT; 2112264Sjacobs papi_attribute_t **request = NULL, **response = NULL; 2122264Sjacobs 2132264Sjacobs if ((svc == NULL) || (printer == NULL) || (job == NULL)) 2142264Sjacobs return (PAPI_BAD_ARGUMENT); 2152264Sjacobs 2162264Sjacobs switch (call_type) { 2172264Sjacobs case _BY_REFERENCE: 2182264Sjacobs #ifdef SOME_DAY_WE_WILL_BE_ABLE_TO_USE_URIS_FOR_JOB_DATA 2192264Sjacobs /* 2202264Sjacobs * For the time being, this is disabled. There are a number 2212264Sjacobs * of issues to be dealt with before we can send a URI 2222264Sjacobs * across the network to the server. For example, the file 2232264Sjacobs * name(s) passed in are most likely relative to the current 2242264Sjacobs * hosts filesystem. They also most likely will require some 2252264Sjacobs * form of authentication information to be passed with the 2262264Sjacobs * URI. 2272264Sjacobs */ 2282264Sjacobs req_type = OPID_PRINT_URI; 2292264Sjacobs req_type = OPID_SEND_URI; 2302264Sjacobs #endif 2312264Sjacobs /* fall-through */ 2322264Sjacobs case _WITH_DATA: 2332264Sjacobs if ((files == NULL) || (files[0] == NULL)) 2342264Sjacobs return (PAPI_BAD_ARGUMENT); 2352264Sjacobs 2362264Sjacobs if (files[1] != NULL) /* more than 1 file */ 2372264Sjacobs req_type = OPID_CREATE_JOB; 2382264Sjacobs 2392264Sjacobs break; 2402264Sjacobs case _VALIDATE: 2412264Sjacobs req_type = OPID_VALIDATE_JOB; 2422264Sjacobs /* if we have files, validate access to them */ 2432264Sjacobs if (files != NULL) { 2448569SJonathan.Ca@Sun.COM for (i = 0; files[i] != NULL; i++) { 2452264Sjacobs if (access(files[i], R_OK) < 0) { 2462264Sjacobs detailed_error(svc, "%s: %s", files[i], 2478569SJonathan.Ca@Sun.COM strerror(errno)); 2482264Sjacobs return (PAPI_DOCUMENT_ACCESS_ERROR); 2492264Sjacobs } 2508569SJonathan.Ca@Sun.COM 2518569SJonathan.Ca@Sun.COM if (strcmp("standard input", files[i]) != 0) { 2528569SJonathan.Ca@Sun.COM stat(files[i], &statbuf); 2538569SJonathan.Ca@Sun.COM if (statbuf.st_size == 0) { 2548569SJonathan.Ca@Sun.COM detailed_error(svc, 2558569SJonathan.Ca@Sun.COM "Zero byte (empty) file: " 2568569SJonathan.Ca@Sun.COM "%s", 2578569SJonathan.Ca@Sun.COM files[i]); 2588569SJonathan.Ca@Sun.COM return (PAPI_BAD_ARGUMENT); 2598569SJonathan.Ca@Sun.COM } 2608569SJonathan.Ca@Sun.COM } 2618569SJonathan.Ca@Sun.COM } 2622264Sjacobs files = NULL; 2632264Sjacobs } 2642264Sjacobs break; 2652264Sjacobs } 2662264Sjacobs 2672264Sjacobs /* if we are already connected, use that connection. */ 2682264Sjacobs if (svc->connection == NULL) 2692264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 2702264Sjacobs return (result); 2712264Sjacobs 2722264Sjacobs if ((*job = j = calloc(1, sizeof (*j))) == NULL) 2732264Sjacobs return (PAPI_TEMPORARY_ERROR); 2742264Sjacobs 275*9166SSonam.Gupta@Sun.COM /* 276*9166SSonam.Gupta@Sun.COM * before creating IPP request 277*9166SSonam.Gupta@Sun.COM * add the job-name 278*9166SSonam.Gupta@Sun.COM */ 279*9166SSonam.Gupta@Sun.COM if ((files != NULL) && (files[0] != NULL)) 280*9166SSonam.Gupta@Sun.COM papiAttributeListAddString(&job_attributes, PAPI_ATTR_EXCL, 281*9166SSonam.Gupta@Sun.COM "job-name", files[0]); 282*9166SSonam.Gupta@Sun.COM 2832264Sjacobs /* create IPP request */ 2842264Sjacobs populate_job_request(svc, &request, job_attributes, printer, req_type); 2852264Sjacobs 2862264Sjacobs switch (req_type) { 2872264Sjacobs case OPID_PRINT_JOB: 2882264Sjacobs result = ipp_send_request_with_file(svc, request, &response, 2898569SJonathan.Ca@Sun.COM files[0]); 2902264Sjacobs break; 2912264Sjacobs case OPID_CREATE_JOB: 2922264Sjacobs case OPID_VALIDATE_JOB: 2932264Sjacobs case OPID_PRINT_URI: 2942264Sjacobs result = ipp_send_request(svc, request, &response); 2952264Sjacobs break; 2962264Sjacobs } 2972264Sjacobs papiAttributeListFree(request); 2982264Sjacobs 2992264Sjacobs if (result == PAPI_OK) { 3002264Sjacobs papi_attribute_t **op = NULL; 3012264Sjacobs 3022264Sjacobs /* retrieve the job attributes */ 3032264Sjacobs papiAttributeListGetCollection(response, NULL, 3048569SJonathan.Ca@Sun.COM "job-attributes-group", &op); 3052264Sjacobs copy_attributes(&j->attributes, op); 3062264Sjacobs 3072264Sjacobs if (req_type == OPID_CREATE_JOB) { 3082264Sjacobs int32_t id = 0; 3092264Sjacobs 3102264Sjacobs papiAttributeListGetInteger(j->attributes, NULL, 3118569SJonathan.Ca@Sun.COM "job-id", &id); 3122264Sjacobs /* send each document */ 3132264Sjacobs for (i = 0; ((result == PAPI_OK) && (files[i] != NULL)); 3148569SJonathan.Ca@Sun.COM i++) 3152264Sjacobs result = send_document_uri(svc, files[i], 3168569SJonathan.Ca@Sun.COM job_attributes, 3178569SJonathan.Ca@Sun.COM printer, id, (files[i+1]?0:1), 3188569SJonathan.Ca@Sun.COM data_type); 3192264Sjacobs } 3202264Sjacobs } 3212264Sjacobs papiAttributeListFree(response); 3222264Sjacobs 3232264Sjacobs return (result); 3242264Sjacobs } 3252264Sjacobs 3262264Sjacobs papi_status_t 3272264Sjacobs papiJobSubmit(papi_service_t handle, char *printer, 3282264Sjacobs papi_attribute_t **job_attributes, 3292264Sjacobs papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) 3302264Sjacobs { 3312264Sjacobs return (internal_job_submit(handle, printer, job_attributes, 3328569SJonathan.Ca@Sun.COM job_ticket, files, job, _WITH_DATA)); 3332264Sjacobs } 3342264Sjacobs 3352264Sjacobs papi_status_t 3362264Sjacobs papiJobSubmitByReference(papi_service_t handle, char *printer, 3372264Sjacobs papi_attribute_t **job_attributes, 3382264Sjacobs papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) 3392264Sjacobs { 3402264Sjacobs return (internal_job_submit(handle, printer, job_attributes, 3418569SJonathan.Ca@Sun.COM job_ticket, files, job, _BY_REFERENCE)); 3422264Sjacobs } 3432264Sjacobs 3442264Sjacobs papi_status_t 3452264Sjacobs papiJobValidate(papi_service_t handle, char *printer, 3462264Sjacobs papi_attribute_t **job_attributes, 3472264Sjacobs papi_job_ticket_t *job_ticket, char **files, papi_job_t *job) 3482264Sjacobs { 3492264Sjacobs return (internal_job_submit(handle, printer, job_attributes, 3508569SJonathan.Ca@Sun.COM job_ticket, files, job, _VALIDATE)); 3512264Sjacobs } 3522264Sjacobs 3532264Sjacobs papi_status_t 3542264Sjacobs papiJobStreamOpen(papi_service_t handle, char *printer, 3552264Sjacobs papi_attribute_t **job_attributes, 3562264Sjacobs papi_job_ticket_t *job_ticket, papi_stream_t *stream) 3572264Sjacobs { 3582264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 3592264Sjacobs papi_attribute_t **request = NULL; 3602264Sjacobs service_t *svc = handle; 3612264Sjacobs 3622264Sjacobs if ((svc == NULL) || (printer == NULL) || (stream == NULL)) 3632264Sjacobs return (PAPI_BAD_ARGUMENT); 3642264Sjacobs 3652264Sjacobs /* if we are already connected, use that connection. */ 3662264Sjacobs if (svc->connection == NULL) 3672264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 3682264Sjacobs return (result); 3692264Sjacobs 3702264Sjacobs /* create job request */ 3712264Sjacobs populate_job_request(svc, &request, job_attributes, printer, 3728569SJonathan.Ca@Sun.COM OPID_PRINT_JOB); 3732264Sjacobs 3742264Sjacobs *stream = svc->connection; 3752264Sjacobs 3762264Sjacobs result = ipp_send_initial_request_block(svc, request, 0); 3772264Sjacobs papiAttributeListFree(request); 3782264Sjacobs 3792264Sjacobs return (result); 3802264Sjacobs } 3812264Sjacobs 3822264Sjacobs papi_status_t 3832264Sjacobs papiJobStreamWrite(papi_service_t handle, 3842264Sjacobs papi_stream_t stream, void *buffer, size_t buflen) 3852264Sjacobs { 3862264Sjacobs papi_status_t result = PAPI_OK; 3872264Sjacobs service_t *svc = handle; 3882264Sjacobs size_t rc; 3892264Sjacobs 3902264Sjacobs #ifdef DEBUG 3912264Sjacobs printf("papiJobStreamWrite(0x%8.8x, 0x%8.8x, 0x%8.8x, %d)\n", 3928569SJonathan.Ca@Sun.COM handle, stream, buffer, buflen); 3932264Sjacobs httpDumpData(stdout, "papiJobStreamWrite:", buffer, buflen); 3942264Sjacobs #endif 3952264Sjacobs 3962264Sjacobs if ((svc == NULL) || (stream == NULL) || (buffer == NULL) || 3972264Sjacobs (buflen == 0)) 3982264Sjacobs return (PAPI_BAD_ARGUMENT); 3992264Sjacobs 4002264Sjacobs while ((result == PAPI_OK) && (buflen > 0)) { 4012264Sjacobs rc = ipp_request_write(svc, buffer, buflen); 4022264Sjacobs if (rc < 0) 4032264Sjacobs result = PAPI_TEMPORARY_ERROR; 4042264Sjacobs else { 4052264Sjacobs buffer = (char *)buffer + rc; 4062264Sjacobs buflen -= rc; 4072264Sjacobs } 4082264Sjacobs } 4092264Sjacobs 4102264Sjacobs #ifdef DEBUG 4112264Sjacobs printf("papiJobStreamWrite(): %s\n", papiStatusString(result)); 4122264Sjacobs #endif 4132264Sjacobs 4142264Sjacobs return (result); 4152264Sjacobs } 4162264Sjacobs 4172264Sjacobs papi_status_t 4182264Sjacobs papiJobStreamClose(papi_service_t handle, 4192264Sjacobs papi_stream_t stream, papi_job_t *job) 4202264Sjacobs { 4212264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 4222264Sjacobs http_status_t status = HTTP_CONTINUE; 4232264Sjacobs service_t *svc = handle; 4242264Sjacobs papi_attribute_t **response = NULL; 4252264Sjacobs job_t *j = NULL; 4262264Sjacobs 4272264Sjacobs if ((svc == NULL) || (stream == NULL) || (job == NULL)) 4282264Sjacobs return (PAPI_BAD_ARGUMENT); 4292264Sjacobs 4302264Sjacobs if ((*job = j = calloc(1, sizeof (*j))) == NULL) 4312264Sjacobs return (PAPI_TEMPORARY_ERROR); 4322264Sjacobs 4332264Sjacobs (void) ipp_request_write(svc, "", 0); 4342264Sjacobs 4352264Sjacobs /* update our connection info */ 4362264Sjacobs while (status == HTTP_CONTINUE) 4372264Sjacobs status = httpUpdate(svc->connection); 4382264Sjacobs 4392264Sjacobs if (status != HTTP_OK) 4402264Sjacobs return (http_to_papi_status(status)); 4412264Sjacobs httpWait(svc->connection, 1000); 4422264Sjacobs 4432264Sjacobs /* read the IPP response */ 4442264Sjacobs result = ipp_read_message(&ipp_request_read, svc, &response, 4458569SJonathan.Ca@Sun.COM IPP_TYPE_RESPONSE); 4462264Sjacobs if (result == PAPI_OK) 4472264Sjacobs result = ipp_status_info(svc, response); 4482264Sjacobs 4492264Sjacobs if (result == PAPI_OK) { 4502264Sjacobs papi_attribute_t **op = NULL; 4512264Sjacobs 4522264Sjacobs papiAttributeListGetCollection(response, NULL, 4538569SJonathan.Ca@Sun.COM "job-attributes-group", &op); 4542264Sjacobs copy_attributes(&j->attributes, op); 4552264Sjacobs } 4562264Sjacobs papiAttributeListFree(response); 4572264Sjacobs 4582264Sjacobs return (result); 4592264Sjacobs } 4602264Sjacobs 4612264Sjacobs papi_status_t 4622264Sjacobs papiJobQuery(papi_service_t handle, char *printer, int32_t job_id, 4632264Sjacobs char **requested_attrs, 4642264Sjacobs papi_job_t *job) 4652264Sjacobs { 4662264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 4672264Sjacobs service_t *svc = handle; 4682264Sjacobs job_t *j = NULL; 4692264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 4702264Sjacobs 4712264Sjacobs if ((svc == NULL) || (printer == NULL)) 4722264Sjacobs return (PAPI_BAD_ARGUMENT); 4732264Sjacobs 4742264Sjacobs /* if we are already connected, use that connection. */ 4752264Sjacobs if (svc->connection == NULL) 4762264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 4772264Sjacobs return (result); 4782264Sjacobs 4792264Sjacobs if ((*job = j = calloc(1, sizeof (*j))) == NULL) 4802264Sjacobs return (PAPI_TEMPORARY_ERROR); 4812264Sjacobs 4822264Sjacobs ipp_initialize_request(svc, &request, OPID_GET_JOB_ATTRIBUTES); 4832264Sjacobs 4843917Sjacobs ipp_initialize_operational_attributes(svc, &op, printer, job_id); 4852264Sjacobs 4862264Sjacobs if (requested_attrs != NULL) { 4872264Sjacobs int i; 4882264Sjacobs 4892264Sjacobs for (i = 0; requested_attrs[i] != NULL; i++) 4902264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND, 4918569SJonathan.Ca@Sun.COM "requested-attributes", requested_attrs[i]); 4922264Sjacobs } 4932264Sjacobs 4942264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 4958569SJonathan.Ca@Sun.COM "operational-attributes-group", op); 4962264Sjacobs papiAttributeListFree(op); 4972264Sjacobs result = ipp_send_request(svc, request, &response); 4982264Sjacobs papiAttributeListFree(request); 4992264Sjacobs 5002264Sjacobs op = NULL; 5012264Sjacobs papiAttributeListGetCollection(response, NULL, 5028569SJonathan.Ca@Sun.COM "job-attributes-group", &op); 5032264Sjacobs copy_attributes(&j->attributes, op); 5042264Sjacobs papiAttributeListFree(response); 5052264Sjacobs 5062264Sjacobs return (result); 5072264Sjacobs } 5082264Sjacobs 5092264Sjacobs /* papiJob{Cancel|Hold|Release|Restart|Promote} are all the same */ 5102264Sjacobs static papi_status_t 5112264Sjacobs _job_cancel_hold_release_restart_promote(papi_service_t handle, 5122264Sjacobs char *printer, int32_t job_id, uint16_t type) 5132264Sjacobs { 5142264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 5152264Sjacobs service_t *svc = handle; 5162264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 5172264Sjacobs 5182264Sjacobs if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 5192264Sjacobs return (PAPI_BAD_ARGUMENT); 5202264Sjacobs 5212264Sjacobs /* if we are already connected, use that connection. */ 5222264Sjacobs if (svc->connection == NULL) 5232264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 5242264Sjacobs return (result); 5252264Sjacobs 5262264Sjacobs ipp_initialize_request(svc, &request, type); 5272264Sjacobs 5283917Sjacobs ipp_initialize_operational_attributes(svc, &op, printer, job_id); 5292264Sjacobs 5302264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 5318569SJonathan.Ca@Sun.COM "operational-attributes-group", op); 5322264Sjacobs papiAttributeListFree(op); 5332264Sjacobs result = ipp_send_request(svc, request, &response); 5342264Sjacobs papiAttributeListFree(request); 5352264Sjacobs papiAttributeListFree(response); 5362264Sjacobs 5372264Sjacobs return (result); 5382264Sjacobs } 5392264Sjacobs 5402264Sjacobs papi_status_t 5412264Sjacobs papiJobCancel(papi_service_t handle, char *printer, int32_t job_id) 5422264Sjacobs { 5432264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 5448569SJonathan.Ca@Sun.COM job_id, OPID_CANCEL_JOB)); 5452264Sjacobs } 5462264Sjacobs 5472264Sjacobs 5482264Sjacobs papi_status_t 5492264Sjacobs papiJobHold(papi_service_t handle, char *printer, int32_t job_id) 5502264Sjacobs { 5512264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 5528569SJonathan.Ca@Sun.COM job_id, OPID_HOLD_JOB)); 5532264Sjacobs } 5542264Sjacobs 5552264Sjacobs papi_status_t 5562264Sjacobs papiJobRelease(papi_service_t handle, char *printer, int32_t job_id) 5572264Sjacobs { 5582264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 5598569SJonathan.Ca@Sun.COM job_id, OPID_RELEASE_JOB)); 5602264Sjacobs } 5612264Sjacobs 5622264Sjacobs papi_status_t 5632264Sjacobs papiJobRestart(papi_service_t handle, char *printer, int32_t job_id) 5642264Sjacobs { 5652264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 5668569SJonathan.Ca@Sun.COM job_id, OPID_RESTART_JOB)); 5672264Sjacobs } 5682264Sjacobs 5692264Sjacobs papi_status_t 5702264Sjacobs papiJobPromote(papi_service_t handle, char *printer, int32_t job_id) 5712264Sjacobs { 5722264Sjacobs return (_job_cancel_hold_release_restart_promote(handle, printer, 5738569SJonathan.Ca@Sun.COM job_id, OPID_PROMOTE_JOB)); 5742264Sjacobs } 5752264Sjacobs 5762264Sjacobs papi_status_t 5772264Sjacobs papiJobMove(papi_service_t handle, char *printer, int32_t job_id, 5782264Sjacobs char *destination) 5792264Sjacobs { 5802264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 5812264Sjacobs service_t *svc = handle; 5822264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 5832264Sjacobs 5842264Sjacobs if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 5852264Sjacobs (destination == NULL)) 5862264Sjacobs return (PAPI_BAD_ARGUMENT); 5872264Sjacobs 5882264Sjacobs /* if we are already connected, use that connection. */ 5892264Sjacobs if (svc->connection == NULL) 5902264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 5912264Sjacobs return (result); 5922264Sjacobs 5932264Sjacobs ipp_initialize_request(svc, &request, OPID_CUPS_MOVE_JOB); 5942264Sjacobs 5953917Sjacobs ipp_initialize_operational_attributes(svc, &op, printer, job_id); 5962264Sjacobs 5972264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 5988569SJonathan.Ca@Sun.COM "operational-attributes-group", op); 5992264Sjacobs papiAttributeListFree(op); 6002264Sjacobs 6012264Sjacobs op = NULL; 6022264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_EXCL, 6038569SJonathan.Ca@Sun.COM "job-printer-uri", destination); 6042264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 6058569SJonathan.Ca@Sun.COM "job-attributes-group", op); 6062264Sjacobs papiAttributeListFree(op); 6072264Sjacobs 6082264Sjacobs result = ipp_send_request(svc, request, &response); 6092264Sjacobs papiAttributeListFree(request); 6102264Sjacobs papiAttributeListFree(response); 6112264Sjacobs 6122264Sjacobs return (result); 6132264Sjacobs } 6142264Sjacobs 6152264Sjacobs papi_status_t 6162264Sjacobs papiJobModify(papi_service_t handle, char *printer, int32_t job_id, 6172264Sjacobs papi_attribute_t **attributes, papi_job_t *job) 6182264Sjacobs { 6192264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 6202264Sjacobs service_t *svc = handle; 6212264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 6222264Sjacobs job_t *j = NULL; 6232264Sjacobs 6242264Sjacobs if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 6252264Sjacobs (attributes == NULL)) 6262264Sjacobs return (PAPI_BAD_ARGUMENT); 6272264Sjacobs 6282264Sjacobs if ((*job = j = calloc(1, sizeof (*j))) == NULL) 6292264Sjacobs return (PAPI_TEMPORARY_ERROR); 6302264Sjacobs 6312264Sjacobs /* if we are already connected, use that connection. */ 6322264Sjacobs if (svc->connection == NULL) 6332264Sjacobs if ((result = service_connect(svc, printer)) != PAPI_OK) 6342264Sjacobs return (result); 6352264Sjacobs 6362264Sjacobs ipp_initialize_request(svc, &request, OPID_SET_JOB_ATTRIBUTES); 6372264Sjacobs 6383917Sjacobs ipp_initialize_operational_attributes(svc, &op, printer, job_id); 6392264Sjacobs 6402264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 6418569SJonathan.Ca@Sun.COM "operational-attributes-group", op); 6422264Sjacobs papiAttributeListFree(op); 6432264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 6448569SJonathan.Ca@Sun.COM "job-attributes-group", attributes); 6452264Sjacobs result = ipp_send_request(svc, request, &response); 6462264Sjacobs papiAttributeListFree(request); 6472264Sjacobs 6482264Sjacobs op = NULL; 6492264Sjacobs papiAttributeListGetCollection(response, NULL, 6508569SJonathan.Ca@Sun.COM "job-attributes-group", &op); 6512264Sjacobs copy_attributes(&j->attributes, op); 6522264Sjacobs papiAttributeListFree(response); 6532264Sjacobs 6542264Sjacobs return (result); 6552264Sjacobs } 656