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 /*
23 * Copyright 2006 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 #include "dispatch.h"
32 #include <syslog.h>
33 #include <time.h>
34
35 char *showForms(PSTATUS *);
36
37 /*
38 * untidbit_all() - CALL untidbit() FOR A LIST OF TYPES
39 */
40
41 static void
untidbit_all(char ** printer_types)42 untidbit_all (char **printer_types)
43 {
44 char ** pl;
45
46 for (pl = printer_types; *pl; pl++)
47 untidbit (*pl);
48 return;
49 }
50
51 /*
52 * s_load_printer()
53 */
54
55 void
s_load_printer(char * m,MESG * md)56 s_load_printer(char *m, MESG *md)
57 {
58 char *printer;
59 ushort status;
60 register PRINTER *pp;
61 register PSTATUS *pps;
62 char **paperDenied;
63
64 (void) getmessage(m, S_LOAD_PRINTER, &printer);
65 syslog(LOG_DEBUG, "s_load_printer(%s)", (printer ? printer : "NULL"));
66
67 if (!*printer)
68 /* no printer */
69 status = MNODEST;
70 else if (!(pp = Getprinter(printer))) {
71 /* Strange or missing printer? */
72 switch (errno) {
73 case EBADF:
74 status = MERRDEST;
75 break;
76 case ENOENT:
77 default:
78 status = MNODEST;
79 break;
80 }
81 } else if ((pps = search_pstatus(printer))) {
82 /* Printer we know about already? */
83 PRINTER *op = pps->printer;
84
85 pps->printer = pp;
86
87 /*
88 * Ensure that an old Terminfo type that's no longer
89 * needed gets freed, and that an existing type gets
90 * reloaded (in case it has been changed).
91 */
92 untidbit_all (op->printer_types);
93 untidbit_all (pp->printer_types);
94
95 /*
96 * Does an alert get affected?
97 * - Different command?
98 * - Different wait interval?
99 */
100 if (pps->alert->active)
101 if (!SAME(pp->fault_alert.shcmd,
102 op->fault_alert.shcmd) ||
103 pp->fault_alert.W != op->fault_alert.W) {
104 /*
105 * We can't use "cancel_alert()" here
106 * because it will remove the message.
107 * We'll do half of the cancel, then
108 * check if we need to run the new alert,
109 * and remove the message if not.
110 */
111 pps->alert->active = 0;
112 terminate (pps->alert->exec);
113 if (pp->fault_alert.shcmd)
114 alert(A_PRINTER, pps, (RSTATUS *)0,
115 (char *)0);
116 else
117 Unlink (pps->alert->msgfile);
118 }
119 freeprinter (op);
120
121 unload_list (&pps->users_allowed);
122 unload_list (&pps->users_denied);
123 unload_list (&pps->forms_allowed);
124 unload_list (&pps->forms_denied);
125 load_userprinter_access(pp->name, &pps->users_allowed,
126 &pps->users_denied);
127 load_formprinter_access(pp->name, &pps->forms_allowed,
128 &pps->forms_denied);
129
130 unload_list (&pps->paper_allowed);
131 load_paperprinter_access(pp->name, &pps->paper_allowed,
132 &paperDenied);
133 freelist(paperDenied);
134
135 load_sdn (&pps->cpi, pp->cpi);
136 load_sdn (&pps->lpi, pp->lpi);
137 load_sdn (&pps->plen, pp->plen);
138 load_sdn (&pps->pwid, pp->pwid);
139
140 pps->last_dial_rc = 0;
141 pps->nretry = 0;
142
143 /*
144 * Evaluate all requests queued for this printer,
145 * to make sure they are still eligible. They will
146 * get moved to another printer, get (re)filtered,
147 * or get canceled.
148 */
149 (void) queue_repel(pps, 0, (qchk_fnc_type)0);
150
151 status = MOK;
152 } else if (pp->remote) {
153 /* don't really load a remote printer */
154 status = MOK;
155 } else if ((pps = new_pstatus(pp))) {
156 pps->status = PS_DISABLED | PS_REJECTED;
157 load_str (&pps->dis_reason, CUZ_NEW_PRINTER);
158 load_str (&pps->rej_reason, CUZ_NEW_DEST);
159 load_str (&pps->fault_reason, CUZ_PRINTING_OK);
160 time (&pps->dis_date);
161 time (&pps->rej_date);
162
163 dump_pstatus ();
164
165 status = MOK;
166 } else {
167 freeprinter (pp);
168 status = MNOSPACE;
169 }
170
171
172 mputm (md, R_LOAD_PRINTER, status);
173 return;
174 }
175
176 /*
177 * s_unload_printer()
178 */
179
180 static void
_unload_printer(PSTATUS * pps)181 _unload_printer(PSTATUS *pps)
182 {
183 int i;
184
185 if (pps->alert->active)
186 cancel_alert (A_PRINTER, pps);
187
188 /*
189 * Remove this printer from the classes it may be in.
190 * This is likely to be redundant, i.e. upon deleting
191 * a printer the caller is SUPPOSED TO check all the
192 * classes; any that contain the printer will be changed
193 * and we should receive a S_LOAD_CLASS message for each
194 * to reload the class.
195 *
196 * HOWEVER, this leaves a (small) window where someone
197 * can sneak a request in destined for the CLASS. If
198 * we have deleted the printer but still have it in the
199 * class, we may have trouble!
200 */
201 for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++)
202 (void) dellist(&(CStatus[i]->class->members),
203 pps->printer->name);
204
205 free_pstatus(pps);
206 /*
207 * this is removed from the PStatus table by the caller
208 * list_remove((void ***)&PStatus, (void *)pps);
209 */
210
211 return;
212 }
213
214 void
s_unload_printer(char * m,MESG * md)215 s_unload_printer(char *m, MESG *md)
216 {
217 char *printer;
218 ushort status;
219 register PSTATUS *pps;
220
221 (void) getmessage(m, S_UNLOAD_PRINTER, &printer);
222
223 syslog(LOG_DEBUG, "s_unload_printer(%s)",
224 (printer ? printer : "NULL"));
225
226 if (!*printer || STREQU(printer, NAME_ALL))
227 /* Unload ALL printers */
228 if (!Request_List)
229 /* If we have ANY requests queued, we can't do it. */
230 status = MBUSY;
231
232 else {
233 int i;
234 for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
235 _unload_printer (PStatus[i]);
236 free(PStatus);
237 PStatus = NULL;
238 status = MOK;
239 }
240
241 else if (!(pps = search_pstatus(printer)))
242 /* Have we seen this printer before */
243 status = MNODEST;
244 else {
245 /*
246 * Note: This routine WILL MOVE requests to another
247 * printer. It will not stop until it has gone through
248 * the entire list of requests, so all requests that
249 * can be moved will be moved. If any couldn't move,
250 * however, we don't unload the printer.
251 */
252 if (queue_repel(pps, 1, (qchk_fnc_type)0))
253 status = MOK;
254 else
255 status = MBUSY;
256
257 if (status == MOK) {
258 _unload_printer (pps);
259 list_remove((void ***)&PStatus, (void *)pps);
260 }
261 }
262
263 if (status == MOK)
264 dump_pstatus ();
265
266 mputm (md, R_UNLOAD_PRINTER, status);
267 return;
268 }
269
270 /*
271 * combineReasons()
272 */
273
274 static char *
combineReasons(PSTATUS * pps,char * freeReason)275 combineReasons(PSTATUS *pps, char *freeReason)
276 {
277 char *reason = NULL;
278
279 if (pps->status & PS_FAULTED) {
280 if ((pps->status & (PS_DISABLED | PS_LATER)) &&
281 (!STREQU(pps->dis_reason, CUZ_STOPPED)) &&
282 (addstring(&reason, "Fault reason: ") == 0) &&
283 (addstring(&reason, pps->fault_reason) == 0) &&
284 (addstring(&reason, "\n\tDisable reason: ") == 0) &&
285 (addstring(&reason, pps->dis_reason) == 0))
286 *freeReason = 1;
287
288 else {
289 if (reason)
290 /* memory allocation failed part way through */
291 Free(reason);
292
293 reason = pps->fault_reason;
294 *freeReason = 0;
295 }
296 } else {
297 reason = pps->dis_reason;
298 *freeReason = 0;
299 }
300 return (reason);
301 }
302
303 static void
local_printer_status(MESG * md,PSTATUS * pps,short status)304 local_printer_status(MESG *md, PSTATUS *pps, short status)
305 {
306 char *reason = NULL;
307 char freeReason = 0;
308 char *formList = NULL;
309
310 reason = combineReasons(pps, &freeReason);
311 formList = showForms(pps);
312
313 send(md, R_INQUIRE_PRINTER_STATUS, status, pps->printer->name,
314 (formList ? formList : ""),
315 (pps->pwheel_name ? pps->pwheel_name : ""),
316 reason, pps->rej_reason, pps->status,
317 (pps->request ? pps->request->secure->req_id : ""),
318 pps->dis_date, pps->rej_date);
319
320 if (formList)
321 Free(formList);
322
323 if (freeReason)
324 Free(reason);
325 }
326
327 /*
328 * s_inquire_printer_status()
329 */
330
331 void
s_inquire_printer_status(char * m,MESG * md)332 s_inquire_printer_status(char *m, MESG *md)
333 {
334 char *printer;
335 register PSTATUS *pps;
336
337 (void) getmessage(m, S_INQUIRE_PRINTER_STATUS, &printer);
338 syslog(LOG_DEBUG, "s_inquire_printer_status(%s)", printer);
339
340 if (!*printer || STREQU(printer, NAME_ALL)) {
341 /* inquire about all printers */
342 int i;
343
344 for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) {
345 pps = PStatus[i];
346 if (PStatus[i + 1] != NULL)
347 local_printer_status(md, pps, MOKMORE);
348 }
349 } else
350 /* inquire about a specific printer */
351 pps = search_pstatus(printer);
352
353 if (pps)
354 local_printer_status(md, pps, MOK);
355 else {
356 mputm(md, R_INQUIRE_PRINTER_STATUS, MNODEST, "", "", "", "",
357 "", 0, "", 0L, 0L);
358 }
359 }
360
361
362 /*
363 * s_load_class()
364 */
365
366 void
s_load_class(char * m,MESG * md)367 s_load_class(char *m, MESG *md)
368 {
369 char *class;
370 ushort status;
371 register CLASS *pc;
372 register CLSTATUS *pcs;
373
374 (void) getmessage(m, S_LOAD_CLASS, &class);
375 syslog(LOG_DEBUG, "s_load_class(%s)", (class ? class : "NULL"));
376
377 if (!*class)
378 /* no class defined */
379 status = MNODEST;
380 else if (!(pc = Getclass(class))) {
381 /* Strange or missing class */
382 switch (errno) {
383 case EBADF:
384 status = MERRDEST;
385 break;
386 case ENOENT:
387 default:
388 status = MNODEST;
389 break;
390 }
391
392 } else if ((pcs = search_cstatus(class))) {
393 /* Class we already know about */
394 register RSTATUS *prs;
395
396 freeclass (pcs->class);
397 pcs->class = pc;
398
399 /*
400 * Here we go through the list of requests
401 * to see who gets affected.
402 */
403 for (prs = Request_List; prs != NULL; prs = prs->next)
404 if (STREQU(prs->request->destination, class)) {
405 /*
406 * If not still eligible for this class...
407 */
408 switch (validate_request(prs, (char **)0, 1)) {
409 case MOK:
410 case MERRDEST: /* rejecting (shouldn't happen) */
411 break;
412 case MDENYDEST:
413 case MNOMOUNT:
414 case MNOMEDIA:
415 case MNOFILTER:
416 default:
417 /*
418 * ...then too bad!
419 */
420 cancel (prs, 1);
421 break;
422 }
423 }
424
425 status = MOK;
426 } else if ((pcs = new_cstatus(pc))) {
427 /* Room for new class? */
428 pcs->status = CS_REJECTED;
429 load_str (&pcs->rej_reason, CUZ_NEW_DEST);
430 time (&pcs->rej_date);
431
432 dump_cstatus ();
433
434 status = MOK;
435 } else {
436 freeclass (pc);
437 status = MNOSPACE;
438 }
439
440
441 mputm (md, R_LOAD_CLASS, status);
442 return;
443 }
444
445 /*
446 * s_unload_class()
447 */
448
449 static void
_unload_class(CLSTATUS * pcs)450 _unload_class(CLSTATUS *pcs)
451 {
452 freeclass (pcs->class);
453 if (pcs->rej_reason != NULL)
454 Free (pcs->rej_reason);
455 Free(pcs);
456
457 return;
458 }
459
460 void
s_unload_class(char * m,MESG * md)461 s_unload_class(char *m, MESG *md)
462 {
463 char *class;
464 ushort status;
465 RSTATUS *prs;
466 register CLSTATUS *pcs;
467
468 (void) getmessage(m, S_UNLOAD_CLASS, &class);
469 syslog(LOG_DEBUG, "s_unload_class(%s)", (class ? class : "NULL"));
470
471 /*
472 * Unload ALL classes?
473 */
474 if (!*class || STREQU(class, NAME_ALL)) {
475 int i;
476 /*
477 * If we have a request queued for a member of ANY
478 * class, we can't do it.
479 */
480 status = MOK;
481 for (i = 0; ((CStatus[i] != NULL) && (status == MOK)); i++) {
482 for (prs = Request_List; prs != NULL; prs = prs->next)
483 if (STREQU(prs->request->destination,
484 CStatus[i]->class->name)) {
485 status = MBUSY;
486 break;
487 }
488 }
489
490 if (status == MOK) {
491 for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++)
492 _unload_class (CStatus[i]);
493 free(CStatus);
494 CStatus = NULL;
495 }
496
497 /*
498 * Have we seen this class before?
499 */
500 } else if (!(pcs = search_cstatus(class)))
501 status = MNODEST;
502
503 /*
504 * Is there even one request queued for this class?
505 * If not, we can safely remove it.
506 */
507 else {
508 status = MOK;
509 for (prs = Request_List; prs != NULL; prs = prs->next)
510 if (STREQU(prs->request->destination, class)) {
511 status = MBUSY;
512 break;
513 }
514
515 if (status == MOK) {
516 _unload_class (pcs);
517 list_remove((void ***)&CStatus, (void *)pcs);
518 }
519 }
520
521 if (status == MOK)
522 dump_cstatus ();
523
524 mputm (md, R_UNLOAD_CLASS, status);
525 return;
526 }
527
528 /*
529 * s_inquire_class()
530 */
531
532 void
s_inquire_class(char * m,MESG * md)533 s_inquire_class(char *m, MESG *md)
534 {
535 char *class;
536 register CLSTATUS *pcs;
537
538 (void) getmessage(m, S_INQUIRE_CLASS, &class);
539 syslog(LOG_DEBUG, "s_inquire_class(%s)", (class ? class : "NULL"));
540
541
542
543 if (!*class || STREQU(class, NAME_ALL)) {
544 /* inquire about ALL classes */
545 int i;
546
547 for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++) {
548 pcs = CStatus[i];
549 if (CStatus[i + 1] != NULL)
550 send(md, R_INQUIRE_CLASS, MOKMORE,
551 pcs->class->name, pcs->status,
552 pcs->rej_reason, pcs->rej_date);
553 }
554 } else
555 /* inquire about a single class */
556 pcs = search_cstatus(class);
557
558 if (pcs)
559 send(md, R_INQUIRE_CLASS, MOK, pcs->class->name, pcs->status,
560 pcs->rej_reason, pcs->rej_date);
561 else
562 mputm (md, R_INQUIRE_CLASS, MNODEST, "", 0, "", 0L);
563
564 return;
565 }
566
567 /*
568 * s_paper_allowed()
569 */
570
571 void
s_paper_allowed(char * m,MESG * md)572 s_paper_allowed(char *m, MESG *md)
573 {
574 char *printer;
575 char *paperList = NULL;
576 register PSTATUS *pps, *ppsnext;
577
578 (void) getmessage(m, S_PAPER_ALLOWED, &printer);
579 syslog(LOG_DEBUG, "s_paper_allowed(%s)", (printer ? printer : "NULL"));
580
581
582 if (!*printer || STREQU(printer, NAME_ALL)) {
583 /* inquire about ALL printers */
584 int i;
585
586 for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) {
587 pps = PStatus[i];
588 if (PStatus[i + 1] != NULL) {
589 paperList = sprintlist(pps->paper_allowed);
590 send(md, R_PAPER_ALLOWED, MOKMORE,
591 pps->printer->name,
592 (paperList ? paperList : ""));
593 if (paperList)
594 Free(paperList);
595 }
596 }
597 } else
598 /* inquire about a specific printer */
599 pps = search_pstatus(printer);
600
601 if (pps) {
602 paperList = sprintlist(pps->paper_allowed);
603 send(md, R_PAPER_ALLOWED, MOK, pps->printer->name,
604 (paperList ? paperList : ""));
605 if (paperList)
606 Free(paperList);
607
608 } else {
609 mputm(md, R_PAPER_ALLOWED, MNODEST, "", "");
610 }
611 }
612