/* * 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 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /*LINTLIBRARY*/ #include #include #include #include #include /* lpsched include files */ #include "lp.h" #include "requests.h" #include "printers.h" #include papi_status_t job_attributes_to_lpsched_request(papi_service_t svc, REQUEST *r, papi_attribute_t **attributes) { papi_status_t status = PAPI_OK; papi_attribute_t *attr; papi_attribute_t **unmapped = NULL; papi_attribute_t *tmp[2]; int i; char *s; char **options = NULL; char **modes = NULL; char pr_filter = 0; char *pr_title = NULL; int pr_width = -1; int pr_indent = -1; int numberUp = 0; int orientation = 0; int lower = 0; int upper = 0; char buf[256]; void *iterator = NULL; char *mapped_keys[] = { "copies", "document-format", "form", "job-class", "job-hold-until", "job-host", "job-name", "job-originating-user-name", "job-printer", "job-sheets", "lp-charset", "lp-modes", "number-up", "orienttation-requested", "page-ranges", "pr-filter", "pr-indent", "pr-title", "pr-width", "job-priority", "requesting-user-name", "job-originating-host-name", NULL }; if (attributes == NULL) return (PAPI_BAD_ARGUMENT); /* replace the current destination */ papiAttributeListGetLPString(attributes, "job-printer", &r->destination); /* set the copies. We need at least 1 */ i = r->copies; papiAttributeListGetInteger(attributes, NULL, "copies", &i); if (i <= 0) i = 1; r->copies = i; /* * set the priority. PAPI/IPP uses 1-100, lpsched use 0-39, so we * have to convert it. */ if (papiAttributeListGetInteger(attributes, NULL, "job-priority", &i) == PAPI_OK) { if ((i < 1) || (i > 100)) i = 50; i = 40 - (i / 2.5); r->priority = i; } if ((r->priority < 0) || (r->priority > 39)) r->priority = 20; /* set the requested form to print on */ papiAttributeListGetLPString(attributes, "form", &r->form); /* set the page range */ memset(tmp, NULL, sizeof (tmp)); tmp[0] = papiAttributeListFind(attributes, "page-ranges"); if (tmp[0] != NULL) { char buf[BUFSIZ]; papiAttributeListToString(tmp, " ", buf, sizeof (buf)); if ((s = strchr(buf, '=')) != NULL) r->pages = (char *)strdup(++s); } /* * set the document format, converting to old format names as * as needed. */ s = NULL; papiAttributeListGetString(attributes, NULL, "document-format", &s); if (s != NULL) r->input_type = strdup(mime_type_to_lp_type(s)); /* * If we don't have an owner, set one. */ if (r->user == NULL) { uid_t uid = getuid(); struct passwd *pw; char *user = "intruder"; char *host = NULL; char buf[256]; if ((pw = getpwuid(uid)) != NULL) user = pw->pw_name; /* default to the process owner */ if ((uid == 0) || (uid == 71)) { /* root/lp can forge this */ papiAttributeListGetString(attributes, NULL, "job-originating-host-name", &host); papiAttributeListGetString(attributes, NULL, "job-host", &host); papiAttributeListGetString(attributes, NULL, "job-originating-user-name", &user); papiAttributeListGetString(attributes, NULL, "requesting-user-name", &user); snprintf(buf, sizeof (buf), "%s%s%s", user, (host ? "@" : ""), (host ? host : "")); user = buf; } r->user = strdup(user); } /* set any held state */ s = NULL; papiAttributeListGetString(attributes, NULL, "job-hold-until", &s); if (s != NULL) { r->actions &= ~(ACT_SPECIAL); /* strip immediate/hold/resume */ if (strcmp(s, "resume") == 0) r->actions |= ACT_RESUME; else if ((strcmp(s, "immediate") == 0) || (strcmp(s, "no-hold") == 0)) r->actions |= ACT_IMMEDIATE; else if ((strcmp(s, "indefinite") == 0) || (strcmp(s, "hold") == 0)) r->actions |= ACT_HOLD; } /* set lp charset/printwheel */ papiAttributeListGetLPString(attributes, "lp-charset", &r->charset); /* legacy pr(1) filter related garbage "lpr -p" */ papiAttributeListGetBoolean(attributes, NULL, "pr-filter", &pr_filter); papiAttributeListGetString(attributes, NULL, "pr-title", &pr_title); papiAttributeListGetInteger(attributes, NULL, "pr-width", &pr_width); papiAttributeListGetInteger(attributes, NULL, "pr-indent", &pr_indent); if (pr_filter != 0) { char buf[128]; if (pr_title != NULL) { snprintf(buf, sizeof (buf), "prtitle='%s'", pr_title); appendlist(&modes, buf); } if (pr_width > 0) { snprintf(buf, sizeof (buf), "prwidth=%d", pr_width); appendlist(&modes, buf); } if (pr_indent > 0) { snprintf(buf, sizeof (buf), "indent=%d", pr_indent); appendlist(&modes, buf); } } else if ((pr_title != NULL) || (pr_width >= 0) || (pr_indent >= 0)) detailed_error(svc, gettext( "pr(1) filter options specified without enabling pr(1) filter")); /* add burst page information */ s = NULL; papiAttributeListGetString(attributes, NULL, "job-sheets", &s); if ((s != NULL) && (strcasecmp(s, "none") != 0)) { char buf[128]; char *class = NULL; char *job_name = NULL; papiAttributeListGetLPString(attributes, "job-class", &class); papiAttributeListGetLPString(attributes, "job-name", &job_name); /* burst page is enabled by default, add the title */ snprintf(buf, sizeof (buf), "%s%s%s", (job_name ? job_name : ""), (job_name && class ? "\\n#####\\n#####\\t\\t " : ""), (class ? class : "")); if (buf[0] != '\0') { if (r->title != NULL) free(r->title); r->title = strdup(buf); } } else /* burst page is disabled via lp "option" */ appendlist(&options, "nobanner"); /* Convert attribute "number-up" to mode group=n */ papiAttributeListGetInteger(attributes, NULL, "number-up", &numberUp); if ((numberUp >= 2) && ((numberUp % 2) == 0)) { snprintf(buf, sizeof (buf), "group=%d", numberUp); appendlist(&modes, buf); } /* * Convert attribute "orientation-requested" to modes * 'landscape', 'portrait', etc. */ papiAttributeListGetInteger(attributes, NULL, "orientation-requested", &orientation); if ((orientation >= 3) && (orientation <= 6)) { switch (orientation) { case 4: /* landscape */ case 5: /* reverse-landscape, use landscape instead */ appendlist(&modes, "landscape"); break; case 3: /* portrait */ case 6: /* reverse-portrait, use portrait instead */ default: appendlist(&modes, "portrait"); break; } } /* add "lp -y" modes */ attr = papiAttributeListFind(attributes, "lp-modes"); if ((attr != NULL) && (attr->type == PAPI_STRING) && (attr->values != NULL)) { int i; for (i = 0; attr->values[i] != NULL; i++) appendlist(&modes, attr->values[i]->string); } if (modes != NULL) { if (r->modes == NULL) free(r->modes); r->modes = sprintlist(modes); freelist(modes); } /* add any unconsumed attributes to the "options" list */ split_and_copy_attributes(mapped_keys, attributes, NULL, &unmapped); if (unmapped != NULL) { /* convert them to lp options */ char *buf = malloc(1024); ssize_t size = 1024; while (papiAttributeListToString(unmapped, " ", buf, size) != PAPI_OK) { size += 1024; buf = realloc(buf, size); } appendlist(&options, buf); free(buf); papiAttributeListFree(unmapped); } if (options != NULL) { if (r->options != NULL) free(r->options); r->options = sprintlist(options); freelist(options); } return (PAPI_OK); } /* * Convert REQUEST->outcome (or R_REQUEST_* state) to the equivalent * PAPI attribute representation. */ static void lpsched_request_outcome_to_attributes(papi_attribute_t ***attributes, unsigned short state) { if (attributes == NULL) return; if (state & (RS_HELD|RS_ADMINHELD)) { papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, "job-state", 0x04); /* held */ papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, "job-state-reasons", "job-hold-until-specified"); } else if (state & RS_ACTIVE) { papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, "job-state", 0x05); if (state & RS_FILTERING) papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, "job-state-reasons", "job-transforming"); else if (state & RS_PRINTING) papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, "job-state-reasons", "job-printing"); else papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, "job-state-reasons", "job-processing"); } else if (state & RS_CANCELLED) { papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, "job-state", 0x07); papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, "job-state-reasons", "job-canceled-by-user"); } else if (state & RS_PRINTED) { papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, "job-state", 0x09); papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, "job-state-reasons", "job-complete"); } else { papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, "job-state", 0x03); papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, "job-state-reasons", "job-queued"); } papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, "job-hold-until", ((state & RS_HELD) ? "indefinite" : "no-hold")); } /* * convert user[@host] to papi attributes */ static void lpsched_user_to_job_attributes(papi_attribute_t ***list, char *user) { if ((list != NULL) && (user != NULL) && (user[0] != NULL)) { char *host = strrchr(user, '@'); if (host != NULL) { *host = NULL; papiAttributeListAddString(list, PAPI_ATTR_REPLACE, "job-originating-user-name", user); papiAttributeListAddString(list, PAPI_ATTR_REPLACE, "job-originating-host-name", host + 1); *host = '@'; } else papiAttributeListAddString(list, PAPI_ATTR_REPLACE, "job-originating-user-name", user); } } /* * Convert REQUEST structure to the equivalent PAPI attribute representation. */ void lpsched_request_to_job_attributes(REQUEST *r, job_t *j) { char *tmp; int i; /* copies */ papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, "copies", r->copies); /* destination */ papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, "printer-name", r->destination); /* form */ papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, "form", r->form); /* options */ papiAttributeListFromString(&j->attributes, PAPI_ATTR_APPEND, r->options); tmp = (((r->options != NULL) && (strstr(r->options, "nobanner") != NULL)) ? "none" : "standard"); papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, "job-sheets", tmp); tmp = (((r->options != NULL) && (strstr(r->options, "duplex") != NULL)) ? "two-sized" : "one-sided"); papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, "sides", tmp); i = (((r->options != NULL) && (strstr(r->options, "landscape") != NULL)) ? 4 : 3); papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, "orientation-requested", i); /* priority (map 0-39 to 1-100) */ papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, "job-priority", (int)(100 - (r->priority * 2.5))); /* pages */ papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, "page-ranges", r->pages); /* charset */ papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, "lp-charset", r->charset); /* modes */ papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, "lp-modes", r->modes); /* title */ papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, "job-name", r->title); /* input_type */ /* user */ lpsched_user_to_job_attributes(&j->attributes, r->user); /* outcome */ lpsched_request_outcome_to_attributes(&j->attributes, r->outcome); /* constants, (should be derived from options) */ papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, "number-up", 1); papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, "multiple-document-handling", "seperate-documents-collated-copies"); } /* * Convert R_REQUEST_* results to the equivalent PAPI attribute representation. */ void job_status_to_attributes(job_t *job, char *req_id, char *user, char *slabel, size_t size, time_t date, short state, char *destination, char *form, char *charset, short rank, char *file) { char buf[BUFSIZ]; char *p; lpsched_user_to_job_attributes(&job->attributes, user); papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, "job-k-octets", size/1024); papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, "job-octets", size); if ((p = strrchr(req_id, '-')) != NULL) { papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, "job-id", atoi(++p)); } snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s/%d", destination, atoi(p)); papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, "job-uri", buf); snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s", destination); papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, "job-printer-uri", buf); papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, "job-printer-up-time", time(NULL)); papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, "output-device-assigned", destination); papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, "printer-name", destination); papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, "form", form); lpsched_request_outcome_to_attributes(&job->attributes, state); papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, "time-at-creation", date); papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, "lpsched-request-id", req_id); papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, "lp-charset", charset); papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, "lpsched-job-state", state); papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, "number-of-intervening-jobs", rank - 1); papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, "lpsched-file", file); papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_EXCL, "job-name", file); papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_EXCL, "tsol-sensitivity-label", slabel); } void lpsched_read_job_configuration(service_t *svc, job_t *j, char *file) { REQUEST *r; if ((r = getrequest(file)) == NULL) { detailed_error(svc, gettext("unable to read job data: %s"), file); return; } lpsched_request_to_job_attributes(r, j); }