xref: /titanic_53/usr/src/cmd/print/bsd-sysv-commands/in.lpd.c (revision 0a44ef6d9afbfe052a7e975f55ea0d2954b62a82)
1355b4669Sjacobs /*
2355b4669Sjacobs  * CDDL HEADER START
3355b4669Sjacobs  *
4355b4669Sjacobs  * The contents of this file are subject to the terms of the
5355b4669Sjacobs  * Common Development and Distribution License (the "License").
6355b4669Sjacobs  * You may not use this file except in compliance with the License.
7355b4669Sjacobs  *
8355b4669Sjacobs  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9355b4669Sjacobs  * or http://www.opensolaris.org/os/licensing.
10355b4669Sjacobs  * See the License for the specific language governing permissions
11355b4669Sjacobs  * and limitations under the License.
12355b4669Sjacobs  *
13355b4669Sjacobs  * When distributing Covered Code, include this CDDL HEADER in each
14355b4669Sjacobs  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15355b4669Sjacobs  * If applicable, add the following below this CDDL HEADER, with the
16355b4669Sjacobs  * fields enclosed by brackets "[]" replaced with your own identifying
17355b4669Sjacobs  * information: Portions Copyright [yyyy] [name of copyright owner]
18355b4669Sjacobs  *
19355b4669Sjacobs  * CDDL HEADER END
20355b4669Sjacobs  */
21355b4669Sjacobs 
22355b4669Sjacobs /*
23355b4669Sjacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24355b4669Sjacobs  * Use is subject to license terms.
25355b4669Sjacobs  *
26355b4669Sjacobs  */
27355b4669Sjacobs 
28355b4669Sjacobs /* $Id: in.lpd.c 170 2006-05-20 05:58:49Z njacobs $ */
29355b4669Sjacobs 
30355b4669Sjacobs #pragma ident	"%Z%%M%	%I%	%E% SMI"
31355b4669Sjacobs 
32355b4669Sjacobs #include <stdio.h>
33355b4669Sjacobs #include <stdlib.h>
34*0a44ef6dSjacobs #include <unistd.h>
35*0a44ef6dSjacobs #include <fcntl.h>
36355b4669Sjacobs #include <stdarg.h>
37355b4669Sjacobs #include <string.h>
38355b4669Sjacobs #include <errno.h>
39355b4669Sjacobs #include <syslog.h>
40355b4669Sjacobs #include <libintl.h>
41*0a44ef6dSjacobs #include <pwd.h>
42*0a44ef6dSjacobs #include <grp.h>
43*0a44ef6dSjacobs #include <sys/types.h>
44*0a44ef6dSjacobs #include <sys/stat.h>
45*0a44ef6dSjacobs #include <sys/socket.h>
46*0a44ef6dSjacobs #include <netinet/in.h>
47*0a44ef6dSjacobs #include <arpa/inet.h>
48*0a44ef6dSjacobs #include <netdb.h>
49*0a44ef6dSjacobs #include <sys/systeminfo.h>
50355b4669Sjacobs 
51355b4669Sjacobs #include <papi.h>
52*0a44ef6dSjacobs #include <uri.h>
53355b4669Sjacobs #include "common.h"
54355b4669Sjacobs 
55355b4669Sjacobs #define	ACK(fp)		{ (void) fputc('\0', fp); (void) fflush(fp); }
56355b4669Sjacobs #define	NACK(fp)	{ (void) fputc('\1', fp); (void) fflush(fp); }
57355b4669Sjacobs 
58355b4669Sjacobs /*
59355b4669Sjacobs  * This file contains the front-end of the BSD Print Protocol adaptor.  This
60355b4669Sjacobs  * code assumes a BSD Socket interface to the networking side.
61355b4669Sjacobs  */
62355b4669Sjacobs 
63*0a44ef6dSjacobs static char *
64*0a44ef6dSjacobs remote_host_name(FILE *fp)
65*0a44ef6dSjacobs {
66*0a44ef6dSjacobs 	struct hostent *hp;
67*0a44ef6dSjacobs 	struct sockaddr_in6 peer;
68*0a44ef6dSjacobs 	socklen_t peer_len = sizeof (peer);
69*0a44ef6dSjacobs 	int fd = fileno(fp);
70*0a44ef6dSjacobs 	int error_num;
71*0a44ef6dSjacobs 	char myname[MAXHOSTNAMELEN], tmp_buf[INET6_ADDRSTRLEN];
72*0a44ef6dSjacobs 	char *hostname;
73*0a44ef6dSjacobs 
74*0a44ef6dSjacobs 	/* who is our peer ? */
75*0a44ef6dSjacobs 	if (getpeername(fd, (struct sockaddr *)&peer, &peer_len) < 0) {
76*0a44ef6dSjacobs 		if ((errno != ENOTSOCK) && (errno != EINVAL))
77*0a44ef6dSjacobs 			return (NULL);
78*0a44ef6dSjacobs 		else
79*0a44ef6dSjacobs 			return (strdup("localhost"));
80*0a44ef6dSjacobs 	}
81*0a44ef6dSjacobs 
82*0a44ef6dSjacobs 	/* get their name or return a string containing their address */
83*0a44ef6dSjacobs 	if ((hp = getipnodebyaddr((const char *)&peer.sin6_addr,
84*0a44ef6dSjacobs 				sizeof (struct in6_addr), AF_INET6,
85*0a44ef6dSjacobs 				&error_num)) == NULL) {
86*0a44ef6dSjacobs 		return (strdup(inet_ntop(peer.sin6_family,
87*0a44ef6dSjacobs 			&peer.sin6_addr, tmp_buf, sizeof (tmp_buf))));
88*0a44ef6dSjacobs 	}
89*0a44ef6dSjacobs 
90*0a44ef6dSjacobs 	/* is it "localhost" ? */
91*0a44ef6dSjacobs 	if (strcasecmp(hp->h_name, "localhost") == 0)
92*0a44ef6dSjacobs 		return (strdup("localhost"));
93*0a44ef6dSjacobs 
94*0a44ef6dSjacobs 	/* duplicate the name because gethostbyXXXX() is not reentrant */
95*0a44ef6dSjacobs 	hostname = strdup(hp->h_name);
96*0a44ef6dSjacobs 	(void) sysinfo(SI_HOSTNAME, myname, sizeof (myname));
97*0a44ef6dSjacobs 
98*0a44ef6dSjacobs 	/* is it from one of my addresses ? */
99*0a44ef6dSjacobs 	if ((hp = getipnodebyname(myname, AF_INET6, AI_ALL|AI_V4MAPPED,
100*0a44ef6dSjacobs 	    &error_num)) != NULL) {
101*0a44ef6dSjacobs 		struct in6_addr **tmp = (struct in6_addr **)hp->h_addr_list;
102*0a44ef6dSjacobs 		int i = 0;
103*0a44ef6dSjacobs 
104*0a44ef6dSjacobs 		while (tmp[i] != NULL) {
105*0a44ef6dSjacobs 			if (memcmp(tmp[i++], &peer.sin6_addr, hp->h_length)
106*0a44ef6dSjacobs 			    == 0) {
107*0a44ef6dSjacobs 				free(hostname);
108*0a44ef6dSjacobs 				return (strdup("localhost"));
109*0a44ef6dSjacobs 			}
110*0a44ef6dSjacobs 		}
111*0a44ef6dSjacobs 	}
112*0a44ef6dSjacobs 
113*0a44ef6dSjacobs 	/* It must be someone else */
114*0a44ef6dSjacobs 	return (hostname);
115*0a44ef6dSjacobs }
116*0a44ef6dSjacobs 
117*0a44ef6dSjacobs static void
118355b4669Sjacobs fatal(FILE *fp, char *fmt, ...)
119355b4669Sjacobs {
120355b4669Sjacobs 	va_list ap;
121355b4669Sjacobs 
122355b4669Sjacobs 	va_start(ap, fmt);
123355b4669Sjacobs 	vsyslog(LOG_DEBUG, fmt, ap);
124355b4669Sjacobs 	vfprintf(fp, fmt, ap);
125355b4669Sjacobs 	va_end(ap);
126*0a44ef6dSjacobs 	exit(1);
127355b4669Sjacobs }
128355b4669Sjacobs 
129355b4669Sjacobs static void
130*0a44ef6dSjacobs cleanup(char ***files, char **cf)
131355b4669Sjacobs {
132*0a44ef6dSjacobs 	if (*files != NULL) {
133355b4669Sjacobs 		int i;
134355b4669Sjacobs 
135*0a44ef6dSjacobs 		for (i = 0; (*files)[i] != NULL; i++) {
136*0a44ef6dSjacobs 			(void) unlink((*files)[i]);
137*0a44ef6dSjacobs 			free((*files)[i]);
138*0a44ef6dSjacobs 		}
139*0a44ef6dSjacobs 		free(*files);
140*0a44ef6dSjacobs 		*files = NULL;
141*0a44ef6dSjacobs 	}
142*0a44ef6dSjacobs 
143*0a44ef6dSjacobs 	if (*cf != NULL) {
144*0a44ef6dSjacobs 		free(*cf);
145*0a44ef6dSjacobs 		*cf = NULL;
146355b4669Sjacobs 	}
147355b4669Sjacobs }
148355b4669Sjacobs 
149*0a44ef6dSjacobs static papi_attribute_t **
150*0a44ef6dSjacobs parse_cf(papi_service_t svc, char *cf, char **files)
151355b4669Sjacobs {
152*0a44ef6dSjacobs 	papi_attribute_t **list = NULL;
153*0a44ef6dSjacobs 	char	previous = NULL,
154*0a44ef6dSjacobs 		*entry,
155*0a44ef6dSjacobs 		*s,
156*0a44ef6dSjacobs 		text[BUFSIZ];
157*0a44ef6dSjacobs 	int	count = 0,
158*0a44ef6dSjacobs 		copies_set = 0,
159*0a44ef6dSjacobs 		copies = 0;
160355b4669Sjacobs 
161*0a44ef6dSjacobs 	for (entry = strtok(cf, "\n"); entry != NULL;
162*0a44ef6dSjacobs 	    entry = strtok(NULL, "\n")) {
163*0a44ef6dSjacobs 		char *format = NULL;
164*0a44ef6dSjacobs 
165*0a44ef6dSjacobs 		/* count the copies */
166*0a44ef6dSjacobs 		if ((entry[0] >= 'a') && (entry[0] <= 'z') &&
167*0a44ef6dSjacobs 		    (copies_set == 0) && (previous == entry[0]))
168*0a44ef6dSjacobs 			copies++;
169*0a44ef6dSjacobs 		else if ((previous >= 'a') && (previous <= 'z'))
170*0a44ef6dSjacobs 			copies_set = 1;
171*0a44ef6dSjacobs 		previous = entry[0];
172*0a44ef6dSjacobs 
173*0a44ef6dSjacobs 		/* process the control message */
174*0a44ef6dSjacobs 		switch (entry[0]) {
175*0a44ef6dSjacobs 		/* RFC-1179 options */
176*0a44ef6dSjacobs 		case 'J':	/* RFC-1179 Banner Job Name */
177*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
178*0a44ef6dSjacobs 					"job-name", ++entry);
179*0a44ef6dSjacobs 			break;
180*0a44ef6dSjacobs 		case 'C':	/* RFC-1179 Banner Class Name */
181*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
182*0a44ef6dSjacobs 					"rfc-1179-class", ++entry);
183*0a44ef6dSjacobs 			break;
184*0a44ef6dSjacobs 		case 'L':	/* RFC-1179 Banner toggle  */
185*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
186*0a44ef6dSjacobs 					"job-sheets", "standard");
187*0a44ef6dSjacobs 			break;
188*0a44ef6dSjacobs 		case 'T':	/* RFC-1179 Title (pr)  */
189*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
190*0a44ef6dSjacobs 					"pr-title", ++entry);
191*0a44ef6dSjacobs 			break;
192*0a44ef6dSjacobs 		case 'H':	/* RFC-1179 Host */
193*0a44ef6dSjacobs 			/*
194*0a44ef6dSjacobs 			 * use the host as known by us, not by them
195*0a44ef6dSjacobs 			 *
196*0a44ef6dSjacobs 			 * papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
197*0a44ef6dSjacobs 			 *		"job-originating-host-name", ++entry);
198*0a44ef6dSjacobs 			 */
199*0a44ef6dSjacobs 			break;
200*0a44ef6dSjacobs 		case 'P':	/* RFC-1179 User */
201*0a44ef6dSjacobs 			++entry;
202*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
203*0a44ef6dSjacobs 					"requesting-user-name", entry);
204*0a44ef6dSjacobs 			papiServiceSetUserName(svc, entry);
205*0a44ef6dSjacobs 			break;
206*0a44ef6dSjacobs 		case 'M':	/* RFC-1179 Mail to User */
207*0a44ef6dSjacobs 			papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL,
208*0a44ef6dSjacobs 				"rfc-1179-mail", 1);
209*0a44ef6dSjacobs 			break;
210*0a44ef6dSjacobs 		case 'W':	/* RFC-1179 Width (pr) */
211*0a44ef6dSjacobs 			papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL,
212*0a44ef6dSjacobs 					"pr-width", atoi(++entry));
213*0a44ef6dSjacobs 			break;
214*0a44ef6dSjacobs 		case 'I':	/* RFC-1179 Indent (pr) */
215*0a44ef6dSjacobs 			papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL,
216*0a44ef6dSjacobs 					"pr-indent", atoi(++entry));
217*0a44ef6dSjacobs 			break;
218*0a44ef6dSjacobs 		case 'N':	/* RFC-1179 Filename */
219*0a44ef6dSjacobs 			/* could have HPUX extension embedded */
220*0a44ef6dSjacobs 			if (entry[1] != ' ') {	/* real pathname */
221*0a44ef6dSjacobs #ifdef DEBUG
222*0a44ef6dSjacobs 				papiAttributeListAddString(&list,
223*0a44ef6dSjacobs 						PAPI_ATTR_EXCL,
224*0a44ef6dSjacobs 						"flist", ++entry);
225*0a44ef6dSjacobs #endif
226*0a44ef6dSjacobs 			} else if (entry[2] == 'O') /* HPUX lp -o options */
227*0a44ef6dSjacobs 				papiAttributeListFromString(&list,
228*0a44ef6dSjacobs 						PAPI_ATTR_APPEND, ++entry);
229*0a44ef6dSjacobs 			break;
230*0a44ef6dSjacobs 		case 'U':	/* RFC-1179 Unlink */
231*0a44ef6dSjacobs 			break;	/* ignored */
232*0a44ef6dSjacobs 		case '1':	/* RFC-1179 TROFF Font R */
233*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
234*0a44ef6dSjacobs 				"rfc-1179-font-r", ++entry);
235*0a44ef6dSjacobs 			break;
236*0a44ef6dSjacobs 		case '2':	/* RFC-1179 TROFF Font I */
237*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
238*0a44ef6dSjacobs 				"rfc-1179-font-i", ++entry);
239*0a44ef6dSjacobs 			break;
240*0a44ef6dSjacobs 		case '3':	/* RFC-1179 TROFF Font B */
241*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
242*0a44ef6dSjacobs 				"rfc-1179-font-b", ++entry);
243*0a44ef6dSjacobs 			break;
244*0a44ef6dSjacobs 		case '4':	/* RFC-1179 TROFF Font S */
245*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
246*0a44ef6dSjacobs 				"rfc-1179-font-s", ++entry);
247*0a44ef6dSjacobs 			break;
248*0a44ef6dSjacobs 		case 'f':	/* RFC-1179 ASCII file (print) */
249*0a44ef6dSjacobs 			format = "text/plain";
250*0a44ef6dSjacobs 			if (is_postscript(files[0]) == 1)
251*0a44ef6dSjacobs 				format = "application/postscript";
252*0a44ef6dSjacobs 			break;
253*0a44ef6dSjacobs 		case 'l':	/* RFC-1179 CATV file (print) */
254*0a44ef6dSjacobs 			format = "application/octet-stream";
255*0a44ef6dSjacobs 			if (is_postscript(files[0]) == 1)
256*0a44ef6dSjacobs 				format = "application/postscript";
257*0a44ef6dSjacobs 			break;
258*0a44ef6dSjacobs 		case 'o':	/* RFC-1179 Postscript file (print) */
259*0a44ef6dSjacobs 			format = "application/postscript";
260*0a44ef6dSjacobs 			break;
261*0a44ef6dSjacobs 		case 'p':	/* RFC-1179 PR file (print) */
262*0a44ef6dSjacobs 			format = "application/x-pr";
263*0a44ef6dSjacobs 			papiAttributeListAddBoolean(&list, PAPI_ATTR_EXCL,
264*0a44ef6dSjacobs 					"pr-filter", 1);
265*0a44ef6dSjacobs 			break;
266*0a44ef6dSjacobs 		case 't':	/* RFC-1179 TROFF file (print) */
267*0a44ef6dSjacobs 			format = "application/x-troff";
268*0a44ef6dSjacobs 			break;
269*0a44ef6dSjacobs 		case 'n':	/* RFC-1179 DITROFF file (print) */
270*0a44ef6dSjacobs 			format = "application/x-ditroff";
271*0a44ef6dSjacobs 			break;
272*0a44ef6dSjacobs 		case 'd':	/* RFC-1179 DVI file (print) */
273*0a44ef6dSjacobs 			format = "application/x-dvi";
274*0a44ef6dSjacobs 			break;
275*0a44ef6dSjacobs 		case 'g':	/* RFC-1179 GRAPH file (print) */
276*0a44ef6dSjacobs 			format = "application/x-plot";
277*0a44ef6dSjacobs 			break;
278*0a44ef6dSjacobs 		case 'c':	/* RFC-1179 CIF file (print) */
279*0a44ef6dSjacobs 			format = "application/x-cif";
280*0a44ef6dSjacobs 			break;
281*0a44ef6dSjacobs 		case 'v':	/* RFC-1179 RASTER file (print) */
282*0a44ef6dSjacobs 			format = "application/x-raster";
283*0a44ef6dSjacobs 			break;
284*0a44ef6dSjacobs 		case 'r':	/* RFC-1179 FORTRAN file (print) */
285*0a44ef6dSjacobs 			format = "application/x-fortran";
286*0a44ef6dSjacobs 			break;
287*0a44ef6dSjacobs 		/* Sun Solaris Extensions */
288*0a44ef6dSjacobs 		case 'O':
289*0a44ef6dSjacobs 			++entry;
290*0a44ef6dSjacobs 			do {
291*0a44ef6dSjacobs 				if (*entry != '"')
292*0a44ef6dSjacobs 					text[count++] = *entry;
293*0a44ef6dSjacobs 			} while (*entry++);
294*0a44ef6dSjacobs 			papiAttributeListFromString(&list, PAPI_ATTR_APPEND,
295*0a44ef6dSjacobs 				text);
296*0a44ef6dSjacobs 			break;
297*0a44ef6dSjacobs 		case '5':
298*0a44ef6dSjacobs 			++entry;
299*0a44ef6dSjacobs 			switch (entry[0]) {
300*0a44ef6dSjacobs 			case 'f':	/* Solaris form */
301*0a44ef6dSjacobs 				papiAttributeListAddString(&list,
302*0a44ef6dSjacobs 						PAPI_ATTR_EXCL,
303*0a44ef6dSjacobs 						"form", ++entry);
304*0a44ef6dSjacobs 				break;
305*0a44ef6dSjacobs 			case 'H':	/* Solaris handling */
306*0a44ef6dSjacobs 				++entry;
307*0a44ef6dSjacobs 				if (strcasecmp(entry, "hold") == 0)
308*0a44ef6dSjacobs 					papiAttributeListAddString(&list,
309*0a44ef6dSjacobs 						PAPI_ATTR_EXCL,
310*0a44ef6dSjacobs 						"job-hold-until", "indefinite");
311*0a44ef6dSjacobs 				else if (strcasecmp(entry, "release") == 0)
312*0a44ef6dSjacobs 					papiAttributeListAddString(&list,
313*0a44ef6dSjacobs 						PAPI_ATTR_EXCL,
314*0a44ef6dSjacobs 						"job-hold-until", "no-hold");
315*0a44ef6dSjacobs 				else if (strcasecmp(entry, "immediate") == 0)
316*0a44ef6dSjacobs 					papiAttributeListAddInteger(&list,
317*0a44ef6dSjacobs 						PAPI_ATTR_EXCL,
318*0a44ef6dSjacobs 						"job-priority", 100);
319*0a44ef6dSjacobs 				else
320*0a44ef6dSjacobs 					papiAttributeListAddString(&list,
321*0a44ef6dSjacobs 						PAPI_ATTR_EXCL,
322*0a44ef6dSjacobs 						"job-hold-until", entry);
323*0a44ef6dSjacobs 				break;
324*0a44ef6dSjacobs 			case 'p':	/* Solaris notification */
325*0a44ef6dSjacobs 				papiAttributeListAddBoolean(&list,
326*0a44ef6dSjacobs 					PAPI_ATTR_EXCL, "rfc-1179-mail", 1);
327*0a44ef6dSjacobs 				break;
328*0a44ef6dSjacobs 			case 'P':	/* Solaris page list */
329*0a44ef6dSjacobs 				papiAttributeListAddString(&list,
330*0a44ef6dSjacobs 						PAPI_ATTR_EXCL,
331*0a44ef6dSjacobs 						"page-ranges", ++entry);
332*0a44ef6dSjacobs 				break;
333*0a44ef6dSjacobs 			case 'q': {	/* Solaris priority */
334*0a44ef6dSjacobs 				int i = atoi(optarg);
335*0a44ef6dSjacobs 
336*0a44ef6dSjacobs 				i = 99 * (39 - i) / 39 + 1;
337*0a44ef6dSjacobs 				if ((i < 1) || (i > 100))
338*0a44ef6dSjacobs 					i = 50;
339*0a44ef6dSjacobs 				papiAttributeListAddInteger(&list,
340*0a44ef6dSjacobs 					PAPI_ATTR_EXCL, "priority", i);
341*0a44ef6dSjacobs 				}
342*0a44ef6dSjacobs 				break;
343*0a44ef6dSjacobs 			case 'S':	/* Solaris character set */
344*0a44ef6dSjacobs 				papiAttributeListAddString(&list,
345*0a44ef6dSjacobs 					PAPI_ATTR_EXCL, "lp-charset",
346*0a44ef6dSjacobs 					++entry);
347*0a44ef6dSjacobs 				break;
348*0a44ef6dSjacobs 			case 'T':	/* Solaris type */
349*0a44ef6dSjacobs 				format = lp_type_to_mime_type(++entry);
350*0a44ef6dSjacobs 				break;
351*0a44ef6dSjacobs 			case 'y':	/* Solaris mode */
352*0a44ef6dSjacobs 				papiAttributeListAddString(&list,
353*0a44ef6dSjacobs 					PAPI_ATTR_APPEND, "lp-modes", ++entry);
354*0a44ef6dSjacobs 				break;
355*0a44ef6dSjacobs 			default:
356*0a44ef6dSjacobs 				syslog(LOG_INFO|LOG_DEBUG,
357*0a44ef6dSjacobs 					"Warning: cf message (%s) ignored",
358*0a44ef6dSjacobs 					entry);
359*0a44ef6dSjacobs 				break;
360*0a44ef6dSjacobs 			}
361*0a44ef6dSjacobs 			break;
362*0a44ef6dSjacobs 		/* Undefined Extensions: SCO, Ultrix, AIX, ... */
363*0a44ef6dSjacobs 
364*0a44ef6dSjacobs 		default:
365*0a44ef6dSjacobs 			syslog(LOG_INFO|LOG_DEBUG,
366*0a44ef6dSjacobs 				"Warning: cf message (%s) ignored", entry);
367*0a44ef6dSjacobs 			break;
368*0a44ef6dSjacobs 		}
369*0a44ef6dSjacobs 
370*0a44ef6dSjacobs 		if (format != NULL)
371*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
372*0a44ef6dSjacobs 				"document-format", format);
373*0a44ef6dSjacobs 	}
374*0a44ef6dSjacobs 
375*0a44ef6dSjacobs 	papiAttributeListAddInteger(&list, PAPI_ATTR_EXCL,
376*0a44ef6dSjacobs 					"copies", ++copies);
377*0a44ef6dSjacobs 	papiAttributeListAddString(&list, PAPI_ATTR_EXCL,
378*0a44ef6dSjacobs 					"job-sheets", "none");
379*0a44ef6dSjacobs 
380*0a44ef6dSjacobs 	return (list);
381*0a44ef6dSjacobs }
382*0a44ef6dSjacobs 
383*0a44ef6dSjacobs static papi_status_t
384*0a44ef6dSjacobs submit_job(papi_service_t svc, FILE *ifp, char *printer, char *cf, char **files)
385*0a44ef6dSjacobs {
386*0a44ef6dSjacobs 	papi_attribute_t **list = NULL;
387*0a44ef6dSjacobs 	papi_status_t status;
388*0a44ef6dSjacobs 	papi_job_t job = NULL;
389*0a44ef6dSjacobs 	char *format = "";
390*0a44ef6dSjacobs 
391*0a44ef6dSjacobs 	if ((list = parse_cf(svc, cf, files)) != NULL) {
392*0a44ef6dSjacobs 		/* use the host as known by us, not by them */
393*0a44ef6dSjacobs 		char *host = remote_host_name(ifp);
394*0a44ef6dSjacobs 
395*0a44ef6dSjacobs 		if (host != NULL) {
396*0a44ef6dSjacobs 			papiAttributeListAddString(&list, PAPI_ATTR_REPLACE,
397*0a44ef6dSjacobs 					"job-originating-host-name", host);
398*0a44ef6dSjacobs 			free(host);
399*0a44ef6dSjacobs 		}
400*0a44ef6dSjacobs 	}
401*0a44ef6dSjacobs 
402*0a44ef6dSjacobs 	status = papiJobSubmit(svc, printer, list, NULL, files, &job);
403*0a44ef6dSjacobs 	syslog(LOG_DEBUG, "submit: %s", papiStatusString(status));
404*0a44ef6dSjacobs 	if (status != PAPI_OK) {
405*0a44ef6dSjacobs 		char *tmp = papiServiceGetStatusMessage(svc);
406*0a44ef6dSjacobs 
407*0a44ef6dSjacobs 		syslog(LOG_DEBUG, "submit-detail: %s", tmp ? tmp : "none");
408*0a44ef6dSjacobs 	}
409*0a44ef6dSjacobs 	papiJobFree(job);
410*0a44ef6dSjacobs 
411*0a44ef6dSjacobs 	return (status);
412*0a44ef6dSjacobs }
413*0a44ef6dSjacobs 
414*0a44ef6dSjacobs static char *
415*0a44ef6dSjacobs receive_control_file(papi_service_t svc, FILE *ifp, FILE *ofp, int size)
416*0a44ef6dSjacobs {
417*0a44ef6dSjacobs 	char *ptr, *cf_data;
418*0a44ef6dSjacobs 
419*0a44ef6dSjacobs 	if ((ptr = cf_data = calloc(1, size + 1)) == NULL) {
420*0a44ef6dSjacobs 		NACK(ofp);
421*0a44ef6dSjacobs 		return (NULL);
422*0a44ef6dSjacobs 	} else
423355b4669Sjacobs 		ACK(ofp);
424355b4669Sjacobs 
425*0a44ef6dSjacobs 	while (size > 0) {
426*0a44ef6dSjacobs 		int rc;
427355b4669Sjacobs 
428*0a44ef6dSjacobs 		if (((rc = fread(ptr, 1, size, ifp)) == 0) &&
429*0a44ef6dSjacobs 		    (feof(ifp) != 0)) {
430*0a44ef6dSjacobs 			free(cf_data);
431*0a44ef6dSjacobs 			return (NULL);
432*0a44ef6dSjacobs 		} else {
433*0a44ef6dSjacobs 			ptr += rc;
434*0a44ef6dSjacobs 			size -= rc;
435*0a44ef6dSjacobs 		}
436*0a44ef6dSjacobs 	}
437*0a44ef6dSjacobs 	syslog(LOG_DEBUG, "cf_data(%s)", cf_data);
438*0a44ef6dSjacobs 
439*0a44ef6dSjacobs 	if (fgetc(ifp) != 0) {
440*0a44ef6dSjacobs 		free(cf_data);
441*0a44ef6dSjacobs 		return (NULL);
442*0a44ef6dSjacobs 	}
443*0a44ef6dSjacobs 	ACK(ofp);
444*0a44ef6dSjacobs 
445*0a44ef6dSjacobs 	return (cf_data);
446*0a44ef6dSjacobs }
447*0a44ef6dSjacobs 
448*0a44ef6dSjacobs static char *
449*0a44ef6dSjacobs receive_data_file(FILE *ifp, FILE *ofp, int size)
450*0a44ef6dSjacobs {
451355b4669Sjacobs 	char file[] = "lpdXXXXXX";
452*0a44ef6dSjacobs 	char buf[BUFSIZ];
453355b4669Sjacobs 	int fd;
454355b4669Sjacobs 
455*0a44ef6dSjacobs 	if ((fd = mkstemp(file)) < 0) {
456*0a44ef6dSjacobs 		NACK(ofp);
457*0a44ef6dSjacobs 		return (NULL);
458*0a44ef6dSjacobs 	} else
459*0a44ef6dSjacobs 		ACK(ofp);
460355b4669Sjacobs 
461*0a44ef6dSjacobs 	while (size > 0) {
462*0a44ef6dSjacobs 		int rc = ((size > BUFSIZ) ? BUFSIZ : size);
463*0a44ef6dSjacobs 
464*0a44ef6dSjacobs 		if (((rc = fread(buf, 1, rc, ifp)) == 0) &&
465*0a44ef6dSjacobs 		    (feof(ifp) != 0)) {
466*0a44ef6dSjacobs 			close(fd);
467*0a44ef6dSjacobs 			unlink(file);
468*0a44ef6dSjacobs 			return (NULL);
469*0a44ef6dSjacobs 		} else {
470*0a44ef6dSjacobs 			char *ptr = buf;
471*0a44ef6dSjacobs 
472*0a44ef6dSjacobs 			while (rc > 0) {
473*0a44ef6dSjacobs 				int wrc = write(fd, ptr, rc);
474*0a44ef6dSjacobs 
475*0a44ef6dSjacobs 				if (wrc < 0) {
476*0a44ef6dSjacobs 					close(fd);
477*0a44ef6dSjacobs 					unlink(file);
478*0a44ef6dSjacobs 					return(NULL);
479*0a44ef6dSjacobs 				}
480*0a44ef6dSjacobs 
481*0a44ef6dSjacobs 				ptr += wrc;
482*0a44ef6dSjacobs 				size -= wrc;
483*0a44ef6dSjacobs 				rc -= wrc;
484*0a44ef6dSjacobs 			}
485*0a44ef6dSjacobs 		}
486*0a44ef6dSjacobs 	}
487*0a44ef6dSjacobs 	close(fd);
488*0a44ef6dSjacobs 	if (fgetc(ifp) != 0) {
489*0a44ef6dSjacobs 		unlink(file);
490*0a44ef6dSjacobs 		return (NULL);
491*0a44ef6dSjacobs 	}
492*0a44ef6dSjacobs 	ACK(ofp);
493*0a44ef6dSjacobs 
494*0a44ef6dSjacobs 	return (strdup(file));
495*0a44ef6dSjacobs }
496*0a44ef6dSjacobs 
497*0a44ef6dSjacobs static papi_status_t
498*0a44ef6dSjacobs berkeley_receive_files(papi_service_t svc, FILE *ifp, FILE *ofp, char *printer)
499*0a44ef6dSjacobs {
500*0a44ef6dSjacobs 	papi_status_t status = PAPI_OK;
501*0a44ef6dSjacobs 	char *file, **files = NULL;	/* the job data files */
502*0a44ef6dSjacobs 	char *cf = NULL;
503*0a44ef6dSjacobs 	char buf[BUFSIZ];
504*0a44ef6dSjacobs 
505*0a44ef6dSjacobs 	while (fgets(buf, sizeof (buf), ifp) != NULL) {
506*0a44ef6dSjacobs 		int size;
507*0a44ef6dSjacobs 
508*0a44ef6dSjacobs 		syslog(LOG_DEBUG, "XFER CMD: (%d)%s\n", buf[0], &buf[1]);
509*0a44ef6dSjacobs #ifdef DEBUG	/* translate [1-3]... messages to \[1-3] to run by hand */
510*0a44ef6dSjacobs 		if ((buf[0] > '0') && (buf[0] < '4'))
511*0a44ef6dSjacobs 			buf[0] -= '0';
512*0a44ef6dSjacobs #endif
513*0a44ef6dSjacobs 		switch (buf[0]) {
514*0a44ef6dSjacobs 		case 0x01:	/* Abort */
515*0a44ef6dSjacobs 			cleanup(&files, &cf);
516*0a44ef6dSjacobs 			break;
517*0a44ef6dSjacobs 		case 0x02: {	/* Receive control file */
518*0a44ef6dSjacobs 			cf = receive_control_file(svc, ifp, ofp, atoi(&buf[1]));
519*0a44ef6dSjacobs 			if (cf == NULL) {
520*0a44ef6dSjacobs 				cleanup(&files, &cf);
521*0a44ef6dSjacobs 				return (PAPI_BAD_REQUEST);
522*0a44ef6dSjacobs 			} else if (files != NULL) {
523*0a44ef6dSjacobs 				status = submit_job(svc, ifp, printer, cf,
524*0a44ef6dSjacobs 							files);
525*0a44ef6dSjacobs 				cleanup(&files, &cf);
526*0a44ef6dSjacobs 			}
527*0a44ef6dSjacobs 			}
528*0a44ef6dSjacobs 			break;
529*0a44ef6dSjacobs 		case 0x03: {	/* Receive data file */
530*0a44ef6dSjacobs 			file = receive_data_file(ifp, ofp, atoi(&buf[1]));
531*0a44ef6dSjacobs 			if (file == NULL) {
532*0a44ef6dSjacobs 				cleanup(&files, &cf);
533*0a44ef6dSjacobs 				return (PAPI_TEMPORARY_ERROR);
534*0a44ef6dSjacobs 			}
535*0a44ef6dSjacobs 			list_append(&files, file);
536355b4669Sjacobs 			}
537355b4669Sjacobs 			break;
538355b4669Sjacobs 		default:
539*0a44ef6dSjacobs 			cleanup(&files, &cf);
540355b4669Sjacobs 			fatal(ofp, "protocol screwup");
541355b4669Sjacobs 			break;
542355b4669Sjacobs 		}
543355b4669Sjacobs 	}
544355b4669Sjacobs 
545*0a44ef6dSjacobs 	if ((cf != NULL) && (files != NULL))
546*0a44ef6dSjacobs 		status = submit_job(svc, ifp, printer, cf, files);
547*0a44ef6dSjacobs 
548*0a44ef6dSjacobs 	cleanup(&files, &cf);
549*0a44ef6dSjacobs 
550*0a44ef6dSjacobs 	return (status);
551355b4669Sjacobs }
552355b4669Sjacobs 
553*0a44ef6dSjacobs static papi_status_t
554355b4669Sjacobs berkeley_transfer_files(papi_service_t svc, FILE *ifp, FILE *ofp,
555355b4669Sjacobs 		char *printer)
556355b4669Sjacobs {
557355b4669Sjacobs 	papi_status_t status;
558355b4669Sjacobs 	papi_printer_t p = NULL;
559*0a44ef6dSjacobs 	char *keys[] = { "printer-is-accepting-jobs", NULL };
560355b4669Sjacobs 
561355b4669Sjacobs 	status = papiPrinterQuery(svc, printer, keys, NULL, &p);
562355b4669Sjacobs 	if ((status == PAPI_OK) && (p != NULL)) {
563355b4669Sjacobs 		papi_attribute_t **attrs = papiPrinterGetAttributeList(p);
564355b4669Sjacobs 		char accepting = PAPI_FALSE;
565355b4669Sjacobs 
566355b4669Sjacobs 		papiAttributeListGetBoolean(attrs, NULL,
567*0a44ef6dSjacobs 				"printer-is-accepting-jobs", &accepting);
568355b4669Sjacobs 
569*0a44ef6dSjacobs 		if (accepting == PAPI_TRUE) {
570*0a44ef6dSjacobs 			ACK(ofp);
571*0a44ef6dSjacobs 			status = berkeley_receive_files(svc, ifp, ofp, printer);
572*0a44ef6dSjacobs 		} else
573355b4669Sjacobs 			NACK(ofp);
574355b4669Sjacobs 
575355b4669Sjacobs 		papiPrinterFree(p);
576355b4669Sjacobs 	} else
577355b4669Sjacobs 		NACK(ofp);
578*0a44ef6dSjacobs 
579*0a44ef6dSjacobs 	return (status);
580355b4669Sjacobs }
581355b4669Sjacobs 
582*0a44ef6dSjacobs static int
583*0a44ef6dSjacobs cyclical_service_check(char *svc_name)
584*0a44ef6dSjacobs {
585*0a44ef6dSjacobs 	papi_attribute_t **list;
586*0a44ef6dSjacobs 	char buf[BUFSIZ];
587*0a44ef6dSjacobs 	uri_t *uri = NULL;
588*0a44ef6dSjacobs 	char *s = NULL;
589*0a44ef6dSjacobs 
590*0a44ef6dSjacobs 	/* was there a printer? */
591*0a44ef6dSjacobs 	if (svc_name == NULL)
592*0a44ef6dSjacobs 		return (0);
593*0a44ef6dSjacobs 
594*0a44ef6dSjacobs 	if ((list = getprinterbyname(svc_name, NULL)) == NULL)
595*0a44ef6dSjacobs 		return (0);     /* if it doesnt' resolve, we will fail later */
596*0a44ef6dSjacobs 
597*0a44ef6dSjacobs 	papiAttributeListGetString(list, NULL, "printer-uri-supported", &s);
598*0a44ef6dSjacobs 	if ((s == NULL) || (strcasecmp(svc_name, s) != 0))
599*0a44ef6dSjacobs 		return (0);     /* they don't match */
600*0a44ef6dSjacobs 
601*0a44ef6dSjacobs 	/* is it in uri form? */
602*0a44ef6dSjacobs 	if (uri_from_string(s, &uri) < 0)
603*0a44ef6dSjacobs 		return (0);
604*0a44ef6dSjacobs 
605*0a44ef6dSjacobs 	if ((uri == NULL) || (uri->scheme == NULL) || (uri->host == NULL)) {
606*0a44ef6dSjacobs 		uri_free(uri);
607*0a44ef6dSjacobs 		return (0);
608*0a44ef6dSjacobs 	}
609*0a44ef6dSjacobs 
610*0a44ef6dSjacobs 	/* is it in lpd form? */
611*0a44ef6dSjacobs 	if (strcasecmp(uri->scheme, "lpd") != 0) {
612*0a44ef6dSjacobs 		uri_free(uri);
613*0a44ef6dSjacobs 		return (0);
614*0a44ef6dSjacobs 	}
615*0a44ef6dSjacobs 
616*0a44ef6dSjacobs 	/* is it the local host? */
617*0a44ef6dSjacobs 	sysinfo(SI_HOSTNAME, buf, sizeof (buf));
618*0a44ef6dSjacobs 	if ((strcasecmp(uri->host, "localhost") != 0) &&
619*0a44ef6dSjacobs 	     (strcasecmp(uri->host, buf) != 0)) {
620*0a44ef6dSjacobs 		uri_free(uri);
621*0a44ef6dSjacobs 		return (0);
622*0a44ef6dSjacobs 	}
623*0a44ef6dSjacobs 
624*0a44ef6dSjacobs 	uri_free(uri);
625*0a44ef6dSjacobs 	return (1);
626*0a44ef6dSjacobs }
627*0a44ef6dSjacobs 
628*0a44ef6dSjacobs 
629355b4669Sjacobs /*
630355b4669Sjacobs  * This is the entry point for this program.  The program takes the
631355b4669Sjacobs  * following options:
632355b4669Sjacobs  * 	(none)
633355b4669Sjacobs  */
634355b4669Sjacobs int
635355b4669Sjacobs main(int ac, char *av[])
636355b4669Sjacobs {
637355b4669Sjacobs 	papi_status_t status;
638355b4669Sjacobs 	papi_service_t svc = NULL;
639355b4669Sjacobs 	papi_encryption_t encryption = PAPI_ENCRYPT_NEVER;
640355b4669Sjacobs 	FILE	*ifp = stdin,
641355b4669Sjacobs 		*ofp = stdout;
642355b4669Sjacobs 	int	c;
643355b4669Sjacobs 	char	buf[BUFSIZ],
644355b4669Sjacobs 		**args,
645*0a44ef6dSjacobs 		*printer,
646*0a44ef6dSjacobs 		*run_dir = "/var/run/in.lpd",
647*0a44ef6dSjacobs 		*run_user = NULL;
648*0a44ef6dSjacobs 	struct passwd *pw = NULL;
649355b4669Sjacobs 
650*0a44ef6dSjacobs 	(void) chdir("/tmp");		/* run in /tmp by default */
651355b4669Sjacobs 	openlog("bsd-gw", LOG_PID, LOG_LPR);
652355b4669Sjacobs 
653*0a44ef6dSjacobs 	while ((c = getopt(ac, av, "Ed:u:")) != EOF)
654355b4669Sjacobs 		switch (c) {
655355b4669Sjacobs 		case 'E':
656355b4669Sjacobs 			encryption = PAPI_ENCRYPT_ALWAYS;
657355b4669Sjacobs 			break;
658*0a44ef6dSjacobs 		case 'd':	/* run where they tell you */
659*0a44ef6dSjacobs 			run_dir = optarg;
660*0a44ef6dSjacobs 			break;
661*0a44ef6dSjacobs 		case 'u':	/* run as */
662*0a44ef6dSjacobs 			run_user = optarg;
663*0a44ef6dSjacobs 			break;
664355b4669Sjacobs 		default:
665355b4669Sjacobs 			;
666355b4669Sjacobs 		}
667355b4669Sjacobs 
668*0a44ef6dSjacobs 	if (run_user != NULL)	/* get the requested user info */
669*0a44ef6dSjacobs 		pw = getpwnam(run_user);
670*0a44ef6dSjacobs 
671*0a44ef6dSjacobs 	if (run_dir != NULL) {	/* setup the run_dir */
672*0a44ef6dSjacobs 		(void) mkdir(run_dir, 0700);
673*0a44ef6dSjacobs 		if (pw != NULL)
674*0a44ef6dSjacobs 			(void) chown(run_dir, pw->pw_uid, pw->pw_gid);
675*0a44ef6dSjacobs 	}
676*0a44ef6dSjacobs 
677*0a44ef6dSjacobs 	if (pw != NULL) {	/* run as the requested user */
678*0a44ef6dSjacobs 		syslog(LOG_DEBUG, "name: %s, uid: %d, gid: %d",
679*0a44ef6dSjacobs 				pw->pw_name, pw->pw_uid, pw->pw_gid);
680*0a44ef6dSjacobs 		initgroups(pw->pw_name, pw->pw_gid);
681*0a44ef6dSjacobs 		setgid(pw->pw_gid);
682*0a44ef6dSjacobs 		setuid(pw->pw_uid);
683*0a44ef6dSjacobs 	}
684*0a44ef6dSjacobs 
685*0a44ef6dSjacobs 	if (run_dir != NULL)	/* move to the run_dir */
686*0a44ef6dSjacobs 		if (chdir(run_dir) < 0) {
687*0a44ef6dSjacobs 			syslog(LOG_DEBUG, "failed to chdir(%s)", run_dir);
688*0a44ef6dSjacobs 			exit(1);
689*0a44ef6dSjacobs 		}
690*0a44ef6dSjacobs 
691*0a44ef6dSjacobs 	syslog(LOG_DEBUG, "$CWD = %s", getwd(NULL));
692*0a44ef6dSjacobs 
693355b4669Sjacobs 	if (fgets(buf, sizeof (buf), ifp) == NULL) {
694355b4669Sjacobs 		if (feof(ifp) == 0)
695355b4669Sjacobs 			syslog(LOG_ERR, "Error reading from connection: %s",
696355b4669Sjacobs 				strerror(errno));
697355b4669Sjacobs 		exit(1);
698355b4669Sjacobs 	}
699355b4669Sjacobs 
700*0a44ef6dSjacobs 	syslog(LOG_DEBUG, "CMD: (%d)%s\n", buf[0], &buf[1]);
701*0a44ef6dSjacobs 
702*0a44ef6dSjacobs #ifdef DEBUG	/* translate [1-5]... messages to \[1-5] to run by hand */
703*0a44ef6dSjacobs 	if ((buf[0] > '0') && (buf[0] < '6'))
704*0a44ef6dSjacobs 		buf[0] -= '0';
705*0a44ef6dSjacobs #endif
706*0a44ef6dSjacobs 
707355b4669Sjacobs 	if ((buf[0] < 1) || (buf[0] > 5)) {
708355b4669Sjacobs 		fatal(ofp, "Invalid protocol request (%d): %c%s\n",
709355b4669Sjacobs 			buf[0], buf[0], buf);
710355b4669Sjacobs 		exit(1);
711355b4669Sjacobs 	}
712355b4669Sjacobs 
713355b4669Sjacobs 	args = strsplit(&buf[1], "\t\n ");
714355b4669Sjacobs 	printer = *args++;
715355b4669Sjacobs 
716355b4669Sjacobs 	if (printer == NULL) {
717355b4669Sjacobs 		fatal(ofp, "Can't determine requested printer");
718355b4669Sjacobs 		exit(1);
719355b4669Sjacobs 	}
720355b4669Sjacobs 
721*0a44ef6dSjacobs 	if (cyclical_service_check(printer) != 0) {
722*0a44ef6dSjacobs 		fatal(ofp, "%s is cyclical\n", printer);
723*0a44ef6dSjacobs 		exit(1);
724*0a44ef6dSjacobs 	}
725*0a44ef6dSjacobs 
726355b4669Sjacobs 	status = papiServiceCreate(&svc, printer, NULL, NULL, NULL,
727355b4669Sjacobs 					encryption, NULL);
728355b4669Sjacobs 	if (status != PAPI_OK) {
729355b4669Sjacobs 		fatal(ofp, "Failed to contact service for %s: %s\n", printer,
730355b4669Sjacobs 			verbose_papi_message(svc, status));
731355b4669Sjacobs 		exit(1);
732355b4669Sjacobs 	}
733355b4669Sjacobs 
734*0a44ef6dSjacobs 	/*
735*0a44ef6dSjacobs 	 * Trusted Solaris can't be trusting of intermediaries.  Pass
736*0a44ef6dSjacobs 	 * the socket connection to the print service to retrieve the
737*0a44ef6dSjacobs 	 * sensativity label off of a multi-level port.
738*0a44ef6dSjacobs 	 */
739*0a44ef6dSjacobs 	(void) papiServiceSetPeer(svc, fileno(ifp));
740355b4669Sjacobs 
741355b4669Sjacobs 	switch (buf[0]) {
742355b4669Sjacobs 	case '\1':	/* restart printer */
743355b4669Sjacobs 		ACK(ofp);	/* there is no equivalent */
744355b4669Sjacobs 		break;
745355b4669Sjacobs 	case '\2':	/* transfer job(s) */
746*0a44ef6dSjacobs 		status = berkeley_transfer_files(svc, ifp, ofp, printer);
747355b4669Sjacobs 		break;
748355b4669Sjacobs 	case '\3':	/* show queue (short) */
749355b4669Sjacobs 	case '\4': {	/* show queue (long) */
750355b4669Sjacobs 		int count;
751355b4669Sjacobs 
752355b4669Sjacobs 		for (count = 0; args[count] != 0; count++);
753355b4669Sjacobs 
754355b4669Sjacobs 		berkeley_queue_report(svc, ofp, printer, buf[0], count, args);
755355b4669Sjacobs 		}
756355b4669Sjacobs 		break;
757355b4669Sjacobs 	case '\5': {	/* cancel job(s) */
758*0a44ef6dSjacobs 		char *user = *args++;
759*0a44ef6dSjacobs 		char *host = remote_host_name(ifp);
760355b4669Sjacobs 		int count;
761355b4669Sjacobs 
762*0a44ef6dSjacobs 		if (host != NULL) {
763*0a44ef6dSjacobs 			char buf[BUFSIZ];
764*0a44ef6dSjacobs 
765*0a44ef6dSjacobs 			snprintf(buf, sizeof (buf), "%s@%s", user, host);
766*0a44ef6dSjacobs 			status = papiServiceSetUserName(svc, buf);
767*0a44ef6dSjacobs 		} else
768*0a44ef6dSjacobs 			status = papiServiceSetUserName(svc, user);
769*0a44ef6dSjacobs 
770355b4669Sjacobs 		for (count = 0; args[count] != 0; count++);
771355b4669Sjacobs 
772355b4669Sjacobs 		berkeley_cancel_request(svc, ofp, printer, count, args);
773355b4669Sjacobs 		}
774355b4669Sjacobs 		break;
775355b4669Sjacobs 	default:
776355b4669Sjacobs 		fatal(ofp, "unsupported protocol request (%c), %s",
777355b4669Sjacobs 			buf[0], &buf[1]);
778355b4669Sjacobs 	}
779355b4669Sjacobs 
780355b4669Sjacobs 	(void) fflush(ofp);
781355b4669Sjacobs 
782355b4669Sjacobs 	syslog(LOG_DEBUG, "protocol request(%d) for %s completed: %s",
783355b4669Sjacobs 		buf[0], printer, papiStatusString(status));
784*0a44ef6dSjacobs 	if (status != PAPI_OK)
785*0a44ef6dSjacobs 		syslog(LOG_DEBUG, "detail: %s",
786*0a44ef6dSjacobs 				verbose_papi_message(svc, status));
787355b4669Sjacobs 
788355b4669Sjacobs 	papiServiceDestroy(svc);
789355b4669Sjacobs 
790355b4669Sjacobs 	return (0);
791355b4669Sjacobs }
792