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