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