| /* |
| * CDDL HEADER START |
| * |
| * The contents of this file are subject to the terms of the |
| * Common Development and Distribution License (the "License"). |
| * You may not use this file except in compliance with the License. |
| * |
| * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
| * or http://www.opensolaris.org/os/licensing. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * |
| * When distributing Covered Code, include this CDDL HEADER in each |
| * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
| * If applicable, add the following below this CDDL HEADER, with the |
| * fields enclosed by brackets "[]" replaced with your own identifying |
| * information: Portions Copyright [yyyy] [name of copyright owner] |
| * |
| * CDDL HEADER END |
| */ |
| /* |
| * Copyright 2006 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| #pragma ident "%Z%%M% %I% %E% SMI" |
| |
| /*LINTLIBRARY*/ |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <libintl.h> |
| #include <pwd.h> |
| #include <sys/stat.h> |
| #include <papi_impl.h> |
| |
| #ifdef LP_USE_PAPI_ATTR |
| static papi_status_t psm_modifyAttrsFile(const papi_attribute_t **attrs, |
| char *file); |
| static papi_status_t psm_modifyAttrsList(char *file, |
| const papi_attribute_t **attrs, papi_attribute_t ***newAttrs); |
| #endif |
| |
| |
| void |
| papiJobFree(papi_job_t job) |
| { |
| job_t *tmp = (job_t *)job; |
| |
| if (tmp != NULL) { |
| papiAttributeListFree(tmp->attributes); |
| free(tmp); |
| } |
| } |
| |
| void |
| papiJobListFree(papi_job_t *jobs) |
| { |
| if (jobs != NULL) { |
| int i; |
| |
| for (i = 0; jobs[i] != NULL; i++) { |
| papiJobFree(jobs[i]); |
| } |
| free(jobs); |
| } |
| } |
| |
| papi_attribute_t ** |
| papiJobGetAttributeList(papi_job_t job) |
| { |
| job_t *tmp = (job_t *)job; |
| |
| if (tmp != NULL) |
| return (tmp->attributes); |
| |
| return (NULL); |
| } |
| |
| char * |
| papiJobGetPrinterName(papi_job_t job) |
| { |
| job_t *tmp = (job_t *)job; |
| char *result = NULL; |
| |
| if (tmp != NULL) |
| papiAttributeListGetString(tmp->attributes, NULL, |
| "printer-name", &result); |
| |
| return (result); |
| } |
| |
| int32_t |
| papiJobGetId(papi_job_t job) |
| { |
| job_t *tmp = (job_t *)job; |
| int result = -1; |
| |
| if (tmp != NULL) |
| papiAttributeListGetInteger(tmp->attributes, NULL, "job-id", |
| &result); |
| |
| return (result); |
| } |
| |
| papi_job_ticket_t * |
| papiJobGetJobTicket(papi_job_t job) |
| { |
| return (NULL); /* NOT SUPPORTED */ |
| } |
| |
| static REQUEST * |
| create_request(papi_service_t svc, char *printer, papi_attribute_t **attributes) |
| { |
| static REQUEST r; |
| |
| memset(&r, 0, sizeof (r)); |
| r.priority = -1; |
| r.destination = printer_name_from_uri_id(printer, -1); |
| job_attributes_to_lpsched_request(svc, &r, attributes); |
| |
| return (&r); |
| } |
| |
| static papi_status_t |
| authorized(service_t *svc, int32_t id) |
| { |
| papi_status_t result = PAPI_NOT_AUTHORIZED; /* assume the worst */ |
| char file[32]; |
| REQUEST *r; |
| |
| snprintf(file, sizeof (file), "%d-0", id); |
| if ((r = getrequest(file)) != NULL) { |
| uid_t uid = getuid(); |
| struct passwd *pw = NULL; |
| char *user = "intruder"; /* assume an intruder */ |
| |
| if ((pw = getpwuid(uid)) != NULL) |
| user = pw->pw_name; /* use the process owner */ |
| |
| if ((uid == 0) || (uid == 71)) { /* root/lp can forge this */ |
| papi_status_t s; |
| s = papiAttributeListGetString(svc->attributes, NULL, |
| "user-name", &user); |
| if (s != PAPI_OK) /* true root/lp are almighty */ |
| result = PAPI_OK; |
| } |
| |
| if ((result != PAPI_OK) && (strcmp(user, r->user) == 0)) |
| result = PAPI_OK; |
| |
| freerequest(r); |
| } else |
| result = PAPI_NOT_FOUND; |
| |
| return (result); |
| } |
| |
| static papi_status_t |
| copy_file(const char *from, char *to) |
| { |
| int ifd, ofd; |
| char buf[BUFSIZ]; |
| int rc; |
| |
| if ((ifd = open(from, O_RDONLY)) < 0) |
| return (PAPI_DOCUMENT_ACCESS_ERROR); |
| |
| if ((ofd = open(to, O_WRONLY)) < 0) { |
| close(ifd); |
| return (PAPI_NOT_POSSIBLE); |
| } |
| |
| while ((rc = read(ifd, buf, sizeof (buf))) > 0) |
| write(ofd, buf, rc); |
| |
| close(ifd); |
| close(ofd); |
| |
| return (PAPI_OK); |
| } |
| |
| |
| #ifdef LP_USE_PAPI_ATTR |
| /* |
| * ***************************************************************************** |
| * |
| * Description: Create a file containing all the attributes in the attribute |
| * list passed to this function. |
| * This file is then passed through lpsched and given to either |
| * a slow-filter or to the printer's interface script to process |
| * the attributes. |
| * |
| * Parameters: attrs - list of attributes and their values |
| * file - file pathname to create and put the attributes into. |
| * |
| * ***************************************************************************** |
| */ |
| |
| static papi_status_t |
| psm_copy_attrsToFile(const papi_attribute_t **attrs, char *file) |
| |
| { |
| papi_status_t result = PAPI_OK; |
| FILE *out = NULL; |
| |
| if ((attrs != NULL) && (*attrs != NULL)) |
| { |
| out = fopen(file, "w"); |
| if (out != NULL) |
| { |
| papiAttributeListPrint( |
| out, "", (papi_attribute_t **)attrs); |
| fclose(out); |
| } |
| else |
| { |
| result = PAPI_NOT_POSSIBLE; |
| } |
| } |
| |
| return (result); |
| } /* psm_copy_attrsToFile */ |
| |
| |
| /* |
| * ***************************************************************************** |
| * |
| * Description: Modify the given attribute 'file' with the attributes from the |
| * 'attrs' list. Attributes already in the file will be replaced |
| * with the new value. New attributes will be added into the file. |
| * |
| * Parameters: attrs - list of attributes and their values |
| * file - file pathname to create and put the attributes into. |
| * |
| * ***************************************************************************** |
| */ |
| |
| static papi_status_t |
| psm_modifyAttrsFile(const papi_attribute_t **attrs, char *file) |
| |
| { |
| papi_status_t result = PAPI_OK; |
| papi_attribute_t **newAttrs = NULL; |
| struct stat tmpBuf; |
| FILE *fd = NULL; |
| |
| if ((attrs != NULL) && (*attrs != NULL) && (file != NULL)) |
| { |
| |
| /* |
| * check file exist before try to modify it, if it doesn't |
| * exist assume there is an error |
| */ |
| if (stat(file, &tmpBuf) == 0) |
| { |
| /* |
| * if file is currently empty just write the given |
| * attributes to the file otherwise exact the attributes |
| * from the file and modify them accordingly before |
| * writing them back to the file |
| */ |
| if (tmpBuf.st_size == 0) |
| { |
| printf("psm_modifyAttrsFile() @1 - empty attribute file\n"); |
| newAttrs = (papi_attribute_t **)attrs; |
| |
| fd = fopen(file, "w"); |
| if (fd != NULL) |
| { |
| papiAttributeListPrint(fd, |
| "", newAttrs); |
| fclose(fd); |
| } |
| else |
| { |
| result = PAPI_NOT_POSSIBLE; |
| } |
| } |
| else |
| { |
| printf("psm_modifyAttrsFile() @2 - modify file\n"); |
| result = |
| psm_modifyAttrsList(file, attrs, &newAttrs); |
| |
| fd = fopen(file, "w"); |
| if (fd != NULL) |
| { |
| papiAttributeListPrint(fd, |
| "", newAttrs); |
| fclose(fd); |
| } |
| else |
| { |
| result = PAPI_NOT_POSSIBLE; |
| } |
| |
| papiAttributeListFree(newAttrs); |
| } |
| } |
| else |
| { |
| result = PAPI_NOT_POSSIBLE; |
| } |
| } |
| |
| return (result); |
| } /* psm_modifyAttrsFile */ |
| |
| |
| /* |
| * ***************************************************************************** |
| * |
| * Description: Extracts the attributes in the given attribute 'file' and |
| * creates a new list 'newAttrs' containing the modified list of |
| * attributes. |
| * |
| * Parameters: file - pathname of file containing attributes to be modified |
| * attrs - list of attributes and their values to modify |
| * newAttrs - returns the modified list of attributes |
| * |
| * ***************************************************************************** |
| */ |
| |
| static papi_status_t |
| psm_modifyAttrsList(char *file, const papi_attribute_t **attrs, |
| papi_attribute_t ***newAttrs) |
| |
| { |
| papi_status_t result = PAPI_OK; |
| papi_attribute_t *nextAttr = NULL; |
| papi_attribute_value_t **values = NULL; |
| void *iter = NULL; |
| FILE *fd = NULL; |
| register int fD = 0; |
| char aBuff[200]; |
| char *a = NULL; |
| char *p = NULL; |
| int count = 0; |
| int n = 0; |
| |
| fd = fopen(file, "r"); |
| if (fd != NULL) |
| { |
| fD = fileno(fd); |
| a = &aBuff[0]; |
| p = &aBuff[0]; |
| count = read(fD, &aBuff[0], sizeof (aBuff) - 1); |
| while ((result == PAPI_OK) && (count > 0)) |
| { |
| aBuff[count+n] = '\0'; |
| if (count == sizeof (aBuff) - n - 1) |
| { |
| p = strrchr(aBuff, '\n'); |
| if (p != NULL) |
| { |
| /* terminate at last complete line */ |
| *p = '\0'; |
| } |
| } |
| printf("psm_modifyAttrsList() @3 - aBuff=\n"); |
| printf("%s\n", aBuff); |
| result = papiAttributeListFromString( |
| newAttrs, PAPI_ATTR_EXCL, aBuff); |
| printf("psm_modifyAttrsList() @4 - result=%d\n", result); |
| |
| if (result == PAPI_OK) |
| { |
| /* |
| * handle any part lines and then read the next |
| * buffer from the file |
| */ |
| n = 0; |
| if (p != a) |
| { |
| p++; /* skip NL */ |
| n = sizeof (aBuff) - 1 - (p - a); |
| strncpy(aBuff, p, n); |
| } |
| count = read(fD, &aBuff[n], |
| sizeof (aBuff) - n - 1); |
| p = &aBuff[0]; |
| } |
| } |
| fclose(fd); |
| } |
| |
| /* now modify the attribute list with the new attributes in 'attrs' */ |
| |
| nextAttr = papiAttributeListGetNext((papi_attribute_t **)attrs, &iter); |
| while ((result == PAPI_OK) && (nextAttr != NULL)) |
| { |
| values = nextAttr->values; |
| |
| if ((values != NULL) && (*values != NULL)) |
| { |
| result = papiAttributeListAdd(newAttrs, |
| PAPI_ATTR_REPLACE, |
| nextAttr->name, |
| nextAttr->type, *values); |
| values++; |
| } |
| |
| while ((result == PAPI_OK) && |
| (values != NULL) && (*values != NULL)) |
| { |
| result = papiAttributeListAdd(newAttrs, |
| PAPI_ATTR_APPEND, |
| nextAttr->name, |
| nextAttr->type, *values); |
| values++; |
| } |
| nextAttr = |
| papiAttributeListGetNext((papi_attribute_t **)attrs, &iter); |
| } |
| |
| return (result); |
| } /* papi_modifyAttrsList() */ |
| #endif |
| |
| |
| papi_status_t |
| papiJobSubmit(papi_service_t handle, const char *printer, |
| const papi_attribute_t **job_attributes, |
| const papi_job_ticket_t *job_ticket, |
| const char **files, papi_job_t *job) |
| { |
| papi_status_t status; |
| service_t *svc = handle; |
| job_t *j; |
| int file_no; |
| char *request_id = NULL; |
| REQUEST *request; |
| int i; |
| char *c; |
| char *tmp = NULL; |
| char lpfile[BUFSIZ]; |
| |
| if ((svc == NULL) || (printer == NULL) || (files == NULL) || |
| (job == NULL)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| if (job_ticket != NULL) |
| return (PAPI_OPERATION_NOT_SUPPORTED); |
| |
| if (files != NULL) |
| for (file_no = 0; files[file_no] != NULL; file_no++) |
| if (access(files[file_no], R_OK) < 0) { |
| detailed_error(svc, |
| gettext("Cannot access file: %s: %s"), |
| files[file_no], strerror(errno)); |
| return (PAPI_BAD_ARGUMENT); |
| } |
| |
| if ((*job = j = calloc(1, sizeof (*j))) == NULL) |
| return (PAPI_TEMPORARY_ERROR); |
| |
| /* file_no + 1 for the control file (-0) */ |
| status = lpsched_alloc_files(svc, file_no + 1, &request_id); |
| if (status != PAPI_OK) |
| return (status); |
| |
| request = create_request(svc, (char *)printer, |
| (papi_attribute_t **)job_attributes); |
| |
| for (i = 0; files[i] != NULL; i++) { |
| papi_status_t status; |
| snprintf(lpfile, sizeof (lpfile), "%s%s-%d", |
| "/var/spool/lp/temp/", request_id, i+1); |
| status = copy_file(files[i], lpfile); |
| if (status != PAPI_OK) { |
| detailed_error(svc, |
| gettext("unable to copy: %s -> %s: %s"), |
| files[i], lpfile, strerror(errno)); |
| freerequest(request); |
| return (PAPI_DEVICE_ERROR); |
| } |
| addlist(&(request->file_list), lpfile); |
| } |
| |
| #ifdef LP_USE_PAPI_ATTR |
| /* |
| * store the job attributes in the PAPI job attribute file that was |
| * created by lpsched_alloc_files(), the attributes will then pass |
| * through lpsched and be given to the slow-filters and the printer's |
| * interface script to process them |
| */ |
| snprintf(lpfile, sizeof (lpfile), "%s%s-%s", |
| "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); |
| status = psm_copy_attrsToFile(job_attributes, lpfile); |
| if (status != PAPI_OK) { |
| detailed_error(svc, "unable to copy attributes to file: %s: %s", |
| lpfile, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| #endif |
| |
| /* store the meta-data file */ |
| snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); |
| if (putrequest(lpfile, request) < 0) { |
| detailed_error(svc, gettext("unable to save request: %s: %s"), |
| lpfile, strerror(errno)); |
| freerequest(request); |
| return (PAPI_DEVICE_ERROR); |
| } |
| |
| status = lpsched_commit_job(svc, lpfile, &tmp); |
| if (status != PAPI_OK) { |
| unlink(lpfile); |
| freerequest(request); |
| return (status); |
| } |
| |
| lpsched_request_to_job_attributes(request, j); |
| freerequest(request); |
| |
| if ((c = strrchr(tmp, '-')) != NULL) |
| c++; |
| papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, |
| "job-id", atoi(c)); |
| papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, |
| "job-uri", tmp); |
| |
| return (PAPI_OK); |
| } |
| |
| papi_status_t |
| papiJobSubmitByReference(papi_service_t handle, const char *printer, |
| const papi_attribute_t **job_attributes, |
| const papi_job_ticket_t *job_ticket, |
| const char **files, papi_job_t *job) |
| { |
| service_t *svc = handle; |
| job_t *j; |
| int file_no; |
| short status; |
| char *request_id = NULL; |
| REQUEST *request; |
| char *c; |
| char *tmp = NULL; |
| char lpfile[BUFSIZ]; |
| char **file_list = NULL; |
| |
| if ((svc == NULL) || (printer == NULL) || (files == NULL) || |
| (job == NULL)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| if (job_ticket != NULL) |
| return (PAPI_OPERATION_NOT_SUPPORTED); |
| |
| if (files != NULL) |
| for (file_no = 0; files[file_no] != NULL; file_no++) { |
| if (access(files[file_no], R_OK) < 0) { |
| detailed_error(svc, |
| gettext("Cannot access file: %s: %s"), |
| files[file_no], strerror(errno)); |
| return (PAPI_BAD_ARGUMENT); |
| } |
| addlist(&file_list, (char *)files[file_no]); |
| } |
| |
| if ((*job = j = calloc(1, sizeof (*j))) == NULL) |
| return (PAPI_TEMPORARY_ERROR); |
| |
| /* 1 for the control file (-0) */ |
| status = lpsched_alloc_files(svc, 1, &request_id); |
| if (status != PAPI_OK) |
| return (status); |
| |
| request = create_request(svc, (char *)printer, |
| (papi_attribute_t **)job_attributes); |
| request->file_list = file_list; |
| |
| #ifdef LP_USE_PAPI_ATTR |
| /* |
| * store the job attributes in the PAPI job attribute file that was |
| * created by lpsched_alloc_files(), the attributes will then pass |
| * through lpsched and be given to the slow-filters and the printer's |
| * interface script to process them |
| */ |
| snprintf(lpfile, sizeof (lpfile), "%s%s-%s", |
| "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); |
| status = psm_copy_attrsToFile(job_attributes, lpfile); |
| if (status != PAPI_OK) { |
| detailed_error(svc, "unable to copy attributes to file: %s: %s", |
| lpfile, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| #endif |
| |
| /* store the meta-data file */ |
| snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); |
| if (putrequest(lpfile, request) < 0) { |
| detailed_error(svc, gettext("unable to save request: %s: %s"), |
| lpfile, strerror(errno)); |
| freerequest(request); |
| return (PAPI_DEVICE_ERROR); |
| } |
| |
| status = lpsched_commit_job(svc, lpfile, &tmp); |
| if (status != PAPI_OK) { |
| unlink(lpfile); |
| freerequest(request); |
| return (status); |
| } |
| |
| lpsched_request_to_job_attributes(request, j); |
| |
| freerequest(request); |
| |
| if ((c = strrchr(tmp, '-')) != NULL) |
| c++; |
| papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, |
| "job-id", atoi(c)); |
| papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, |
| "job-uri", tmp); |
| |
| return (PAPI_OK); |
| } |
| |
| papi_status_t |
| papiJobValidate(papi_service_t handle, const char *printer, |
| const papi_attribute_t **job_attributes, |
| const papi_job_ticket_t *job_ticket, |
| const char **files, papi_job_t *job) |
| { |
| papi_status_t status; |
| papi_attribute_t **attributes = NULL; |
| int i; |
| |
| papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE, |
| "job-hold-until", "hold"); |
| for (i = 0; job_attributes[i]; i++) |
| list_append(&attributes, job_attributes[i]); |
| |
| status = papiJobSubmitByReference(handle, printer, |
| (const papi_attribute_t **)attributes, |
| job_ticket, files, job); |
| if (status == PAPI_OK) { |
| int id = papiJobGetId(*job); |
| |
| if (id != -1) |
| papiJobCancel(handle, printer, id); |
| } |
| |
| attributes[1] = NULL; /* after attr[0], they are in another list */ |
| papiAttributeListFree(attributes); |
| |
| return (status); |
| } |
| |
| papi_status_t |
| papiJobStreamOpen(papi_service_t handle, const char *printer, |
| const papi_attribute_t **job_attributes, |
| const papi_job_ticket_t *job_ticket, papi_stream_t *stream) |
| { |
| papi_status_t status; |
| service_t *svc = handle; |
| job_stream_t *s = NULL; |
| char *request_id = NULL; |
| char lpfile[BUFSIZ]; |
| |
| if ((svc == NULL) || (printer == NULL) || (stream == NULL)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| if (job_ticket != NULL) |
| return (PAPI_OPERATION_NOT_SUPPORTED); |
| |
| if ((*stream = s = calloc(1, sizeof (*s))) == NULL) |
| return (PAPI_TEMPORARY_ERROR); |
| |
| /* 1 for data, 1 for the meta-data (-0) */ |
| status = lpsched_alloc_files(svc, 2, &request_id); |
| if (status != PAPI_OK) |
| return (status); |
| |
| s->request = create_request(svc, (char *)printer, |
| (papi_attribute_t **)job_attributes); |
| snprintf(lpfile, sizeof (lpfile), "/var/spool/lp/temp/%s-1", |
| request_id); |
| s->fd = open(lpfile, O_WRONLY); |
| addlist(&(s->request->file_list), lpfile); |
| |
| #ifdef LP_USE_PAPI_ATTR |
| /* |
| * store the job attributes in the PAPI job attribute file that was |
| * created by lpsched_alloc_files(), the attributes will then pass |
| * through lpsched and be given to the slow-filters and the printer's |
| * interface script to process them |
| */ |
| snprintf(lpfile, sizeof (lpfile), "%s%s-%s", |
| "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); |
| status = psm_copy_attrsToFile(job_attributes, lpfile); |
| if (status != PAPI_OK) { |
| detailed_error(svc, "unable to copy attributes to file: %s: %s", |
| lpfile, strerror(errno)); |
| close(s->fd); |
| free(s); |
| return (PAPI_DEVICE_ERROR); |
| } |
| #endif |
| |
| /* store the meta-data file */ |
| snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); |
| s->meta_data_file = strdup(lpfile); |
| if (putrequest(lpfile, s->request) < 0) { |
| detailed_error(svc, gettext("unable to save request: %s: %s"), |
| lpfile, strerror(errno)); |
| s->request = NULL; |
| return (PAPI_DEVICE_ERROR); |
| } |
| |
| return (PAPI_OK); |
| } |
| |
| papi_status_t |
| papiJobStreamWrite(papi_service_t handle, |
| papi_stream_t stream, const void *buffer, const size_t buflen) |
| { |
| service_t *svc = handle; |
| job_stream_t *s = stream; |
| |
| if ((svc == NULL) || (stream == NULL) || (buffer == NULL)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| if (write(s->fd, buffer, buflen) != buflen) |
| return (PAPI_DEVICE_ERROR); |
| |
| return (PAPI_OK); |
| } |
| papi_status_t |
| papiJobStreamClose(papi_service_t handle, |
| papi_stream_t stream, papi_job_t *job) |
| { |
| papi_status_t status = PAPI_OK; |
| service_t *svc = handle; |
| job_stream_t *s = stream; |
| job_t *j = NULL; |
| char *tmp = NULL, *c; |
| |
| if ((svc == NULL) || (stream == NULL) || (job == NULL)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| if ((*job = j = calloc(1, sizeof (*j))) == NULL) |
| return (PAPI_TEMPORARY_ERROR); |
| |
| close(s->fd); |
| |
| lpsched_request_to_job_attributes(s->request, j); |
| |
| if (s->meta_data_file != NULL) { |
| status = lpsched_commit_job(svc, s->meta_data_file, &tmp); |
| if (status != PAPI_OK) { |
| unlink(s->meta_data_file); |
| return (status); |
| } |
| if ((c = strrchr(tmp, '-')) != NULL) |
| c++; |
| papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, |
| "job-id", atoi(c)); |
| papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, |
| "job-uri", tmp); |
| free(s->meta_data_file); |
| } |
| free(s); |
| |
| return (PAPI_OK); |
| } |
| |
| papi_status_t |
| papiJobQuery(papi_service_t handle, const char *printer, const int32_t job_id, |
| const char **requested_attrs, |
| papi_job_t *job) |
| { |
| service_t *svc = handle; |
| job_t *j; |
| char *dest; |
| char req_id[32]; |
| short rc; |
| char *form = NULL, |
| *request_id = NULL, |
| *charset = NULL, |
| *user = NULL, |
| *slabel = NULL, |
| *file = NULL; |
| time_t date = 0; |
| size_t size = 0; |
| short rank = 0, |
| state = 0; |
| |
| if ((handle == NULL) || (printer == NULL) || (job_id < 0)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| dest = printer_name_from_uri_id(printer, job_id); |
| snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); |
| free(dest); |
| |
| rc = snd_msg(svc, S_INQUIRE_REQUEST_RANK, 0, "", "", req_id, "", ""); |
| if (rc < 0) |
| return (PAPI_SERVICE_UNAVAILABLE); |
| |
| if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &request_id, |
| &user, &slabel, &size, &date, &state, &dest, &form, |
| &charset, &rank, &file) < 0) { |
| detailed_error(svc, |
| gettext("failed to read response from scheduler")); |
| return (PAPI_DEVICE_ERROR); |
| } |
| |
| if ((request_id == NULL) || (request_id[0] == NULL)) |
| return (PAPI_NOT_FOUND); |
| |
| if ((*job = j = calloc(1, sizeof (*j))) == NULL) |
| return (PAPI_TEMPORARY_ERROR); |
| |
| job_status_to_attributes(j, request_id, user, slabel, size, date, state, |
| dest, form, charset, rank, file); |
| |
| snprintf(req_id, sizeof (req_id), "%d-0", job_id); |
| lpsched_read_job_configuration(svc, j, req_id); |
| |
| return (PAPI_OK); |
| } |
| |
| papi_status_t |
| papiJobCancel(papi_service_t handle, const char *printer, const int32_t job_id) |
| { |
| papi_status_t result = PAPI_OK; |
| service_t *svc = handle; |
| char req_id[64]; |
| char *dest; |
| char *user = NULL; |
| |
| if ((svc == NULL) || (printer == NULL) || (job_id < 0)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| dest = printer_name_from_uri_id(printer, job_id); |
| snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); |
| free(dest); |
| |
| if (papiAttributeListGetString(svc->attributes, NULL, "user-name", |
| &user) == PAPI_OK) { |
| REQUEST *r = getrequest(req_id); |
| |
| if ((r != NULL) && (strcmp(r->user, user) != 0)) |
| result = PAPI_NOT_AUTHORIZED; |
| freerequest(r); |
| } |
| |
| if (result == PAPI_OK) { |
| short status = MOK; |
| |
| if ((snd_msg(svc, S_CANCEL_REQUEST, req_id) < 0) || |
| (rcv_msg(svc, R_CANCEL_REQUEST, &status) < 0)) |
| status = MTRANSMITERR; |
| |
| result = lpsched_status_to_papi_status(status); |
| } |
| |
| return (result); |
| } |
| |
| papi_status_t |
| hold_release_job(papi_service_t handle, const char *printer, |
| const int32_t job_id, int flag) |
| { |
| papi_status_t status; |
| service_t *svc = handle; |
| REQUEST *r = NULL; |
| char *file; |
| char *dest; |
| |
| if ((svc == NULL) || (printer == NULL) || (job_id < 0)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| if ((status = authorized(svc, job_id)) != PAPI_OK) |
| return (status); |
| |
| dest = printer_name_from_uri_id(printer, job_id); |
| status = lpsched_start_change(svc, dest, job_id, &file); |
| if (status != PAPI_OK) |
| return (status); |
| |
| if ((r = getrequest(file)) != NULL) { |
| r->actions &= ~ACT_RESUME; |
| if (flag == 0) |
| r->actions |= ACT_HOLD; |
| else |
| r->actions |= ACT_RESUME; |
| if (putrequest(file, r) < 0) { |
| detailed_error(svc, |
| gettext("failed to write job: %s: %s"), |
| file, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| } else { |
| detailed_error(svc, gettext("failed to read job: %s: %s"), |
| file, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| |
| status = lpsched_end_change(svc, dest, job_id); |
| freerequest(r); |
| free(dest); |
| |
| return (status); |
| } |
| |
| papi_status_t |
| papiJobHold(papi_service_t handle, const char *printer, const int32_t job_id, |
| const char *hold_until, const time_t *hold_until_time) |
| { |
| return (hold_release_job(handle, printer, job_id, 0)); |
| } |
| |
| papi_status_t |
| papiJobRelease(papi_service_t handle, const char *printer, const int32_t job_id) |
| { |
| return (hold_release_job(handle, printer, job_id, 1)); |
| } |
| |
| papi_status_t |
| papiJobRestart(papi_service_t handle, const char *printer, const int32_t job_id) |
| { |
| return (PAPI_OPERATION_NOT_SUPPORTED); |
| } |
| |
| papi_status_t |
| papiJobModify(papi_service_t handle, const char *printer, const int32_t job_id, |
| const papi_attribute_t **attributes, papi_job_t *job) |
| { |
| papi_status_t status; |
| job_t *j = NULL; |
| service_t *svc = handle; |
| char *file = NULL; |
| char *dest; |
| REQUEST *r = NULL; |
| char lpfile[BUFSIZ]; |
| |
| if ((svc == NULL) || (printer == NULL) || (job_id < 0) || |
| (attributes == NULL)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| if ((status = authorized(svc, job_id)) != PAPI_OK) |
| return (status); |
| |
| if ((*job = j = calloc(1, sizeof (*j))) == NULL) |
| return (PAPI_TEMPORARY_ERROR); |
| |
| dest = printer_name_from_uri_id(printer, job_id); |
| status = lpsched_start_change(svc, dest, job_id, &file); |
| if (status != PAPI_OK) |
| return (status); |
| |
| if ((r = getrequest(file)) != NULL) { |
| job_attributes_to_lpsched_request(handle, r, |
| (papi_attribute_t **)attributes); |
| #ifdef LP_USE_PAPI_ATTR |
| /* |
| * store the job attributes in the PAPI job attribute file |
| * that was created by the origonal job request. We need to |
| * modify the attributes in the file as per the new attributes |
| */ |
| snprintf(lpfile, sizeof (lpfile), "%s%d-%s", |
| "/var/spool/lp/temp/", job_id, LP_PAPIATTRNAME); |
| status = psm_modifyAttrsFile(attributes, lpfile); |
| if (status != PAPI_OK) { |
| detailed_error(svc, |
| "unable to modify the attributes file: %s: %s", |
| lpfile, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| #endif |
| |
| if (putrequest(file, r) < 0) { |
| detailed_error(svc, |
| gettext("failed to write job: %s: %s"), |
| file, strerror(errno)); |
| freerequest(r); |
| return (PAPI_DEVICE_ERROR); |
| } |
| } else { |
| detailed_error(svc, gettext("failed to read job: %s: %s"), |
| file, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| |
| status = lpsched_end_change(svc, dest, job_id); |
| lpsched_request_to_job_attributes(r, j); |
| freerequest(r); |
| free(dest); |
| |
| return (status); |
| } |
| |
| /* |
| * Extension to PAPI, a variation of this is slated for post-1.0 |
| */ |
| #define DUMMY_FILE "/var/spool/lp/fifos/FIFO" |
| |
| papi_status_t |
| papiJobCreate(papi_service_t handle, const char *printer, |
| const papi_attribute_t **job_attributes, |
| const papi_job_ticket_t *job_ticket, papi_job_t *job) |
| { |
| papi_status_t status; |
| service_t *svc = handle; |
| job_t *j = NULL; |
| REQUEST *request; |
| char *request_id = NULL; |
| char *c; |
| char *tmp = NULL; |
| char metadata_file[MAXPATHLEN]; |
| |
| if ((svc == NULL) || (printer == NULL) || (job == NULL)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| if (job_ticket != NULL) |
| return (PAPI_JOB_TICKET_NOT_SUPPORTED); |
| |
| if ((*job = j = calloc(1, sizeof (*j))) == NULL) |
| return (PAPI_TEMPORARY_ERROR); |
| |
| /* 1 for the control file (-0) */ |
| status = lpsched_alloc_files(svc, 1, &request_id); |
| if (status != PAPI_OK) |
| return (status); |
| |
| /* convert the attributes to an lpsched REQUEST structure */ |
| request = create_request(svc, (char *)printer, |
| (papi_attribute_t **)job_attributes); |
| addlist(&request->file_list, DUMMY_FILE); /* add a dummy file */ |
| request->actions |= ACT_HOLD; /* hold the job */ |
| |
| #ifdef LP_USE_PAPI_ATTR |
| /* |
| * store the job attributes in the PAPI job attribute file that was |
| * created by lpsched_alloc_files(), the attributes will then pass |
| * through lpsched and be given to the slow-filters and the printer's |
| * interface script to process them |
| */ |
| snprintf(metadata_file, sizeof (metadata_file), "%s%s-%s", |
| "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); |
| status = psm_copy_attrsToFile(job_attributes, metadata_file); |
| if (status != PAPI_OK) { |
| detailed_error(svc, "unable to copy attributes to file: %s: %s", |
| metadata_file, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| #endif |
| |
| /* store the REQUEST on disk */ |
| snprintf(metadata_file, sizeof (metadata_file), "%s-0", request_id); |
| if (putrequest(metadata_file, request) < 0) { |
| detailed_error(svc, gettext("unable to save request: %s: %s"), |
| metadata_file, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| |
| status = lpsched_commit_job(svc, metadata_file, &tmp); |
| if (status != PAPI_OK) { |
| unlink(metadata_file); |
| return (status); |
| } |
| |
| lpsched_request_to_job_attributes(request, j); |
| |
| if ((c = strrchr(tmp, '-')) != NULL) |
| c++; |
| papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, |
| "job-id", atoi(c)); |
| papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, |
| "job-uri", tmp); |
| |
| return (PAPI_OK); |
| } |
| |
| papi_status_t |
| papiJobCommit(papi_service_t handle, char *printer, int32_t id) |
| { |
| papi_status_t status = PAPI_OK; |
| service_t *svc = handle; |
| REQUEST *r = NULL; |
| char *metadata_file; |
| char *dest; |
| |
| if ((svc == NULL) || (printer == NULL)) |
| return (PAPI_BAD_ARGUMENT); |
| |
| dest = printer_name_from_uri_id(printer, id); |
| /* tell the scheduler that we want to change the job */ |
| status = lpsched_start_change(svc, dest, id, &metadata_file); |
| if (status != PAPI_OK) |
| return (status); |
| |
| if ((r = getrequest(metadata_file)) != NULL) { |
| r->actions &= ~ACT_RESUME; |
| r->actions |= ACT_RESUME; |
| dellist(&r->file_list, DUMMY_FILE); |
| |
| if (putrequest(metadata_file, r) < 0) { |
| detailed_error(svc, |
| gettext("failed to write job: %s: %s"), |
| metadata_file, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| } else { |
| detailed_error(svc, gettext("failed to read job: %s: %s"), |
| metadata_file, strerror(errno)); |
| return (PAPI_DEVICE_ERROR); |
| } |
| |
| status = lpsched_end_change(svc, dest, id); |
| freerequest(r); |
| free(dest); |
| |
| return (status); |
| } |
| |
| papi_status_t |
| papiJobStreamAdd(papi_service_t handle, char *printer, int32_t id, |
| papi_stream_t *stream) |
| { |
| papi_status_t status; |
| service_t *svc = handle; |
| job_stream_t *s = NULL; |
| char *metadata_file = NULL; |
| char *dest; |
| char path[MAXPATHLEN]; |
| |
| /* allocate space for the stream */ |
| if ((*stream = s = calloc(1, sizeof (*s))) == NULL) |
| return (PAPI_TEMPORARY_ERROR); |
| |
| dest = printer_name_from_uri_id(printer, id); |
| /* create/open data file (only root or lp can really do this */ |
| snprintf(path, sizeof (path), "/var/spool/lp/temp/%d-XXXXXX", id); |
| if ((s->fd = mkstemp(path)) < 0) { |
| detailed_error(svc, gettext("unable to create sink (%s): %s"), |
| path, strerror(errno)); |
| free(s); |
| return (PAPI_NOT_AUTHORIZED); |
| } |
| |
| /* add data file to job */ |
| status = lpsched_start_change(svc, dest, id, &metadata_file); |
| if (status != PAPI_OK) { |
| close(s->fd); |
| free(s); |
| unlink(path); |
| return (status); |
| } |
| |
| if ((s->request = getrequest(metadata_file)) == NULL) { |
| detailed_error(svc, gettext("unable to load request: %s: %s"), |
| metadata_file, strerror(errno)); |
| close(s->fd); |
| free(s); |
| unlink(path); |
| return (PAPI_NOT_POSSIBLE); |
| } |
| |
| addlist(&(s->request->file_list), path); |
| |
| if (putrequest(metadata_file, s->request) < 0) { |
| detailed_error(svc, gettext("unable to save request: %s: %s"), |
| metadata_file, strerror(errno)); |
| close(s->fd); |
| free(s); |
| unlink(path); |
| return (PAPI_NOT_POSSIBLE); |
| } |
| |
| status = lpsched_end_change(svc, dest, id); |
| free(dest); |
| |
| if (status != PAPI_OK) |
| return (status); |
| |
| return (PAPI_OK); |
| } |