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