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