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