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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * 26 */ 27 28 /* $Id: in.lpd.c 170 2006-05-20 05:58:49Z njacobs $ */ 29 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <fcntl.h> 36 #include <stdarg.h> 37 #include <string.h> 38 #include <ctype.h> 39 #include <errno.h> 40 #include <syslog.h> 41 #include <libintl.h> 42 #include <pwd.h> 43 #include <grp.h> 44 #include <sys/types.h> 45 #include <sys/stat.h> 46 #include <sys/socket.h> 47 #include <netinet/in.h> 48 #include <arpa/inet.h> 49 #include <netdb.h> 50 #include <sys/systeminfo.h> 51 52 #include <papi.h> 53 #include <uri.h> 54 #include "common.h" 55 56 #define ACK(fp) { (void) fputc('\0', fp); (void) fflush(fp); } 57 #define NACK(fp) { (void) fputc('\1', fp); (void) fflush(fp); } 58 59 /* 60 * This file contains the front-end of the BSD Print Protocol adaptor. This 61 * code assumes a BSD Socket interface to the networking side. 62 */ 63 64 static char * 65 remote_host_name(FILE *fp) 66 { 67 struct hostent *hp; 68 struct sockaddr_in6 peer; 69 socklen_t peer_len = sizeof (peer); 70 int fd = fileno(fp); 71 int error_num; 72 char myname[MAXHOSTNAMELEN], tmp_buf[INET6_ADDRSTRLEN]; 73 char *hostname; 74 75 /* who is our peer ? */ 76 if (getpeername(fd, (struct sockaddr *)&peer, &peer_len) < 0) { 77 if ((errno != ENOTSOCK) && (errno != EINVAL)) 78 return (NULL); 79 else 80 return (strdup("localhost")); 81 } 82 83 /* get their name or return a string containing their address */ 84 if ((hp = getipnodebyaddr((const char *)&peer.sin6_addr, 85 sizeof (struct in6_addr), AF_INET6, 86 &error_num)) == NULL) { 87 return (strdup(inet_ntop(peer.sin6_family, 88 &peer.sin6_addr, tmp_buf, sizeof (tmp_buf)))); 89 } 90 91 /* is it "localhost" ? */ 92 if (strcasecmp(hp->h_name, "localhost") == 0) 93 return (strdup("localhost")); 94 95 /* duplicate the name because gethostbyXXXX() is not reentrant */ 96 hostname = strdup(hp->h_name); 97 (void) sysinfo(SI_HOSTNAME, myname, sizeof (myname)); 98 99 /* is it from one of my addresses ? */ 100 if ((hp = getipnodebyname(myname, AF_INET6, AI_ALL|AI_V4MAPPED, 101 &error_num)) != NULL) { 102 struct in6_addr **tmp = (struct in6_addr **)hp->h_addr_list; 103 int i = 0; 104 105 while (tmp[i] != NULL) { 106 if (memcmp(tmp[i++], &peer.sin6_addr, hp->h_length) 107 == 0) { 108 free(hostname); 109 return (strdup("localhost")); 110 } 111 } 112 } 113 114 /* It must be someone else */ 115 return (hostname); 116 } 117 118 static void 119 fatal(FILE *fp, char *fmt, ...) 120 { 121 va_list ap; 122 123 va_start(ap, fmt); 124 vsyslog(LOG_DEBUG, fmt, ap); 125 vfprintf(fp, fmt, ap); 126 va_end(ap); 127 exit(1); 128 } 129 130 static void 131 cleanup(char ***files, char **cf) 132 { 133 if (*files != NULL) { 134 int i; 135 136 for (i = 0; (*files)[i] != NULL; i++) { 137 (void) unlink((*files)[i]); 138 free((*files)[i]); 139 } 140 free(*files); 141 *files = NULL; 142 } 143 144 if (*cf != NULL) { 145 free(*cf); 146 *cf = NULL; 147 } 148 } 149 150 static papi_attribute_t ** 151 parse_cf(papi_service_t svc, char *cf, char **files) 152 { 153 papi_attribute_t **list = NULL; 154 char previous = NULL, 155 *entry, 156 *s, 157 text[BUFSIZ]; 158 int count = 0, 159 copies_set = 0, 160 copies = 0; 161 162 for (entry = strtok(cf, "\n"); entry != NULL; 163 entry = strtok(NULL, "\n")) { 164 char *format = NULL; 165 166 /* count the copies */ 167 if ((entry[0] >= 'a') && (entry[0] <= 'z') && 168 (copies_set == 0) && (previous == entry[0])) 169 copies++; 170 else if ((previous >= 'a') && (previous <= 'z')) 171 copies_set = 1; 172 previous = entry[0]; 173 174 /* process the control message */ 175 switch (entry[0]) { 176 /* RFC-1179 options */ 177 case 'J': /* RFC-1179 Banner Job Name */ 178 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 179 "job-name", ++entry); 180 break; 181 case 'C': /* RFC-1179 Banner Class Name */ 182 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 183 "rfc-1179-class", ++entry); 184 break; 185 case 'L': /* RFC-1179 Banner toggle */ 186 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 187 "job-sheets", "standard"); 188 break; 189 case 'T': /* RFC-1179 Title (pr) */ 190 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 191 "pr-title", ++entry); 192 break; 193 case 'H': /* RFC-1179 Host */ 194 /* 195 * use the host as known by us, not by them 196 * 197 * papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 198 * "job-originating-host-name", ++entry); 199 */ 200 break; 201 case 'P': /* RFC-1179 User */ 202 ++entry; 203 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 204 "requesting-user-name", entry); 205 papiServiceSetUserName(svc, entry); 206 break; 207 case 'M': /* RFC-1179 Mail to User */ 208 papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL, 209 "rfc-1179-mail", 1); 210 break; 211 case 'W': /* RFC-1179 Width (pr) */ 212 papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 213 "pr-width", atoi(++entry)); 214 break; 215 case 'I': /* RFC-1179 Indent (pr) */ 216 papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 217 "pr-indent", atoi(++entry)); 218 break; 219 case 'N': /* RFC-1179 Filename */ 220 /* could have HPUX extension embedded */ 221 if (entry[1] != ' ') { /* real pathname */ 222 #ifdef DEBUG 223 papiAttributeListAddString(&list, 224 PAPI_ATTR_EXCL, 225 "flist", ++entry); 226 #endif 227 } else if (entry[2] == 'O') /* HPUX lp -o options */ 228 papiAttributeListFromString(&list, 229 PAPI_ATTR_APPEND, ++entry); 230 break; 231 case 'U': /* RFC-1179 Unlink */ 232 break; /* ignored */ 233 case '1': /* RFC-1179 TROFF Font R */ 234 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 235 "rfc-1179-font-r", ++entry); 236 break; 237 case '2': /* RFC-1179 TROFF Font I */ 238 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 239 "rfc-1179-font-i", ++entry); 240 break; 241 case '3': /* RFC-1179 TROFF Font B */ 242 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 243 "rfc-1179-font-b", ++entry); 244 break; 245 case '4': /* RFC-1179 TROFF Font S */ 246 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 247 "rfc-1179-font-s", ++entry); 248 break; 249 case 'f': /* RFC-1179 ASCII file (print) */ 250 format = "text/plain"; 251 if (is_postscript(files[0]) == 1) 252 format = "application/postscript"; 253 break; 254 case 'l': /* RFC-1179 CATV file (print) */ 255 format = "application/octet-stream"; 256 if (is_postscript(files[0]) == 1) 257 format = "application/postscript"; 258 break; 259 case 'o': /* RFC-1179 Postscript file (print) */ 260 format = "application/postscript"; 261 break; 262 case 'p': /* RFC-1179 PR file (print) */ 263 format = "application/x-pr"; 264 papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL, 265 "pr-filter", 1); 266 break; 267 case 't': /* RFC-1179 TROFF file (print) */ 268 format = "application/x-troff"; 269 break; 270 case 'n': /* RFC-1179 DITROFF file (print) */ 271 format = "application/x-ditroff"; 272 break; 273 case 'd': /* RFC-1179 DVI file (print) */ 274 format = "application/x-dvi"; 275 break; 276 case 'g': /* RFC-1179 GRAPH file (print) */ 277 format = "application/x-plot"; 278 break; 279 case 'c': /* RFC-1179 CIF file (print) */ 280 format = "application/x-cif"; 281 break; 282 case 'v': /* RFC-1179 RASTER file (print) */ 283 format = "application/x-raster"; 284 break; 285 case 'r': /* RFC-1179 FORTRAN file (print) */ 286 format = "application/x-fortran"; 287 break; 288 /* Sun Solaris Extensions */ 289 case 'O': 290 ++entry; 291 do { 292 if (*entry != '"') 293 text[count++] = *entry; 294 } while (*entry++); 295 papiAttributeListFromString(&list, PAPI_ATTR_APPEND, 296 text); 297 break; 298 case '5': 299 ++entry; 300 switch (entry[0]) { 301 case 'f': /* Solaris form */ 302 papiAttributeListAddString(&list, 303 PAPI_ATTR_EXCL, 304 "form", ++entry); 305 break; 306 case 'H': /* Solaris handling */ 307 ++entry; 308 if (strcasecmp(entry, "hold") == 0) 309 papiAttributeListAddString(&list, 310 PAPI_ATTR_EXCL, 311 "job-hold-until", "indefinite"); 312 else if (strcasecmp(entry, "immediate") == 0) 313 papiAttributeListAddString(&list, 314 PAPI_ATTR_EXCL, 315 "job-hold-until", "no-hold"); 316 else 317 papiAttributeListAddString(&list, 318 PAPI_ATTR_EXCL, 319 "job-hold-until", entry); 320 break; 321 case 'p': /* Solaris notification */ 322 papiAttributeListAddBoolean(&list, 323 PAPI_ATTR_EXCL, "rfc-1179-mail", 1); 324 break; 325 case 'P': { /* Solaris page list */ 326 char buf[BUFSIZ]; 327 328 snprintf(buf, sizeof (buf), "page-ranges=%s", 329 ++entry); 330 papiAttributeListFromString(&list, 331 PAPI_ATTR_EXCL, buf); 332 } 333 break; 334 case 'q': { /* Solaris priority */ 335 int i = atoi(optarg); 336 337 i = 100 - (i * 2.5); 338 if ((i < 1) || (i > 100)) 339 i = 50; 340 papiAttributeListAddInteger(&list, 341 PAPI_ATTR_EXCL, "job-priority", i); 342 } 343 break; 344 case 'S': /* Solaris character set */ 345 papiAttributeListAddString(&list, 346 PAPI_ATTR_EXCL, "lp-charset", 347 ++entry); 348 break; 349 case 'T': /* Solaris type */ 350 format = lp_type_to_mime_type(++entry); 351 break; 352 case 'y': /* Solaris mode */ 353 papiAttributeListAddString(&list, 354 PAPI_ATTR_APPEND, "lp-modes", ++entry); 355 break; 356 default: 357 syslog(LOG_INFO|LOG_DEBUG, 358 "Warning: cf message (%s) ignored", 359 entry); 360 break; 361 } 362 break; 363 /* Undefined Extensions: SCO, Ultrix, AIX, ... */ 364 365 default: 366 syslog(LOG_INFO|LOG_DEBUG, 367 "Warning: cf message (%s) ignored", entry); 368 break; 369 } 370 371 if (format != NULL) 372 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 373 "document-format", format); 374 } 375 376 papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 377 "copies", ++copies); 378 papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 379 "job-sheets", "none"); 380 381 return (list); 382 } 383 384 static papi_status_t 385 submit_job(papi_service_t svc, FILE *ifp, char *printer, int rid, char *cf, 386 char **files) 387 { 388 papi_attribute_t **list = NULL; 389 papi_status_t status; 390 papi_job_t job = NULL; 391 char *format = ""; 392 393 if ((list = parse_cf(svc, cf, files)) != NULL) { 394 /* use the host as known by us, not by them */ 395 char *host = remote_host_name(ifp); 396 397 if (host != NULL) { 398 papiAttributeListAddString(&list, PAPI_ATTR_REPLACE, 399 "job-originating-host-name", host); 400 free(host); 401 } 402 if (rid > 0) { 403 papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 404 "job-id-requested", rid); 405 } 406 } 407 408 status = papiJobSubmit(svc, printer, list, NULL, files, &job); 409 syslog(LOG_DEBUG, "submit: %s", papiStatusString(status)); 410 if (status != PAPI_OK) { 411 char *tmp = papiServiceGetStatusMessage(svc); 412 413 syslog(LOG_DEBUG, "submit-detail: %s", tmp ? tmp : "none"); 414 } 415 papiJobFree(job); 416 417 return (status); 418 } 419 420 static char * 421 receive_control_file(papi_service_t svc, FILE *ifp, FILE *ofp, int size) 422 { 423 char *ptr, *cf_data; 424 425 if ((ptr = cf_data = calloc(1, size + 1)) == NULL) { 426 NACK(ofp); 427 return (NULL); 428 } else 429 ACK(ofp); 430 431 while (size > 0) { 432 int rc; 433 434 if (((rc = fread(ptr, 1, size, ifp)) == 0) && 435 (feof(ifp) != 0)) { 436 free(cf_data); 437 return (NULL); 438 } else { 439 ptr += rc; 440 size -= rc; 441 } 442 } 443 syslog(LOG_DEBUG, "cf_data(%s)", cf_data); 444 445 if (fgetc(ifp) != 0) { 446 free(cf_data); 447 return (NULL); 448 } 449 ACK(ofp); 450 451 return (cf_data); 452 } 453 454 static char * 455 receive_data_file(FILE *ifp, FILE *ofp, int size) 456 { 457 char file[] = "lpdXXXXXX"; 458 char buf[BUFSIZ]; 459 int fd; 460 461 if ((fd = mkstemp(file)) < 0) { 462 NACK(ofp); 463 return (NULL); 464 } else 465 ACK(ofp); 466 467 while (size > 0) { 468 int rc = ((size > BUFSIZ) ? BUFSIZ : size); 469 470 if (((rc = fread(buf, 1, rc, ifp)) == 0) && 471 (feof(ifp) != 0)) { 472 close(fd); 473 unlink(file); 474 return (NULL); 475 } else { 476 char *ptr = buf; 477 478 while (rc > 0) { 479 int wrc = write(fd, ptr, rc); 480 481 if (wrc < 0) { 482 close(fd); 483 unlink(file); 484 return (NULL); 485 } 486 487 ptr += wrc; 488 size -= wrc; 489 rc -= wrc; 490 } 491 } 492 } 493 close(fd); 494 if (fgetc(ifp) != 0) { 495 unlink(file); 496 return (NULL); 497 } 498 ACK(ofp); 499 500 return (strdup(file)); 501 } 502 503 static papi_status_t 504 berkeley_receive_files(papi_service_t svc, FILE *ifp, FILE *ofp, char *printer) 505 { 506 papi_status_t status = PAPI_OK; 507 char *file, **files = NULL; /* the job data files */ 508 char *cf = NULL; 509 int rid = 0; 510 char buf[BUFSIZ]; 511 512 while (fgets(buf, sizeof (buf), ifp) != NULL) { 513 int size; 514 515 syslog(LOG_DEBUG, "XFER CMD: (%d)%s\n", buf[0], &buf[1]); 516 #ifdef DEBUG /* translate [1-3]... messages to \[1-3] to run by hand */ 517 if ((buf[0] > '0') && (buf[0] < '4')) 518 buf[0] -= '0'; 519 #endif 520 switch (buf[0]) { 521 case 0x01: /* Abort */ 522 cleanup(&files, &cf); 523 break; 524 case 0x02: { /* Receive control file */ 525 if (((cf = strchr(buf, ' ')) != NULL) && 526 (strlen(cf) > 4)) { 527 while ((*cf != NULL) && (isdigit(*cf) == 0)) 528 cf++; 529 rid = atoi(cf); 530 } 531 cf = receive_control_file(svc, ifp, ofp, atoi(&buf[1])); 532 if (cf == NULL) { 533 cleanup(&files, &cf); 534 return (PAPI_BAD_REQUEST); 535 } else if (files != NULL) { 536 status = submit_job(svc, ifp, printer, rid, cf, 537 files); 538 cleanup(&files, &cf); 539 } 540 } 541 break; 542 case 0x03: { /* Receive data file */ 543 file = receive_data_file(ifp, ofp, atoi(&buf[1])); 544 if (file == NULL) { 545 cleanup(&files, &cf); 546 return (PAPI_TEMPORARY_ERROR); 547 } 548 list_append(&files, file); 549 } 550 break; 551 default: 552 cleanup(&files, &cf); 553 fatal(ofp, "protocol screwup"); 554 break; 555 } 556 } 557 558 if ((cf != NULL) && (files != NULL)) 559 status = submit_job(svc, ifp, printer, rid, cf, files); 560 561 cleanup(&files, &cf); 562 563 return (status); 564 } 565 566 static papi_status_t 567 berkeley_transfer_files(papi_service_t svc, FILE *ifp, FILE *ofp, 568 char *printer) 569 { 570 papi_status_t status; 571 papi_printer_t p = NULL; 572 char *keys[] = { "printer-is-accepting-jobs", NULL }; 573 574 status = papiPrinterQuery(svc, printer, keys, NULL, &p); 575 if ((status == PAPI_OK) && (p != NULL)) { 576 papi_attribute_t **attrs = papiPrinterGetAttributeList(p); 577 char accepting = PAPI_FALSE; 578 579 papiAttributeListGetBoolean(attrs, NULL, 580 "printer-is-accepting-jobs", &accepting); 581 582 if (accepting == PAPI_TRUE) { 583 ACK(ofp); 584 status = berkeley_receive_files(svc, ifp, ofp, printer); 585 } else 586 NACK(ofp); 587 588 papiPrinterFree(p); 589 } else 590 NACK(ofp); 591 592 return (status); 593 } 594 595 static int 596 cyclical_service_check(char *svc_name) 597 { 598 papi_attribute_t **list; 599 char buf[BUFSIZ]; 600 uri_t *uri = NULL; 601 char *s = NULL; 602 603 /* was there a printer? */ 604 if (svc_name == NULL) 605 return (0); 606 607 if ((list = getprinterbyname(svc_name, NULL)) == NULL) 608 return (0); /* if it doesnt' resolve, we will fail later */ 609 610 papiAttributeListGetString(list, NULL, "printer-uri-supported", &s); 611 if ((s == NULL) || (strcasecmp(svc_name, s) != 0)) 612 return (0); /* they don't match */ 613 614 /* is it in uri form? */ 615 if (uri_from_string(s, &uri) < 0) 616 return (0); 617 618 if ((uri == NULL) || (uri->scheme == NULL) || (uri->host == NULL)) { 619 uri_free(uri); 620 return (0); 621 } 622 623 /* is it in lpd form? */ 624 if (strcasecmp(uri->scheme, "lpd") != 0) { 625 uri_free(uri); 626 return (0); 627 } 628 629 /* is it the local host? */ 630 sysinfo(SI_HOSTNAME, buf, sizeof (buf)); 631 if ((strcasecmp(uri->host, "localhost") != 0) && 632 (strcasecmp(uri->host, buf) != 0)) { 633 uri_free(uri); 634 return (0); 635 } 636 637 uri_free(uri); 638 return (1); 639 } 640 641 642 /* 643 * This is the entry point for this program. The program takes the 644 * following options: 645 * (none) 646 */ 647 int 648 main(int ac, char *av[]) 649 { 650 papi_status_t status; 651 papi_service_t svc = NULL; 652 papi_encryption_t encryption = PAPI_ENCRYPT_NEVER; 653 FILE *ifp = stdin, 654 *ofp = stdout; 655 int c; 656 char buf[BUFSIZ], 657 **args, 658 *printer, 659 *run_dir = "/var/run/in.lpd", 660 *run_user = NULL; 661 struct passwd *pw = NULL; 662 663 (void) chdir("/tmp"); /* run in /tmp by default */ 664 openlog("bsd-gw", LOG_PID, LOG_LPR); 665 666 while ((c = getopt(ac, av, "Ed:u:")) != EOF) 667 switch (c) { 668 case 'E': 669 encryption = PAPI_ENCRYPT_ALWAYS; 670 break; 671 case 'd': /* run where they tell you */ 672 run_dir = optarg; 673 break; 674 case 'u': /* run as */ 675 run_user = optarg; 676 break; 677 default: 678 ; 679 } 680 681 if (run_user != NULL) /* get the requested user info */ 682 pw = getpwnam(run_user); 683 684 if (run_dir != NULL) { /* setup the run_dir */ 685 (void) mkdir(run_dir, 0700); 686 if (pw != NULL) 687 (void) chown(run_dir, pw->pw_uid, pw->pw_gid); 688 } 689 690 if (pw != NULL) { /* run as the requested user */ 691 syslog(LOG_DEBUG, "name: %s, uid: %d, gid: %d", 692 pw->pw_name, pw->pw_uid, pw->pw_gid); 693 initgroups(pw->pw_name, pw->pw_gid); 694 setgid(pw->pw_gid); 695 setuid(pw->pw_uid); 696 } 697 698 if (run_dir != NULL) /* move to the run_dir */ 699 if (chdir(run_dir) < 0) { 700 syslog(LOG_DEBUG, "failed to chdir(%s)", run_dir); 701 exit(1); 702 } 703 704 syslog(LOG_DEBUG, "$CWD = %s", getwd(NULL)); 705 706 if (fgets(buf, sizeof (buf), ifp) == NULL) { 707 if (feof(ifp) == 0) 708 syslog(LOG_ERR, "Error reading from connection: %s", 709 strerror(errno)); 710 exit(1); 711 } 712 713 syslog(LOG_DEBUG, "CMD: (%d)%s\n", buf[0], &buf[1]); 714 715 #ifdef DEBUG /* translate [1-5]... messages to \[1-5] to run by hand */ 716 if ((buf[0] > '0') && (buf[0] < '6')) 717 buf[0] -= '0'; 718 #endif 719 720 if ((buf[0] < 1) || (buf[0] > 5)) { 721 fatal(ofp, "Invalid protocol request (%d): %c%s\n", 722 buf[0], buf[0], buf); 723 exit(1); 724 } 725 726 args = strsplit(&buf[1], "\t\n "); 727 printer = *args++; 728 729 if (printer == NULL) { 730 fatal(ofp, "Can't determine requested printer"); 731 exit(1); 732 } 733 734 if (cyclical_service_check(printer) != 0) { 735 fatal(ofp, "%s is cyclical\n", printer); 736 exit(1); 737 } 738 739 status = papiServiceCreate(&svc, printer, NULL, NULL, NULL, 740 encryption, NULL); 741 if (status != PAPI_OK) { 742 fatal(ofp, "Failed to contact service for %s: %s\n", printer, 743 verbose_papi_message(svc, status)); 744 exit(1); 745 } 746 747 /* 748 * Trusted Solaris can't be trusting of intermediaries. Pass 749 * the socket connection to the print service to retrieve the 750 * sensativity label off of a multi-level port. 751 */ 752 (void) papiServiceSetPeer(svc, fileno(ifp)); 753 754 switch (buf[0]) { 755 case '\1': /* restart printer */ 756 ACK(ofp); /* there is no equivalent */ 757 break; 758 case '\2': /* transfer job(s) */ 759 status = berkeley_transfer_files(svc, ifp, ofp, printer); 760 break; 761 case '\3': /* show queue (short) */ 762 case '\4': { /* show queue (long) */ 763 int count; 764 765 for (count = 0; args[count] != 0; count++); 766 767 berkeley_queue_report(svc, ofp, printer, buf[0], count, args); 768 } 769 break; 770 case '\5': { /* cancel job(s) */ 771 char *user = *args++; 772 char *host = remote_host_name(ifp); 773 int count; 774 775 if (host != NULL) { 776 char buf[BUFSIZ]; 777 778 snprintf(buf, sizeof (buf), "%s@%s", user, host); 779 status = papiServiceSetUserName(svc, buf); 780 } else 781 status = papiServiceSetUserName(svc, user); 782 783 for (count = 0; args[count] != 0; count++); 784 785 berkeley_cancel_request(svc, ofp, printer, count, args); 786 } 787 break; 788 default: 789 fatal(ofp, "unsupported protocol request (%c), %s", 790 buf[0], &buf[1]); 791 } 792 793 (void) fflush(ofp); 794 795 syslog(LOG_DEBUG, "protocol request(%d) for %s completed: %s", 796 buf[0], printer, papiStatusString(status)); 797 if (status != PAPI_OK) 798 syslog(LOG_DEBUG, "detail: %s", 799 verbose_papi_message(svc, status)); 800 801 papiServiceDestroy(svc); 802 803 return (0); 804 } 805