dowait.c revision 0a44ef6d9afbfe052a7e975f55ea0d2954b62a82
/*
* 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
* 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 */
#pragma ident "%Z%%M% %I% %E% SMI"
/* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
#include "lpsched.h"
#include "ctype.h"
#include <syslog.h>
/*
* Macro to test if we should notify the user.
*/
#define SHOULD_NOTIFY(PRS) \
( \
)
/**
** dowait() - CLEAN UP CHILD THAT HAS FINISHED, RESCHEDULE ANOTHER TASK
**/
void
dowait (void)
{
int exited,
i;
while (DoneChildren > 0) {
DoneChildren--;
break;
continue;
case EX_INTERF:
/*
* WARNING: It could be that when we get here
*
* pps->request->printer != pps
*
* because the request has been assigned to
* another printer.
*/
/*
* If the interface program exited cleanly
* or with just a user error, the printer
* is assumed to be working.
*/
}
/*
* If the interface program was killed with
* SIGTERM, it may have been because we canceled
* the request, disabled the printer, or for some
* other reason stopped the request.
* If so, clear the "killed" flag because that's
* not the condition of importance here.
*/
canned = 0;
canned = 1;
if (
|| Shutdown
)
killed = 0;
}
/*
* If there was standard error output from the
* interface program, or if the interface program
* exited with a (user) exit code, or if it got
* a strange signal, the user should be notified.
*/
if (
|| killed
) {
if (exited != EXIT_RETRY) {
}
if (errbuf)
/*
* If the request was canceled, call "notify()"
* in case we're to notify the user.
*/
} else if (canned) {
if (SHOULD_NOTIFY(prs))
/*
* If the request finished successfully, call
* "notify()" in case we're to notify the user.
*/
} else if (exited == 0) {
if (SHOULD_NOTIFY(prs))
}
/*
* If the interface program exits with an
* exit code higher than EXEC_EXIT_USER, it's
* a special case.
*/
switch (exited) {
case EXEC_EXIT_FAULT:
break;
case EXEC_EXIT_HUP:
break;
case EXEC_EXIT_INTR:
break;
case EXEC_EXIT_PIPE:
break;
case EXEC_EXIT_EXIT:
note (
"Bad exit from interface program for printer %s: %d\n",
);
break;
case EXEC_EXIT_NPORT:
break;
case EXEC_EXIT_TMOUT:
break;
case EXEC_EXIT_NOPEN:
note (
"Failed to open a print service file (%s).\n",
);
break;
case EXEC_EXIT_NEXEC:
note (
"Failed to exec child process (%s).\n",
);
break;
case EXEC_EXIT_NOMEM:
mallocfail ();
break;
case EXEC_EXIT_NFORK:
note (
"Failed to fork child process (%s).\n",
);
break;
case EXEC_EXIT_NPUSH:
break;
default:
pps,
prs,
);
else if (
exited < -1
|| exited > EXEC_EXIT_USER
)
note (
"Bad exit from exec() for printer %s: %d\n",
);
break;
}
/*
* Being in the "dowait()" routine means the
* interface (and fast filter!) have stopped.
* If we have a fault and we're expected to try
* again later, make sure we try again later.
*/
if (
) {
}
/*
* If the printer to which this request was
* assigned is not able to handle requests now,
* push waiting requests off on to another
* printer.
*/
/*
* If the request is now assigned to a different
* printer, call "schedule()" to fire up an
* interface. If this request also happens to
* be dead, or in need of refiltering, it won't
* get scheduled.
*/
if (
)
check_request (prs);
/*
* Attract the FIRST request that is waiting to
* print to this printer, unless the printer isn't
* ready to print another request. We do this
* even though requests may already be assigned
* to this printer, because a request NOT assigned
* might be ahead of them in the queue.
*/
break;
case EX_SLOWF:
/*
* If the slow filter was killed with SIGTERM,
* it may have been because we canceled the
* request, stopped the filtering, or put a
* change hold on the request. If so, clear
* the "killed" flag because that's not the
* condition of importance.
*/
canned = 0;
canned = 1;
if (
|| Shutdown
)
killed = 0;
}
/*
* If there was standard error output from the
* slow filter, or if the interface program exited
* with a non-zero exit code, the user should
* be notified.
*/
& (RS_REFILTER | RS_STOPPED)) {
if (errbuf) {
}
}
if (
|| killed
) {
if (errbuf)
/*
* If the request was canceled, call "notify()"
* in case we're to notify the user.
*/
} else if (canned) {
if (SHOULD_NOTIFY(prs))
/*
* If the slow filter exited normally, mark
* the request as finished slow filtering.
*/
} else if (exited == 0) {
} else if (exited == -1) {
/*EMPTY*/;
} else if (exited == EXEC_EXIT_NOPEN) {
note (
"Failed to open a print service file (%s).\n",
);
} else if (exited == EXEC_EXIT_NEXEC) {
note (
"Failed to exec child process (%s).\n",
);
} else if (exited == EXEC_EXIT_NOMEM) {
mallocfail ();
}
if (
)
else
check_request (prs);
break;
case EX_NOTIFY:
/*
* Now that this notification process slot
* has opened up, schedule the next notification
* (if any).
*/
check_request (prs);
break;
case EX_ALERT:
goto CleanUpAlert;
case EX_FALERT:
goto CleanUpAlert;
case EX_PALERT:
/*
* CAUTION: It may well be that we've removed
* the print wheel by the time we get here.
* Only the alert structure (and exec structure)
* can be considered okay.
*/
if (Shutdown)
break;
break;
}
}
break;
}
}
return;
}
/**
** geterrbuf() - READ NON-BLANK STANDARD ERROR OUTPUT
**/
static char *
{
register char *cp;
int fd,
n;
char *buf = 0,
*file;
if (
) {
/*
* Don't die if we can't allocate space for this
* file--the file may be huge!
*/
buf[n] = 0;
/*
* NOTE: Ignore error output with no
* printable text. This hides problems we
* have with some shell scripts that
* occasionally cause spurious newlines
* when stopped via SIGTERM. Without this
* check for non-blank output, stopping
* a request sometimes causes a request
* failure.
*/
;
if (!*cp) {
buf = 0;
}
} else {
buf = 0;
}
}
if (file)
return (buf);
}
/**
** check_request() - CLEAN UP AFTER REQUEST
**/
void
{
/*
* If the request is done, decrement the count of requests
* needing the form or print wheel. Update the disk copy of
* the request. If we're finished with the request, get rid of it.
*/
unqueue_form (prs);
free_rstatus (prs);
}
}
return;
}
/**
** check_children()
**/
void
check_children(void)
{
register int i;
for (i = 0; Exec_Table[i] != NULL; i++)
if (Exec_Table[i]->pid > 0)
break;
if (Exec_Table[i] == NULL)
Shutdown = 2;
}