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_DOCUMENT_ACCESS_ERROR); 532 } 533 if (files[file_no][0] != '/') { 534 char path[MAXPATHLEN]; 535 536 if (getcwd(path, sizeof (path)) == NULL) { 537 detailed_error(svc, gettext( 538 "getcwd for file: %s: %s"), 539 files[file_no], 540 strerror(errno)); 541 return (PAPI_DOCUMENT_ACCESS_ERROR); 542 } 543 strlcat(path, "/", sizeof (path)); 544 if (strlcat(path, files[file_no], sizeof (path)) 545 >= sizeof (path)) { 546 detailed_error(svc, gettext( 547 "pathname too long: %s"), 548 files[file_no]); 549 return (PAPI_DOCUMENT_ACCESS_ERROR); 550 } 551 addlist(&file_list, path); 552 } else 553 addlist(&file_list, (char *)files[file_no]); 554 } 555 556 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 557 return (PAPI_TEMPORARY_ERROR); 558 559 /* 1 for the control file (-0) */ 560 status = lpsched_alloc_files(svc, 1, &request_id); 561 if (status != PAPI_OK) 562 return (status); 563 564 request = create_request(svc, (char *)printer, 565 (papi_attribute_t **)job_attributes); 566 request->file_list = file_list; 567 568 #ifdef LP_USE_PAPI_ATTR 569 /* 570 * store the job attributes in the PAPI job attribute file that was 571 * created by lpsched_alloc_files(), the attributes will then pass 572 * through lpsched and be given to the slow-filters and the printer's 573 * interface script to process them 574 */ 575 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 576 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 577 status = psm_copy_attrsToFile(job_attributes, lpfile); 578 if (status != PAPI_OK) { 579 detailed_error(svc, "unable to copy attributes to file: %s: %s", 580 lpfile, strerror(errno)); 581 return (PAPI_DEVICE_ERROR); 582 } 583 #endif 584 585 /* store the meta-data file */ 586 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 587 if (putrequest(lpfile, request) < 0) { 588 detailed_error(svc, gettext("unable to save request: %s: %s"), 589 lpfile, strerror(errno)); 590 freerequest(request); 591 return (PAPI_DEVICE_ERROR); 592 } 593 594 status = lpsched_commit_job(svc, lpfile, &tmp); 595 if (status != PAPI_OK) { 596 unlink(lpfile); 597 freerequest(request); 598 return (status); 599 } 600 601 lpsched_request_to_job_attributes(request, j); 602 603 freerequest(request); 604 605 if ((c = strrchr(tmp, '-')) != NULL) 606 c++; 607 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 608 "job-id", atoi(c)); 609 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 610 "job-uri", tmp); 611 612 return (PAPI_OK); 613 } 614 615 papi_status_t 616 papiJobValidate(papi_service_t handle, char *printer, 617 papi_attribute_t **job_attributes, 618 papi_job_ticket_t *job_ticket, 619 char **files, papi_job_t *job) 620 { 621 papi_status_t status; 622 papi_attribute_t **attributes = NULL; 623 int i; 624 625 papiAttributeListAddString(&attributes, PAPI_ATTR_REPLACE, 626 "job-hold-until", "hold"); 627 for (i = 0; job_attributes[i]; i++) 628 list_append(&attributes, job_attributes[i]); 629 630 status = papiJobSubmitByReference(handle, printer, 631 (papi_attribute_t **)attributes, 632 job_ticket, files, job); 633 if (status == PAPI_OK) { 634 int id = papiJobGetId(*job); 635 636 if (id != -1) 637 papiJobCancel(handle, printer, id); 638 } 639 640 attributes[1] = NULL; /* after attr[0], they are in another list */ 641 papiAttributeListFree(attributes); 642 643 return (status); 644 } 645 646 papi_status_t 647 papiJobStreamOpen(papi_service_t handle, char *printer, 648 papi_attribute_t **job_attributes, 649 papi_job_ticket_t *job_ticket, papi_stream_t *stream) 650 { 651 papi_status_t status; 652 service_t *svc = handle; 653 job_stream_t *s = NULL; 654 char *request_id = NULL; 655 char lpfile[BUFSIZ]; 656 657 if ((svc == NULL) || (printer == NULL) || (stream == NULL)) 658 return (PAPI_BAD_ARGUMENT); 659 660 if (job_ticket != NULL) 661 return (PAPI_OPERATION_NOT_SUPPORTED); 662 663 if ((*stream = s = calloc(1, sizeof (*s))) == NULL) 664 return (PAPI_TEMPORARY_ERROR); 665 666 /* 1 for data, 1 for the meta-data (-0) */ 667 status = lpsched_alloc_files(svc, 2, &request_id); 668 if (status != PAPI_OK) 669 return (status); 670 671 s->request = create_request(svc, (char *)printer, 672 (papi_attribute_t **)job_attributes); 673 snprintf(lpfile, sizeof (lpfile), "/var/spool/lp/temp/%s-1", 674 request_id); 675 s->fd = open(lpfile, O_WRONLY); 676 addlist(&(s->request->file_list), lpfile); 677 678 #ifdef LP_USE_PAPI_ATTR 679 /* 680 * store the job attributes in the PAPI job attribute file that was 681 * created by lpsched_alloc_files(), the attributes will then pass 682 * through lpsched and be given to the slow-filters and the printer's 683 * interface script to process them 684 */ 685 snprintf(lpfile, sizeof (lpfile), "%s%s-%s", 686 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 687 status = psm_copy_attrsToFile(job_attributes, lpfile); 688 if (status != PAPI_OK) { 689 detailed_error(svc, "unable to copy attributes to file: %s: %s", 690 lpfile, strerror(errno)); 691 close(s->fd); 692 free(s); 693 return (PAPI_DEVICE_ERROR); 694 } 695 #endif 696 697 /* store the meta-data file */ 698 snprintf(lpfile, sizeof (lpfile), "%s-0", request_id); 699 s->meta_data_file = strdup(lpfile); 700 if (putrequest(lpfile, s->request) < 0) { 701 detailed_error(svc, gettext("unable to save request: %s: %s"), 702 lpfile, strerror(errno)); 703 s->request = NULL; 704 return (PAPI_DEVICE_ERROR); 705 } 706 707 return (PAPI_OK); 708 } 709 710 papi_status_t 711 papiJobStreamWrite(papi_service_t handle, 712 papi_stream_t stream, void *buffer, size_t buflen) 713 { 714 service_t *svc = handle; 715 job_stream_t *s = stream; 716 717 if ((svc == NULL) || (stream == NULL) || (buffer == NULL)) 718 return (PAPI_BAD_ARGUMENT); 719 720 if (write(s->fd, buffer, buflen) != buflen) 721 return (PAPI_DEVICE_ERROR); 722 723 return (PAPI_OK); 724 } 725 papi_status_t 726 papiJobStreamClose(papi_service_t handle, 727 papi_stream_t stream, papi_job_t *job) 728 { 729 papi_status_t status = PAPI_OK; 730 service_t *svc = handle; 731 job_stream_t *s = stream; 732 job_t *j = NULL; 733 char *tmp = NULL, *c; 734 735 if ((svc == NULL) || (stream == NULL) || (job == NULL)) 736 return (PAPI_BAD_ARGUMENT); 737 738 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 739 return (PAPI_TEMPORARY_ERROR); 740 741 close(s->fd); 742 743 lpsched_request_to_job_attributes(s->request, j); 744 745 if (s->meta_data_file != NULL) { 746 status = lpsched_commit_job(svc, s->meta_data_file, &tmp); 747 if (status != PAPI_OK) { 748 unlink(s->meta_data_file); 749 return (status); 750 } 751 if ((c = strrchr(tmp, '-')) != NULL) 752 c++; 753 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 754 "job-id", atoi(c)); 755 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 756 "job-uri", tmp); 757 free(s->meta_data_file); 758 } 759 free(s); 760 761 return (PAPI_OK); 762 } 763 764 papi_status_t 765 papiJobQuery(papi_service_t handle, char *printer, int32_t job_id, 766 char **requested_attrs, 767 papi_job_t *job) 768 { 769 service_t *svc = handle; 770 job_t *j; 771 char *dest; 772 char req_id[32]; 773 short rc; 774 char *form = NULL, 775 *request_id = NULL, 776 *charset = NULL, 777 *user = NULL, 778 *slabel = NULL, 779 *file = NULL; 780 time_t date = 0; 781 size_t size = 0; 782 short rank = 0, 783 state = 0; 784 785 if ((handle == NULL) || (printer == NULL) || (job_id < 0)) 786 return (PAPI_BAD_ARGUMENT); 787 788 dest = printer_name_from_uri_id(printer, job_id); 789 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); 790 free(dest); 791 792 rc = snd_msg(svc, S_INQUIRE_REQUEST_RANK, 0, "", "", req_id, "", ""); 793 if (rc < 0) 794 return (PAPI_SERVICE_UNAVAILABLE); 795 796 if (rcv_msg(svc, R_INQUIRE_REQUEST_RANK, &rc, &request_id, 797 &user, &slabel, &size, &date, &state, &dest, &form, 798 &charset, &rank, &file) < 0) { 799 detailed_error(svc, 800 gettext("failed to read response from scheduler")); 801 return (PAPI_DEVICE_ERROR); 802 } 803 804 if ((request_id == NULL) || (request_id[0] == NULL)) 805 return (PAPI_NOT_FOUND); 806 807 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 808 return (PAPI_TEMPORARY_ERROR); 809 810 job_status_to_attributes(j, request_id, user, slabel, size, date, state, 811 dest, form, charset, rank, file); 812 813 snprintf(req_id, sizeof (req_id), "%d-0", job_id); 814 lpsched_read_job_configuration(svc, j, req_id); 815 816 return (PAPI_OK); 817 } 818 819 papi_status_t 820 papiJobMove(papi_service_t handle, char *printer, int32_t job_id, 821 char *destination) 822 { 823 papi_status_t result = PAPI_OK; 824 service_t *svc = handle; 825 char req_id[64]; 826 char *queue; 827 char *user = NULL; 828 829 if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 830 (destination == NULL)) 831 return (PAPI_BAD_ARGUMENT); 832 833 queue = printer_name_from_uri_id(printer, job_id); 834 snprintf(req_id, sizeof (req_id), "%s-%d", queue, job_id); 835 free(queue); 836 837 if (papiAttributeListGetString(svc->attributes, NULL, "user-name", 838 &user) == PAPI_OK) { 839 REQUEST *r = getrequest(req_id); 840 841 if ((r != NULL) && (r->user != NULL) && 842 (strcmp(r->user, user) != 0)) 843 result = PAPI_NOT_AUTHORIZED; 844 freerequest(r); 845 } 846 847 if (result == PAPI_OK) { 848 short status = MOK; 849 char *dest = printer_name_from_uri_id(destination, -1); 850 851 if ((snd_msg(svc, S_MOVE_REQUEST, req_id, dest) < 0) || 852 (rcv_msg(svc, R_MOVE_REQUEST, &status) < 0)) 853 status = MTRANSMITERR; 854 855 free(dest); 856 857 result = lpsched_status_to_papi_status(status); 858 } 859 860 return (result); 861 } 862 863 papi_status_t 864 papiJobCancel(papi_service_t handle, char *printer, int32_t job_id) 865 { 866 papi_status_t result = PAPI_OK; 867 service_t *svc = handle; 868 char req_id[64]; 869 char *dest; 870 char *user = NULL; 871 872 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 873 return (PAPI_BAD_ARGUMENT); 874 875 dest = printer_name_from_uri_id(printer, job_id); 876 snprintf(req_id, sizeof (req_id), "%s-%d", dest, job_id); 877 free(dest); 878 879 if (papiAttributeListGetString(svc->attributes, NULL, "user-name", 880 &user) == PAPI_OK) { 881 REQUEST *r = getrequest(req_id); 882 883 if ((r != NULL) && (r->user != NULL) && 884 (strcmp(r->user, user) != 0)) 885 result = PAPI_NOT_AUTHORIZED; 886 freerequest(r); 887 } 888 889 if (result == PAPI_OK) { 890 short status = MOK; 891 892 if ((snd_msg(svc, S_CANCEL_REQUEST, req_id) < 0) || 893 (rcv_msg(svc, R_CANCEL_REQUEST, &status) < 0)) 894 status = MTRANSMITERR; 895 896 result = lpsched_status_to_papi_status(status); 897 } 898 899 return (result); 900 } 901 902 papi_status_t 903 hold_release_job(papi_service_t handle, char *printer, 904 int32_t job_id, int flag) 905 { 906 papi_status_t status; 907 service_t *svc = handle; 908 REQUEST *r = NULL; 909 char *file; 910 char *dest; 911 912 if ((svc == NULL) || (printer == NULL) || (job_id < 0)) 913 return (PAPI_BAD_ARGUMENT); 914 915 if ((status = authorized(svc, job_id)) != PAPI_OK) 916 return (status); 917 918 dest = printer_name_from_uri_id(printer, job_id); 919 status = lpsched_start_change(svc, dest, job_id, &file); 920 if (status != PAPI_OK) 921 return (status); 922 923 if ((r = getrequest(file)) != NULL) { 924 r->actions &= ~ACT_RESUME; 925 switch (flag) { 926 case 0: 927 r->actions |= ACT_HOLD; 928 break; 929 case 1: 930 r->actions |= ACT_RESUME; 931 break; 932 case 2: 933 r->actions |= ACT_IMMEDIATE; 934 break; 935 } 936 if (putrequest(file, r) < 0) { 937 detailed_error(svc, 938 gettext("failed to write job: %s: %s"), 939 file, strerror(errno)); 940 freerequest(r); 941 return (PAPI_DEVICE_ERROR); 942 } 943 freerequest(r); 944 } else { 945 detailed_error(svc, gettext("failed to read job: %s: %s"), 946 file, strerror(errno)); 947 return (PAPI_DEVICE_ERROR); 948 } 949 950 status = lpsched_end_change(svc, dest, job_id); 951 952 return (status); 953 } 954 955 papi_status_t 956 papiJobHold(papi_service_t handle, char *printer, int32_t job_id) 957 { 958 return (hold_release_job(handle, printer, job_id, 0)); 959 } 960 961 papi_status_t 962 papiJobRelease(papi_service_t handle, char *printer, int32_t job_id) 963 { 964 return (hold_release_job(handle, printer, job_id, 1)); 965 } 966 967 papi_status_t 968 papiJobPromote(papi_service_t handle, char *printer, int32_t job_id) 969 { 970 return (hold_release_job(handle, printer, job_id, 2)); 971 } 972 973 papi_status_t 974 papiJobModify(papi_service_t handle, char *printer, int32_t job_id, 975 papi_attribute_t **attributes, papi_job_t *job) 976 { 977 papi_status_t status; 978 job_t *j = NULL; 979 service_t *svc = handle; 980 char *file = NULL; 981 char *dest; 982 REQUEST *r = NULL; 983 char lpfile[BUFSIZ]; 984 985 if ((svc == NULL) || (printer == NULL) || (job_id < 0) || 986 (attributes == NULL)) 987 return (PAPI_BAD_ARGUMENT); 988 989 if ((status = authorized(svc, job_id)) != PAPI_OK) 990 return (status); 991 992 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 993 return (PAPI_TEMPORARY_ERROR); 994 995 dest = printer_name_from_uri_id(printer, job_id); 996 status = lpsched_start_change(svc, dest, job_id, &file); 997 if (status != PAPI_OK) 998 return (status); 999 1000 if ((r = getrequest(file)) != NULL) { 1001 job_attributes_to_lpsched_request(handle, r, 1002 (papi_attribute_t **)attributes); 1003 #ifdef LP_USE_PAPI_ATTR 1004 /* 1005 * store the job attributes in the PAPI job attribute file 1006 * that was created by the origonal job request. We need to 1007 * modify the attributes in the file as per the new attributes 1008 */ 1009 snprintf(lpfile, sizeof (lpfile), "%s%d-%s", 1010 "/var/spool/lp/temp/", job_id, LP_PAPIATTRNAME); 1011 status = psm_modifyAttrsFile(attributes, lpfile); 1012 if (status != PAPI_OK) { 1013 detailed_error(svc, 1014 "unable to modify the attributes file: %s: %s", 1015 lpfile, strerror(errno)); 1016 return (PAPI_DEVICE_ERROR); 1017 } 1018 #endif 1019 1020 if (putrequest(file, r) < 0) { 1021 detailed_error(svc, 1022 gettext("failed to write job: %s: %s"), 1023 file, strerror(errno)); 1024 freerequest(r); 1025 return (PAPI_DEVICE_ERROR); 1026 } 1027 } else { 1028 detailed_error(svc, gettext("failed to read job: %s: %s"), 1029 file, strerror(errno)); 1030 return (PAPI_DEVICE_ERROR); 1031 } 1032 1033 status = lpsched_end_change(svc, dest, job_id); 1034 lpsched_request_to_job_attributes(r, j); 1035 freerequest(r); 1036 1037 return (status); 1038 } 1039 1040 /* 1041 * Extension to PAPI, a variation of this is slated for post-1.0 1042 */ 1043 #define DUMMY_FILE "/var/spool/lp/fifos/FIFO" 1044 1045 papi_status_t 1046 papiJobCreate(papi_service_t handle, char *printer, 1047 papi_attribute_t **job_attributes, 1048 papi_job_ticket_t *job_ticket, papi_job_t *job) 1049 { 1050 papi_status_t status; 1051 service_t *svc = handle; 1052 job_t *j = NULL; 1053 REQUEST *request; 1054 char *request_id = NULL; 1055 char *c; 1056 char *tmp = NULL; 1057 char metadata_file[MAXPATHLEN]; 1058 1059 if ((svc == NULL) || (printer == NULL) || (job == NULL)) 1060 return (PAPI_BAD_ARGUMENT); 1061 1062 if (job_ticket != NULL) 1063 return (PAPI_JOB_TICKET_NOT_SUPPORTED); 1064 1065 if ((*job = j = calloc(1, sizeof (*j))) == NULL) 1066 return (PAPI_TEMPORARY_ERROR); 1067 1068 /* 1 for the control file (-0) */ 1069 status = lpsched_alloc_files(svc, 1, &request_id); 1070 if (status != PAPI_OK) 1071 return (status); 1072 1073 /* convert the attributes to an lpsched REQUEST structure */ 1074 request = create_request(svc, (char *)printer, 1075 (papi_attribute_t **)job_attributes); 1076 if (request == NULL) 1077 return (PAPI_TEMPORARY_ERROR); 1078 addlist(&request->file_list, DUMMY_FILE); /* add a dummy file */ 1079 request->actions |= ACT_HOLD; /* hold the job */ 1080 1081 #ifdef LP_USE_PAPI_ATTR 1082 /* 1083 * store the job attributes in the PAPI job attribute file that was 1084 * created by lpsched_alloc_files(), the attributes will then pass 1085 * through lpsched and be given to the slow-filters and the printer's 1086 * interface script to process them 1087 */ 1088 snprintf(metadata_file, sizeof (metadata_file), "%s%s-%s", 1089 "/var/spool/lp/temp/", request_id, LP_PAPIATTRNAME); 1090 status = psm_copy_attrsToFile(job_attributes, metadata_file); 1091 if (status != PAPI_OK) { 1092 detailed_error(svc, "unable to copy attributes to file: %s: %s", 1093 metadata_file, strerror(errno)); 1094 free(request_id); 1095 return (PAPI_DEVICE_ERROR); 1096 } 1097 #endif 1098 1099 /* store the REQUEST on disk */ 1100 snprintf(metadata_file, sizeof (metadata_file), "%s-0", request_id); 1101 free(request_id); 1102 if (putrequest(metadata_file, request) < 0) { 1103 detailed_error(svc, gettext("unable to save request: %s: %s"), 1104 metadata_file, strerror(errno)); 1105 return (PAPI_DEVICE_ERROR); 1106 } 1107 1108 status = lpsched_commit_job(svc, metadata_file, &tmp); 1109 if (status != PAPI_OK) { 1110 unlink(metadata_file); 1111 return (status); 1112 } 1113 1114 lpsched_request_to_job_attributes(request, j); 1115 1116 if ((c = strrchr(tmp, '-')) != NULL) 1117 c++; 1118 papiAttributeListAddInteger(&j->attributes, PAPI_ATTR_REPLACE, 1119 "job-id", atoi(c)); 1120 papiAttributeListAddString(&j->attributes, PAPI_ATTR_REPLACE, 1121 "job-uri", tmp); 1122 1123 return (PAPI_OK); 1124 } 1125 1126 papi_status_t 1127 papiJobCommit(papi_service_t handle, char *printer, int32_t id) 1128 { 1129 papi_status_t status = PAPI_OK; 1130 service_t *svc = handle; 1131 REQUEST *r = NULL; 1132 char *metadata_file; 1133 char *dest; 1134 1135 if ((svc == NULL) || (printer == NULL)) 1136 return (PAPI_BAD_ARGUMENT); 1137 1138 dest = printer_name_from_uri_id(printer, id); 1139 /* tell the scheduler that we want to change the job */ 1140 status = lpsched_start_change(svc, dest, id, &metadata_file); 1141 if (status != PAPI_OK) 1142 return (status); 1143 1144 if ((r = getrequest(metadata_file)) != NULL) { 1145 r->actions &= ~ACT_RESUME; 1146 r->actions |= ACT_RESUME; 1147 dellist(&r->file_list, DUMMY_FILE); 1148 1149 if (putrequest(metadata_file, r) < 0) { 1150 detailed_error(svc, 1151 gettext("failed to write job: %s: %s"), 1152 metadata_file, strerror(errno)); 1153 freerequest(r); 1154 return (PAPI_DEVICE_ERROR); 1155 } 1156 } else { 1157 detailed_error(svc, gettext("failed to read job: %s: %s"), 1158 metadata_file, strerror(errno)); 1159 return (PAPI_DEVICE_ERROR); 1160 } 1161 1162 status = lpsched_end_change(svc, dest, id); 1163 freerequest(r); 1164 1165 return (status); 1166 } 1167 1168 papi_status_t 1169 papiJobStreamAdd(papi_service_t handle, char *printer, int32_t id, 1170 papi_stream_t *stream) 1171 { 1172 papi_status_t status; 1173 service_t *svc = handle; 1174 job_stream_t *s = NULL; 1175 char *metadata_file = NULL; 1176 char *dest; 1177 char path[MAXPATHLEN]; 1178 1179 /* allocate space for the stream */ 1180 if ((*stream = s = calloc(1, sizeof (*s))) == NULL) 1181 return (PAPI_TEMPORARY_ERROR); 1182 1183 dest = printer_name_from_uri_id(printer, id); 1184 /* create/open data file (only root or lp can really do this */ 1185 snprintf(path, sizeof (path), "/var/spool/lp/temp/%d-XXXXXX", id); 1186 if ((s->fd = mkstemp(path)) < 0) { 1187 detailed_error(svc, gettext("unable to create sink (%s): %s"), 1188 path, strerror(errno)); 1189 free(s); 1190 return (PAPI_NOT_AUTHORIZED); 1191 } 1192 1193 /* add data file to job */ 1194 status = lpsched_start_change(svc, dest, id, &metadata_file); 1195 if (status != PAPI_OK) { 1196 close(s->fd); 1197 free(s); 1198 unlink(path); 1199 return (status); 1200 } 1201 1202 if ((s->request = getrequest(metadata_file)) == NULL) { 1203 detailed_error(svc, gettext("unable to load request: %s: %s"), 1204 metadata_file, strerror(errno)); 1205 close(s->fd); 1206 free(s); 1207 unlink(path); 1208 return (PAPI_NOT_POSSIBLE); 1209 } 1210 1211 addlist(&(s->request->file_list), path); 1212 1213 if (putrequest(metadata_file, s->request) < 0) { 1214 detailed_error(svc, gettext("unable to save request: %s: %s"), 1215 metadata_file, strerror(errno)); 1216 close(s->fd); 1217 free(s); 1218 unlink(path); 1219 return (PAPI_NOT_POSSIBLE); 1220 } 1221 1222 status = lpsched_end_change(svc, dest, id); 1223 1224 if (status != PAPI_OK) 1225 return (status); 1226 1227 return (PAPI_OK); 1228 } 1229