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 stat(files[file_no], &statbuf); 460 if (statbuf.st_size == 0) { 461 detailed_error(svc, 462 gettext("Zero byte (empty) file: %s"), 463 files[file_no]); 464 return (PAPI_BAD_ARGUMENT); 465 } 466 } 467 468 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 469 return (PAPI_TEMPORARY_ERROR); 470 471 /* file_no + 1 for the control file (-0) */ 472 status = lpsched_alloc_files(svc, file_no + 1, &request_id); 473 if (status != PAPI_OK) 474 return (status); 475 476 request = create_request(svc, (char *)printer, 477 (papi_attribute_t **)job_attributes); 478 479 for (i = 0; files[i] != NULL; i++) { 480 papi_status_t status; 481 snprintf(lpfile, sizeof (lpfile), "%s%s-%d", 482 "/var/spool/lp/temp/", request_id, i+1); 483 status = copy_file(files[i], lpfile); 484 if (status != PAPI_OK) { 485 detailed_error(svc, 486 gettext("unable to copy: %s -> %s: %s"), 487 files[i], lpfile, strerror(errno)); 488 freerequest(request); 489 return (PAPI_DEVICE_ERROR); 490 } 491 addlist(&(request->file_list), lpfile); 492 } 493 494 #ifdef LP_USE_PAPI_ATTR 495 /* 496 * store the job attributes in the PAPI job attribute file that was 497 * created by lpsched_alloc_files(), the attributes will then pass 498 * through lpsched and be given to the slow-filters and the printer's 499 * interface script to process them 500 */ 501 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 502 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 503 status = psm_copy_attrsToFile(job_attributes, lpfile); 504 if (status != PAPI_OK) { 505 detailed_error(svc, "unable to copy attributes to file: %s: %s", 506 lpfile, strerror(errno)); 507 return (PAPI_DEVICE_ERROR); 508 } 509 #endif 510 511 /* store the meta-data file */ 512 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 513 if (putrequest(lpfile, request) < 0) { 514 detailed_error(svc, gettext("unable to save request: %s: %s"), 515 lpfile, strerror(errno)); 516 freerequest(request); 517 return (PAPI_DEVICE_ERROR); 518 } 519 520 status = lpsched_commit_job(svc, lpfile, &tmp); 521 if (status != PAPI_OK) { 522 unlink(lpfile); 523 freerequest(request); 524 return (status); 525 } 526 527 lpsched_request_to_job_attributes(request, j); 528 freerequest(request); 529 530 if ((c = strrchr(tmp, '-')) != NULL) 531 c++; 532 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 533 "job-id", atoi(c)); 534 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 535 "job-uri", tmp); 536 537 return (PAPI_OK); 538 } 539 540 papi_status_t 541 papiJobSubmitByReference(papi_service_t handle, char *printer, 542 papi_attribute_t **job_attributes, 543 papi_job_ticket_t *job_ticket, 544 char **files, papi_job_t *job) 545 { 546 service_t *svc = handle; 547 struct stat statbuf; 548 job_t *j; 549 int file_no; 550 short status; 551 char *request_id = NULL; 552 REQUEST *request; 553 char *c; 554 char *tmp = NULL; 555 char lpfile[BUFSIZ]; 556 char **file_list = NULL; 557 558 if ((svc == NULL) || (printer == NULL) || (files == NULL) || 559 (job == NULL)) 560 return (PAPI_BAD_ARGUMENT); 561 562 if (job_ticket != NULL) 563 return (PAPI_OPERATION_NOT_SUPPORTED); 564 565 if (files != NULL) 566 for (file_no = 0; files[file_no] != NULL; file_no++) { 567 if (access(files[file_no], R_OK) < 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 stat(files[file_no], &statbuf); 574 if (statbuf.st_size == 0) { 575 detailed_error(svc, 576 gettext("Zero byte (empty) file: %s"), 577 files[file_no]); 578 return (PAPI_BAD_ARGUMENT); 579 } 580 581 if (files[file_no][0] != '/') { 582 char path[MAXPATHLEN]; 583 584 if (getcwd(path, sizeof (path)) == NULL) { 585 detailed_error(svc, gettext( 586 "getcwd for file: %s: %s"), 587 files[file_no], 588 strerror(errno)); 589 return (PAPI_DOCUMENT_ACCESS_ERROR); 590 } 591 strlcat(path, "/", sizeof (path)); 592 if (strlcat(path, files[file_no], sizeof (path)) 593 >= sizeof (path)) { 594 detailed_error(svc, gettext( 595 "pathname too long: %s"), 596 files[file_no]); 597 return (PAPI_DOCUMENT_ACCESS_ERROR); 598 } 599 addlist(&file_list, path); 600 } else 601 addlist(&file_list, (char *)files[file_no]); 602 } 603 604 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 605 return (PAPI_TEMPORARY_ERROR); 606 607 /* 1 for the control file (-0) */ 608 status = lpsched_alloc_files(svc, 1, &request_id); 609 if (status != PAPI_OK) 610 return (status); 611 612 request = create_request(svc, (char *)printer, 613 (papi_attribute_t **)job_attributes); 614 request->file_list = file_list; 615 616 #ifdef LP_USE_PAPI_ATTR 617 /* 618 * store the job attributes in the PAPI job attribute file that was 619 * created by lpsched_alloc_files(), the attributes will then pass 620 * through lpsched and be given to the slow-filters and the printer's 621 * interface script to process them 622 */ 623 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 624 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 625 status = psm_copy_attrsToFile(job_attributes, lpfile); 626 if (status != PAPI_OK) { 627 detailed_error(svc, "unable to copy attributes to file: %s: %s", 628 lpfile, strerror(errno)); 629 return (PAPI_DEVICE_ERROR); 630 } 631 #endif 632 633 /* store the meta-data file */ 634 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 635 if (putrequest(lpfile, request) < 0) { 636 detailed_error(svc, gettext("unable to save request: %s: %s"), 637 lpfile, strerror(errno)); 638 freerequest(request); 639 return (PAPI_DEVICE_ERROR); 640 } 641 642 status = lpsched_commit_job(svc, lpfile, &tmp); 643 if (status != PAPI_OK) { 644 unlink(lpfile); 645 freerequest(request); 646 return (status); 647 } 648 649 lpsched_request_to_job_attributes(request, j); 650 651 freerequest(request); 652 653 if ((c = strrchr(tmp, '-')) != NULL) 654 c++; 655 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 656 "job-id", atoi(c)); 657 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 658 "job-uri", tmp); 659 660 return (PAPI_OK); 661 } 662 663 papi_status_t 664 papiJobValidate(papi_service_t handle, char *printer, 665 papi_attribute_t **job_attributes, 666 papi_job_ticket_t *job_ticket, 667 char **files, papi_job_t *job) 668 { 669 papi_status_t status; 670 papi_attribute_t **attributes = NULL; 671 int i; 672 673 papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE, 674 "job-hold-until", "indefinite"); 675 for (i = 0; job_attributes[i]; i++) 676 list_append(&attributes, job_attributes[i]); 677 678 status = papiJobSubmitByReference(handle, printer, 679 (papi_attribute_t **)attributes, 680 job_ticket, files, job); 681 if (status == PAPI_OK) { 682 int id = papiJobGetId(*job); 683 684 if (id != -1) 685 papiJobCancel(handle, printer, id); 686 } 687 688 attributes[1] = NULL; /* after attr[0], they are in another list */ 689 papiAttributeListFree(attributes); 690 691 return (status); 692 } 693 694 papi_status_t 695 papiJobStreamOpen(papi_service_t handle, char *printer, 696 papi_attribute_t **job_attributes, 697 papi_job_ticket_t *job_ticket, papi_stream_t *stream) 698 { 699 papi_status_t status; 700 service_t *svc = handle; 701 job_stream_t *s = NULL; 702 char *request_id = NULL; 703 char lpfile[BUFSIZ]; 704 705 if ((svc == NULL) || (printer == NULL) || (stream == NULL)) 706 return (PAPI_BAD_ARGUMENT); 707 708 if (job_ticket != NULL) 709 return (PAPI_OPERATION_NOT_SUPPORTED); 710 711 if ((*stream = s = calloc(1, sizeof (*s))) == NULL) 712 return (PAPI_TEMPORARY_ERROR); 713 714 /* 1 for data, 1 for the meta-data (-0) */ 715 status = lpsched_alloc_files(svc, 2, &request_id); 716 if (status != PAPI_OK) 717 return (status); 718 719 s->request = create_request(svc, (char *)printer, 720 (papi_attribute_t **)job_attributes); 721 snprintf(lpfile, sizeof (lpfile), "/var/spool/lp/temp/%s-1", 722 request_id); 723 s->fd = open(lpfile, O_WRONLY); 724 addlist(&(s->request->file_list), lpfile); 725 726 #ifdef LP_USE_PAPI_ATTR 727 /* 728 * store the job attributes in the PAPI job attribute file that was 729 * created by lpsched_alloc_files(), the attributes will then pass 730 * through lpsched and be given to the slow-filters and the printer's 731 * interface script to process them 732 */ 733 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 734 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 735 status = psm_copy_attrsToFile(job_attributes, lpfile); 736 if (status != PAPI_OK) { 737 detailed_error(svc, "unable to copy attributes to file: %s: %s", 738 lpfile, strerror(errno)); 739 close(s->fd); 740 free(s); 741 return (PAPI_DEVICE_ERROR); 742 } 743 #endif 744 745 /* store the meta-data file */ 746 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 747 s->meta_data_file = strdup(lpfile); 748 if (putrequest(lpfile, s->request) < 0) { 749 detailed_error(svc, gettext("unable to save request: %s: %s"), 750 lpfile, strerror(errno)); 751 s->request = NULL; 752 return (PAPI_DEVICE_ERROR); 753 } 754 755 return (PAPI_OK); 756 } 757 758 papi_status_t 759 papiJobStreamWrite(papi_service_t handle, 760 papi_stream_t stream, void *buffer, size_t buflen) 761 { 762 service_t *svc = handle; 763 job_stream_t *s = stream; 764 765 if ((svc == NULL) || (stream == NULL) || (buffer == NULL)) 766 return (PAPI_BAD_ARGUMENT); 767 768 if (write(s->fd, buffer, buflen) != buflen) 769 return (PAPI_DEVICE_ERROR); 770 771 return (PAPI_OK); 772 } 773 papi_status_t 774 papiJobStreamClose(papi_service_t handle, 775 papi_stream_t stream, papi_job_t *job) 776 { 777 papi_status_t status = PAPI_OK; 778 service_t *svc = handle; 779 job_stream_t *s = stream; 780 job_t *j = NULL; 781 char *tmp = NULL, *c; 782 783 if ((svc == NULL) || (stream == NULL) || (job == NULL)) 784 return (PAPI_BAD_ARGUMENT); 785 786 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 787 return (PAPI_TEMPORARY_ERROR); 788 789 close(s->fd); 790 791 lpsched_request_to_job_attributes(s->request, j); 792 793 if (s->meta_data_file != NULL) { 794 status = lpsched_commit_job(svc, s->meta_data_file, &tmp); 795 if (status != PAPI_OK) { 796 unlink(s->meta_data_file); 797 return (status); 798 } 799 if ((c = strrchr(tmp, '-')) != NULL) 800 c++; 801 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 802 "job-id", atoi(c)); 803 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 804 "job-uri", tmp); 805 free(s->meta_data_file); 806 } 807 freerequest(s->request); 808 free(s); 809 810 return (PAPI_OK); 811 } 812 813 papi_status_t 814 papiJobQuery(papi_service_t handle, char *printer, int32_t job_id, 815 char **requested_attrs, 816 papi_job_t *job) 817 { 818 service_t *svc = handle; 819 job_t *j; 820 char *dest; 821 char req_id[32]; 822 short rc; 823 char *form = NULL, 824 *request_id = NULL, 825 *charset = NULL, 826 *user = NULL, 827 *slabel = NULL, 828 *file = NULL; 829 time_t date = 0; 830 size_t size = 0; 831 short rank = 0, 832 state = 0; 833 834 if ((handle == NULL) || (printer == NULL) || (job_id < 0)) 835 return (PAPI_BAD_ARGUMENT); 836 837 dest = printer_name_from_uri_id(printer, job_id); 838 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); 839 free(dest); 840 841 rc = snd_msg(svc, S_INQUIRE_REQUEST_RANK, 0, "", "", req_id, "", ""); 842 if (rc < 0) 843 return (PAPI_SERVICE_UNAVAILABLE); 844 845 if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &request_id, 846 &user, &slabel, &size, &date, &state, &dest, &form, 847 &charset, &rank, &file) < 0) { 848 detailed_error(svc, 849 gettext("failed to read response from scheduler")); 850 return (PAPI_DEVICE_ERROR); 851 } 852 853 if ((request_id == NULL) || (request_id[0] == NULL)) 854 return (PAPI_NOT_FOUND); 855 856 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 857 return (PAPI_TEMPORARY_ERROR); 858 859 job_status_to_attributes(j, request_id, user, slabel, size, date, state, 860 dest, form, charset, rank, file); 861 862 snprintf(req_id, sizeof (req_id), "%d-0", job_id); 863 lpsched_read_job_configuration(svc, j, req_id); 864 865 return (PAPI_OK); 866 } 867 868 papi_status_t 869 papiJobMove(papi_service_t handle, char *printer, int32_t job_id, 870 char *destination) 871 { 872 papi_status_t result = PAPI_OK; 873 long bits; 874 service_t *svc = handle; 875 char req_id[64]; 876 char *queue; 877 char *user = NULL; 878 879 if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 880 (destination == NULL)) 881 return (PAPI_BAD_ARGUMENT); 882 883 queue = printer_name_from_uri_id(printer, job_id); 884 snprintf(req_id, sizeof (req_id), "%s-%d", queue, job_id); 885 free(queue); 886 887 if (papiAttributeListGetString(svc->attributes, NULL, "user-name", 888 &user) == PAPI_OK) { 889 REQUEST *r = getrequest(req_id); 890 891 if ((r != NULL) && (r->user != NULL) && 892 (strcmp(r->user, user) != 0)) 893 result = PAPI_NOT_AUTHORIZED; 894 freerequest(r); 895 } 896 897 if (result == PAPI_OK) { 898 short status = MOK; 899 char *dest = printer_name_from_uri_id(destination, -1); 900 901 if ((snd_msg(svc, S_MOVE_REQUEST, req_id, dest) < 0) || 902 (rcv_msg(svc, R_MOVE_REQUEST, &status, &bits) < 0)) 903 status = MTRANSMITERR; 904 905 free(dest); 906 907 result = lpsched_status_to_papi_status(status); 908 } 909 910 return (result); 911 } 912 913 papi_status_t 914 papiJobCancel(papi_service_t handle, char *printer, int32_t job_id) 915 { 916 papi_status_t result = PAPI_OK; 917 service_t *svc = handle; 918 char req_id[64]; 919 char *dest; 920 char *user = NULL; 921 922 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 923 return (PAPI_BAD_ARGUMENT); 924 925 dest = printer_name_from_uri_id(printer, job_id); 926 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); 927 free(dest); 928 929 if (papiAttributeListGetString(svc->attributes, NULL, "user-name", 930 &user) == PAPI_OK) { 931 REQUEST *r = getrequest(req_id); 932 933 if ((result = authorized(handle, job_id)) != PAPI_OK) 934 result = PAPI_NOT_AUTHORIZED; 935 936 if ((r != NULL) && (r->user != NULL) && 937 (strcmp(r->user, user) != 0)) 938 result = PAPI_NOT_AUTHORIZED; 939 freerequest(r); 940 } 941 942 if (result == PAPI_OK) { 943 short status = MOK; 944 945 if ((snd_msg(svc, S_CANCEL_REQUEST, req_id) < 0) || 946 (rcv_msg(svc, R_CANCEL_REQUEST, &status) < 0)) 947 status = MTRANSMITERR; 948 949 result = lpsched_status_to_papi_status(status); 950 } 951 952 return (result); 953 } 954 955 papi_status_t 956 hold_release_job(papi_service_t handle, char *printer, 957 int32_t job_id, int flag) 958 { 959 papi_status_t status; 960 service_t *svc = handle; 961 REQUEST *r = NULL; 962 char *file; 963 char *dest; 964 965 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 966 return (PAPI_BAD_ARGUMENT); 967 968 if ((status = authorized(svc, job_id)) != PAPI_OK) 969 return (status); 970 971 dest = printer_name_from_uri_id(printer, job_id); 972 status = lpsched_start_change(svc, dest, job_id, &file); 973 if (status != PAPI_OK) 974 return (status); 975 976 if ((r = getrequest(file)) != NULL) { 977 r->actions &= ~ACT_RESUME; 978 switch (flag) { 979 case 0: 980 r->actions |= ACT_HOLD; 981 break; 982 case 1: 983 r->actions |= ACT_RESUME; 984 break; 985 case 2: 986 r->actions |= ACT_IMMEDIATE; 987 break; 988 } 989 if (putrequest(file, r) < 0) { 990 detailed_error(svc, 991 gettext("failed to write job: %s: %s"), 992 file, strerror(errno)); 993 freerequest(r); 994 return (PAPI_DEVICE_ERROR); 995 } 996 freerequest(r); 997 } else { 998 detailed_error(svc, gettext("failed to read job: %s: %s"), 999 file, strerror(errno)); 1000 return (PAPI_DEVICE_ERROR); 1001 } 1002 1003 status = lpsched_end_change(svc, dest, job_id); 1004 1005 return (status); 1006 } 1007 1008 papi_status_t 1009 papiJobHold(papi_service_t handle, char *printer, int32_t job_id) 1010 { 1011 return (hold_release_job(handle, printer, job_id, 0)); 1012 } 1013 1014 papi_status_t 1015 papiJobRelease(papi_service_t handle, char *printer, int32_t job_id) 1016 { 1017 return (hold_release_job(handle, printer, job_id, 1)); 1018 } 1019 1020 papi_status_t 1021 papiJobPromote(papi_service_t handle, char *printer, int32_t job_id) 1022 { 1023 return (hold_release_job(handle, printer, job_id, 2)); 1024 } 1025 1026 papi_status_t 1027 papiJobModify(papi_service_t handle, char *printer, int32_t job_id, 1028 papi_attribute_t **attributes, papi_job_t *job) 1029 { 1030 papi_status_t status; 1031 job_t *j = NULL; 1032 service_t *svc = handle; 1033 char *file = NULL; 1034 char *dest; 1035 REQUEST *r = NULL; 1036 char lpfile[BUFSIZ]; 1037 1038 if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 1039 (attributes == NULL)) 1040 return (PAPI_BAD_ARGUMENT); 1041 1042 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 1043 return (PAPI_TEMPORARY_ERROR); 1044 1045 dest = printer_name_from_uri_id(printer, job_id); 1046 status = lpsched_start_change(svc, dest, job_id, &file); 1047 if (status != PAPI_OK) 1048 return (status); 1049 1050 if ((r = getrequest(file)) != NULL) { 1051 job_attributes_to_lpsched_request(handle, r, 1052 (papi_attribute_t **)attributes); 1053 #ifdef LP_USE_PAPI_ATTR 1054 /* 1055 * store the job attributes in the PAPI job attribute file 1056 * that was created by the origonal job request. We need to 1057 * modify the attributes in the file as per the new attributes 1058 */ 1059 snprintf(lpfile, sizeof (lpfile), "%s%d-%s", 1060 "/var/spool/lp/temp/", job_id, LP_PAPIATTRNAME); 1061 status = psm_modifyAttrsFile(attributes, lpfile); 1062 if (status != PAPI_OK) { 1063 detailed_error(svc, 1064 "unable to modify the attributes file: %s: %s", 1065 lpfile, strerror(errno)); 1066 return (PAPI_DEVICE_ERROR); 1067 } 1068 #endif 1069 1070 if (putrequest(file, r) < 0) { 1071 detailed_error(svc, 1072 gettext("failed to write job: %s: %s"), 1073 file, strerror(errno)); 1074 freerequest(r); 1075 return (PAPI_DEVICE_ERROR); 1076 } 1077 } else { 1078 detailed_error(svc, gettext("failed to read job: %s: %s"), 1079 file, strerror(errno)); 1080 return (PAPI_DEVICE_ERROR); 1081 } 1082 1083 status = lpsched_end_change(svc, dest, job_id); 1084 lpsched_request_to_job_attributes(r, j); 1085 1086 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 1087 "job-id", job_id); 1088 1089 freerequest(r); 1090 1091 return (status); 1092 } 1093 1094 /* 1095 * Extension to PAPI, a variation of this is slated for post-1.0 1096 */ 1097 #define DUMMY_FILE "/var/spool/lp/fifos/FIFO" 1098 1099 papi_status_t 1100 papiJobCreate(papi_service_t handle, char *printer, 1101 papi_attribute_t **job_attributes, 1102 papi_job_ticket_t *job_ticket, papi_job_t *job) 1103 { 1104 papi_status_t status; 1105 service_t *svc = handle; 1106 job_t *j = NULL; 1107 REQUEST *request; 1108 char *request_id = NULL; 1109 char *c; 1110 char *tmp = NULL; 1111 char metadata_file[MAXPATHLEN]; 1112 1113 if ((svc == NULL) || (printer == NULL) || (job == NULL)) 1114 return (PAPI_BAD_ARGUMENT); 1115 1116 if (job_ticket != NULL) 1117 return (PAPI_JOB_TICKET_NOT_SUPPORTED); 1118 1119 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 1120 return (PAPI_TEMPORARY_ERROR); 1121 1122 /* 1 for the control file (-0) */ 1123 status = lpsched_alloc_files(svc, 1, &request_id); 1124 if (status != PAPI_OK) 1125 return (status); 1126 1127 /* convert the attributes to an lpsched REQUEST structure */ 1128 request = create_request(svc, (char *)printer, 1129 (papi_attribute_t **)job_attributes); 1130 if (request == NULL) 1131 return (PAPI_TEMPORARY_ERROR); 1132 addlist(&request->file_list, DUMMY_FILE); /* add a dummy file */ 1133 request->actions |= ACT_HOLD; /* hold the job */ 1134 1135 #ifdef LP_USE_PAPI_ATTR 1136 /* 1137 * store the job attributes in the PAPI job attribute file that was 1138 * created by lpsched_alloc_files(), the attributes will then pass 1139 * through lpsched and be given to the slow-filters and the printer's 1140 * interface script to process them 1141 */ 1142 snprintf(metadata_file, sizeof (metadata_file), "%s%s-%s", 1143 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 1144 status = psm_copy_attrsToFile(job_attributes, metadata_file); 1145 if (status != PAPI_OK) { 1146 detailed_error(svc, "unable to copy attributes to file: %s: %s", 1147 metadata_file, strerror(errno)); 1148 free(request_id); 1149 return (PAPI_DEVICE_ERROR); 1150 } 1151 #endif 1152 1153 /* store the REQUEST on disk */ 1154 snprintf(metadata_file, sizeof (metadata_file), "%s-0", request_id); 1155 free(request_id); 1156 if (putrequest(metadata_file, request) < 0) { 1157 detailed_error(svc, gettext("unable to save request: %s: %s"), 1158 metadata_file, strerror(errno)); 1159 return (PAPI_DEVICE_ERROR); 1160 } 1161 1162 status = lpsched_commit_job(svc, metadata_file, &tmp); 1163 if (status != PAPI_OK) { 1164 unlink(metadata_file); 1165 return (status); 1166 } 1167 1168 lpsched_request_to_job_attributes(request, j); 1169 1170 if ((c = strrchr(tmp, '-')) != NULL) 1171 c++; 1172 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 1173 "job-id", atoi(c)); 1174 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 1175 "job-uri", tmp); 1176 1177 return (PAPI_OK); 1178 } 1179 1180 papi_status_t 1181 papiJobCommit(papi_service_t handle, char *printer, int32_t id) 1182 { 1183 papi_status_t status = PAPI_OK; 1184 service_t *svc = handle; 1185 REQUEST *r = NULL; 1186 char *metadata_file; 1187 char *dest; 1188 1189 if ((svc == NULL) || (printer == NULL)) 1190 return (PAPI_BAD_ARGUMENT); 1191 1192 dest = printer_name_from_uri_id(printer, id); 1193 /* tell the scheduler that we want to change the job */ 1194 status = lpsched_start_change(svc, dest, id, &metadata_file); 1195 if (status != PAPI_OK) 1196 return (status); 1197 1198 if ((r = getrequest(metadata_file)) != NULL) { 1199 r->actions &= ~ACT_RESUME; 1200 r->actions |= ACT_RESUME; 1201 dellist(&r->file_list, DUMMY_FILE); 1202 1203 if (putrequest(metadata_file, r) < 0) { 1204 detailed_error(svc, 1205 gettext("failed to write job: %s: %s"), 1206 metadata_file, strerror(errno)); 1207 freerequest(r); 1208 return (PAPI_DEVICE_ERROR); 1209 } 1210 } else { 1211 detailed_error(svc, gettext("failed to read job: %s: %s"), 1212 metadata_file, strerror(errno)); 1213 return (PAPI_DEVICE_ERROR); 1214 } 1215 1216 status = lpsched_end_change(svc, dest, id); 1217 freerequest(r); 1218 1219 return (status); 1220 } 1221 1222 papi_status_t 1223 papiJobStreamAdd(papi_service_t handle, char *printer, int32_t id, 1224 papi_stream_t *stream) 1225 { 1226 papi_status_t status; 1227 service_t *svc = handle; 1228 job_stream_t *s = NULL; 1229 char *metadata_file = NULL; 1230 char *dest; 1231 char path[MAXPATHLEN]; 1232 1233 /* allocate space for the stream */ 1234 if ((*stream = s = calloc(1, sizeof (*s))) == NULL) 1235 return (PAPI_TEMPORARY_ERROR); 1236 1237 dest = printer_name_from_uri_id(printer, id); 1238 /* create/open data file (only root or lp can really do this */ 1239 snprintf(path, sizeof (path), "/var/spool/lp/temp/%d-XXXXXX", id); 1240 if ((s->fd = mkstemp(path)) < 0) { 1241 detailed_error(svc, gettext("unable to create sink (%s): %s"), 1242 path, strerror(errno)); 1243 free(s); 1244 return (PAPI_NOT_AUTHORIZED); 1245 } 1246 1247 /* add data file to job */ 1248 status = lpsched_start_change(svc, dest, id, &metadata_file); 1249 if (status != PAPI_OK) { 1250 close(s->fd); 1251 free(s); 1252 unlink(path); 1253 return (status); 1254 } 1255 1256 if ((s->request = getrequest(metadata_file)) == NULL) { 1257 detailed_error(svc, gettext("unable to load request: %s: %s"), 1258 metadata_file, strerror(errno)); 1259 close(s->fd); 1260 free(s); 1261 unlink(path); 1262 return (PAPI_NOT_POSSIBLE); 1263 } 1264 1265 addlist(&(s->request->file_list), path); 1266 1267 if (putrequest(metadata_file, s->request) < 0) { 1268 detailed_error(svc, gettext("unable to save request: %s: %s"), 1269 metadata_file, strerror(errno)); 1270 close(s->fd); 1271 free(s); 1272 unlink(path); 1273 return (PAPI_NOT_POSSIBLE); 1274 } 1275 1276 status = lpsched_end_change(svc, dest, id); 1277 1278 if (status != PAPI_OK) 1279 return (status); 1280 1281 return (PAPI_OK); 1282 } 1283