xref: /illumos-gate/usr/src/cmd/lp/cmd/lpsched/disp3.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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 1998 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 
36 /**
37  ** remount_form() - MOUNT A FORM WHERE ANOTHER WAS MOUNTED
38  **/
39 
40 extern char *LP_TRAY_UNMOUNT;
41 
42 
43 void
44 remount_form(register PSTATUS *pps, FSTATUS *pfs, short trayNum)
45 {
46 	trayNum--; /* make zero based */
47 	if (pps->forms && (pps->forms[trayNum].form == pfs)) {
48 		pps->forms[trayNum].isAvailable = ((pfs ||
49 					 (!LP_TRAY_UNMOUNT)) ? 1 : 0);
50 					 /* force it */
51 		return;	/* nothing to do */
52 	} else if ((!pps->forms) && (!pfs)) {
53 		return;	/* nothing to do */
54 	}
55 
56 	/*
57 	 * Unmount the old form.
58 	 */
59 	if (pps->forms && pps->forms[trayNum].form) {
60 		register FSTATUS	*Opfs	= pps->forms[trayNum].form;
61 
62 		pps->forms[trayNum].form = 0;
63 		pps->forms[trayNum].isAvailable = (LP_TRAY_UNMOUNT ? 0 : 1);
64 		Opfs->mounted--;
65 
66 		/*
67 		 * Unmounting the form may make some print requests
68 		 * no longer printable, because they were accepted
69 		 * only because the form was already mounted.
70 		 * Unmounting the form will also force some requests
71 		 * to another printer (where the form is mounted)
72 		 * so they can print.
73 		 */
74 		form_in_question = Opfs;
75 		(void)queue_repel (pps, 0, qchk_form);
76 
77 		/*
78 		 * Maybe an alert is due.
79 		 */
80 		check_form_alert (Opfs, (_FORM *)0);
81 	}
82 
83 	/*
84 	 * Mount the new form?
85 	 */
86 	if (pfs) {
87 		syslog(LOG_DEBUG, "remount_form add %x(%s) to tray %d\n",
88 			 pfs, (pfs ? pfs->form->name : "NULL"), trayNum);
89 
90 		if (pps && !pps->forms) {
91                         pps->forms = (PFSTATUS *)calloc((trayNum +1),
92 							sizeof(PFSTATUS));
93 			pps->numForms = trayNum + 1;
94 		}
95 
96 		if (pps && pps->forms && (pps->numForms > trayNum)) {
97 			pps->forms[trayNum].form = pfs;
98 			pps->forms[trayNum].isAvailable = 1;
99 			pfs->mounted++;
100 		} else {
101 			return; /* nothing to do, can't mount form,
102 				   so no need to pretend we did */
103 		}
104 
105 
106 		/*
107 		 * Attract all the requests needing this newly mounted
108 		 * form. This may cause some unnecessary shuffling, but
109 		 * we have to ensure requests aren't assigned to a printer
110 		 * without the form mounted, so that the alert check is
111 		 * correct.
112 		 */
113 		if (pfs->requests) {
114 			form_in_question = pfs;
115 			queue_attract (pps, qchk_form, 0);
116 
117 			/*
118 			 * Maybe an alert can be shut off.
119 			 */
120 			check_form_alert (pfs, (_FORM *)0);
121 		}
122 
123 	} else {
124 		/*
125 		 * Attract first request that doesn't need a form mounted.
126 		 * We only need to get one request printing, because it
127 		 * completing will cause the next request to be attracted.
128 		 */
129 		form_in_question = 0;
130 		queue_attract (pps, qchk_form, 1);
131 	}
132 
133 	dump_pstatus ();
134 
135 	return;
136 }
137 
138 /**
139  ** remount_pwheel() - MOUNT A PRINT-WHEEL WHERE ANOTHER WAS MOUNTED
140  **/
141 
142 static void
143 remount_pwheel(register PSTATUS *pps, char *pwheel_name)
144 {
145 	PWSTATUS		*ppws;
146 
147 	if (SAME(pps->pwheel_name, pwheel_name))
148 		return;	/* nothing to do */
149 
150 	/*
151 	 * Unmount the old print wheel
152 	 */
153 	if (pps->pwheel_name) {
154 		register PWSTATUS	*Oppws	= pps->pwheel;
155 
156 		pps->pwheel = 0;
157 		if (Oppws)
158 			Oppws->mounted--;
159 
160 		/*
161 		 * Unmounting the print wheel may make some print
162 		 * requests no longer printable, because they were
163 		 * accepted only because the print wheel was already
164 		 * mounted. Unmounting the print wheel will also force
165 		 * some requests to another printer (where the print wheel
166 		 * is mounted) so they can print.
167 		 */
168 		pwheel_in_question = pps->pwheel_name;
169 		(void)queue_repel (pps, 0, qchk_pwheel);
170 
171 		unload_str (&pps->pwheel_name);
172 
173 		/*
174 		 * Maybe an alert is due.
175 		 */
176 		if (Oppws)
177 			check_pwheel_alert (Oppws, (PWHEEL *)0);
178 	}
179 
180 	/*
181 	 * Mount the new print wheel?
182 	 */
183 	if (pwheel_name) {
184 		load_str (&pps->pwheel_name, pwheel_name);
185 		if (ppws = search_pwtable(pwheel_name)) {
186 			pps->pwheel = ppws;
187 			ppws->mounted++;
188 
189 			/*
190 			 * Attract all requests needing this newly
191 			 * mounted print wheel. This may cause some
192 			 * unnecessary shuffling, but we have to ensure
193 			 * requests aren't assigned to a printer without
194 			 * the print-wheel mounted, so that the alert
195 			 * check is correct.
196 			 */
197 			if (ppws->requests) {
198 				pwheel_in_question = pwheel_name;
199 				queue_attract (pps, qchk_pwheel, 0);
200 
201 				/*
202 				 * Maybe an alert can be shut off.
203 				 */
204 				check_pwheel_alert (ppws, (PWHEEL *)0);
205 			}
206 
207 		} else {
208 			/*
209 			 * Attract the first request that needs this newly
210 			 * mounted print wheel. If no alert has been
211 			 * defined for the print wheel, we don't know how
212 			 * many requests are queued waiting for it, so we
213 			 * have to do this unconditionally.
214 			 */
215 			pwheel_in_question = pwheel_name;
216 			queue_attract (pps, qchk_pwheel, 1);
217 		}
218 
219 	} else {
220 		/*
221 		 * Attract the first request that doesn't need a
222 		 * print wheel mounted.
223 		 * We only need to get one request printing, because it
224 		 * completing will cause the next request to be attracted.
225 		 */
226 		pwheel_in_question = 0;
227 		queue_attract (pps, qchk_pwheel, 1);
228 	}
229 
230 	dump_pstatus ();
231 
232 	return;
233 }
234 
235 #define MAX_TRAYS 100
236 
237 /**
238  ** s_max_trays()
239  **/
240 
241 void
242 s_max_trays(char *m, MESG *md)
243 {
244 	char			*printer;
245 	ushort			status;
246 	short numTrays;
247 	register PSTATUS	*pps;
248 	register PFSTATUS	*ppfs;
249 
250 	(void) getmessage(m, S_MAX_TRAYS, &printer, &numTrays);
251 	syslog(LOG_DEBUG, "s_max_trays(%s, %d)", (printer ? printer : "NULL"),
252 	       numTrays);
253 
254 	/* Have we seen this printer before? */
255 	if (!*printer || !(pps = search_ptable(printer)))
256 		status = MNODEST;
257 
258 	/* How about the tray? */
259 	else if ((numTrays <=0) || (numTrays > MAX_TRAYS))
260 		status = MNOTRAY;
261 
262 	/* If the printer is currently printing, we can't disturb it. */
263 	else if (pps->request)
264 		    status = MBUSY;
265 
266 	else if (pps->forms) {
267 		if (!(ppfs = Realloc(pps->forms,numTrays * sizeof(PFSTATUS))))
268 			status = MNOMEM;
269 		else {
270 			int i;
271 
272 			for (i = pps->numForms; i < numTrays; i++) {
273 				ppfs[i].form = NULL;
274 				ppfs[i].isAvailable = (LP_TRAY_UNMOUNT ? 0 : 1);
275 			}
276 			pps->forms = ppfs;
277 			pps->numForms = numTrays;
278 			status = MOK;
279 		}
280 	} else if (!(ppfs = Calloc(numTrays,sizeof(PFSTATUS)))) {
281 		status = MNOMEM;
282 	} else  {
283 		pps->forms = ppfs;
284 		pps->numForms = numTrays;
285 		status = MOK;
286 	}
287 	dump_pstatus();
288 	mputm(md, R_MAX_TRAYS, status);
289 }
290 
291 /**
292  ** s_mount()
293  **/
294 
295 void
296 s_mount(char *m, MESG *md)
297 {
298 	char			*printer, *form, *pwheel_name;
299 	ushort			status;
300 	register PSTATUS	*pps;
301 	register FSTATUS	*pfs;
302 
303 	(void) getmessage(m, S_MOUNT, &printer, &form, &pwheel_name);
304 	syslog(LOG_DEBUG, "s_mount(%s, %s, %s)", (printer ? printer : "NULL"),
305 	       (form ? form : "NULL"), (pwheel_name ? pwheel_name : "NULL"));
306 
307 	if (!*form && !*pwheel_name)
308 		status = MNOMEDIA;
309 
310 	/* Have we seen this printer before? */
311 	else if (!*printer || !(pps = search_ptable(printer)))
312 		status = MNODEST;
313 
314 	/* How about the form? */
315 	else if (*form && !(pfs = search_ftable(form)))
316 		status = MNOMEDIA;
317 
318 	/* If the printer is currently printing, we can't disturb it. */
319 	else if (pps->request)
320 		    status = MBUSY;
321 
322 	else {
323 		/*
324 		 * Mount them.
325 		 */
326 		if (*form)
327 			remount_form (pps, pfs,1);
328 		if (*pwheel_name)
329 			remount_pwheel(pps, pwheel_name);
330 
331 		status = MOK;
332 	}
333 
334 	mputm(md, R_MOUNT, status);
335 }
336 
337 /*
338  * s_mount_tray()
339  */
340 
341 void
342 s_mount_tray(char *m, MESG *md)
343 {
344 	char			*printer, *form, *pwheel_name;
345 	ushort			status;
346 	short			trayNum;
347 	register PSTATUS	*pps;
348 	register FSTATUS	*pfs;
349 
350 	(void) getmessage(m, S_MOUNT_TRAY, &printer, &form, &pwheel_name,
351 		&trayNum);
352 	syslog(LOG_DEBUG, "s_mount_tray(%s, %s, %s, %d)",
353 	       (printer ? printer : "NULL"), (form ? form : "NULL"),
354 	       (pwheel_name ? pwheel_name : "NULL"), trayNum);
355 
356 	if (!*form && !*pwheel_name)
357 		status = MNOMEDIA;
358 
359 	/* Have we seen this printer before? */
360 	else if (!*printer || !(pps = search_ptable(printer)))
361 		status = MNODEST;
362 
363 	/* How about the form? */
364 	else if (*form && !(pfs = search_ftable(form)))
365 		status = MNOMEDIA;
366 
367 	/* How about the tray? */
368 	else if ((trayNum <=0) || (trayNum > pps->numForms))
369 		status = MNOTRAY;
370 
371 	/* If the printer is currently printing, we can't disturb it. */
372 	else if (pps->request)
373 		    status = MBUSY;
374 
375 	else {
376 		/*
377 		 * Mount them.
378 		 */
379 		if (*form)
380 			remount_form(pps, pfs,trayNum);
381 		if (*pwheel_name)
382 			remount_pwheel(pps, pwheel_name);
383 
384 		status = MOK;
385 	}
386 
387 	mputm (md, R_MOUNT_TRAY, status);
388 }
389 
390 /**
391  ** s_unmount()
392  **/
393 
394 void
395 s_unmount(char *m, MESG *md)
396 {
397 	char			*printer,
398 				*form,
399 				*pwheel_name;
400 	ushort			status;
401 	register PSTATUS	*pps;
402 
403 	(void)getmessage (m, S_UNMOUNT, &printer, &form, &pwheel_name);
404 	syslog(LOG_DEBUG, "s_unmount(%s, %s, %s)",
405 	       (printer ? printer : "NULL"), (form ? form : "NULL"),
406 	       (pwheel_name ? pwheel_name : "NULL"));
407 
408 	if (!*form && !*pwheel_name)
409 		status = MNOMEDIA;
410 
411 	/*
412 	 * Have we seen this printer before?
413 	 */
414 	else if (!*printer || !(pps = search_ptable(printer)))
415 		status = MNODEST;
416 
417 
418 	/*
419 	 * If the printer is currently printing a request,
420 	 * we can't unmount the current form/pwheel.
421 	 */
422 	else if (pps->request)
423 		status = MBUSY;
424 
425 	else {
426 		/*
427 		 * Unmount them.
428 		 */
429 		if (*form)
430 			remount_form (pps, (FSTATUS *)0,1);
431 		if (*pwheel_name)
432 			remount_pwheel (pps, (char *)0);
433 
434 		status = MOK;
435 	}
436 
437 	mputm (md, R_UNMOUNT, status);
438 	return;
439 }
440 /**
441  ** s_unmount_tray()
442  **/
443 
444 void
445 s_unmount_tray(char *m, MESG *md)
446 {
447 	char			*printer,
448 				*form,
449 				*pwheel_name;
450 
451 	ushort			status;
452 	short			trayNum;
453 
454 	register PSTATUS	*pps;
455 
456 	(void)getmessage (m, S_UNMOUNT_TRAY, &printer, &form, &pwheel_name,
457 		&trayNum);
458 	syslog(LOG_DEBUG, "s_unmount_tray(%s, %s, %s, %d)",
459 	       (printer ? printer : "NULL"), (form ? form : "NULL"),
460 	       (pwheel_name ? pwheel_name : "NULL"), trayNum);
461 
462 
463 	if (!*form && !*pwheel_name)
464 		status = MNOMEDIA;
465 
466 	else if (!*printer || !(pps = search_ptable(printer)))
467 		/* haven't seen this printer before */
468 		status = MNODEST;
469 	else if ((trayNum <=0) || (trayNum > pps->numForms))
470 		/* haven't seen the tray before */
471 		status = MNOTRAY;
472 	else if (pps->request)
473 		/* is the printer busy */
474 		status = MBUSY;
475 	else {
476 		/* Unmount them. */
477 		if (*form)
478 			remount_form (pps, (FSTATUS *)0,trayNum);
479 		if (*pwheel_name)
480 			remount_pwheel (pps, (char *)0);
481 
482 		status = MOK;
483 	}
484 
485 	mputm (md, R_UNMOUNT_TRAY, status);
486 	return;
487 }
488 
489 /**
490  ** s_load_form()
491  **/
492 
493 void
494 s_load_form(char *m, MESG *md)
495 {
496 	char			*form;
497 	ushort			status;
498 	register _FORM		*pf;
499 	register FSTATUS	*pfs;
500 
501 	(void)getmessage (m, S_LOAD_FORM, &form);
502 	syslog(LOG_DEBUG, "s_load_form(%s)", (form ? form : "NULL"));
503 
504 	if (!*form)
505 		/* no form specified */
506 		status = MNODEST;
507 	else if (!(pf = Getform(form))) {
508 		/* strange or missing form */
509 		switch (errno) {
510 		case EBADF:
511 			status = MERRDEST;
512 			break;
513 		case ENOENT:
514 		default:
515 			status = MNODEST;
516 			break;
517 		}
518 
519 	} else if ((pfs = search_ftable(form))) {
520 		/* Have we seen this form before? */
521 		unload_list (&pfs->users_allowed);
522 		unload_list (&pfs->users_denied);
523 		load_userform_access (
524 			pf->name,
525 			&pfs->users_allowed,
526 			&pfs->users_denied
527 		);
528 
529 		load_sdn (&pfs->cpi, pf->cpi);
530 		load_sdn (&pfs->lpi, pf->lpi);
531 		load_sdn (&pfs->plen, pf->plen);
532 		load_sdn (&pfs->pwid, pf->pwid);
533 
534 
535 		/*
536 		 * These have to be done in the order shown,
537 		 * and after the assignments above, so that all
538 		 * the new information is in place for the
539 		 * checks. An unfortunate side effect is that
540 		 * it is possible for the alert to shut off
541 		 * and then come on again, if (1) enough requests
542 		 * are canceled to drop the level below the old
543 		 * alert threshold, but (2) the new alert threshold
544 		 * is even lower. The final alert will be correct,
545 		 * though.
546 		 */
547 
548 		form_in_question = pfs;
549 		queue_check (qchk_form);
550 
551 		check_form_alert (pfs, pf);
552 
553 
554 		status = MOK;
555 
556 	/*
557 	 * Room for a new form?
558 	 */
559 	} else if ((pfs = search_ftable((char *)0))) {
560 
561 		pfs->alert->active = 0;
562 		pfs->requests = pfs->requests_last = 0;
563 		pfs->mounted = 0;
564 
565 		/*
566 		 * No alert is possible for a new form, of course,
567 		 * but this routine does a bit more than just check
568 		 * the alert.
569 		 */
570 		check_form_alert (pfs, pf);
571 
572 		unload_list (&pfs->users_allowed);
573 		unload_list (&pfs->users_denied);
574 		load_userform_access (
575 			pf->name,
576 			&pfs->users_allowed,
577 			&pfs->users_denied
578 		);
579 
580 		load_sdn (&pfs->cpi, pf->cpi);
581 		load_sdn (&pfs->lpi, pf->lpi);
582 		load_sdn (&pfs->plen, pf->plen);
583 		load_sdn (&pfs->pwid, pf->pwid);
584 
585 		status = MOK;
586 
587 	} else {
588 		free_form (pf);
589 		status = MNOSPACE;
590 
591 	}
592 
593 	mputm (md, R_LOAD_FORM, status);
594 	return;
595 }
596 
597 /**
598  ** s_unload_form()
599  **/
600 
601 static void
602 _unload_form(register FSTATUS *pfs)
603 {
604 	register PSTATUS	*pps	= &PStatus[0],
605 				*ppsend	= &PStatus[PT_Size];
606 	int i;
607 	short numForms;
608 	PFSTATUS *ppfs;
609 
610 	/*
611 	 * Unmount this form everywhere and get rid of it.
612 	 */
613 	for (; pps < ppsend; pps++)
614 		if (((ppfs = pps->forms) != NULL) &&
615 		    ((numForms = pps->numForms) > 0))
616 			for ( i = 0 ; i < numForms ; i++ )
617 				if (ppfs[i].form == pfs) ppfs[i].form= NULL;
618 
619 	free_form (pfs->form);
620 	pfs->form->name = 0;
621 
622 	return;
623 }
624 
625 void
626 s_unload_form(char *m, MESG *md)
627 {
628 	char			*form;
629 	ushort			status;
630 	RSTATUS			*prs;
631 	register FSTATUS	*pfs;
632 
633 	(void)getmessage (m, S_UNLOAD_FORM, &form);
634 	syslog(LOG_DEBUG, "s_unload_form(%s)", (form ? form : "NULL"));
635 
636 	if (!*form || STREQU(form, NAME_ALL)) {
637 		/* If we have a request queued for ANY form, we can't do it. */
638 		status = MOK;
639 		for (pfs = walk_ftable(1); pfs && status == MOK;
640 		     pfs = walk_ftable(0))
641 			BEGIN_WALK_BY_FORM_LOOP (prs, pfs)
642 				status = MBUSY;
643 				break;
644 			END_WALK_LOOP
645 
646 		if (status == MOK)
647 			for (pfs = walk_ftable(1); pfs; pfs = walk_ftable(0))
648 				_unload_form (pfs);
649 	} else if (!*form || !(pfs = search_ftable(form)))
650 		/* Have we seen this form before? */
651 		status = MNODEST;
652 	else {
653 		/* Is there even one request waiting for this form? */
654 		status = MOK;
655 		BEGIN_WALK_BY_FORM_LOOP (prs, pfs)
656 			status = MBUSY;
657 			break;
658 		END_WALK_LOOP
659 		if (status == MOK)
660 			_unload_form (pfs);
661 	}
662 
663 	mputm (md, R_UNLOAD_FORM, status);
664 	return;
665 }
666 
667 /**
668  ** s_load_printwheel()
669  **/
670 
671 void
672 s_load_printwheel(char *m, MESG *md)
673 {
674 	char			*pwheel_name;
675 	ushort			status;
676 	register PWHEEL		*ppw;
677 	register PWSTATUS	*ppws;
678 
679 	(void)getmessage (m, S_LOAD_PRINTWHEEL, &pwheel_name);
680 	syslog(LOG_DEBUG, "s_load_printwheel(%s)",
681 	       (pwheel_name ? pwheel_name : "NULL"));
682 
683 	if (!*pwheel_name)
684 		/* no printwheel specified */
685 		status = MNODEST;
686 	else if (!(ppw = Getpwheel(pwheel_name))) {
687 		/* Strange or missing print wheel? */
688 		switch (errno) {
689 		case EBADF:
690 			status = MERRDEST;
691 			break;
692 		case ENOENT:
693 		default:
694 			status = MNODEST;
695 			break;
696 		}
697 	} else if ((ppws = search_pwtable(pwheel_name))) {
698 		/* Print wheel we already know about? */
699 		check_pwheel_alert (ppws, ppw);
700 		status = MOK;
701 	} else if ((ppws = search_pwtable((char *)0))) {
702 		/* Room for a new print wheel? */
703 		register RSTATUS	*prs;
704 
705 		ppws->alert->active = 0;
706 		ppws->requests = ppws->requests_last = 0;
707 		ppws->mounted = 0;
708 
709 		/*
710 		 * Because of the quirky nature of the print wheel
711 		 * structures, i.e. no structure unless an alert has
712 		 * been defined, we have to run through the requests
713 		 * and see which ones are waiting for this print wheel,
714 		 * so we can assign alerts and count pending requests.
715 		 */
716 		BEGIN_WALK_BY_PWHEEL_LOOP (prs, pwheel_name)
717 			if (!one_printer_with_charsets(prs)) {
718 				prs->pwheel = ppws;
719 				ppws->requests++;
720 			}
721 		END_WALK_LOOP
722 		check_pwheel_alert (ppws, ppw);
723 
724 		status = MOK;
725 	} else {
726 		freepwheel (ppw);
727 		status = MNOSPACE;
728 	}
729 
730 	mputm (md, R_LOAD_PRINTWHEEL, status);
731 	return;
732 }
733 
734 /**
735  ** s_unload_printwheel()
736  **/
737 
738 static void
739 _unload_pwheel(register PWSTATUS *ppws)
740 {
741 	register PSTATUS	*pps	= &PStatus[0],
742 				*ppsend	= &PStatus[PT_Size];
743 	register RSTATUS	*prs;
744 
745 
746 	/*
747 	 * ``Unmount'' the alert part of this print wheel everywhere.
748 	 * THIS IS NOT A COMPLETE UNMOUNT, JUST THE ALERT STRUCTURE
749 	 * IS REMOVED.
750 	 */
751 	for (; pps < ppsend; pps++)
752 		if (pps->pwheel == ppws)
753 			pps->pwheel = 0;
754 
755 	/*
756 	 * Remove the alert part from all requests.
757 	 */
758 	for (prs = Request_List; prs; prs = prs->next)
759 		if (prs->pwheel == ppws)
760 			prs->pwheel = 0;
761 
762 	/*
763 	 * Cancel any alert pending. Here we're different from the
764 	 * similar code for unloading a form, because, to be able to
765 	 * unload a form we first require NO requests pending. If no
766 	 * requests are pending there should be no alert to cancel.
767 	 * Print wheels, on the other hand, only exist as names and
768 	 * alerts. We can always unload a ``print wheel'' because
769 	 * all we're really unloading is an alert. Thus, there can
770 	 * be requests queued for the print wheel (the name), and
771 	 * thus there can be an alert running.
772 	 */
773 	if (ppws->alert->active)
774 		cancel_alert (A_PWHEEL, ppws);
775 
776 	freepwheel (ppws->pwheel);
777 	ppws->pwheel->name = 0;		/* freeprinter() doesn't */
778 
779 	return;
780 }
781 
782 void
783 s_unload_printwheel(char *m, MESG *md)
784 {
785 	char			*pwheel_name;
786 
787 	ushort			status;
788 
789 	register PWSTATUS	*ppws;
790 
791 
792 	/*
793 	 * We don't care if any requests are waiting for the print
794 	 * wheel(s)--what we're removing here is (are) just the alert(s)!
795 	 */
796 
797 	(void)getmessage (m, S_UNLOAD_PRINTWHEEL, &pwheel_name);
798 	syslog(LOG_DEBUG, "s_unload_printwheel(%s)",
799 	       (pwheel_name ? pwheel_name : "NULL"));
800 
801 
802 	/*
803 	 * Remove all print wheel alerts?
804 	 */
805 	if (!*pwheel_name || STREQU(pwheel_name, NAME_ALL)) {
806 		for (ppws = walk_pwtable(1); ppws; ppws = walk_pwtable(0))
807 			_unload_pwheel (ppws);
808 		status = MOK;
809 
810 	/*
811 	 * Have we seen this print wheel before?
812 	 */
813 	} else if (!(ppws = search_pwtable(pwheel_name)))
814 		status = MNODEST;
815 
816 	else {
817 		_unload_pwheel (ppws);
818 		status = MOK;
819 
820 	}
821 
822 	mputm (md, R_UNLOAD_PRINTWHEEL, status);
823 	return;
824 }
825