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