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 
     22     0  stevel /*
     23  3125  jacobs  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     24     0  stevel  * Use is subject to license terms.
     25     0  stevel  */
     26     0  stevel 
     27  3125  jacobs /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     28  3125  jacobs /*	  All Rights Reserved  	*/
     29     0  stevel 
     30     0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     31     0  stevel 
     32     0  stevel /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
     33     0  stevel 
     34     0  stevel #include "lpsched.h"
     35     0  stevel #include "ctype.h"
     36     0  stevel #include "sys/stat.h"
     37  3125  jacobs #include <syslog.h>
     38     0  stevel 
     39     0  stevel /*
     40     0  stevel  * Macro to test if we should notify the user.
     41     0  stevel  */
     42     0  stevel #define SHOULD_NOTIFY(PRS) \
     43     0  stevel 	( \
     44     0  stevel 		(PRS)->request->actions & (ACT_MAIL|ACT_WRITE|ACT_NOTIFY)\
     45     0  stevel 	     || (PRS)->request->alert \
     46     0  stevel 	)
     47     0  stevel 
     48     0  stevel static char *		geterrbuf ( RSTATUS * );
     49     0  stevel 
     50     0  stevel /**
     51     0  stevel  ** dowait() - CLEAN UP CHILD THAT HAS FINISHED, RESCHEDULE ANOTHER TASK
     52     0  stevel  **/
     53     0  stevel 
     54     0  stevel void
     55     0  stevel dowait (void)
     56     0  stevel {
     57     0  stevel 	int			exited,
     58     0  stevel 				killed,
     59     0  stevel 				canned,
     60     0  stevel 				i;
     61     0  stevel 	EXEC			*ep;
     62     0  stevel 	char			*errbuf = NULL;
     63     0  stevel 	register RSTATUS	*prs;
     64     0  stevel 	register PSTATUS	*pps;
     65     0  stevel 	register ALERT		*pas;
     66     0  stevel 
     67  3125  jacobs 	syslog(LOG_DEBUG, "dowait(%d)", DoneChildren);
     68     0  stevel 	while (DoneChildren > 0) {
     69     0  stevel 		DoneChildren--;
     70     0  stevel 
     71  3125  jacobs 		for (i = 0; (ep = Exec_Table[i]) != NULL; i++)
     72  3125  jacobs 			if (ep->pid == -99)
     73     0  stevel 				break;
     74  3125  jacobs 
     75  3125  jacobs 		syslog(LOG_DEBUG, "dowait(): 0x%8.8x", ep);
     76  3125  jacobs 
     77  3125  jacobs 		if (Exec_Table[i] == NULL)	/* nothing to cleanup */
     78     0  stevel 			continue;
     79     0  stevel 
     80  3125  jacobs 		syslog(LOG_DEBUG, "dowait(): cleaning up 0x%8.8x", ep);
     81  3125  jacobs 
     82     0  stevel 		ep->pid = 0;
     83     0  stevel 		ep->key = 0;	/* avoid subsequent sneaks */
     84     0  stevel 		if (ep->md)
     85     0  stevel 			DROP_MD(ep->md);
     86     0  stevel 
     87     0  stevel 		killed = KILLED(ep->status);
     88     0  stevel 		exited = EXITED(ep->status);
     89  3125  jacobs 
     90  3125  jacobs 		syslog(LOG_DEBUG, "dowait(): type %d, killed %d, exited %d",
     91  3125  jacobs 			ep->type, killed, exited);
     92     0  stevel 
     93     0  stevel 		switch (ep->type) {
     94     0  stevel 
     95     0  stevel 		case EX_INTERF:
     96     0  stevel 			/*
     97     0  stevel 			 * WARNING: It could be that when we get here
     98     0  stevel 			 *
     99     0  stevel 			 *	pps->request->printer != pps
    100     0  stevel 			 *
    101     0  stevel 			 * because the request has been assigned to
    102     0  stevel 			 * another printer.
    103     0  stevel 			 */
    104     0  stevel 			pps = ep->ex.printer;
    105     0  stevel 			prs = pps->request;
    106     0  stevel 			pps->request = 0;
    107     0  stevel 			pps->status &= ~PS_BUSY;
    108     0  stevel 
    109     0  stevel 			/*
    110     0  stevel 			 * If the interface program exited cleanly
    111     0  stevel 			 * or with just a user error, the printer
    112     0  stevel 			 * is assumed to be working.
    113     0  stevel 			 */
    114     0  stevel 			if (0 <= exited && exited < EXEC_EXIT_USER) {
    115     0  stevel 				pps->status &= ~PS_FAULTED;
    116     0  stevel 				if (pps->alert->active)
    117     0  stevel 					cancel_alert (A_PRINTER, pps);
    118     0  stevel 			}
    119     0  stevel 
    120     0  stevel 			/*
    121     0  stevel 			 * If the interface program was killed with
    122     0  stevel 			 * SIGTERM, it may have been because we canceled
    123     0  stevel 			 * the request, disabled the printer, or for some
    124     0  stevel 			 * other reason stopped the request.
    125     0  stevel 			 * If so, clear the "killed" flag because that's
    126     0  stevel 			 * not the condition of importance here.
    127     0  stevel 			 */
    128     0  stevel 			canned = 0;
    129     0  stevel 			if (killed == SIGTERM) {
    130     0  stevel 				if (prs->request->outcome & RS_CANCELLED)
    131     0  stevel 					canned = 1;
    132     0  stevel 
    133     0  stevel 				if (
    134     0  stevel 					canned
    135     0  stevel 				     || pps->status & (PS_DISABLED|PS_FAULTED)
    136     0  stevel 				     || prs->request->outcome & RS_STOPPED
    137     0  stevel 				     || Shutdown
    138     0  stevel 				)
    139     0  stevel 					killed = 0;
    140     0  stevel 			}
    141     0  stevel 
    142     0  stevel 			/*
    143     0  stevel 			 * If there was standard error output from the
    144     0  stevel 			 * interface program, or if the interface program
    145     0  stevel 			 * exited with a (user) exit code, or if it got
    146     0  stevel 			 * a strange signal, the user should be notified.
    147     0  stevel 			 */
    148     0  stevel 			errbuf = geterrbuf(prs);
    149     0  stevel 			if (
    150     0  stevel 				errbuf
    151     0  stevel 			     || (0 < exited && exited <= EXEC_EXIT_USER)
    152     0  stevel 			     || killed
    153     0  stevel 			) {
    154     0  stevel 				if (exited != EXIT_RETRY) {
    155     0  stevel 					prs->request->outcome |= RS_FAILED;
    156     0  stevel 				}
    157     0  stevel 				prs->request->outcome |= RS_NOTIFY;
    158     0  stevel 				notify (prs, errbuf, killed, exited, 0);
    159     0  stevel 				if (errbuf)
    160     0  stevel 					Free (errbuf);
    161     0  stevel 
    162     0  stevel 			/*
    163     0  stevel 			 * If the request was canceled, call "notify()"
    164     0  stevel 			 * in case we're to notify the user.
    165     0  stevel 			 */
    166     0  stevel 			} else if (canned) {
    167     0  stevel 				if (SHOULD_NOTIFY(prs))
    168     0  stevel 					prs->request->outcome |= RS_NOTIFY;
    169     0  stevel 				notify (prs, (char *)0, 0, 0, 0);
    170     0  stevel 
    171     0  stevel 			/*
    172     0  stevel 			 * If the request finished successfully, call
    173     0  stevel 			 * "notify()" in case we're to notify the user.
    174     0  stevel 			 */
    175     0  stevel 			} else if (exited == 0) {
    176     0  stevel 				prs->request->outcome |= RS_PRINTED;
    177     0  stevel 
    178     0  stevel 				if (SHOULD_NOTIFY(prs))
    179     0  stevel 					prs->request->outcome |= RS_NOTIFY;
    180     0  stevel 				notify (prs, (char *)0, 0, 0, 0);
    181     0  stevel 			}
    182     0  stevel 
    183     0  stevel 			/*
    184     0  stevel 			 * If the interface program exits with an
    185     0  stevel 			 * exit code higher than EXEC_EXIT_USER, it's
    186     0  stevel 			 * a special case.
    187     0  stevel 			 */
    188     0  stevel 
    189     0  stevel 			switch (exited) {
    190     0  stevel 
    191     0  stevel 			case EXEC_EXIT_FAULT:
    192     0  stevel 				printer_fault (pps, prs, 0, 0);
    193     0  stevel 				break;
    194     0  stevel 
    195     0  stevel 			case EXEC_EXIT_HUP:
    196     0  stevel 				printer_fault (pps, prs, HANGUP_FAULT, 0);
    197     0  stevel 				break;
    198     0  stevel 
    199     0  stevel 			case EXEC_EXIT_INTR:
    200     0  stevel 				printer_fault (pps, prs, INTERRUPT_FAULT, 0);
    201     0  stevel 				break;
    202     0  stevel 
    203     0  stevel 			case EXEC_EXIT_PIPE:
    204     0  stevel 				printer_fault (pps, prs, PIPE_FAULT, 0);
    205     0  stevel 				break;
    206     0  stevel 
    207     0  stevel 			case EXEC_EXIT_EXIT:
    208     0  stevel 				note (
    209     0  stevel 					"Bad exit from interface program for printer %s: %d\n",
    210     0  stevel 					pps->printer->name,
    211     0  stevel 					ep->Errno
    212     0  stevel 				);
    213     0  stevel 				printer_fault (pps, prs, EXIT_FAULT, 0);
    214     0  stevel 				break;
    215     0  stevel 
    216     0  stevel 			case EXEC_EXIT_NPORT:
    217     0  stevel 				printer_fault (pps, prs, OPEN_FAULT, ep->Errno);
    218     0  stevel 				break;
    219     0  stevel 
    220     0  stevel 			case EXEC_EXIT_TMOUT:
    221     0  stevel 				printer_fault (pps, prs, TIMEOUT_FAULT, 0);
    222     0  stevel 				break;
    223     0  stevel 
    224     0  stevel 			case EXEC_EXIT_NOPEN:
    225     0  stevel 				errno = ep->Errno;
    226     0  stevel 				note (
    227     0  stevel 					"Failed to open a print service file (%s).\n",
    228     0  stevel 					PERROR
    229     0  stevel 				);
    230     0  stevel 				break;
    231     0  stevel 
    232     0  stevel 			case EXEC_EXIT_NEXEC:
    233     0  stevel 				errno = ep->Errno;
    234     0  stevel 				note (
    235     0  stevel 					"Failed to exec child process (%s).\n",
    236     0  stevel 					PERROR
    237     0  stevel 				);
    238     0  stevel 				break;
    239     0  stevel 
    240     0  stevel 			case EXEC_EXIT_NOMEM:
    241     0  stevel 				mallocfail ();
    242     0  stevel 				break;
    243     0  stevel 
    244     0  stevel 			case EXEC_EXIT_NFORK:
    245     0  stevel 				errno = ep->Errno;
    246     0  stevel 				note (
    247     0  stevel 					"Failed to fork child process (%s).\n",
    248     0  stevel 					PERROR
    249     0  stevel 				);
    250     0  stevel 				break;
    251     0  stevel 
    252     0  stevel 			case EXEC_EXIT_NPUSH:
    253     0  stevel 				printer_fault (pps, prs, PUSH_FAULT, ep->Errno);
    254     0  stevel 				break;
    255     0  stevel 
    256     0  stevel 			default:
    257     0  stevel 				if ((exited & EXEC_EXIT_NMASK) == EXEC_EXIT_NDIAL)
    258     0  stevel 					dial_problem (
    259     0  stevel 						pps,
    260     0  stevel 						prs,
    261     0  stevel 						exited & ~EXEC_EXIT_NMASK
    262     0  stevel 					);
    263     0  stevel 
    264     0  stevel 				else if (
    265     0  stevel 					exited < -1
    266     0  stevel 				     || exited > EXEC_EXIT_USER
    267     0  stevel 				)
    268     0  stevel 					note (
    269     0  stevel 						"Bad exit from exec() for printer %s: %d\n",
    270     0  stevel 						pps->printer->name,
    271     0  stevel 						exited
    272     0  stevel 					);
    273     0  stevel 
    274     0  stevel 				break;
    275     0  stevel 			}
    276     0  stevel 
    277     0  stevel 			/*
    278     0  stevel 			 * Being in the "dowait()" routine means the
    279     0  stevel 			 * interface (and fast filter!) have stopped.
    280     0  stevel 			 * If we have a fault and we're expected to try
    281     0  stevel 			 * again later, make sure we try again later.
    282     0  stevel 			 */
    283     0  stevel 			if (
    284     0  stevel 				(pps->status & PS_FAULTED)
    285     0  stevel 			     && !STREQU(pps->printer->fault_rec, NAME_WAIT)
    286     0  stevel 			     && !(pps->status & (PS_LATER|PS_DISABLED))
    287     0  stevel 			) {
    288     0  stevel 				load_str (&pps->dis_reason, CUZ_STOPPED);
    289     0  stevel 				schedule (EV_LATER, WHEN_PRINTER, EV_ENABLE, pps);
    290     0  stevel 			}
    291     0  stevel 
    292     0  stevel 			prs->request->outcome &= ~(RS_PRINTING|RS_STOPPED);
    293     0  stevel 
    294     0  stevel 			/*
    295     0  stevel 			 * If the printer to which this request was
    296     0  stevel 			 * assigned is not able to handle requests now,
    297     0  stevel 			 * push waiting requests off on to another
    298     0  stevel 			 * printer.
    299     0  stevel 			 */
    300     0  stevel 			if (prs->printer->status & (PS_FAULTED|PS_DISABLED|PS_LATER))
    301     0  stevel 				(void)queue_repel (prs->printer, 0, (qchk_fnc_type)0);
    302     0  stevel 
    303     0  stevel 			/*
    304     0  stevel 			 * If the request is now assigned to a different
    305     0  stevel 			 * printer, call "schedule()" to fire up an
    306     0  stevel 			 * interface. If this request also happens to
    307     0  stevel 			 * be dead, or in need of refiltering, it won't
    308     0  stevel 			 * get scheduled.
    309     0  stevel 			 */
    310     0  stevel 			if (
    311     0  stevel 				prs->printer != pps
    312     0  stevel 			)
    313     0  stevel 				schedule (EV_INTERF, prs->printer);
    314     0  stevel 
    315     0  stevel 			check_request (prs);
    316     0  stevel 
    317     0  stevel 			/*
    318     0  stevel 			 * Attract the FIRST request that is waiting to
    319     0  stevel 			 * print to this printer, unless the printer isn't
    320     0  stevel 			 * ready to print another request. We do this
    321     0  stevel 			 * even though requests may already be assigned
    322     0  stevel 			 * to this printer, because a request NOT assigned
    323     0  stevel 			 * might be ahead of them in the queue.
    324     0  stevel 			 */
    325     0  stevel 			if (!(pps->status & (PS_FAULTED|PS_DISABLED|PS_LATER)))
    326     0  stevel 				queue_attract (pps, qchk_waiting, 1);
    327     0  stevel 
    328     0  stevel 			break;
    329     0  stevel 
    330     0  stevel 		case EX_SLOWF:
    331     0  stevel 			prs = ep->ex.request;
    332     0  stevel 			ep->ex.request = 0;
    333     0  stevel 			prs->exec = 0;
    334     0  stevel 			prs->request->outcome &= ~RS_FILTERING;
    335     0  stevel 
    336     0  stevel 			/*
    337     0  stevel 			 * If the slow filter was killed with SIGTERM,
    338     0  stevel 			 * it may have been because we canceled the
    339     0  stevel 			 * request, stopped the filtering, or put a
    340     0  stevel 			 * change hold on the request. If so, clear
    341     0  stevel 			 * the "killed" flag because that's not the
    342     0  stevel 			 * condition of importance.
    343     0  stevel 			 */
    344     0  stevel 			canned = 0;
    345     0  stevel 			if (killed == SIGTERM){
    346     0  stevel 				if (prs->request->outcome & RS_CANCELLED)
    347     0  stevel 					canned = 1;
    348     0  stevel 
    349     0  stevel 				if (
    350     0  stevel 					canned
    351     0  stevel 				     || prs->request->outcome & RS_STOPPED
    352     0  stevel 				     || Shutdown
    353     0  stevel 				)
    354     0  stevel 					killed = 0;
    355     0  stevel 			}
    356     0  stevel 
    357     0  stevel 			/*
    358     0  stevel 			 * If there was standard error output from the
    359     0  stevel 			 * slow filter, or if the interface program exited
    360     0  stevel 			 * with a non-zero exit code, the user should
    361     0  stevel 			 * be notified.
    362     0  stevel 			 */
    363     0  stevel 			errbuf = geterrbuf(prs);
    364     0  stevel 			if (prs->request->outcome
    365     0  stevel 			    & (RS_REFILTER | RS_STOPPED)) {
    366     0  stevel 				if (errbuf) {
    367     0  stevel 					Free(errbuf);
    368     0  stevel 					errbuf = NULL;
    369     0  stevel 				}
    370     0  stevel 			}
    371     0  stevel 			if (
    372     0  stevel 				errbuf
    373     0  stevel 			     || 0 < exited && exited <= EXEC_EXIT_USER
    374     0  stevel 			     || killed
    375     0  stevel 			) {
    376     0  stevel 				prs->request->outcome |= RS_FAILED;
    377     0  stevel 				prs->request->outcome |= RS_NOTIFY;
    378     0  stevel 				notify (prs, errbuf, killed, exited, 1);
    379     0  stevel 				if (errbuf)
    380     0  stevel 					Free (errbuf);
    381     0  stevel 
    382     0  stevel 
    383     0  stevel 			/*
    384     0  stevel 			 * If the request was canceled, call "notify()"
    385     0  stevel 			 * in case we're to notify the user.
    386     0  stevel 			 */
    387     0  stevel 			} else if (canned) {
    388     0  stevel 				if (SHOULD_NOTIFY(prs))
    389     0  stevel 					prs->request->outcome |= RS_NOTIFY;
    390     0  stevel 				notify (prs, (char *)0, 0, 0, 1);
    391     0  stevel 
    392     0  stevel 			/*
    393     0  stevel 			 * If the slow filter exited normally, mark
    394     0  stevel 			 * the request as finished slow filtering.
    395     0  stevel 			 */
    396     0  stevel 			} else if (exited == 0) {
    397     0  stevel 				prs->request->outcome |= RS_FILTERED;
    398     0  stevel 
    399     0  stevel 			} else if (exited == -1) {
    400     0  stevel 				/*EMPTY*/;
    401     0  stevel 
    402     0  stevel 			} else if (exited == EXEC_EXIT_NOPEN) {
    403     0  stevel 				errno = ep->Errno;
    404     0  stevel 				note (
    405     0  stevel 					"Failed to open a print service file (%s).\n",
    406     0  stevel 					PERROR
    407     0  stevel 				);
    408     0  stevel 
    409     0  stevel 			} else if (exited == EXEC_EXIT_NEXEC) {
    410     0  stevel 				errno = ep->Errno;
    411     0  stevel 				note (
    412     0  stevel 					"Failed to exec child process (%s).\n",
    413     0  stevel 					PERROR
    414     0  stevel 				);
    415     0  stevel 
    416     0  stevel 			} else if (exited == EXEC_EXIT_NOMEM) {
    417     0  stevel 				mallocfail ();
    418     0  stevel 
    419     0  stevel 			}
    420     0  stevel 
    421     0  stevel 			prs->request->outcome &= ~RS_STOPPED;
    422     0  stevel 
    423     0  stevel 			schedule (EV_INTERF, prs->printer);
    424     0  stevel 			if (
    425     0  stevel 				prs->request->outcome & RS_REFILTER
    426     0  stevel 			)
    427     0  stevel 				schedule (EV_SLOWF, prs);
    428     0  stevel 			else
    429     0  stevel 				schedule (EV_SLOWF, (RSTATUS *)0);
    430     0  stevel 
    431     0  stevel 			check_request (prs);
    432     0  stevel 			break;
    433     0  stevel 
    434     0  stevel 		case EX_NOTIFY:
    435     0  stevel 			prs = ep->ex.request;
    436     0  stevel 			ep->ex.request = 0;
    437     0  stevel 			prs->exec = 0;
    438     0  stevel 
    439     0  stevel 			prs->request->outcome &= ~RS_NOTIFYING;
    440     0  stevel 			    if (!Shutdown || !killed)
    441     0  stevel 				prs->request->outcome &= ~RS_NOTIFY;
    442     0  stevel 
    443     0  stevel 			/*
    444     0  stevel 			 * Now that this notification process slot
    445     0  stevel 			 * has opened up, schedule the next notification
    446     0  stevel 			 * (if any).
    447     0  stevel 			 */
    448     0  stevel 			schedule (EV_NOTIFY, (RSTATUS *)0);
    449     0  stevel 
    450     0  stevel 			check_request (prs);
    451     0  stevel 			break;
    452     0  stevel 
    453     0  stevel 		case EX_ALERT:
    454     0  stevel 			pas = ep->ex.printer->alert;
    455     0  stevel 			goto CleanUpAlert;
    456     0  stevel 
    457     0  stevel 		case EX_FALERT:
    458     0  stevel 			pas = ep->ex.form->alert;
    459     0  stevel 			goto CleanUpAlert;
    460     0  stevel 
    461     0  stevel 		case EX_PALERT:
    462     0  stevel 			pas = ep->ex.pwheel->alert;
    463     0  stevel 			/*
    464     0  stevel 			 * CAUTION: It may well be that we've removed
    465     0  stevel 			 * the print wheel by the time we get here.
    466     0  stevel 			 * Only the alert structure (and exec structure)
    467     0  stevel 			 * can be considered okay.
    468     0  stevel 			 */
    469     0  stevel 
    470     0  stevel CleanUpAlert:
    471     0  stevel 			if (Shutdown)
    472     0  stevel 				break;
    473     0  stevel 
    474     0  stevel 			if (ep->flags & EXF_RESTART) {
    475     0  stevel 				ep->flags &= ~(EXF_RESTART);
    476     0  stevel 				if (exec(ep->type, ep->ex.form) == 0) {
    477     0  stevel 					pas->active = 1;
    478     0  stevel 					break;
    479     0  stevel 				}
    480     0  stevel 			}
    481     0  stevel 			(void)Unlink (pas->msgfile);
    482     0  stevel 			break;
    483     0  stevel 
    484     0  stevel 		}
    485     0  stevel 	}
    486     0  stevel 
    487     0  stevel 	return;
    488     0  stevel }
    489     0  stevel 
    490     0  stevel 
    491     0  stevel /**
    492     0  stevel  ** geterrbuf() - READ NON-BLANK STANDARD ERROR OUTPUT
    493     0  stevel  **/
    494     0  stevel 
    495     0  stevel static char *
    496     0  stevel geterrbuf(RSTATUS *prs)
    497     0  stevel {
    498     0  stevel 	register char		*cp;
    499     0  stevel 	int                     fd,
    500     0  stevel 				n;
    501     0  stevel 	char                    *buf    = 0,
    502     0  stevel 				*file;
    503     0  stevel 	struct stat             statbuf;
    504     0  stevel 
    505     0  stevel 	if (!prs) return(NULL);
    506     0  stevel 
    507     0  stevel 	file = makereqerr(prs);
    508     0  stevel 	if (
    509     0  stevel 		Stat(file, &statbuf) == 0
    510     0  stevel 	     && statbuf.st_size
    511     0  stevel 	     && (fd = Open(file, O_RDONLY)) != -1
    512     0  stevel 	) {
    513     0  stevel 		/*
    514     0  stevel 		 * Don't die if we can't allocate space for this
    515     0  stevel 		 * file--the file may be huge!
    516     0  stevel 		 */
    517     0  stevel 		lp_alloc_fail_handler = 0;
    518     0  stevel 		if ((buf = Malloc(statbuf.st_size + 1)))
    519     0  stevel 			if ((n = Read(fd, buf, statbuf.st_size)) > 0) {
    520     0  stevel 				buf[n] = 0;
    521     0  stevel 
    522     0  stevel 				/*
    523     0  stevel 				 * NOTE: Ignore error output with no
    524     0  stevel 				 * printable text. This hides problems we
    525     0  stevel 				 * have with some shell scripts that
    526     0  stevel 				 * occasionally cause spurious newlines
    527     0  stevel 				 * when stopped via SIGTERM. Without this
    528     0  stevel 				 * check for non-blank output, stopping
    529     0  stevel 				 * a request sometimes causes a request
    530     0  stevel 				 * failure.
    531     0  stevel 				 */
    532     0  stevel 				for (cp = buf; *cp && isspace(*cp); cp++)
    533     0  stevel 					;
    534     0  stevel 				if (!*cp) {
    535     0  stevel 					Free (buf);
    536     0  stevel 					buf = 0;
    537     0  stevel 				}
    538     0  stevel 			} else {
    539     0  stevel 				Free (buf);
    540     0  stevel 				buf = 0;
    541     0  stevel 			}
    542     0  stevel 		lp_alloc_fail_handler = mallocfail;
    543     0  stevel 		Close(fd);
    544     0  stevel 	}
    545     0  stevel 	if (file)
    546     0  stevel 		Free (file);
    547     0  stevel 
    548     0  stevel 	return (buf);
    549     0  stevel }
    550     0  stevel 
    551     0  stevel /**
    552     0  stevel  ** check_request() - CLEAN UP AFTER REQUEST
    553     0  stevel  **/
    554     0  stevel 
    555     0  stevel void
    556     0  stevel check_request(RSTATUS *prs)
    557     0  stevel {
    558     0  stevel 	/*
    559     0  stevel 	 * If the request is done, decrement the count of requests
    560     0  stevel 	 * needing the form or print wheel. Update the disk copy of
    561     0  stevel 	 * the request. If we're finished with the request, get rid of it.
    562     0  stevel 	 */
    563     0  stevel 	if (prs->request->outcome & RS_DONE) {
    564     0  stevel 		unqueue_form (prs);
    565     0  stevel 		unqueue_pwheel (prs);
    566     0  stevel 		putrequest (prs->req_file, prs->request);
    567  3125  jacobs 		if (!(prs->request->outcome & (RS_ACTIVE | RS_NOTIFY))) {
    568     0  stevel 			rmfiles (prs, 1);
    569  3125  jacobs 			free_rstatus (prs);
    570     0  stevel 		}
    571     0  stevel 	}
    572     0  stevel 	return;
    573     0  stevel }
    574     0  stevel 
    575     0  stevel /**
    576     0  stevel  ** check_children()
    577     0  stevel  **/
    578     0  stevel 
    579     0  stevel void
    580     0  stevel check_children(void)
    581     0  stevel {
    582     0  stevel 	register int		i;
    583     0  stevel 
    584  3125  jacobs 	for (i = 0; Exec_Table[i] != NULL; i++)
    585  3125  jacobs 		if (Exec_Table[i]->pid > 0)
    586     0  stevel 			break;
    587     0  stevel 
    588  3125  jacobs 	if (Exec_Table[i] == NULL)
    589     0  stevel 		Shutdown = 2;
    590     0  stevel }
    591