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 2006 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 <stdarg.h> 35 #include <string.h> 36 #include <errno.h> 37 #include <syslog.h> 38 #include <libintl.h> 39 40 #include <papi.h> 41 #include "common.h" 42 43 #define ACK(fp) { (void) fputc('\0', fp); (void) fflush(fp); } 44 #define NACK(fp) { (void) fputc('\1', fp); (void) fflush(fp); } 45 46 /* 47 * This file contains the front-end of the BSD Print Protocol adaptor. This 48 * code assumes a BSD Socket interface to the networking side. 49 */ 50 51 void 52 fatal(FILE *fp, char *fmt, ...) 53 { 54 va_list ap; 55 56 va_start(ap, fmt); 57 vsyslog(LOG_DEBUG, fmt, ap); 58 vfprintf(fp, fmt, ap); 59 va_end(ap); 60 } 61 62 static void 63 cleanup(char **files) 64 { 65 if (files != NULL) { 66 int i; 67 68 for (i = 0; files[i] != NULL; i++) 69 unlink(files[i]); 70 } 71 } 72 73 static void 74 berkeley_receive_files(papi_service_t svc, FILE *ifp, FILE *ofp) 75 { 76 char line[BUFSIZ]; 77 char **files = NULL; /* the job data files */ 78 79 /* This should actually implement transfer job from RFC-1179 */ 80 ACK(ofp); 81 82 while (fgets(line, sizeof (line), ifp) != NULL) { 83 switch (line[0]) { 84 case 0x01: /* Abort */ 85 cleanup(files); 86 break; 87 case 0x02: /* Receive control file */ 88 89 break; 90 case 0x03: { /* Receive data file */ 91 char file[] = "lpdXXXXXX"; 92 int fd; 93 94 fd = mkstemp(file); 95 96 list_append(&files, strdup(file)); 97 } 98 break; 99 default: 100 fatal(ofp, "protocol screwup"); 101 cleanup(files); 102 break; 103 } 104 } 105 106 cleanup(files); 107 } 108 109 static void 110 berkeley_transfer_files(papi_service_t svc, FILE *ifp, FILE *ofp, 111 char *printer) 112 { 113 papi_status_t status; 114 papi_printer_t p = NULL; 115 char *keys[] = { "printer-is-accepting", NULL }; 116 117 status = papiPrinterQuery(svc, printer, keys, NULL, &p); 118 if ((status == PAPI_OK) && (p != NULL)) { 119 papi_attribute_t **attrs = papiPrinterGetAttributeList(p); 120 char accepting = PAPI_FALSE; 121 122 papiAttributeListGetBoolean(attrs, NULL, 123 "printer-is-accepting", &accepting); 124 125 if (accepting == PAPI_TRUE) 126 berkeley_receive_files(svc, ifp, ofp); 127 else 128 NACK(ofp); 129 130 papiPrinterFree(p); 131 } else 132 NACK(ofp); 133 } 134 135 /* 136 * This is the entry point for this program. The program takes the 137 * following options: 138 * (none) 139 */ 140 int 141 main(int ac, char *av[]) 142 { 143 papi_status_t status; 144 papi_service_t svc = NULL; 145 papi_encryption_t encryption = PAPI_ENCRYPT_NEVER; 146 FILE *ifp = stdin, 147 *ofp = stdout; 148 int c; 149 char buf[BUFSIZ], 150 **args, 151 *printer; 152 153 openlog("bsd-gw", LOG_PID, LOG_LPR); 154 155 while ((c = getopt(ac, av, "d")) != EOF) 156 switch (c) { 157 case 'E': 158 encryption = PAPI_ENCRYPT_ALWAYS; 159 break; 160 case 'd': 161 default: 162 ; 163 } 164 165 if (fgets(buf, sizeof (buf), ifp) == NULL) { 166 if (feof(ifp) == 0) 167 syslog(LOG_ERR, "Error reading from connection: %s", 168 strerror(errno)); 169 exit(1); 170 } 171 172 if ((buf[0] < 1) || (buf[0] > 5)) { 173 fatal(ofp, "Invalid protocol request (%d): %c%s\n", 174 buf[0], buf[0], buf); 175 exit(1); 176 } 177 178 args = strsplit(&buf[1], "\t\n "); 179 printer = *args++; 180 181 if (printer == NULL) { 182 fatal(ofp, "Can't determine requested printer"); 183 exit(1); 184 } 185 186 status = papiServiceCreate(&svc, printer, NULL, NULL, NULL, 187 encryption, NULL); 188 if (status != PAPI_OK) { 189 fatal(ofp, "Failed to contact service for %s: %s\n", printer, 190 verbose_papi_message(svc, status)); 191 exit(1); 192 } 193 194 #ifdef HAVE_IS_SYSTEM_LABELED 195 if (is_system_labeled()) { 196 int fd = fileno(ifp); 197 198 (void) papiServiceSetPeer(svc, fd); 199 } 200 #endif 201 202 switch (buf[0]) { 203 case '\1': /* restart printer */ 204 ACK(ofp); /* there is no equivalent */ 205 break; 206 case '\2': /* transfer job(s) */ 207 berkeley_transfer_files(svc, ifp, ofp, printer); 208 break; 209 case '\3': /* show queue (short) */ 210 case '\4': { /* show queue (long) */ 211 int count; 212 213 for (count = 0; args[count] != 0; count++); 214 215 berkeley_queue_report(svc, ofp, printer, buf[0], count, args); 216 } 217 break; 218 case '\5': { /* cancel job(s) */ 219 char *requestor = *args++; 220 int count; 221 222 status = papiServiceSetUserName(svc, requestor); 223 for (count = 0; args[count] != 0; count++); 224 225 berkeley_cancel_request(svc, ofp, printer, count, args); 226 } 227 break; 228 default: 229 fatal(ofp, "unsupported protocol request (%c), %s", 230 buf[0], &buf[1]); 231 } 232 233 (void) fflush(ofp); 234 235 syslog(LOG_DEBUG, "protocol request(%d) for %s completed: %s", 236 buf[0], printer, papiStatusString(status)); 237 syslog(LOG_DEBUG, "detail: %s", verbose_papi_message(svc, status)); 238 239 papiServiceDestroy(svc); 240 241 return (0); 242 } 243