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