xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/disp2.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 /*
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