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 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /*LINTLIBRARY*/ 29 30 #include <stdlib.h> 31 #include <string.h> 32 #include <unistd.h> 33 #include <libintl.h> 34 #include <pwd.h> 35 #include <sys/stat.h> 36 #include <papi_impl.h> 37 38 39 /* 40 * for an older application that may have been linked with a pre-v1.0 41 * PAPI implementation. 42 */ 43 papi_status_t 44 papiAttributeListAdd(papi_attribute_t ***attrs, int flags, char *name, 45 papi_attribute_value_type_t type, papi_attribute_value_t *value) 46 { 47 return (papiAttributeListAddValue(attrs, flags, name, type, value)); 48 } 49 50 #ifdef LP_USE_PAPI_ATTR 51 static papi_status_t psm_modifyAttrsFile(papi_attribute_t **attrs, char *file); 52 static papi_status_t psm_modifyAttrsList(char *file, papi_attribute_t **attrs, 53 papi_attribute_t ***newAttrs); 54 #endif 55 56 57 void 58 papiJobFree(papi_job_t job) 59 { 60 job_t *tmp = (job_t *)job; 61 62 if (tmp != NULL) { 63 papiAttributeListFree(tmp->attributes); 64 free(tmp); 65 } 66 } 67 68 void 69 papiJobListFree(papi_job_t *jobs) 70 { 71 if (jobs != NULL) { 72 int i; 73 74 for (i = 0; jobs[i] != NULL; i++) { 75 papiJobFree(jobs[i]); 76 } 77 free(jobs); 78 } 79 } 80 81 papi_attribute_t ** 82 papiJobGetAttributeList(papi_job_t job) 83 { 84 job_t *tmp = (job_t *)job; 85 86 if (tmp != NULL) 87 return (tmp->attributes); 88 89 return (NULL); 90 } 91 92 char * 93 papiJobGetPrinterName(papi_job_t job) 94 { 95 job_t *tmp = (job_t *)job; 96 char *result = NULL; 97 98 if (tmp != NULL) 99 papiAttributeListGetString(tmp->attributes, NULL, 100 "printer-name", &result); 101 102 return (result); 103 } 104 105 int32_t 106 papiJobGetId(papi_job_t job) 107 { 108 job_t *tmp = (job_t *)job; 109 int result = -1; 110 111 if (tmp != NULL) 112 papiAttributeListGetInteger(tmp->attributes, NULL, "job-id", 113 &result); 114 115 return (result); 116 } 117 118 static REQUEST * 119 create_request(papi_service_t svc, char *printer, papi_attribute_t **attributes) 120 { 121 REQUEST *r; 122 123 if ((r = calloc(1, sizeof (*r))) != NULL) { 124 r->priority = -1; 125 r->destination = printer_name_from_uri_id(printer, -1); 126 job_attributes_to_lpsched_request(svc, r, attributes); 127 } 128 129 return (r); 130 } 131 132 static papi_status_t 133 authorized(service_t *svc, int32_t id) 134 { 135 papi_status_t result = PAPI_NOT_AUTHORIZED; /* assume the worst */ 136 char file[32]; 137 REQUEST *r; 138 139 snprintf(file, sizeof (file), "%d-0", id); 140 if ((r = getrequest(file)) != NULL) { 141 uid_t uid = getuid(); 142 struct passwd *pw = NULL; 143 char *user = "intruder"; /* assume an intruder */ 144 145 if ((pw = getpwuid(uid)) != NULL) 146 user = pw->pw_name; /* use the process owner */ 147 148 if ((uid == 0) || (uid == 71)) { /* root/lp can forge this */ 149 papi_status_t s; 150 s = papiAttributeListGetString(svc->attributes, NULL, 151 "user-name", &user); 152 if (s != PAPI_OK) /* true root/lp are almighty */ 153 result = PAPI_OK; 154 } 155 156 if ((result != PAPI_OK) && (strcmp(user, r->user) == 0)) 157 result = PAPI_OK; 158 159 freerequest(r); 160 } else 161 result = PAPI_NOT_FOUND; 162 163 return (result); 164 } 165 166 static papi_status_t 167 copy_file(char *from, char *to) 168 { 169 int ifd, ofd; 170 char buf[BUFSIZ]; 171 int rc; 172 173 if ((ifd = open(from, O_RDONLY)) < 0) 174 return (PAPI_DOCUMENT_ACCESS_ERROR); 175 176 if ((ofd = open(to, O_WRONLY)) < 0) { 177 close(ifd); 178 return (PAPI_NOT_POSSIBLE); 179 } 180 181 while ((rc = read(ifd, buf, sizeof (buf))) > 0) 182 write(ofd, buf, rc); 183 184 close(ifd); 185 close(ofd); 186 187 return (PAPI_OK); 188 } 189 190 191 #ifdef LP_USE_PAPI_ATTR 192 /* 193 * ***************************************************************************** 194 * 195 * Description: Create a file containing all the attributes in the attribute 196 * list passed to this function. 197 * This file is then passed through lpsched and given to either 198 * a slow-filter or to the printer's interface script to process 199 * the attributes. 200 * 201 * Parameters: attrs - list of attributes and their values 202 * file - file pathname to create and put the attributes into. 203 * 204 * ***************************************************************************** 205 */ 206 207 static papi_status_t 208 psm_copy_attrsToFile(papi_attribute_t **attrs, char *file) 209 210 { 211 papi_status_t result = PAPI_OK; 212 213 if ((attrs != NULL) && (*attrs != NULL)) { 214 FILE *out = NULL; 215 216 if ((out = fopen(file, "w")) != NULL) { 217 papiAttributeListPrint(out, attrs, ""); 218 fclose(out); 219 } else { 220 result = PAPI_NOT_POSSIBLE; 221 } 222 } 223 224 return (result); 225 } /* psm_copy_attrsToFile */ 226 227 228 /* 229 * ***************************************************************************** 230 * 231 * Description: Modify the given attribute 'file' with the attributes from the 232 * 'attrs' list. Attributes already in the file will be replaced 233 * with the new value. New attributes will be added into the file. 234 * 235 * Parameters: attrs - list of attributes and their values 236 * file - file pathname to create and put the attributes into. 237 * 238 * ***************************************************************************** 239 */ 240 241 static papi_status_t 242 psm_modifyAttrsFile(papi_attribute_t **attrs, char *file) 243 244 { 245 papi_status_t result = PAPI_OK; 246 papi_attribute_t **newAttrs = NULL; 247 struct stat tmpBuf; 248 FILE *fd = NULL; 249 250 if ((attrs != NULL) && (*attrs != NULL) && (file != NULL)) { 251 252 /* 253 * check file exist before try to modify it, if it doesn't 254 * exist assume there is an error 255 */ 256 if (stat(file, &tmpBuf) == 0) { 257 /* 258 * if file is currently empty just write the given 259 * attributes to the file otherwise exact the attributes 260 * from the file and modify them accordingly before 261 * writing them back to the file 262 */ 263 if (tmpBuf.st_size == 0) { 264 newAttrs = (papi_attribute_t **)attrs; 265 266 fd = fopen(file, "w"); 267 if (fd != NULL) { 268 papiAttributeListPrint(fd, 269 newAttrs, ""); 270 fclose(fd); 271 } else { 272 result = PAPI_NOT_POSSIBLE; 273 } 274 } else { 275 result = 276 psm_modifyAttrsList(file, attrs, &newAttrs); 277 278 fd = fopen(file, "w"); 279 if (fd != NULL) { 280 papiAttributeListPrint(fd, 281 newAttrs, ""); 282 fclose(fd); 283 } else { 284 result = PAPI_NOT_POSSIBLE; 285 } 286 287 papiAttributeListFree(newAttrs); 288 } 289 } else { 290 result = PAPI_NOT_POSSIBLE; 291 } 292 } 293 294 return (result); 295 } /* psm_modifyAttrsFile */ 296 297 298 /* 299 * ***************************************************************************** 300 * 301 * Description: Extracts the attributes in the given attribute 'file' and 302 * creates a new list 'newAttrs' containing the modified list of 303 * attributes. 304 * 305 * Parameters: file - pathname of file containing attributes to be modified 306 * attrs - list of attributes and their values to modify 307 * newAttrs - returns the modified list of attributes 308 * 309 * ***************************************************************************** 310 */ 311 312 static papi_status_t 313 psm_modifyAttrsList(char *file, papi_attribute_t **attrs, 314 papi_attribute_t ***newAttrs) 315 316 { 317 papi_status_t result = PAPI_OK; 318 papi_attribute_t *nextAttr = NULL; 319 papi_attribute_value_t **values = NULL; 320 void *iter = NULL; 321 FILE *fd = NULL; 322 register int fD = 0; 323 char aBuff[200]; 324 char *a = NULL; 325 char *p = NULL; 326 int count = 0; 327 int n = 0; 328 329 fd = fopen(file, "r"); 330 if (fd != NULL) { 331 fD = fileno(fd); 332 a = &aBuff[0]; 333 p = &aBuff[0]; 334 count = read(fD, &aBuff[0], sizeof (aBuff) - 1); 335 while ((result == PAPI_OK) && (count > 0)) { 336 aBuff[count+n] = '\0'; 337 if (count == sizeof (aBuff) - n - 1) { 338 p = strrchr(aBuff, '\n'); 339 if (p != NULL) { 340 /* terminate at last complete line */ 341 *p = '\0'; 342 } 343 } 344 result = papiAttributeListFromString( 345 newAttrs, PAPI_ATTR_EXCL, aBuff); 346 347 if (result == PAPI_OK) { 348 /* 349 * handle any part lines and then read the next 350 * buffer from the file 351 */ 352 n = 0; 353 if (p != a) { 354 p++; /* skip NL */ 355 n = sizeof (aBuff) - 1 - (p - a); 356 strncpy(aBuff, p, n); 357 } 358 count = read(fD, &aBuff[n], 359 sizeof (aBuff) - n - 1); 360 p = &aBuff[0]; 361 } 362 } 363 fclose(fd); 364 } 365 366 /* now modify the attribute list with the new attributes in 'attrs' */ 367 368 nextAttr = papiAttributeListGetNext((papi_attribute_t **)attrs, &iter); 369 while ((result == PAPI_OK) && (nextAttr != NULL)) { 370 values = nextAttr->values; 371 372 if ((values != NULL) && (*values != NULL)) { 373 result = papiAttributeListAddValue(newAttrs, 374 PAPI_ATTR_REPLACE, 375 nextAttr->name, 376 nextAttr->type, *values); 377 values++; 378 } 379 380 while ((result == PAPI_OK) && 381 (values != NULL) && (*values != NULL)) { 382 result = papiAttributeListAddValue(newAttrs, 383 PAPI_ATTR_APPEND, 384 nextAttr->name, 385 nextAttr->type, *values); 386 values++; 387 } 388 nextAttr = 389 papiAttributeListGetNext((papi_attribute_t **)attrs, &iter); 390 } 391 392 return (result); 393 } /* papi_modifyAttrsList() */ 394 #endif 395 396 397 papi_status_t 398 papiJobSubmit(papi_service_t handle, char *printer, 399 papi_attribute_t **job_attributes, 400 papi_job_ticket_t *job_ticket, 401 char **files, papi_job_t *job) 402 { 403 papi_status_t status; 404 service_t *svc = handle; 405 job_t *j; 406 int file_no; 407 char *request_id = NULL; 408 REQUEST *request; 409 int i; 410 char *c; 411 char *tmp = NULL; 412 char lpfile[BUFSIZ]; 413 414 if ((svc == NULL) || (printer == NULL) || (files == NULL) || 415 (job == NULL)) 416 return (PAPI_BAD_ARGUMENT); 417 418 if (job_ticket != NULL) 419 return (PAPI_OPERATION_NOT_SUPPORTED); 420 421 if (files != NULL) 422 for (file_no = 0; files[file_no] != NULL; file_no++) 423 if (access(files[file_no], R_OK) < 0) { 424 detailed_error(svc, 425 gettext("Cannot access file: %s: %s"), 426 files[file_no], strerror(errno)); 427 return (PAPI_BAD_ARGUMENT); 428 } 429 430 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 431 return (PAPI_TEMPORARY_ERROR); 432 433 /* file_no + 1 for the control file (-0) */ 434 status = lpsched_alloc_files(svc, file_no + 1, &request_id); 435 if (status != PAPI_OK) 436 return (status); 437 438 request = create_request(svc, (char *)printer, 439 (papi_attribute_t **)job_attributes); 440 441 for (i = 0; files[i] != NULL; i++) { 442 papi_status_t status; 443 snprintf(lpfile, sizeof (lpfile), "%s%s-%d", 444 "/var/spool/lp/temp/", request_id, i+1); 445 status = copy_file(files[i], lpfile); 446 if (status != PAPI_OK) { 447 detailed_error(svc, 448 gettext("unable to copy: %s -> %s: %s"), 449 files[i], lpfile, strerror(errno)); 450 freerequest(request); 451 return (PAPI_DEVICE_ERROR); 452 } 453 addlist(&(request->file_list), lpfile); 454 } 455 456 #ifdef LP_USE_PAPI_ATTR 457 /* 458 * store the job attributes in the PAPI job attribute file that was 459 * created by lpsched_alloc_files(), the attributes will then pass 460 * through lpsched and be given to the slow-filters and the printer's 461 * interface script to process them 462 */ 463 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 464 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 465 status = psm_copy_attrsToFile(job_attributes, lpfile); 466 if (status != PAPI_OK) { 467 detailed_error(svc, "unable to copy attributes to file: %s: %s", 468 lpfile, strerror(errno)); 469 return (PAPI_DEVICE_ERROR); 470 } 471 #endif 472 473 /* store the meta-data file */ 474 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 475 if (putrequest(lpfile, request) < 0) { 476 detailed_error(svc, gettext("unable to save request: %s: %s"), 477 lpfile, strerror(errno)); 478 freerequest(request); 479 return (PAPI_DEVICE_ERROR); 480 } 481 482 status = lpsched_commit_job(svc, lpfile, &tmp); 483 if (status != PAPI_OK) { 484 unlink(lpfile); 485 freerequest(request); 486 return (status); 487 } 488 489 lpsched_request_to_job_attributes(request, j); 490 freerequest(request); 491 492 if ((c = strrchr(tmp, '-')) != NULL) 493 c++; 494 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 495 "job-id", atoi(c)); 496 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 497 "job-uri", tmp); 498 499 return (PAPI_OK); 500 } 501 502 papi_status_t 503 papiJobSubmitByReference(papi_service_t handle, char *printer, 504 papi_attribute_t **job_attributes, 505 papi_job_ticket_t *job_ticket, 506 char **files, papi_job_t *job) 507 { 508 service_t *svc = handle; 509 job_t *j; 510 int file_no; 511 short status; 512 char *request_id = NULL; 513 REQUEST *request; 514 char *c; 515 char *tmp = NULL; 516 char lpfile[BUFSIZ]; 517 char **file_list = NULL; 518 519 if ((svc == NULL) || (printer == NULL) || (files == NULL) || 520 (job == NULL)) 521 return (PAPI_BAD_ARGUMENT); 522 523 if (job_ticket != NULL) 524 return (PAPI_OPERATION_NOT_SUPPORTED); 525 526 if (files != NULL) 527 for (file_no = 0; files[file_no] != NULL; file_no++) { 528 if (access(files[file_no], R_OK) < 0) { 529 detailed_error(svc, 530 gettext("Cannot access file: %s: %s"), 531 files[file_no], strerror(errno)); 532 return (PAPI_DOCUMENT_ACCESS_ERROR); 533 } 534 if (files[file_no][0] != '/') { 535 char path[MAXPATHLEN]; 536 537 if (getcwd(path, sizeof (path)) == NULL) { 538 detailed_error(svc, gettext( 539 "getcwd for file: %s: %s"), 540 files[file_no], 541 strerror(errno)); 542 return (PAPI_DOCUMENT_ACCESS_ERROR); 543 } 544 strlcat(path, "/", sizeof (path)); 545 if (strlcat(path, files[file_no], sizeof (path)) 546 >= sizeof (path)) { 547 detailed_error(svc, gettext( 548 "pathname too long: %s"), 549 files[file_no]); 550 return (PAPI_DOCUMENT_ACCESS_ERROR); 551 } 552 addlist(&file_list, path); 553 } else 554 addlist(&file_list, (char *)files[file_no]); 555 } 556 557 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 558 return (PAPI_TEMPORARY_ERROR); 559 560 /* 1 for the control file (-0) */ 561 status = lpsched_alloc_files(svc, 1, &request_id); 562 if (status != PAPI_OK) 563 return (status); 564 565 request = create_request(svc, (char *)printer, 566 (papi_attribute_t **)job_attributes); 567 request->file_list = file_list; 568 569 #ifdef LP_USE_PAPI_ATTR 570 /* 571 * store the job attributes in the PAPI job attribute file that was 572 * created by lpsched_alloc_files(), the attributes will then pass 573 * through lpsched and be given to the slow-filters and the printer's 574 * interface script to process them 575 */ 576 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 577 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 578 status = psm_copy_attrsToFile(job_attributes, lpfile); 579 if (status != PAPI_OK) { 580 detailed_error(svc, "unable to copy attributes to file: %s: %s", 581 lpfile, strerror(errno)); 582 return (PAPI_DEVICE_ERROR); 583 } 584 #endif 585 586 /* store the meta-data file */ 587 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 588 if (putrequest(lpfile, request) < 0) { 589 detailed_error(svc, gettext("unable to save request: %s: %s"), 590 lpfile, strerror(errno)); 591 freerequest(request); 592 return (PAPI_DEVICE_ERROR); 593 } 594 595 status = lpsched_commit_job(svc, lpfile, &tmp); 596 if (status != PAPI_OK) { 597 unlink(lpfile); 598 freerequest(request); 599 return (status); 600 } 601 602 lpsched_request_to_job_attributes(request, j); 603 604 freerequest(request); 605 606 if ((c = strrchr(tmp, '-')) != NULL) 607 c++; 608 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 609 "job-id", atoi(c)); 610 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 611 "job-uri", tmp); 612 613 return (PAPI_OK); 614 } 615 616 papi_status_t 617 papiJobValidate(papi_service_t handle, char *printer, 618 papi_attribute_t **job_attributes, 619 papi_job_ticket_t *job_ticket, 620 char **files, papi_job_t *job) 621 { 622 papi_status_t status; 623 papi_attribute_t **attributes = NULL; 624 int i; 625 626 papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE, 627 "job-hold-until", "indefinite"); 628 for (i = 0; job_attributes[i]; i++) 629 list_append(&attributes, job_attributes[i]); 630 631 status = papiJobSubmitByReference(handle, printer, 632 (papi_attribute_t **)attributes, 633 job_ticket, files, job); 634 if (status == PAPI_OK) { 635 int id = papiJobGetId(*job); 636 637 if (id != -1) 638 papiJobCancel(handle, printer, id); 639 } 640 641 attributes[1] = NULL; /* after attr[0], they are in another list */ 642 papiAttributeListFree(attributes); 643 644 return (status); 645 } 646 647 papi_status_t 648 papiJobStreamOpen(papi_service_t handle, char *printer, 649 papi_attribute_t **job_attributes, 650 papi_job_ticket_t *job_ticket, papi_stream_t *stream) 651 { 652 papi_status_t status; 653 service_t *svc = handle; 654 job_stream_t *s = NULL; 655 char *request_id = NULL; 656 char lpfile[BUFSIZ]; 657 658 if ((svc == NULL) || (printer == NULL) || (stream == NULL)) 659 return (PAPI_BAD_ARGUMENT); 660 661 if (job_ticket != NULL) 662 return (PAPI_OPERATION_NOT_SUPPORTED); 663 664 if ((*stream = s = calloc(1, sizeof (*s))) == NULL) 665 return (PAPI_TEMPORARY_ERROR); 666 667 /* 1 for data, 1 for the meta-data (-0) */ 668 status = lpsched_alloc_files(svc, 2, &request_id); 669 if (status != PAPI_OK) 670 return (status); 671 672 s->request = create_request(svc, (char *)printer, 673 (papi_attribute_t **)job_attributes); 674 snprintf(lpfile, sizeof (lpfile), "/var/spool/lp/temp/%s-1", 675 request_id); 676 s->fd = open(lpfile, O_WRONLY); 677 addlist(&(s->request->file_list), lpfile); 678 679 #ifdef LP_USE_PAPI_ATTR 680 /* 681 * store the job attributes in the PAPI job attribute file that was 682 * created by lpsched_alloc_files(), the attributes will then pass 683 * through lpsched and be given to the slow-filters and the printer's 684 * interface script to process them 685 */ 686 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 687 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 688 status = psm_copy_attrsToFile(job_attributes, lpfile); 689 if (status != PAPI_OK) { 690 detailed_error(svc, "unable to copy attributes to file: %s: %s", 691 lpfile, strerror(errno)); 692 close(s->fd); 693 free(s); 694 return (PAPI_DEVICE_ERROR); 695 } 696 #endif 697 698 /* store the meta-data file */ 699 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 700 s->meta_data_file = strdup(lpfile); 701 if (putrequest(lpfile, s->request) < 0) { 702 detailed_error(svc, gettext("unable to save request: %s: %s"), 703 lpfile, strerror(errno)); 704 s->request = NULL; 705 return (PAPI_DEVICE_ERROR); 706 } 707 708 return (PAPI_OK); 709 } 710 711 papi_status_t 712 papiJobStreamWrite(papi_service_t handle, 713 papi_stream_t stream, void *buffer, size_t buflen) 714 { 715 service_t *svc = handle; 716 job_stream_t *s = stream; 717 718 if ((svc == NULL) || (stream == NULL) || (buffer == NULL)) 719 return (PAPI_BAD_ARGUMENT); 720 721 if (write(s->fd, buffer, buflen) != buflen) 722 return (PAPI_DEVICE_ERROR); 723 724 return (PAPI_OK); 725 } 726 papi_status_t 727 papiJobStreamClose(papi_service_t handle, 728 papi_stream_t stream, papi_job_t *job) 729 { 730 papi_status_t status = PAPI_OK; 731 service_t *svc = handle; 732 job_stream_t *s = stream; 733 job_t *j = NULL; 734 char *tmp = NULL, *c; 735 736 if ((svc == NULL) || (stream == NULL) || (job == NULL)) 737 return (PAPI_BAD_ARGUMENT); 738 739 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 740 return (PAPI_TEMPORARY_ERROR); 741 742 close(s->fd); 743 744 lpsched_request_to_job_attributes(s->request, j); 745 746 if (s->meta_data_file != NULL) { 747 status = lpsched_commit_job(svc, s->meta_data_file, &tmp); 748 if (status != PAPI_OK) { 749 unlink(s->meta_data_file); 750 return (status); 751 } 752 if ((c = strrchr(tmp, '-')) != NULL) 753 c++; 754 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 755 "job-id", atoi(c)); 756 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 757 "job-uri", tmp); 758 free(s->meta_data_file); 759 } 760 freerequest(s->request); 761 free(s); 762 763 return (PAPI_OK); 764 } 765 766 papi_status_t 767 papiJobQuery(papi_service_t handle, char *printer, int32_t job_id, 768 char **requested_attrs, 769 papi_job_t *job) 770 { 771 service_t *svc = handle; 772 job_t *j; 773 char *dest; 774 char req_id[32]; 775 short rc; 776 char *form = NULL, 777 *request_id = NULL, 778 *charset = NULL, 779 *user = NULL, 780 *slabel = NULL, 781 *file = NULL; 782 time_t date = 0; 783 size_t size = 0; 784 short rank = 0, 785 state = 0; 786 787 if ((handle == NULL) || (printer == NULL) || (job_id < 0)) 788 return (PAPI_BAD_ARGUMENT); 789 790 dest = printer_name_from_uri_id(printer, job_id); 791 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); 792 free(dest); 793 794 rc = snd_msg(svc, S_INQUIRE_REQUEST_RANK, 0, "", "", req_id, "", ""); 795 if (rc < 0) 796 return (PAPI_SERVICE_UNAVAILABLE); 797 798 if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &request_id, 799 &user, &slabel, &size, &date, &state, &dest, &form, 800 &charset, &rank, &file) < 0) { 801 detailed_error(svc, 802 gettext("failed to read response from scheduler")); 803 return (PAPI_DEVICE_ERROR); 804 } 805 806 if ((request_id == NULL) || (request_id[0] == NULL)) 807 return (PAPI_NOT_FOUND); 808 809 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 810 return (PAPI_TEMPORARY_ERROR); 811 812 job_status_to_attributes(j, request_id, user, slabel, size, date, state, 813 dest, form, charset, rank, file); 814 815 snprintf(req_id, sizeof (req_id), "%d-0", job_id); 816 lpsched_read_job_configuration(svc, j, req_id); 817 818 return (PAPI_OK); 819 } 820 821 papi_status_t 822 papiJobMove(papi_service_t handle, char *printer, int32_t job_id, 823 char *destination) 824 { 825 papi_status_t result = PAPI_OK; 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) < 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