xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/disp4.c (revision 19d32b9a)
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 
39 void
s_accept_dest(char * m,MESG * md)40 s_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 
88 void
s_reject_dest(char * m,MESG * md)89 s_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 
142 void
s_enable_dest(char * m,MESG * md)143 s_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 
172 void
s_disable_dest(char * m,MESG * md)173 s_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 
229 void
s_load_filter_table(char * m,MESG * md)230 s_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 
256 void
s_unload_filter_table(char * m,MESG * md)257 s_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 
276 void
s_load_user_file(char * m,MESG * md)277 s_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 
294 void
s_unload_user_file(char * m,MESG * md)295 s_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 
308 void
s_shutdown(char * m,MESG * md)309 s_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 
336 void
s_quiet_alert(char * m,MESG * md)337 s_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 
427 void
s_send_fault(char * m,MESG * md)428 s_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  */
454 void
s_clear_fault(char * m,MESG * md)455 s_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  */
483 void
s_paper_changed(char * m,MESG * md)484 s_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