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