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 /*
     23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28 /*	  All Rights Reserved  	*/
     29 
     30 
     31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     32 
     33 #include	"dispatch.h"
     34 #include <syslog.h>
     35 #include <time.h>
     36 
     37 char *showForms(PSTATUS *);
     38 
     39 /*
     40  * untidbit_all() - CALL untidbit() FOR A LIST OF TYPES
     41  */
     42 
     43 static void
     44 untidbit_all (char **printer_types)
     45 {
     46 	char **			pl;
     47 
     48 	for (pl = printer_types; *pl; pl++)
     49 		untidbit (*pl);
     50 	return;
     51 }
     52 
     53 /*
     54  * s_load_printer()
     55  */
     56 
     57 void
     58 s_load_printer(char *m, MESG *md)
     59 {
     60 	char			*printer;
     61 	ushort			status;
     62 	register PRINTER	*pp;
     63 	register PSTATUS	*pps;
     64 	char **paperDenied;
     65 
     66 	(void) getmessage(m, S_LOAD_PRINTER, &printer);
     67 	syslog(LOG_DEBUG, "s_load_printer(%s)", (printer ? printer : "NULL"));
     68 
     69 	if (!*printer)
     70 		/* no printer */
     71 		status = MNODEST;
     72 	else if (!(pp = Getprinter(printer))) {
     73 		/* Strange or missing printer? */
     74 		switch (errno) {
     75 		case EBADF:
     76 			status = MERRDEST;
     77 			break;
     78 		case ENOENT:
     79 		default:
     80 			status = MNODEST;
     81 			break;
     82 		}
     83 	} else if ((pps = search_pstatus(printer))) {
     84 		/* Printer we know about already? */
     85 		PRINTER	*op = pps->printer;
     86 
     87 		pps->printer = pp;
     88 
     89 		/*
     90 		 * Ensure that an old Terminfo type that's no longer
     91 		 * needed gets freed, and that an existing type gets
     92 		 * reloaded (in case it has been changed).
     93 		 */
     94 		untidbit_all (op->printer_types);
     95 		untidbit_all (pp->printer_types);
     96 
     97 		/*
     98 		 * Does an alert get affected?
     99 		 *	- Different command?
    100 		 *	- Different wait interval?
    101 		 */
    102 		if (pps->alert->active)
    103 			if (!SAME(pp->fault_alert.shcmd,
    104 				  op->fault_alert.shcmd) ||
    105 			    pp->fault_alert.W != op->fault_alert.W) {
    106 				/*
    107 				 * We can't use "cancel_alert()" here
    108 				 * because it will remove the message.
    109 				 * We'll do half of the cancel, then
    110 				 * check if we need to run the new alert,
    111 				 * and remove the message if not.
    112 				 */
    113 				pps->alert->active = 0;
    114 				terminate (pps->alert->exec);
    115 				if (pp->fault_alert.shcmd)
    116 					alert(A_PRINTER, pps, (RSTATUS *)0,
    117 						(char *)0);
    118 				else
    119 					Unlink (pps->alert->msgfile);
    120 			}
    121 		freeprinter (op);
    122 
    123 		unload_list (&pps->users_allowed);
    124 		unload_list (&pps->users_denied);
    125 		unload_list (&pps->forms_allowed);
    126 		unload_list (&pps->forms_denied);
    127 		load_userprinter_access(pp->name, &pps->users_allowed,
    128 			&pps->users_denied);
    129 		load_formprinter_access(pp->name, &pps->forms_allowed,
    130 			&pps->forms_denied);
    131 
    132 		unload_list (&pps->paper_allowed);
    133 		load_paperprinter_access(pp->name, &pps->paper_allowed,
    134 			&paperDenied);
    135 		freelist(paperDenied);
    136 
    137 		load_sdn (&pps->cpi, pp->cpi);
    138 		load_sdn (&pps->lpi, pp->lpi);
    139 		load_sdn (&pps->plen, pp->plen);
    140 		load_sdn (&pps->pwid, pp->pwid);
    141 
    142 		pps->last_dial_rc = 0;
    143 		pps->nretry = 0;
    144 
    145 		/*
    146 		 * Evaluate all requests queued for this printer,
    147 		 * to make sure they are still eligible. They will
    148 		 * get moved to another printer, get (re)filtered,
    149 		 * or get canceled.
    150 		 */
    151 		(void) queue_repel(pps, 0, (qchk_fnc_type)0);
    152 
    153 		status = MOK;
    154         } else if (pp->remote) {
    155 		/* don't really load a remote printer */
    156 		status = MOK;
    157 	} else if ((pps = new_pstatus(pp))) {
    158 		pps->status = PS_DISABLED | PS_REJECTED;
    159 		load_str (&pps->dis_reason, CUZ_NEW_PRINTER);
    160 		load_str (&pps->rej_reason, CUZ_NEW_DEST);
    161 		load_str (&pps->fault_reason, CUZ_PRINTING_OK);
    162 		time (&pps->dis_date);
    163 		time (&pps->rej_date);
    164 
    165 		dump_pstatus ();
    166 
    167 		status = MOK;
    168 	} else {
    169 		freeprinter (pp);
    170 		status = MNOSPACE;
    171 	}
    172 
    173 
    174 	mputm (md, R_LOAD_PRINTER, status);
    175 	return;
    176 }
    177 
    178 /*
    179  * s_unload_printer()
    180  */
    181 
    182 static void
    183 _unload_printer(PSTATUS *pps)
    184 {
    185 	int i;
    186 
    187 	if (pps->alert->active)
    188 		cancel_alert (A_PRINTER, pps);
    189 
    190 	/*
    191 	 * Remove this printer from the classes it may be in.
    192 	 * This is likely to be redundant, i.e. upon deleting
    193 	 * a printer the caller is SUPPOSED TO check all the
    194 	 * classes; any that contain the printer will be changed
    195 	 * and we should receive a S_LOAD_CLASS message for each
    196 	 * to reload the class.
    197 	 *
    198 	 * HOWEVER, this leaves a (small) window where someone
    199 	 * can sneak a request in destined for the CLASS. If
    200 	 * we have deleted the printer but still have it in the
    201 	 * class, we may have trouble!
    202 	 */
    203 	for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++)
    204 		(void) dellist(&(CStatus[i]->class->members),
    205 				pps->printer->name);
    206 
    207 	free_pstatus(pps);
    208 	/*
    209 	 * this is removed from the PStatus table by the caller
    210 	 *   list_remove((void ***)&PStatus, (void *)pps);
    211 	 */
    212 
    213 	return;
    214 }
    215 
    216 void
    217 s_unload_printer(char *m, MESG *md)
    218 {
    219 	char			*printer;
    220 	ushort			status;
    221 	register PSTATUS	*pps;
    222 
    223 	(void) getmessage(m, S_UNLOAD_PRINTER, &printer);
    224 
    225 	syslog(LOG_DEBUG, "s_unload_printer(%s)",
    226 	       (printer ? printer : "NULL"));
    227 
    228 	if (!*printer || STREQU(printer, NAME_ALL))
    229 		/* Unload ALL printers */
    230 		if (!Request_List)
    231 			/*  If we have ANY requests queued, we can't do it. */
    232 			status = MBUSY;
    233 
    234 		else {
    235 			int i;
    236 			for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
    237 				_unload_printer (PStatus[i]);
    238 			free(PStatus);
    239 			PStatus = NULL;
    240 			status = MOK;
    241 		}
    242 
    243 	else if (!(pps = search_pstatus(printer)))
    244 		/* Have we seen this printer before */
    245 		status = MNODEST;
    246 	else {
    247 		/*
    248 		 * Note: This routine WILL MOVE requests to another
    249 		 * printer. It will not stop until it has gone through
    250 		 * the entire list of requests, so all requests that
    251 		 * can be moved will be moved. If any couldn't move,
    252 		 * however, we don't unload the printer.
    253 		 */
    254 		if (queue_repel(pps, 1, (qchk_fnc_type)0))
    255 			status = MOK;
    256 		else
    257 			status = MBUSY;
    258 
    259 		if (status == MOK) {
    260 			_unload_printer (pps);
    261 			list_remove((void ***)&PStatus, (void *)pps);
    262 		}
    263 	}
    264 
    265 	if (status == MOK)
    266 		dump_pstatus ();
    267 
    268 	mputm (md, R_UNLOAD_PRINTER, status);
    269 	return;
    270 }
    271 
    272 /*
    273  * combineReasons()
    274  */
    275 
    276 static char *
    277 combineReasons(PSTATUS *pps, char *freeReason)
    278 {
    279 	char	*reason = NULL;
    280 
    281 	if (pps->status & PS_FAULTED) {
    282 		if ((pps->status & (PS_DISABLED | PS_LATER)) &&
    283 		    (!STREQU(pps->dis_reason, CUZ_STOPPED)) &&
    284 		    (addstring(&reason, "Fault reason: ") == 0) &&
    285 		    (addstring(&reason, pps->fault_reason) == 0) &&
    286 		    (addstring(&reason, "\n\tDisable reason: ") == 0) &&
    287 		    (addstring(&reason, pps->dis_reason) == 0))
    288 			*freeReason = 1;
    289 
    290 		else {
    291 			if (reason)
    292 				/* memory allocation failed part way through */
    293 				Free(reason);
    294 
    295 			reason = pps->fault_reason;
    296 			*freeReason = 0;
    297 		}
    298 	} else {
    299 		reason = pps->dis_reason;
    300 		*freeReason = 0;
    301 	}
    302 	return (reason);
    303 }
    304 
    305 static void
    306 local_printer_status(MESG *md, PSTATUS *pps, short status)
    307 {
    308 	char	*reason = NULL;
    309 	char	freeReason = 0;
    310 	char	*formList = NULL;
    311 
    312 	reason = combineReasons(pps, &freeReason);
    313 	formList = showForms(pps);
    314 
    315 	send(md, R_INQUIRE_PRINTER_STATUS, status, pps->printer->name,
    316 		(formList ? formList : ""),
    317 		(pps->pwheel_name ? pps->pwheel_name : ""),
    318 		reason, pps->rej_reason, pps->status,
    319 		(pps->request ? pps->request->secure->req_id : ""),
    320 		pps->dis_date, pps->rej_date);
    321 
    322 	if (formList)
    323 		Free(formList);
    324 
    325 	if (freeReason)
    326 		Free(reason);
    327 }
    328 
    329 /*
    330  * s_inquire_printer_status()
    331  */
    332 
    333 void
    334 s_inquire_printer_status(char *m, MESG *md)
    335 {
    336 	char			*printer;
    337 	register PSTATUS	*pps;
    338 
    339 	(void) getmessage(m, S_INQUIRE_PRINTER_STATUS, &printer);
    340 	syslog(LOG_DEBUG, "s_inquire_printer_status(%s)", printer);
    341 
    342 	if (!*printer || STREQU(printer, NAME_ALL)) {
    343 		/* inquire about all printers */
    344 		int i;
    345 
    346 		for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) {
    347 			pps = PStatus[i];
    348 			if (PStatus[i + 1] != NULL)
    349 				local_printer_status(md, pps, MOKMORE);
    350 		}
    351 	} else
    352 		/* inquire about a specific printer */
    353 		pps = search_pstatus(printer);
    354 
    355 	if (pps)
    356 		local_printer_status(md, pps, MOK);
    357 	else {
    358 		mputm(md, R_INQUIRE_PRINTER_STATUS, MNODEST, "", "", "", "",
    359 			"", 0, "", 0L, 0L);
    360 	}
    361 }
    362 
    363 
    364 /*
    365  * s_load_class()
    366  */
    367 
    368 void
    369 s_load_class(char *m, MESG *md)
    370 {
    371 	char			*class;
    372 	ushort			status;
    373 	register CLASS		*pc;
    374 	register CSTATUS	*pcs;
    375 
    376 	(void) getmessage(m, S_LOAD_CLASS, &class);
    377 	syslog(LOG_DEBUG, "s_load_class(%s)", (class ? class : "NULL"));
    378 
    379 	if (!*class)
    380 		/* no class defined */
    381 		status = MNODEST;
    382 	else if (!(pc = Getclass(class))) {
    383 		/* Strange or missing class */
    384 		switch (errno) {
    385 		case EBADF:
    386 			status = MERRDEST;
    387 			break;
    388 		case ENOENT:
    389 		default:
    390 			status = MNODEST;
    391 			break;
    392 		}
    393 
    394 	} else if ((pcs = search_cstatus(class))) {
    395 		/* Class we already know about */
    396 		register RSTATUS	*prs;
    397 
    398 		freeclass (pcs->class);
    399 		pcs->class = pc;
    400 
    401 		/*
    402 		 * Here we go through the list of requests
    403 		 * to see who gets affected.
    404 		 */
    405 		for (prs = Request_List; prs != NULL; prs = prs->next)
    406 			if (STREQU(prs->request->destination, class)) {
    407 				/*
    408 			 	* If not still eligible for this class...
    409 			 	*/
    410 				switch (validate_request(prs, (char **)0, 1)) {
    411 				case MOK:
    412 				case MERRDEST:	/* rejecting (shouldn't happen) */
    413 					break;
    414 				case MDENYDEST:
    415 				case MNOMOUNT:
    416 				case MNOMEDIA:
    417 				case MNOFILTER:
    418 				default:
    419 					/*
    420 				 	* ...then too bad!
    421 				 	*/
    422 					cancel (prs, 1);
    423 					break;
    424 				}
    425 			}
    426 
    427 		status = MOK;
    428 	} else if ((pcs = new_cstatus(pc))) {
    429 		/* Room for new class? */
    430 		pcs->status = CS_REJECTED;
    431 		load_str (&pcs->rej_reason, CUZ_NEW_DEST);
    432 		time (&pcs->rej_date);
    433 
    434 		dump_cstatus ();
    435 
    436 		status = MOK;
    437 	} else {
    438 		freeclass (pc);
    439 		status = MNOSPACE;
    440 	}
    441 
    442 
    443 	mputm (md, R_LOAD_CLASS, status);
    444 	return;
    445 }
    446 
    447 /*
    448  * s_unload_class()
    449  */
    450 
    451 static void
    452 _unload_class(CSTATUS *pcs)
    453 {
    454 	freeclass (pcs->class);
    455 	if (pcs->rej_reason != NULL)
    456 		Free (pcs->rej_reason);
    457 	Free(pcs);
    458 
    459 	return;
    460 }
    461 
    462 void
    463 s_unload_class(char *m, MESG *md)
    464 {
    465 	char			*class;
    466 	ushort			status;
    467 	RSTATUS 		*prs;
    468 	register CSTATUS	*pcs;
    469 
    470 	(void) getmessage(m, S_UNLOAD_CLASS, &class);
    471 	syslog(LOG_DEBUG, "s_unload_class(%s)", (class ? class : "NULL"));
    472 
    473 	/*
    474 	 * Unload ALL classes?
    475 	 */
    476 	if (!*class || STREQU(class, NAME_ALL)) {
    477 		int i;
    478 		/*
    479 		 * If we have a request queued for a member of ANY
    480 		 * class, we can't do it.
    481 		 */
    482 		status = MOK;
    483 		for (i = 0; ((CStatus[i] != NULL) && (status == MOK)); i++) {
    484 			for (prs = Request_List; prs != NULL; prs = prs->next)
    485 				if (STREQU(prs->request->destination,
    486 						CStatus[i]->class->name)) {
    487 					status = MBUSY;
    488 					break;
    489 				}
    490 		}
    491 
    492 		if (status == MOK) {
    493 			for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++)
    494 				_unload_class (CStatus[i]);
    495 			free(CStatus);
    496 			CStatus = NULL;
    497 		}
    498 
    499 	/*
    500 	 * Have we seen this class before?
    501 	 */
    502 	} else if (!(pcs = search_cstatus(class)))
    503 		status = MNODEST;
    504 
    505 	/*
    506 	 * Is there even one request queued for this class?
    507 	 * If not, we can safely remove it.
    508 	 */
    509 	else {
    510 		status = MOK;
    511 		for (prs = Request_List; prs != NULL; prs = prs->next)
    512 			if (STREQU(prs->request->destination, class)) {
    513 				status = MBUSY;
    514 				break;
    515 			}
    516 
    517 		if (status == MOK) {
    518 			_unload_class (pcs);
    519 			list_remove((void ***)&CStatus, (void *)pcs);
    520 		}
    521 	}
    522 
    523 	if (status == MOK)
    524 		dump_cstatus ();
    525 
    526 	mputm (md, R_UNLOAD_CLASS, status);
    527 	return;
    528 }
    529 
    530 /*
    531  * s_inquire_class()
    532  */
    533 
    534 void
    535 s_inquire_class(char *m, MESG *md)
    536 {
    537 	char			*class;
    538 	register CSTATUS	*pcs;
    539 
    540 	(void) getmessage(m, S_INQUIRE_CLASS, &class);
    541 	syslog(LOG_DEBUG, "s_inquire_class(%s)", (class ? class : "NULL"));
    542 
    543 
    544 
    545 	if (!*class || STREQU(class, NAME_ALL)) {
    546 		/* inquire about ALL classes */
    547 		int i;
    548 
    549 		for (i = 0; CStatus != NULL && CStatus[i] != NULL; i++) {
    550 			pcs = CStatus[i];
    551 			if (CStatus[i + 1] != NULL)
    552 				send(md, R_INQUIRE_CLASS, MOKMORE,
    553 			     		pcs->class->name, pcs->status,
    554 			     		pcs->rej_reason, pcs->rej_date);
    555 		}
    556 	} else
    557 		/* inquire about a single class */
    558 		pcs = search_cstatus(class);
    559 
    560 	if (pcs)
    561 		send(md, R_INQUIRE_CLASS, MOK, pcs->class->name, pcs->status,
    562 			pcs->rej_reason, pcs->rej_date);
    563 	else
    564 		mputm (md, R_INQUIRE_CLASS, MNODEST, "", 0, "", 0L);
    565 
    566 	return;
    567 }
    568 
    569 /*
    570  * s_paper_allowed()
    571  */
    572 
    573 void
    574 s_paper_allowed(char *m, MESG *md)
    575 {
    576 	char			*printer;
    577 	char			*paperList = NULL;
    578 	register PSTATUS	*pps, *ppsnext;
    579 
    580 	(void) getmessage(m, S_PAPER_ALLOWED, &printer);
    581 	syslog(LOG_DEBUG, "s_paper_allowed(%s)", (printer ? printer : "NULL"));
    582 
    583 
    584 	if (!*printer || STREQU(printer, NAME_ALL)) {
    585 		/* inquire about ALL printers */
    586 		int i;
    587 
    588 		for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++) {
    589 			pps = PStatus[i];
    590 			if (PStatus[i + 1] != NULL) {
    591 				paperList = sprintlist(pps->paper_allowed);
    592 				send(md, R_PAPER_ALLOWED, MOKMORE,
    593 					pps->printer->name,
    594 					(paperList ? paperList : ""));
    595 				if (paperList)
    596 					Free(paperList);
    597 			}
    598 		}
    599 	} else
    600 		/* inquire about a specific printer */
    601 		pps = search_pstatus(printer);
    602 
    603 	if (pps) {
    604 		paperList = sprintlist(pps->paper_allowed);
    605 		send(md, R_PAPER_ALLOWED, MOK, pps->printer->name,
    606 			(paperList ? paperList : ""));
    607 		if (paperList)
    608 			Free(paperList);
    609 
    610 	} else {
    611 		mputm(md, R_PAPER_ALLOWED, MNODEST, "", "");
    612 	}
    613 }
    614