4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 /* $Id: job.c 148 2006-04-25 16:54:17Z njacobs $ */
36 #include <papi_impl.h>
38 #include <sys/types.h>
42 #ifndef OPID_CUPS_MOVE_JOB
43 #define OPID_CUPS_MOVE_JOB 0x400D
47 papiJobFree(papi_job_t job
)
49 job_t
*tmp
= (job_t
*)job
;
52 if (tmp
->attributes
!= NULL
)
53 papiAttributeListFree(tmp
->attributes
);
59 papiJobListFree(papi_job_t
*jobs
)
64 for (i
= 0; jobs
[i
] != NULL
; i
++)
71 papiJobGetAttributeList(papi_job_t job
)
73 papi_attribute_t
**result
= NULL
;
77 result
= j
->attributes
;
83 papiJobGetPrinterName(papi_job_t job
)
89 (void) papiAttributeListGetString(j
->attributes
, NULL
,
90 "printer-name", &result
);
96 papiJobGetId(papi_job_t job
)
102 (void) papiAttributeListGetInteger(j
->attributes
, NULL
,
109 papiJobGetJobTicket(papi_job_t job
)
111 papi_job_ticket_t
*result
= NULL
;
117 populate_job_request(service_t
*svc
, papi_attribute_t
***request
,
118 papi_attribute_t
**attributes
, char *printer
, uint16_t type
)
120 papi_attribute_t
**operational
= NULL
, **job
= NULL
;
121 static char *operational_names
[] = {
122 "job-name", "ipp-attribute-fidelity", "document-name",
123 "compression", "document-format", "document-natural-language",
124 "job-k-octets", "job-impressions", "job-media-sheets", NULL
127 /* create the base IPP request */
128 ipp_initialize_request(svc
, request
, type
);
130 /* create an operational attributes group */
131 ipp_initialize_operational_attributes(svc
, &operational
, printer
, -1);
133 /* split up the attributes into operational and job attributes */
134 split_and_copy_attributes(operational_names
, attributes
,
137 /* add the operational attributes group to the request */
138 papiAttributeListAddCollection(request
, PAPI_ATTR_REPLACE
,
139 "operational-attributes-group", operational
);
140 papiAttributeListFree(operational
);
142 /* add the job attributes group to the request */
145 * Add job-originating-host-name to attributes
146 * if not already set.
148 char *hostname
= NULL
;
150 papiAttributeListGetString(job
, NULL
,
151 "job-originating-host-name", &hostname
);
153 if (hostname
== NULL
) {
156 if (gethostname(host
, sizeof (host
)) == 0)
157 papiAttributeListAddString(&job
, PAPI_ATTR_EXCL
,
158 "job-originating-host-name", host
);
161 papiAttributeListAddCollection(request
, PAPI_ATTR_REPLACE
,
162 "job-attributes-group", job
);
163 papiAttributeListFree(job
);
168 send_document_uri(service_t
*svc
, char *file
, papi_attribute_t
**attributes
,
169 char *printer
, int32_t id
, char last
, uint16_t type
)
171 papi_status_t result
= PAPI_INTERNAL_ERROR
;
172 papi_attribute_t
**request
= NULL
, **op
= NULL
, **response
= NULL
;
174 /* create the base IPP request */
175 ipp_initialize_request(svc
, &request
, type
);
177 /* create an operational attributes group */
178 ipp_initialize_operational_attributes(svc
, &op
, printer
, id
);
180 papiAttributeListAddString(&op
, PAPI_ATTR_REPLACE
, "document-name",
182 papiAttributeListAddBoolean(&op
, PAPI_ATTR_REPLACE
, "last-document",
183 (last
? PAPI_TRUE
: PAPI_FALSE
));
184 papiAttributeListAddCollection(&request
, PAPI_ATTR_REPLACE
,
185 "operational-attributes-group", op
);
186 papiAttributeListFree(op
);
188 /* send the IPP request to the server */
189 result
= ipp_send_request_with_file(svc
, request
, &response
, file
);
190 papiAttributeListFree(request
);
191 papiAttributeListFree(response
);
196 typedef enum {_WITH_DATA
, _BY_REFERENCE
, _VALIDATE
} call_type_t
;
199 internal_job_submit(papi_service_t handle
, char *printer
,
200 papi_attribute_t
**job_attributes
,
201 papi_job_ticket_t
*job_ticket
,
202 char **files
, papi_job_t
*job
,
203 call_type_t call_type
)
205 papi_status_t result
= PAPI_INTERNAL_ERROR
;
206 service_t
*svc
= handle
;
210 uint16_t req_type
= OPID_PRINT_JOB
;
211 uint16_t data_type
= OPID_SEND_DOCUMENT
;
212 papi_attribute_t
**request
= NULL
, **response
= NULL
;
214 if ((svc
== NULL
) || (printer
== NULL
) || (job
== NULL
))
215 return (PAPI_BAD_ARGUMENT
);
219 #ifdef SOME_DAY_WE_WILL_BE_ABLE_TO_USE_URIS_FOR_JOB_DATA
221 * For the time being, this is disabled. There are a number
222 * of issues to be dealt with before we can send a URI
223 * across the network to the server. For example, the file
224 * name(s) passed in are most likely relative to the current
225 * hosts filesystem. They also most likely will require some
226 * form of authentication information to be passed with the
229 req_type
= OPID_PRINT_URI
;
230 req_type
= OPID_SEND_URI
;
234 if ((files
== NULL
) || (files
[0] == NULL
))
235 return (PAPI_BAD_ARGUMENT
);
237 if (files
[1] != NULL
) /* more than 1 file */
238 req_type
= OPID_CREATE_JOB
;
242 req_type
= OPID_VALIDATE_JOB
;
243 /* if we have files, validate access to them */
245 for (i
= 0; files
[i
] != NULL
; i
++) {
246 if (access(files
[i
], R_OK
) < 0) {
247 detailed_error(svc
, "%s: %s", files
[i
],
249 return (PAPI_DOCUMENT_ACCESS_ERROR
);
252 if (strcmp("standard input", files
[i
]) != 0) {
253 if (stat(files
[i
], &statbuf
) < 0) {
254 detailed_error(svc
, gettext(
255 "Cannot access file: %s:"
259 PAPI_DOCUMENT_ACCESS_ERROR
);
261 if (statbuf
.st_size
== 0) {
263 "Zero byte (empty) file: "
266 return (PAPI_BAD_ARGUMENT
);
275 /* if we are already connected, use that connection. */
276 if (svc
->connection
== NULL
)
277 if ((result
= service_connect(svc
, printer
)) != PAPI_OK
)
280 if ((*job
= j
= calloc(1, sizeof (*j
))) == NULL
)
281 return (PAPI_TEMPORARY_ERROR
);
284 * before creating IPP request
287 if ((files
!= NULL
) && (files
[0] != NULL
))
288 papiAttributeListAddString(&job_attributes
, PAPI_ATTR_EXCL
,
289 "job-name", files
[0]);
291 /* create IPP request */
292 populate_job_request(svc
, &request
, job_attributes
, printer
, req_type
);
296 result
= ipp_send_request_with_file(svc
, request
, &response
,
299 case OPID_CREATE_JOB
:
300 case OPID_VALIDATE_JOB
:
302 result
= ipp_send_request(svc
, request
, &response
);
305 papiAttributeListFree(request
);
307 if (result
== PAPI_OK
) {
308 papi_attribute_t
**op
= NULL
;
310 /* retrieve the job attributes */
311 papiAttributeListGetCollection(response
, NULL
,
312 "job-attributes-group", &op
);
313 copy_attributes(&j
->attributes
, op
);
315 if (req_type
== OPID_CREATE_JOB
) {
318 papiAttributeListGetInteger(j
->attributes
, NULL
,
320 /* send each document */
321 for (i
= 0; ((result
== PAPI_OK
) && (files
[i
] != NULL
));
323 result
= send_document_uri(svc
, files
[i
],
325 printer
, id
, (files
[i
+1]?0:1),
329 papiAttributeListFree(response
);
335 papiJobSubmit(papi_service_t handle
, char *printer
,
336 papi_attribute_t
**job_attributes
,
337 papi_job_ticket_t
*job_ticket
, char **files
, papi_job_t
*job
)
339 return (internal_job_submit(handle
, printer
, job_attributes
,
340 job_ticket
, files
, job
, _WITH_DATA
));
344 papiJobSubmitByReference(papi_service_t handle
, char *printer
,
345 papi_attribute_t
**job_attributes
,
346 papi_job_ticket_t
*job_ticket
, char **files
, papi_job_t
*job
)
348 return (internal_job_submit(handle
, printer
, job_attributes
,
349 job_ticket
, files
, job
, _BY_REFERENCE
));
353 papiJobValidate(papi_service_t handle
, char *printer
,
354 papi_attribute_t
**job_attributes
,
355 papi_job_ticket_t
*job_ticket
, char **files
, papi_job_t
*job
)
357 return (internal_job_submit(handle
, printer
, job_attributes
,
358 job_ticket
, files
, job
, _VALIDATE
));
362 papiJobStreamOpen(papi_service_t handle
, char *printer
,
363 papi_attribute_t
**job_attributes
,
364 papi_job_ticket_t
*job_ticket
, papi_stream_t
*stream
)
366 papi_status_t result
= PAPI_INTERNAL_ERROR
;
367 papi_attribute_t
**request
= NULL
;
368 service_t
*svc
= handle
;
370 if ((svc
== NULL
) || (printer
== NULL
) || (stream
== NULL
))
371 return (PAPI_BAD_ARGUMENT
);
373 /* if we are already connected, use that connection. */
374 if (svc
->connection
== NULL
)
375 if ((result
= service_connect(svc
, printer
)) != PAPI_OK
)
378 papiAttributeListAddString(&job_attributes
, PAPI_ATTR_EXCL
,
379 "job-name", "standard input");
381 /* create job request */
382 populate_job_request(svc
, &request
, job_attributes
, printer
,
385 *stream
= svc
->connection
;
387 result
= ipp_send_initial_request_block(svc
, request
, 0);
388 papiAttributeListFree(request
);
394 papiJobStreamWrite(papi_service_t handle
,
395 papi_stream_t stream
, void *buffer
, size_t buflen
)
397 papi_status_t result
= PAPI_OK
;
398 service_t
*svc
= handle
;
402 printf("papiJobStreamWrite(0x%8.8x, 0x%8.8x, 0x%8.8x, %d)\n",
403 handle
, stream
, buffer
, buflen
);
404 httpDumpData(stdout
, "papiJobStreamWrite:", buffer
, buflen
);
407 if ((svc
== NULL
) || (stream
== NULL
) || (buffer
== NULL
) ||
409 return (PAPI_BAD_ARGUMENT
);
411 while ((result
== PAPI_OK
) && (buflen
> 0)) {
412 rc
= ipp_request_write(svc
, buffer
, buflen
);
414 result
= PAPI_TEMPORARY_ERROR
;
416 buffer
= (char *)buffer
+ rc
;
422 printf("papiJobStreamWrite(): %s\n", papiStatusString(result
));
429 papiJobStreamClose(papi_service_t handle
,
430 papi_stream_t stream
, papi_job_t
*job
)
432 papi_status_t result
= PAPI_INTERNAL_ERROR
;
433 http_status_t status
= HTTP_CONTINUE
;
434 service_t
*svc
= handle
;
435 papi_attribute_t
**response
= NULL
;
438 if ((svc
== NULL
) || (stream
== NULL
) || (job
== NULL
))
439 return (PAPI_BAD_ARGUMENT
);
441 if ((*job
= j
= calloc(1, sizeof (*j
))) == NULL
)
442 return (PAPI_TEMPORARY_ERROR
);
444 (void) ipp_request_write(svc
, "", 0);
446 /* update our connection info */
447 while (status
== HTTP_CONTINUE
)
448 status
= httpUpdate(svc
->connection
);
450 if (status
!= HTTP_OK
)
451 return (http_to_papi_status(status
));
452 httpWait(svc
->connection
, 1000);
454 /* read the IPP response */
455 result
= ipp_read_message(&ipp_request_read
, svc
, &response
,
457 if (result
== PAPI_OK
)
458 result
= ipp_status_info(svc
, response
);
460 if (result
== PAPI_OK
) {
461 papi_attribute_t
**op
= NULL
;
463 papiAttributeListGetCollection(response
, NULL
,
464 "job-attributes-group", &op
);
465 copy_attributes(&j
->attributes
, op
);
467 papiAttributeListFree(response
);
473 papiJobQuery(papi_service_t handle
, char *printer
, int32_t job_id
,
474 char **requested_attrs
,
477 papi_status_t result
= PAPI_INTERNAL_ERROR
;
478 service_t
*svc
= handle
;
480 papi_attribute_t
**request
= NULL
, **op
= NULL
, **response
= NULL
;
482 if ((svc
== NULL
) || (printer
== NULL
))
483 return (PAPI_BAD_ARGUMENT
);
485 /* if we are already connected, use that connection. */
486 if (svc
->connection
== NULL
)
487 if ((result
= service_connect(svc
, printer
)) != PAPI_OK
)
490 if ((*job
= j
= calloc(1, sizeof (*j
))) == NULL
)
491 return (PAPI_TEMPORARY_ERROR
);
493 ipp_initialize_request(svc
, &request
, OPID_GET_JOB_ATTRIBUTES
);
495 ipp_initialize_operational_attributes(svc
, &op
, printer
, job_id
);
497 if (requested_attrs
!= NULL
) {
500 for (i
= 0; requested_attrs
[i
] != NULL
; i
++)
501 papiAttributeListAddString(&op
, PAPI_ATTR_APPEND
,
502 "requested-attributes", requested_attrs
[i
]);
505 papiAttributeListAddCollection(&request
, PAPI_ATTR_REPLACE
,
506 "operational-attributes-group", op
);
507 papiAttributeListFree(op
);
508 result
= ipp_send_request(svc
, request
, &response
);
509 papiAttributeListFree(request
);
512 papiAttributeListGetCollection(response
, NULL
,
513 "job-attributes-group", &op
);
514 copy_attributes(&j
->attributes
, op
);
515 papiAttributeListFree(response
);
520 /* papiJob{Cancel|Hold|Release|Restart|Promote} are all the same */
522 _job_cancel_hold_release_restart_promote(papi_service_t handle
,
523 char *printer
, int32_t job_id
, uint16_t type
)
525 papi_status_t result
= PAPI_INTERNAL_ERROR
;
526 service_t
*svc
= handle
;
527 papi_attribute_t
**request
= NULL
, **op
= NULL
, **response
= NULL
;
529 if ((svc
== NULL
) || (printer
== NULL
) || (job_id
< 0))
530 return (PAPI_BAD_ARGUMENT
);
532 /* if we are already connected, use that connection. */
533 if (svc
->connection
== NULL
)
534 if ((result
= service_connect(svc
, printer
)) != PAPI_OK
)
537 ipp_initialize_request(svc
, &request
, type
);
539 ipp_initialize_operational_attributes(svc
, &op
, printer
, job_id
);
541 papiAttributeListAddCollection(&request
, PAPI_ATTR_REPLACE
,
542 "operational-attributes-group", op
);
543 papiAttributeListFree(op
);
544 result
= ipp_send_request(svc
, request
, &response
);
545 papiAttributeListFree(request
);
546 papiAttributeListFree(response
);
552 papiJobCancel(papi_service_t handle
, char *printer
, int32_t job_id
)
554 return (_job_cancel_hold_release_restart_promote(handle
, printer
,
555 job_id
, OPID_CANCEL_JOB
));
560 papiJobHold(papi_service_t handle
, char *printer
, int32_t job_id
)
562 return (_job_cancel_hold_release_restart_promote(handle
, printer
,
563 job_id
, OPID_HOLD_JOB
));
567 papiJobRelease(papi_service_t handle
, char *printer
, int32_t job_id
)
569 return (_job_cancel_hold_release_restart_promote(handle
, printer
,
570 job_id
, OPID_RELEASE_JOB
));
574 papiJobRestart(papi_service_t handle
, char *printer
, int32_t job_id
)
576 return (_job_cancel_hold_release_restart_promote(handle
, printer
,
577 job_id
, OPID_RESTART_JOB
));
581 papiJobPromote(papi_service_t handle
, char *printer
, int32_t job_id
)
583 return (_job_cancel_hold_release_restart_promote(handle
, printer
,
584 job_id
, OPID_PROMOTE_JOB
));
588 papiJobMove(papi_service_t handle
, char *printer
, int32_t job_id
,
591 papi_status_t result
= PAPI_INTERNAL_ERROR
;
592 service_t
*svc
= handle
;
593 papi_attribute_t
**request
= NULL
, **op
= NULL
, **response
= NULL
;
595 if ((svc
== NULL
) || (printer
== NULL
) || (job_id
< 0) ||
596 (destination
== NULL
))
597 return (PAPI_BAD_ARGUMENT
);
599 /* if we are already connected, use that connection. */
600 if (svc
->connection
== NULL
)
601 if ((result
= service_connect(svc
, printer
)) != PAPI_OK
)
604 ipp_initialize_request(svc
, &request
, OPID_CUPS_MOVE_JOB
);
606 ipp_initialize_operational_attributes(svc
, &op
, printer
, job_id
);
608 papiAttributeListAddCollection(&request
, PAPI_ATTR_REPLACE
,
609 "operational-attributes-group", op
);
610 papiAttributeListFree(op
);
613 papiAttributeListAddString(&op
, PAPI_ATTR_EXCL
,
614 "job-printer-uri", destination
);
615 papiAttributeListAddCollection(&request
, PAPI_ATTR_REPLACE
,
616 "job-attributes-group", op
);
617 papiAttributeListFree(op
);
619 result
= ipp_send_request(svc
, request
, &response
);
620 papiAttributeListFree(request
);
621 papiAttributeListFree(response
);
627 papiJobModify(papi_service_t handle
, char *printer
, int32_t job_id
,
628 papi_attribute_t
**attributes
, papi_job_t
*job
)
630 papi_status_t result
= PAPI_INTERNAL_ERROR
;
631 service_t
*svc
= handle
;
632 papi_attribute_t
**request
= NULL
, **op
= NULL
, **response
= NULL
;
635 if ((svc
== NULL
) || (printer
== NULL
) || (job_id
< 0) ||
636 (attributes
== NULL
))
637 return (PAPI_BAD_ARGUMENT
);
639 if ((*job
= j
= calloc(1, sizeof (*j
))) == NULL
)
640 return (PAPI_TEMPORARY_ERROR
);
642 /* if we are already connected, use that connection. */
643 if (svc
->connection
== NULL
)
644 if ((result
= service_connect(svc
, printer
)) != PAPI_OK
)
647 ipp_initialize_request(svc
, &request
, OPID_SET_JOB_ATTRIBUTES
);
649 ipp_initialize_operational_attributes(svc
, &op
, printer
, job_id
);
651 papiAttributeListAddCollection(&request
, PAPI_ATTR_REPLACE
,
652 "operational-attributes-group", op
);
653 papiAttributeListFree(op
);
654 papiAttributeListAddCollection(&request
, PAPI_ATTR_REPLACE
,
655 "job-attributes-group", attributes
);
656 result
= ipp_send_request(svc
, request
, &response
);
657 papiAttributeListFree(request
);
660 papiAttributeListGetCollection(response
, NULL
,
661 "job-attributes-group", &op
);
662 copy_attributes(&j
->attributes
, op
);
663 papiAttributeListFree(response
);