12264Sjacobs /* 22264Sjacobs * CDDL HEADER START 32264Sjacobs * 42264Sjacobs * The contents of this file are subject to the terms of the 52264Sjacobs * Common Development and Distribution License (the "License"). 62264Sjacobs * You may not use this file except in compliance with the License. 72264Sjacobs * 82264Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92264Sjacobs * or http://www.opensolaris.org/os/licensing. 102264Sjacobs * See the License for the specific language governing permissions 112264Sjacobs * and limitations under the License. 122264Sjacobs * 132264Sjacobs * When distributing Covered Code, include this CDDL HEADER in each 142264Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152264Sjacobs * If applicable, add the following below this CDDL HEADER, with the 162264Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying 172264Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner] 182264Sjacobs * 192264Sjacobs * CDDL HEADER END 202264Sjacobs */ 212264Sjacobs 222264Sjacobs /* 23*9606SKeerthi.Kondaka@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 242264Sjacobs * Use is subject to license terms. 252264Sjacobs * 262264Sjacobs */ 272264Sjacobs 282264Sjacobs /* $Id: in.lpd.c 170 2006-05-20 05:58:49Z njacobs $ */ 292264Sjacobs 302264Sjacobs #include <stdio.h> 312264Sjacobs #include <stdlib.h> 323125Sjacobs #include <unistd.h> 333125Sjacobs #include <fcntl.h> 342264Sjacobs #include <stdarg.h> 352264Sjacobs #include <string.h> 366817Sjacobs #include <ctype.h> 372264Sjacobs #include <errno.h> 382264Sjacobs #include <syslog.h> 392264Sjacobs #include <libintl.h> 403125Sjacobs #include <pwd.h> 413125Sjacobs #include <grp.h> 423125Sjacobs #include <sys/types.h> 433125Sjacobs #include <sys/stat.h> 443125Sjacobs #include <sys/socket.h> 453125Sjacobs #include <netinet/in.h> 463125Sjacobs #include <arpa/inet.h> 473125Sjacobs #include <netdb.h> 483125Sjacobs #include <sys/systeminfo.h> 492264Sjacobs 502264Sjacobs #include <papi.h> 513125Sjacobs #include <uri.h> 522264Sjacobs #include "common.h" 532264Sjacobs 542264Sjacobs #define ACK(fp) { (void) fputc('\0', fp); (void) fflush(fp); } 552264Sjacobs #define NACK(fp) { (void) fputc('\1', fp); (void) fflush(fp); } 562264Sjacobs 572264Sjacobs /* 582264Sjacobs * This file contains the front-end of the BSD Print Protocol adaptor. This 592264Sjacobs * code assumes a BSD Socket interface to the networking side. 602264Sjacobs */ 612264Sjacobs 623125Sjacobs static char * 633125Sjacobs remote_host_name(FILE *fp) 643125Sjacobs { 653125Sjacobs struct hostent *hp; 663125Sjacobs struct sockaddr_in6 peer; 673125Sjacobs socklen_t peer_len = sizeof (peer); 683125Sjacobs int fd = fileno(fp); 693125Sjacobs int error_num; 707132Sps29005 char tmp_buf[INET6_ADDRSTRLEN]; 713125Sjacobs char *hostname; 723125Sjacobs 733125Sjacobs /* who is our peer ? */ 743125Sjacobs if (getpeername(fd, (struct sockaddr *)&peer, &peer_len) < 0) { 753125Sjacobs if ((errno != ENOTSOCK) && (errno != EINVAL)) 763125Sjacobs return (NULL); 773125Sjacobs else 783125Sjacobs return (strdup("localhost")); 793125Sjacobs } 803125Sjacobs 813125Sjacobs /* get their name or return a string containing their address */ 823125Sjacobs if ((hp = getipnodebyaddr((const char *)&peer.sin6_addr, 833125Sjacobs sizeof (struct in6_addr), AF_INET6, 843125Sjacobs &error_num)) == NULL) { 853125Sjacobs return (strdup(inet_ntop(peer.sin6_family, 863125Sjacobs &peer.sin6_addr, tmp_buf, sizeof (tmp_buf)))); 873125Sjacobs } 883125Sjacobs 897132Sps29005 hostname = strdup(hp->h_name); 907132Sps29005 if (is_localhost(hp->h_name) != 0) 913125Sjacobs return (strdup("localhost")); 923125Sjacobs 933125Sjacobs /* It must be someone else */ 943125Sjacobs return (hostname); 953125Sjacobs } 963125Sjacobs 973125Sjacobs static void 982264Sjacobs fatal(FILE *fp, char *fmt, ...) 992264Sjacobs { 1002264Sjacobs va_list ap; 1012264Sjacobs 1022264Sjacobs va_start(ap, fmt); 1032264Sjacobs vsyslog(LOG_DEBUG, fmt, ap); 1042264Sjacobs vfprintf(fp, fmt, ap); 1052264Sjacobs va_end(ap); 1063125Sjacobs exit(1); 1072264Sjacobs } 1082264Sjacobs 1092264Sjacobs static void 1103125Sjacobs cleanup(char ***files, char **cf) 1113125Sjacobs { 1123125Sjacobs if (*files != NULL) { 1133125Sjacobs int i; 1143125Sjacobs 1153125Sjacobs for (i = 0; (*files)[i] != NULL; i++) { 1163125Sjacobs (void) unlink((*files)[i]); 1173125Sjacobs free((*files)[i]); 1183125Sjacobs } 1193125Sjacobs free(*files); 1203125Sjacobs *files = NULL; 1213125Sjacobs } 1223125Sjacobs 1233125Sjacobs if (*cf != NULL) { 1243125Sjacobs free(*cf); 1253125Sjacobs *cf = NULL; 1263125Sjacobs } 1273125Sjacobs } 1283125Sjacobs 1293125Sjacobs static papi_attribute_t ** 1303125Sjacobs parse_cf(papi_service_t svc, char *cf, char **files) 1312264Sjacobs { 1323125Sjacobs papi_attribute_t **list = NULL; 1333125Sjacobs char previous = NULL, 1347132Sps29005 *entry; 1357132Sps29005 int copies_set = 0, 1363125Sjacobs copies = 0; 1373125Sjacobs 1383125Sjacobs for (entry = strtok(cf, "\n"); entry != NULL; 1393125Sjacobs entry = strtok(NULL, "\n")) { 1403125Sjacobs char *format = NULL; 1413125Sjacobs 1423125Sjacobs /* count the copies */ 1433125Sjacobs if ((entry[0] >= 'a') && (entry[0] <= 'z') && 1443125Sjacobs (copies_set == 0) && (previous == entry[0])) 1453125Sjacobs copies++; 1463125Sjacobs else if ((previous >= 'a') && (previous <= 'z')) 1473125Sjacobs copies_set = 1; 1483125Sjacobs previous = entry[0]; 1492264Sjacobs 1503125Sjacobs /* process the control message */ 1513125Sjacobs switch (entry[0]) { 1523125Sjacobs /* RFC-1179 options */ 1533125Sjacobs case 'J': /* RFC-1179 Banner Job Name */ 1543125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 1553125Sjacobs "job-name", ++entry); 1563125Sjacobs break; 1573125Sjacobs case 'C': /* RFC-1179 Banner Class Name */ 1583125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 1593125Sjacobs "rfc-1179-class", ++entry); 1603125Sjacobs break; 1613125Sjacobs case 'L': /* RFC-1179 Banner toggle */ 1623125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 1633125Sjacobs "job-sheets", "standard"); 1643125Sjacobs break; 1653125Sjacobs case 'T': /* RFC-1179 Title (pr) */ 1663125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 1673125Sjacobs "pr-title", ++entry); 1683125Sjacobs break; 1693125Sjacobs case 'H': /* RFC-1179 Host */ 1703125Sjacobs /* 1713125Sjacobs * use the host as known by us, not by them 1723125Sjacobs * 1733125Sjacobs * papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 1743125Sjacobs * "job-originating-host-name", ++entry); 1753125Sjacobs */ 1763125Sjacobs break; 1773125Sjacobs case 'P': /* RFC-1179 User */ 1783125Sjacobs ++entry; 1793125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 180*9606SKeerthi.Kondaka@Sun.COM "job-originating-user-name", entry); 1813125Sjacobs papiServiceSetUserName(svc, entry); 1823125Sjacobs break; 1833125Sjacobs case 'M': /* RFC-1179 Mail to User */ 1843125Sjacobs papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL, 1853125Sjacobs "rfc-1179-mail", 1); 1863125Sjacobs break; 1873125Sjacobs case 'W': /* RFC-1179 Width (pr) */ 1883125Sjacobs papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 1893125Sjacobs "pr-width", atoi(++entry)); 1903125Sjacobs break; 1913125Sjacobs case 'I': /* RFC-1179 Indent (pr) */ 1923125Sjacobs papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 1933125Sjacobs "pr-indent", atoi(++entry)); 1943125Sjacobs break; 1953125Sjacobs case 'N': /* RFC-1179 Filename */ 1963125Sjacobs /* could have HPUX extension embedded */ 1973125Sjacobs if (entry[1] != ' ') { /* real pathname */ 1983125Sjacobs #ifdef DEBUG 1993125Sjacobs papiAttributeListAddString(&list, 2003125Sjacobs PAPI_ATTR_EXCL, 2013125Sjacobs "flist", ++entry); 2023125Sjacobs #endif 2033125Sjacobs } else if (entry[2] == 'O') /* HPUX lp -o options */ 2043125Sjacobs papiAttributeListFromString(&list, 2053125Sjacobs PAPI_ATTR_APPEND, ++entry); 2063125Sjacobs break; 2073125Sjacobs case 'U': /* RFC-1179 Unlink */ 2083125Sjacobs break; /* ignored */ 2093125Sjacobs case '1': /* RFC-1179 TROFF Font R */ 2103125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 2113125Sjacobs "rfc-1179-font-r", ++entry); 2123125Sjacobs break; 2133125Sjacobs case '2': /* RFC-1179 TROFF Font I */ 2143125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 2153125Sjacobs "rfc-1179-font-i", ++entry); 2163125Sjacobs break; 2173125Sjacobs case '3': /* RFC-1179 TROFF Font B */ 2183125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 2193125Sjacobs "rfc-1179-font-b", ++entry); 2203125Sjacobs break; 2213125Sjacobs case '4': /* RFC-1179 TROFF Font S */ 2223125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 2233125Sjacobs "rfc-1179-font-s", ++entry); 2243125Sjacobs break; 2253125Sjacobs case 'f': /* RFC-1179 ASCII file (print) */ 2263125Sjacobs format = "text/plain"; 2273125Sjacobs if (is_postscript(files[0]) == 1) 2283125Sjacobs format = "application/postscript"; 2293125Sjacobs break; 2303125Sjacobs case 'l': /* RFC-1179 CATV file (print) */ 2313125Sjacobs format = "application/octet-stream"; 2323125Sjacobs if (is_postscript(files[0]) == 1) 2333125Sjacobs format = "application/postscript"; 2343125Sjacobs break; 2353125Sjacobs case 'o': /* RFC-1179 Postscript file (print) */ 2363125Sjacobs format = "application/postscript"; 2373125Sjacobs break; 2383125Sjacobs case 'p': /* RFC-1179 PR file (print) */ 2393125Sjacobs format = "application/x-pr"; 2403125Sjacobs papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL, 2413125Sjacobs "pr-filter", 1); 2423125Sjacobs break; 2433125Sjacobs case 't': /* RFC-1179 TROFF file (print) */ 2443125Sjacobs format = "application/x-troff"; 2453125Sjacobs break; 2463125Sjacobs case 'n': /* RFC-1179 DITROFF file (print) */ 2473125Sjacobs format = "application/x-ditroff"; 2483125Sjacobs break; 2493125Sjacobs case 'd': /* RFC-1179 DVI file (print) */ 2503125Sjacobs format = "application/x-dvi"; 2513125Sjacobs break; 2523125Sjacobs case 'g': /* RFC-1179 GRAPH file (print) */ 2533125Sjacobs format = "application/x-plot"; 2543125Sjacobs break; 2553125Sjacobs case 'c': /* RFC-1179 CIF file (print) */ 2563125Sjacobs format = "application/x-cif"; 2573125Sjacobs break; 2583125Sjacobs case 'v': /* RFC-1179 RASTER file (print) */ 2593125Sjacobs format = "application/x-raster"; 2603125Sjacobs break; 2613125Sjacobs case 'r': /* RFC-1179 FORTRAN file (print) */ 2623125Sjacobs format = "application/x-fortran"; 2633125Sjacobs break; 2643125Sjacobs /* Sun Solaris Extensions */ 2653125Sjacobs case 'O': 2663125Sjacobs ++entry; 2677132Sps29005 { 2687132Sps29005 int rd, wr; 2697132Sps29005 2707132Sps29005 for (rd = wr = 0; entry[rd] != '\0'; rd++) { 2717132Sps29005 if (entry[rd] == '"') 2727132Sps29005 continue; 2737132Sps29005 if (rd != wr) 2747132Sps29005 entry[wr] = entry[rd]; 2757132Sps29005 wr++; 2767132Sps29005 } 2777132Sps29005 entry[wr] = '\0'; 2787132Sps29005 2797132Sps29005 papiAttributeListFromString(&list, 2807132Sps29005 PAPI_ATTR_APPEND, entry); 2817132Sps29005 } 2823125Sjacobs break; 2833125Sjacobs case '5': 2843125Sjacobs ++entry; 2853125Sjacobs switch (entry[0]) { 2863125Sjacobs case 'f': /* Solaris form */ 2873125Sjacobs papiAttributeListAddString(&list, 2883125Sjacobs PAPI_ATTR_EXCL, 2893125Sjacobs "form", ++entry); 2903125Sjacobs break; 2913125Sjacobs case 'H': /* Solaris handling */ 2923125Sjacobs ++entry; 2933125Sjacobs if (strcasecmp(entry, "hold") == 0) 2943125Sjacobs papiAttributeListAddString(&list, 2953125Sjacobs PAPI_ATTR_EXCL, 2963125Sjacobs "job-hold-until", "indefinite"); 2976725Sjacobs else if (strcasecmp(entry, "immediate") == 0) 2983125Sjacobs papiAttributeListAddString(&list, 2993125Sjacobs PAPI_ATTR_EXCL, 3003125Sjacobs "job-hold-until", "no-hold"); 3013125Sjacobs else 3023125Sjacobs papiAttributeListAddString(&list, 3033125Sjacobs PAPI_ATTR_EXCL, 3043125Sjacobs "job-hold-until", entry); 3053125Sjacobs break; 3063125Sjacobs case 'p': /* Solaris notification */ 3073125Sjacobs papiAttributeListAddBoolean(&list, 3083125Sjacobs PAPI_ATTR_EXCL, "rfc-1179-mail", 1); 3093125Sjacobs break; 3106725Sjacobs case 'P': { /* Solaris page list */ 3116725Sjacobs char buf[BUFSIZ]; 3126725Sjacobs 3136725Sjacobs snprintf(buf, sizeof (buf), "page-ranges=%s", 3146725Sjacobs ++entry); 3156728Sjacobs papiAttributeListFromString(&list, 3166725Sjacobs PAPI_ATTR_EXCL, buf); 3176725Sjacobs } 3183125Sjacobs break; 3193125Sjacobs case 'q': { /* Solaris priority */ 3203125Sjacobs int i = atoi(optarg); 3213125Sjacobs 3226725Sjacobs i = 100 - (i * 2.5); 3233125Sjacobs if ((i < 1) || (i > 100)) 3243125Sjacobs i = 50; 3253125Sjacobs papiAttributeListAddInteger(&list, 3266725Sjacobs PAPI_ATTR_EXCL, "job-priority", i); 3273125Sjacobs } 3283125Sjacobs break; 3293125Sjacobs case 'S': /* Solaris character set */ 3303125Sjacobs papiAttributeListAddString(&list, 3313125Sjacobs PAPI_ATTR_EXCL, "lp-charset", 3323125Sjacobs ++entry); 3333125Sjacobs break; 3343125Sjacobs case 'T': /* Solaris type */ 3353125Sjacobs format = lp_type_to_mime_type(++entry); 3363125Sjacobs break; 3373125Sjacobs case 'y': /* Solaris mode */ 3383125Sjacobs papiAttributeListAddString(&list, 3393125Sjacobs PAPI_ATTR_APPEND, "lp-modes", ++entry); 3403125Sjacobs break; 3413125Sjacobs default: 3423125Sjacobs syslog(LOG_INFO|LOG_DEBUG, 3433125Sjacobs "Warning: cf message (%s) ignored", 3443125Sjacobs entry); 3453125Sjacobs break; 3463125Sjacobs } 3473125Sjacobs break; 3483125Sjacobs /* Undefined Extensions: SCO, Ultrix, AIX, ... */ 3493125Sjacobs 3503125Sjacobs default: 3513125Sjacobs syslog(LOG_INFO|LOG_DEBUG, 3523125Sjacobs "Warning: cf message (%s) ignored", entry); 3533125Sjacobs break; 3543125Sjacobs } 3553125Sjacobs 3563125Sjacobs if (format != NULL) 3573125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 3583125Sjacobs "document-format", format); 3593125Sjacobs } 3603125Sjacobs 3613125Sjacobs papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 3623125Sjacobs "copies", ++copies); 3633125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_EXCL, 3643125Sjacobs "job-sheets", "none"); 3653125Sjacobs 3663125Sjacobs return (list); 3673125Sjacobs } 3683125Sjacobs 3693125Sjacobs static papi_status_t 3706817Sjacobs submit_job(papi_service_t svc, FILE *ifp, char *printer, int rid, char *cf, 3716817Sjacobs char **files) 3723125Sjacobs { 3733125Sjacobs papi_attribute_t **list = NULL; 3743125Sjacobs papi_status_t status; 3753125Sjacobs papi_job_t job = NULL; 3763125Sjacobs char *format = ""; 3773125Sjacobs 3783125Sjacobs if ((list = parse_cf(svc, cf, files)) != NULL) { 3793125Sjacobs /* use the host as known by us, not by them */ 3803125Sjacobs char *host = remote_host_name(ifp); 3813125Sjacobs 3823125Sjacobs if (host != NULL) { 3833125Sjacobs papiAttributeListAddString(&list, PAPI_ATTR_REPLACE, 3843125Sjacobs "job-originating-host-name", host); 3853125Sjacobs free(host); 3863125Sjacobs } 3876817Sjacobs if (rid > 0) { 3886817Sjacobs papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL, 3896817Sjacobs "job-id-requested", rid); 3906817Sjacobs } 3913125Sjacobs } 3923125Sjacobs 3933125Sjacobs status = papiJobSubmit(svc, printer, list, NULL, files, &job); 3943125Sjacobs syslog(LOG_DEBUG, "submit: %s", papiStatusString(status)); 3953125Sjacobs if (status != PAPI_OK) { 3963125Sjacobs char *tmp = papiServiceGetStatusMessage(svc); 3973125Sjacobs 3983125Sjacobs syslog(LOG_DEBUG, "submit-detail: %s", tmp ? tmp : "none"); 3993125Sjacobs } 4003125Sjacobs papiJobFree(job); 4013125Sjacobs 4023125Sjacobs return (status); 4033125Sjacobs } 4043125Sjacobs 4053125Sjacobs static char * 4063125Sjacobs receive_control_file(papi_service_t svc, FILE *ifp, FILE *ofp, int size) 4073125Sjacobs { 4083125Sjacobs char *ptr, *cf_data; 4093125Sjacobs 4103125Sjacobs if ((ptr = cf_data = calloc(1, size + 1)) == NULL) { 4113125Sjacobs NACK(ofp); 4123125Sjacobs return (NULL); 4133125Sjacobs } else 4143125Sjacobs ACK(ofp); 4153125Sjacobs 4163125Sjacobs while (size > 0) { 4173125Sjacobs int rc; 4183125Sjacobs 4193125Sjacobs if (((rc = fread(ptr, 1, size, ifp)) == 0) && 4203125Sjacobs (feof(ifp) != 0)) { 4213125Sjacobs free(cf_data); 4223125Sjacobs return (NULL); 4233125Sjacobs } else { 4243125Sjacobs ptr += rc; 4253125Sjacobs size -= rc; 4263125Sjacobs } 4273125Sjacobs } 4283125Sjacobs syslog(LOG_DEBUG, "cf_data(%s)", cf_data); 4293125Sjacobs 4303125Sjacobs if (fgetc(ifp) != 0) { 4313125Sjacobs free(cf_data); 4323125Sjacobs return (NULL); 4333125Sjacobs } 4342264Sjacobs ACK(ofp); 4352264Sjacobs 4363125Sjacobs return (cf_data); 4373125Sjacobs } 4383125Sjacobs 4393125Sjacobs static char * 4403125Sjacobs receive_data_file(FILE *ifp, FILE *ofp, int size) 4413125Sjacobs { 4423125Sjacobs char file[] = "lpdXXXXXX"; 4433125Sjacobs char buf[BUFSIZ]; 4443125Sjacobs int fd; 4453125Sjacobs 4463125Sjacobs if ((fd = mkstemp(file)) < 0) { 4473125Sjacobs NACK(ofp); 4483125Sjacobs return (NULL); 4493125Sjacobs } else 4503125Sjacobs ACK(ofp); 4513125Sjacobs 4523125Sjacobs while (size > 0) { 4533125Sjacobs int rc = ((size > BUFSIZ) ? BUFSIZ : size); 4543125Sjacobs 4553125Sjacobs if (((rc = fread(buf, 1, rc, ifp)) == 0) && 4563125Sjacobs (feof(ifp) != 0)) { 4573125Sjacobs close(fd); 4583125Sjacobs unlink(file); 4593125Sjacobs return (NULL); 4603125Sjacobs } else { 4613125Sjacobs char *ptr = buf; 4623125Sjacobs 4633125Sjacobs while (rc > 0) { 4643125Sjacobs int wrc = write(fd, ptr, rc); 4653125Sjacobs 4663125Sjacobs if (wrc < 0) { 4673125Sjacobs close(fd); 4683125Sjacobs unlink(file); 4693127Sjacobs return (NULL); 4703125Sjacobs } 4713125Sjacobs 4723125Sjacobs ptr += wrc; 4733125Sjacobs size -= wrc; 4743125Sjacobs rc -= wrc; 4753125Sjacobs } 4763125Sjacobs } 4773125Sjacobs } 4783125Sjacobs close(fd); 4793125Sjacobs if (fgetc(ifp) != 0) { 4803125Sjacobs unlink(file); 4813125Sjacobs return (NULL); 4823125Sjacobs } 4833125Sjacobs ACK(ofp); 4843125Sjacobs 4853125Sjacobs return (strdup(file)); 4863125Sjacobs } 4873127Sjacobs 4883125Sjacobs static papi_status_t 4893125Sjacobs berkeley_receive_files(papi_service_t svc, FILE *ifp, FILE *ofp, char *printer) 4903125Sjacobs { 4913125Sjacobs papi_status_t status = PAPI_OK; 4923125Sjacobs char *file, **files = NULL; /* the job data files */ 4933125Sjacobs char *cf = NULL; 4946817Sjacobs int rid = 0; 4953125Sjacobs char buf[BUFSIZ]; 4963125Sjacobs 4973125Sjacobs while (fgets(buf, sizeof (buf), ifp) != NULL) { 4983125Sjacobs int size; 4993125Sjacobs 5003125Sjacobs syslog(LOG_DEBUG, "XFER CMD: (%d)%s\n", buf[0], &buf[1]); 5013125Sjacobs #ifdef DEBUG /* translate [1-3]... messages to \[1-3] to run by hand */ 5023125Sjacobs if ((buf[0] > '0') && (buf[0] < '4')) 5033125Sjacobs buf[0] -= '0'; 5043125Sjacobs #endif 5053125Sjacobs switch (buf[0]) { 5062264Sjacobs case 0x01: /* Abort */ 5073125Sjacobs cleanup(&files, &cf); 5082264Sjacobs break; 5093125Sjacobs case 0x02: { /* Receive control file */ 5106817Sjacobs if (((cf = strchr(buf, ' ')) != NULL) && 5116817Sjacobs (strlen(cf) > 4)) { 5126817Sjacobs while ((*cf != NULL) && (isdigit(*cf) == 0)) 5136817Sjacobs cf++; 5146817Sjacobs rid = atoi(cf); 5156817Sjacobs } 5163125Sjacobs cf = receive_control_file(svc, ifp, ofp, atoi(&buf[1])); 5173125Sjacobs if (cf == NULL) { 5183125Sjacobs cleanup(&files, &cf); 5193125Sjacobs return (PAPI_BAD_REQUEST); 5203125Sjacobs } else if (files != NULL) { 5216817Sjacobs status = submit_job(svc, ifp, printer, rid, cf, 5223125Sjacobs files); 5233125Sjacobs cleanup(&files, &cf); 5243125Sjacobs } 5253125Sjacobs } 5262264Sjacobs break; 5272264Sjacobs case 0x03: { /* Receive data file */ 5283125Sjacobs file = receive_data_file(ifp, ofp, atoi(&buf[1])); 5293125Sjacobs if (file == NULL) { 5303125Sjacobs cleanup(&files, &cf); 5313125Sjacobs return (PAPI_TEMPORARY_ERROR); 5323125Sjacobs } 5333125Sjacobs list_append(&files, file); 5342264Sjacobs } 5352264Sjacobs break; 5362264Sjacobs default: 5373125Sjacobs cleanup(&files, &cf); 5382264Sjacobs fatal(ofp, "protocol screwup"); 5392264Sjacobs break; 5402264Sjacobs } 5412264Sjacobs } 5422264Sjacobs 5433125Sjacobs if ((cf != NULL) && (files != NULL)) 5446817Sjacobs status = submit_job(svc, ifp, printer, rid, cf, files); 5453125Sjacobs 5463125Sjacobs cleanup(&files, &cf); 5473125Sjacobs 5483125Sjacobs return (status); 5492264Sjacobs } 5502264Sjacobs 5513125Sjacobs static papi_status_t 5522264Sjacobs berkeley_transfer_files(papi_service_t svc, FILE *ifp, FILE *ofp, 5532264Sjacobs char *printer) 5542264Sjacobs { 5552264Sjacobs papi_status_t status; 5562264Sjacobs papi_printer_t p = NULL; 5573125Sjacobs char *keys[] = { "printer-is-accepting-jobs", NULL }; 5582264Sjacobs 5592264Sjacobs status = papiPrinterQuery(svc, printer, keys, NULL, &p); 5602264Sjacobs if ((status == PAPI_OK) && (p != NULL)) { 5612264Sjacobs papi_attribute_t **attrs = papiPrinterGetAttributeList(p); 5622264Sjacobs char accepting = PAPI_FALSE; 5632264Sjacobs 5642264Sjacobs papiAttributeListGetBoolean(attrs, NULL, 5653125Sjacobs "printer-is-accepting-jobs", &accepting); 5662264Sjacobs 5673125Sjacobs if (accepting == PAPI_TRUE) { 5683125Sjacobs ACK(ofp); 5693125Sjacobs status = berkeley_receive_files(svc, ifp, ofp, printer); 5703125Sjacobs } else 5712264Sjacobs NACK(ofp); 5722264Sjacobs 5732264Sjacobs papiPrinterFree(p); 5742264Sjacobs } else 5752264Sjacobs NACK(ofp); 5763125Sjacobs 5773125Sjacobs return (status); 5782264Sjacobs } 5792264Sjacobs 5803125Sjacobs static int 5813125Sjacobs cyclical_service_check(char *svc_name) 5823125Sjacobs { 5833125Sjacobs papi_attribute_t **list; 5843125Sjacobs uri_t *uri = NULL; 5853125Sjacobs char *s = NULL; 5863125Sjacobs 5873125Sjacobs /* was there a printer? */ 5883125Sjacobs if (svc_name == NULL) 5893125Sjacobs return (0); 5903125Sjacobs 5913125Sjacobs if ((list = getprinterbyname(svc_name, NULL)) == NULL) 5923127Sjacobs return (0); /* if it doesnt' resolve, we will fail later */ 5933125Sjacobs 5943125Sjacobs papiAttributeListGetString(list, NULL, "printer-uri-supported", &s); 5953125Sjacobs if ((s == NULL) || (strcasecmp(svc_name, s) != 0)) 5963127Sjacobs return (0); /* they don't match */ 5973125Sjacobs 5983125Sjacobs /* is it in uri form? */ 5993125Sjacobs if (uri_from_string(s, &uri) < 0) 6003125Sjacobs return (0); 6013125Sjacobs 6023125Sjacobs if ((uri == NULL) || (uri->scheme == NULL) || (uri->host == NULL)) { 6033125Sjacobs uri_free(uri); 6043125Sjacobs return (0); 6053125Sjacobs } 6063125Sjacobs 6073125Sjacobs /* is it in lpd form? */ 6083125Sjacobs if (strcasecmp(uri->scheme, "lpd") != 0) { 6093125Sjacobs uri_free(uri); 6103125Sjacobs return (0); 6113125Sjacobs } 6123125Sjacobs 6133125Sjacobs /* is it the local host? */ 6147132Sps29005 if (is_localhost(uri->host) != 0) { 6153125Sjacobs uri_free(uri); 6163125Sjacobs return (0); 6173125Sjacobs } 6183125Sjacobs 6193125Sjacobs uri_free(uri); 6203125Sjacobs return (1); 6213125Sjacobs } 6223125Sjacobs 6233125Sjacobs 6242264Sjacobs /* 6252264Sjacobs * This is the entry point for this program. The program takes the 6262264Sjacobs * following options: 6272264Sjacobs * (none) 6282264Sjacobs */ 6292264Sjacobs int 6302264Sjacobs main(int ac, char *av[]) 6312264Sjacobs { 6322264Sjacobs papi_status_t status; 6332264Sjacobs papi_service_t svc = NULL; 6342264Sjacobs papi_encryption_t encryption = PAPI_ENCRYPT_NEVER; 6352264Sjacobs FILE *ifp = stdin, 6362264Sjacobs *ofp = stdout; 6372264Sjacobs int c; 6382264Sjacobs char buf[BUFSIZ], 6392264Sjacobs **args, 6403125Sjacobs *printer, 6413125Sjacobs *run_dir = "/var/run/in.lpd", 6423125Sjacobs *run_user = NULL; 6433125Sjacobs struct passwd *pw = NULL; 6442264Sjacobs 6453125Sjacobs (void) chdir("/tmp"); /* run in /tmp by default */ 6462264Sjacobs openlog("bsd-gw", LOG_PID, LOG_LPR); 6472264Sjacobs 6483125Sjacobs while ((c = getopt(ac, av, "Ed:u:")) != EOF) 6492264Sjacobs switch (c) { 6502264Sjacobs case 'E': 6512264Sjacobs encryption = PAPI_ENCRYPT_ALWAYS; 6522264Sjacobs break; 6533125Sjacobs case 'd': /* run where they tell you */ 6543125Sjacobs run_dir = optarg; 6553125Sjacobs break; 6563125Sjacobs case 'u': /* run as */ 6573125Sjacobs run_user = optarg; 6583125Sjacobs break; 6592264Sjacobs default: 6602264Sjacobs ; 6612264Sjacobs } 6622264Sjacobs 6633125Sjacobs if (run_user != NULL) /* get the requested user info */ 6643125Sjacobs pw = getpwnam(run_user); 6653127Sjacobs 6663125Sjacobs if (run_dir != NULL) { /* setup the run_dir */ 6673125Sjacobs (void) mkdir(run_dir, 0700); 6683125Sjacobs if (pw != NULL) 6693125Sjacobs (void) chown(run_dir, pw->pw_uid, pw->pw_gid); 6703125Sjacobs } 6713125Sjacobs 6723125Sjacobs if (pw != NULL) { /* run as the requested user */ 6733127Sjacobs syslog(LOG_DEBUG, "name: %s, uid: %d, gid: %d", 6743125Sjacobs pw->pw_name, pw->pw_uid, pw->pw_gid); 6753125Sjacobs initgroups(pw->pw_name, pw->pw_gid); 6763125Sjacobs setgid(pw->pw_gid); 6773125Sjacobs setuid(pw->pw_uid); 6783125Sjacobs } 6793125Sjacobs 6803125Sjacobs if (run_dir != NULL) /* move to the run_dir */ 6813125Sjacobs if (chdir(run_dir) < 0) { 6823125Sjacobs syslog(LOG_DEBUG, "failed to chdir(%s)", run_dir); 6833125Sjacobs exit(1); 6843125Sjacobs } 6853125Sjacobs 6863125Sjacobs syslog(LOG_DEBUG, "$CWD = %s", getwd(NULL)); 6873125Sjacobs 6882264Sjacobs if (fgets(buf, sizeof (buf), ifp) == NULL) { 6892264Sjacobs if (feof(ifp) == 0) 6902264Sjacobs syslog(LOG_ERR, "Error reading from connection: %s", 6912264Sjacobs strerror(errno)); 6922264Sjacobs exit(1); 6932264Sjacobs } 6942264Sjacobs 6953125Sjacobs syslog(LOG_DEBUG, "CMD: (%d)%s\n", buf[0], &buf[1]); 6963125Sjacobs 6973125Sjacobs #ifdef DEBUG /* translate [1-5]... messages to \[1-5] to run by hand */ 6983125Sjacobs if ((buf[0] > '0') && (buf[0] < '6')) 6993125Sjacobs buf[0] -= '0'; 7003125Sjacobs #endif 7013125Sjacobs 7022264Sjacobs if ((buf[0] < 1) || (buf[0] > 5)) { 7032264Sjacobs fatal(ofp, "Invalid protocol request (%d): %c%s\n", 7042264Sjacobs buf[0], buf[0], buf); 7052264Sjacobs exit(1); 7062264Sjacobs } 7072264Sjacobs 7082264Sjacobs args = strsplit(&buf[1], "\t\n "); 7092264Sjacobs printer = *args++; 7102264Sjacobs 7112264Sjacobs if (printer == NULL) { 7122264Sjacobs fatal(ofp, "Can't determine requested printer"); 7132264Sjacobs exit(1); 7142264Sjacobs } 7152264Sjacobs 7163125Sjacobs if (cyclical_service_check(printer) != 0) { 7173125Sjacobs fatal(ofp, "%s is cyclical\n", printer); 7183125Sjacobs exit(1); 7193125Sjacobs } 7203125Sjacobs 7212264Sjacobs status = papiServiceCreate(&svc, printer, NULL, NULL, NULL, 7222264Sjacobs encryption, NULL); 7232264Sjacobs if (status != PAPI_OK) { 7242264Sjacobs fatal(ofp, "Failed to contact service for %s: %s\n", printer, 7252264Sjacobs verbose_papi_message(svc, status)); 7262264Sjacobs exit(1); 7272264Sjacobs } 7282264Sjacobs 7293125Sjacobs /* 7303125Sjacobs * Trusted Solaris can't be trusting of intermediaries. Pass 7313125Sjacobs * the socket connection to the print service to retrieve the 7323125Sjacobs * sensativity label off of a multi-level port. 7333125Sjacobs */ 7343125Sjacobs (void) papiServiceSetPeer(svc, fileno(ifp)); 7352264Sjacobs 7362264Sjacobs switch (buf[0]) { 7372264Sjacobs case '\1': /* restart printer */ 7382264Sjacobs ACK(ofp); /* there is no equivalent */ 7392264Sjacobs break; 7402264Sjacobs case '\2': /* transfer job(s) */ 7413125Sjacobs status = berkeley_transfer_files(svc, ifp, ofp, printer); 7422264Sjacobs break; 7432264Sjacobs case '\3': /* show queue (short) */ 7442264Sjacobs case '\4': { /* show queue (long) */ 7452264Sjacobs int count; 7462264Sjacobs 7472264Sjacobs for (count = 0; args[count] != 0; count++); 7482264Sjacobs 7492264Sjacobs berkeley_queue_report(svc, ofp, printer, buf[0], count, args); 7502264Sjacobs } 7512264Sjacobs break; 7522264Sjacobs case '\5': { /* cancel job(s) */ 7533125Sjacobs char *user = *args++; 7543125Sjacobs char *host = remote_host_name(ifp); 7552264Sjacobs int count; 7562264Sjacobs 7573125Sjacobs if (host != NULL) { 7583125Sjacobs char buf[BUFSIZ]; 7593125Sjacobs 7603125Sjacobs snprintf(buf, sizeof (buf), "%s@%s", user, host); 7613125Sjacobs status = papiServiceSetUserName(svc, buf); 7623125Sjacobs } else 7633125Sjacobs status = papiServiceSetUserName(svc, user); 7643125Sjacobs 7652264Sjacobs for (count = 0; args[count] != 0; count++); 7662264Sjacobs 7672264Sjacobs berkeley_cancel_request(svc, ofp, printer, count, args); 7682264Sjacobs } 7692264Sjacobs break; 7702264Sjacobs default: 7712264Sjacobs fatal(ofp, "unsupported protocol request (%c), %s", 7722264Sjacobs buf[0], &buf[1]); 7732264Sjacobs } 7742264Sjacobs 7752264Sjacobs (void) fflush(ofp); 7762264Sjacobs 7772264Sjacobs syslog(LOG_DEBUG, "protocol request(%d) for %s completed: %s", 7782264Sjacobs buf[0], printer, papiStatusString(status)); 7793125Sjacobs if (status != PAPI_OK) 7803125Sjacobs syslog(LOG_DEBUG, "detail: %s", 7813125Sjacobs verbose_papi_message(svc, status)); 7822264Sjacobs 7832264Sjacobs papiServiceDestroy(svc); 7842264Sjacobs 7852264Sjacobs return (0); 7862264Sjacobs } 787