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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /*LINTLIBRARY*/ 26 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 #include <libintl.h> 31 #include <pwd.h> 32 #include <sys/stat.h> 33 #include <papi_impl.h> 34 35 /* 36 * for an older application that may have been linked with a pre-v1.0 37 * PAPI implementation. 38 */ 39 papi_status_t 40 papiAttributeListAdd(papi_attribute_t ***attrs, int flags, char *name, 41 papi_attribute_value_type_t type, papi_attribute_value_t *value) 42 { 43 return (papiAttributeListAddValue(attrs, flags, name, type, value)); 44 } 45 46 #ifdef LP_USE_PAPI_ATTR 47 static papi_status_t psm_modifyAttrsFile(papi_attribute_t **attrs, char *file); 48 static papi_status_t psm_modifyAttrsList(char *file, papi_attribute_t **attrs, 49 papi_attribute_t ***newAttrs); 50 #endif 51 52 int32_t 53 check_job_id(papi_service_t svc, char *printer, int32_t id) 54 { 55 papi_job_t *jobs = NULL; 56 papi_status_t status; 57 int ret = -1; 58 char *jattrs[] = { "job-id", 59 "job-id-requested", NULL }; 60 61 status = papiPrinterListJobs(svc, printer, jattrs, PAPI_LIST_JOBS_ALL, 62 0, &jobs); 63 64 if (status != PAPI_OK) { 65 detailed_error(svc, 66 gettext("Failed to query service for %s: %s\n"), 67 printer, lpsched_status_string(status)); 68 return (-1); 69 } 70 71 if (jobs != NULL) { 72 int i = 0; 73 74 for (i = 0; jobs[i] != NULL; i++) { 75 int32_t rid = -1; 76 int32_t jid = -1; 77 papi_attribute_t **list = 78 papiJobGetAttributeList(jobs[i]); 79 80 papiAttributeListGetInteger(list, NULL, 81 "job-id-requested", &rid); 82 papiAttributeListGetInteger(list, NULL, 83 "job-id", &jid); 84 85 /* 86 * check if id matches with either rid or jid 87 */ 88 if (rid == id) { 89 /* get the actual id and return it */ 90 papiAttributeListGetInteger(list, NULL, 91 "job-id", &id); 92 return (id); 93 } else if (jid == id) { 94 if (rid != -1) { 95 /* 96 * It is a remote lpd job. 97 * It cannot be modified based on job-id 98 * or spool number 99 */ 100 return (-1); 101 } else { 102 /* 103 * It is either local job or 104 * remote ipp job 105 */ 106 return (id); 107 } 108 } 109 } 110 } 111 return (id); 112 } 113 114 void 115 papiJobFree(papi_job_t job) 116 { 117 job_t *tmp = (job_t *)job; 118 119 if (tmp != NULL) { 120 papiAttributeListFree(tmp->attributes); 121 free(tmp); 122 } 123 } 124 125 void 126 papiJobListFree(papi_job_t *jobs) 127 { 128 if (jobs != NULL) { 129 int i; 130 131 for (i = 0; jobs[i] != NULL; i++) { 132 papiJobFree(jobs[i]); 133 } 134 free(jobs); 135 } 136 } 137 138 papi_attribute_t ** 139 papiJobGetAttributeList(papi_job_t job) 140 { 141 job_t *tmp = (job_t *)job; 142 143 if (tmp != NULL) 144 return (tmp->attributes); 145 146 return (NULL); 147 } 148 149 char * 150 papiJobGetPrinterName(papi_job_t job) 151 { 152 job_t *tmp = (job_t *)job; 153 char *result = NULL; 154 155 if (tmp != NULL) 156 papiAttributeListGetString(tmp->attributes, NULL, 157 "printer-name", &result); 158 159 return (result); 160 } 161 162 int32_t 163 papiJobGetId(papi_job_t job) 164 { 165 job_t *tmp = (job_t *)job; 166 int result = -1; 167 168 if (tmp != NULL) 169 papiAttributeListGetInteger(tmp->attributes, NULL, "job-id", 170 &result); 171 172 return (result); 173 } 174 175 static REQUEST * 176 create_request(papi_service_t svc, char *printer, papi_attribute_t **attributes) 177 { 178 REQUEST *r; 179 180 if ((r = calloc(1, sizeof (*r))) != NULL) { 181 char *hostname = NULL; 182 183 r->priority = -1; 184 r->destination = printer_name_from_uri_id(printer, -1); 185 186 papiAttributeListGetString(attributes, NULL, 187 "job-originating-host-name", &hostname); 188 189 if (hostname == NULL) { 190 char host[BUFSIZ]; 191 192 if (gethostname(host, sizeof (host)) == 0) 193 papiAttributeListAddString(&attributes, 194 PAPI_ATTR_REPLACE, 195 "job-originating-host-name", 196 host); 197 } 198 199 job_attributes_to_lpsched_request(svc, r, attributes); 200 } 201 202 return (r); 203 } 204 205 static papi_status_t 206 authorized(service_t *svc, int32_t id) 207 { 208 papi_status_t result = PAPI_NOT_AUTHORIZED; /* assume the worst */ 209 char file[32]; 210 REQUEST *r; 211 212 snprintf(file, sizeof (file), "%d-0", id); 213 if ((r = getrequest(file)) != NULL) { 214 uid_t uid = getuid(); 215 struct passwd *pw = NULL; 216 char *user = "intruder"; /* assume an intruder */ 217 218 if ((pw = getpwuid(uid)) != NULL) 219 user = pw->pw_name; /* use the process owner */ 220 221 if ((uid == 0) || (uid == 71)) { /* root/lp can forge this */ 222 papi_status_t s; 223 s = papiAttributeListGetString(svc->attributes, NULL, 224 "user-name", &user); 225 if (s != PAPI_OK) /* true root/lp are almighty */ 226 result = PAPI_OK; 227 } 228 229 if (result != PAPI_OK) { 230 if (strcmp(user, r->user) == 0) 231 result = PAPI_OK; 232 else { 233 /* 234 * user and r->user might contain the 235 * host info also 236 */ 237 char *token1 = strtok(r->user, "@"); 238 char *token2 = strtok(NULL, "@"); 239 char *token3 = strtok(user, "@"); 240 char *token4 = strtok(NULL, "@"); 241 242 /* 243 * token1 and token3 contain usernames 244 * token2 and token4 contain hostnames 245 */ 246 if ((token1 == NULL) || (token3 == NULL)) 247 result = PAPI_NOT_AUTHORIZED; 248 else if ((token4 != NULL) && 249 (strcmp(token4, "localhost") == 0) && 250 (strcmp(token3, "root") == 0) || 251 (strcmp(token3, "lp") == 0)) { 252 /* 253 * root/lp user on server can 254 * cancel any requset 255 */ 256 result = PAPI_OK; 257 } else if (strcmp(token1, token3) == 0) { 258 /* 259 * usernames are same 260 * compare the hostnames 261 */ 262 if ((token4 != NULL) && 263 (token2 != NULL) && 264 (strcmp(token4, "localhost") == 265 0)) { 266 /* 267 * Its server machine 268 */ 269 static char host[256]; 270 if (gethostname(host, 271 sizeof (host)) == 0) { 272 if ((host != NULL) && 273 (strcmp(host, 274 token2) == 0)) 275 result = 276 PAPI_OK; 277 } 278 279 } else if ((token4 != NULL) && 280 (token2 != NULL) && 281 (strcmp(token4, token2) == 0)) { 282 result = PAPI_OK; 283 } else if ((token4 == NULL) && 284 (token2 != NULL)) { 285 /* 286 * When the request is sent from 287 * client to server using ipp 288 * token4 is NULL 289 */ 290 result = PAPI_OK; 291 } 292 } 293 } 294 } 295 296 freerequest(r); 297 } else 298 result = PAPI_NOT_FOUND; 299 300 return (result); 301 } 302 303 static papi_status_t 304 copy_file(char *from, char *to) 305 { 306 int ifd, ofd; 307 char buf[BUFSIZ]; 308 int rc; 309 310 if ((ifd = open(from, O_RDONLY)) < 0) 311 return (PAPI_DOCUMENT_ACCESS_ERROR); 312 313 if ((ofd = open(to, O_WRONLY)) < 0) { 314 close(ifd); 315 return (PAPI_NOT_POSSIBLE); 316 } 317 318 while ((rc = read(ifd, buf, sizeof (buf))) > 0) 319 write(ofd, buf, rc); 320 321 close(ifd); 322 close(ofd); 323 324 return (PAPI_OK); 325 } 326 327 328 #ifdef LP_USE_PAPI_ATTR 329 /* 330 * ***************************************************************************** 331 * 332 * Description: Create a file containing all the attributes in the attribute 333 * list passed to this function. 334 * This file is then passed through lpsched and given to either 335 * a slow-filter or to the printer's interface script to process 336 * the attributes. 337 * 338 * Parameters: attrs - list of attributes and their values 339 * file - file pathname to create and put the attributes into. 340 * 341 * ***************************************************************************** 342 */ 343 344 static papi_status_t 345 psm_copy_attrsToFile(papi_attribute_t **attrs, char *file) 346 347 { 348 papi_status_t result = PAPI_OK; 349 350 if ((attrs != NULL) && (*attrs != NULL)) { 351 FILE *out = NULL; 352 353 if ((out = fopen(file, "w")) != NULL) { 354 papiAttributeListPrint(out, attrs, ""); 355 fclose(out); 356 } else { 357 result = PAPI_NOT_POSSIBLE; 358 } 359 } 360 361 return (result); 362 } /* psm_copy_attrsToFile */ 363 364 365 /* 366 * ***************************************************************************** 367 * 368 * Description: Modify the given attribute 'file' with the attributes from the 369 * 'attrs' list. Attributes already in the file will be replaced 370 * with the new value. New attributes will be added into the file. 371 * 372 * Parameters: attrs - list of attributes and their values 373 * file - file pathname to create and put the attributes into. 374 * 375 * ***************************************************************************** 376 */ 377 378 static papi_status_t 379 psm_modifyAttrsFile(papi_attribute_t **attrs, char *file) 380 381 { 382 papi_status_t result = PAPI_OK; 383 papi_attribute_t **newAttrs = NULL; 384 struct stat tmpBuf; 385 FILE *fd = NULL; 386 387 if ((attrs != NULL) && (*attrs != NULL) && (file != NULL)) { 388 389 /* 390 * check file exist before try to modify it, if it doesn't 391 * exist assume there is an error 392 */ 393 if (stat(file, &tmpBuf) == 0) { 394 /* 395 * if file is currently empty just write the given 396 * attributes to the file otherwise exact the attributes 397 * from the file and modify them accordingly before 398 * writing them back to the file 399 */ 400 if (tmpBuf.st_size == 0) { 401 newAttrs = (papi_attribute_t **)attrs; 402 403 fd = fopen(file, "w"); 404 if (fd != NULL) { 405 papiAttributeListPrint(fd, 406 newAttrs, ""); 407 fclose(fd); 408 } else { 409 result = PAPI_NOT_POSSIBLE; 410 } 411 } else { 412 result = 413 psm_modifyAttrsList(file, attrs, &newAttrs); 414 415 fd = fopen(file, "w"); 416 if (fd != NULL) { 417 papiAttributeListPrint(fd, 418 newAttrs, ""); 419 fclose(fd); 420 } else { 421 result = PAPI_NOT_POSSIBLE; 422 } 423 424 papiAttributeListFree(newAttrs); 425 } 426 } else { 427 result = PAPI_NOT_POSSIBLE; 428 } 429 } 430 431 return (result); 432 } /* psm_modifyAttrsFile */ 433 434 435 /* 436 * ***************************************************************************** 437 * 438 * Description: Extracts the attributes in the given attribute 'file' and 439 * creates a new list 'newAttrs' containing the modified list of 440 * attributes. 441 * 442 * Parameters: file - pathname of file containing attributes to be modified 443 * attrs - list of attributes and their values to modify 444 * newAttrs - returns the modified list of attributes 445 * 446 * ***************************************************************************** 447 */ 448 449 static papi_status_t 450 psm_modifyAttrsList(char *file, papi_attribute_t **attrs, 451 papi_attribute_t ***newAttrs) 452 453 { 454 papi_status_t result = PAPI_OK; 455 papi_attribute_t *nextAttr = NULL; 456 papi_attribute_value_t **values = NULL; 457 void *iter = NULL; 458 FILE *fd = NULL; 459 register int fD = 0; 460 char aBuff[200]; 461 char *a = NULL; 462 char *p = NULL; 463 int count = 0; 464 int n = 0; 465 466 fd = fopen(file, "r"); 467 if (fd != NULL) { 468 fD = fileno(fd); 469 a = &aBuff[0]; 470 p = &aBuff[0]; 471 count = read(fD, &aBuff[0], sizeof (aBuff) - 1); 472 while ((result == PAPI_OK) && (count > 0)) { 473 aBuff[count+n] = '\0'; 474 if (count == sizeof (aBuff) - n - 1) { 475 p = strrchr(aBuff, '\n'); 476 if (p != NULL) { 477 /* terminate at last complete line */ 478 *p = '\0'; 479 } 480 } 481 result = papiAttributeListFromString( 482 newAttrs, PAPI_ATTR_EXCL, aBuff); 483 484 if (result == PAPI_OK) { 485 /* 486 * handle any part lines and then read the next 487 * buffer from the file 488 */ 489 n = 0; 490 if (p != a) { 491 p++; /* skip NL */ 492 n = sizeof (aBuff) - 1 - (p - a); 493 strncpy(aBuff, p, n); 494 } 495 count = read(fD, &aBuff[n], 496 sizeof (aBuff) - n - 1); 497 p = &aBuff[0]; 498 } 499 } 500 fclose(fd); 501 } 502 503 /* now modify the attribute list with the new attributes in 'attrs' */ 504 505 nextAttr = papiAttributeListGetNext((papi_attribute_t **)attrs, &iter); 506 while ((result == PAPI_OK) && (nextAttr != NULL)) { 507 values = nextAttr->values; 508 509 if ((values != NULL) && (*values != NULL)) { 510 result = papiAttributeListAddValue(newAttrs, 511 PAPI_ATTR_REPLACE, 512 nextAttr->name, 513 nextAttr->type, *values); 514 values++; 515 } 516 517 while ((result == PAPI_OK) && 518 (values != NULL) && (*values != NULL)) { 519 result = papiAttributeListAddValue(newAttrs, 520 PAPI_ATTR_APPEND, 521 nextAttr->name, 522 nextAttr->type, *values); 523 values++; 524 } 525 nextAttr = 526 papiAttributeListGetNext((papi_attribute_t **)attrs, &iter); 527 } 528 529 return (result); 530 } /* papi_modifyAttrsList() */ 531 #endif 532 533 534 papi_status_t 535 papiJobSubmit(papi_service_t handle, char *printer, 536 papi_attribute_t **job_attributes, 537 papi_job_ticket_t *job_ticket, 538 char **files, papi_job_t *job) 539 { 540 papi_status_t status; 541 service_t *svc = handle; 542 struct stat statbuf; 543 job_t *j; 544 int file_no; 545 char *request_id = NULL; 546 REQUEST *request; 547 int i; 548 char *c; 549 char *tmp = NULL; 550 char lpfile[BUFSIZ]; 551 552 if ((svc == NULL) || (printer == NULL) || (files == NULL) || 553 (job == NULL)) 554 return (PAPI_BAD_ARGUMENT); 555 556 if (job_ticket != NULL) 557 return (PAPI_OPERATION_NOT_SUPPORTED); 558 559 if (files != NULL) 560 for (file_no = 0; files[file_no] != NULL; file_no++) { 561 if (access(files[file_no], R_OK) < 0) { 562 detailed_error(svc, 563 gettext("Cannot access file: %s: %s"), 564 files[file_no], strerror(errno)); 565 return (PAPI_BAD_ARGUMENT); 566 } 567 if (stat(files[file_no], &statbuf) < 0) { 568 detailed_error(svc, 569 gettext("Cannot access file: %s: %s"), 570 files[file_no], strerror(errno)); 571 return (PAPI_DOCUMENT_ACCESS_ERROR); 572 } 573 if (statbuf.st_size == 0) { 574 detailed_error(svc, 575 gettext("Zero byte (empty) file: %s"), 576 files[file_no]); 577 return (PAPI_BAD_ARGUMENT); 578 } 579 } 580 581 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 582 return (PAPI_TEMPORARY_ERROR); 583 584 /* file_no + 1 for the control file (-0) */ 585 status = lpsched_alloc_files(svc, file_no + 1, &request_id); 586 if (status != PAPI_OK) 587 return (status); 588 589 request = create_request(svc, (char *)printer, 590 (papi_attribute_t **)job_attributes); 591 592 for (i = 0; files[i] != NULL; i++) { 593 papi_status_t status; 594 snprintf(lpfile, sizeof (lpfile), "%s%s-%d", 595 "/var/spool/lp/temp/", request_id, i+1); 596 status = copy_file(files[i], lpfile); 597 if (status != PAPI_OK) { 598 detailed_error(svc, 599 gettext("unable to copy: %s -> %s: %s"), 600 files[i], lpfile, strerror(errno)); 601 freerequest(request); 602 return (PAPI_DEVICE_ERROR); 603 } 604 addlist(&(request->file_list), lpfile); 605 } 606 607 #ifdef LP_USE_PAPI_ATTR 608 /* 609 * store the job attributes in the PAPI job attribute file that was 610 * created by lpsched_alloc_files(), the attributes will then pass 611 * through lpsched and be given to the slow-filters and the printer's 612 * interface script to process them 613 */ 614 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 615 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 616 status = psm_copy_attrsToFile(job_attributes, lpfile); 617 if (status != PAPI_OK) { 618 detailed_error(svc, "unable to copy attributes to file: %s: %s", 619 lpfile, strerror(errno)); 620 return (PAPI_DEVICE_ERROR); 621 } 622 #endif 623 624 /* store the meta-data file */ 625 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 626 if (putrequest(lpfile, request) < 0) { 627 detailed_error(svc, gettext("unable to save request: %s: %s"), 628 lpfile, strerror(errno)); 629 freerequest(request); 630 return (PAPI_DEVICE_ERROR); 631 } 632 633 status = lpsched_commit_job(svc, lpfile, &tmp); 634 if (status != PAPI_OK) { 635 unlink(lpfile); 636 freerequest(request); 637 return (status); 638 } 639 640 lpsched_request_to_job_attributes(request, j); 641 freerequest(request); 642 643 if ((c = strrchr(tmp, '-')) != NULL) 644 c++; 645 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 646 "job-id", atoi(c)); 647 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 648 "job-uri", tmp); 649 650 return (PAPI_OK); 651 } 652 653 papi_status_t 654 papiJobSubmitByReference(papi_service_t handle, char *printer, 655 papi_attribute_t **job_attributes, 656 papi_job_ticket_t *job_ticket, 657 char **files, papi_job_t *job) 658 { 659 service_t *svc = handle; 660 struct stat statbuf; 661 job_t *j; 662 int file_no; 663 short status; 664 char *request_id = NULL; 665 REQUEST *request; 666 char *c; 667 char *tmp = NULL; 668 char lpfile[BUFSIZ]; 669 char **file_list = NULL; 670 671 if ((svc == NULL) || (printer == NULL) || (files == NULL) || 672 (job == NULL)) 673 return (PAPI_BAD_ARGUMENT); 674 675 if (job_ticket != NULL) 676 return (PAPI_OPERATION_NOT_SUPPORTED); 677 678 if (files != NULL) 679 for (file_no = 0; files[file_no] != NULL; file_no++) { 680 if (access(files[file_no], R_OK) < 0) { 681 detailed_error(svc, 682 gettext("Cannot access file: %s: %s"), 683 files[file_no], strerror(errno)); 684 return (PAPI_DOCUMENT_ACCESS_ERROR); 685 } 686 if (stat(files[file_no], &statbuf) < 0) { 687 detailed_error(svc, 688 gettext("Cannot access file: %s: %s"), 689 files[file_no], strerror(errno)); 690 return (PAPI_DOCUMENT_ACCESS_ERROR); 691 } 692 if (statbuf.st_size == 0) { 693 detailed_error(svc, 694 gettext("Zero byte (empty) file: %s"), 695 files[file_no]); 696 return (PAPI_BAD_ARGUMENT); 697 } 698 699 if (files[file_no][0] != '/') { 700 char path[MAXPATHLEN]; 701 702 if (getcwd(path, sizeof (path)) == NULL) { 703 detailed_error(svc, gettext( 704 "getcwd for file: %s: %s"), 705 files[file_no], 706 strerror(errno)); 707 return (PAPI_DOCUMENT_ACCESS_ERROR); 708 } 709 strlcat(path, "/", sizeof (path)); 710 if (strlcat(path, files[file_no], sizeof (path)) 711 >= sizeof (path)) { 712 detailed_error(svc, gettext( 713 "pathname too long: %s"), 714 files[file_no]); 715 return (PAPI_DOCUMENT_ACCESS_ERROR); 716 } 717 addlist(&file_list, path); 718 } else 719 addlist(&file_list, (char *)files[file_no]); 720 } 721 722 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 723 return (PAPI_TEMPORARY_ERROR); 724 725 /* 1 for the control file (-0) */ 726 status = lpsched_alloc_files(svc, 1, &request_id); 727 if (status != PAPI_OK) 728 return (status); 729 730 request = create_request(svc, (char *)printer, 731 (papi_attribute_t **)job_attributes); 732 request->file_list = file_list; 733 734 #ifdef LP_USE_PAPI_ATTR 735 /* 736 * store the job attributes in the PAPI job attribute file that was 737 * created by lpsched_alloc_files(), the attributes will then pass 738 * through lpsched and be given to the slow-filters and the printer's 739 * interface script to process them 740 */ 741 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 742 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 743 status = psm_copy_attrsToFile(job_attributes, lpfile); 744 if (status != PAPI_OK) { 745 detailed_error(svc, "unable to copy attributes to file: %s: %s", 746 lpfile, strerror(errno)); 747 return (PAPI_DEVICE_ERROR); 748 } 749 #endif 750 751 /* store the meta-data file */ 752 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 753 if (putrequest(lpfile, request) < 0) { 754 detailed_error(svc, gettext("unable to save request: %s: %s"), 755 lpfile, strerror(errno)); 756 freerequest(request); 757 return (PAPI_DEVICE_ERROR); 758 } 759 760 status = lpsched_commit_job(svc, lpfile, &tmp); 761 if (status != PAPI_OK) { 762 unlink(lpfile); 763 freerequest(request); 764 return (status); 765 } 766 767 lpsched_request_to_job_attributes(request, j); 768 769 freerequest(request); 770 771 if ((c = strrchr(tmp, '-')) != NULL) 772 c++; 773 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 774 "job-id", atoi(c)); 775 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 776 "job-uri", tmp); 777 778 return (PAPI_OK); 779 } 780 781 papi_status_t 782 papiJobValidate(papi_service_t handle, char *printer, 783 papi_attribute_t **job_attributes, 784 papi_job_ticket_t *job_ticket, 785 char **files, papi_job_t *job) 786 { 787 papi_status_t status; 788 papi_attribute_t **attributes = NULL; 789 int i; 790 791 papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE, 792 "job-hold-until", "indefinite"); 793 for (i = 0; job_attributes[i]; i++) 794 list_append(&attributes, job_attributes[i]); 795 796 status = papiJobSubmitByReference(handle, printer, 797 (papi_attribute_t **)attributes, 798 job_ticket, files, job); 799 if (status == PAPI_OK) { 800 int id = papiJobGetId(*job); 801 802 if (id != -1) 803 papiJobCancel(handle, printer, id); 804 } 805 806 attributes[1] = NULL; /* after attr[0], they are in another list */ 807 papiAttributeListFree(attributes); 808 809 return (status); 810 } 811 812 papi_status_t 813 papiJobStreamOpen(papi_service_t handle, char *printer, 814 papi_attribute_t **job_attributes, 815 papi_job_ticket_t *job_ticket, papi_stream_t *stream) 816 { 817 papi_status_t status; 818 service_t *svc = handle; 819 job_stream_t *s = NULL; 820 char *request_id = NULL; 821 char lpfile[BUFSIZ]; 822 823 if ((svc == NULL) || (printer == NULL) || (stream == NULL)) 824 return (PAPI_BAD_ARGUMENT); 825 826 if (job_ticket != NULL) 827 return (PAPI_OPERATION_NOT_SUPPORTED); 828 829 if ((*stream = s = calloc(1, sizeof (*s))) == NULL) 830 return (PAPI_TEMPORARY_ERROR); 831 832 /* 1 for data, 1 for the meta-data (-0) */ 833 status = lpsched_alloc_files(svc, 2, &request_id); 834 if (status != PAPI_OK) 835 return (status); 836 837 s->request = create_request(svc, (char *)printer, 838 (papi_attribute_t **)job_attributes); 839 snprintf(lpfile, sizeof (lpfile), "/var/spool/lp/temp/%s-1", 840 request_id); 841 s->fd = open(lpfile, O_WRONLY); 842 addlist(&(s->request->file_list), lpfile); 843 844 #ifdef LP_USE_PAPI_ATTR 845 /* 846 * store the job attributes in the PAPI job attribute file that was 847 * created by lpsched_alloc_files(), the attributes will then pass 848 * through lpsched and be given to the slow-filters and the printer's 849 * interface script to process them 850 */ 851 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 852 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 853 status = psm_copy_attrsToFile(job_attributes, lpfile); 854 if (status != PAPI_OK) { 855 detailed_error(svc, "unable to copy attributes to file: %s: %s", 856 lpfile, strerror(errno)); 857 close(s->fd); 858 free(s); 859 return (PAPI_DEVICE_ERROR); 860 } 861 #endif 862 863 /* store the meta-data file */ 864 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 865 s->meta_data_file = strdup(lpfile); 866 if (putrequest(lpfile, s->request) < 0) { 867 detailed_error(svc, gettext("unable to save request: %s: %s"), 868 lpfile, strerror(errno)); 869 s->request = NULL; 870 return (PAPI_DEVICE_ERROR); 871 } 872 873 return (PAPI_OK); 874 } 875 876 papi_status_t 877 papiJobStreamWrite(papi_service_t handle, 878 papi_stream_t stream, void *buffer, size_t buflen) 879 { 880 service_t *svc = handle; 881 job_stream_t *s = stream; 882 883 if ((svc == NULL) || (stream == NULL) || (buffer == NULL)) 884 return (PAPI_BAD_ARGUMENT); 885 886 if (write(s->fd, buffer, buflen) != buflen) 887 return (PAPI_DEVICE_ERROR); 888 889 return (PAPI_OK); 890 } 891 papi_status_t 892 papiJobStreamClose(papi_service_t handle, 893 papi_stream_t stream, papi_job_t *job) 894 { 895 papi_status_t status = PAPI_OK; 896 service_t *svc = handle; 897 job_stream_t *s = stream; 898 job_t *j = NULL; 899 char *tmp = NULL, *c; 900 901 if ((svc == NULL) || (stream == NULL) || (job == NULL)) 902 return (PAPI_BAD_ARGUMENT); 903 904 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 905 return (PAPI_TEMPORARY_ERROR); 906 907 close(s->fd); 908 909 lpsched_request_to_job_attributes(s->request, j); 910 911 if (s->meta_data_file != NULL) { 912 status = lpsched_commit_job(svc, s->meta_data_file, &tmp); 913 if (status != PAPI_OK) { 914 unlink(s->meta_data_file); 915 return (status); 916 } 917 if ((c = strrchr(tmp, '-')) != NULL) 918 c++; 919 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 920 "job-id", atoi(c)); 921 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 922 "job-uri", tmp); 923 free(s->meta_data_file); 924 } 925 freerequest(s->request); 926 free(s); 927 928 return (PAPI_OK); 929 } 930 931 papi_status_t 932 papiJobQuery(papi_service_t handle, char *printer, int32_t job_id, 933 char **requested_attrs, 934 papi_job_t *job) 935 { 936 service_t *svc = handle; 937 job_t *j; 938 char *dest; 939 char req_id[32]; 940 short rc; 941 char *form = NULL, 942 *request_id = NULL, 943 *charset = NULL, 944 *user = NULL, 945 *slabel = NULL, 946 *file = NULL; 947 time_t date = 0; 948 size_t size = 0; 949 short rank = 0, 950 state = 0; 951 952 if ((handle == NULL) || (printer == NULL) || (job_id < 0)) 953 return (PAPI_BAD_ARGUMENT); 954 955 dest = printer_name_from_uri_id(printer, job_id); 956 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); 957 free(dest); 958 959 rc = snd_msg(svc, S_INQUIRE_REQUEST_RANK, 0, "", "", req_id, "", ""); 960 if (rc < 0) 961 return (PAPI_SERVICE_UNAVAILABLE); 962 963 if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &request_id, 964 &user, &slabel, &size, &date, &state, &dest, &form, 965 &charset, &rank, &file) < 0) { 966 detailed_error(svc, 967 gettext("failed to read response from scheduler")); 968 return (PAPI_DEVICE_ERROR); 969 } 970 971 if ((request_id == NULL) || (request_id[0] == NULL)) 972 return (PAPI_NOT_FOUND); 973 974 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 975 return (PAPI_TEMPORARY_ERROR); 976 977 snprintf(req_id, sizeof (req_id), "%d-0", job_id); 978 lpsched_read_job_configuration(svc, j, req_id); 979 980 job_status_to_attributes(j, request_id, user, slabel, size, date, state, 981 dest, form, charset, rank, file); 982 983 return (PAPI_OK); 984 } 985 986 papi_status_t 987 papiJobMove(papi_service_t handle, char *printer, int32_t job_id, 988 char *destination) 989 { 990 papi_status_t result = PAPI_OK; 991 long bits; 992 service_t *svc = handle; 993 char req_id[64]; 994 char *queue; 995 char *user = NULL; 996 997 if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 998 (destination == NULL)) 999 return (PAPI_BAD_ARGUMENT); 1000 1001 queue = printer_name_from_uri_id(printer, job_id); 1002 snprintf(req_id, sizeof (req_id), "%s-%d", queue, job_id); 1003 free(queue); 1004 1005 if (papiAttributeListGetString(svc->attributes, NULL, "user-name", 1006 &user) == PAPI_OK) { 1007 REQUEST *r = getrequest(req_id); 1008 1009 if ((r != NULL) && (r->user != NULL) && 1010 (strcmp(r->user, user) != 0)) 1011 result = PAPI_NOT_AUTHORIZED; 1012 freerequest(r); 1013 } 1014 1015 if (result == PAPI_OK) { 1016 short status = MOK; 1017 char *dest = printer_name_from_uri_id(destination, -1); 1018 1019 if ((snd_msg(svc, S_MOVE_REQUEST, req_id, dest) < 0) || 1020 (rcv_msg(svc, R_MOVE_REQUEST, &status, &bits) < 0)) 1021 status = MTRANSMITERR; 1022 1023 free(dest); 1024 1025 result = lpsched_status_to_papi_status(status); 1026 } 1027 1028 return (result); 1029 } 1030 1031 papi_status_t 1032 papiJobCancel(papi_service_t handle, char *printer, int32_t job_id) 1033 { 1034 papi_status_t result = PAPI_OK; 1035 service_t *svc = handle; 1036 char req_id[64]; 1037 char *dest; 1038 char *user = NULL; 1039 1040 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 1041 return (PAPI_BAD_ARGUMENT); 1042 1043 dest = printer_name_from_uri_id(printer, job_id); 1044 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); 1045 free(dest); 1046 1047 if (papiAttributeListGetString(svc->attributes, NULL, "user-name", 1048 &user) == PAPI_OK) { 1049 REQUEST *r = getrequest(req_id); 1050 1051 if ((result = authorized(handle, job_id)) != PAPI_OK) 1052 result = PAPI_NOT_AUTHORIZED; 1053 1054 if ((r != NULL) && (r->user != NULL) && 1055 (strcmp(r->user, user) != 0)) 1056 result = PAPI_NOT_AUTHORIZED; 1057 freerequest(r); 1058 } 1059 1060 if (result == PAPI_OK) { 1061 short status = MOK; 1062 1063 if ((snd_msg(svc, S_CANCEL_REQUEST, req_id) < 0) || 1064 (rcv_msg(svc, R_CANCEL_REQUEST, &status) < 0)) 1065 status = MTRANSMITERR; 1066 1067 result = lpsched_status_to_papi_status(status); 1068 } 1069 1070 return (result); 1071 } 1072 1073 papi_status_t 1074 hold_release_job(papi_service_t handle, char *printer, 1075 int32_t job_id, int flag) 1076 { 1077 papi_status_t status; 1078 service_t *svc = handle; 1079 REQUEST *r = NULL; 1080 char *file; 1081 char *dest; 1082 1083 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 1084 return (PAPI_BAD_ARGUMENT); 1085 1086 if ((status = authorized(svc, job_id)) != PAPI_OK) 1087 return (status); 1088 1089 dest = printer_name_from_uri_id(printer, job_id); 1090 status = lpsched_start_change(svc, dest, job_id, &file); 1091 if (status != PAPI_OK) 1092 return (status); 1093 1094 if ((r = getrequest(file)) != NULL) { 1095 r->actions &= ~ACT_RESUME; 1096 switch (flag) { 1097 case 0: 1098 r->actions |= ACT_HOLD; 1099 break; 1100 case 1: 1101 r->actions |= ACT_RESUME; 1102 break; 1103 case 2: 1104 r->actions |= ACT_IMMEDIATE; 1105 break; 1106 } 1107 if (putrequest(file, r) < 0) { 1108 detailed_error(svc, 1109 gettext("failed to write job: %s: %s"), 1110 file, strerror(errno)); 1111 freerequest(r); 1112 return (PAPI_DEVICE_ERROR); 1113 } 1114 freerequest(r); 1115 } else { 1116 detailed_error(svc, gettext("failed to read job: %s: %s"), 1117 file, strerror(errno)); 1118 return (PAPI_DEVICE_ERROR); 1119 } 1120 1121 status = lpsched_end_change(svc, dest, job_id); 1122 1123 return (status); 1124 } 1125 1126 papi_status_t 1127 papiJobHold(papi_service_t handle, char *printer, int32_t job_id) 1128 { 1129 return (hold_release_job(handle, printer, job_id, 0)); 1130 } 1131 1132 papi_status_t 1133 papiJobRelease(papi_service_t handle, char *printer, int32_t job_id) 1134 { 1135 return (hold_release_job(handle, printer, job_id, 1)); 1136 } 1137 1138 papi_status_t 1139 papiJobPromote(papi_service_t handle, char *printer, int32_t job_id) 1140 { 1141 return (hold_release_job(handle, printer, job_id, 2)); 1142 } 1143 1144 papi_status_t 1145 papiJobModify(papi_service_t handle, char *printer, int32_t job_id, 1146 papi_attribute_t **attributes, papi_job_t *job) 1147 { 1148 papi_status_t status; 1149 job_t *j = NULL; 1150 service_t *svc = handle; 1151 char *file = NULL; 1152 char *dest; 1153 REQUEST *r = NULL; 1154 char lpfile[BUFSIZ]; 1155 int32_t job_id_actual; 1156 1157 if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 1158 (attributes == NULL)) 1159 return (PAPI_BAD_ARGUMENT); 1160 1161 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 1162 return (PAPI_TEMPORARY_ERROR); 1163 1164 dest = printer_name_from_uri_id(printer, job_id); 1165 1166 /* 1167 * job-id might be job-id-requested 1168 * If it is job-id-requested then we need to 1169 * look for corresponding job-id 1170 */ 1171 job_id_actual = check_job_id(svc, printer, job_id); 1172 1173 if (job_id_actual < 0) { 1174 status = PAPI_NOT_FOUND; 1175 detailed_error(svc, 1176 "failed to initiate change for job (%s-%d): %s", 1177 dest, job_id, "no such resource"); 1178 return (status); 1179 } 1180 1181 status = lpsched_start_change(svc, dest, job_id_actual, &file); 1182 if (status != PAPI_OK) 1183 return (status); 1184 1185 if ((r = getrequest(file)) != NULL) { 1186 job_attributes_to_lpsched_request(handle, r, 1187 (papi_attribute_t **)attributes); 1188 #ifdef LP_USE_PAPI_ATTR 1189 /* 1190 * store the job attributes in the PAPI job attribute file 1191 * that was created by the original job request. We need to 1192 * modify the attributes in the file as per the new attributes 1193 */ 1194 snprintf(lpfile, sizeof (lpfile), "%s%d-%s", 1195 "/var/spool/lp/temp/", job_id_actual, LP_PAPIATTRNAME); 1196 status = psm_modifyAttrsFile(attributes, lpfile); 1197 if (status != PAPI_OK) { 1198 detailed_error(svc, 1199 "unable to modify the attributes file: %s: %s", 1200 lpfile, strerror(errno)); 1201 return (PAPI_DEVICE_ERROR); 1202 } 1203 #endif 1204 1205 if (putrequest(file, r) < 0) { 1206 detailed_error(svc, 1207 gettext("failed to write job: %s: %s"), 1208 file, strerror(errno)); 1209 freerequest(r); 1210 return (PAPI_DEVICE_ERROR); 1211 } 1212 } else { 1213 detailed_error(svc, gettext("failed to read job: %s: %s"), 1214 file, strerror(errno)); 1215 return (PAPI_DEVICE_ERROR); 1216 } 1217 1218 status = lpsched_end_change(svc, dest, job_id_actual); 1219 lpsched_request_to_job_attributes(r, j); 1220 1221 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 1222 "job-id", job_id_actual); 1223 1224 freerequest(r); 1225 1226 return (status); 1227 } 1228 1229 /* 1230 * Extension to PAPI, a variation of this is slated for post-1.0 1231 */ 1232 #define DUMMY_FILE "/var/spool/lp/fifos/FIFO" 1233 1234 papi_status_t 1235 papiJobCreate(papi_service_t handle, char *printer, 1236 papi_attribute_t **job_attributes, 1237 papi_job_ticket_t *job_ticket, papi_job_t *job) 1238 { 1239 papi_status_t status; 1240 service_t *svc = handle; 1241 job_t *j = NULL; 1242 REQUEST *request; 1243 char *request_id = NULL; 1244 char *c; 1245 char *tmp = NULL; 1246 char metadata_file[MAXPATHLEN]; 1247 1248 if ((svc == NULL) || (printer == NULL) || (job == NULL)) 1249 return (PAPI_BAD_ARGUMENT); 1250 1251 if (job_ticket != NULL) 1252 return (PAPI_JOB_TICKET_NOT_SUPPORTED); 1253 1254 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 1255 return (PAPI_TEMPORARY_ERROR); 1256 1257 /* 1 for the control file (-0) */ 1258 status = lpsched_alloc_files(svc, 1, &request_id); 1259 if (status != PAPI_OK) 1260 return (status); 1261 1262 /* convert the attributes to an lpsched REQUEST structure */ 1263 request = create_request(svc, (char *)printer, 1264 (papi_attribute_t **)job_attributes); 1265 if (request == NULL) 1266 return (PAPI_TEMPORARY_ERROR); 1267 addlist(&request->file_list, DUMMY_FILE); /* add a dummy file */ 1268 request->actions |= ACT_HOLD; /* hold the job */ 1269 1270 #ifdef LP_USE_PAPI_ATTR 1271 /* 1272 * store the job attributes in the PAPI job attribute file that was 1273 * created by lpsched_alloc_files(), the attributes will then pass 1274 * through lpsched and be given to the slow-filters and the printer's 1275 * interface script to process them 1276 */ 1277 snprintf(metadata_file, sizeof (metadata_file), "%s%s-%s", 1278 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 1279 status = psm_copy_attrsToFile(job_attributes, metadata_file); 1280 if (status != PAPI_OK) { 1281 detailed_error(svc, "unable to copy attributes to file: %s: %s", 1282 metadata_file, strerror(errno)); 1283 free(request_id); 1284 return (PAPI_DEVICE_ERROR); 1285 } 1286 #endif 1287 1288 /* store the REQUEST on disk */ 1289 snprintf(metadata_file, sizeof (metadata_file), "%s-0", request_id); 1290 free(request_id); 1291 if (putrequest(metadata_file, request) < 0) { 1292 detailed_error(svc, gettext("unable to save request: %s: %s"), 1293 metadata_file, strerror(errno)); 1294 return (PAPI_DEVICE_ERROR); 1295 } 1296 1297 status = lpsched_commit_job(svc, metadata_file, &tmp); 1298 if (status != PAPI_OK) { 1299 unlink(metadata_file); 1300 return (status); 1301 } 1302 1303 lpsched_request_to_job_attributes(request, j); 1304 1305 if ((c = strrchr(tmp, '-')) != NULL) 1306 c++; 1307 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 1308 "job-id", atoi(c)); 1309 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 1310 "job-uri", tmp); 1311 1312 return (PAPI_OK); 1313 } 1314 1315 papi_status_t 1316 papiJobCommit(papi_service_t handle, char *printer, int32_t id) 1317 { 1318 papi_status_t status = PAPI_OK; 1319 service_t *svc = handle; 1320 REQUEST *r = NULL; 1321 char *metadata_file; 1322 char *dest; 1323 1324 if ((svc == NULL) || (printer == NULL)) 1325 return (PAPI_BAD_ARGUMENT); 1326 1327 dest = printer_name_from_uri_id(printer, id); 1328 /* tell the scheduler that we want to change the job */ 1329 status = lpsched_start_change(svc, dest, id, &metadata_file); 1330 if (status != PAPI_OK) 1331 return (status); 1332 1333 if ((r = getrequest(metadata_file)) != NULL) { 1334 r->actions &= ~ACT_RESUME; 1335 r->actions |= ACT_RESUME; 1336 dellist(&r->file_list, DUMMY_FILE); 1337 1338 if (putrequest(metadata_file, r) < 0) { 1339 detailed_error(svc, 1340 gettext("failed to write job: %s: %s"), 1341 metadata_file, strerror(errno)); 1342 freerequest(r); 1343 return (PAPI_DEVICE_ERROR); 1344 } 1345 } else { 1346 detailed_error(svc, gettext("failed to read job: %s: %s"), 1347 metadata_file, strerror(errno)); 1348 return (PAPI_DEVICE_ERROR); 1349 } 1350 1351 status = lpsched_end_change(svc, dest, id); 1352 freerequest(r); 1353 1354 return (status); 1355 } 1356 1357 papi_status_t 1358 papiJobStreamAdd(papi_service_t handle, char *printer, int32_t id, 1359 papi_stream_t *stream) 1360 { 1361 papi_status_t status; 1362 service_t *svc = handle; 1363 job_stream_t *s = NULL; 1364 char *metadata_file = NULL; 1365 char *dest; 1366 char path[MAXPATHLEN]; 1367 1368 /* allocate space for the stream */ 1369 if ((*stream = s = calloc(1, sizeof (*s))) == NULL) 1370 return (PAPI_TEMPORARY_ERROR); 1371 1372 dest = printer_name_from_uri_id(printer, id); 1373 /* create/open data file (only root or lp can really do this */ 1374 snprintf(path, sizeof (path), "/var/spool/lp/temp/%d-XXXXXX", id); 1375 if ((s->fd = mkstemp(path)) < 0) { 1376 detailed_error(svc, gettext("unable to create sink (%s): %s"), 1377 path, strerror(errno)); 1378 free(s); 1379 return (PAPI_NOT_AUTHORIZED); 1380 } 1381 1382 /* add data file to job */ 1383 status = lpsched_start_change(svc, dest, id, &metadata_file); 1384 if (status != PAPI_OK) { 1385 close(s->fd); 1386 free(s); 1387 unlink(path); 1388 return (status); 1389 } 1390 1391 if ((s->request = getrequest(metadata_file)) == NULL) { 1392 detailed_error(svc, gettext("unable to load request: %s: %s"), 1393 metadata_file, strerror(errno)); 1394 close(s->fd); 1395 free(s); 1396 unlink(path); 1397 return (PAPI_NOT_POSSIBLE); 1398 } 1399 1400 addlist(&(s->request->file_list), path); 1401 1402 if (putrequest(metadata_file, s->request) < 0) { 1403 detailed_error(svc, gettext("unable to save request: %s: %s"), 1404 metadata_file, strerror(errno)); 1405 close(s->fd); 1406 free(s); 1407 unlink(path); 1408 return (PAPI_NOT_POSSIBLE); 1409 } 1410 1411 status = lpsched_end_change(svc, dest, id); 1412 1413 if (status != PAPI_OK) 1414 return (status); 1415 1416 return (PAPI_OK); 1417 } 1418