xref: /titanic_53/usr/src/cmd/print/bsd-sysv-commands/in.lpd.c (revision 355b4669e025ff377602b6fc7caaf30dbc218371)
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