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_attribute_t *attr; 48 int i; 49 char *s; 50 51 char **options = NULL; 52 char **modes = NULL; 53 char *class = NULL; 54 char *job_name = 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 lowerPage = 0; 63 int upperPage = 0; 64 papi_status_t getResult = 0; 65 char buf[256]; 66 void *iterator = NULL; 67 68 char banner = 0; 69 70 if (attributes == NULL) 71 return (PAPI_BAD_ARGUMENT); 72 73 papiAttributeListGetString(attributes, NULL, "job-printer", 74 &r->destination); 75 76 i = r->copies; 77 papiAttributeListGetInteger(attributes, NULL, "copies", &i); 78 if (i <= 0) 79 i = 1; 80 r->copies = i; 81 82 if (papiAttributeListGetInteger(attributes, NULL, "priority", &i) 83 == PAPI_OK) { 84 if ((i < 1) || (i > 100)) 85 i = 50; 86 i = (i + 1) / 2.5; 87 r->priority = i; 88 } 89 90 if ((r->priority < 0) || (r->priority > 39)) 91 r->priority = 20; 92 93 /* 94 * 'media' size should be processed both in the lpsched filter and 95 * the foomatic filter (if present) so that we ensure the result of 96 * other options like 'page-ranges' are consistent. 97 */ 98 /* 99 * TODO - I thing we should really have this but I can't get it to filter 100 * so its commented out for now (paulcun) 101 * papiAttributeListGetString(attributes, NULL, "media", &r->form); 102 */ 103 104 #ifndef LP_USE_PAPI_ATTR 105 papiAttributeListGetString(attributes, NULL, "page-ranges", &r->pages); 106 #else 107 getResult = 108 papiAttributeListGetRange(attributes, &iterator, 109 "page-ranges", &lowerPage, &upperPage); 110 while (getResult == PAPI_OK) { 111 if (r->pages == NULL) { 112 snprintf(buf, sizeof (buf), 113 "%d-%d", lowerPage, upperPage); 114 r->pages = (char *)strdup(buf); 115 } 116 else 117 { 118 snprintf(buf, sizeof (buf), "%s,%d-%d", 119 r->pages, lowerPage, upperPage); 120 free(r->pages); 121 r->pages = (char *)strdup(buf); 122 } 123 /* 124 * get the next value; note the attribute 'name' is set to 125 * NULL to do this. 126 */ 127 getResult = 128 papiAttributeListGetRange(attributes, &iterator, 129 "page-ranges", &lowerPage, &upperPage); 130 } 131 #endif 132 133 134 s = NULL; 135 papiAttributeListGetString(attributes, NULL, "document-format", &s); 136 if (s != NULL) 137 r->input_type = strdup(mime_type_to_lp_type(s)); 138 139 /* 140 * If we don't have an owner, set one. 141 */ 142 if (r->user == NULL) { 143 uid_t uid = getuid(); 144 struct passwd *pw; 145 char *user = "intruder"; 146 char *host = NULL; 147 char buf[256]; 148 149 if ((pw = getpwuid(uid)) != NULL) 150 user = pw->pw_name; /* default to the process owner */ 151 152 if ((uid == 0) || (uid == 71)) { /* root/lp can forge this */ 153 papiAttributeListGetString(attributes, NULL, 154 "job-host", &host); 155 papiAttributeListGetString(attributes, NULL, 156 "job-originating-user-name", &user); 157 papiAttributeListGetString(attributes, NULL, 158 "requesting-user-name", &user); 159 160 snprintf(buf, sizeof (buf), "%s%s%s", user, 161 (host ? "@" : ""), (host ? host : "")); 162 user = buf; 163 } 164 165 r->user = strdup(user); 166 } 167 168 s = NULL; 169 papiAttributeListGetString(attributes, NULL, "job-hold-until", &s); 170 if (s != NULL) { 171 if (strcmp(s, "immediate") == 0) 172 r->actions |= ACT_IMMEDIATE; 173 else if ((strcmp(s, "resume") == 0) || 174 (strcmp(s, "no-hold") == 0)) 175 r->actions |= ACT_RESUME; 176 else if ((strcmp(s, "hold") == 0) || 177 (strcmp(s, "indefinite") == 0)) 178 r->actions |= ACT_HOLD; 179 } 180 181 papiAttributeListGetString(attributes, NULL, "lp-charset", &r->charset); 182 183 /* legacy pr(1) filter related garbage "lpr -p" */ 184 papiAttributeListGetBoolean(attributes, NULL, "pr-filter", &pr_filter); 185 papiAttributeListGetString(attributes, NULL, "pr-title", &pr_title); 186 papiAttributeListGetInteger(attributes, NULL, "pr-width", &pr_width); 187 papiAttributeListGetInteger(attributes, NULL, "pr-indent", &pr_indent); 188 189 if (pr_filter != 0) { 190 char buf[128]; 191 192 if (pr_title != NULL) { 193 snprintf(buf, sizeof (buf), "prtitle='%s'", pr_title); 194 appendlist(&modes, buf); 195 } 196 197 if (pr_width > 0) { 198 snprintf(buf, sizeof (buf), "prwidth=%d", pr_width); 199 appendlist(&modes, buf); 200 } 201 202 if (pr_indent > 0) { 203 snprintf(buf, sizeof (buf), "indent=%d", pr_indent); 204 appendlist(&modes, buf); 205 } 206 } else if ((pr_title != NULL) || (pr_width >= 0) || (pr_indent >= 0)) 207 detailed_error(svc, gettext( 208 "pr(1) filter options specified without enabling pr(1) filter")); 209 210 /* add burst page information */ 211 papiAttributeListGetBoolean(attributes, NULL, "job-sheets", &banner); 212 papiAttributeListGetString(attributes, NULL, "job-class", &class); 213 papiAttributeListGetString(attributes, NULL, "job-name", &job_name); 214 215 { 216 char buf[128]; 217 /* burst page is enabled by default, add the title */ 218 snprintf(buf, sizeof (buf), "%s%s%s", 219 (job_name ? job_name : ""), 220 (job_name && class ? "\\n#####\\n#####\\t\\t " : ""), 221 (class ? class : "")); 222 if (buf[0] != '\0') { 223 if (r->title != NULL) 224 free(r->title); 225 r->title = strdup(buf); 226 } 227 } 228 if (banner == 0) /* burst page is disabled via lp "option" */ 229 appendlist(&options, "nobanner"); 230 231 /* add "lp -o" options */ 232 attr = papiAttributeListFind(attributes, "lp-options"); 233 if ((attr != NULL) && (attr->type == PAPI_STRING) && 234 (attr->values != NULL)) { 235 int i; 236 237 for (i = 0; attr->values[i] != NULL; i++) 238 appendlist(&options, attr->values[i]->string); 239 } 240 241 if (options != NULL) { 242 if (r->options != NULL) 243 free(r->options); 244 r->options = sprintlist(options); 245 freelist(options); 246 } 247 248 /* Convert attribute "number-up" to mode group=n */ 249 papiAttributeListGetInteger(attributes, NULL, "number-up", &numberUp); 250 if ((numberUp >= 2) && ((numberUp % 2) == 0)) { 251 snprintf(buf, sizeof (buf), "group=%d", numberUp); 252 appendlist(&modes, buf); 253 } 254 255 /* 256 * Convert attribute "orientation-requested" to modes 257 * 'landscape', 'portrait', etc. 258 */ 259 papiAttributeListGetInteger(attributes, NULL, 260 "orientation-requested", &orientation); 261 if ((orientation >= 3) && (orientation <= 6)) { 262 switch (orientation) { 263 case 3: 264 { 265 /* 3 = portrait */ 266 appendlist(&modes, "portrait"); 267 break; 268 } 269 270 case 4: 271 { 272 /* 4 = landscape */ 273 appendlist(&modes, "landscape"); 274 break; 275 } 276 277 case 5: 278 { 279 /* 280 * 5 = reverse-landscape - not supported in 281 * lpsched so just use 'landscape' for now 282 */ 283 appendlist(&modes, "landscape"); 284 break; 285 } 286 287 case 6: 288 { 289 /* 290 * 6 = reverse-portrait not supported in 291 * lpsched so just use 'portrait' for now 292 */ 293 appendlist(&modes, "portrait"); 294 break; 295 } 296 297 default: 298 { 299 appendlist(&modes, "portrait"); 300 break; 301 } 302 } 303 } 304 305 /* add "lp -y" modes */ 306 attr = papiAttributeListFind(attributes, "lp-modes"); 307 if ((attr != NULL) && (attr->type == PAPI_STRING) && 308 (attr->values != NULL)) { 309 int i; 310 311 for (i = 0; attr->values[i] != NULL; i++) 312 appendlist(&modes, attr->values[i]->string); 313 } 314 315 if (modes != NULL) { 316 if (r->modes == NULL) 317 free(r->modes); 318 r->modes = sprintlist(modes); 319 freelist(modes); 320 } 321 322 return (PAPI_OK); 323 } 324 325 /* 326 * Convert REQUEST->outcome (or R_REQUEST_* state) to the equivalent 327 * PAPI attribute representation. 328 */ 329 static void 330 lpsched_request_outcome_to_attributes(papi_attribute_t ***attributes, 331 unsigned short state) 332 { 333 if (attributes == NULL) 334 return; 335 336 if (state & (RS_HELD|RS_ADMINHELD)) { 337 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 338 "job-state", 0x04); /* held */ 339 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 340 "job-state-reasons", "job-hold-until-specified"); 341 } else if (state & RS_ACTIVE) { 342 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 343 "job-state", 0x05); 344 if (state & RS_FILTERING) 345 papiAttributeListAddString(attributes, 346 PAPI_ATTR_REPLACE, 347 "job-state-reasons", "job-transforming"); 348 else if (state & RS_PRINTING) 349 papiAttributeListAddString(attributes, 350 PAPI_ATTR_REPLACE, 351 "job-state-reasons", "job-printing"); 352 else 353 papiAttributeListAddString(attributes, 354 PAPI_ATTR_REPLACE, 355 "job-state-reasons", "job-processing"); 356 } else if (state & RS_CANCELLED) { 357 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 358 "job-state", 0x07); 359 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 360 "job-state-reasons", "job-canceled-by-user"); 361 } else if (state & RS_PRINTED) { 362 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 363 "job-state", 0x09); 364 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 365 "job-state-reasons", "job-complete"); 366 } else { 367 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 368 "job-state", 0x03); 369 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 370 "job-state-reasons", "job-queued"); 371 } 372 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 373 "job-hold-until", 374 ((state & RS_HELD) ? "indefinite" : "no-hold")); 375 } 376 377 /* 378 * Convert REQUEST structure to the equivalent PAPI attribute representation. 379 */ 380 void 381 lpsched_request_to_job_attributes(REQUEST *r, job_t *j) 382 { 383 char *tmp; 384 int i; 385 386 /* copies */ 387 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 388 "copies", r->copies); 389 390 /* destination */ 391 addLPString(&j->attributes, PAPI_ATTR_REPLACE, "printer-name", 392 r->destination); 393 394 /* file_list */ 395 addLPStrings(&j->attributes, PAPI_ATTR_REPLACE, 396 "lpsched-files", r->file_list); 397 398 /* form */ 399 addLPString(&j->attributes, PAPI_ATTR_REPLACE, "media", r->form); 400 401 /* actions */ 402 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 403 "lpsched-actions", r->actions); 404 405 /* alert */ 406 addLPString(&j->attributes, PAPI_ATTR_REPLACE, "lp-alert", r->alert); 407 408 /* options */ 409 addLPString(&j->attributes, PAPI_ATTR_REPLACE, 410 "lp-options", r->options); 411 412 tmp = (((r->options != NULL) && (strstr(r->options, "nobanner") 413 != NULL)) ? "none" : "standard"); 414 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 415 "job-sheets", tmp); 416 417 tmp = (((r->options != NULL) && (strstr(r->options, "duplex") 418 != NULL)) ? "two-sized" : "one-sided"); 419 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 420 "sides", tmp); 421 422 i = (((r->options != NULL) && (strstr(r->options, "landscape") 423 != NULL)) ? 4 : 3); 424 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 425 "orientation-requested", i); 426 427 /* priority (map 0-39 to 1-100) */ 428 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 429 "job-priority", (int)((r->priority + 1) * 2.5)); 430 431 /* pages */ 432 addLPString(&j->attributes, PAPI_ATTR_REPLACE, "page-ranges", r->pages); 433 434 /* charset */ 435 addLPString(&j->attributes, PAPI_ATTR_REPLACE, "lp-charset", 436 r->charset); 437 438 /* modes */ 439 addLPString(&j->attributes, PAPI_ATTR_REPLACE, "lp-modes", r->modes); 440 441 /* title */ 442 addLPString(&j->attributes, PAPI_ATTR_REPLACE, "job-name", r->title); 443 444 /* input_type */ 445 446 /* user */ 447 addLPString(&j->attributes, PAPI_ATTR_REPLACE, 448 "job-originating-user-name", r->user); 449 450 /* outcome */ 451 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 452 "lpsched-outcome", r->outcome); 453 lpsched_request_outcome_to_attributes(&j->attributes, r->outcome); 454 455 /* version */ 456 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 457 "lpsched-version", r->version); 458 459 /* constants, (should be derived from options) */ 460 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 461 "number-up", 1); 462 463 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 464 "multiple-document-handling", 465 "seperate-documents-collated-copies"); 466 } 467 468 /* 469 * Convert R_REQUEST_* results to the equivalent PAPI attribute representation. 470 */ 471 void 472 job_status_to_attributes(job_t *job, char *req_id, char *user, char *slabel, 473 size_t size, time_t date, short state, char *destination, 474 char *form, char *charset, short rank, char *file) 475 { 476 char buf[BUFSIZ]; 477 char *p; 478 479 addLPString(&job->attributes, PAPI_ATTR_REPLACE, 480 "job-originating-user-name", user); 481 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 482 "job-k-octets", size/1024); 483 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 484 "job-octets", size); 485 if ((p = strrchr(req_id, '-')) != NULL) { 486 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 487 "job-id", atoi(++p)); 488 } 489 snprintf(buf, sizeof (buf), "lpsched://%s/%d", destination, atoi(p)); 490 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 491 "job-uri", buf); 492 snprintf(buf, sizeof (buf), "lpsched://%s", destination); 493 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 494 "job-printer-uri", buf); 495 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 496 "job-printer-up-time", time(NULL)); 497 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 498 "output-device-assigned", destination); 499 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 500 "printer-name", destination); 501 addLPString(&job->attributes, PAPI_ATTR_REPLACE, "media", form); 502 503 lpsched_request_outcome_to_attributes(&job->attributes, state); 504 505 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 506 "time-at-creation", date); 507 addLPString(&job->attributes, PAPI_ATTR_REPLACE, 508 "lpsched-request-id", req_id); 509 addLPString(&job->attributes, PAPI_ATTR_REPLACE, 510 "lp-charset", charset); 511 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 512 "lpsched-job-state", state); 513 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 514 "number-of-intervening-jobs", rank - 1); 515 addLPString(&job->attributes, PAPI_ATTR_REPLACE, 516 "lpsched-file", file); 517 addLPString(&job->attributes, PAPI_ATTR_EXCL, 518 "job-name", file); 519 addLPString(&job->attributes, PAPI_ATTR_EXCL, 520 "tsol-sensitivity-label", slabel); 521 } 522 523 void 524 lpsched_read_job_configuration(service_t *svc, job_t *j, char *file) 525 { 526 REQUEST *r; 527 528 if ((r = getrequest(file)) == NULL) { 529 detailed_error(svc, gettext("unable to read job data: %s"), 530 file); 531 return; 532 } 533 534 lpsched_request_to_job_attributes(r, j); 535 } 536