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