1*355b4669Sjacobs /* 2*355b4669Sjacobs * CDDL HEADER START 3*355b4669Sjacobs * 4*355b4669Sjacobs * The contents of this file are subject to the terms of the 5*355b4669Sjacobs * Common Development and Distribution License (the "License"). 6*355b4669Sjacobs * You may not use this file except in compliance with the License. 7*355b4669Sjacobs * 8*355b4669Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*355b4669Sjacobs * or http://www.opensolaris.org/os/licensing. 10*355b4669Sjacobs * See the License for the specific language governing permissions 11*355b4669Sjacobs * and limitations under the License. 12*355b4669Sjacobs * 13*355b4669Sjacobs * When distributing Covered Code, include this CDDL HEADER in each 14*355b4669Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*355b4669Sjacobs * If applicable, add the following below this CDDL HEADER, with the 16*355b4669Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying 17*355b4669Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner] 18*355b4669Sjacobs * 19*355b4669Sjacobs * CDDL HEADER END 20*355b4669Sjacobs */ 21*355b4669Sjacobs 22*355b4669Sjacobs /* 23*355b4669Sjacobs * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24*355b4669Sjacobs * Use is subject to license terms. 25*355b4669Sjacobs * 26*355b4669Sjacobs */ 27*355b4669Sjacobs 28*355b4669Sjacobs /* $Id: in.lpd.c 170 2006-05-20 05:58:49Z njacobs $ */ 29*355b4669Sjacobs 30*355b4669Sjacobs #pragma ident "%Z%%M% %I% %E% SMI" 31*355b4669Sjacobs 32*355b4669Sjacobs #include <stdio.h> 33*355b4669Sjacobs #include <stdlib.h> 34*355b4669Sjacobs #include <stdarg.h> 35*355b4669Sjacobs #include <string.h> 36*355b4669Sjacobs #include <errno.h> 37*355b4669Sjacobs #include <syslog.h> 38*355b4669Sjacobs #include <libintl.h> 39*355b4669Sjacobs 40*355b4669Sjacobs #include <papi.h> 41*355b4669Sjacobs #include "common.h" 42*355b4669Sjacobs 43*355b4669Sjacobs #define ACK(fp) { (void) fputc('\0', fp); (void) fflush(fp); } 44*355b4669Sjacobs #define NACK(fp) { (void) fputc('\1', fp); (void) fflush(fp); } 45*355b4669Sjacobs 46*355b4669Sjacobs /* 47*355b4669Sjacobs * This file contains the front-end of the BSD Print Protocol adaptor. This 48*355b4669Sjacobs * code assumes a BSD Socket interface to the networking side. 49*355b4669Sjacobs */ 50*355b4669Sjacobs 51*355b4669Sjacobs void 52*355b4669Sjacobs fatal(FILE *fp, char *fmt, ...) 53*355b4669Sjacobs { 54*355b4669Sjacobs va_list ap; 55*355b4669Sjacobs 56*355b4669Sjacobs va_start(ap, fmt); 57*355b4669Sjacobs vsyslog(LOG_DEBUG, fmt, ap); 58*355b4669Sjacobs vfprintf(fp, fmt, ap); 59*355b4669Sjacobs va_end(ap); 60*355b4669Sjacobs } 61*355b4669Sjacobs 62*355b4669Sjacobs static void 63*355b4669Sjacobs cleanup(char **files) 64*355b4669Sjacobs { 65*355b4669Sjacobs if (files != NULL) { 66*355b4669Sjacobs int i; 67*355b4669Sjacobs 68*355b4669Sjacobs for (i = 0; files[i] != NULL; i++) 69*355b4669Sjacobs unlink(files[i]); 70*355b4669Sjacobs } 71*355b4669Sjacobs } 72*355b4669Sjacobs 73*355b4669Sjacobs static void 74*355b4669Sjacobs berkeley_receive_files(papi_service_t svc, FILE *ifp, FILE *ofp) 75*355b4669Sjacobs { 76*355b4669Sjacobs char line[BUFSIZ]; 77*355b4669Sjacobs char **files = NULL; /* the job data files */ 78*355b4669Sjacobs 79*355b4669Sjacobs /* This should actually implement transfer job from RFC-1179 */ 80*355b4669Sjacobs ACK(ofp); 81*355b4669Sjacobs 82*355b4669Sjacobs while (fgets(line, sizeof (line), ifp) != NULL) { 83*355b4669Sjacobs switch (line[0]) { 84*355b4669Sjacobs case 0x01: /* Abort */ 85*355b4669Sjacobs cleanup(files); 86*355b4669Sjacobs break; 87*355b4669Sjacobs case 0x02: /* Receive control file */ 88*355b4669Sjacobs 89*355b4669Sjacobs break; 90*355b4669Sjacobs case 0x03: { /* Receive data file */ 91*355b4669Sjacobs char file[] = "lpdXXXXXX"; 92*355b4669Sjacobs int fd; 93*355b4669Sjacobs 94*355b4669Sjacobs fd = mkstemp(file); 95*355b4669Sjacobs 96*355b4669Sjacobs list_append(&files, strdup(file)); 97*355b4669Sjacobs } 98*355b4669Sjacobs break; 99*355b4669Sjacobs default: 100*355b4669Sjacobs fatal(ofp, "protocol screwup"); 101*355b4669Sjacobs cleanup(files); 102*355b4669Sjacobs break; 103*355b4669Sjacobs } 104*355b4669Sjacobs } 105*355b4669Sjacobs 106*355b4669Sjacobs cleanup(files); 107*355b4669Sjacobs } 108*355b4669Sjacobs 109*355b4669Sjacobs static void 110*355b4669Sjacobs berkeley_transfer_files(papi_service_t svc, FILE *ifp, FILE *ofp, 111*355b4669Sjacobs char *printer) 112*355b4669Sjacobs { 113*355b4669Sjacobs papi_status_t status; 114*355b4669Sjacobs papi_printer_t p = NULL; 115*355b4669Sjacobs char *keys[] = { "printer-is-accepting", NULL }; 116*355b4669Sjacobs 117*355b4669Sjacobs status = papiPrinterQuery(svc, printer, keys, NULL, &p); 118*355b4669Sjacobs if ((status == PAPI_OK) && (p != NULL)) { 119*355b4669Sjacobs papi_attribute_t **attrs = papiPrinterGetAttributeList(p); 120*355b4669Sjacobs char accepting = PAPI_FALSE; 121*355b4669Sjacobs 122*355b4669Sjacobs papiAttributeListGetBoolean(attrs, NULL, 123*355b4669Sjacobs "printer-is-accepting", &accepting); 124*355b4669Sjacobs 125*355b4669Sjacobs if (accepting == PAPI_TRUE) 126*355b4669Sjacobs berkeley_receive_files(svc, ifp, ofp); 127*355b4669Sjacobs else 128*355b4669Sjacobs NACK(ofp); 129*355b4669Sjacobs 130*355b4669Sjacobs papiPrinterFree(p); 131*355b4669Sjacobs } else 132*355b4669Sjacobs NACK(ofp); 133*355b4669Sjacobs } 134*355b4669Sjacobs 135*355b4669Sjacobs /* 136*355b4669Sjacobs * This is the entry point for this program. The program takes the 137*355b4669Sjacobs * following options: 138*355b4669Sjacobs * (none) 139*355b4669Sjacobs */ 140*355b4669Sjacobs int 141*355b4669Sjacobs main(int ac, char *av[]) 142*355b4669Sjacobs { 143*355b4669Sjacobs papi_status_t status; 144*355b4669Sjacobs papi_service_t svc = NULL; 145*355b4669Sjacobs papi_encryption_t encryption = PAPI_ENCRYPT_NEVER; 146*355b4669Sjacobs FILE *ifp = stdin, 147*355b4669Sjacobs *ofp = stdout; 148*355b4669Sjacobs int c; 149*355b4669Sjacobs char buf[BUFSIZ], 150*355b4669Sjacobs **args, 151*355b4669Sjacobs *printer; 152*355b4669Sjacobs 153*355b4669Sjacobs openlog("bsd-gw", LOG_PID, LOG_LPR); 154*355b4669Sjacobs 155*355b4669Sjacobs while ((c = getopt(ac, av, "d")) != EOF) 156*355b4669Sjacobs switch (c) { 157*355b4669Sjacobs case 'E': 158*355b4669Sjacobs encryption = PAPI_ENCRYPT_ALWAYS; 159*355b4669Sjacobs break; 160*355b4669Sjacobs case 'd': 161*355b4669Sjacobs default: 162*355b4669Sjacobs ; 163*355b4669Sjacobs } 164*355b4669Sjacobs 165*355b4669Sjacobs if (fgets(buf, sizeof (buf), ifp) == NULL) { 166*355b4669Sjacobs if (feof(ifp) == 0) 167*355b4669Sjacobs syslog(LOG_ERR, "Error reading from connection: %s", 168*355b4669Sjacobs strerror(errno)); 169*355b4669Sjacobs exit(1); 170*355b4669Sjacobs } 171*355b4669Sjacobs 172*355b4669Sjacobs if ((buf[0] < 1) || (buf[0] > 5)) { 173*355b4669Sjacobs fatal(ofp, "Invalid protocol request (%d): %c%s\n", 174*355b4669Sjacobs buf[0], buf[0], buf); 175*355b4669Sjacobs exit(1); 176*355b4669Sjacobs } 177*355b4669Sjacobs 178*355b4669Sjacobs args = strsplit(&buf[1], "\t\n "); 179*355b4669Sjacobs printer = *args++; 180*355b4669Sjacobs 181*355b4669Sjacobs if (printer == NULL) { 182*355b4669Sjacobs fatal(ofp, "Can't determine requested printer"); 183*355b4669Sjacobs exit(1); 184*355b4669Sjacobs } 185*355b4669Sjacobs 186*355b4669Sjacobs status = papiServiceCreate(&svc, printer, NULL, NULL, NULL, 187*355b4669Sjacobs encryption, NULL); 188*355b4669Sjacobs if (status != PAPI_OK) { 189*355b4669Sjacobs fatal(ofp, "Failed to contact service for %s: %s\n", printer, 190*355b4669Sjacobs verbose_papi_message(svc, status)); 191*355b4669Sjacobs exit(1); 192*355b4669Sjacobs } 193*355b4669Sjacobs 194*355b4669Sjacobs #ifdef HAVE_IS_SYSTEM_LABELED 195*355b4669Sjacobs if (is_system_labeled()) { 196*355b4669Sjacobs int fd = fileno(ifp); 197*355b4669Sjacobs 198*355b4669Sjacobs (void) papiServiceSetPeer(svc, fd); 199*355b4669Sjacobs } 200*355b4669Sjacobs #endif 201*355b4669Sjacobs 202*355b4669Sjacobs switch (buf[0]) { 203*355b4669Sjacobs case '\1': /* restart printer */ 204*355b4669Sjacobs ACK(ofp); /* there is no equivalent */ 205*355b4669Sjacobs break; 206*355b4669Sjacobs case '\2': /* transfer job(s) */ 207*355b4669Sjacobs berkeley_transfer_files(svc, ifp, ofp, printer); 208*355b4669Sjacobs break; 209*355b4669Sjacobs case '\3': /* show queue (short) */ 210*355b4669Sjacobs case '\4': { /* show queue (long) */ 211*355b4669Sjacobs int count; 212*355b4669Sjacobs 213*355b4669Sjacobs for (count = 0; args[count] != 0; count++); 214*355b4669Sjacobs 215*355b4669Sjacobs berkeley_queue_report(svc, ofp, printer, buf[0], count, args); 216*355b4669Sjacobs } 217*355b4669Sjacobs break; 218*355b4669Sjacobs case '\5': { /* cancel job(s) */ 219*355b4669Sjacobs char *requestor = *args++; 220*355b4669Sjacobs int count; 221*355b4669Sjacobs 222*355b4669Sjacobs status = papiServiceSetUserName(svc, requestor); 223*355b4669Sjacobs for (count = 0; args[count] != 0; count++); 224*355b4669Sjacobs 225*355b4669Sjacobs berkeley_cancel_request(svc, ofp, printer, count, args); 226*355b4669Sjacobs } 227*355b4669Sjacobs break; 228*355b4669Sjacobs default: 229*355b4669Sjacobs fatal(ofp, "unsupported protocol request (%c), %s", 230*355b4669Sjacobs buf[0], &buf[1]); 231*355b4669Sjacobs } 232*355b4669Sjacobs 233*355b4669Sjacobs (void) fflush(ofp); 234*355b4669Sjacobs 235*355b4669Sjacobs syslog(LOG_DEBUG, "protocol request(%d) for %s completed: %s", 236*355b4669Sjacobs buf[0], printer, papiStatusString(status)); 237*355b4669Sjacobs syslog(LOG_DEBUG, "detail: %s", verbose_papi_message(svc, status)); 238*355b4669Sjacobs 239*355b4669Sjacobs papiServiceDestroy(svc); 240*355b4669Sjacobs 241*355b4669Sjacobs return (0); 242*355b4669Sjacobs } 243