disp4.c revision 19d32b9ab53d17ac6605971e14c45a5281f8d9bb
/*
* 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 "time.h"
#include "dispatch.h"
#include <syslog.h>
/**
** s_accept_dest()
**/
void
s_accept_dest(char *m, MESG *md)
{
char *destination;
ushort status;
register PSTATUS *pps;
register CLSTATUS *pcs;
getmessage (m, S_ACCEPT_DEST, &destination);
syslog(LOG_DEBUG, "s_accept_dest(%s)",
(destination ? destination : "NULL"));
/*
* Have we seen this destination as a printer?
*/
if ((pps = search_pstatus(destination)))
if ((pps->status & PS_REJECTED) == 0)
status = MERRDEST;
else {
pps->status &= ~PS_REJECTED;
(void) time (&pps->rej_date);
dump_pstatus ();
status = MOK;
}
/*
* Have we seen this destination as a class?
*/
else if ((pcs = search_cstatus(destination)))
if ((pcs->status & CS_REJECTED) == 0)
status = MERRDEST;
else {
pcs->status &= ~CS_REJECTED;
(void) time (&pcs->rej_date);
dump_cstatus ();
status = MOK;
}
else
status = MNODEST;
mputm (md, R_ACCEPT_DEST, status);
return;
}
/**
** s_reject_dest()
**/
void
s_reject_dest(char *m, MESG *md)
{
char *destination,
*reason;
ushort status;
register PSTATUS *pps;
register CLSTATUS *pcs;
getmessage (m, S_REJECT_DEST, &destination, &reason);
syslog(LOG_DEBUG, "s_reject_dest(%s, %s)",
(destination ? destination : "NULL"),
(reason ? reason : "NULL"));
/*
* Have we seen this destination as a printer?
*/
if ((pps = search_pstatus(destination)))
if (pps->status & PS_REJECTED)
status = MERRDEST;
else {
pps->status |= PS_REJECTED;
(void) time (&pps->rej_date);
load_str (&pps->rej_reason, reason);
dump_pstatus ();
status = MOK;
}
/*
* Have we seen this destination as a class?
*/
else if ((pcs = search_cstatus(destination)))
if (pcs->status & CS_REJECTED)
status = MERRDEST;
else {
pcs->status |= CS_REJECTED;
(void) time (&pcs->rej_date);
load_str (&pcs->rej_reason, reason);
dump_cstatus ();
status = MOK;
}
else
status = MNODEST;
mputm (md, R_REJECT_DEST, status);
return;
}
/**
** s_enable_dest()
**/
void
s_enable_dest(char *m, MESG *md)
{
char *printer;
ushort status;
register PSTATUS *pps;
getmessage (m, S_ENABLE_DEST, &printer);
syslog(LOG_DEBUG, "s_enable_dest(%s)", (printer ? printer : "NULL"));
/*
* Have we seen this printer before?
*/
if ((pps = search_pstatus(printer)))
if (enable(pps) == -1)
status = MERRDEST;
else
status = MOK;
else
status = MNODEST;
mputm (md, R_ENABLE_DEST, status);
return;
}
/**
** s_disable_dest()
**/
void
s_disable_dest(char *m, MESG *md)
{
char *destination,
*reason,
*req_id = 0;
ushort when,
status;
register PSTATUS *pps;
getmessage (m, S_DISABLE_DEST, &destination, &reason, &when);
syslog(LOG_DEBUG, "s_disable_dest(%s, %s, %d)",
(destination ? destination : "NULL"),
(reason ? reason : "NULL"), when);
/*
* Have we seen this printer before?
*/
if ((pps = search_pstatus(destination))) {
/*
* If we are to cancel a currently printing request,
* we will send back the request's ID.
* Save a copy of the ID before calling "disable()",
* in case the disabling loses it (e.g. the request
* might get attached to another printer). (Actually,
* the current implementation won't DETACH the request
* from this printer until the child process responds,
* but a future implementation might.)
*/
if (pps->request && when == 2)
req_id = Strdup(pps->request->secure->req_id);
if (disable(pps, reason, (int)when) == -1) {
if (req_id) {
Free (req_id);
req_id = 0;
}
status = MERRDEST;
} else
status = MOK;
} else
status = MNODEST;
mputm (md, R_DISABLE_DEST, status, NB(req_id));
if (req_id)
Free (req_id);
return;
}
/**
** s_load_filter_table()
**/
void
s_load_filter_table(char *m, MESG *md)
{
ushort status;
syslog(LOG_DEBUG, "s_load_filter_table()");
trash_filters ();
if (Loadfilters((char *)0) == -1)
status = MNOOPEN;
else {
/*
* This is what makes changing filters expensive!
*/
queue_check (qchk_filter);
status = MOK;
}
mputm (md, R_LOAD_FILTER_TABLE, status);
return;
}
/**
** s_unload_filter_table()
**/
void
s_unload_filter_table(char *m, MESG *md)
{
syslog(LOG_DEBUG, "s_unload_filter_table()");
trash_filters ();
/*
* This is what makes changing filters expensive!
*/
queue_check (qchk_filter);
mputm (md, R_UNLOAD_FILTER_TABLE, MOK);
return;
}
/**
** s_load_user_file()
**/
void
s_load_user_file(char *m, MESG *md)
{
/*
* The first call to "getuser()" will load the whole file.
*/
syslog(LOG_DEBUG, "s_load_user_file()");
trashusers ();
mputm (md, R_LOAD_USER_FILE, MOK);
return;
}
/**
** s_unload_user_file()
**/
void
s_unload_user_file(char *m, MESG *md)
{
syslog(LOG_DEBUG, "s_unload_user_file()");
trashusers (); /* THIS WON'T DO TRUE UNLOAD, SORRY! */
mputm (md, R_UNLOAD_USER_FILE, MOK);
return;
}
/**
** s_shutdown()
**/
void
s_shutdown(char *m, MESG *md)
{
ushort immediate;
(void)getmessage (m, S_SHUTDOWN, &immediate);
syslog(LOG_DEBUG, "s_shutdown(%d)", immediate);
switch (md->type) {
case MD_STREAM:
case MD_SYS_FIFO:
case MD_USR_FIFO:
mputm (md, R_SHUTDOWN, MOK);
lpshut (immediate);
/*NOTREACHED*/
default:
syslog(LOG_DEBUG,
"Received S_SHUTDOWN on a type %d connection\n",
md->type);
}
return;
}
/**
** s_quiet_alert()
**/
void
s_quiet_alert(char *m, MESG *md)
{
char *name;
ushort type,
status;
register FSTATUS *pfs;
register PSTATUS *pps;
register PWSTATUS *ppws;
/*
* We quiet an alert by cancelling it with "cancel_alert()"
* and then resetting the active flag. This effectively just
* terminates the process running the alert but tricks the
* rest of the Spooler into thinking it is still active.
* The alert will be reactivated only AFTER "cancel_alert()"
* has been called (to clear the active flag) and then "alert()"
* is called again. Thus:
*
* For printer faults the alert will be reactivated when:
* - a fault is found after the current fault has been
* cleared (i.e. after successful print or after manually
* enabled).
*
* For forms/print-wheels the alert will be reactivated when:
* - the form/print-wheel becomes mounted and then unmounted
* again, with too many requests still pending;
* - the number of requests falls below the threshold and
* then rises above it again.
*/
(void)getmessage (m, S_QUIET_ALERT, &name, &type);
syslog(LOG_DEBUG, "s_quiet_alert(%s, %d)", (name ? name : "NULL"),
type);
if (!*name)
status = MNODEST;
else switch (type) {
case QA_FORM:
if (!(pfs = search_fstatus(name)))
status = MNODEST;
else if (!pfs->alert->active)
status = MERRDEST;
else {
cancel_alert (A_FORM, pfs);
pfs->alert->active = 1;
status = MOK;
}
break;
case QA_PRINTER:
if (!(pps = search_pstatus(name)))
status = MNODEST;
else if (!pps->alert->active)
status = MERRDEST;
else {
cancel_alert (A_PRINTER, pps);
pps->alert->active = 1;
status = MOK;
}
break;
case QA_PRINTWHEEL:
if (!(ppws = search_pwstatus(name)))
status = MNODEST;
else if (!ppws->alert->active)
status = MERRDEST;
else {
cancel_alert (A_PWHEEL, ppws);
ppws->alert->active = 1;
status = MOK;
}
break;
}
mputm (md, R_QUIET_ALERT, status);
return;
}
/**
** s_send_fault()
**/
void
s_send_fault(char *m, MESG *md)
{
long key;
char *printerOrForm, *alert_text;
ushort status;
register PSTATUS *pps;
getmessage (m, S_SEND_FAULT, &printerOrForm, &key, &alert_text);
syslog(LOG_DEBUG, "s_send_fault(%s, %x, %s)",
(printerOrForm ? printerOrForm : "NULL"), key,
(alert_text ? alert_text : "NULL"));
if (!(pps = search_pstatus(printerOrForm)) || (!pps->exec) ||
pps->exec->key != key || !pps->request) {
status = MERRDEST;
} else {
printer_fault(pps, pps->request, alert_text, 0);
status = MOK;
}
mputm (md, R_SEND_FAULT, status);
}
/*
* s_clear_fault()
*/
void
s_clear_fault(char *m, MESG *md)
{
long key;
char *printerOrForm, *alert_text;
ushort status;
register PSTATUS *pps;
getmessage(m, S_CLEAR_FAULT, &printerOrForm, &key, &alert_text);
syslog(LOG_DEBUG, "s_clear_fault(%s, %x, %s)",
(printerOrForm ? printerOrForm : "NULL"), key,
(alert_text ? alert_text : "NULL"));
if (! (pps = search_pstatus(printerOrForm)) || ((key > 0) &&
((!pps->exec) || pps->exec->key != key || !pps->request ))) {
status = MERRDEST;
} else {
clear_printer_fault(pps, alert_text);
status = MOK;
}
mputm (md, R_CLEAR_FAULT, status);
}
/*
* s_paper_changed()
*/
void
s_paper_changed(char *m, MESG *md)
{
short trayNum, mode, pagesPrinted;
char *printer, *paper;
ushort status;
short chgd = 0;
register PSTATUS *pps;
register FSTATUS *pfs,*pfsWas;
getmessage(m, S_PAPER_CHANGED, &printer, &trayNum, &paper, &mode,
&pagesPrinted);
syslog(LOG_DEBUG, "s_paper_changed(%s, %d, %s, %d, %d)",
(printer ? printer : "NULL"), trayNum, (paper ? paper : "NULL"),
mode, pagesPrinted);
if (!(pps = search_pstatus(printer)))
status = MNODEST;
else if ((trayNum <=0) || (trayNum > pps->numForms))
status = MNOTRAY;
else {
status = MOK;
if (*paper && (pfsWas = pps->forms[trayNum-1].form) &&
(!STREQU(pfsWas->form->paper,paper))) {
pfs = search_fptable(paper);
if (pfs) {
remount_form(pps, pfs, trayNum);
chgd = 1;
} else
status = MNOMEDIA;
}
if ( status == MOK ) {
pps->forms[trayNum].isAvailable = mode;
if ((chgd || !mode) && (!pagesPrinted) && pps->exec) {
if (pps->request)
pps->request->request->outcome |=
RS_STOPPED;
terminate(pps->exec);
schedule(EV_LATER, 1, EV_INTERF, pps);
}
}
}
mputm(md, R_PAPER_CHANGED, status);
}