/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "dispatch.h" #include /** ** remount_form() - MOUNT A FORM WHERE ANOTHER WAS MOUNTED **/ void remount_form(register PSTATUS *pps, FSTATUS *pfs, short trayNum) { trayNum--; /* make zero based */ if (pps->forms && (pps->forms[trayNum].form == pfs)) { pps->forms[trayNum].isAvailable = (pfs ? 1 : 0); /* force it */ return; /* nothing to do */ } else if ((!pps->forms) && (!pfs)) { return; /* nothing to do */ } /* * Unmount the old form. */ if (pps->forms && pps->forms[trayNum].form) { register FSTATUS *Opfs = pps->forms[trayNum].form; pps->forms[trayNum].form = 0; pps->forms[trayNum].isAvailable = 1; Opfs->mounted--; /* * Unmounting the form may make some print requests * no longer printable, because they were accepted * only because the form was already mounted. * Unmounting the form will also force some requests * to another printer (where the form is mounted) * so they can print. */ form_in_question = Opfs; (void)queue_repel (pps, 0, qchk_form); /* * Maybe an alert is due. */ check_form_alert (Opfs, (_FORM *)0); } /* * Mount the new form? */ if (pfs) { syslog(LOG_DEBUG, "remount_form add %x(%s) to tray %d\n", pfs, (pfs ? pfs->form->name : "NULL"), trayNum); if (pps && !pps->forms) { pps->forms = (PFSTATUS *)calloc((trayNum +1), sizeof(PFSTATUS)); pps->numForms = trayNum + 1; } if (pps && pps->forms && (pps->numForms > trayNum)) { pps->forms[trayNum].form = pfs; pps->forms[trayNum].isAvailable = 1; pfs->mounted++; } else { return; /* nothing to do, can't mount form, so no need to pretend we did */ } /* * Attract all the requests needing this newly mounted * form. This may cause some unnecessary shuffling, but * we have to ensure requests aren't assigned to a printer * without the form mounted, so that the alert check is * correct. */ if (pfs->requests) { form_in_question = pfs; queue_attract (pps, qchk_form, 0); /* * Maybe an alert can be shut off. */ check_form_alert (pfs, (_FORM *)0); } } else { /* * Attract first request that doesn't need a form mounted. * We only need to get one request printing, because it * completing will cause the next request to be attracted. */ form_in_question = 0; queue_attract (pps, qchk_form, 1); } dump_pstatus (); return; } /** ** remount_pwheel() - MOUNT A PRINT-WHEEL WHERE ANOTHER WAS MOUNTED **/ static void remount_pwheel(register PSTATUS *pps, char *pwheel_name) { PWSTATUS *ppws; if (SAME(pps->pwheel_name, pwheel_name)) return; /* nothing to do */ /* * Unmount the old print wheel */ if (pps->pwheel_name) { register PWSTATUS *Oppws = pps->pwheel; pps->pwheel = 0; if (Oppws) Oppws->mounted--; /* * Unmounting the print wheel may make some print * requests no longer printable, because they were * accepted only because the print wheel was already * mounted. Unmounting the print wheel will also force * some requests to another printer (where the print wheel * is mounted) so they can print. */ pwheel_in_question = pps->pwheel_name; (void)queue_repel (pps, 0, qchk_pwheel); unload_str (&pps->pwheel_name); /* * Maybe an alert is due. */ if (Oppws) check_pwheel_alert (Oppws, (PWHEEL *)0); } /* * Mount the new print wheel? */ if (pwheel_name) { load_str (&pps->pwheel_name, pwheel_name); if (ppws = search_pwstatus(pwheel_name)) { pps->pwheel = ppws; ppws->mounted++; /* * Attract all requests needing this newly * mounted print wheel. This may cause some * unnecessary shuffling, but we have to ensure * requests aren't assigned to a printer without * the print-wheel mounted, so that the alert * check is correct. */ if (ppws->requests) { pwheel_in_question = pwheel_name; queue_attract (pps, qchk_pwheel, 0); /* * Maybe an alert can be shut off. */ check_pwheel_alert (ppws, (PWHEEL *)0); } } else { /* * Attract the first request that needs this newly * mounted print wheel. If no alert has been * defined for the print wheel, we don't know how * many requests are queued waiting for it, so we * have to do this unconditionally. */ pwheel_in_question = pwheel_name; queue_attract (pps, qchk_pwheel, 1); } } else { /* * Attract the first request that doesn't need a * print wheel mounted. * We only need to get one request printing, because it * completing will cause the next request to be attracted. */ pwheel_in_question = 0; queue_attract (pps, qchk_pwheel, 1); } dump_pstatus (); return; } #define MAX_TRAYS 100 /** ** s_max_trays() **/ void s_max_trays(char *m, MESG *md) { char *printer; ushort status; short numTrays; register PSTATUS *pps; register PFSTATUS *ppfs; (void) getmessage(m, S_MAX_TRAYS, &printer, &numTrays); syslog(LOG_DEBUG, "s_max_trays(%s, %d)", (printer ? printer : "NULL"), numTrays); /* Have we seen this printer before? */ if (!*printer || !(pps = search_pstatus(printer))) status = MNODEST; /* How about the tray? */ else if ((numTrays <=0) || (numTrays > MAX_TRAYS)) status = MNOTRAY; /* If the printer is currently printing, we can't disturb it. */ else if (pps->request) status = MBUSY; else if (pps->forms) { if (!(ppfs = Realloc(pps->forms,numTrays * sizeof(PFSTATUS)))) status = MNOMEM; else { int i; for (i = pps->numForms; i < numTrays; i++) { ppfs[i].form = NULL; ppfs[i].isAvailable = 1; } pps->forms = ppfs; pps->numForms = numTrays; status = MOK; } } else if (!(ppfs = Calloc(numTrays,sizeof(PFSTATUS)))) { status = MNOMEM; } else { pps->forms = ppfs; pps->numForms = numTrays; status = MOK; } dump_pstatus(); mputm(md, R_MAX_TRAYS, status); } /** ** s_mount() **/ void s_mount(char *m, MESG *md) { char *printer, *form, *pwheel_name; ushort status; register PSTATUS *pps; register FSTATUS *pfs; (void) getmessage(m, S_MOUNT, &printer, &form, &pwheel_name); syslog(LOG_DEBUG, "s_mount(%s, %s, %s)", (printer ? printer : "NULL"), (form ? form : "NULL"), (pwheel_name ? pwheel_name : "NULL")); if (!*form && !*pwheel_name) status = MNOMEDIA; /* Have we seen this printer before? */ else if (!*printer || !(pps = search_pstatus(printer))) status = MNODEST; /* How about the form? */ else if (*form && !(pfs = search_fstatus(form))) status = MNOMEDIA; /* If the printer is currently printing, we can't disturb it. */ else if (pps->request) status = MBUSY; else { /* * Mount them. */ if (*form) remount_form (pps, pfs,1); if (*pwheel_name) remount_pwheel(pps, pwheel_name); status = MOK; } mputm(md, R_MOUNT, status); } /* * s_mount_tray() */ void s_mount_tray(char *m, MESG *md) { char *printer, *form, *pwheel_name; ushort status; short trayNum; register PSTATUS *pps; register FSTATUS *pfs; (void) getmessage(m, S_MOUNT_TRAY, &printer, &form, &pwheel_name, &trayNum); syslog(LOG_DEBUG, "s_mount_tray(%s, %s, %s, %d)", (printer ? printer : "NULL"), (form ? form : "NULL"), (pwheel_name ? pwheel_name : "NULL"), trayNum); if (!*form && !*pwheel_name) status = MNOMEDIA; /* Have we seen this printer before? */ else if (!*printer || !(pps = search_pstatus(printer))) status = MNODEST; /* How about the form? */ else if (*form && !(pfs = search_fstatus(form))) status = MNOMEDIA; /* How about the tray? */ else if ((trayNum <=0) || (trayNum > pps->numForms)) status = MNOTRAY; /* If the printer is currently printing, we can't disturb it. */ else if (pps->request) status = MBUSY; else { /* * Mount them. */ if (*form) remount_form(pps, pfs,trayNum); if (*pwheel_name) remount_pwheel(pps, pwheel_name); status = MOK; } mputm (md, R_MOUNT_TRAY, status); } /** ** s_unmount() **/ void s_unmount(char *m, MESG *md) { char *printer, *form, *pwheel_name; ushort status; register PSTATUS *pps; (void)getmessage (m, S_UNMOUNT, &printer, &form, &pwheel_name); syslog(LOG_DEBUG, "s_unmount(%s, %s, %s)", (printer ? printer : "NULL"), (form ? form : "NULL"), (pwheel_name ? pwheel_name : "NULL")); if (!*form && !*pwheel_name) status = MNOMEDIA; /* * Have we seen this printer before? */ else if (!*printer || !(pps = search_pstatus(printer))) status = MNODEST; /* * If the printer is currently printing a request, * we can't unmount the current form/pwheel. */ else if (pps->request) status = MBUSY; else { /* * Unmount them. */ if (*form) remount_form (pps, (FSTATUS *)0,1); if (*pwheel_name) remount_pwheel (pps, (char *)0); status = MOK; } mputm (md, R_UNMOUNT, status); return; } /** ** s_unmount_tray() **/ void s_unmount_tray(char *m, MESG *md) { char *printer, *form, *pwheel_name; ushort status; short trayNum; register PSTATUS *pps; (void)getmessage (m, S_UNMOUNT_TRAY, &printer, &form, &pwheel_name, &trayNum); syslog(LOG_DEBUG, "s_unmount_tray(%s, %s, %s, %d)", (printer ? printer : "NULL"), (form ? form : "NULL"), (pwheel_name ? pwheel_name : "NULL"), trayNum); if (!*form && !*pwheel_name) status = MNOMEDIA; else if (!*printer || !(pps = search_pstatus(printer))) /* haven't seen this printer before */ status = MNODEST; else if ((trayNum <=0) || (trayNum > pps->numForms)) /* haven't seen the tray before */ status = MNOTRAY; else if (pps->request) /* is the printer busy */ status = MBUSY; else { /* Unmount them. */ if (*form) remount_form (pps, (FSTATUS *)0,trayNum); if (*pwheel_name) remount_pwheel (pps, (char *)0); status = MOK; } mputm (md, R_UNMOUNT_TRAY, status); return; } /** ** s_load_form() **/ void s_load_form(char *m, MESG *md) { char *form; ushort status; register _FORM *pf; register FSTATUS *pfs; (void)getmessage (m, S_LOAD_FORM, &form); syslog(LOG_DEBUG, "s_load_form(%s)", (form ? form : "NULL")); if (!*form) /* no form specified */ status = MNODEST; else if (!(pf = Getform(form))) { /* strange or missing form */ switch (errno) { case EBADF: status = MERRDEST; break; case ENOENT: default: status = MNODEST; break; } } else if ((pfs = search_fstatus(form))) { /* Have we seen this form before? */ unload_list (&pfs->users_allowed); unload_list (&pfs->users_denied); load_userform_access ( pf->name, &pfs->users_allowed, &pfs->users_denied ); load_sdn (&pfs->cpi, pf->cpi); load_sdn (&pfs->lpi, pf->lpi); load_sdn (&pfs->plen, pf->plen); load_sdn (&pfs->pwid, pf->pwid); /* * These have to be done in the order shown, * and after the assignments above, so that all * the new information is in place for the * checks. An unfortunate side effect is that * it is possible for the alert to shut off * and then come on again, if (1) enough requests * are canceled to drop the level below the old * alert threshold, but (2) the new alert threshold * is even lower. The final alert will be correct, * though. */ form_in_question = pfs; queue_check (qchk_form); check_form_alert (pfs, pf); status = MOK; /* * Room for a new form? */ } else if ((pfs = new_fstatus(pf))) { /* * No alert is possible for a new form, of course, * but this routine does a bit more than just check * the alert. */ check_form_alert (pfs, pf); status = MOK; } else { free_form (pf); status = MNOSPACE; } mputm (md, R_LOAD_FORM, status); return; } /** ** s_unload_form() **/ static void _unload_form(register FSTATUS *pfs) { int i; short numForms; PFSTATUS *ppfs; /* * Unmount this form everywhere and get rid of it. */ for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) if (((ppfs = PStatus[i]->forms) != NULL) && ((numForms = PStatus[i]->numForms) > 0)) { int j; for ( j = 0 ; j < numForms ; j++ ) if (ppfs[j].form == pfs) ppfs[j].form= NULL; } return; } void s_unload_form(char *m, MESG *md) { char *form; ushort status; RSTATUS *prs; register FSTATUS *pfs; (void)getmessage (m, S_UNLOAD_FORM, &form); syslog(LOG_DEBUG, "s_unload_form(%s)", (form ? form : "NULL")); if (!*form || STREQU(form, NAME_ALL)) { int i; /* If we have a request queued for ANY form, we can't do it. */ status = MOK; for (i = 0; FStatus != NULL && FStatus[i] != NULL && status == MOK; i++) { for (prs = Request_List; prs != NULL; prs = prs->next) if (prs->form == FStatus[i]) { status = MBUSY; break; } } if (status == MOK) { for (i = 0; FStatus != NULL && FStatus[i] != NULL; i++) _unload_form (FStatus[i]); free(FStatus); FStatus = NULL; } } else if (!*form || !(pfs = search_fstatus(form))) /* Have we seen this form before? */ status = MNODEST; else { /* Is there even one request waiting for this form? */ status = MOK; for (prs = Request_List; prs != NULL; prs = prs->next) if (prs->form == pfs) { status = MBUSY; break; } if (status == MOK) { _unload_form (pfs); list_remove((void ***)&FStatus, (void *)pfs); } } mputm (md, R_UNLOAD_FORM, status); return; } /** ** s_load_printwheel() **/ void s_load_printwheel(char *m, MESG *md) { char *pwheel_name; ushort status; register PWHEEL *ppw; register PWSTATUS *ppws; (void)getmessage (m, S_LOAD_PRINTWHEEL, &pwheel_name); syslog(LOG_DEBUG, "s_load_printwheel(%s)", (pwheel_name ? pwheel_name : "NULL")); if (!*pwheel_name) /* no printwheel specified */ status = MNODEST; else if (!(ppw = Getpwheel(pwheel_name))) { /* Strange or missing print wheel? */ switch (errno) { case EBADF: status = MERRDEST; break; case ENOENT: default: status = MNODEST; break; } } else if ((ppws = search_pwstatus(pwheel_name))) { /* Print wheel we already know about? */ check_pwheel_alert (ppws, ppw); status = MOK; } else if ((ppws = new_pwstatus(ppw))) { /* Room for a new print wheel? */ register RSTATUS *prs; /* * Because of the quirky nature of the print wheel * structures, i.e. no structure unless an alert has * been defined, we have to run through the requests * and see which ones are waiting for this print wheel, * so we can assign alerts and count pending requests. */ for (prs = Request_List; prs != NULL; prs = prs->next) if ((prs->pwheel_name == pwheel_name) && (!one_printer_with_charsets(prs))) { prs->pwheel = ppws; ppws->requests++; } check_pwheel_alert (ppws, ppw); status = MOK; } else { freepwheel (ppw); status = MNOSPACE; } mputm (md, R_LOAD_PRINTWHEEL, status); return; } /** ** s_unload_printwheel() **/ static void _unload_pwheel(register PWSTATUS *ppws) { register PSTATUS *pps; register RSTATUS *prs; int i; /* * ``Unmount'' the alert part of this print wheel everywhere. * THIS IS NOT A COMPLETE UNMOUNT, JUST THE ALERT STRUCTURE * IS REMOVED. */ for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) if (PStatus[i]->pwheel == ppws) PStatus[i]->pwheel = 0; /* * Remove the alert part from all requests. */ for (prs = Request_List; prs; prs = prs->next) if (prs->pwheel == ppws) prs->pwheel = 0; /* * Cancel any alert pending. Here we're different from the * similar code for unloading a form, because, to be able to * unload a form we first require NO requests pending. If no * requests are pending there should be no alert to cancel. * Print wheels, on the other hand, only exist as names and * alerts. We can always unload a ``print wheel'' because * all we're really unloading is an alert. Thus, there can * be requests queued for the print wheel (the name), and * thus there can be an alert running. */ if (ppws->alert->active) cancel_alert (A_PWHEEL, ppws); free_pwstatus(ppws); return; } void s_unload_printwheel(char *m, MESG *md) { char *pwheel_name; ushort status; register PWSTATUS *ppws; /* * We don't care if any requests are waiting for the print * wheel(s)--what we're removing here is (are) just the alert(s)! */ (void)getmessage (m, S_UNLOAD_PRINTWHEEL, &pwheel_name); syslog(LOG_DEBUG, "s_unload_printwheel(%s)", (pwheel_name ? pwheel_name : "NULL")); /* * Remove all print wheel alerts? */ if (!*pwheel_name || STREQU(pwheel_name, NAME_ALL)) { int i; for (i = 0; PWStatus != NULL && PWStatus[i] != NULL; i++) _unload_pwheel (PWStatus[i]); free(PWStatus); PWStatus = NULL; status = MOK; /* * Have we seen this print wheel before? */ } else if (!(ppws = search_pwstatus(pwheel_name))) status = MNODEST; else { _unload_pwheel (ppws); list_remove((void ***)&PWStatus, (void *)ppws); status = MOK; } mputm (md, R_UNLOAD_PRINTWHEEL, status); return; }