Home | History | Annotate | Download | only in lpsched
      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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All Rights Reserved  	*/
     28 
     29 
     30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     31 
     32 #include "time.h"
     33 #include "dispatch.h"
     34 #include <syslog.h>
     35 
     36 
     37 /**
     38  ** s_accept_dest()
     39  **/
     40 
     41 void
     42 s_accept_dest(char *m, MESG *md)
     43 {
     44 	char			*destination;
     45 	ushort			status;
     46 	register PSTATUS	*pps;
     47 	register CSTATUS	*pcs;
     48 
     49 	getmessage (m, S_ACCEPT_DEST, &destination);
     50 	syslog(LOG_DEBUG, "s_accept_dest(%s)",
     51 	       (destination ? destination : "NULL"));
     52 
     53 	/*
     54 	 * Have we seen this destination as a printer?
     55 	 */
     56 	if ((pps = search_pstatus(destination)))
     57 		if ((pps->status & PS_REJECTED) == 0)
     58 			status = MERRDEST;
     59 		else {
     60 			pps->status &= ~PS_REJECTED;
     61 			(void) time (&pps->rej_date);
     62 			dump_pstatus ();
     63 			status = MOK;
     64 		}
     65 
     66 	/*
     67 	 * Have we seen this destination as a class?
     68 	 */
     69 	else if ((pcs = search_cstatus(destination)))
     70 		if ((pcs->status & CS_REJECTED) == 0)
     71 			status = MERRDEST;
     72 		else {
     73 			pcs->status &= ~CS_REJECTED;
     74 			(void) time (&pcs->rej_date);
     75 			dump_cstatus ();
     76 			status = MOK;
     77 		}
     78 
     79 	else
     80 		status = MNODEST;
     81 
     82 	mputm (md, R_ACCEPT_DEST, status);
     83 	return;
     84 }
     85 
     86 /**
     87  ** s_reject_dest()
     88  **/
     89 
     90 void
     91 s_reject_dest(char *m, MESG *md)
     92 {
     93 	char			*destination,
     94 				*reason;
     95 	ushort			status;
     96 	register PSTATUS	*pps;
     97 	register CSTATUS	*pcs;
     98 
     99 
    100 	getmessage (m, S_REJECT_DEST, &destination, &reason);
    101 	syslog(LOG_DEBUG, "s_reject_dest(%s, %s)",
    102 	       (destination ? destination : "NULL"),
    103 	       (reason ? reason : "NULL"));
    104 
    105 	/*
    106 	 * Have we seen this destination as a printer?
    107 	 */
    108 	if ((pps = search_pstatus(destination)))
    109 		if (pps->status & PS_REJECTED)
    110 			status = MERRDEST;
    111 		else {
    112 			pps->status |= PS_REJECTED;
    113 			(void) time (&pps->rej_date);
    114 			load_str (&pps->rej_reason, reason);
    115 			dump_pstatus ();
    116 			status = MOK;
    117 		}
    118 
    119 	/*
    120 	 * Have we seen this destination as a class?
    121 	 */
    122 	else if ((pcs = search_cstatus(destination)))
    123 		if (pcs->status & CS_REJECTED)
    124 			status = MERRDEST;
    125 		else {
    126 			pcs->status |= CS_REJECTED;
    127 			(void) time (&pcs->rej_date);
    128 			load_str (&pcs->rej_reason, reason);
    129 			dump_cstatus ();
    130 			status = MOK;
    131 		}
    132 
    133 	else
    134 		status = MNODEST;
    135 
    136 	mputm (md, R_REJECT_DEST, status);
    137 	return;
    138 }
    139 
    140 /**
    141  ** s_enable_dest()
    142  **/
    143 
    144 void
    145 s_enable_dest(char *m, MESG *md)
    146 {
    147 	char			*printer;
    148 	ushort			status;
    149 	register PSTATUS	*pps;
    150 
    151 
    152 	getmessage (m, S_ENABLE_DEST, &printer);
    153 	syslog(LOG_DEBUG, "s_enable_dest(%s)", (printer ? printer : "NULL"));
    154 
    155 	/*
    156 	 * Have we seen this printer before?
    157 	 */
    158 	if ((pps = search_pstatus(printer)))
    159 		if (enable(pps) == -1)
    160 			status = MERRDEST;
    161 		else
    162 			status = MOK;
    163 	else
    164 		status = MNODEST;
    165 
    166 	mputm (md, R_ENABLE_DEST, status);
    167 	return;
    168 }
    169 
    170 /**
    171  ** s_disable_dest()
    172  **/
    173 
    174 void
    175 s_disable_dest(char *m, MESG *md)
    176 {
    177 	char			*destination,
    178 				*reason,
    179 				*req_id		= 0;
    180 	ushort			when,
    181 				status;
    182 	register PSTATUS	*pps;
    183 
    184 	getmessage (m, S_DISABLE_DEST, &destination, &reason, &when);
    185 	syslog(LOG_DEBUG, "s_disable_dest(%s, %s, %d)",
    186 	       (destination ? destination : "NULL"),
    187 	       (reason ? reason : "NULL"), when);
    188 
    189 
    190 	/*
    191 	 * Have we seen this printer before?
    192 	 */
    193 	if ((pps = search_pstatus(destination))) {
    194 
    195 		/*
    196 		 * If we are to cancel a currently printing request,
    197 		 * we will send back the request's ID.
    198 		 * Save a copy of the ID before calling "disable()",
    199 		 * in case the disabling loses it (e.g. the request
    200 		 * might get attached to another printer). (Actually,
    201 		 * the current implementation won't DETACH the request
    202 		 * from this printer until the child process responds,
    203 		 * but a future implementation might.)
    204 		 */
    205 		if (pps->request && when == 2)
    206 			req_id = Strdup(pps->request->secure->req_id);
    207 
    208 		if (disable(pps, reason, (int)when) == -1) {
    209 			if (req_id) {
    210 				Free (req_id);
    211 				req_id = 0;
    212 			}
    213 			status = MERRDEST;
    214 		} else
    215 			status = MOK;
    216 
    217 	} else
    218 		status = MNODEST;
    219 
    220 	mputm (md, R_DISABLE_DEST, status, NB(req_id));
    221 	if (req_id)
    222 		Free (req_id);
    223 
    224 	return;
    225 }
    226 
    227 /**
    228  ** s_load_filter_table()
    229  **/
    230 
    231 void
    232 s_load_filter_table(char *m, MESG *md)
    233 {
    234 	ushort			status;
    235 
    236 	syslog(LOG_DEBUG, "s_load_filter_table()");
    237 
    238 	trash_filters ();
    239 	if (Loadfilters((char *)0) == -1)
    240 		status = MNOOPEN;
    241 	else {
    242 		/*
    243 		 * This is what makes changing filters expensive!
    244 		 */
    245 		queue_check (qchk_filter);
    246 
    247 		status = MOK;
    248 	}
    249 
    250 	mputm (md, R_LOAD_FILTER_TABLE, status);
    251 	return;
    252 }
    253 
    254 /**
    255  ** s_unload_filter_table()
    256  **/
    257 
    258 void
    259 s_unload_filter_table(char *m, MESG *md)
    260 {
    261 	syslog(LOG_DEBUG, "s_unload_filter_table()");
    262 
    263 	trash_filters ();
    264 
    265 	/*
    266 	 * This is what makes changing filters expensive!
    267 	 */
    268 	queue_check (qchk_filter);
    269 
    270 	mputm (md, R_UNLOAD_FILTER_TABLE, MOK);
    271 	return;
    272 }
    273 
    274 /**
    275  ** s_load_user_file()
    276  **/
    277 
    278 void
    279 s_load_user_file(char *m, MESG *md)
    280 {
    281 	/*
    282 	 * The first call to "getuser()" will load the whole file.
    283 	 */
    284 	syslog(LOG_DEBUG, "s_load_user_file()");
    285 
    286 	trashusers ();
    287 
    288 	mputm (md, R_LOAD_USER_FILE, MOK);
    289 	return;
    290 }
    291 
    292 /**
    293  ** s_unload_user_file()
    294  **/
    295 
    296 void
    297 s_unload_user_file(char *m, MESG *md)
    298 {
    299 	syslog(LOG_DEBUG, "s_unload_user_file()");
    300 
    301 	trashusers ();	/* THIS WON'T DO TRUE UNLOAD, SORRY! */
    302 
    303 	mputm (md, R_UNLOAD_USER_FILE, MOK);
    304 	return;
    305 }
    306 /**
    307  ** s_shutdown()
    308  **/
    309 
    310 void
    311 s_shutdown(char *m, MESG *md)
    312 {
    313 	ushort			immediate;
    314 
    315 	(void)getmessage (m, S_SHUTDOWN, &immediate);
    316 	syslog(LOG_DEBUG, "s_shutdown(%d)", immediate);
    317 
    318 	switch (md->type) {
    319 	case MD_STREAM:
    320 	case MD_SYS_FIFO:
    321 	case MD_USR_FIFO:
    322 		mputm (md, R_SHUTDOWN, MOK);
    323 		lpshut (immediate);
    324 		/*NOTREACHED*/
    325 	default:
    326 		syslog(LOG_DEBUG,
    327 		       "Received S_SHUTDOWN on a type %d connection\n",
    328 		       md->type);
    329 	}
    330 
    331 	return;
    332 }
    333 
    334 /**
    335  ** s_quiet_alert()
    336  **/
    337 
    338 void
    339 s_quiet_alert(char *m, MESG *md)
    340 {
    341 	char			*name;
    342 	ushort			type,
    343 				status;
    344 	register FSTATUS	*pfs;
    345 	register PSTATUS	*pps;
    346 	register PWSTATUS	*ppws;
    347 
    348 
    349 	/*
    350 	 * We quiet an alert by cancelling it with "cancel_alert()"
    351 	 * and then resetting the active flag. This effectively just
    352 	 * terminates the process running the alert but tricks the
    353 	 * rest of the Spooler into thinking it is still active.
    354 	 * The alert will be reactivated only AFTER "cancel_alert()"
    355 	 * has been called (to clear the active flag) and then "alert()"
    356 	 * is called again. Thus:
    357 	 *
    358 	 * For printer faults the alert will be reactivated when:
    359 	 *	- a fault is found after the current fault has been
    360 	 *	  cleared (i.e. after successful print or after manually
    361 	 *	  enabled).
    362 	 *
    363 	 * For forms/print-wheels the alert will be reactivated when:
    364 	 *	- the form/print-wheel becomes mounted and then unmounted
    365 	 *	  again, with too many requests still pending;
    366 	 *	- the number of requests falls below the threshold and
    367 	 *	  then rises above it again.
    368 	 */
    369 
    370 	(void)getmessage (m, S_QUIET_ALERT, &name, &type);
    371 	syslog(LOG_DEBUG, "s_quiet_alert(%s, %d)", (name ? name : "NULL"),
    372 	       type);
    373 
    374 	if (!*name)
    375 		status = MNODEST;
    376 
    377 	else switch (type) {
    378 	case QA_FORM:
    379 		if (!(pfs = search_fstatus(name)))
    380 			status = MNODEST;
    381 
    382 		else if (!pfs->alert->active)
    383 			status = MERRDEST;
    384 
    385 		else {
    386 			cancel_alert (A_FORM, pfs);
    387 			pfs->alert->active = 1;
    388 			status = MOK;
    389 		}
    390 		break;
    391 
    392 	case QA_PRINTER:
    393 		if (!(pps = search_pstatus(name)))
    394 			status = MNODEST;
    395 
    396 		else if (!pps->alert->active)
    397 			status = MERRDEST;
    398 
    399 		else {
    400 			cancel_alert (A_PRINTER, pps);
    401 			pps->alert->active = 1;
    402 			status = MOK;
    403 		}
    404 		break;
    405 
    406 	case QA_PRINTWHEEL:
    407 		if (!(ppws = search_pwstatus(name)))
    408 			status = MNODEST;
    409 
    410 		else if (!ppws->alert->active)
    411 			status = MERRDEST;
    412 
    413 		else {
    414 			cancel_alert (A_PWHEEL, ppws);
    415 			ppws->alert->active = 1;
    416 			status = MOK;
    417 		}
    418 		break;
    419 	}
    420 
    421 	mputm (md, R_QUIET_ALERT, status);
    422 	return;
    423 }
    424 
    425 /**
    426  ** s_send_fault()
    427  **/
    428 
    429 void
    430 s_send_fault(char *m, MESG *md)
    431 {
    432 	long			key;
    433 	char			*printerOrForm, *alert_text;
    434 	ushort			status;
    435 	register PSTATUS	*pps;
    436 
    437 	getmessage (m, S_SEND_FAULT, &printerOrForm, &key, &alert_text);
    438 	syslog(LOG_DEBUG, "s_send_fault(%s, %x, %s)",
    439 	       (printerOrForm ? printerOrForm : "NULL"), key,
    440 	       (alert_text ? alert_text : "NULL"));
    441 
    442 	if (!(pps = search_pstatus(printerOrForm)) || (!pps->exec) ||
    443 		pps->exec->key != key || !pps->request) {
    444 		status = MERRDEST;
    445 	} else {
    446 		printer_fault(pps, pps->request, alert_text, 0);
    447 		status = MOK;
    448 	}
    449 
    450 	mputm (md, R_SEND_FAULT, status);
    451 }
    452 
    453 /*
    454  * s_clear_fault()
    455  */
    456 void
    457 s_clear_fault(char *m, MESG *md)
    458 {
    459 	long	key;
    460 	char	*printerOrForm, *alert_text;
    461 	ushort	status;
    462 	register PSTATUS	*pps;
    463 
    464 	getmessage(m, S_CLEAR_FAULT, &printerOrForm, &key, &alert_text);
    465 	syslog(LOG_DEBUG, "s_clear_fault(%s, %x, %s)",
    466 	       (printerOrForm ? printerOrForm : "NULL"), key,
    467 	       (alert_text ? alert_text : "NULL"));
    468 
    469 
    470 	if (! (pps = search_pstatus(printerOrForm)) || ((key > 0) &&
    471 	    ((!pps->exec) || pps->exec->key != key || !pps->request ))) {
    472 		status = MERRDEST;
    473 	} else {
    474 		clear_printer_fault(pps, alert_text);
    475 		status = MOK;
    476 	}
    477 
    478 	mputm (md, R_CLEAR_FAULT, status);
    479 }
    480 
    481 
    482 /*
    483  * s_paper_changed()
    484  */
    485 void
    486 s_paper_changed(char *m, MESG *md)
    487 {
    488 	short			trayNum, mode, pagesPrinted;
    489 	char			*printer, *paper;
    490 	ushort			status;
    491 	short			chgd = 0;
    492 	register PSTATUS	*pps;
    493 	register FSTATUS	*pfs,*pfsWas;
    494 
    495 	getmessage(m, S_PAPER_CHANGED, &printer, &trayNum, &paper, &mode,
    496 		&pagesPrinted);
    497 	syslog(LOG_DEBUG, "s_paper_changed(%s, %d, %s, %d, %d)",
    498 	       (printer ? printer : "NULL"), trayNum, (paper ? paper : "NULL"),
    499 	       mode, pagesPrinted);
    500 
    501 	if (!(pps = search_pstatus(printer)))
    502 		status = MNODEST;
    503 	else if ((trayNum <=0) || (trayNum > pps->numForms))
    504 		status = MNOTRAY;
    505 	else {
    506 		status = MOK;
    507 		if (*paper && (pfsWas = pps->forms[trayNum-1].form) &&
    508 		    (!STREQU(pfsWas->form->paper,paper))) {
    509 			pfs = search_fptable(paper);
    510 			if (pfs) {
    511 				remount_form(pps, pfs, trayNum);
    512 				chgd = 1;
    513 			} else
    514 				status = MNOMEDIA;
    515 		}
    516 		if ( status == MOK ) {
    517 			pps->forms[trayNum].isAvailable = mode;
    518 			if ((chgd || !mode) && (!pagesPrinted) && pps->exec) {
    519 				if (pps->request)
    520 					pps->request->request->outcome |=
    521 						RS_STOPPED;
    522 				terminate(pps->exec);
    523 				schedule(EV_LATER, 1, EV_INTERF, pps);
    524 			}
    525 		}
    526 	}
    527 	mputm(md, R_PAPER_CHANGED, status);
    528 }
    529 
    530