1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /*LINTLIBRARY*/ 29 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 #include <libintl.h> 34 #include <pwd.h> 35 36 /* lpsched include files */ 37 #include "lp.h" 38 #include "requests.h" 39 #include "printers.h" 40 41 #include <papi_impl.h> 42 43 papi_status_t 44 job_attributes_to_lpsched_request(papi_service_t svc, REQUEST *r, 45 papi_attribute_t **attributes) 46 { 47 papi_status_t status = PAPI_OK; 48 papi_attribute_t *attr; 49 papi_attribute_t **unmapped = NULL; 50 int i; 51 char *s; 52 53 char **options = NULL; 54 char **modes = NULL; 55 56 char pr_filter = 0; 57 char *pr_title = NULL; 58 int pr_width = -1; 59 int pr_indent = -1; 60 int numberUp = 0; 61 int orientation = 0; 62 int lower = 0; 63 int upper = 0; 64 char buf[256]; 65 void *iterator = NULL; 66 char *mapped_keys[] = { "copies", "document-format", "form", 67 "job-class", "job-hold-until", "job-host", "job-name", 68 "job-originating-user-name", "job-printer", 69 "job-sheets", "lp-charset", "lp-modes", "number-up", 70 "orienttation-requested", "page-ranges", "pr-filter", 71 "pr-indent", "pr-title", "pr-width", "priority", 72 "requesting-user-name", NULL }; 73 74 if (attributes == NULL) 75 return (PAPI_BAD_ARGUMENT); 76 77 /* replace the current destination */ 78 papiAttributeListGetLPString(attributes, 79 "job-printer", &r->destination); 80 81 /* set the copies. We need at least 1 */ 82 i = r->copies; 83 papiAttributeListGetInteger(attributes, NULL, "copies", &i); 84 if (i <= 0) 85 i = 1; 86 r->copies = i; 87 88 /* 89 * set the priority. PAPI/IPP uses 1-100, lpsched use 0-39, so we 90 * have to convert it. 91 */ 92 if (papiAttributeListGetInteger(attributes, NULL, "priority", &i) 93 == PAPI_OK) { 94 if ((i < 1) || (i > 100)) 95 i = 50; 96 i = (i + 1) / 2.5; 97 r->priority = i; 98 } 99 if ((r->priority < 0) || (r->priority > 39)) 100 r->priority = 20; 101 102 /* set the requested form to print on */ 103 papiAttributeListGetLPString(attributes, "form", &r->form); 104 105 /* set the page range */ 106 #ifndef LP_USE_PAPI_ATTR 107 papiAttributeListGetLPString(attributes, "page-ranges", &r->pages); 108 #else 109 for (status = papiAttributeListGetRange(attributes, &iterator, 110 "page-ranges", &lower, &upper); 111 status == PAPI_OK; 112 status = papiAttributeListGetRange(attributes, &iterator, 113 "page-ranges", &lower, &upper)) { 114 if (r->pages != NULL) { 115 snprintf(buf, sizeof (buf), "%s,%d-%d", 116 r->pages, lower, upper); 117 free(r->pages); 118 } else 119 snprintf(buf, sizeof (buf), "%d-%d", lower, upper); 120 r->pages = (char *)strdup(buf); 121 } 122 #endif 123 124 /* 125 * set the document format, converting to old format names as 126 * as needed. 127 */ 128 s = NULL; 129 papiAttributeListGetString(attributes, NULL, "document-format", &s); 130 if (s != NULL) 131 r->input_type = strdup(mime_type_to_lp_type(s)); 132 133 134 /* 135 * If we don't have an owner, set one. 136 */ 137 if (r->user == NULL) { 138 uid_t uid = getuid(); 139 struct passwd *pw; 140 char *user = "intruder"; 141 char *host = NULL; 142 char buf[256]; 143 144 if ((pw = getpwuid(uid)) != NULL) 145 user = pw->pw_name; /* default to the process owner */ 146 147 if ((uid == 0) || (uid == 71)) { /* root/lp can forge this */ 148 papiAttributeListGetString(attributes, NULL, 149 "job-host", &host); 150 papiAttributeListGetString(attributes, NULL, 151 "job-originating-user-name", &user); 152 papiAttributeListGetString(attributes, NULL, 153 "requesting-user-name", &user); 154 155 snprintf(buf, sizeof (buf), "%s%s%s", user, 156 (host ? "@" : ""), (host ? host : "")); 157 user = buf; 158 } 159 160 r->user = strdup(user); 161 } 162 163 /* set any held state */ 164 s = NULL; 165 papiAttributeListGetString(attributes, NULL, "job-hold-until", &s); 166 if (s != NULL) { 167 if (strcmp(s, "immediate") == 0) 168 r->actions |= ACT_IMMEDIATE; 169 else if ((strcmp(s, "resume") == 0) || 170 (strcmp(s, "no-hold") == 0)) 171 r->actions |= ACT_RESUME; 172 else if ((strcmp(s, "hold") == 0) || 173 (strcmp(s, "indefinite") == 0)) 174 r->actions |= ACT_HOLD; 175 } 176 177 /* set lp charset/printwheel */ 178 papiAttributeListGetLPString(attributes, "lp-charset", &r->charset); 179 180 /* legacy pr(1) filter related garbage "lpr -p" */ 181 papiAttributeListGetBoolean(attributes, NULL, "pr-filter", &pr_filter); 182 papiAttributeListGetString(attributes, NULL, "pr-title", &pr_title); 183 papiAttributeListGetInteger(attributes, NULL, "pr-width", &pr_width); 184 papiAttributeListGetInteger(attributes, NULL, "pr-indent", &pr_indent); 185 186 if (pr_filter != 0) { 187 char buf[128]; 188 189 if (pr_title != NULL) { 190 snprintf(buf, sizeof (buf), "prtitle='%s'", pr_title); 191 appendlist(&modes, buf); 192 } 193 194 if (pr_width > 0) { 195 snprintf(buf, sizeof (buf), "prwidth=%d", pr_width); 196 appendlist(&modes, buf); 197 } 198 199 if (pr_indent > 0) { 200 snprintf(buf, sizeof (buf), "indent=%d", pr_indent); 201 appendlist(&modes, buf); 202 } 203 } else if ((pr_title != NULL) || (pr_width >= 0) || (pr_indent >= 0)) 204 detailed_error(svc, gettext( 205 "pr(1) filter options specified without enabling pr(1) filter")); 206 207 /* add burst page information */ 208 s = NULL; 209 papiAttributeListGetString(attributes, NULL, "job-sheets", &s); 210 if ((s != NULL) && (strcasecmp(s, "none") == 0)) { 211 char buf[128]; 212 char *class = NULL; 213 char *job_name = NULL; 214 215 papiAttributeListGetLPString(attributes, "job-class", &class); 216 papiAttributeListGetLPString(attributes, "job-name", &job_name); 217 218 /* burst page is enabled by default, add the title */ 219 snprintf(buf, sizeof (buf), "%s%s%s", 220 (job_name ? job_name : ""), 221 (job_name && class ? "\\n#####\\n#####\\t\\t " : ""), 222 (class ? class : "")); 223 if (buf[0] != '\0') { 224 if (r->title != NULL) 225 free(r->title); 226 r->title = strdup(buf); 227 } 228 } else /* burst page is disabled via lp "option" */ 229 appendlist(&options, "nobanner"); 230 231 /* Convert attribute "number-up" to mode group=n */ 232 papiAttributeListGetInteger(attributes, NULL, "number-up", &numberUp); 233 if ((numberUp >= 2) && ((numberUp % 2) == 0)) { 234 snprintf(buf, sizeof (buf), "group=%d", numberUp); 235 appendlist(&modes, buf); 236 } 237 238 /* 239 * Convert attribute "orientation-requested" to modes 240 * 'landscape', 'portrait', etc. 241 */ 242 papiAttributeListGetInteger(attributes, NULL, 243 "orientation-requested", &orientation); 244 if ((orientation >= 3) && (orientation <= 6)) { 245 switch (orientation) { 246 case 4: /* landscape */ 247 case 5: /* reverse-landscape, use landscape instead */ 248 appendlist(&modes, "landscape"); 249 break; 250 case 3: /* portrait */ 251 case 6: /* reverse-portrait, use portrait instead */ 252 default: 253 appendlist(&modes, "portrait"); 254 break; 255 } 256 } 257 258 /* add "lp -y" modes */ 259 attr = papiAttributeListFind(attributes, "lp-modes"); 260 if ((attr != NULL) && (attr->type == PAPI_STRING) && 261 (attr->values != NULL)) { 262 int i; 263 264 for (i = 0; attr->values[i] != NULL; i++) 265 appendlist(&modes, attr->values[i]->string); 266 } 267 268 if (modes != NULL) { 269 if (r->modes == NULL) 270 free(r->modes); 271 r->modes = sprintlist(modes); 272 freelist(modes); 273 } 274 275 /* add any unconsumed attributes to the "options" list */ 276 split_and_copy_attributes(mapped_keys, attributes, NULL, &unmapped); 277 if (unmapped != NULL) { /* convert them to lp options */ 278 char *buf = malloc(1024); 279 ssize_t size = 1024; 280 281 while (papiAttributeListToString(unmapped, ", ", buf, size) 282 != PAPI_OK) { 283 size += 1024; 284 buf = realloc(buf, size); 285 } 286 appendlist(&options, buf); 287 free(buf); 288 papiAttributeListFree(unmapped); 289 } 290 291 if (options != NULL) { 292 if (r->options != NULL) 293 free(r->options); 294 r->options = sprintlist(options); 295 freelist(options); 296 } 297 298 return (PAPI_OK); 299 } 300 301 /* 302 * Convert REQUEST->outcome (or R_REQUEST_* state) to the equivalent 303 * PAPI attribute representation. 304 */ 305 static void 306 lpsched_request_outcome_to_attributes(papi_attribute_t ***attributes, 307 unsigned short state) 308 { 309 if (attributes == NULL) 310 return; 311 312 if (state & (RS_HELD|RS_ADMINHELD)) { 313 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 314 "job-state", 0x04); /* held */ 315 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 316 "job-state-reasons", "job-hold-until-specified"); 317 } else if (state & RS_ACTIVE) { 318 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 319 "job-state", 0x05); 320 if (state & RS_FILTERING) 321 papiAttributeListAddString(attributes, 322 PAPI_ATTR_REPLACE, 323 "job-state-reasons", "job-transforming"); 324 else if (state & RS_PRINTING) 325 papiAttributeListAddString(attributes, 326 PAPI_ATTR_REPLACE, 327 "job-state-reasons", "job-printing"); 328 else 329 papiAttributeListAddString(attributes, 330 PAPI_ATTR_REPLACE, 331 "job-state-reasons", "job-processing"); 332 } else if (state & RS_CANCELLED) { 333 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 334 "job-state", 0x07); 335 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 336 "job-state-reasons", "job-canceled-by-user"); 337 } else if (state & RS_PRINTED) { 338 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 339 "job-state", 0x09); 340 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 341 "job-state-reasons", "job-complete"); 342 } else { 343 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 344 "job-state", 0x03); 345 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 346 "job-state-reasons", "job-queued"); 347 } 348 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 349 "job-hold-until", 350 ((state & RS_HELD) ? "indefinite" : "no-hold")); 351 } 352 353 /* 354 * Convert REQUEST structure to the equivalent PAPI attribute representation. 355 */ 356 void 357 lpsched_request_to_job_attributes(REQUEST *r, job_t *j) 358 { 359 char *tmp; 360 int i; 361 362 /* copies */ 363 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 364 "copies", r->copies); 365 366 /* destination */ 367 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 368 "printer-name", r->destination); 369 370 /* form */ 371 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 372 "form", r->form); 373 374 /* options */ 375 papiAttributeListFromString(&j->attributes, PAPI_ATTR_APPEND, 376 r->options); 377 378 tmp = (((r->options != NULL) && (strstr(r->options, "nobanner") 379 != NULL)) ? "none" : "standard"); 380 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 381 "job-sheets", tmp); 382 383 tmp = (((r->options != NULL) && (strstr(r->options, "duplex") 384 != NULL)) ? "two-sized" : "one-sided"); 385 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 386 "sides", tmp); 387 388 i = (((r->options != NULL) && (strstr(r->options, "landscape") 389 != NULL)) ? 4 : 3); 390 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 391 "orientation-requested", i); 392 393 /* priority (map 0-39 to 1-100) */ 394 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 395 "job-priority", (int)((r->priority + 1) * 2.5)); 396 397 /* pages */ 398 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 399 "page-ranges", r->pages); 400 401 /* charset */ 402 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 403 "lp-charset", r->charset); 404 405 /* modes */ 406 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 407 "lp-modes", r->modes); 408 409 /* title */ 410 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 411 "job-name", r->title); 412 413 /* input_type */ 414 415 /* user */ 416 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 417 "job-originating-user-name", r->user); 418 419 /* outcome */ 420 lpsched_request_outcome_to_attributes(&j->attributes, r->outcome); 421 422 /* constants, (should be derived from options) */ 423 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 424 "number-up", 1); 425 426 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 427 "multiple-document-handling", 428 "seperate-documents-collated-copies"); 429 } 430 431 /* 432 * Convert R_REQUEST_* results to the equivalent PAPI attribute representation. 433 */ 434 void 435 job_status_to_attributes(job_t *job, char *req_id, char *user, char *slabel, 436 size_t size, time_t date, short state, char *destination, 437 char *form, char *charset, short rank, char *file) 438 { 439 char buf[BUFSIZ]; 440 char *p; 441 442 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, 443 "job-originating-user-name", user); 444 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 445 "job-k-octets", size/1024); 446 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 447 "job-octets", size); 448 if ((p = strrchr(req_id, '-')) != NULL) { 449 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 450 "job-id", atoi(++p)); 451 } 452 snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s/%d", 453 destination, atoi(p)); 454 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 455 "job-uri", buf); 456 snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s", 457 destination); 458 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 459 "job-printer-uri", buf); 460 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 461 "job-printer-up-time", time(NULL)); 462 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 463 "output-device-assigned", destination); 464 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 465 "printer-name", destination); 466 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, 467 "form", form); 468 469 lpsched_request_outcome_to_attributes(&job->attributes, state); 470 471 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 472 "time-at-creation", date); 473 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, 474 "lpsched-request-id", req_id); 475 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, 476 "lp-charset", charset); 477 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 478 "lpsched-job-state", state); 479 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 480 "number-of-intervening-jobs", rank - 1); 481 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, 482 "lpsched-file", file); 483 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_EXCL, 484 "job-name", file); 485 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_EXCL, 486 "tsol-sensitivity-label", slabel); 487 } 488 489 void 490 lpsched_read_job_configuration(service_t *svc, job_t *j, char *file) 491 { 492 REQUEST *r; 493 494 if ((r = getrequest(file)) == NULL) { 495 detailed_error(svc, gettext("unable to read job data: %s"), 496 file); 497 return; 498 } 499 500 lpsched_request_to_job_attributes(r, j); 501 } 502