/*
* 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 <syslog.h>
#include <time.h>
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, "", "");
}
}