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", "job-originating-host-name", 73 NULL }; 74 75 if (attributes == NULL) 76 return (PAPI_BAD_ARGUMENT); 77 78 /* replace the current destination */ 79 papiAttributeListGetLPString(attributes, 80 "job-printer", &r->destination); 81 82 /* set the copies. We need at least 1 */ 83 i = r->copies; 84 papiAttributeListGetInteger(attributes, NULL, "copies", &i); 85 if (i <= 0) 86 i = 1; 87 r->copies = i; 88 89 /* 90 * set the priority. PAPI/IPP uses 1-100, lpsched use 0-39, so we 91 * have to convert it. 92 */ 93 if (papiAttributeListGetInteger(attributes, NULL, "priority", &i) 94 == PAPI_OK) { 95 if ((i < 1) || (i > 100)) 96 i = 50; 97 i = (i + 1) / 2.5; 98 r->priority = i; 99 } 100 if ((r->priority < 0) || (r->priority > 39)) 101 r->priority = 20; 102 103 /* set the requested form to print on */ 104 papiAttributeListGetLPString(attributes, "form", &r->form); 105 106 /* set the page range */ 107 #ifndef LP_USE_PAPI_ATTR 108 papiAttributeListGetLPString(attributes, "page-ranges", &r->pages); 109 #else 110 for (status = papiAttributeListGetRange(attributes, &iterator, 111 "page-ranges", &lower, &upper); 112 status == PAPI_OK; 113 status = papiAttributeListGetRange(attributes, &iterator, 114 "page-ranges", &lower, &upper)) { 115 if (r->pages != NULL) { 116 snprintf(buf, sizeof (buf), "%s,%d-%d", 117 r->pages, lower, upper); 118 free(r->pages); 119 } else 120 snprintf(buf, sizeof (buf), "%d-%d", lower, upper); 121 r->pages = (char *)strdup(buf); 122 } 123 #endif 124 125 /* 126 * set the document format, converting to old format names as 127 * as needed. 128 */ 129 s = NULL; 130 papiAttributeListGetString(attributes, NULL, "document-format", &s); 131 if (s != NULL) 132 r->input_type = strdup(mime_type_to_lp_type(s)); 133 134 135 /* 136 * If we don't have an owner, set one. 137 */ 138 if (r->user == NULL) { 139 uid_t uid = getuid(); 140 struct passwd *pw; 141 char *user = "intruder"; 142 char *host = NULL; 143 char buf[256]; 144 145 if ((pw = getpwuid(uid)) != NULL) 146 user = pw->pw_name; /* default to the process owner */ 147 148 if ((uid == 0) || (uid == 71)) { /* root/lp can forge this */ 149 papiAttributeListGetString(attributes, NULL, 150 "job-originating-host-name", &host); 151 papiAttributeListGetString(attributes, NULL, 152 "job-host", &host); 153 papiAttributeListGetString(attributes, NULL, 154 "job-originating-user-name", &user); 155 papiAttributeListGetString(attributes, NULL, 156 "requesting-user-name", &user); 157 158 snprintf(buf, sizeof (buf), "%s%s%s", user, 159 (host ? "@" : ""), (host ? host : "")); 160 user = buf; 161 } 162 163 r->user = strdup(user); 164 } 165 166 /* set any held state */ 167 s = NULL; 168 papiAttributeListGetString(attributes, NULL, "job-hold-until", &s); 169 if (s != NULL) { 170 if (strcmp(s, "immediate") == 0) 171 r->actions |= ACT_IMMEDIATE; 172 else if ((strcmp(s, "resume") == 0) || 173 (strcmp(s, "no-hold") == 0)) 174 r->actions |= ACT_RESUME; 175 else if ((strcmp(s, "hold") == 0) || 176 (strcmp(s, "indefinite") == 0)) 177 r->actions |= ACT_HOLD; 178 } 179 180 /* set lp charset/printwheel */ 181 papiAttributeListGetLPString(attributes, "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 s = NULL; 212 papiAttributeListGetString(attributes, NULL, "job-sheets", &s); 213 if ((s != NULL) && (strcasecmp(s, "none") != 0)) { 214 char buf[128]; 215 char *class = NULL; 216 char *job_name = NULL; 217 218 papiAttributeListGetLPString(attributes, "job-class", &class); 219 papiAttributeListGetLPString(attributes, "job-name", &job_name); 220 221 /* burst page is enabled by default, add the title */ 222 snprintf(buf, sizeof (buf), "%s%s%s", 223 (job_name ? job_name : ""), 224 (job_name && class ? "\\n#####\\n#####\\t\\t " : ""), 225 (class ? class : "")); 226 if (buf[0] != '\0') { 227 if (r->title != NULL) 228 free(r->title); 229 r->title = strdup(buf); 230 } 231 } else /* burst page is disabled via lp "option" */ 232 appendlist(&options, "nobanner"); 233 234 /* Convert attribute "number-up" to mode group=n */ 235 papiAttributeListGetInteger(attributes, NULL, "number-up", &numberUp); 236 if ((numberUp >= 2) && ((numberUp % 2) == 0)) { 237 snprintf(buf, sizeof (buf), "group=%d", numberUp); 238 appendlist(&modes, buf); 239 } 240 241 /* 242 * Convert attribute "orientation-requested" to modes 243 * 'landscape', 'portrait', etc. 244 */ 245 papiAttributeListGetInteger(attributes, NULL, 246 "orientation-requested", &orientation); 247 if ((orientation >= 3) && (orientation <= 6)) { 248 switch (orientation) { 249 case 4: /* landscape */ 250 case 5: /* reverse-landscape, use landscape instead */ 251 appendlist(&modes, "landscape"); 252 break; 253 case 3: /* portrait */ 254 case 6: /* reverse-portrait, use portrait instead */ 255 default: 256 appendlist(&modes, "portrait"); 257 break; 258 } 259 } 260 261 /* add "lp -y" modes */ 262 attr = papiAttributeListFind(attributes, "lp-modes"); 263 if ((attr != NULL) && (attr->type == PAPI_STRING) && 264 (attr->values != NULL)) { 265 int i; 266 267 for (i = 0; attr->values[i] != NULL; i++) 268 appendlist(&modes, attr->values[i]->string); 269 } 270 271 if (modes != NULL) { 272 if (r->modes == NULL) 273 free(r->modes); 274 r->modes = sprintlist(modes); 275 freelist(modes); 276 } 277 278 /* add any unconsumed attributes to the "options" list */ 279 split_and_copy_attributes(mapped_keys, attributes, NULL, &unmapped); 280 if (unmapped != NULL) { /* convert them to lp options */ 281 char *buf = malloc(1024); 282 ssize_t size = 1024; 283 284 while (papiAttributeListToString(unmapped, ", ", buf, size) 285 != PAPI_OK) { 286 size += 1024; 287 buf = realloc(buf, size); 288 } 289 appendlist(&options, buf); 290 free(buf); 291 papiAttributeListFree(unmapped); 292 } 293 294 if (options != NULL) { 295 if (r->options != NULL) 296 free(r->options); 297 r->options = sprintlist(options); 298 freelist(options); 299 } 300 301 return (PAPI_OK); 302 } 303 304 /* 305 * Convert REQUEST->outcome (or R_REQUEST_* state) to the equivalent 306 * PAPI attribute representation. 307 */ 308 static void 309 lpsched_request_outcome_to_attributes(papi_attribute_t ***attributes, 310 unsigned short state) 311 { 312 if (attributes == NULL) 313 return; 314 315 if (state & (RS_HELD|RS_ADMINHELD)) { 316 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 317 "job-state", 0x04); /* held */ 318 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 319 "job-state-reasons", "job-hold-until-specified"); 320 } else if (state & RS_ACTIVE) { 321 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 322 "job-state", 0x05); 323 if (state & RS_FILTERING) 324 papiAttributeListAddString(attributes, 325 PAPI_ATTR_REPLACE, 326 "job-state-reasons", "job-transforming"); 327 else if (state & RS_PRINTING) 328 papiAttributeListAddString(attributes, 329 PAPI_ATTR_REPLACE, 330 "job-state-reasons", "job-printing"); 331 else 332 papiAttributeListAddString(attributes, 333 PAPI_ATTR_REPLACE, 334 "job-state-reasons", "job-processing"); 335 } else if (state & RS_CANCELLED) { 336 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 337 "job-state", 0x07); 338 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 339 "job-state-reasons", "job-canceled-by-user"); 340 } else if (state & RS_PRINTED) { 341 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 342 "job-state", 0x09); 343 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 344 "job-state-reasons", "job-complete"); 345 } else { 346 papiAttributeListAddInteger(attributes, PAPI_ATTR_REPLACE, 347 "job-state", 0x03); 348 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 349 "job-state-reasons", "job-queued"); 350 } 351 papiAttributeListAddString(attributes, PAPI_ATTR_REPLACE, 352 "job-hold-until", 353 ((state & RS_HELD) ? "indefinite" : "no-hold")); 354 } 355 356 /* 357 * convert user[@host] to papi attributes 358 */ 359 static void 360 lpsched_user_to_job_attributes(papi_attribute_t ***list, char *user) 361 { 362 if ((list != NULL) && (user != NULL) && (user[0] != NULL)) { 363 char *host = strrchr(user, '@'); 364 365 if (host != NULL) { 366 *host = NULL; 367 papiAttributeListAddString(list, PAPI_ATTR_REPLACE, 368 "job-originating-user-name", user); 369 papiAttributeListAddString(list, PAPI_ATTR_REPLACE, 370 "job-originating-host-name", host + 1); 371 *host = '@'; 372 } else 373 papiAttributeListAddString(list, PAPI_ATTR_REPLACE, 374 "job-originating-user-name", user); 375 } 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 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 393 "printer-name", r->destination); 394 395 /* form */ 396 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 397 "form", r->form); 398 399 /* options */ 400 papiAttributeListFromString(&j->attributes, PAPI_ATTR_APPEND, 401 r->options); 402 403 tmp = (((r->options != NULL) && (strstr(r->options, "nobanner") 404 != NULL)) ? "none" : "standard"); 405 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 406 "job-sheets", tmp); 407 408 tmp = (((r->options != NULL) && (strstr(r->options, "duplex") 409 != NULL)) ? "two-sized" : "one-sided"); 410 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 411 "sides", tmp); 412 413 i = (((r->options != NULL) && (strstr(r->options, "landscape") 414 != NULL)) ? 4 : 3); 415 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 416 "orientation-requested", i); 417 418 /* priority (map 0-39 to 1-100) */ 419 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 420 "job-priority", (int)((r->priority + 1) * 2.5)); 421 422 /* pages */ 423 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 424 "page-ranges", r->pages); 425 426 /* charset */ 427 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 428 "lp-charset", r->charset); 429 430 /* modes */ 431 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 432 "lp-modes", r->modes); 433 434 /* title */ 435 papiAttributeListAddLPString(&j->attributes, PAPI_ATTR_REPLACE, 436 "job-name", r->title); 437 438 /* input_type */ 439 440 /* user */ 441 lpsched_user_to_job_attributes(&j->attributes, r->user); 442 443 /* outcome */ 444 lpsched_request_outcome_to_attributes(&j->attributes, r->outcome); 445 446 /* constants, (should be derived from options) */ 447 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 448 "number-up", 1); 449 450 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 451 "multiple-document-handling", 452 "seperate-documents-collated-copies"); 453 } 454 455 /* 456 * Convert R_REQUEST_* results to the equivalent PAPI attribute representation. 457 */ 458 void 459 job_status_to_attributes(job_t *job, char *req_id, char *user, char *slabel, 460 size_t size, time_t date, short state, char *destination, 461 char *form, char *charset, short rank, char *file) 462 { 463 char buf[BUFSIZ]; 464 char *p; 465 466 lpsched_user_to_job_attributes(&job->attributes, user); 467 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 468 "job-k-octets", size/1024); 469 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 470 "job-octets", size); 471 if ((p = strrchr(req_id, '-')) != NULL) { 472 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 473 "job-id", atoi(++p)); 474 } 475 snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s/%d", 476 destination, atoi(p)); 477 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 478 "job-uri", buf); 479 snprintf(buf, sizeof (buf), "lpsched://localhost/printers/%s", 480 destination); 481 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 482 "job-printer-uri", buf); 483 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 484 "job-printer-up-time", time(NULL)); 485 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 486 "output-device-assigned", destination); 487 papiAttributeListAddString(&job->attributes, PAPI_ATTR_REPLACE, 488 "printer-name", destination); 489 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, 490 "form", form); 491 492 lpsched_request_outcome_to_attributes(&job->attributes, state); 493 494 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 495 "time-at-creation", date); 496 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, 497 "lpsched-request-id", req_id); 498 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, 499 "lp-charset", charset); 500 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 501 "lpsched-job-state", state); 502 papiAttributeListAddInteger(&job->attributes, PAPI_ATTR_REPLACE, 503 "number-of-intervening-jobs", rank - 1); 504 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_REPLACE, 505 "lpsched-file", file); 506 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_EXCL, 507 "job-name", file); 508 papiAttributeListAddLPString(&job->attributes, PAPI_ATTR_EXCL, 509 "tsol-sensitivity-label", slabel); 510 } 511 512 void 513 lpsched_read_job_configuration(service_t *svc, job_t *j, char *file) 514 { 515 REQUEST *r; 516 517 if ((r = getrequest(file)) == NULL) { 518 detailed_error(svc, gettext("unable to read job data: %s"), 519 file); 520 return; 521 } 522 523 lpsched_request_to_job_attributes(r, j); 524 } 525