/* * 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 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include "dispatch.h" #include #include char *showForms(PSTATUS *); /* * untidbit_all() - CALL untidbit() FOR A LIST OF TYPES */ static void untidbit_all (char **printer_types) { char ** pl; for (pl = printer_types; *pl; pl++) untidbit (*pl); return; } /* * s_load_printer() */ void s_load_printer(char *m, MESG *md) { char *printer; ushort status; register PRINTER *pp; register PSTATUS *pps; char **paperDenied; (void) getmessage(m, S_LOAD_PRINTER, &printer); syslog(LOG_DEBUG, "s_load_printer(%s)", (printer ? printer : "NULL")); if (!*printer) /* no printer */ status = MNODEST; else if (!(pp = Getprinter(printer))) { /* Strange or missing printer? */ switch (errno) { case EBADF: status = MERRDEST; break; case ENOENT: default: status = MNODEST; break; } } else if ((pps = search_pstatus(printer))) { /* Printer we know about already? */ PRINTER *op = pps->printer; pps->printer = pp; /* * Ensure that an old Terminfo type that's no longer * needed gets freed, and that an existing type gets * reloaded (in case it has been changed). */ untidbit_all (op->printer_types); untidbit_all (pp->printer_types); /* * Does an alert get affected? * - Different command? * - Different wait interval? */ if (pps->alert->active) if (!SAME(pp->fault_alert.shcmd, op->fault_alert.shcmd) || pp->fault_alert.W != op->fault_alert.W) { /* * We can't use "cancel_alert()" here * because it will remove the message. * We'll do half of the cancel, then * check if we need to run the new alert, * and remove the message if not. */ pps->alert->active = 0; terminate (pps->alert->exec); if (pp->fault_alert.shcmd) alert(A_PRINTER, pps, (RSTATUS *)0, (char *)0); else Unlink (pps->alert->msgfile); } freeprinter (op); unload_list (&pps->users_allowed); unload_list (&pps->users_denied); unload_list (&pps->forms_allowed); unload_list (&pps->forms_denied); load_userprinter_access(pp->name, &pps->users_allowed, &pps->users_denied); load_formprinter_access(pp->name, &pps->forms_allowed, &pps->forms_denied); unload_list (&pps->paper_allowed); load_paperprinter_access(pp->name, &pps->paper_allowed, &paperDenied); freelist(paperDenied); load_sdn (&pps->cpi, pp->cpi); load_sdn (&pps->lpi, pp->lpi); load_sdn (&pps->plen, pp->plen); load_sdn (&pps->pwid, pp->pwid); pps->last_dial_rc = 0; pps->nretry = 0; /* * Evaluate all requests queued for this printer, * to make sure they are still eligible. They will * get moved to another printer, get (re)filtered, * or get canceled. */ (void) queue_repel(pps, 0, (qchk_fnc_type)0); status = MOK; } else if (pp->remote) { /* don't really load a remote printer */ status = MOK; } else if ((pps = new_pstatus(pp))) { pps->status = PS_DISABLED | PS_REJECTED; load_str (&pps->dis_reason, CUZ_NEW_PRINTER); load_str (&pps->rej_reason, CUZ_NEW_DEST); load_str (&pps->fault_reason, CUZ_PRINTING_OK); time (&pps->dis_date); time (&pps->rej_date); dump_pstatus (); status = MOK; } else { freeprinter (pp); status = MNOSPACE; } mputm (md, R_LOAD_PRINTER, status); return; } /* * s_unload_printer() */ static void _unload_printer(PSTATUS *pps) { int i; if (pps->alert->active) cancel_alert (A_PRINTER, pps); /* * Remove this printer from the classes it may be in. * This is likely to be redundant, i.e. upon deleting * a printer the caller is SUPPOSED TO check all the * classes; any that contain the printer will be changed * and we should receive a S_LOAD_CLASS message for each * to reload the class. * * HOWEVER, this leaves a (small) window where someone * can sneak a request in destined for the CLASS. If * we have deleted the printer but still have it in the * class, we may have trouble! */ for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++) (void) dellist(&(CStatus[i]->class->members), pps->printer->name); free_pstatus(pps); /* * this is removed from the PStatus table by the caller * list_remove((void ***)&PStatus, (void *)pps); */ return; } void s_unload_printer(char *m, MESG *md) { char *printer; ushort status; register PSTATUS *pps; (void) getmessage(m, S_UNLOAD_PRINTER, &printer); syslog(LOG_DEBUG, "s_unload_printer(%s)", (printer ? printer : "NULL")); if (!*printer || STREQU(printer, NAME_ALL)) /* Unload ALL printers */ if (!Request_List) /* If we have ANY requests queued, we can't do it. */ status = MBUSY; else { int i; for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) _unload_printer (PStatus[i]); free(PStatus); PStatus = NULL; status = MOK; } else if (!(pps = search_pstatus(printer))) /* Have we seen this printer before */ status = MNODEST; else { /* * Note: This routine WILL MOVE requests to another * printer. It will not stop until it has gone through * the entire list of requests, so all requests that * can be moved will be moved. If any couldn't move, * however, we don't unload the printer. */ if (queue_repel(pps, 1, (qchk_fnc_type)0)) status = MOK; else status = MBUSY; if (status == MOK) { _unload_printer (pps); list_remove((void ***)&PStatus, (void *)pps); } } if (status == MOK) dump_pstatus (); mputm (md, R_UNLOAD_PRINTER, status); return; } /* * combineReasons() */ static char * combineReasons(PSTATUS *pps, char *freeReason) { char *reason = NULL; if (pps->status & PS_FAULTED) { if ((pps->status & (PS_DISABLED | PS_LATER)) && (!STREQU(pps->dis_reason, CUZ_STOPPED)) && (addstring(&reason, "Fault reason: ") == 0) && (addstring(&reason, pps->fault_reason) == 0) && (addstring(&reason, "\n\tDisable reason: ") == 0) && (addstring(&reason, pps->dis_reason) == 0)) *freeReason = 1; else { if (reason) /* memory allocation failed part way through */ Free(reason); reason = pps->fault_reason; *freeReason = 0; } } else { reason = pps->dis_reason; *freeReason = 0; } return (reason); } static void local_printer_status(MESG *md, PSTATUS *pps, short status) { char *reason = NULL; char freeReason = 0; char *formList = NULL; reason = combineReasons(pps, &freeReason); formList = showForms(pps); send(md, R_INQUIRE_PRINTER_STATUS, status, pps->printer->name, (formList ? formList : ""), (pps->pwheel_name ? pps->pwheel_name : ""), reason, pps->rej_reason, pps->status, (pps->request ? pps->request->secure->req_id : ""), pps->dis_date, pps->rej_date); if (formList) Free(formList); if (freeReason) Free(reason); } /* * s_inquire_printer_status() */ void s_inquire_printer_status(char *m, MESG *md) { char *printer; register PSTATUS *pps; (void) getmessage(m, S_INQUIRE_PRINTER_STATUS, &printer); syslog(LOG_DEBUG, "s_inquire_printer_status(%s)", printer); if (!*printer || STREQU(printer, NAME_ALL)) { /* inquire about all printers */ int i; for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) { pps = PStatus[i]; if (PStatus[i + 1] != NULL) local_printer_status(md, pps, MOKMORE); } } else /* inquire about a specific printer */ pps = search_pstatus(printer); if (pps) local_printer_status(md, pps, MOK); else { mputm(md, R_INQUIRE_PRINTER_STATUS, MNODEST, "", "", "", "", "", 0, "", 0L, 0L); } } /* * s_load_class() */ void s_load_class(char *m, MESG *md) { char *class; ushort status; register CLASS *pc; register CLSTATUS *pcs; (void) getmessage(m, S_LOAD_CLASS, &class); syslog(LOG_DEBUG, "s_load_class(%s)", (class ? class : "NULL")); if (!*class) /* no class defined */ status = MNODEST; else if (!(pc = Getclass(class))) { /* Strange or missing class */ switch (errno) { case EBADF: status = MERRDEST; break; case ENOENT: default: status = MNODEST; break; } } else if ((pcs = search_cstatus(class))) { /* Class we already know about */ register RSTATUS *prs; freeclass (pcs->class); pcs->class = pc; /* * Here we go through the list of requests * to see who gets affected. */ for (prs = Request_List; prs != NULL; prs = prs->next) if (STREQU(prs->request->destination, class)) { /* * If not still eligible for this class... */ switch (validate_request(prs, (char **)0, 1)) { case MOK: case MERRDEST: /* rejecting (shouldn't happen) */ break; case MDENYDEST: case MNOMOUNT: case MNOMEDIA: case MNOFILTER: default: /* * ...then too bad! */ cancel (prs, 1); break; } } status = MOK; } else if ((pcs = new_cstatus(pc))) { /* Room for new class? */ pcs->status = CS_REJECTED; load_str (&pcs->rej_reason, CUZ_NEW_DEST); time (&pcs->rej_date); dump_cstatus (); status = MOK; } else { freeclass (pc); status = MNOSPACE; } mputm (md, R_LOAD_CLASS, status); return; } /* * s_unload_class() */ static void _unload_class(CLSTATUS *pcs) { freeclass (pcs->class); if (pcs->rej_reason != NULL) Free (pcs->rej_reason); Free(pcs); return; } void s_unload_class(char *m, MESG *md) { char *class; ushort status; RSTATUS *prs; register CLSTATUS *pcs; (void) getmessage(m, S_UNLOAD_CLASS, &class); syslog(LOG_DEBUG, "s_unload_class(%s)", (class ? class : "NULL")); /* * Unload ALL classes? */ if (!*class || STREQU(class, NAME_ALL)) { int i; /* * If we have a request queued for a member of ANY * class, we can't do it. */ status = MOK; for (i = 0; ((CStatus[i] != NULL) && (status == MOK)); i++) { for (prs = Request_List; prs != NULL; prs = prs->next) if (STREQU(prs->request->destination, CStatus[i]->class->name)) { status = MBUSY; break; } } if (status == MOK) { for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++) _unload_class (CStatus[i]); free(CStatus); CStatus = NULL; } /* * Have we seen this class before? */ } else if (!(pcs = search_cstatus(class))) status = MNODEST; /* * Is there even one request queued for this class? * If not, we can safely remove it. */ else { status = MOK; for (prs = Request_List; prs != NULL; prs = prs->next) if (STREQU(prs->request->destination, class)) { status = MBUSY; break; } if (status == MOK) { _unload_class (pcs); list_remove((void ***)&CStatus, (void *)pcs); } } if (status == MOK) dump_cstatus (); mputm (md, R_UNLOAD_CLASS, status); return; } /* * s_inquire_class() */ void s_inquire_class(char *m, MESG *md) { char *class; register CLSTATUS *pcs; (void) getmessage(m, S_INQUIRE_CLASS, &class); syslog(LOG_DEBUG, "s_inquire_class(%s)", (class ? class : "NULL")); if (!*class || STREQU(class, NAME_ALL)) { /* inquire about ALL classes */ int i; for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++) { pcs = CStatus[i]; if (CStatus[i + 1] != NULL) send(md, R_INQUIRE_CLASS, MOKMORE, pcs->class->name, pcs->status, pcs->rej_reason, pcs->rej_date); } } else /* inquire about a single class */ pcs = search_cstatus(class); if (pcs) send(md, R_INQUIRE_CLASS, MOK, pcs->class->name, pcs->status, pcs->rej_reason, pcs->rej_date); else mputm (md, R_INQUIRE_CLASS, MNODEST, "", 0, "", 0L); return; } /* * s_paper_allowed() */ void s_paper_allowed(char *m, MESG *md) { char *printer; char *paperList = NULL; register PSTATUS *pps, *ppsnext; (void) getmessage(m, S_PAPER_ALLOWED, &printer); syslog(LOG_DEBUG, "s_paper_allowed(%s)", (printer ? printer : "NULL")); if (!*printer || STREQU(printer, NAME_ALL)) { /* inquire about ALL printers */ int i; for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) { pps = PStatus[i]; if (PStatus[i + 1] != NULL) { paperList = sprintlist(pps->paper_allowed); send(md, R_PAPER_ALLOWED, MOKMORE, pps->printer->name, (paperList ? paperList : "")); if (paperList) Free(paperList); } } } else /* inquire about a specific printer */ pps = search_pstatus(printer); if (pps) { paperList = sprintlist(pps->paper_allowed); send(md, R_PAPER_ALLOWED, MOK, pps->printer->name, (paperList ? paperList : "")); if (paperList) Free(paperList); } else { mputm(md, R_PAPER_ALLOWED, MNODEST, "", ""); } }