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