xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/validate.c (revision 7c478bd95313f5f23a4c958a745db2134aa0324)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2001 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.11.1.10	*/
32*7c478bd9Sstevel@tonic-gate /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include "lpsched.h"
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #include "validate.h"
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #define register auto
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate int		pickfilter ( RSTATUS * , CANDIDATE * , FSTATUS * );
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate unsigned long		chkprinter_result	= 0;
43*7c478bd9Sstevel@tonic-gate char *			o_cpi		= 0;
44*7c478bd9Sstevel@tonic-gate char *			o_lpi		= 0;
45*7c478bd9Sstevel@tonic-gate char *			o_width		= 0;
46*7c478bd9Sstevel@tonic-gate char *			o_length	= 0;
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate static int		wants_nobanner	= 0;
49*7c478bd9Sstevel@tonic-gate static int		lp_or_root	= 0;
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate static int		_chkopts ( RSTATUS *, CANDIDATE * , FSTATUS * );
52*7c478bd9Sstevel@tonic-gate static void		free_candidate ( CANDIDATE * );
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /**
55*7c478bd9Sstevel@tonic-gate  ** _validate() - FIND A PRINTER TO HANDLE A REQUEST
56*7c478bd9Sstevel@tonic-gate  **/
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate short
59*7c478bd9Sstevel@tonic-gate _validate(RSTATUS *prs, PSTATUS *pps, PSTATUS *stop_pps, char **prefixp,
60*7c478bd9Sstevel@tonic-gate 	 int moving)
61*7c478bd9Sstevel@tonic-gate {
62*7c478bd9Sstevel@tonic-gate 	register CANDIDATE	*pc		= 0,
63*7c478bd9Sstevel@tonic-gate 				*pcend,
64*7c478bd9Sstevel@tonic-gate 				*best_pc	= 0;
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate 	register FSTATUS	*pfs		= 0;
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate 	register CSTATUS	*pcs		= 0;
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate 	CANDIDATE		*arena		= 0,
71*7c478bd9Sstevel@tonic-gate 				single;
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate 	size_t			n;
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate 	short			ret;
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 	chkprinter_result = 0;
78*7c478bd9Sstevel@tonic-gate 	o_cpi = o_lpi = o_width = o_length = 0;
79*7c478bd9Sstevel@tonic-gate 	wants_nobanner = 0;
80*7c478bd9Sstevel@tonic-gate 	memset (&single, 0, sizeof(single));
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate 	lp_or_root = 0;
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate 	if (STREQU(prs->secure->system, Local_System))
85*7c478bd9Sstevel@tonic-gate 		if (bangequ(prs->secure->user, "root") ||
86*7c478bd9Sstevel@tonic-gate 					bangequ(prs->secure->user, "lp"))
87*7c478bd9Sstevel@tonic-gate 			lp_or_root = 1;
88*7c478bd9Sstevel@tonic-gate 
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate 	if (prefixp)
91*7c478bd9Sstevel@tonic-gate 		*prefixp = prs->request->destination;
92*7c478bd9Sstevel@tonic-gate 
93*7c478bd9Sstevel@tonic-gate 	/*
94*7c478bd9Sstevel@tonic-gate 	 * If a destination other than "any" was given,
95*7c478bd9Sstevel@tonic-gate 	 * see if it exists in our internal tables.
96*7c478bd9Sstevel@tonic-gate 	 */
97*7c478bd9Sstevel@tonic-gate 	if (!pps && prs->request->destination &&
98*7c478bd9Sstevel@tonic-gate 	    !STREQU(prs->request->destination, NAME_ANY))
99*7c478bd9Sstevel@tonic-gate 		if (((pps = search_ptable(prs->request->destination)) != NULL) ||
100*7c478bd9Sstevel@tonic-gate 		    ((pcs = search_ctable(prs->request->destination)) != NULL) &&
101*7c478bd9Sstevel@tonic-gate 		    pcs->class->members)
102*7c478bd9Sstevel@tonic-gate 			/*EMPTY*/;
103*7c478bd9Sstevel@tonic-gate 		else {
104*7c478bd9Sstevel@tonic-gate 			ret = MNODEST;
105*7c478bd9Sstevel@tonic-gate 			goto Return;
106*7c478bd9Sstevel@tonic-gate 		}
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	/*
109*7c478bd9Sstevel@tonic-gate 	 * If we are trying to avoid a printer, but the request
110*7c478bd9Sstevel@tonic-gate 	 * was destined for just that printer, we're out.
111*7c478bd9Sstevel@tonic-gate 	 */
112*7c478bd9Sstevel@tonic-gate 	if (pps && pps == stop_pps) {
113*7c478bd9Sstevel@tonic-gate 		ret = MERRDEST;
114*7c478bd9Sstevel@tonic-gate 		goto Return;
115*7c478bd9Sstevel@tonic-gate 	}
116*7c478bd9Sstevel@tonic-gate 
117*7c478bd9Sstevel@tonic-gate 	/*
118*7c478bd9Sstevel@tonic-gate 	 * If a form was given, see if it exists; if so,
119*7c478bd9Sstevel@tonic-gate 	 * see if the user is allowed to use it.
120*7c478bd9Sstevel@tonic-gate 	 * If a remote printer was specified, then don't use any local
121*7c478bd9Sstevel@tonic-gate 	 * form knowledge.
122*7c478bd9Sstevel@tonic-gate 	 */
123*7c478bd9Sstevel@tonic-gate 	if (prs && prs->request && prs->request->form && (pps || pcs)) {
124*7c478bd9Sstevel@tonic-gate 		if ((pfs = search_ftable(prs->request->form))) {
125*7c478bd9Sstevel@tonic-gate 			if (lp_or_root || allowed(prs->secure->user,
126*7c478bd9Sstevel@tonic-gate 				pfs->users_allowed, pfs->users_denied))
127*7c478bd9Sstevel@tonic-gate 				/*EMPTY*/;
128*7c478bd9Sstevel@tonic-gate 			else {
129*7c478bd9Sstevel@tonic-gate 				ret = MDENYMEDIA;
130*7c478bd9Sstevel@tonic-gate 				goto Return;
131*7c478bd9Sstevel@tonic-gate 			}
132*7c478bd9Sstevel@tonic-gate 		} else {
133*7c478bd9Sstevel@tonic-gate 			ret = MNOMEDIA;
134*7c478bd9Sstevel@tonic-gate 			goto Return;
135*7c478bd9Sstevel@tonic-gate 		}
136*7c478bd9Sstevel@tonic-gate 	}
137*7c478bd9Sstevel@tonic-gate 
138*7c478bd9Sstevel@tonic-gate 	/*
139*7c478bd9Sstevel@tonic-gate 	 * If the request includes -o options there may be pitch and
140*7c478bd9Sstevel@tonic-gate 	 * size and no-banner requests that have to be checked. One
141*7c478bd9Sstevel@tonic-gate 	 * could argue that this shouldn't be in the Spooler, because
142*7c478bd9Sstevel@tonic-gate 	 * the Spooler's job is SPOOLING, not PRINTING. That's right,
143*7c478bd9Sstevel@tonic-gate 	 * except that the Spooler will be making a choice of printers
144*7c478bd9Sstevel@tonic-gate 	 * so it has to evaluate carefully: E.g. user wants ANY printer,
145*7c478bd9Sstevel@tonic-gate 	 * so we should pick one that can handle what he/she wants.
146*7c478bd9Sstevel@tonic-gate 	 *
147*7c478bd9Sstevel@tonic-gate 	 * Parse out the important stuff here so we have it when we
148*7c478bd9Sstevel@tonic-gate 	 * need it.
149*7c478bd9Sstevel@tonic-gate 	 */
150*7c478bd9Sstevel@tonic-gate 	{
151*7c478bd9Sstevel@tonic-gate 		register char		**list,
152*7c478bd9Sstevel@tonic-gate 					**pl;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 		if (
155*7c478bd9Sstevel@tonic-gate 			prs->request->options
156*7c478bd9Sstevel@tonic-gate 		     && (list = dashos(prs->request->options))
157*7c478bd9Sstevel@tonic-gate 		) {
158*7c478bd9Sstevel@tonic-gate 			for (pl = list ; *pl; pl++)
159*7c478bd9Sstevel@tonic-gate 				if (STRNEQU(*pl, "cpi=", 4))
160*7c478bd9Sstevel@tonic-gate 					o_cpi = Strdup(*pl + 4);
161*7c478bd9Sstevel@tonic-gate 				else if (STRNEQU(*pl, "lpi=", 4))
162*7c478bd9Sstevel@tonic-gate 					o_lpi = Strdup(*pl + 4);
163*7c478bd9Sstevel@tonic-gate 				else if (STRNEQU(*pl, "width=", 6))
164*7c478bd9Sstevel@tonic-gate 					o_width = Strdup(*pl + 6);
165*7c478bd9Sstevel@tonic-gate 				else if (STRNEQU(*pl, "length=", 7))
166*7c478bd9Sstevel@tonic-gate 					o_length = Strdup(*pl + 7);
167*7c478bd9Sstevel@tonic-gate 				else if (STREQU(*pl, "nobanner"))
168*7c478bd9Sstevel@tonic-gate 					wants_nobanner = 1;
169*7c478bd9Sstevel@tonic-gate 			freelist (list);
170*7c478bd9Sstevel@tonic-gate 		}
171*7c478bd9Sstevel@tonic-gate 	}
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	/*
174*7c478bd9Sstevel@tonic-gate 	 * This macro checks that a form has a mandatory print wheel
175*7c478bd9Sstevel@tonic-gate 	 * (or character set).
176*7c478bd9Sstevel@tonic-gate 	 */
177*7c478bd9Sstevel@tonic-gate #define	CHKMAND(PFS) \
178*7c478bd9Sstevel@tonic-gate 	( \
179*7c478bd9Sstevel@tonic-gate 		(PFS) \
180*7c478bd9Sstevel@tonic-gate 	     && (PFS)->form->chset \
181*7c478bd9Sstevel@tonic-gate 	     && !STREQU((PFS)->form->chset, NAME_ANY) \
182*7c478bd9Sstevel@tonic-gate 	     && (PFS)->form->mandatory \
183*7c478bd9Sstevel@tonic-gate 	)
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	/*
186*7c478bd9Sstevel@tonic-gate 	 * This macro checks that the user is allowed to use the
187*7c478bd9Sstevel@tonic-gate 	 * printer.
188*7c478bd9Sstevel@tonic-gate 	 */
189*7c478bd9Sstevel@tonic-gate #define CHKU(PRS,PPS) \
190*7c478bd9Sstevel@tonic-gate 	( \
191*7c478bd9Sstevel@tonic-gate 		lp_or_root \
192*7c478bd9Sstevel@tonic-gate 	     || allowed( \
193*7c478bd9Sstevel@tonic-gate 			(PRS)->secure->user, \
194*7c478bd9Sstevel@tonic-gate 			(PPS)->users_allowed, \
195*7c478bd9Sstevel@tonic-gate 			(PPS)->users_denied \
196*7c478bd9Sstevel@tonic-gate 		) \
197*7c478bd9Sstevel@tonic-gate 	)
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	/*
200*7c478bd9Sstevel@tonic-gate 	 * This macro checks that the form is allowed on the printer,
201*7c478bd9Sstevel@tonic-gate 	 * or is already mounted there.
202*7c478bd9Sstevel@tonic-gate 	 * Note: By doing this check we don't have to check that the
203*7c478bd9Sstevel@tonic-gate 	 * characteristics of the form, such as pitch, size, or
204*7c478bd9Sstevel@tonic-gate 	 * character set, against the printer's capabilities, ASSUMING,
205*7c478bd9Sstevel@tonic-gate 	 * of course, that the allow list is correct. That is, the
206*7c478bd9Sstevel@tonic-gate 	 * allow list lists forms that have already been checked against
207*7c478bd9Sstevel@tonic-gate 	 * the printer!
208*7c478bd9Sstevel@tonic-gate 	 */
209*7c478bd9Sstevel@tonic-gate #define CHKF(PFS,PPS) \
210*7c478bd9Sstevel@tonic-gate 	( \
211*7c478bd9Sstevel@tonic-gate 		isFormMountedOnPrinter(PPS,PFS) \
212*7c478bd9Sstevel@tonic-gate 	     || allowed( \
213*7c478bd9Sstevel@tonic-gate 			(PFS)->form->name, \
214*7c478bd9Sstevel@tonic-gate 			(PPS)->forms_allowed, \
215*7c478bd9Sstevel@tonic-gate 			(PPS)->forms_denied \
216*7c478bd9Sstevel@tonic-gate 		) \
217*7c478bd9Sstevel@tonic-gate 	)
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	/*
220*7c478bd9Sstevel@tonic-gate 	 * This macro checks that the print wheel is acceptable
221*7c478bd9Sstevel@tonic-gate 	 * for the printer or is mounted. Note: If the printer doesn't
222*7c478bd9Sstevel@tonic-gate 	 * take print wheels, the check passes. The check for printers
223*7c478bd9Sstevel@tonic-gate 	 * that don't take print wheels is below.
224*7c478bd9Sstevel@tonic-gate 	 */
225*7c478bd9Sstevel@tonic-gate #define CHKPW(PW,PPS) \
226*7c478bd9Sstevel@tonic-gate 	( \
227*7c478bd9Sstevel@tonic-gate 		!(PPS)->printer->daisy \
228*7c478bd9Sstevel@tonic-gate 	     || ( \
229*7c478bd9Sstevel@tonic-gate 			(PPS)->pwheel_name \
230*7c478bd9Sstevel@tonic-gate 		     && STREQU((PPS)->pwheel_name, (PW)) \
231*7c478bd9Sstevel@tonic-gate 		) \
232*7c478bd9Sstevel@tonic-gate 	     || searchlist((PW), (PPS)->printer->char_sets) \
233*7c478bd9Sstevel@tonic-gate 	)
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	/*
236*7c478bd9Sstevel@tonic-gate 	 * This macro checks the pitch, page size, and (if need be)
237*7c478bd9Sstevel@tonic-gate 	 * the character set. The character set isn't checked if the
238*7c478bd9Sstevel@tonic-gate 	 * printer takes print wheels, or if the character set is
239*7c478bd9Sstevel@tonic-gate 	 * listed in the printer's alias list.
240*7c478bd9Sstevel@tonic-gate 	 * The form has to be checked as well; while we're sure that
241*7c478bd9Sstevel@tonic-gate 	 * at least one type for each printer can handle the form's
242*7c478bd9Sstevel@tonic-gate 	 * cpi/lpi/etc. characteristics (lpadmin made sure), we aren't
243*7c478bd9Sstevel@tonic-gate 	 * sure that ALL the types work.
244*7c478bd9Sstevel@tonic-gate 	 */
245*7c478bd9Sstevel@tonic-gate #define CHKOPTS(PRS,PC,PFS) _chkopts((PRS),(PC),(PFS)) /* was a macro */
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 	/*
248*7c478bd9Sstevel@tonic-gate 	 * This macro checks the acceptance status of a printer.
249*7c478bd9Sstevel@tonic-gate 	 * If the request is already assigned to that printer,
250*7c478bd9Sstevel@tonic-gate 	 * then it's okay. It's ambiguous what should happen if
251*7c478bd9Sstevel@tonic-gate 	 * originally a "-d any" request was accepted, temporarily
252*7c478bd9Sstevel@tonic-gate 	 * assigned one printer, then the administrator (1) rejected
253*7c478bd9Sstevel@tonic-gate 	 * further requests for the printers and (2) made the
254*7c478bd9Sstevel@tonic-gate 	 * temporarily assigned printer unusable for the request.
255*7c478bd9Sstevel@tonic-gate 	 * What will happen, of course, is that the request will
256*7c478bd9Sstevel@tonic-gate 	 * be canceled, even though the other printers would be okay
257*7c478bd9Sstevel@tonic-gate 	 * if not rejecting....but if we were to say, gee it's okay,
258*7c478bd9Sstevel@tonic-gate 	 * the request has already been accepted, we may be allowing
259*7c478bd9Sstevel@tonic-gate 	 * it on printers that were NEVER accepting. Thus we can
260*7c478bd9Sstevel@tonic-gate 	 * continue to accept it only for the printer already assigned.
261*7c478bd9Sstevel@tonic-gate 	 */
262*7c478bd9Sstevel@tonic-gate #define CHKACCEPT(PRS,PPS) \
263*7c478bd9Sstevel@tonic-gate 	( \
264*7c478bd9Sstevel@tonic-gate 		!((PPS)->status & PS_REJECTED) \
265*7c478bd9Sstevel@tonic-gate 	     || (PRS)->printer == (PPS) \
266*7c478bd9Sstevel@tonic-gate 	     || moving \
267*7c478bd9Sstevel@tonic-gate 	)
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	/*
270*7c478bd9Sstevel@tonic-gate 	 * If a print wheel or character set is given, see if it
271*7c478bd9Sstevel@tonic-gate 	 * is allowed on the form.
272*7c478bd9Sstevel@tonic-gate 	 */
273*7c478bd9Sstevel@tonic-gate 	if (prs->request->charset)
274*7c478bd9Sstevel@tonic-gate 		if (
275*7c478bd9Sstevel@tonic-gate 			!CHKMAND(pfs)
276*7c478bd9Sstevel@tonic-gate 		     || STREQU(prs->request->charset, pfs->form->chset)
277*7c478bd9Sstevel@tonic-gate 		)
278*7c478bd9Sstevel@tonic-gate 			/*EMPTY*/;
279*7c478bd9Sstevel@tonic-gate 		else {
280*7c478bd9Sstevel@tonic-gate 			ret = MDENYMEDIA;
281*7c478bd9Sstevel@tonic-gate 			chkprinter_result |= PCK_CHARSET;
282*7c478bd9Sstevel@tonic-gate 			goto Return;
283*7c478bd9Sstevel@tonic-gate 		}
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 	/*
286*7c478bd9Sstevel@tonic-gate 	 * If a single printer was named, check the request against it.
287*7c478bd9Sstevel@tonic-gate 	 * Do the accept/reject check late so that we give the most
288*7c478bd9Sstevel@tonic-gate 	 * useful information to the user.
289*7c478bd9Sstevel@tonic-gate 	 */
290*7c478bd9Sstevel@tonic-gate 	if (pps) {
291*7c478bd9Sstevel@tonic-gate 		(pc = &single)->pps = pps;
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 		/* Does the printer allow the user? */
294*7c478bd9Sstevel@tonic-gate 		if (!CHKU(prs, pps)) {
295*7c478bd9Sstevel@tonic-gate 			ret = MDENYDEST;
296*7c478bd9Sstevel@tonic-gate 			goto Return;
297*7c478bd9Sstevel@tonic-gate 		}
298*7c478bd9Sstevel@tonic-gate 
299*7c478bd9Sstevel@tonic-gate 		/* Does the printer allow the form? */
300*7c478bd9Sstevel@tonic-gate 		if (pfs && !CHKF(pfs, pps)) {
301*7c478bd9Sstevel@tonic-gate 			ret = MNOMOUNT;
302*7c478bd9Sstevel@tonic-gate 			goto Return;
303*7c478bd9Sstevel@tonic-gate 		}
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate 		/* Does the printer allow the pwheel? */
306*7c478bd9Sstevel@tonic-gate 		if (
307*7c478bd9Sstevel@tonic-gate 			prs->request->charset
308*7c478bd9Sstevel@tonic-gate 		     && !CHKPW(prs->request->charset, pps)
309*7c478bd9Sstevel@tonic-gate 		) {
310*7c478bd9Sstevel@tonic-gate 			ret = MNOMOUNT;
311*7c478bd9Sstevel@tonic-gate 			goto Return;
312*7c478bd9Sstevel@tonic-gate 		}
313*7c478bd9Sstevel@tonic-gate 
314*7c478bd9Sstevel@tonic-gate 		/* Can printer handle the pitch/size/charset/nobanner? */
315*7c478bd9Sstevel@tonic-gate 		if (!CHKOPTS(prs, pc, pfs)) {
316*7c478bd9Sstevel@tonic-gate 			ret = MDENYDEST;
317*7c478bd9Sstevel@tonic-gate 			goto Return;
318*7c478bd9Sstevel@tonic-gate 		}
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 		/* Is the printer allowing requests? */
321*7c478bd9Sstevel@tonic-gate 		if (!CHKACCEPT(prs, pps)) {
322*7c478bd9Sstevel@tonic-gate 			ret = MERRDEST;
323*7c478bd9Sstevel@tonic-gate 			goto Return;
324*7c478bd9Sstevel@tonic-gate 		}
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 		/* Is there a filter which will convert the input? */
327*7c478bd9Sstevel@tonic-gate 		if (!pickfilter(prs, pc, pfs)) {
328*7c478bd9Sstevel@tonic-gate 			ret = MNOFILTER;
329*7c478bd9Sstevel@tonic-gate 			goto Return;
330*7c478bd9Sstevel@tonic-gate 		}
331*7c478bd9Sstevel@tonic-gate 
332*7c478bd9Sstevel@tonic-gate 		best_pc = pc;
333*7c478bd9Sstevel@tonic-gate 		ret = MOK;
334*7c478bd9Sstevel@tonic-gate 		goto Return;
335*7c478bd9Sstevel@tonic-gate 	}
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 	/*
338*7c478bd9Sstevel@tonic-gate 	 * Do the acceptance check on the class (if we have one)
339*7c478bd9Sstevel@tonic-gate 	 * now so we can proceed with checks on individual printers
340*7c478bd9Sstevel@tonic-gate 	 * in the class. Don't toss out the request if it is already
341*7c478bd9Sstevel@tonic-gate 	 * assigned a printer just because the class is NOW rejecting.
342*7c478bd9Sstevel@tonic-gate 	 */
343*7c478bd9Sstevel@tonic-gate 	if (
344*7c478bd9Sstevel@tonic-gate 		pcs
345*7c478bd9Sstevel@tonic-gate 	     && (pcs->status & CS_REJECTED)
346*7c478bd9Sstevel@tonic-gate 	     && !moving
347*7c478bd9Sstevel@tonic-gate 	     && !prs->printer
348*7c478bd9Sstevel@tonic-gate 	) {
349*7c478bd9Sstevel@tonic-gate 		ret = MERRDEST;
350*7c478bd9Sstevel@tonic-gate 		goto Return;
351*7c478bd9Sstevel@tonic-gate 	}
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate 	/*
354*7c478bd9Sstevel@tonic-gate 	 * Construct a list of printers based on the destination
355*7c478bd9Sstevel@tonic-gate 	 * given. Cross off those that aren't accepting requests,
356*7c478bd9Sstevel@tonic-gate 	 * that can't take the form, or which the user can't use.
357*7c478bd9Sstevel@tonic-gate 	 * See if the list becomes empty.
358*7c478bd9Sstevel@tonic-gate 	 */
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	if (pcs)
361*7c478bd9Sstevel@tonic-gate 		n = lenlist(pcs->class->members);
362*7c478bd9Sstevel@tonic-gate 	else {
363*7c478bd9Sstevel@tonic-gate 		n = 0;
364*7c478bd9Sstevel@tonic-gate 		for (pps = walk_ptable(1); pps; pps = walk_ptable(0))
365*7c478bd9Sstevel@tonic-gate 			n++;
366*7c478bd9Sstevel@tonic-gate 	}
367*7c478bd9Sstevel@tonic-gate 	pcend = arena = (CANDIDATE *)Calloc(n, sizeof(CANDIDATE));
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate 	/*
370*7c478bd9Sstevel@tonic-gate 	 * Start with a list of printers that are accepting requests.
371*7c478bd9Sstevel@tonic-gate 	 * Don't skip a printer if it's rejecting but the request
372*7c478bd9Sstevel@tonic-gate 	 * has already been accepted for it.
373*7c478bd9Sstevel@tonic-gate 	 */
374*7c478bd9Sstevel@tonic-gate 	if (pcs) {
375*7c478bd9Sstevel@tonic-gate 		register char		 **pn;
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate 		for (pn = pcs->class->members; *pn; pn++)
378*7c478bd9Sstevel@tonic-gate 			if (
379*7c478bd9Sstevel@tonic-gate 				((pps = search_ptable(*pn)) != NULL)
380*7c478bd9Sstevel@tonic-gate 			     && pps != stop_pps
381*7c478bd9Sstevel@tonic-gate 			)
382*7c478bd9Sstevel@tonic-gate 				(pcend++)->pps = pps;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate 	} else
386*7c478bd9Sstevel@tonic-gate 		for (pps = walk_ptable(1); pps; pps = walk_ptable(0))
387*7c478bd9Sstevel@tonic-gate 			if (CHKACCEPT(prs, pps) && pps != stop_pps)
388*7c478bd9Sstevel@tonic-gate 				(pcend++)->pps = pps;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	if (pcend == arena) {
391*7c478bd9Sstevel@tonic-gate 		ret = MERRDEST;
392*7c478bd9Sstevel@tonic-gate 		goto Return;
393*7c478bd9Sstevel@tonic-gate 	}
394*7c478bd9Sstevel@tonic-gate 
395*7c478bd9Sstevel@tonic-gate 	/*
396*7c478bd9Sstevel@tonic-gate 	 * Clean out printers that the user can't use. We piggy-back
397*7c478bd9Sstevel@tonic-gate 	 * the pitch/size/banner checks here because the same error return
398*7c478bd9Sstevel@tonic-gate 	 * is given (strange, eh?).
399*7c478bd9Sstevel@tonic-gate 	 */
400*7c478bd9Sstevel@tonic-gate 	{
401*7c478bd9Sstevel@tonic-gate 		register CANDIDATE	*pcend2;
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 		for (pcend2 = pc = arena; pc < pcend; pc++) {
404*7c478bd9Sstevel@tonic-gate 			if (CHKU(prs, pc->pps) && CHKOPTS(prs, pc, pfs))
405*7c478bd9Sstevel@tonic-gate 				*pcend2++ = *pc;
406*7c478bd9Sstevel@tonic-gate 			else
407*7c478bd9Sstevel@tonic-gate 				free_candidate (pc);
408*7c478bd9Sstevel@tonic-gate 		}
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate 		if (pcend2 == arena) {
411*7c478bd9Sstevel@tonic-gate 			ret = MDENYDEST;
412*7c478bd9Sstevel@tonic-gate 			goto Return;
413*7c478bd9Sstevel@tonic-gate 		}
414*7c478bd9Sstevel@tonic-gate 		pcend = pcend2;
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 	}
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	/*
419*7c478bd9Sstevel@tonic-gate 	 * Clean out printers that can't mount the form,
420*7c478bd9Sstevel@tonic-gate 	 * EXCEPT for printers that already have it mounted:
421*7c478bd9Sstevel@tonic-gate 	 */
422*7c478bd9Sstevel@tonic-gate 	if (pfs) {
423*7c478bd9Sstevel@tonic-gate 		register CANDIDATE	*pcend2;
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate 		for (pcend2 = pc = arena; pc < pcend; pc++)
426*7c478bd9Sstevel@tonic-gate 			if (CHKF(pfs, pc->pps))
427*7c478bd9Sstevel@tonic-gate 				*pcend2++ = *pc;
428*7c478bd9Sstevel@tonic-gate 			else
429*7c478bd9Sstevel@tonic-gate 				free_candidate (pc);
430*7c478bd9Sstevel@tonic-gate 
431*7c478bd9Sstevel@tonic-gate 		if (pcend2 == arena) {
432*7c478bd9Sstevel@tonic-gate 			ret = MNOMOUNT;
433*7c478bd9Sstevel@tonic-gate 			goto Return;
434*7c478bd9Sstevel@tonic-gate 		}
435*7c478bd9Sstevel@tonic-gate 		pcend = pcend2;
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	}
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 	/*
440*7c478bd9Sstevel@tonic-gate 	 * Clean out printers that can't take the print wheel
441*7c478bd9Sstevel@tonic-gate 	 * EXCEPT for printers that already have it mounted
442*7c478bd9Sstevel@tonic-gate 	 * or printers for which it is a selectable character set:
443*7c478bd9Sstevel@tonic-gate 	 */
444*7c478bd9Sstevel@tonic-gate 	if (prs->request->charset) {
445*7c478bd9Sstevel@tonic-gate 		register CANDIDATE	*pcend2;
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 		for (pcend2 = pc = arena; pc < pcend; pc++)
448*7c478bd9Sstevel@tonic-gate 			if (CHKPW(prs->request->charset, pc->pps))
449*7c478bd9Sstevel@tonic-gate 				*pcend2++ = *pc;
450*7c478bd9Sstevel@tonic-gate 			else
451*7c478bd9Sstevel@tonic-gate 				free_candidate (pc);
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 		if (pcend2 == arena) {
454*7c478bd9Sstevel@tonic-gate 			ret = MNOMOUNT;
455*7c478bd9Sstevel@tonic-gate 			goto Return;
456*7c478bd9Sstevel@tonic-gate 		}
457*7c478bd9Sstevel@tonic-gate 		pcend = pcend2;
458*7c478bd9Sstevel@tonic-gate 
459*7c478bd9Sstevel@tonic-gate 	}
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 	/*
462*7c478bd9Sstevel@tonic-gate 	 * Clean out printers that can't handle the printing
463*7c478bd9Sstevel@tonic-gate 	 * and for which there's no filter to convert the input.
464*7c478bd9Sstevel@tonic-gate 	 *
465*7c478bd9Sstevel@tonic-gate 	 */
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 	/*
468*7c478bd9Sstevel@tonic-gate 	 * Is the form mounted, or is none needed?
469*7c478bd9Sstevel@tonic-gate 	 */
470*7c478bd9Sstevel@tonic-gate #define CHKFMNT(PFS,PPS) (isFormUsableOnPrinter(PPS,PFS))
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 	/*
473*7c478bd9Sstevel@tonic-gate 	 * Is the print-wheel mounted, or is none needed?
474*7c478bd9Sstevel@tonic-gate 	 */
475*7c478bd9Sstevel@tonic-gate #define CHKPWMNT(PRS,PPS) SAME((PPS)->pwheel_name, (PRS)->request->charset)
476*7c478bd9Sstevel@tonic-gate 
477*7c478bd9Sstevel@tonic-gate 	/*
478*7c478bd9Sstevel@tonic-gate 	 * Do we NOT need a special character set, or can we select
479*7c478bd9Sstevel@tonic-gate 	 * it on the printer? Note: Getting this far means that IF
480*7c478bd9Sstevel@tonic-gate 	 * the printer has selectable character sets (!daisy) then
481*7c478bd9Sstevel@tonic-gate 	 * it can select the one we want.
482*7c478bd9Sstevel@tonic-gate 	 */
483*7c478bd9Sstevel@tonic-gate #define CHKCHSET(PRS,PPS) \
484*7c478bd9Sstevel@tonic-gate 	( \
485*7c478bd9Sstevel@tonic-gate 		!(PRS)->request->charset \
486*7c478bd9Sstevel@tonic-gate 	     || !(PPS)->printer->daisy \
487*7c478bd9Sstevel@tonic-gate 	)
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	/*
490*7c478bd9Sstevel@tonic-gate 	 * Is the printer able to print now?
491*7c478bd9Sstevel@tonic-gate 	 */
492*7c478bd9Sstevel@tonic-gate #define CHKENB(PPS)	 (!((PPS)->status & (PS_DISABLED|PS_FAULTED)))
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate 	/*
495*7c478bd9Sstevel@tonic-gate 	 * Is the printer not busy printing another request, or
496*7c478bd9Sstevel@tonic-gate 	 * not awaiting an auto-retry after a fault?
497*7c478bd9Sstevel@tonic-gate 	 */
498*7c478bd9Sstevel@tonic-gate #define CHKFREE(PPS)	 (!((PPS)->status & (PS_BUSY|PS_LATER)))
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 	/*
501*7c478bd9Sstevel@tonic-gate 	 * Is the printer local?
502*7c478bd9Sstevel@tonic-gate 	 */
503*7c478bd9Sstevel@tonic-gate #define CHKLOCAL(PPS)	 (!((PPS)->status & (PS_REMOTE)))
504*7c478bd9Sstevel@tonic-gate 
505*7c478bd9Sstevel@tonic-gate 	{
506*7c478bd9Sstevel@tonic-gate 		register CANDIDATE	*pcend2;
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 		for (pcend2 = pc = arena; pc < pcend; pc++)
509*7c478bd9Sstevel@tonic-gate 			if (pickfilter(prs, pc, pfs)) {
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate 				/*
512*7c478bd9Sstevel@tonic-gate 				 * Compute a ``weight'' for this printer,
513*7c478bd9Sstevel@tonic-gate 				 * based on its status. We'll later pick
514*7c478bd9Sstevel@tonic-gate 				 * the printer with the highest weight.
515*7c478bd9Sstevel@tonic-gate 				 */
516*7c478bd9Sstevel@tonic-gate 				pc->weight = 0;
517*7c478bd9Sstevel@tonic-gate 				if (!pc->fast && !pc->slow)
518*7c478bd9Sstevel@tonic-gate 					pc->weight += WEIGHT_NOFILTER;
519*7c478bd9Sstevel@tonic-gate 				if (CHKFREE(pc->pps))
520*7c478bd9Sstevel@tonic-gate 					pc->weight += WEIGHT_FREE;
521*7c478bd9Sstevel@tonic-gate 				if (CHKENB(pc->pps))
522*7c478bd9Sstevel@tonic-gate 					pc->weight += WEIGHT_ENABLED;
523*7c478bd9Sstevel@tonic-gate 				if (CHKFMNT(pfs, pc->pps))
524*7c478bd9Sstevel@tonic-gate 					pc->weight += WEIGHT_MOUNTED;
525*7c478bd9Sstevel@tonic-gate 				if (CHKPWMNT(prs, pc->pps))
526*7c478bd9Sstevel@tonic-gate 					pc->weight += WEIGHT_MOUNTED;
527*7c478bd9Sstevel@tonic-gate 				if (CHKCHSET(prs, pc->pps))
528*7c478bd9Sstevel@tonic-gate 					pc->weight += WEIGHT_SELECTS;
529*7c478bd9Sstevel@tonic-gate 				if (CHKLOCAL(pc->pps))
530*7c478bd9Sstevel@tonic-gate 					pc->weight += WEIGHT_LOCAL;
531*7c478bd9Sstevel@tonic-gate 
532*7c478bd9Sstevel@tonic-gate #if	defined(FILTER_EARLY_OUT)
533*7c478bd9Sstevel@tonic-gate 				if (pc->weight == WEIGHT_MAX) {
534*7c478bd9Sstevel@tonic-gate 					/*
535*7c478bd9Sstevel@tonic-gate 					 * This is the one!
536*7c478bd9Sstevel@tonic-gate 					 */
537*7c478bd9Sstevel@tonic-gate 					best_pc = pc;
538*7c478bd9Sstevel@tonic-gate 					ret = MOK;
539*7c478bd9Sstevel@tonic-gate 					goto Return;
540*7c478bd9Sstevel@tonic-gate 				}
541*7c478bd9Sstevel@tonic-gate #endif
542*7c478bd9Sstevel@tonic-gate 				/*
543*7c478bd9Sstevel@tonic-gate 				 * This is a candidate!
544*7c478bd9Sstevel@tonic-gate 				 */
545*7c478bd9Sstevel@tonic-gate 				*pcend2++ = *pc;
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 			} else
548*7c478bd9Sstevel@tonic-gate 				/*
549*7c478bd9Sstevel@tonic-gate 				 * No filter for this one!
550*7c478bd9Sstevel@tonic-gate 				 */
551*7c478bd9Sstevel@tonic-gate 				free_candidate (pc);
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate 		if (pcend2 == arena) {
554*7c478bd9Sstevel@tonic-gate 			ret = MNOFILTER;
555*7c478bd9Sstevel@tonic-gate 			goto Return;
556*7c478bd9Sstevel@tonic-gate 		}
557*7c478bd9Sstevel@tonic-gate 		pcend = pcend2;
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate 	}
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate 	if (pcend - arena == 1) {
562*7c478bd9Sstevel@tonic-gate 		best_pc = arena;
563*7c478bd9Sstevel@tonic-gate 		ret = MOK;
564*7c478bd9Sstevel@tonic-gate 		goto Return;
565*7c478bd9Sstevel@tonic-gate 	}
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate #if	defined(OTHER_FACTORS)
568*7c478bd9Sstevel@tonic-gate 	/*
569*7c478bd9Sstevel@tonic-gate 	 * Here you might want to add code that considers
570*7c478bd9Sstevel@tonic-gate 	 * other factors: the size of the file(s) to be
571*7c478bd9Sstevel@tonic-gate 	 * printed ("prs->secure->size") in relation to the
572*7c478bd9Sstevel@tonic-gate 	 * printer (e.g. printer A gets mostly large
573*7c478bd9Sstevel@tonic-gate 	 * files, printer B gets mostly small files); the
574*7c478bd9Sstevel@tonic-gate 	 * number/total-size of requests currently queued
575*7c478bd9Sstevel@tonic-gate 	 * for the printer; etc.
576*7c478bd9Sstevel@tonic-gate 	 *
577*7c478bd9Sstevel@tonic-gate 	 * If your code includes eliminating printers drop them
578*7c478bd9Sstevel@tonic-gate 	 * from the list (as done in several places above).
579*7c478bd9Sstevel@tonic-gate 	 * Otherwise, your code should add weights to the weight
580*7c478bd9Sstevel@tonic-gate 	 * already computed. Change the WEIGHT_MAX, increase the
581*7c478bd9Sstevel@tonic-gate 	 * other WEIGHT_X values to compensate, etc., as appropriate.
582*7c478bd9Sstevel@tonic-gate 	 */
583*7c478bd9Sstevel@tonic-gate 	;
584*7c478bd9Sstevel@tonic-gate #endif
585*7c478bd9Sstevel@tonic-gate 
586*7c478bd9Sstevel@tonic-gate 	/*
587*7c478bd9Sstevel@tonic-gate 	 * Pick the best printer from a list of eligible candidates.
588*7c478bd9Sstevel@tonic-gate 	 */
589*7c478bd9Sstevel@tonic-gate 	best_pc = arena;
590*7c478bd9Sstevel@tonic-gate 	for (pc = arena + 1; pc < pcend; pc++)
591*7c478bd9Sstevel@tonic-gate 		if (pc->weight > best_pc->weight)
592*7c478bd9Sstevel@tonic-gate 			best_pc = pc;
593*7c478bd9Sstevel@tonic-gate 	ret = MOK;
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 	/*
596*7c478bd9Sstevel@tonic-gate 	 * Branch to here if MOK and/or if things have been allocated.
597*7c478bd9Sstevel@tonic-gate 	 */
598*7c478bd9Sstevel@tonic-gate Return:	if (ret == MOK) {
599*7c478bd9Sstevel@tonic-gate 		register USER		*pu = Getuser(prs->secure->user);
600*7c478bd9Sstevel@tonic-gate 
601*7c478bd9Sstevel@tonic-gate 		register char		*pwheel_name;
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 		PSTATUS			*oldpps = prs->printer;
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 		/*
607*7c478bd9Sstevel@tonic-gate 		 * We are going to accept this print request, having
608*7c478bd9Sstevel@tonic-gate 		 * found a printer for it. This printer will be assigned
609*7c478bd9Sstevel@tonic-gate 		 * to the request, although this assignment may be
610*7c478bd9Sstevel@tonic-gate 		 * temporary if other printers qualify and this printer
611*7c478bd9Sstevel@tonic-gate 		 * is changed to no longer qualify. Qualification in
612*7c478bd9Sstevel@tonic-gate 		 * this context includes being ready to print!
613*7c478bd9Sstevel@tonic-gate 		 */
614*7c478bd9Sstevel@tonic-gate 		prs->printer = best_pc->pps;
615*7c478bd9Sstevel@tonic-gate 		load_str (&(prs->printer_type), best_pc->printer_type);
616*7c478bd9Sstevel@tonic-gate 
617*7c478bd9Sstevel@tonic-gate 		/*
618*7c478bd9Sstevel@tonic-gate 		 * Assign the form (if any) to the request. Adjust
619*7c478bd9Sstevel@tonic-gate 		 * the number of requests queued for old and new form
620*7c478bd9Sstevel@tonic-gate 		 * accordingly.
621*7c478bd9Sstevel@tonic-gate 		 */
622*7c478bd9Sstevel@tonic-gate 		if (prs->form != pfs) {
623*7c478bd9Sstevel@tonic-gate 			unqueue_form (prs);
624*7c478bd9Sstevel@tonic-gate 			queue_form (prs, pfs);
625*7c478bd9Sstevel@tonic-gate 		}
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate 		/*
628*7c478bd9Sstevel@tonic-gate 		 * Ditto for the print wheel, except include here the
629*7c478bd9Sstevel@tonic-gate 		 * print wheel needed by the form.
630*7c478bd9Sstevel@tonic-gate 		 * CAUTION: When checking this request later, don't
631*7c478bd9Sstevel@tonic-gate 		 * refuse to service it if the print wheel for the
632*7c478bd9Sstevel@tonic-gate 		 * form isn't mounted but the form is; a mounted form
633*7c478bd9Sstevel@tonic-gate 		 * overrides its other needs. Don't be confused by the
634*7c478bd9Sstevel@tonic-gate 		 * name of the bit, RSS_PWMAND; a printer that prints
635*7c478bd9Sstevel@tonic-gate 		 * this request MUST have the print wheel mounted
636*7c478bd9Sstevel@tonic-gate 		 * (if it takes print wheels) if the user asked for
637*7c478bd9Sstevel@tonic-gate 		 * a particular print wheel.
638*7c478bd9Sstevel@tonic-gate 		 */
639*7c478bd9Sstevel@tonic-gate 		prs->status &= ~RSS_PWMAND;
640*7c478bd9Sstevel@tonic-gate 		if (CHKMAND(pfs))
641*7c478bd9Sstevel@tonic-gate 			pwheel_name = pfs->form->chset;
642*7c478bd9Sstevel@tonic-gate 		else
643*7c478bd9Sstevel@tonic-gate 			if ((pwheel_name = prs->request->charset) != NULL)
644*7c478bd9Sstevel@tonic-gate 				prs->status |= RSS_PWMAND;
645*7c478bd9Sstevel@tonic-gate 
646*7c478bd9Sstevel@tonic-gate 		if (!SAME(pwheel_name, prs->pwheel_name)) {
647*7c478bd9Sstevel@tonic-gate 			unqueue_pwheel (prs);
648*7c478bd9Sstevel@tonic-gate 			queue_pwheel (prs, pwheel_name);
649*7c478bd9Sstevel@tonic-gate 		}
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 		/*
652*7c478bd9Sstevel@tonic-gate 		 * Adjust the priority to lie within the limits allowed
653*7c478bd9Sstevel@tonic-gate 		 * for the user (this is a silent adjustment as required).
654*7c478bd9Sstevel@tonic-gate 		 * CURRENTLY, ONLY NEW REQUESTS WILL GET QUEUED ACCORDING
655*7c478bd9Sstevel@tonic-gate 		 * TO THIS PRIORITY. EXISTING REQUESTS BEING (RE)EVALUATED
656*7c478bd9Sstevel@tonic-gate 		 * WILL NOT BE REQUEUED.
657*7c478bd9Sstevel@tonic-gate 		 * A wild priority is changed to the default, or the
658*7c478bd9Sstevel@tonic-gate 		 * limit, whichever is the lower priority (higher value).
659*7c478bd9Sstevel@tonic-gate 		 */
660*7c478bd9Sstevel@tonic-gate 		if (prs->request->priority < 0 || 39 < prs->request->priority)
661*7c478bd9Sstevel@tonic-gate 			prs->request->priority = getdfltpri();
662*7c478bd9Sstevel@tonic-gate 		if (pu && prs->request->priority < pu->priority_limit)
663*7c478bd9Sstevel@tonic-gate 			prs->request->priority = pu->priority_limit;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 		/*
666*7c478bd9Sstevel@tonic-gate 		 * If a filter is involved, change the number of
667*7c478bd9Sstevel@tonic-gate 		 * copies to 1 (if the filter handles it).
668*7c478bd9Sstevel@tonic-gate 		 */
669*7c478bd9Sstevel@tonic-gate 		if (
670*7c478bd9Sstevel@tonic-gate 			(best_pc->fast || best_pc->slow)
671*7c478bd9Sstevel@tonic-gate 		     && (best_pc->flags & FPARM_COPIES)
672*7c478bd9Sstevel@tonic-gate 		     && prs->request->copies > 1
673*7c478bd9Sstevel@tonic-gate 		)
674*7c478bd9Sstevel@tonic-gate 			prs->copies = 1;
675*7c478bd9Sstevel@tonic-gate 		else
676*7c478bd9Sstevel@tonic-gate 			/*
677*7c478bd9Sstevel@tonic-gate 			 * We use two ".copies" because we don't
678*7c478bd9Sstevel@tonic-gate 			 * want to lose track of the number requested,
679*7c478bd9Sstevel@tonic-gate 			 * but do want to mark the number the interface
680*7c478bd9Sstevel@tonic-gate 			 * program is to handle. Here is the best
681*7c478bd9Sstevel@tonic-gate 			 * place to know this.
682*7c478bd9Sstevel@tonic-gate 			 */
683*7c478bd9Sstevel@tonic-gate 			prs->copies = prs->request->copies;
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 		if (best_pc->slow) {
686*7c478bd9Sstevel@tonic-gate 			/*
687*7c478bd9Sstevel@tonic-gate 			 * If the filter has changed, the request will
688*7c478bd9Sstevel@tonic-gate 			 * have to be refiltered. This may mean stopping
689*7c478bd9Sstevel@tonic-gate 			 * a currently running filter or interface.
690*7c478bd9Sstevel@tonic-gate 			 */
691*7c478bd9Sstevel@tonic-gate 			if (!SAME(best_pc->slow, prs->slow)) {
692*7c478bd9Sstevel@tonic-gate 
693*7c478bd9Sstevel@tonic-gate 			    if (prs->request->outcome & RS_FILTERED)
694*7c478bd9Sstevel@tonic-gate 				prs->request->outcome &= ~RS_FILTERED;
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 			    if (
697*7c478bd9Sstevel@tonic-gate 				prs->request->outcome & RS_FILTERING
698*7c478bd9Sstevel@tonic-gate 			     && !(prs->request->outcome & RS_STOPPED)
699*7c478bd9Sstevel@tonic-gate 			    ) {
700*7c478bd9Sstevel@tonic-gate 				prs->request->outcome |= RS_REFILTER;
701*7c478bd9Sstevel@tonic-gate 				prs->request->outcome |= RS_STOPPED;
702*7c478bd9Sstevel@tonic-gate 				terminate (prs->exec);
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 			    } else if (
705*7c478bd9Sstevel@tonic-gate 				prs->request->outcome & RS_PRINTING
706*7c478bd9Sstevel@tonic-gate 			     && !(prs->request->outcome & RS_STOPPED)
707*7c478bd9Sstevel@tonic-gate 			    ) {
708*7c478bd9Sstevel@tonic-gate 				prs->request->outcome |= RS_STOPPED;
709*7c478bd9Sstevel@tonic-gate 				terminate (oldpps->exec);
710*7c478bd9Sstevel@tonic-gate 			    }
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 			}
713*7c478bd9Sstevel@tonic-gate 
714*7c478bd9Sstevel@tonic-gate 			load_str (&(prs->slow), best_pc->slow);
715*7c478bd9Sstevel@tonic-gate 			/* Assumption: if there is a slow filter,
716*7c478bd9Sstevel@tonic-gate 			 * there is an output_type
717*7c478bd9Sstevel@tonic-gate 			 */
718*7c478bd9Sstevel@tonic-gate 
719*7c478bd9Sstevel@tonic-gate 			load_str (&(prs->output_type), best_pc->output_type);
720*7c478bd9Sstevel@tonic-gate 		} else
721*7c478bd9Sstevel@tonic-gate 			unload_str (&(prs->slow));
722*7c478bd9Sstevel@tonic-gate 
723*7c478bd9Sstevel@tonic-gate 		load_str (&(prs->fast), best_pc->fast);
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 		if (prs->request->actions & ACT_FAST && prs->slow) {
726*7c478bd9Sstevel@tonic-gate 			if (prs->fast) {
727*7c478bd9Sstevel@tonic-gate 				prs->fast = makestr(
728*7c478bd9Sstevel@tonic-gate 					prs->slow,
729*7c478bd9Sstevel@tonic-gate 					"|",
730*7c478bd9Sstevel@tonic-gate 					prs->fast,
731*7c478bd9Sstevel@tonic-gate 					(char *)0
732*7c478bd9Sstevel@tonic-gate 				);
733*7c478bd9Sstevel@tonic-gate 				Free (prs->slow);
734*7c478bd9Sstevel@tonic-gate 			} else
735*7c478bd9Sstevel@tonic-gate 				prs->fast = prs->slow;
736*7c478bd9Sstevel@tonic-gate 			prs->slow = 0;
737*7c478bd9Sstevel@tonic-gate 		}
738*7c478bd9Sstevel@tonic-gate 
739*7c478bd9Sstevel@tonic-gate 	}
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate 
742*7c478bd9Sstevel@tonic-gate 	/*
743*7c478bd9Sstevel@tonic-gate 	 * Free the space allocated for the candidates, INCLUDING
744*7c478bd9Sstevel@tonic-gate 	 * the one chosen. Any allocated space in the chosen candidate
745*7c478bd9Sstevel@tonic-gate 	 * that has to be saved should have been COPIED already.
746*7c478bd9Sstevel@tonic-gate 	 */
747*7c478bd9Sstevel@tonic-gate 	if (arena) {
748*7c478bd9Sstevel@tonic-gate 		for (pc = arena; pc < pcend; pc++)
749*7c478bd9Sstevel@tonic-gate 			free_candidate (pc);
750*7c478bd9Sstevel@tonic-gate 		Free ((char *)arena);
751*7c478bd9Sstevel@tonic-gate 	} else if (best_pc)
752*7c478bd9Sstevel@tonic-gate 		free_candidate (best_pc);
753*7c478bd9Sstevel@tonic-gate 
754*7c478bd9Sstevel@tonic-gate 	if (o_length)
755*7c478bd9Sstevel@tonic-gate 		Free (o_length);
756*7c478bd9Sstevel@tonic-gate 	if (o_width)
757*7c478bd9Sstevel@tonic-gate 		Free (o_width);
758*7c478bd9Sstevel@tonic-gate 	if (o_lpi)
759*7c478bd9Sstevel@tonic-gate 		Free (o_lpi);
760*7c478bd9Sstevel@tonic-gate 	if (o_cpi)
761*7c478bd9Sstevel@tonic-gate 		Free (o_cpi);
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate 
764*7c478bd9Sstevel@tonic-gate 	/*
765*7c478bd9Sstevel@tonic-gate 	 * The following value is valid ONLY IF the request
766*7c478bd9Sstevel@tonic-gate 	 * is canceled or rejected. Not all requests that
767*7c478bd9Sstevel@tonic-gate 	 * we fail in this routine are tossed out!
768*7c478bd9Sstevel@tonic-gate 	 */
769*7c478bd9Sstevel@tonic-gate 	prs->reason = ret;
770*7c478bd9Sstevel@tonic-gate 
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 	return (ret);
773*7c478bd9Sstevel@tonic-gate }
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate /**
776*7c478bd9Sstevel@tonic-gate  ** _chkopts() - CHECK -o OPTIONS
777*7c478bd9Sstevel@tonic-gate  **/
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate static int
780*7c478bd9Sstevel@tonic-gate _chkopts(RSTATUS *prs, CANDIDATE *pc, FSTATUS *pfs)
781*7c478bd9Sstevel@tonic-gate {
782*7c478bd9Sstevel@tonic-gate 	unsigned long		ret	= 0;
783*7c478bd9Sstevel@tonic-gate 	unsigned long		chk	= 0;
784*7c478bd9Sstevel@tonic-gate 
785*7c478bd9Sstevel@tonic-gate 	char *			charset;
786*7c478bd9Sstevel@tonic-gate 	char *			cpi	= 0;
787*7c478bd9Sstevel@tonic-gate 	char *			lpi	= 0;
788*7c478bd9Sstevel@tonic-gate 	char *			width	= 0;
789*7c478bd9Sstevel@tonic-gate 	char *			length	= 0;
790*7c478bd9Sstevel@tonic-gate 	char *			paper = NULL;
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 	char **			pt;
793*7c478bd9Sstevel@tonic-gate 
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	/*
796*7c478bd9Sstevel@tonic-gate 	 * If we have a form, it overrides whatever print characteristics
797*7c478bd9Sstevel@tonic-gate 	 * the user gave.
798*7c478bd9Sstevel@tonic-gate 	 */
799*7c478bd9Sstevel@tonic-gate 	if (pfs) {
800*7c478bd9Sstevel@tonic-gate 		cpi = pfs->cpi;
801*7c478bd9Sstevel@tonic-gate 		lpi = pfs->lpi;
802*7c478bd9Sstevel@tonic-gate 		width = pfs->pwid;
803*7c478bd9Sstevel@tonic-gate 		length = pfs->plen;
804*7c478bd9Sstevel@tonic-gate 		paper = pfs->form->paper;
805*7c478bd9Sstevel@tonic-gate 	} else {
806*7c478bd9Sstevel@tonic-gate 		cpi = o_cpi;
807*7c478bd9Sstevel@tonic-gate 		lpi = o_lpi;
808*7c478bd9Sstevel@tonic-gate 		width = o_width;
809*7c478bd9Sstevel@tonic-gate 		length = o_length;
810*7c478bd9Sstevel@tonic-gate 	}
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate 	/*
813*7c478bd9Sstevel@tonic-gate 	 * If the printer takes print wheels, or the character set
814*7c478bd9Sstevel@tonic-gate 	 * the user wants is listed in the character set map for this
815*7c478bd9Sstevel@tonic-gate 	 * printer, we needn't check if the printer can handle the
816*7c478bd9Sstevel@tonic-gate 	 * character set. (Note: The check for the print wheel case
817*7c478bd9Sstevel@tonic-gate 	 * is done elsewhere.)
818*7c478bd9Sstevel@tonic-gate 	 */
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 	if (pc->pps->printer->daisy ||
821*7c478bd9Sstevel@tonic-gate 	    search_cslist(prs->request->charset, pc->pps->printer->char_sets))
822*7c478bd9Sstevel@tonic-gate 		charset = 0;
823*7c478bd9Sstevel@tonic-gate 	else
824*7c478bd9Sstevel@tonic-gate 		charset = prs->request->charset;
825*7c478bd9Sstevel@tonic-gate 
826*7c478bd9Sstevel@tonic-gate 	pc->printer_types = 0;
827*7c478bd9Sstevel@tonic-gate 	for (pt = pc->pps->printer->printer_types; *pt; pt++) {
828*7c478bd9Sstevel@tonic-gate 		unsigned long		this;
829*7c478bd9Sstevel@tonic-gate 
830*7c478bd9Sstevel@tonic-gate 		if (paper) {
831*7c478bd9Sstevel@tonic-gate 			if (allowed(paper,pc->pps->paper_allowed,NULL)) {
832*7c478bd9Sstevel@tonic-gate 				addlist (&(pc->printer_types), *pt);
833*7c478bd9Sstevel@tonic-gate 			} else {
834*7c478bd9Sstevel@tonic-gate 				ret |= PCK_PAPER;
835*7c478bd9Sstevel@tonic-gate 			}
836*7c478bd9Sstevel@tonic-gate 		} else {
837*7c478bd9Sstevel@tonic-gate 			this = chkprinter(*pt, cpi, lpi, length, width,
838*7c478bd9Sstevel@tonic-gate 				charset);
839*7c478bd9Sstevel@tonic-gate 			if (this == 0)
840*7c478bd9Sstevel@tonic-gate 				addlist(&(pc->printer_types), *pt);
841*7c478bd9Sstevel@tonic-gate 			chk |= this;
842*7c478bd9Sstevel@tonic-gate 		}
843*7c478bd9Sstevel@tonic-gate 	}
844*7c478bd9Sstevel@tonic-gate 	if (!pc->printer_types)
845*7c478bd9Sstevel@tonic-gate 		ret |= chk;
846*7c478bd9Sstevel@tonic-gate 
847*7c478bd9Sstevel@tonic-gate 	if (pc->pps->printer->banner == BAN_ALWAYS) {
848*7c478bd9Sstevel@tonic-gate 		if ((wants_nobanner == 1) && (lp_or_root != 1)) {
849*7c478bd9Sstevel@tonic-gate 			/* delete "nobanner" */
850*7c478bd9Sstevel@tonic-gate 			char **list;
851*7c478bd9Sstevel@tonic-gate 
852*7c478bd9Sstevel@tonic-gate 			if (prs->request->options &&
853*7c478bd9Sstevel@tonic-gate 			    (list = dashos(prs->request->options))) {
854*7c478bd9Sstevel@tonic-gate 				dellist(&list, "nobanner");
855*7c478bd9Sstevel@tonic-gate 				free(prs->request->options);
856*7c478bd9Sstevel@tonic-gate 				prs->request->options = sprintlist(list);
857*7c478bd9Sstevel@tonic-gate 			}
858*7c478bd9Sstevel@tonic-gate 		}
859*7c478bd9Sstevel@tonic-gate 	} else if (pc->pps->printer->banner == BAN_NEVER) {
860*7c478bd9Sstevel@tonic-gate 		if (wants_nobanner == 0) {
861*7c478bd9Sstevel@tonic-gate 			/* add "nobanner" */
862*7c478bd9Sstevel@tonic-gate 			char **list = NULL;
863*7c478bd9Sstevel@tonic-gate 
864*7c478bd9Sstevel@tonic-gate 			if (prs->request->options) {
865*7c478bd9Sstevel@tonic-gate 				list = dashos(prs->request->options);
866*7c478bd9Sstevel@tonic-gate 				free(prs->request->options);
867*7c478bd9Sstevel@tonic-gate 			}
868*7c478bd9Sstevel@tonic-gate 			appendlist(&list, "nobanner");
869*7c478bd9Sstevel@tonic-gate 			prs->request->options = sprintlist(list);
870*7c478bd9Sstevel@tonic-gate 		}
871*7c478bd9Sstevel@tonic-gate 	} else /* if (pc->pps->printer->banner == BAN_OPTIONAL) */ {
872*7c478bd9Sstevel@tonic-gate 		/* it is optional, leave it alone */
873*7c478bd9Sstevel@tonic-gate 	}
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate 	chkprinter_result |= ret;
876*7c478bd9Sstevel@tonic-gate 	return (ret == 0);
877*7c478bd9Sstevel@tonic-gate }
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate /**
880*7c478bd9Sstevel@tonic-gate  ** free_candidate()
881*7c478bd9Sstevel@tonic-gate  **/
882*7c478bd9Sstevel@tonic-gate 
883*7c478bd9Sstevel@tonic-gate static void
884*7c478bd9Sstevel@tonic-gate free_candidate(CANDIDATE *pc)
885*7c478bd9Sstevel@tonic-gate {
886*7c478bd9Sstevel@tonic-gate 	if (pc->slow)
887*7c478bd9Sstevel@tonic-gate 		unload_str (&(pc->slow));
888*7c478bd9Sstevel@tonic-gate 	if (pc->fast)
889*7c478bd9Sstevel@tonic-gate 		unload_str (&(pc->fast));
890*7c478bd9Sstevel@tonic-gate 	if (pc->printer_types) {
891*7c478bd9Sstevel@tonic-gate 		freelist (pc->printer_types);
892*7c478bd9Sstevel@tonic-gate 		pc->printer_types = 0;
893*7c478bd9Sstevel@tonic-gate 	}
894*7c478bd9Sstevel@tonic-gate 	if (pc->printer_type)
895*7c478bd9Sstevel@tonic-gate 		unload_str (&(pc->printer_type));
896*7c478bd9Sstevel@tonic-gate 	if (pc->output_type)
897*7c478bd9Sstevel@tonic-gate 		unload_str (&(pc->output_type));
898*7c478bd9Sstevel@tonic-gate 	return;
899*7c478bd9Sstevel@tonic-gate }
900