kill tsol ("Trusted Solaris") aka TX ("Trusted Extensions")
[unleashed.git] / usr / src / cmd / lp / lib / papi / job.c
blobc853fb198da5ba1834e48eb6c75f703db7fd3d69
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 /*LINTLIBRARY*/
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <libintl.h>
31 #include <pwd.h>
32 #include <sys/stat.h>
33 #include <papi_impl.h>
36 * for an older application that may have been linked with a pre-v1.0
37 * PAPI implementation.
39 papi_status_t
40 papiAttributeListAdd(papi_attribute_t ***attrs, int flags, char *name,
41 papi_attribute_value_type_t type, papi_attribute_value_t *value)
43 return (papiAttributeListAddValue(attrs, flags, name, type, value));
46 #ifdef LP_USE_PAPI_ATTR
47 static papi_status_t psm_modifyAttrsFile(papi_attribute_t **attrs, char *file);
48 static papi_status_t psm_modifyAttrsList(char *file, papi_attribute_t **attrs,
49 papi_attribute_t ***newAttrs);
50 #endif
52 int32_t
53 check_job_id(papi_service_t svc, char *printer, int32_t id)
55 papi_job_t *jobs = NULL;
56 papi_status_t status;
57 int ret = -1;
58 char *jattrs[] = { "job-id",
59 "job-id-requested", NULL };
61 status = papiPrinterListJobs(svc, printer, jattrs, PAPI_LIST_JOBS_ALL,
62 0, &jobs);
64 if (status != PAPI_OK) {
65 detailed_error(svc,
66 gettext("Failed to query service for %s: %s\n"),
67 printer, lpsched_status_string(status));
68 return (-1);
71 if (jobs != NULL) {
72 int i = 0;
74 for (i = 0; jobs[i] != NULL; i++) {
75 int32_t rid = -1;
76 int32_t jid = -1;
77 papi_attribute_t **list =
78 papiJobGetAttributeList(jobs[i]);
80 papiAttributeListGetInteger(list, NULL,
81 "job-id-requested", &rid);
82 papiAttributeListGetInteger(list, NULL,
83 "job-id", &jid);
86 * check if id matches with either rid or jid
88 if (rid == id) {
89 /* get the actual id and return it */
90 papiAttributeListGetInteger(list, NULL,
91 "job-id", &id);
92 return (id);
93 } else if (jid == id) {
94 if (rid != -1) {
96 * It is a remote lpd job.
97 * It cannot be modified based on job-id
98 * or spool number
100 return (-1);
101 } else {
103 * It is either local job or
104 * remote ipp job
106 return (id);
111 return (id);
114 void
115 papiJobFree(papi_job_t job)
117 job_t *tmp = (job_t *)job;
119 if (tmp != NULL) {
120 papiAttributeListFree(tmp->attributes);
121 free(tmp);
125 void
126 papiJobListFree(papi_job_t *jobs)
128 if (jobs != NULL) {
129 int i;
131 for (i = 0; jobs[i] != NULL; i++) {
132 papiJobFree(jobs[i]);
134 free(jobs);
138 papi_attribute_t **
139 papiJobGetAttributeList(papi_job_t job)
141 job_t *tmp = (job_t *)job;
143 if (tmp != NULL)
144 return (tmp->attributes);
146 return (NULL);
149 char *
150 papiJobGetPrinterName(papi_job_t job)
152 job_t *tmp = (job_t *)job;
153 char *result = NULL;
155 if (tmp != NULL)
156 papiAttributeListGetString(tmp->attributes, NULL,
157 "printer-name", &result);
159 return (result);
162 int32_t
163 papiJobGetId(papi_job_t job)
165 job_t *tmp = (job_t *)job;
166 int result = -1;
168 if (tmp != NULL)
169 papiAttributeListGetInteger(tmp->attributes, NULL, "job-id",
170 &result);
172 return (result);
175 static REQUEST *
176 create_request(papi_service_t svc, char *printer, papi_attribute_t **attributes)
178 REQUEST *r;
180 if ((r = calloc(1, sizeof (*r))) != NULL) {
181 char *hostname = NULL;
183 r->priority = -1;
184 r->destination = printer_name_from_uri_id(printer, -1);
186 papiAttributeListGetString(attributes, NULL,
187 "job-originating-host-name", &hostname);
189 if (hostname == NULL) {
190 char host[BUFSIZ];
192 if (gethostname(host, sizeof (host)) == 0)
193 papiAttributeListAddString(&attributes,
194 PAPI_ATTR_REPLACE,
195 "job-originating-host-name",
196 host);
199 job_attributes_to_lpsched_request(svc, r, attributes);
202 return (r);
205 static papi_status_t
206 authorized(service_t *svc, int32_t id)
208 papi_status_t result = PAPI_NOT_AUTHORIZED; /* assume the worst */
209 char file[32];
210 REQUEST *r;
212 snprintf(file, sizeof (file), "%d-0", id);
213 if ((r = getrequest(file)) != NULL) {
214 uid_t uid = getuid();
215 struct passwd *pw = NULL;
216 char *user = "intruder"; /* assume an intruder */
218 if ((pw = getpwuid(uid)) != NULL)
219 user = pw->pw_name; /* use the process owner */
221 if ((uid == 0) || (uid == 71)) { /* root/lp can forge this */
222 papi_status_t s;
223 s = papiAttributeListGetString(svc->attributes, NULL,
224 "user-name", &user);
225 if (s != PAPI_OK) /* true root/lp are almighty */
226 result = PAPI_OK;
229 if (result != PAPI_OK) {
230 if (strcmp(user, r->user) == 0)
231 result = PAPI_OK;
232 else {
234 * user and r->user might contain the
235 * host info also
237 char *token1 = strtok(r->user, "@");
238 char *token2 = strtok(NULL, "@");
239 char *token3 = strtok(user, "@");
240 char *token4 = strtok(NULL, "@");
243 * token1 and token3 contain usernames
244 * token2 and token4 contain hostnames
246 if ((token1 == NULL) || (token3 == NULL))
247 result = PAPI_NOT_AUTHORIZED;
248 else if ((token4 != NULL) &&
249 (strcmp(token4, "localhost") == 0) &&
250 (strcmp(token3, "root") == 0) ||
251 (strcmp(token3, "lp") == 0)) {
253 * root/lp user on server can
254 * cancel any requset
256 result = PAPI_OK;
257 } else if (strcmp(token1, token3) == 0) {
259 * usernames are same
260 * compare the hostnames
262 if ((token4 != NULL) &&
263 (token2 != NULL) &&
264 (strcmp(token4, "localhost") ==
265 0)) {
267 * Its server machine
269 static char host[256];
270 if (gethostname(host,
271 sizeof (host)) == 0) {
272 if ((host != NULL) &&
273 (strcmp(host,
274 token2) == 0))
275 result =
276 PAPI_OK;
279 } else if ((token4 != NULL) &&
280 (token2 != NULL) &&
281 (strcmp(token4, token2) == 0)) {
282 result = PAPI_OK;
283 } else if ((token4 == NULL) &&
284 (token2 != NULL)) {
286 * When the request is sent from
287 * client to server using ipp
288 * token4 is NULL
290 result = PAPI_OK;
296 freerequest(r);
297 } else
298 result = PAPI_NOT_FOUND;
300 return (result);
303 static papi_status_t
304 copy_file(char *from, char *to)
306 int ifd, ofd;
307 char buf[BUFSIZ];
308 int rc;
310 if ((ifd = open(from, O_RDONLY)) < 0)
311 return (PAPI_DOCUMENT_ACCESS_ERROR);
313 if ((ofd = open(to, O_WRONLY)) < 0) {
314 close(ifd);
315 return (PAPI_NOT_POSSIBLE);
318 while ((rc = read(ifd, buf, sizeof (buf))) > 0)
319 write(ofd, buf, rc);
321 close(ifd);
322 close(ofd);
324 return (PAPI_OK);
328 #ifdef LP_USE_PAPI_ATTR
330 * *****************************************************************************
332 * Description: Create a file containing all the attributes in the attribute
333 * list passed to this function.
334 * This file is then passed through lpsched and given to either
335 * a slow-filter or to the printer's interface script to process
336 * the attributes.
338 * Parameters: attrs - list of attributes and their values
339 * file - file pathname to create and put the attributes into.
341 * *****************************************************************************
344 static papi_status_t
345 psm_copy_attrsToFile(papi_attribute_t **attrs, char *file)
348 papi_status_t result = PAPI_OK;
350 if ((attrs != NULL) && (*attrs != NULL)) {
351 FILE *out = NULL;
353 if ((out = fopen(file, "w")) != NULL) {
354 papiAttributeListPrint(out, attrs, "");
355 fclose(out);
356 } else {
357 result = PAPI_NOT_POSSIBLE;
361 return (result);
362 } /* psm_copy_attrsToFile */
366 * *****************************************************************************
368 * Description: Modify the given attribute 'file' with the attributes from the
369 * 'attrs' list. Attributes already in the file will be replaced
370 * with the new value. New attributes will be added into the file.
372 * Parameters: attrs - list of attributes and their values
373 * file - file pathname to create and put the attributes into.
375 * *****************************************************************************
378 static papi_status_t
379 psm_modifyAttrsFile(papi_attribute_t **attrs, char *file)
382 papi_status_t result = PAPI_OK;
383 papi_attribute_t **newAttrs = NULL;
384 struct stat tmpBuf;
385 FILE *fd = NULL;
387 if ((attrs != NULL) && (*attrs != NULL) && (file != NULL)) {
390 * check file exist before try to modify it, if it doesn't
391 * exist assume there is an error
393 if (stat(file, &tmpBuf) == 0) {
395 * if file is currently empty just write the given
396 * attributes to the file otherwise exact the attributes
397 * from the file and modify them accordingly before
398 * writing them back to the file
400 if (tmpBuf.st_size == 0) {
401 newAttrs = (papi_attribute_t **)attrs;
403 fd = fopen(file, "w");
404 if (fd != NULL) {
405 papiAttributeListPrint(fd,
406 newAttrs, "");
407 fclose(fd);
408 } else {
409 result = PAPI_NOT_POSSIBLE;
411 } else {
412 result =
413 psm_modifyAttrsList(file, attrs, &newAttrs);
415 fd = fopen(file, "w");
416 if (fd != NULL) {
417 papiAttributeListPrint(fd,
418 newAttrs, "");
419 fclose(fd);
420 } else {
421 result = PAPI_NOT_POSSIBLE;
424 papiAttributeListFree(newAttrs);
426 } else {
427 result = PAPI_NOT_POSSIBLE;
431 return (result);
432 } /* psm_modifyAttrsFile */
436 * *****************************************************************************
438 * Description: Extracts the attributes in the given attribute 'file' and
439 * creates a new list 'newAttrs' containing the modified list of
440 * attributes.
442 * Parameters: file - pathname of file containing attributes to be modified
443 * attrs - list of attributes and their values to modify
444 * newAttrs - returns the modified list of attributes
446 * *****************************************************************************
449 static papi_status_t
450 psm_modifyAttrsList(char *file, papi_attribute_t **attrs,
451 papi_attribute_t ***newAttrs)
454 papi_status_t result = PAPI_OK;
455 papi_attribute_t *nextAttr = NULL;
456 papi_attribute_value_t **values = NULL;
457 void *iter = NULL;
458 FILE *fd = NULL;
459 register int fD = 0;
460 char aBuff[200];
461 char *a = NULL;
462 char *p = NULL;
463 int count = 0;
464 int n = 0;
466 fd = fopen(file, "r");
467 if (fd != NULL) {
468 fD = fileno(fd);
469 a = &aBuff[0];
470 p = &aBuff[0];
471 count = read(fD, &aBuff[0], sizeof (aBuff) - 1);
472 while ((result == PAPI_OK) && (count > 0)) {
473 aBuff[count+n] = '\0';
474 if (count == sizeof (aBuff) - n - 1) {
475 p = strrchr(aBuff, '\n');
476 if (p != NULL) {
477 /* terminate at last complete line */
478 *p = '\0';
481 result = papiAttributeListFromString(
482 newAttrs, PAPI_ATTR_EXCL, aBuff);
484 if (result == PAPI_OK) {
486 * handle any part lines and then read the next
487 * buffer from the file
489 n = 0;
490 if (p != a) {
491 p++; /* skip NL */
492 n = sizeof (aBuff) - 1 - (p - a);
493 strncpy(aBuff, p, n);
495 count = read(fD, &aBuff[n],
496 sizeof (aBuff) - n - 1);
497 p = &aBuff[0];
500 fclose(fd);
503 /* now modify the attribute list with the new attributes in 'attrs' */
505 nextAttr = papiAttributeListGetNext((papi_attribute_t **)attrs, &iter);
506 while ((result == PAPI_OK) && (nextAttr != NULL)) {
507 values = nextAttr->values;
509 if ((values != NULL) && (*values != NULL)) {
510 result = papiAttributeListAddValue(newAttrs,
511 PAPI_ATTR_REPLACE,
512 nextAttr->name,
513 nextAttr->type, *values);
514 values++;
517 while ((result == PAPI_OK) &&
518 (values != NULL) && (*values != NULL)) {
519 result = papiAttributeListAddValue(newAttrs,
520 PAPI_ATTR_APPEND,
521 nextAttr->name,
522 nextAttr->type, *values);
523 values++;
525 nextAttr =
526 papiAttributeListGetNext((papi_attribute_t **)attrs, &iter);
529 return (result);
530 } /* papi_modifyAttrsList() */
531 #endif
534 papi_status_t
535 papiJobSubmit(papi_service_t handle, char *printer,
536 papi_attribute_t **job_attributes,
537 papi_job_ticket_t *job_ticket,
538 char **files, papi_job_t *job)
540 papi_status_t status;
541 service_t *svc = handle;
542 struct stat statbuf;
543 job_t *j;
544 int file_no;
545 char *request_id = NULL;
546 REQUEST *request;
547 int i;
548 char *c;
549 char *tmp = NULL;
550 char lpfile[BUFSIZ];
552 if ((svc == NULL) || (printer == NULL) || (files == NULL) ||
553 (job == NULL))
554 return (PAPI_BAD_ARGUMENT);
556 if (job_ticket != NULL)
557 return (PAPI_OPERATION_NOT_SUPPORTED);
559 if (files != NULL)
560 for (file_no = 0; files[file_no] != NULL; file_no++) {
561 if (access(files[file_no], R_OK) < 0) {
562 detailed_error(svc,
563 gettext("Cannot access file: %s: %s"),
564 files[file_no], strerror(errno));
565 return (PAPI_BAD_ARGUMENT);
567 if (stat(files[file_no], &statbuf) < 0) {
568 detailed_error(svc,
569 gettext("Cannot access file: %s: %s"),
570 files[file_no], strerror(errno));
571 return (PAPI_DOCUMENT_ACCESS_ERROR);
573 if (statbuf.st_size == 0) {
574 detailed_error(svc,
575 gettext("Zero byte (empty) file: %s"),
576 files[file_no]);
577 return (PAPI_BAD_ARGUMENT);
581 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
582 return (PAPI_TEMPORARY_ERROR);
584 /* file_no + 1 for the control file (-0) */
585 status = lpsched_alloc_files(svc, file_no + 1, &request_id);
586 if (status != PAPI_OK)
587 return (status);
589 request = create_request(svc, (char *)printer,
590 (papi_attribute_t **)job_attributes);
592 for (i = 0; files[i] != NULL; i++) {
593 papi_status_t status;
594 snprintf(lpfile, sizeof (lpfile), "%s%s-%d",
595 "/var/spool/lp/temp/", request_id, i+1);
596 status = copy_file(files[i], lpfile);
597 if (status != PAPI_OK) {
598 detailed_error(svc,
599 gettext("unable to copy: %s -> %s: %s"),
600 files[i], lpfile, strerror(errno));
601 freerequest(request);
602 return (PAPI_DEVICE_ERROR);
604 addlist(&(request->file_list), lpfile);
607 #ifdef LP_USE_PAPI_ATTR
609 * store the job attributes in the PAPI job attribute file that was
610 * created by lpsched_alloc_files(), the attributes will then pass
611 * through lpsched and be given to the slow-filters and the printer's
612 * interface script to process them
614 snprintf(lpfile, sizeof (lpfile), "%s%s-%s",
615 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME);
616 status = psm_copy_attrsToFile(job_attributes, lpfile);
617 if (status != PAPI_OK) {
618 detailed_error(svc, "unable to copy attributes to file: %s: %s",
619 lpfile, strerror(errno));
620 return (PAPI_DEVICE_ERROR);
622 #endif
624 /* store the meta-data file */
625 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id);
626 if (putrequest(lpfile, request) < 0) {
627 detailed_error(svc, gettext("unable to save request: %s: %s"),
628 lpfile, strerror(errno));
629 freerequest(request);
630 return (PAPI_DEVICE_ERROR);
633 status = lpsched_commit_job(svc, lpfile, &tmp);
634 if (status != PAPI_OK) {
635 unlink(lpfile);
636 freerequest(request);
637 return (status);
640 lpsched_request_to_job_attributes(request, j);
641 freerequest(request);
643 if ((c = strrchr(tmp, '-')) != NULL)
644 c++;
645 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
646 "job-id", atoi(c));
647 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
648 "job-uri", tmp);
650 return (PAPI_OK);
653 papi_status_t
654 papiJobSubmitByReference(papi_service_t handle, char *printer,
655 papi_attribute_t **job_attributes,
656 papi_job_ticket_t *job_ticket,
657 char **files, papi_job_t *job)
659 service_t *svc = handle;
660 struct stat statbuf;
661 job_t *j;
662 int file_no;
663 short status;
664 char *request_id = NULL;
665 REQUEST *request;
666 char *c;
667 char *tmp = NULL;
668 char lpfile[BUFSIZ];
669 char **file_list = NULL;
671 if ((svc == NULL) || (printer == NULL) || (files == NULL) ||
672 (job == NULL))
673 return (PAPI_BAD_ARGUMENT);
675 if (job_ticket != NULL)
676 return (PAPI_OPERATION_NOT_SUPPORTED);
678 if (files != NULL)
679 for (file_no = 0; files[file_no] != NULL; file_no++) {
680 if (access(files[file_no], R_OK) < 0) {
681 detailed_error(svc,
682 gettext("Cannot access file: %s: %s"),
683 files[file_no], strerror(errno));
684 return (PAPI_DOCUMENT_ACCESS_ERROR);
686 if (stat(files[file_no], &statbuf) < 0) {
687 detailed_error(svc,
688 gettext("Cannot access file: %s: %s"),
689 files[file_no], strerror(errno));
690 return (PAPI_DOCUMENT_ACCESS_ERROR);
692 if (statbuf.st_size == 0) {
693 detailed_error(svc,
694 gettext("Zero byte (empty) file: %s"),
695 files[file_no]);
696 return (PAPI_BAD_ARGUMENT);
699 if (files[file_no][0] != '/') {
700 char path[MAXPATHLEN];
702 if (getcwd(path, sizeof (path)) == NULL) {
703 detailed_error(svc, gettext(
704 "getcwd for file: %s: %s"),
705 files[file_no],
706 strerror(errno));
707 return (PAPI_DOCUMENT_ACCESS_ERROR);
709 strlcat(path, "/", sizeof (path));
710 if (strlcat(path, files[file_no], sizeof (path))
711 >= sizeof (path)) {
712 detailed_error(svc, gettext(
713 "pathname too long: %s"),
714 files[file_no]);
715 return (PAPI_DOCUMENT_ACCESS_ERROR);
717 addlist(&file_list, path);
718 } else
719 addlist(&file_list, (char *)files[file_no]);
722 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
723 return (PAPI_TEMPORARY_ERROR);
725 /* 1 for the control file (-0) */
726 status = lpsched_alloc_files(svc, 1, &request_id);
727 if (status != PAPI_OK)
728 return (status);
730 request = create_request(svc, (char *)printer,
731 (papi_attribute_t **)job_attributes);
732 request->file_list = file_list;
734 #ifdef LP_USE_PAPI_ATTR
736 * store the job attributes in the PAPI job attribute file that was
737 * created by lpsched_alloc_files(), the attributes will then pass
738 * through lpsched and be given to the slow-filters and the printer's
739 * interface script to process them
741 snprintf(lpfile, sizeof (lpfile), "%s%s-%s",
742 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME);
743 status = psm_copy_attrsToFile(job_attributes, lpfile);
744 if (status != PAPI_OK) {
745 detailed_error(svc, "unable to copy attributes to file: %s: %s",
746 lpfile, strerror(errno));
747 return (PAPI_DEVICE_ERROR);
749 #endif
751 /* store the meta-data file */
752 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id);
753 if (putrequest(lpfile, request) < 0) {
754 detailed_error(svc, gettext("unable to save request: %s: %s"),
755 lpfile, strerror(errno));
756 freerequest(request);
757 return (PAPI_DEVICE_ERROR);
760 status = lpsched_commit_job(svc, lpfile, &tmp);
761 if (status != PAPI_OK) {
762 unlink(lpfile);
763 freerequest(request);
764 return (status);
767 lpsched_request_to_job_attributes(request, j);
769 freerequest(request);
771 if ((c = strrchr(tmp, '-')) != NULL)
772 c++;
773 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
774 "job-id", atoi(c));
775 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
776 "job-uri", tmp);
778 return (PAPI_OK);
781 papi_status_t
782 papiJobValidate(papi_service_t handle, char *printer,
783 papi_attribute_t **job_attributes,
784 papi_job_ticket_t *job_ticket,
785 char **files, papi_job_t *job)
787 papi_status_t status;
788 papi_attribute_t **attributes = NULL;
789 int i;
791 papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE,
792 "job-hold-until", "indefinite");
793 for (i = 0; job_attributes[i]; i++)
794 list_append(&attributes, job_attributes[i]);
796 status = papiJobSubmitByReference(handle, printer,
797 (papi_attribute_t **)attributes,
798 job_ticket, files, job);
799 if (status == PAPI_OK) {
800 int id = papiJobGetId(*job);
802 if (id != -1)
803 papiJobCancel(handle, printer, id);
806 attributes[1] = NULL; /* after attr[0], they are in another list */
807 papiAttributeListFree(attributes);
809 return (status);
812 papi_status_t
813 papiJobStreamOpen(papi_service_t handle, char *printer,
814 papi_attribute_t **job_attributes,
815 papi_job_ticket_t *job_ticket, papi_stream_t *stream)
817 papi_status_t status;
818 service_t *svc = handle;
819 job_stream_t *s = NULL;
820 char *request_id = NULL;
821 char lpfile[BUFSIZ];
823 if ((svc == NULL) || (printer == NULL) || (stream == NULL))
824 return (PAPI_BAD_ARGUMENT);
826 if (job_ticket != NULL)
827 return (PAPI_OPERATION_NOT_SUPPORTED);
829 if ((*stream = s = calloc(1, sizeof (*s))) == NULL)
830 return (PAPI_TEMPORARY_ERROR);
832 /* 1 for data, 1 for the meta-data (-0) */
833 status = lpsched_alloc_files(svc, 2, &request_id);
834 if (status != PAPI_OK)
835 return (status);
837 papiAttributeListAddString(&job_attributes, PAPI_ATTR_EXCL,
838 "job-name", "standard input");
840 s->request = create_request(svc, (char *)printer,
841 (papi_attribute_t **)job_attributes);
842 snprintf(lpfile, sizeof (lpfile), "/var/spool/lp/temp/%s-1",
843 request_id);
844 s->fd = open(lpfile, O_WRONLY);
845 addlist(&(s->request->file_list), lpfile);
847 #ifdef LP_USE_PAPI_ATTR
849 * store the job attributes in the PAPI job attribute file that was
850 * created by lpsched_alloc_files(), the attributes will then pass
851 * through lpsched and be given to the slow-filters and the printer's
852 * interface script to process them
854 snprintf(lpfile, sizeof (lpfile), "%s%s-%s",
855 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME);
856 status = psm_copy_attrsToFile(job_attributes, lpfile);
857 if (status != PAPI_OK) {
858 detailed_error(svc, "unable to copy attributes to file: %s: %s",
859 lpfile, strerror(errno));
860 close(s->fd);
861 free(s);
862 return (PAPI_DEVICE_ERROR);
864 #endif
866 /* store the meta-data file */
867 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id);
868 s->meta_data_file = strdup(lpfile);
869 if (putrequest(lpfile, s->request) < 0) {
870 detailed_error(svc, gettext("unable to save request: %s: %s"),
871 lpfile, strerror(errno));
872 s->request = NULL;
873 return (PAPI_DEVICE_ERROR);
876 return (PAPI_OK);
879 papi_status_t
880 papiJobStreamWrite(papi_service_t handle,
881 papi_stream_t stream, void *buffer, size_t buflen)
883 service_t *svc = handle;
884 job_stream_t *s = stream;
886 if ((svc == NULL) || (stream == NULL) || (buffer == NULL))
887 return (PAPI_BAD_ARGUMENT);
889 if (write(s->fd, buffer, buflen) != buflen)
890 return (PAPI_DEVICE_ERROR);
892 return (PAPI_OK);
894 papi_status_t
895 papiJobStreamClose(papi_service_t handle,
896 papi_stream_t stream, papi_job_t *job)
898 papi_status_t status = PAPI_OK;
899 service_t *svc = handle;
900 job_stream_t *s = stream;
901 job_t *j = NULL;
902 char *tmp = NULL, *c;
904 if ((svc == NULL) || (stream == NULL) || (job == NULL))
905 return (PAPI_BAD_ARGUMENT);
907 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
908 return (PAPI_TEMPORARY_ERROR);
910 close(s->fd);
912 lpsched_request_to_job_attributes(s->request, j);
914 if (s->meta_data_file != NULL) {
915 status = lpsched_commit_job(svc, s->meta_data_file, &tmp);
916 if (status != PAPI_OK) {
917 unlink(s->meta_data_file);
918 return (status);
920 if ((c = strrchr(tmp, '-')) != NULL)
921 c++;
922 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
923 "job-id", atoi(c));
924 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
925 "job-uri", tmp);
926 free(s->meta_data_file);
928 freerequest(s->request);
929 free(s);
931 return (PAPI_OK);
934 papi_status_t
935 papiJobQuery(papi_service_t handle, char *printer, int32_t job_id,
936 char **requested_attrs,
937 papi_job_t *job)
939 service_t *svc = handle;
940 job_t *j;
941 char *dest;
942 char req_id[32];
943 short rc;
944 char *form = NULL,
945 *request_id = NULL,
946 *charset = NULL,
947 *user = NULL,
948 *file = NULL;
949 time_t date = 0;
950 size_t size = 0;
951 short rank = 0,
952 state = 0;
954 if ((handle == NULL) || (printer == NULL) || (job_id < 0))
955 return (PAPI_BAD_ARGUMENT);
957 dest = printer_name_from_uri_id(printer, job_id);
958 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id);
959 free(dest);
961 rc = snd_msg(svc, S_INQUIRE_REQUEST_RANK, 0, "", "", req_id, "", "");
962 if (rc < 0)
963 return (PAPI_SERVICE_UNAVAILABLE);
965 if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &request_id,
966 &user, &size, &date, &state, &dest, &form,
967 &charset, &rank, &file) < 0) {
968 detailed_error(svc,
969 gettext("failed to read response from scheduler"));
970 return (PAPI_DEVICE_ERROR);
973 if ((request_id == NULL) || (request_id[0] == NULL))
974 return (PAPI_NOT_FOUND);
976 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
977 return (PAPI_TEMPORARY_ERROR);
979 snprintf(req_id, sizeof (req_id), "%d-0", job_id);
980 lpsched_read_job_configuration(svc, j, req_id);
982 job_status_to_attributes(j, request_id, user, size, date, state,
983 dest, form, charset, rank, file);
985 return (PAPI_OK);
988 papi_status_t
989 papiJobMove(papi_service_t handle, char *printer, int32_t job_id,
990 char *destination)
992 papi_status_t result = PAPI_OK;
993 long bits;
994 service_t *svc = handle;
995 char req_id[64];
996 char *queue;
997 char *user = NULL;
999 if ((svc == NULL) || (printer == NULL) || (job_id < 0) ||
1000 (destination == NULL))
1001 return (PAPI_BAD_ARGUMENT);
1003 queue = printer_name_from_uri_id(printer, job_id);
1004 snprintf(req_id, sizeof (req_id), "%s-%d", queue, job_id);
1005 free(queue);
1007 if (papiAttributeListGetString(svc->attributes, NULL, "user-name",
1008 &user) == PAPI_OK) {
1009 REQUEST *r = getrequest(req_id);
1011 if ((r != NULL) && (r->user != NULL) &&
1012 (strcmp(r->user, user) != 0))
1013 result = PAPI_NOT_AUTHORIZED;
1014 freerequest(r);
1017 if (result == PAPI_OK) {
1018 short status = MOK;
1019 char *dest = printer_name_from_uri_id(destination, -1);
1021 if ((snd_msg(svc, S_MOVE_REQUEST, req_id, dest) < 0) ||
1022 (rcv_msg(svc, R_MOVE_REQUEST, &status, &bits) < 0))
1023 status = MTRANSMITERR;
1025 free(dest);
1027 result = lpsched_status_to_papi_status(status);
1030 return (result);
1033 papi_status_t
1034 papiJobCancel(papi_service_t handle, char *printer, int32_t job_id)
1036 papi_status_t result = PAPI_OK;
1037 service_t *svc = handle;
1038 char req_id[64];
1039 char *dest;
1040 char *user = NULL;
1042 if ((svc == NULL) || (printer == NULL) || (job_id < 0))
1043 return (PAPI_BAD_ARGUMENT);
1045 dest = printer_name_from_uri_id(printer, job_id);
1046 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id);
1047 free(dest);
1049 if (papiAttributeListGetString(svc->attributes, NULL, "user-name",
1050 &user) == PAPI_OK) {
1051 REQUEST *r = getrequest(req_id);
1053 if ((result = authorized(handle, job_id)) != PAPI_OK)
1054 result = PAPI_NOT_AUTHORIZED;
1056 if ((r != NULL) && (r->user != NULL) &&
1057 (strcmp(r->user, user) != 0))
1058 result = PAPI_NOT_AUTHORIZED;
1059 freerequest(r);
1062 if (result == PAPI_OK) {
1063 short status = MOK;
1065 if ((snd_msg(svc, S_CANCEL_REQUEST, req_id) < 0) ||
1066 (rcv_msg(svc, R_CANCEL_REQUEST, &status) < 0))
1067 status = MTRANSMITERR;
1069 result = lpsched_status_to_papi_status(status);
1072 return (result);
1075 papi_status_t
1076 hold_release_job(papi_service_t handle, char *printer,
1077 int32_t job_id, int flag)
1079 papi_status_t status;
1080 service_t *svc = handle;
1081 REQUEST *r = NULL;
1082 char *file;
1083 char *dest;
1085 if ((svc == NULL) || (printer == NULL) || (job_id < 0))
1086 return (PAPI_BAD_ARGUMENT);
1088 if ((status = authorized(svc, job_id)) != PAPI_OK)
1089 return (status);
1091 dest = printer_name_from_uri_id(printer, job_id);
1092 status = lpsched_start_change(svc, dest, job_id, &file);
1093 if (status != PAPI_OK)
1094 return (status);
1096 if ((r = getrequest(file)) != NULL) {
1097 r->actions &= ~ACT_RESUME;
1098 switch (flag) {
1099 case 0:
1100 r->actions |= ACT_HOLD;
1101 break;
1102 case 1:
1103 r->actions |= ACT_RESUME;
1104 break;
1105 case 2:
1106 r->actions |= ACT_IMMEDIATE;
1107 break;
1109 if (putrequest(file, r) < 0) {
1110 detailed_error(svc,
1111 gettext("failed to write job: %s: %s"),
1112 file, strerror(errno));
1113 freerequest(r);
1114 return (PAPI_DEVICE_ERROR);
1116 freerequest(r);
1117 } else {
1118 detailed_error(svc, gettext("failed to read job: %s: %s"),
1119 file, strerror(errno));
1120 return (PAPI_DEVICE_ERROR);
1123 status = lpsched_end_change(svc, dest, job_id);
1125 return (status);
1128 papi_status_t
1129 papiJobHold(papi_service_t handle, char *printer, int32_t job_id)
1131 return (hold_release_job(handle, printer, job_id, 0));
1134 papi_status_t
1135 papiJobRelease(papi_service_t handle, char *printer, int32_t job_id)
1137 return (hold_release_job(handle, printer, job_id, 1));
1140 papi_status_t
1141 papiJobPromote(papi_service_t handle, char *printer, int32_t job_id)
1143 return (hold_release_job(handle, printer, job_id, 2));
1146 papi_status_t
1147 papiJobModify(papi_service_t handle, char *printer, int32_t job_id,
1148 papi_attribute_t **attributes, papi_job_t *job)
1150 papi_status_t status;
1151 job_t *j = NULL;
1152 service_t *svc = handle;
1153 char *file = NULL;
1154 char *dest;
1155 REQUEST *r = NULL;
1156 char lpfile[BUFSIZ];
1157 int32_t job_id_actual;
1159 if ((svc == NULL) || (printer == NULL) || (job_id < 0) ||
1160 (attributes == NULL))
1161 return (PAPI_BAD_ARGUMENT);
1163 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
1164 return (PAPI_TEMPORARY_ERROR);
1166 dest = printer_name_from_uri_id(printer, job_id);
1169 * job-id might be job-id-requested
1170 * If it is job-id-requested then we need to
1171 * look for corresponding job-id
1173 job_id_actual = check_job_id(svc, printer, job_id);
1175 if (job_id_actual < 0) {
1176 status = PAPI_NOT_FOUND;
1177 detailed_error(svc,
1178 "failed to initiate change for job (%s-%d): %s",
1179 dest, job_id, "no such resource");
1180 return (status);
1183 status = lpsched_start_change(svc, dest, job_id_actual, &file);
1184 if (status != PAPI_OK)
1185 return (status);
1187 if ((r = getrequest(file)) != NULL) {
1188 job_attributes_to_lpsched_request(handle, r,
1189 (papi_attribute_t **)attributes);
1190 #ifdef LP_USE_PAPI_ATTR
1192 * store the job attributes in the PAPI job attribute file
1193 * that was created by the original job request. We need to
1194 * modify the attributes in the file as per the new attributes
1196 snprintf(lpfile, sizeof (lpfile), "%s%d-%s",
1197 "/var/spool/lp/temp/", job_id_actual, LP_PAPIATTRNAME);
1198 status = psm_modifyAttrsFile(attributes, lpfile);
1199 if (status != PAPI_OK) {
1200 detailed_error(svc,
1201 "unable to modify the attributes file: %s: %s",
1202 lpfile, strerror(errno));
1203 return (PAPI_DEVICE_ERROR);
1205 #endif
1207 if (putrequest(file, r) < 0) {
1208 detailed_error(svc,
1209 gettext("failed to write job: %s: %s"),
1210 file, strerror(errno));
1211 freerequest(r);
1212 return (PAPI_DEVICE_ERROR);
1214 } else {
1215 detailed_error(svc, gettext("failed to read job: %s: %s"),
1216 file, strerror(errno));
1217 return (PAPI_DEVICE_ERROR);
1220 status = lpsched_end_change(svc, dest, job_id_actual);
1221 lpsched_request_to_job_attributes(r, j);
1223 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
1224 "job-id", job_id_actual);
1226 freerequest(r);
1228 return (status);
1232 * Extension to PAPI, a variation of this is slated for post-1.0
1234 #define DUMMY_FILE "/var/spool/lp/fifos/FIFO"
1236 papi_status_t
1237 papiJobCreate(papi_service_t handle, char *printer,
1238 papi_attribute_t **job_attributes,
1239 papi_job_ticket_t *job_ticket, papi_job_t *job)
1241 papi_status_t status;
1242 service_t *svc = handle;
1243 job_t *j = NULL;
1244 REQUEST *request;
1245 char *request_id = NULL;
1246 char *c;
1247 char *tmp = NULL;
1248 char metadata_file[MAXPATHLEN];
1250 if ((svc == NULL) || (printer == NULL) || (job == NULL))
1251 return (PAPI_BAD_ARGUMENT);
1253 if (job_ticket != NULL)
1254 return (PAPI_JOB_TICKET_NOT_SUPPORTED);
1256 if ((*job = j = calloc(1, sizeof (*j))) == NULL)
1257 return (PAPI_TEMPORARY_ERROR);
1259 /* 1 for the control file (-0) */
1260 status = lpsched_alloc_files(svc, 1, &request_id);
1261 if (status != PAPI_OK)
1262 return (status);
1264 /* convert the attributes to an lpsched REQUEST structure */
1265 request = create_request(svc, (char *)printer,
1266 (papi_attribute_t **)job_attributes);
1267 if (request == NULL)
1268 return (PAPI_TEMPORARY_ERROR);
1269 addlist(&request->file_list, DUMMY_FILE); /* add a dummy file */
1270 request->actions |= ACT_HOLD; /* hold the job */
1272 #ifdef LP_USE_PAPI_ATTR
1274 * store the job attributes in the PAPI job attribute file that was
1275 * created by lpsched_alloc_files(), the attributes will then pass
1276 * through lpsched and be given to the slow-filters and the printer's
1277 * interface script to process them
1279 snprintf(metadata_file, sizeof (metadata_file), "%s%s-%s",
1280 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME);
1281 status = psm_copy_attrsToFile(job_attributes, metadata_file);
1282 if (status != PAPI_OK) {
1283 detailed_error(svc, "unable to copy attributes to file: %s: %s",
1284 metadata_file, strerror(errno));
1285 free(request_id);
1286 return (PAPI_DEVICE_ERROR);
1288 #endif
1290 /* store the REQUEST on disk */
1291 snprintf(metadata_file, sizeof (metadata_file), "%s-0", request_id);
1292 free(request_id);
1293 if (putrequest(metadata_file, request) < 0) {
1294 detailed_error(svc, gettext("unable to save request: %s: %s"),
1295 metadata_file, strerror(errno));
1296 return (PAPI_DEVICE_ERROR);
1299 status = lpsched_commit_job(svc, metadata_file, &tmp);
1300 if (status != PAPI_OK) {
1301 unlink(metadata_file);
1302 return (status);
1305 lpsched_request_to_job_attributes(request, j);
1307 if ((c = strrchr(tmp, '-')) != NULL)
1308 c++;
1309 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE,
1310 "job-id", atoi(c));
1311 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE,
1312 "job-uri", tmp);
1314 return (PAPI_OK);
1317 papi_status_t
1318 papiJobCommit(papi_service_t handle, char *printer, int32_t id)
1320 papi_status_t status = PAPI_OK;
1321 service_t *svc = handle;
1322 REQUEST *r = NULL;
1323 char *metadata_file;
1324 char *dest;
1326 if ((svc == NULL) || (printer == NULL))
1327 return (PAPI_BAD_ARGUMENT);
1329 dest = printer_name_from_uri_id(printer, id);
1330 /* tell the scheduler that we want to change the job */
1331 status = lpsched_start_change(svc, dest, id, &metadata_file);
1332 if (status != PAPI_OK)
1333 return (status);
1335 if ((r = getrequest(metadata_file)) != NULL) {
1336 r->actions &= ~ACT_RESUME;
1337 r->actions |= ACT_RESUME;
1338 dellist(&r->file_list, DUMMY_FILE);
1340 if (putrequest(metadata_file, r) < 0) {
1341 detailed_error(svc,
1342 gettext("failed to write job: %s: %s"),
1343 metadata_file, strerror(errno));
1344 freerequest(r);
1345 return (PAPI_DEVICE_ERROR);
1347 } else {
1348 detailed_error(svc, gettext("failed to read job: %s: %s"),
1349 metadata_file, strerror(errno));
1350 return (PAPI_DEVICE_ERROR);
1353 status = lpsched_end_change(svc, dest, id);
1354 freerequest(r);
1356 return (status);
1359 papi_status_t
1360 papiJobStreamAdd(papi_service_t handle, char *printer, int32_t id,
1361 papi_stream_t *stream)
1363 papi_status_t status;
1364 service_t *svc = handle;
1365 job_stream_t *s = NULL;
1366 char *metadata_file = NULL;
1367 char *dest;
1368 char path[MAXPATHLEN];
1370 /* allocate space for the stream */
1371 if ((*stream = s = calloc(1, sizeof (*s))) == NULL)
1372 return (PAPI_TEMPORARY_ERROR);
1374 dest = printer_name_from_uri_id(printer, id);
1375 /* create/open data file (only root or lp can really do this */
1376 snprintf(path, sizeof (path), "/var/spool/lp/temp/%d-XXXXXX", id);
1377 if ((s->fd = mkstemp(path)) < 0) {
1378 detailed_error(svc, gettext("unable to create sink (%s): %s"),
1379 path, strerror(errno));
1380 free(s);
1381 return (PAPI_NOT_AUTHORIZED);
1384 /* add data file to job */
1385 status = lpsched_start_change(svc, dest, id, &metadata_file);
1386 if (status != PAPI_OK) {
1387 close(s->fd);
1388 free(s);
1389 unlink(path);
1390 return (status);
1393 if ((s->request = getrequest(metadata_file)) == NULL) {
1394 detailed_error(svc, gettext("unable to load request: %s: %s"),
1395 metadata_file, strerror(errno));
1396 close(s->fd);
1397 free(s);
1398 unlink(path);
1399 return (PAPI_NOT_POSSIBLE);
1402 addlist(&(s->request->file_list), path);
1404 if (putrequest(metadata_file, s->request) < 0) {
1405 detailed_error(svc, gettext("unable to save request: %s: %s"),
1406 metadata_file, strerror(errno));
1407 close(s->fd);
1408 free(s);
1409 unlink(path);
1410 return (PAPI_NOT_POSSIBLE);
1413 status = lpsched_end_change(svc, dest, id);
1415 if (status != PAPI_OK)
1416 return (status);
1418 return (PAPI_OK);