in.lpd.c revision 355b4669e025ff377602b6fc7caaf30dbc218371
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * CDDL HEADER START
355b4669e025ff377602b6fc7caaf30dbc218371jacobs *
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * The contents of this file are subject to the terms of the
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * Common Development and Distribution License (the "License").
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * You may not use this file except in compliance with the License.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs *
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * or http://www.opensolaris.org/os/licensing.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * See the License for the specific language governing permissions
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * and limitations under the License.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs *
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * When distributing Covered Code, include this CDDL HEADER in each
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * If applicable, add the following below this CDDL HEADER, with the
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * fields enclosed by brackets "[]" replaced with your own identifying
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * information: Portions Copyright [yyyy] [name of copyright owner]
355b4669e025ff377602b6fc7caaf30dbc218371jacobs *
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * CDDL HEADER END
355b4669e025ff377602b6fc7caaf30dbc218371jacobs */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * Use is subject to license terms.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs *
355b4669e025ff377602b6fc7caaf30dbc218371jacobs */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/* $Id: in.lpd.c 170 2006-05-20 05:58:49Z njacobs $ */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#pragma ident "%Z%%M% %I% %E% SMI"
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#include <stdio.h>
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#include <stdlib.h>
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#include <stdarg.h>
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#include <string.h>
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#include <errno.h>
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#include <syslog.h>
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#include <libintl.h>
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#include <papi.h>
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#include "common.h"
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#define ACK(fp) { (void) fputc('\0', fp); (void) fflush(fp); }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#define NACK(fp) { (void) fputc('\1', fp); (void) fflush(fp); }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * This file contains the front-end of the BSD Print Protocol adaptor. This
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * code assumes a BSD Socket interface to the networking side.
355b4669e025ff377602b6fc7caaf30dbc218371jacobs */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobsvoid
355b4669e025ff377602b6fc7caaf30dbc218371jacobsfatal(FILE *fp, char *fmt, ...)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs{
355b4669e025ff377602b6fc7caaf30dbc218371jacobs va_list ap;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs va_start(ap, fmt);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs vsyslog(LOG_DEBUG, fmt, ap);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs vfprintf(fp, fmt, ap);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs va_end(ap);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs}
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic void
355b4669e025ff377602b6fc7caaf30dbc218371jacobscleanup(char **files)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs{
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if (files != NULL) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs int i;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs for (i = 0; files[i] != NULL; i++)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs unlink(files[i]);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs}
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic void
355b4669e025ff377602b6fc7caaf30dbc218371jacobsberkeley_receive_files(papi_service_t svc, FILE *ifp, FILE *ofp)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs{
355b4669e025ff377602b6fc7caaf30dbc218371jacobs char line[BUFSIZ];
355b4669e025ff377602b6fc7caaf30dbc218371jacobs char **files = NULL; /* the job data files */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs /* This should actually implement transfer job from RFC-1179 */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs ACK(ofp);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs while (fgets(line, sizeof (line), ifp) != NULL) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs switch (line[0]) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case 0x01: /* Abort */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs cleanup(files);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs break;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case 0x02: /* Receive control file */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs break;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case 0x03: { /* Receive data file */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs char file[] = "lpdXXXXXX";
355b4669e025ff377602b6fc7caaf30dbc218371jacobs int fd;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fd = mkstemp(file);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs list_append(&files, strdup(file));
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs break;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs default:
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fatal(ofp, "protocol screwup");
355b4669e025ff377602b6fc7caaf30dbc218371jacobs cleanup(files);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs break;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs cleanup(files);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs}
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobsstatic void
355b4669e025ff377602b6fc7caaf30dbc218371jacobsberkeley_transfer_files(papi_service_t svc, FILE *ifp, FILE *ofp,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs char *printer)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs{
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papi_status_t status;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papi_printer_t p = NULL;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs char *keys[] = { "printer-is-accepting", NULL };
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs status = papiPrinterQuery(svc, printer, keys, NULL, &p);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if ((status == PAPI_OK) && (p != NULL)) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papi_attribute_t **attrs = papiPrinterGetAttributeList(p);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs char accepting = PAPI_FALSE;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papiAttributeListGetBoolean(attrs, NULL,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs "printer-is-accepting", &accepting);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if (accepting == PAPI_TRUE)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs berkeley_receive_files(svc, ifp, ofp);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs else
355b4669e025ff377602b6fc7caaf30dbc218371jacobs NACK(ofp);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papiPrinterFree(p);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs } else
355b4669e025ff377602b6fc7caaf30dbc218371jacobs NACK(ofp);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs}
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs/*
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * This is the entry point for this program. The program takes the
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * following options:
355b4669e025ff377602b6fc7caaf30dbc218371jacobs * (none)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs */
355b4669e025ff377602b6fc7caaf30dbc218371jacobsint
355b4669e025ff377602b6fc7caaf30dbc218371jacobsmain(int ac, char *av[])
355b4669e025ff377602b6fc7caaf30dbc218371jacobs{
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papi_status_t status;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papi_service_t svc = NULL;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papi_encryption_t encryption = PAPI_ENCRYPT_NEVER;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs FILE *ifp = stdin,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs *ofp = stdout;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs int c;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs char buf[BUFSIZ],
355b4669e025ff377602b6fc7caaf30dbc218371jacobs **args,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs *printer;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs openlog("bsd-gw", LOG_PID, LOG_LPR);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs while ((c = getopt(ac, av, "d")) != EOF)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs switch (c) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case 'E':
355b4669e025ff377602b6fc7caaf30dbc218371jacobs encryption = PAPI_ENCRYPT_ALWAYS;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs break;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case 'd':
355b4669e025ff377602b6fc7caaf30dbc218371jacobs default:
355b4669e025ff377602b6fc7caaf30dbc218371jacobs ;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if (fgets(buf, sizeof (buf), ifp) == NULL) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if (feof(ifp) == 0)
355b4669e025ff377602b6fc7caaf30dbc218371jacobs syslog(LOG_ERR, "Error reading from connection: %s",
355b4669e025ff377602b6fc7caaf30dbc218371jacobs strerror(errno));
355b4669e025ff377602b6fc7caaf30dbc218371jacobs exit(1);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if ((buf[0] < 1) || (buf[0] > 5)) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fatal(ofp, "Invalid protocol request (%d): %c%s\n",
355b4669e025ff377602b6fc7caaf30dbc218371jacobs buf[0], buf[0], buf);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs exit(1);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs args = strsplit(&buf[1], "\t\n ");
355b4669e025ff377602b6fc7caaf30dbc218371jacobs printer = *args++;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if (printer == NULL) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fatal(ofp, "Can't determine requested printer");
355b4669e025ff377602b6fc7caaf30dbc218371jacobs exit(1);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs status = papiServiceCreate(&svc, printer, NULL, NULL, NULL,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs encryption, NULL);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if (status != PAPI_OK) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fatal(ofp, "Failed to contact service for %s: %s\n", printer,
355b4669e025ff377602b6fc7caaf30dbc218371jacobs verbose_papi_message(svc, status));
355b4669e025ff377602b6fc7caaf30dbc218371jacobs exit(1);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#ifdef HAVE_IS_SYSTEM_LABELED
355b4669e025ff377602b6fc7caaf30dbc218371jacobs if (is_system_labeled()) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs int fd = fileno(ifp);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs (void) papiServiceSetPeer(svc, fd);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs#endif
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs switch (buf[0]) {
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case '\1': /* restart printer */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs ACK(ofp); /* there is no equivalent */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs break;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case '\2': /* transfer job(s) */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs berkeley_transfer_files(svc, ifp, ofp, printer);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs break;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case '\3': /* show queue (short) */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case '\4': { /* show queue (long) */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs int count;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs for (count = 0; args[count] != 0; count++);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs berkeley_queue_report(svc, ofp, printer, buf[0], count, args);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs break;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs case '\5': { /* cancel job(s) */
355b4669e025ff377602b6fc7caaf30dbc218371jacobs char *requestor = *args++;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs int count;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs status = papiServiceSetUserName(svc, requestor);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs for (count = 0; args[count] != 0; count++);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs berkeley_cancel_request(svc, ofp, printer, count, args);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs break;
355b4669e025ff377602b6fc7caaf30dbc218371jacobs default:
355b4669e025ff377602b6fc7caaf30dbc218371jacobs fatal(ofp, "unsupported protocol request (%c), %s",
355b4669e025ff377602b6fc7caaf30dbc218371jacobs buf[0], &buf[1]);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs }
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs (void) fflush(ofp);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs syslog(LOG_DEBUG, "protocol request(%d) for %s completed: %s",
355b4669e025ff377602b6fc7caaf30dbc218371jacobs buf[0], printer, papiStatusString(status));
355b4669e025ff377602b6fc7caaf30dbc218371jacobs syslog(LOG_DEBUG, "detail: %s", verbose_papi_message(svc, status));
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs papiServiceDestroy(svc);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs
355b4669e025ff377602b6fc7caaf30dbc218371jacobs return (0);
355b4669e025ff377602b6fc7caaf30dbc218371jacobs}