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