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