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