1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
27/*	  All Rights Reserved  	*/
28
29
30#include "time.h"
31#include "dispatch.h"
32#include <syslog.h>
33
34
35/**
36 ** s_accept_dest()
37 **/
38
39void
40s_accept_dest(char *m, MESG *md)
41{
42	char			*destination;
43	ushort			status;
44	register PSTATUS	*pps;
45	register CLSTATUS	*pcs;
46
47	getmessage (m, S_ACCEPT_DEST, &destination);
48	syslog(LOG_DEBUG, "s_accept_dest(%s)",
49	       (destination ? destination : "NULL"));
50
51	/*
52	 * Have we seen this destination as a printer?
53	 */
54	if ((pps = search_pstatus(destination)))
55		if ((pps->status & PS_REJECTED) == 0)
56			status = MERRDEST;
57		else {
58			pps->status &= ~PS_REJECTED;
59			(void) time (&pps->rej_date);
60			dump_pstatus ();
61			status = MOK;
62		}
63
64	/*
65	 * Have we seen this destination as a class?
66	 */
67	else if ((pcs = search_cstatus(destination)))
68		if ((pcs->status & CS_REJECTED) == 0)
69			status = MERRDEST;
70		else {
71			pcs->status &= ~CS_REJECTED;
72			(void) time (&pcs->rej_date);
73			dump_cstatus ();
74			status = MOK;
75		}
76
77	else
78		status = MNODEST;
79
80	mputm (md, R_ACCEPT_DEST, status);
81	return;
82}
83
84/**
85 ** s_reject_dest()
86 **/
87
88void
89s_reject_dest(char *m, MESG *md)
90{
91	char			*destination,
92				*reason;
93	ushort			status;
94	register PSTATUS	*pps;
95	register CLSTATUS	*pcs;
96
97
98	getmessage (m, S_REJECT_DEST, &destination, &reason);
99	syslog(LOG_DEBUG, "s_reject_dest(%s, %s)",
100	       (destination ? destination : "NULL"),
101	       (reason ? reason : "NULL"));
102
103	/*
104	 * Have we seen this destination as a printer?
105	 */
106	if ((pps = search_pstatus(destination)))
107		if (pps->status & PS_REJECTED)
108			status = MERRDEST;
109		else {
110			pps->status |= PS_REJECTED;
111			(void) time (&pps->rej_date);
112			load_str (&pps->rej_reason, reason);
113			dump_pstatus ();
114			status = MOK;
115		}
116
117	/*
118	 * Have we seen this destination as a class?
119	 */
120	else if ((pcs = search_cstatus(destination)))
121		if (pcs->status & CS_REJECTED)
122			status = MERRDEST;
123		else {
124			pcs->status |= CS_REJECTED;
125			(void) time (&pcs->rej_date);
126			load_str (&pcs->rej_reason, reason);
127			dump_cstatus ();
128			status = MOK;
129		}
130
131	else
132		status = MNODEST;
133
134	mputm (md, R_REJECT_DEST, status);
135	return;
136}
137
138/**
139 ** s_enable_dest()
140 **/
141
142void
143s_enable_dest(char *m, MESG *md)
144{
145	char			*printer;
146	ushort			status;
147	register PSTATUS	*pps;
148
149
150	getmessage (m, S_ENABLE_DEST, &printer);
151	syslog(LOG_DEBUG, "s_enable_dest(%s)", (printer ? printer : "NULL"));
152
153	/*
154	 * Have we seen this printer before?
155	 */
156	if ((pps = search_pstatus(printer)))
157		if (enable(pps) == -1)
158			status = MERRDEST;
159		else
160			status = MOK;
161	else
162		status = MNODEST;
163
164	mputm (md, R_ENABLE_DEST, status);
165	return;
166}
167
168/**
169 ** s_disable_dest()
170 **/
171
172void
173s_disable_dest(char *m, MESG *md)
174{
175	char			*destination,
176				*reason,
177				*req_id		= 0;
178	ushort			when,
179				status;
180	register PSTATUS	*pps;
181
182	getmessage (m, S_DISABLE_DEST, &destination, &reason, &when);
183	syslog(LOG_DEBUG, "s_disable_dest(%s, %s, %d)",
184	       (destination ? destination : "NULL"),
185	       (reason ? reason : "NULL"), when);
186
187
188	/*
189	 * Have we seen this printer before?
190	 */
191	if ((pps = search_pstatus(destination))) {
192
193		/*
194		 * If we are to cancel a currently printing request,
195		 * we will send back the request's ID.
196		 * Save a copy of the ID before calling "disable()",
197		 * in case the disabling loses it (e.g. the request
198		 * might get attached to another printer). (Actually,
199		 * the current implementation won't DETACH the request
200		 * from this printer until the child process responds,
201		 * but a future implementation might.)
202		 */
203		if (pps->request && when == 2)
204			req_id = Strdup(pps->request->secure->req_id);
205
206		if (disable(pps, reason, (int)when) == -1) {
207			if (req_id) {
208				Free (req_id);
209				req_id = 0;
210			}
211			status = MERRDEST;
212		} else
213			status = MOK;
214
215	} else
216		status = MNODEST;
217
218	mputm (md, R_DISABLE_DEST, status, NB(req_id));
219	if (req_id)
220		Free (req_id);
221
222	return;
223}
224
225/**
226 ** s_load_filter_table()
227 **/
228
229void
230s_load_filter_table(char *m, MESG *md)
231{
232	ushort			status;
233
234	syslog(LOG_DEBUG, "s_load_filter_table()");
235
236	trash_filters ();
237	if (Loadfilters((char *)0) == -1)
238		status = MNOOPEN;
239	else {
240		/*
241		 * This is what makes changing filters expensive!
242		 */
243		queue_check (qchk_filter);
244
245		status = MOK;
246	}
247
248	mputm (md, R_LOAD_FILTER_TABLE, status);
249	return;
250}
251
252/**
253 ** s_unload_filter_table()
254 **/
255
256void
257s_unload_filter_table(char *m, MESG *md)
258{
259	syslog(LOG_DEBUG, "s_unload_filter_table()");
260
261	trash_filters ();
262
263	/*
264	 * This is what makes changing filters expensive!
265	 */
266	queue_check (qchk_filter);
267
268	mputm (md, R_UNLOAD_FILTER_TABLE, MOK);
269	return;
270}
271
272/**
273 ** s_load_user_file()
274 **/
275
276void
277s_load_user_file(char *m, MESG *md)
278{
279	/*
280	 * The first call to "getuser()" will load the whole file.
281	 */
282	syslog(LOG_DEBUG, "s_load_user_file()");
283
284	trashusers ();
285
286	mputm (md, R_LOAD_USER_FILE, MOK);
287	return;
288}
289
290/**
291 ** s_unload_user_file()
292 **/
293
294void
295s_unload_user_file(char *m, MESG *md)
296{
297	syslog(LOG_DEBUG, "s_unload_user_file()");
298
299	trashusers ();	/* THIS WON'T DO TRUE UNLOAD, SORRY! */
300
301	mputm (md, R_UNLOAD_USER_FILE, MOK);
302	return;
303}
304/**
305 ** s_shutdown()
306 **/
307
308void
309s_shutdown(char *m, MESG *md)
310{
311	ushort			immediate;
312
313	(void)getmessage (m, S_SHUTDOWN, &immediate);
314	syslog(LOG_DEBUG, "s_shutdown(%d)", immediate);
315
316	switch (md->type) {
317	case MD_STREAM:
318	case MD_SYS_FIFO:
319	case MD_USR_FIFO:
320		mputm (md, R_SHUTDOWN, MOK);
321		lpshut (immediate);
322		/*NOTREACHED*/
323	default:
324		syslog(LOG_DEBUG,
325		       "Received S_SHUTDOWN on a type %d connection\n",
326		       md->type);
327	}
328
329	return;
330}
331
332/**
333 ** s_quiet_alert()
334 **/
335
336void
337s_quiet_alert(char *m, MESG *md)
338{
339	char			*name;
340	ushort			type,
341				status;
342	register FSTATUS	*pfs;
343	register PSTATUS	*pps;
344	register PWSTATUS	*ppws;
345
346
347	/*
348	 * We quiet an alert by cancelling it with "cancel_alert()"
349	 * and then resetting the active flag. This effectively just
350	 * terminates the process running the alert but tricks the
351	 * rest of the Spooler into thinking it is still active.
352	 * The alert will be reactivated only AFTER "cancel_alert()"
353	 * has been called (to clear the active flag) and then "alert()"
354	 * is called again. Thus:
355	 *
356	 * For printer faults the alert will be reactivated when:
357	 *	- a fault is found after the current fault has been
358	 *	  cleared (i.e. after successful print or after manually
359	 *	  enabled).
360	 *
361	 * For forms/print-wheels the alert will be reactivated when:
362	 *	- the form/print-wheel becomes mounted and then unmounted
363	 *	  again, with too many requests still pending;
364	 *	- the number of requests falls below the threshold and
365	 *	  then rises above it again.
366	 */
367
368	(void)getmessage (m, S_QUIET_ALERT, &name, &type);
369	syslog(LOG_DEBUG, "s_quiet_alert(%s, %d)", (name ? name : "NULL"),
370	       type);
371
372	if (!*name)
373		status = MNODEST;
374
375	else switch (type) {
376	case QA_FORM:
377		if (!(pfs = search_fstatus(name)))
378			status = MNODEST;
379
380		else if (!pfs->alert->active)
381			status = MERRDEST;
382
383		else {
384			cancel_alert (A_FORM, pfs);
385			pfs->alert->active = 1;
386			status = MOK;
387		}
388		break;
389
390	case QA_PRINTER:
391		if (!(pps = search_pstatus(name)))
392			status = MNODEST;
393
394		else if (!pps->alert->active)
395			status = MERRDEST;
396
397		else {
398			cancel_alert (A_PRINTER, pps);
399			pps->alert->active = 1;
400			status = MOK;
401		}
402		break;
403
404	case QA_PRINTWHEEL:
405		if (!(ppws = search_pwstatus(name)))
406			status = MNODEST;
407
408		else if (!ppws->alert->active)
409			status = MERRDEST;
410
411		else {
412			cancel_alert (A_PWHEEL, ppws);
413			ppws->alert->active = 1;
414			status = MOK;
415		}
416		break;
417	}
418
419	mputm (md, R_QUIET_ALERT, status);
420	return;
421}
422
423/**
424 ** s_send_fault()
425 **/
426
427void
428s_send_fault(char *m, MESG *md)
429{
430	long			key;
431	char			*printerOrForm, *alert_text;
432	ushort			status;
433	register PSTATUS	*pps;
434
435	getmessage (m, S_SEND_FAULT, &printerOrForm, &key, &alert_text);
436	syslog(LOG_DEBUG, "s_send_fault(%s, %x, %s)",
437	       (printerOrForm ? printerOrForm : "NULL"), key,
438	       (alert_text ? alert_text : "NULL"));
439
440	if (!(pps = search_pstatus(printerOrForm)) || (!pps->exec) ||
441		pps->exec->key != key || !pps->request) {
442		status = MERRDEST;
443	} else {
444		printer_fault(pps, pps->request, alert_text, 0);
445		status = MOK;
446	}
447
448	mputm (md, R_SEND_FAULT, status);
449}
450
451/*
452 * s_clear_fault()
453 */
454void
455s_clear_fault(char *m, MESG *md)
456{
457	long	key;
458	char	*printerOrForm, *alert_text;
459	ushort	status;
460	register PSTATUS	*pps;
461
462	getmessage(m, S_CLEAR_FAULT, &printerOrForm, &key, &alert_text);
463	syslog(LOG_DEBUG, "s_clear_fault(%s, %x, %s)",
464	       (printerOrForm ? printerOrForm : "NULL"), key,
465	       (alert_text ? alert_text : "NULL"));
466
467
468	if (! (pps = search_pstatus(printerOrForm)) || ((key > 0) &&
469	    ((!pps->exec) || pps->exec->key != key || !pps->request ))) {
470		status = MERRDEST;
471	} else {
472		clear_printer_fault(pps, alert_text);
473		status = MOK;
474	}
475
476	mputm (md, R_CLEAR_FAULT, status);
477}
478
479
480/*
481 * s_paper_changed()
482 */
483void
484s_paper_changed(char *m, MESG *md)
485{
486	short			trayNum, mode, pagesPrinted;
487	char			*printer, *paper;
488	ushort			status;
489	short			chgd = 0;
490	register PSTATUS	*pps;
491	register FSTATUS	*pfs,*pfsWas;
492
493	getmessage(m, S_PAPER_CHANGED, &printer, &trayNum, &paper, &mode,
494		&pagesPrinted);
495	syslog(LOG_DEBUG, "s_paper_changed(%s, %d, %s, %d, %d)",
496	       (printer ? printer : "NULL"), trayNum, (paper ? paper : "NULL"),
497	       mode, pagesPrinted);
498
499	if (!(pps = search_pstatus(printer)))
500		status = MNODEST;
501	else if ((trayNum <=0) || (trayNum > pps->numForms))
502		status = MNOTRAY;
503	else {
504		status = MOK;
505		if (*paper && (pfsWas = pps->forms[trayNum-1].form) &&
506		    (!STREQU(pfsWas->form->paper,paper))) {
507			pfs = search_fptable(paper);
508			if (pfs) {
509				remount_form(pps, pfs, trayNum);
510				chgd = 1;
511			} else
512				status = MNOMEDIA;
513		}
514		if ( status == MOK ) {
515			pps->forms[trayNum].isAvailable = mode;
516			if ((chgd || !mode) && (!pagesPrinted) && pps->exec) {
517				if (pps->request)
518					pps->request->request->outcome |=
519						RS_STOPPED;
520				terminate(pps->exec);
521				schedule(EV_LATER, 1, EV_INTERF, pps);
522			}
523		}
524	}
525	mputm(md, R_PAPER_CHANGED, status);
526}
527
528