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