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