Home | History | Annotate | Download | only in lpsched
      1     0  stevel /*
      2     0  stevel  * CDDL HEADER START
      3     0  stevel  *
      4     0  stevel  * The contents of this file are subject to the terms of the
      5  3125  jacobs  * Common Development and Distribution License (the "License").
      6  3125  jacobs  * You may not use this file except in compliance with the License.
      7     0  stevel  *
      8     0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9     0  stevel  * or http://www.opensolaris.org/os/licensing.
     10     0  stevel  * See the License for the specific language governing permissions
     11     0  stevel  * and limitations under the License.
     12     0  stevel  *
     13     0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14     0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15     0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     16     0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17     0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18     0  stevel  *
     19     0  stevel  * CDDL HEADER END
     20     0  stevel  */
     21     0  stevel /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     22     0  stevel /*	  All Rights Reserved  	*/
     23     0  stevel 
     24     0  stevel 
     25     0  stevel /*
     26  4599  wendyp  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     27  3125  jacobs  * Use is subject to license terms.
     28     0  stevel  */
     29     0  stevel 
     30     0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     31     0  stevel 
     32     0  stevel #include "lpsched.h"
     33  4599  wendyp #include <syslog.h>
     34     0  stevel 
     35     0  stevel static int	max_requests_needing_form_mounted ( FSTATUS * );
     36     0  stevel static int	max_requests_needing_pwheel_mounted ( char * );
     37     0  stevel 
     38     0  stevel /**
     39     0  stevel  ** queue_form() - ADD A REQUEST TO A FORM QUEUE
     40     0  stevel  **/
     41     0  stevel 
     42     0  stevel void
     43  3125  jacobs queue_form(RSTATUS *prs, FSTATUS *pfs)
     44     0  stevel {
     45     0  stevel 	if ((prs->form = pfs) != NULL) {
     46     0  stevel 		prs->form->requests++;
     47     0  stevel 		if (prs->printer)
     48     0  stevel 			check_form_alert (prs->form, (_FORM *)0);
     49     0  stevel 	}
     50     0  stevel 	return;
     51     0  stevel }
     52     0  stevel 
     53     0  stevel /**
     54     0  stevel  ** unqueue_form() - REMOVE A REQUEST FROM A FORM QUEUE
     55     0  stevel  **/
     56     0  stevel 
     57     0  stevel void
     58  3125  jacobs unqueue_form(RSTATUS *prs)
     59     0  stevel {
     60     0  stevel 	FSTATUS *		pfs	= prs->form;
     61     0  stevel 
     62     0  stevel 	prs->form = 0;
     63     0  stevel 	if (pfs) {
     64     0  stevel 		pfs->requests--;
     65     0  stevel 		if (prs->printer)
     66     0  stevel 			check_form_alert (pfs, (_FORM *)0);
     67     0  stevel 	}
     68     0  stevel 	return;
     69     0  stevel }
     70     0  stevel 
     71     0  stevel /**
     72     0  stevel  ** queue_pwheel() - ADD A REQUEST TO A PRINT WHEEL QUEUE
     73     0  stevel  **/
     74     0  stevel 
     75     0  stevel void
     76  3125  jacobs queue_pwheel(RSTATUS *prs, char *name)
     77     0  stevel {
     78     0  stevel 	if (name) {
     79     0  stevel 		prs->pwheel_name = Strdup(name);
     80     0  stevel 		/*
     81     0  stevel 		 * Don't bother queueing the request for
     82     0  stevel 		 * a print wheel if this request is destined for
     83     0  stevel 		 * only this printer and the printer doesn't take
     84     0  stevel 		 * print wheels.
     85     0  stevel 		 */
     86     0  stevel 		if (
     87     0  stevel 			!one_printer_with_charsets(prs)
     88  3125  jacobs 		     && (prs->pwheel = search_pwstatus(name))
     89     0  stevel 		) {
     90     0  stevel 			prs->pwheel->requests++;
     91     0  stevel 			check_pwheel_alert (prs->pwheel, (PWHEEL *)0);
     92     0  stevel 		}
     93     0  stevel 	}
     94     0  stevel 	return;
     95     0  stevel }
     96     0  stevel 
     97     0  stevel /**
     98     0  stevel  ** unqueue_pwheel() - REMOVE A REQUEST FROM A PRINT WHEEL QUEUE
     99     0  stevel  **/
    100     0  stevel 
    101     0  stevel void
    102  3125  jacobs unqueue_pwheel(RSTATUS *prs)
    103     0  stevel {
    104     0  stevel 	PWSTATUS *		ppws	= prs->pwheel;
    105     0  stevel 
    106     0  stevel 	prs->pwheel = 0;
    107     0  stevel 	unload_str (&(prs->pwheel_name));
    108     0  stevel 	if (ppws) {
    109     0  stevel 		ppws->requests--;
    110     0  stevel 		check_pwheel_alert (ppws, (PWHEEL *)0);
    111     0  stevel 	}
    112     0  stevel 	return;
    113     0  stevel }
    114     0  stevel 
    115     0  stevel /**
    116     0  stevel  ** check_form_alert() - CHECK CHANGES TO MOUNT FORM ALERT
    117     0  stevel  **/
    118     0  stevel 
    119     0  stevel void
    120  3125  jacobs check_form_alert(FSTATUS *pfs, _FORM *pf)
    121     0  stevel {
    122  3125  jacobs 	short			trigger,
    123     0  stevel 				fire_off_alert	= 0;
    124     0  stevel 
    125     0  stevel 	int			requests_waiting;
    126     0  stevel 
    127     0  stevel 
    128     0  stevel 	/*
    129     0  stevel 	 * Call this routine whenever a requests has been queued
    130     0  stevel 	 * or dequeued for a form, and whenever the form changes.
    131     0  stevel 	 * If a pointer to a new _FORM is passed, the FSTATUS
    132     0  stevel 	 * structure is updated with the changes. Use a second
    133     0  stevel 	 * argument of 0 if no change.
    134     0  stevel 	 *
    135     0  stevel 	 * WARNING: It is valid to call this routine when adding
    136     0  stevel 	 * a NEW form (not just changing it). Thus the members of
    137     0  stevel 	 * the structure "pfs->form" may not be set.
    138     0  stevel 	 * In this case, though, "pf" MUST be set, and there can
    139     0  stevel 	 * be NO alert active.
    140     0  stevel 	 */
    141     0  stevel 
    142  4599  wendyp 	syslog(LOG_DEBUG, "check_form_alert:\n");
    143  4599  wendyp 	if (pfs)
    144  4599  wendyp 		syslog(LOG_DEBUG, "check_form_alert: pfs->name <%s>\n",
    145  4599  wendyp 			(pfs->form->name != NULL) ? pfs->form->name : "null");
    146  4599  wendyp 	if (pf)
    147  4599  wendyp 		syslog(LOG_DEBUG, "check_form_alert: pf->name <%s>\n",
    148  4599  wendyp 			(pf->name != NULL) ? pf->name : "null");
    149  4599  wendyp 
    150  4599  wendyp 
    151     0  stevel 	if (pf) {
    152     0  stevel 		if ((trigger = pf->alert.Q) <= 0)
    153     0  stevel 			trigger = 1;
    154     0  stevel 	} else
    155     0  stevel 		trigger = pfs->trigger;
    156     0  stevel 
    157     0  stevel 	if (Starting)
    158     0  stevel 		goto Return;
    159     0  stevel 
    160     0  stevel #define	OALERT	pfs->form->alert
    161     0  stevel #define NALERT	pf->alert
    162     0  stevel 
    163     0  stevel 	requests_waiting = max_requests_needing_form_mounted(pfs);
    164     0  stevel 
    165     0  stevel 	/*
    166     0  stevel 	 * Cancel an active alert if the number of requests queued
    167     0  stevel 	 * has dropped below the threshold (or the threshold has been
    168     0  stevel 	 * raised), or if the alert command or period has changed.
    169     0  stevel 	 * In the latter case we'll reactive the alert later.
    170     0  stevel 	 */
    171     0  stevel 	if (pfs->alert->active)
    172     0  stevel 		if (!requests_waiting || requests_waiting < trigger)
    173     0  stevel 			cancel_alert (A_FORM, pfs);
    174     0  stevel 
    175     0  stevel 		else if (
    176     0  stevel 			pf
    177     0  stevel 		     && (
    178     0  stevel 				!SAME(NALERT.shcmd, OALERT.shcmd)
    179     0  stevel 			     || NALERT.W != OALERT.W
    180     0  stevel 			     || NALERT.Q != OALERT.Q
    181     0  stevel 			)
    182     0  stevel 		)
    183     0  stevel 			cancel_alert (A_FORM, pfs);
    184     0  stevel 
    185     0  stevel 	/*
    186     0  stevel 	 * If we still have the condition for an alert, we'll fire
    187     0  stevel 	 * one off. It is possible the alert is still running, but
    188     0  stevel 	 * that's okay. First, we may want to change the alert message;
    189     0  stevel 	 * second, the "alert()" routine doesn't execute an alert
    190     0  stevel 	 * if it is already running.
    191     0  stevel 	 */
    192     0  stevel 	if (trigger > 0 && requests_waiting >= trigger)
    193     0  stevel 		if ((pf && NALERT.shcmd) || OALERT.shcmd)
    194     0  stevel 			fire_off_alert = 1;
    195     0  stevel 
    196     0  stevel #undef	OALERT
    197     0  stevel #undef	NALERT
    198     0  stevel 
    199     0  stevel Return:	if (pf) {
    200     0  stevel 
    201  4599  wendyp 		 pfs->form = pf;
    202  4599  wendyp 
    203     0  stevel 		pfs->trigger = trigger;
    204     0  stevel 	}
    205     0  stevel 
    206     0  stevel 	/*
    207     0  stevel 	 * Have to do this after updating the changes.
    208     0  stevel 	 */
    209     0  stevel 	if (fire_off_alert)
    210     0  stevel 		alert (A_FORM, pfs);
    211     0  stevel 
    212     0  stevel 	return;
    213     0  stevel }
    214     0  stevel 
    215     0  stevel /**
    216     0  stevel  ** check_pwheel_alert() - CHECK CHANGES TO MOUNT PRINTWHEEL ALERT
    217     0  stevel  **/
    218     0  stevel 
    219     0  stevel void
    220  3125  jacobs check_pwheel_alert(PWSTATUS *ppws, PWHEEL *ppw)
    221     0  stevel {
    222  3125  jacobs 	short			trigger,
    223     0  stevel 				fire_off_alert	= 0;
    224     0  stevel 	int			requests_waiting;
    225     0  stevel 
    226     0  stevel 
    227     0  stevel 	/*
    228     0  stevel 	 * Call this routine whenever a request has been queued
    229     0  stevel 	 * or dequeued for a print-wheel, and whenever the print-wheel
    230     0  stevel 	 * changes. If a pointer to a new PWHEEL is passed, the
    231     0  stevel 	 * PWSTATUS structure is updated with the changes. Use a
    232     0  stevel 	 * second argument of 0 if no change.
    233     0  stevel 	 *
    234     0  stevel 	 * WARNING: It is valid to call this routine when adding
    235     0  stevel 	 * a NEW print wheel (not just changing it). Thus the members
    236     0  stevel 	 * of the structure "ppws->pwheel" may not be set.
    237     0  stevel 	 * In this case, though, "ppw" MUST be set, and there can
    238     0  stevel 	 * be NO alert active.
    239     0  stevel 	 */
    240     0  stevel 
    241     0  stevel 	if (ppw) {
    242     0  stevel 		if ((trigger = ppw->alert.Q) <= 0)
    243     0  stevel 			trigger = 1;
    244     0  stevel 	} else
    245     0  stevel 		trigger = ppws->trigger;
    246     0  stevel 
    247     0  stevel 	if (Starting)
    248     0  stevel 		goto Return;
    249     0  stevel 
    250     0  stevel #define	OALERT	ppws->pwheel->alert
    251     0  stevel #define NALERT	ppw->alert
    252     0  stevel 
    253     0  stevel 	requests_waiting = max_requests_needing_pwheel_mounted(ppws->pwheel->name);
    254     0  stevel 
    255     0  stevel 	/*
    256     0  stevel 	 * Cancel an active alert if the number of requests queued
    257     0  stevel 	 * has dropped below the threshold (or the threshold has been
    258     0  stevel 	 * raised), or if the alert command or period has changed.
    259     0  stevel 	 * In the latter case we'll reactive the alert later.
    260     0  stevel 	 */
    261     0  stevel 	if (ppws->alert->active)
    262     0  stevel 		if (!requests_waiting || requests_waiting < trigger)
    263     0  stevel 			cancel_alert (A_PWHEEL, ppws);
    264     0  stevel 
    265     0  stevel 		else if (
    266     0  stevel 			ppw
    267     0  stevel 		     && (
    268     0  stevel 				!SAME(NALERT.shcmd, OALERT.shcmd)
    269     0  stevel 			     || NALERT.W != OALERT.W
    270     0  stevel 			     || NALERT.Q != OALERT.Q
    271     0  stevel 			)
    272     0  stevel 		)
    273     0  stevel 			cancel_alert (A_PWHEEL, ppws);
    274     0  stevel 
    275     0  stevel 	/*
    276     0  stevel 	 * If we still have the condition for an alert, we'll fire
    277     0  stevel 	 * one off. It is possible the alert is still running, but
    278     0  stevel 	 * that's okay. First, we may want to change the alert message;
    279     0  stevel 	 * second, the "alert()" routine doesn't execute an alert
    280     0  stevel 	 * if it is already running.
    281     0  stevel 	 */
    282     0  stevel 	if (trigger > 0 && requests_waiting >= trigger)
    283     0  stevel 		if ((ppw && NALERT.shcmd) || OALERT.shcmd)
    284     0  stevel 			fire_off_alert = 1;
    285     0  stevel 
    286     0  stevel #undef	OALERT
    287     0  stevel #undef	NALERT
    288     0  stevel 
    289     0  stevel Return:	if (ppw) {
    290     0  stevel 
    291  4599  wendyp 		ppws->pwheel = ppw;
    292     0  stevel 		ppws->trigger = trigger;
    293     0  stevel 	}
    294     0  stevel 
    295     0  stevel 	/*
    296     0  stevel 	 * Have to do this after updating the changes.
    297     0  stevel 	 */
    298     0  stevel 	if (fire_off_alert)
    299     0  stevel 		alert (A_PWHEEL, ppws);
    300     0  stevel 
    301     0  stevel 	return;
    302     0  stevel }
    303     0  stevel 
    304     0  stevel static int
    305     0  stevel trayWithForm(PSTATUS *pps, FSTATUS *pfs, int startingTray, int checkAvail)
    306     0  stevel {
    307     0  stevel 	int i;
    308     0  stevel 	PFSTATUS *ppfs;
    309     0  stevel 
    310     0  stevel 	ppfs = pps->forms;
    311     0  stevel 	if (startingTray < 0)
    312     0  stevel 		startingTray = 0;
    313     0  stevel 
    314     0  stevel 	if (ppfs) {
    315     0  stevel 		for (i = startingTray; i < pps->numForms; i++)
    316     0  stevel 			if ((!checkAvail || ppfs[i].isAvailable) &&
    317     0  stevel 			    (ppfs[i].form == pfs))
    318     0  stevel 					return(i);
    319     0  stevel 	}
    320     0  stevel 	else if (!pfs)
    321     0  stevel 		/* no form request matches no form mounted */
    322     0  stevel 		return(0);
    323     0  stevel 
    324     0  stevel 	return(-1);
    325     0  stevel }
    326     0  stevel 
    327     0  stevel char *
    328     0  stevel allTraysWithForm(PSTATUS *pps, FSTATUS *pfs)
    329     0  stevel {
    330     0  stevel 
    331     0  stevel 	int tray = 0;
    332     0  stevel 	char *ptr, *p;
    333     0  stevel 	char trayList[MAX_INPUT];
    334     0  stevel 	int n;
    335     0  stevel 
    336     0  stevel 	ptr = trayList;
    337     0  stevel 	if (pfs && pfs->form && pfs->form->paper)
    338     0  stevel 		p = pfs->form->paper;
    339     0  stevel 	else
    340     0  stevel 		p = "";
    341     0  stevel 
    342     0  stevel 	n = sizeof (trayList);
    343     0  stevel 	snprintf(ptr, n, "LP_TRAY_ARG=%s:", p);
    344     0  stevel 
    345     0  stevel 	ptr += strlen(ptr);
    346     0  stevel 	n -= strlen(ptr);
    347     0  stevel 
    348     0  stevel 	while ((tray = trayWithForm(pps, pfs, tray, 1)) > 0) {
    349     0  stevel 		tray++;
    350     0  stevel 		snprintf(ptr, n, "%d,", tray);
    351     0  stevel 		ptr += strlen(ptr);
    352     0  stevel 		n -= strlen(ptr);
    353     0  stevel 	}
    354     0  stevel 	if (*(ptr-1) == ',')
    355     0  stevel 		*(ptr-1) = 0;
    356     0  stevel 
    357     0  stevel 	putenv(trayList);
    358     0  stevel 	return(NULL);
    359     0  stevel }
    360     0  stevel 
    361     0  stevel int
    362     0  stevel isFormUsableOnPrinter(PSTATUS *pps, FSTATUS *pfs)
    363     0  stevel {
    364     0  stevel 	return (trayWithForm(pps,pfs,0,1) >= 0 );
    365     0  stevel }
    366     0  stevel int
    367     0  stevel isFormMountedOnPrinter(PSTATUS *pps, FSTATUS *pfs)
    368     0  stevel {
    369     0  stevel 	return (trayWithForm(pps,pfs,0,0) >= 0 );
    370     0  stevel }
    371     0  stevel 
    372     0  stevel /**
    373     0  stevel  ** max_requests_needing_form_mounted()
    374     0  stevel  ** max_requests_needing_pwheel_mounted()
    375     0  stevel  **/
    376     0  stevel 
    377     0  stevel static int
    378     0  stevel max_requests_needing_form_mounted(FSTATUS *pfs)
    379     0  stevel {
    380     0  stevel 	PSTATUS *		pps;
    381     0  stevel 	RSTATUS *		prs;
    382     0  stevel 	int			max	= 0;
    383  3125  jacobs 	int			i;
    384     0  stevel 
    385     0  stevel 	/*
    386     0  stevel 	 * For each printer that doesn't have this form mounted,
    387     0  stevel 	 * count the number of requests needing this form and
    388     0  stevel 	 * assigned to the printer. Find the maximum across all such
    389     0  stevel 	 * printers. Sorry, the code actually has a different loop
    390     0  stevel 	 * (it steps through the requests) but the description of what
    391     0  stevel 	 * happens below is easier to understand as given. (Looping
    392     0  stevel 	 * through the printers would result in #printers x #requests
    393     0  stevel 	 * steps, whereas this entails #requests steps.)
    394     0  stevel 	 */
    395  3125  jacobs 	for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
    396  3125  jacobs 		PStatus[i]->nrequests = 0;
    397  3125  jacobs 
    398  3125  jacobs 	for (prs = Request_List; prs != NULL; prs = prs->next)
    399  3125  jacobs 		if ((prs->form == pfs) && ((pps = prs->printer) != NULL) &&
    400  3125  jacobs 	    	    (!isFormMountedOnPrinter(pps,pfs)) &&
    401  3125  jacobs 		    (++pps->nrequests >= max))
    402  3125  jacobs 			max = pps->nrequests;
    403  3125  jacobs 
    404     0  stevel 	if (NewRequest)
    405     0  stevel 		if (((pps = NewRequest->printer) != NULL) &&
    406     0  stevel 		    (!isFormMountedOnPrinter(pps,pfs)))
    407     0  stevel 			if (++pps->nrequests >= max)
    408     0  stevel 				max = pps->nrequests;
    409     0  stevel 	return (max);
    410     0  stevel }
    411     0  stevel 
    412     0  stevel static int
    413     0  stevel max_requests_needing_pwheel_mounted(char *pwheel_name)
    414     0  stevel {
    415     0  stevel 	PSTATUS *		pps;
    416     0  stevel 	RSTATUS *		prs;
    417     0  stevel 	int			max	= 0;
    418  3125  jacobs 	int			i;
    419     0  stevel 
    420     0  stevel 
    421     0  stevel 	/*
    422     0  stevel 	 * For each printer that doesn't have this print-wheel mounted,
    423     0  stevel 	 * count the number of requests needing this print-wheel and
    424     0  stevel 	 * assigned to the printer. Find the maximum across all such
    425     0  stevel 	 * printers. Sorry, the code actually has a different loop
    426     0  stevel 	 * (it steps through the requests) but the description of what
    427     0  stevel 	 * happens below is easier to understand as given. (Looping
    428     0  stevel 	 * through the printers would result in #printers x #requests
    429     0  stevel 	 * steps, whereas this entails #requests steps.)
    430     0  stevel 	 */
    431  3125  jacobs 	for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
    432  3125  jacobs 		PStatus[i]->nrequests = 0;
    433  3125  jacobs 
    434  3125  jacobs 	for (prs = Request_List; prs != NULL; prs = prs->next)
    435  3125  jacobs 		if ((prs->pwheel_name != NULL) &&
    436  3125  jacobs 		    (STREQU(prs->pwheel_name, pwheel_name)) &&
    437  3125  jacobs 		    ((pps = prs->printer) != NULL) && pps->printer->daisy &&
    438  3125  jacobs 		    (!SAME(pps->pwheel_name, pwheel_name)))
    439     0  stevel 			if (++pps->nrequests >= max)
    440     0  stevel 				max = pps->nrequests;
    441  3125  jacobs 
    442     0  stevel 	if (NewRequest)
    443     0  stevel 		if (
    444     0  stevel 			((pps = NewRequest->printer) != NULL)
    445     0  stevel 		     && pps->printer->daisy
    446     0  stevel 		     && !SAME(pps->pwheel_name, pwheel_name)
    447     0  stevel 		)
    448     0  stevel 			if (++pps->nrequests >= max)
    449     0  stevel 				max = pps->nrequests;
    450     0  stevel 	return (max);
    451     0  stevel }
    452     0  stevel 
    453     0  stevel /**
    454     0  stevel  ** one_printer_with_charsets()
    455     0  stevel  **/
    456     0  stevel 
    457     0  stevel int
    458  3125  jacobs one_printer_with_charsets(RSTATUS *prs)
    459     0  stevel {
    460     0  stevel 	/*
    461     0  stevel 	 * This little function answers the question: Is a request
    462     0  stevel 	 * that needs a character set destined for a particular
    463     0  stevel 	 * printer that has selectable character sets instead of
    464     0  stevel 	 * mountable print wheels?
    465     0  stevel 	 */
    466     0  stevel 	return (
    467     0  stevel 	    STREQU(prs->request->destination, prs->printer->printer->name)
    468     0  stevel 	 && !prs->printer->printer->daisy
    469     0  stevel 	);
    470     0  stevel }
    471