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