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 papiAttributeListAddString(&job_attributes, PAPI_ATTR_EXCL, 838 "job-name", "standard input"); 839 840 s->request = create_request(svc, (char *)printer, 841 (papi_attribute_t **)job_attributes); 842 snprintf(lpfile, sizeof (lpfile), "/var/spool/lp/temp/%s-1", 843 request_id); 844 s->fd = open(lpfile, O_WRONLY); 845 addlist(&(s->request->file_list), lpfile); 846 847 #ifdef LP_USE_PAPI_ATTR 848 /* 849 * store the job attributes in the PAPI job attribute file that was 850 * created by lpsched_alloc_files(), the attributes will then pass 851 * through lpsched and be given to the slow-filters and the printer's 852 * interface script to process them 853 */ 854 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 855 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 856 status = psm_copy_attrsToFile(job_attributes, lpfile); 857 if (status != PAPI_OK) { 858 detailed_error(svc, "unable to copy attributes to file: %s: %s", 859 lpfile, strerror(errno)); 860 close(s->fd); 861 free(s); 862 return (PAPI_DEVICE_ERROR); 863 } 864 #endif 865 866 /* store the meta-data file */ 867 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 868 s->meta_data_file = strdup(lpfile); 869 if (putrequest(lpfile, s->request) < 0) { 870 detailed_error(svc, gettext("unable to save request: %s: %s"), 871 lpfile, strerror(errno)); 872 s->request = NULL; 873 return (PAPI_DEVICE_ERROR); 874 } 875 876 return (PAPI_OK); 877 } 878 879 papi_status_t 880 papiJobStreamWrite(papi_service_t handle, 881 papi_stream_t stream, void *buffer, size_t buflen) 882 { 883 service_t *svc = handle; 884 job_stream_t *s = stream; 885 886 if ((svc == NULL) || (stream == NULL) || (buffer == NULL)) 887 return (PAPI_BAD_ARGUMENT); 888 889 if (write(s->fd, buffer, buflen) != buflen) 890 return (PAPI_DEVICE_ERROR); 891 892 return (PAPI_OK); 893 } 894 papi_status_t 895 papiJobStreamClose(papi_service_t handle, 896 papi_stream_t stream, papi_job_t *job) 897 { 898 papi_status_t status = PAPI_OK; 899 service_t *svc = handle; 900 job_stream_t *s = stream; 901 job_t *j = NULL; 902 char *tmp = NULL, *c; 903 904 if ((svc == NULL) || (stream == NULL) || (job == NULL)) 905 return (PAPI_BAD_ARGUMENT); 906 907 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 908 return (PAPI_TEMPORARY_ERROR); 909 910 close(s->fd); 911 912 lpsched_request_to_job_attributes(s->request, j); 913 914 if (s->meta_data_file != NULL) { 915 status = lpsched_commit_job(svc, s->meta_data_file, &tmp); 916 if (status != PAPI_OK) { 917 unlink(s->meta_data_file); 918 return (status); 919 } 920 if ((c = strrchr(tmp, '-')) != NULL) 921 c++; 922 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 923 "job-id", atoi(c)); 924 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 925 "job-uri", tmp); 926 free(s->meta_data_file); 927 } 928 freerequest(s->request); 929 free(s); 930 931 return (PAPI_OK); 932 } 933 934 papi_status_t 935 papiJobQuery(papi_service_t handle, char *printer, int32_t job_id, 936 char **requested_attrs, 937 papi_job_t *job) 938 { 939 service_t *svc = handle; 940 job_t *j; 941 char *dest; 942 char req_id[32]; 943 short rc; 944 char *form = NULL, 945 *request_id = NULL, 946 *charset = NULL, 947 *user = NULL, 948 *slabel = NULL, 949 *file = NULL; 950 time_t date = 0; 951 size_t size = 0; 952 short rank = 0, 953 state = 0; 954 955 if ((handle == NULL) || (printer == NULL) || (job_id < 0)) 956 return (PAPI_BAD_ARGUMENT); 957 958 dest = printer_name_from_uri_id(printer, job_id); 959 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); 960 free(dest); 961 962 rc = snd_msg(svc, S_INQUIRE_REQUEST_RANK, 0, "", "", req_id, "", ""); 963 if (rc < 0) 964 return (PAPI_SERVICE_UNAVAILABLE); 965 966 if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &request_id, 967 &user, &slabel, &size, &date, &state, &dest, &form, 968 &charset, &rank, &file) < 0) { 969 detailed_error(svc, 970 gettext("failed to read response from scheduler")); 971 return (PAPI_DEVICE_ERROR); 972 } 973 974 if ((request_id == NULL) || (request_id[0] == '\0')) 975 return (PAPI_NOT_FOUND); 976 977 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 978 return (PAPI_TEMPORARY_ERROR); 979 980 snprintf(req_id, sizeof (req_id), "%d-0", job_id); 981 lpsched_read_job_configuration(svc, j, req_id); 982 983 job_status_to_attributes(j, request_id, user, slabel, size, date, state, 984 dest, form, charset, rank, file); 985 986 return (PAPI_OK); 987 } 988 989 papi_status_t 990 papiJobMove(papi_service_t handle, char *printer, int32_t job_id, 991 char *destination) 992 { 993 papi_status_t result = PAPI_OK; 994 long bits; 995 service_t *svc = handle; 996 char req_id[64]; 997 char *queue; 998 char *user = NULL; 999 1000 if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 1001 (destination == NULL)) 1002 return (PAPI_BAD_ARGUMENT); 1003 1004 queue = printer_name_from_uri_id(printer, job_id); 1005 snprintf(req_id, sizeof (req_id), "%s-%d", queue, job_id); 1006 free(queue); 1007 1008 if (papiAttributeListGetString(svc->attributes, NULL, "user-name", 1009 &user) == PAPI_OK) { 1010 REQUEST *r = getrequest(req_id); 1011 1012 if ((r != NULL) && (r->user != NULL) && 1013 (strcmp(r->user, user) != 0)) 1014 result = PAPI_NOT_AUTHORIZED; 1015 freerequest(r); 1016 } 1017 1018 if (result == PAPI_OK) { 1019 short status = MOK; 1020 char *dest = printer_name_from_uri_id(destination, -1); 1021 1022 if ((snd_msg(svc, S_MOVE_REQUEST, req_id, dest) < 0) || 1023 (rcv_msg(svc, R_MOVE_REQUEST, &status, &bits) < 0)) 1024 status = MTRANSMITERR; 1025 1026 free(dest); 1027 1028 result = lpsched_status_to_papi_status(status); 1029 } 1030 1031 return (result); 1032 } 1033 1034 papi_status_t 1035 papiJobCancel(papi_service_t handle, char *printer, int32_t job_id) 1036 { 1037 papi_status_t result = PAPI_OK; 1038 service_t *svc = handle; 1039 char req_id[64]; 1040 char *dest; 1041 char *user = NULL; 1042 1043 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 1044 return (PAPI_BAD_ARGUMENT); 1045 1046 dest = printer_name_from_uri_id(printer, job_id); 1047 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); 1048 free(dest); 1049 1050 if (papiAttributeListGetString(svc->attributes, NULL, "user-name", 1051 &user) == PAPI_OK) { 1052 REQUEST *r = getrequest(req_id); 1053 1054 if ((result = authorized(handle, job_id)) != PAPI_OK) 1055 result = PAPI_NOT_AUTHORIZED; 1056 1057 if ((r != NULL) && (r->user != NULL) && 1058 (strcmp(r->user, user) != 0)) 1059 result = PAPI_NOT_AUTHORIZED; 1060 freerequest(r); 1061 } 1062 1063 if (result == PAPI_OK) { 1064 short status = MOK; 1065 1066 if ((snd_msg(svc, S_CANCEL_REQUEST, req_id) < 0) || 1067 (rcv_msg(svc, R_CANCEL_REQUEST, &status) < 0)) 1068 status = MTRANSMITERR; 1069 1070 result = lpsched_status_to_papi_status(status); 1071 } 1072 1073 return (result); 1074 } 1075 1076 papi_status_t 1077 hold_release_job(papi_service_t handle, char *printer, 1078 int32_t job_id, int flag) 1079 { 1080 papi_status_t status; 1081 service_t *svc = handle; 1082 REQUEST *r = NULL; 1083 char *file; 1084 char *dest; 1085 1086 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 1087 return (PAPI_BAD_ARGUMENT); 1088 1089 if ((status = authorized(svc, job_id)) != PAPI_OK) 1090 return (status); 1091 1092 dest = printer_name_from_uri_id(printer, job_id); 1093 status = lpsched_start_change(svc, dest, job_id, &file); 1094 if (status != PAPI_OK) 1095 return (status); 1096 1097 if ((r = getrequest(file)) != NULL) { 1098 r->actions &= ~ACT_RESUME; 1099 switch (flag) { 1100 case 0: 1101 r->actions |= ACT_HOLD; 1102 break; 1103 case 1: 1104 r->actions |= ACT_RESUME; 1105 break; 1106 case 2: 1107 r->actions |= ACT_IMMEDIATE; 1108 break; 1109 } 1110 if (putrequest(file, r) < 0) { 1111 detailed_error(svc, 1112 gettext("failed to write job: %s: %s"), 1113 file, strerror(errno)); 1114 freerequest(r); 1115 return (PAPI_DEVICE_ERROR); 1116 } 1117 freerequest(r); 1118 } else { 1119 detailed_error(svc, gettext("failed to read job: %s: %s"), 1120 file, strerror(errno)); 1121 return (PAPI_DEVICE_ERROR); 1122 } 1123 1124 status = lpsched_end_change(svc, dest, job_id); 1125 1126 return (status); 1127 } 1128 1129 papi_status_t 1130 papiJobHold(papi_service_t handle, char *printer, int32_t job_id) 1131 { 1132 return (hold_release_job(handle, printer, job_id, 0)); 1133 } 1134 1135 papi_status_t 1136 papiJobRelease(papi_service_t handle, char *printer, int32_t job_id) 1137 { 1138 return (hold_release_job(handle, printer, job_id, 1)); 1139 } 1140 1141 papi_status_t 1142 papiJobPromote(papi_service_t handle, char *printer, int32_t job_id) 1143 { 1144 return (hold_release_job(handle, printer, job_id, 2)); 1145 } 1146 1147 papi_status_t 1148 papiJobModify(papi_service_t handle, char *printer, int32_t job_id, 1149 papi_attribute_t **attributes, papi_job_t *job) 1150 { 1151 papi_status_t status; 1152 job_t *j = NULL; 1153 service_t *svc = handle; 1154 char *file = NULL; 1155 char *dest; 1156 REQUEST *r = NULL; 1157 char lpfile[BUFSIZ]; 1158 int32_t job_id_actual; 1159 1160 if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 1161 (attributes == NULL)) 1162 return (PAPI_BAD_ARGUMENT); 1163 1164 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 1165 return (PAPI_TEMPORARY_ERROR); 1166 1167 dest = printer_name_from_uri_id(printer, job_id); 1168 1169 /* 1170 * job-id might be job-id-requested 1171 * If it is job-id-requested then we need to 1172 * look for corresponding job-id 1173 */ 1174 job_id_actual = check_job_id(svc, printer, job_id); 1175 1176 if (job_id_actual < 0) { 1177 status = PAPI_NOT_FOUND; 1178 detailed_error(svc, 1179 "failed to initiate change for job (%s-%d): %s", 1180 dest, job_id, "no such resource"); 1181 return (status); 1182 } 1183 1184 status = lpsched_start_change(svc, dest, job_id_actual, &file); 1185 if (status != PAPI_OK) 1186 return (status); 1187 1188 if ((r = getrequest(file)) != NULL) { 1189 job_attributes_to_lpsched_request(handle, r, 1190 (papi_attribute_t **)attributes); 1191 #ifdef LP_USE_PAPI_ATTR 1192 /* 1193 * store the job attributes in the PAPI job attribute file 1194 * that was created by the original job request. We need to 1195 * modify the attributes in the file as per the new attributes 1196 */ 1197 snprintf(lpfile, sizeof (lpfile), "%s%d-%s", 1198 "/var/spool/lp/temp/", job_id_actual, LP_PAPIATTRNAME); 1199 status = psm_modifyAttrsFile(attributes, lpfile); 1200 if (status != PAPI_OK) { 1201 detailed_error(svc, 1202 "unable to modify the attributes file: %s: %s", 1203 lpfile, strerror(errno)); 1204 return (PAPI_DEVICE_ERROR); 1205 } 1206 #endif 1207 1208 if (putrequest(file, r) < 0) { 1209 detailed_error(svc, 1210 gettext("failed to write job: %s: %s"), 1211 file, strerror(errno)); 1212 freerequest(r); 1213 return (PAPI_DEVICE_ERROR); 1214 } 1215 } else { 1216 detailed_error(svc, gettext("failed to read job: %s: %s"), 1217 file, strerror(errno)); 1218 return (PAPI_DEVICE_ERROR); 1219 } 1220 1221 status = lpsched_end_change(svc, dest, job_id_actual); 1222 lpsched_request_to_job_attributes(r, j); 1223 1224 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 1225 "job-id", job_id_actual); 1226 1227 freerequest(r); 1228 1229 return (status); 1230 } 1231 1232 /* 1233 * Extension to PAPI, a variation of this is slated for post-1.0 1234 */ 1235 #define DUMMY_FILE "/var/spool/lp/fifos/FIFO" 1236 1237 papi_status_t 1238 papiJobCreate(papi_service_t handle, char *printer, 1239 papi_attribute_t **job_attributes, 1240 papi_job_ticket_t *job_ticket, papi_job_t *job) 1241 { 1242 papi_status_t status; 1243 service_t *svc = handle; 1244 job_t *j = NULL; 1245 REQUEST *request; 1246 char *request_id = NULL; 1247 char *c; 1248 char *tmp = NULL; 1249 char metadata_file[MAXPATHLEN]; 1250 1251 if ((svc == NULL) || (printer == NULL) || (job == NULL)) 1252 return (PAPI_BAD_ARGUMENT); 1253 1254 if (job_ticket != NULL) 1255 return (PAPI_JOB_TICKET_NOT_SUPPORTED); 1256 1257 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 1258 return (PAPI_TEMPORARY_ERROR); 1259 1260 /* 1 for the control file (-0) */ 1261 status = lpsched_alloc_files(svc, 1, &request_id); 1262 if (status != PAPI_OK) 1263 return (status); 1264 1265 /* convert the attributes to an lpsched REQUEST structure */ 1266 request = create_request(svc, (char *)printer, 1267 (papi_attribute_t **)job_attributes); 1268 if (request == NULL) 1269 return (PAPI_TEMPORARY_ERROR); 1270 addlist(&request->file_list, DUMMY_FILE); /* add a dummy file */ 1271 request->actions |= ACT_HOLD; /* hold the job */ 1272 1273 #ifdef LP_USE_PAPI_ATTR 1274 /* 1275 * store the job attributes in the PAPI job attribute file that was 1276 * created by lpsched_alloc_files(), the attributes will then pass 1277 * through lpsched and be given to the slow-filters and the printer's 1278 * interface script to process them 1279 */ 1280 snprintf(metadata_file, sizeof (metadata_file), "%s%s-%s", 1281 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 1282 status = psm_copy_attrsToFile(job_attributes, metadata_file); 1283 if (status != PAPI_OK) { 1284 detailed_error(svc, "unable to copy attributes to file: %s: %s", 1285 metadata_file, strerror(errno)); 1286 free(request_id); 1287 return (PAPI_DEVICE_ERROR); 1288 } 1289 #endif 1290 1291 /* store the REQUEST on disk */ 1292 snprintf(metadata_file, sizeof (metadata_file), "%s-0", request_id); 1293 free(request_id); 1294 if (putrequest(metadata_file, request) < 0) { 1295 detailed_error(svc, gettext("unable to save request: %s: %s"), 1296 metadata_file, strerror(errno)); 1297 return (PAPI_DEVICE_ERROR); 1298 } 1299 1300 status = lpsched_commit_job(svc, metadata_file, &tmp); 1301 if (status != PAPI_OK) { 1302 unlink(metadata_file); 1303 return (status); 1304 } 1305 1306 lpsched_request_to_job_attributes(request, j); 1307 1308 if ((c = strrchr(tmp, '-')) != NULL) 1309 c++; 1310 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 1311 "job-id", atoi(c)); 1312 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 1313 "job-uri", tmp); 1314 1315 return (PAPI_OK); 1316 } 1317 1318 papi_status_t 1319 papiJobCommit(papi_service_t handle, char *printer, int32_t id) 1320 { 1321 papi_status_t status = PAPI_OK; 1322 service_t *svc = handle; 1323 REQUEST *r = NULL; 1324 char *metadata_file; 1325 char *dest; 1326 1327 if ((svc == NULL) || (printer == NULL)) 1328 return (PAPI_BAD_ARGUMENT); 1329 1330 dest = printer_name_from_uri_id(printer, id); 1331 /* tell the scheduler that we want to change the job */ 1332 status = lpsched_start_change(svc, dest, id, &metadata_file); 1333 if (status != PAPI_OK) 1334 return (status); 1335 1336 if ((r = getrequest(metadata_file)) != NULL) { 1337 r->actions &= ~ACT_RESUME; 1338 r->actions |= ACT_RESUME; 1339 dellist(&r->file_list, DUMMY_FILE); 1340 1341 if (putrequest(metadata_file, r) < 0) { 1342 detailed_error(svc, 1343 gettext("failed to write job: %s: %s"), 1344 metadata_file, strerror(errno)); 1345 freerequest(r); 1346 return (PAPI_DEVICE_ERROR); 1347 } 1348 } else { 1349 detailed_error(svc, gettext("failed to read job: %s: %s"), 1350 metadata_file, strerror(errno)); 1351 return (PAPI_DEVICE_ERROR); 1352 } 1353 1354 status = lpsched_end_change(svc, dest, id); 1355 freerequest(r); 1356 1357 return (status); 1358 } 1359 1360 papi_status_t 1361 papiJobStreamAdd(papi_service_t handle, char *printer, int32_t id, 1362 papi_stream_t *stream) 1363 { 1364 papi_status_t status; 1365 service_t *svc = handle; 1366 job_stream_t *s = NULL; 1367 char *metadata_file = NULL; 1368 char *dest; 1369 char path[MAXPATHLEN]; 1370 1371 /* allocate space for the stream */ 1372 if ((*stream = s = calloc(1, sizeof (*s))) == NULL) 1373 return (PAPI_TEMPORARY_ERROR); 1374 1375 dest = printer_name_from_uri_id(printer, id); 1376 /* create/open data file (only root or lp can really do this */ 1377 snprintf(path, sizeof (path), "/var/spool/lp/temp/%d-XXXXXX", id); 1378 if ((s->fd = mkstemp(path)) < 0) { 1379 detailed_error(svc, gettext("unable to create sink (%s): %s"), 1380 path, strerror(errno)); 1381 free(s); 1382 return (PAPI_NOT_AUTHORIZED); 1383 } 1384 1385 /* add data file to job */ 1386 status = lpsched_start_change(svc, dest, id, &metadata_file); 1387 if (status != PAPI_OK) { 1388 close(s->fd); 1389 free(s); 1390 unlink(path); 1391 return (status); 1392 } 1393 1394 if ((s->request = getrequest(metadata_file)) == NULL) { 1395 detailed_error(svc, gettext("unable to load request: %s: %s"), 1396 metadata_file, strerror(errno)); 1397 close(s->fd); 1398 free(s); 1399 unlink(path); 1400 return (PAPI_NOT_POSSIBLE); 1401 } 1402 1403 addlist(&(s->request->file_list), path); 1404 1405 if (putrequest(metadata_file, s->request) < 0) { 1406 detailed_error(svc, gettext("unable to save request: %s: %s"), 1407 metadata_file, strerror(errno)); 1408 close(s->fd); 1409 free(s); 1410 unlink(path); 1411 return (PAPI_NOT_POSSIBLE); 1412 } 1413 1414 status = lpsched_end_change(svc, dest, id); 1415 1416 if (status != PAPI_OK) 1417 return (status); 1418 1419 return (PAPI_OK); 1420 } 1421