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