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