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
remount_form(register PSTATUS * pps,FSTATUS * pfs,short trayNum)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
remount_pwheel(register PSTATUS * pps,char * pwheel_name)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
s_max_trays(char * m,MESG * md)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
s_mount(char * m,MESG * md)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
s_mount_tray(char * m,MESG * md)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
s_unmount(char * m,MESG * md)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
s_unmount_tray(char * m,MESG * md)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
s_load_form(char * m,MESG * md)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
_unload_form(register FSTATUS * pfs)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
s_unload_form(char * m,MESG * md)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
s_load_printwheel(char * m,MESG * md)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
_unload_pwheel(register PWSTATUS * ppws)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
s_unload_printwheel(char * m,MESG * md)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