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