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