17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0a44ef6dSjacobs * Common Development and Distribution License (the "License"). 6*0a44ef6dSjacobs * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate 227c478bd9Sstevel@tonic-gate /* 23*0a44ef6dSjacobs * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 27*0a44ef6dSjacobs /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*0a44ef6dSjacobs /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include "lpsched.h" 357c478bd9Sstevel@tonic-gate #include "ctype.h" 367c478bd9Sstevel@tonic-gate #include "sys/stat.h" 37*0a44ef6dSjacobs #include <syslog.h> 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * Macro to test if we should notify the user. 417c478bd9Sstevel@tonic-gate */ 427c478bd9Sstevel@tonic-gate #define SHOULD_NOTIFY(PRS) \ 437c478bd9Sstevel@tonic-gate ( \ 447c478bd9Sstevel@tonic-gate (PRS)->request->actions & (ACT_MAIL|ACT_WRITE|ACT_NOTIFY)\ 457c478bd9Sstevel@tonic-gate || (PRS)->request->alert \ 467c478bd9Sstevel@tonic-gate ) 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate static char * geterrbuf ( RSTATUS * ); 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /** 517c478bd9Sstevel@tonic-gate ** dowait() - CLEAN UP CHILD THAT HAS FINISHED, RESCHEDULE ANOTHER TASK 527c478bd9Sstevel@tonic-gate **/ 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate void 557c478bd9Sstevel@tonic-gate dowait (void) 567c478bd9Sstevel@tonic-gate { 577c478bd9Sstevel@tonic-gate int exited, 587c478bd9Sstevel@tonic-gate killed, 597c478bd9Sstevel@tonic-gate canned, 607c478bd9Sstevel@tonic-gate i; 617c478bd9Sstevel@tonic-gate EXEC *ep; 627c478bd9Sstevel@tonic-gate char *errbuf = NULL; 637c478bd9Sstevel@tonic-gate register RSTATUS *prs; 647c478bd9Sstevel@tonic-gate register PSTATUS *pps; 657c478bd9Sstevel@tonic-gate register ALERT *pas; 667c478bd9Sstevel@tonic-gate 67*0a44ef6dSjacobs syslog(LOG_DEBUG, "dowait(%d)", DoneChildren); 687c478bd9Sstevel@tonic-gate while (DoneChildren > 0) { 697c478bd9Sstevel@tonic-gate DoneChildren--; 707c478bd9Sstevel@tonic-gate 71*0a44ef6dSjacobs for (i = 0; (ep = Exec_Table[i]) != NULL; i++) 72*0a44ef6dSjacobs if (ep->pid == -99) 737c478bd9Sstevel@tonic-gate break; 74*0a44ef6dSjacobs 75*0a44ef6dSjacobs syslog(LOG_DEBUG, "dowait(): 0x%8.8x", ep); 76*0a44ef6dSjacobs 77*0a44ef6dSjacobs if (Exec_Table[i] == NULL) /* nothing to cleanup */ 787c478bd9Sstevel@tonic-gate continue; 797c478bd9Sstevel@tonic-gate 80*0a44ef6dSjacobs syslog(LOG_DEBUG, "dowait(): cleaning up 0x%8.8x", ep); 81*0a44ef6dSjacobs 827c478bd9Sstevel@tonic-gate ep->pid = 0; 837c478bd9Sstevel@tonic-gate ep->key = 0; /* avoid subsequent sneaks */ 847c478bd9Sstevel@tonic-gate if (ep->md) 857c478bd9Sstevel@tonic-gate DROP_MD(ep->md); 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate killed = KILLED(ep->status); 887c478bd9Sstevel@tonic-gate exited = EXITED(ep->status); 897c478bd9Sstevel@tonic-gate 90*0a44ef6dSjacobs syslog(LOG_DEBUG, "dowait(): type %d, killed %d, exited %d", 91*0a44ef6dSjacobs ep->type, killed, exited); 92*0a44ef6dSjacobs 937c478bd9Sstevel@tonic-gate switch (ep->type) { 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate case EX_INTERF: 967c478bd9Sstevel@tonic-gate /* 977c478bd9Sstevel@tonic-gate * WARNING: It could be that when we get here 987c478bd9Sstevel@tonic-gate * 997c478bd9Sstevel@tonic-gate * pps->request->printer != pps 1007c478bd9Sstevel@tonic-gate * 1017c478bd9Sstevel@tonic-gate * because the request has been assigned to 1027c478bd9Sstevel@tonic-gate * another printer. 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate pps = ep->ex.printer; 1057c478bd9Sstevel@tonic-gate prs = pps->request; 1067c478bd9Sstevel@tonic-gate pps->request = 0; 1077c478bd9Sstevel@tonic-gate pps->status &= ~PS_BUSY; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* 1107c478bd9Sstevel@tonic-gate * If the interface program exited cleanly 1117c478bd9Sstevel@tonic-gate * or with just a user error, the printer 1127c478bd9Sstevel@tonic-gate * is assumed to be working. 1137c478bd9Sstevel@tonic-gate */ 1147c478bd9Sstevel@tonic-gate if (0 <= exited && exited < EXEC_EXIT_USER) { 1157c478bd9Sstevel@tonic-gate pps->status &= ~PS_FAULTED; 1167c478bd9Sstevel@tonic-gate if (pps->alert->active) 1177c478bd9Sstevel@tonic-gate cancel_alert (A_PRINTER, pps); 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * If the interface program was killed with 1227c478bd9Sstevel@tonic-gate * SIGTERM, it may have been because we canceled 1237c478bd9Sstevel@tonic-gate * the request, disabled the printer, or for some 1247c478bd9Sstevel@tonic-gate * other reason stopped the request. 1257c478bd9Sstevel@tonic-gate * If so, clear the "killed" flag because that's 1267c478bd9Sstevel@tonic-gate * not the condition of importance here. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate canned = 0; 1297c478bd9Sstevel@tonic-gate if (killed == SIGTERM) { 1307c478bd9Sstevel@tonic-gate if (prs->request->outcome & RS_CANCELLED) 1317c478bd9Sstevel@tonic-gate canned = 1; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate if ( 1347c478bd9Sstevel@tonic-gate canned 1357c478bd9Sstevel@tonic-gate || pps->status & (PS_DISABLED|PS_FAULTED) 1367c478bd9Sstevel@tonic-gate || prs->request->outcome & RS_STOPPED 1377c478bd9Sstevel@tonic-gate || Shutdown 1387c478bd9Sstevel@tonic-gate ) 1397c478bd9Sstevel@tonic-gate killed = 0; 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * If there was standard error output from the 1447c478bd9Sstevel@tonic-gate * interface program, or if the interface program 1457c478bd9Sstevel@tonic-gate * exited with a (user) exit code, or if it got 1467c478bd9Sstevel@tonic-gate * a strange signal, the user should be notified. 1477c478bd9Sstevel@tonic-gate */ 1487c478bd9Sstevel@tonic-gate errbuf = geterrbuf(prs); 1497c478bd9Sstevel@tonic-gate if ( 1507c478bd9Sstevel@tonic-gate errbuf 1517c478bd9Sstevel@tonic-gate || (0 < exited && exited <= EXEC_EXIT_USER) 1527c478bd9Sstevel@tonic-gate || killed 1537c478bd9Sstevel@tonic-gate ) { 1547c478bd9Sstevel@tonic-gate if (exited != EXIT_RETRY) { 1557c478bd9Sstevel@tonic-gate prs->request->outcome |= RS_FAILED; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate prs->request->outcome |= RS_NOTIFY; 1587c478bd9Sstevel@tonic-gate notify (prs, errbuf, killed, exited, 0); 1597c478bd9Sstevel@tonic-gate if (errbuf) 1607c478bd9Sstevel@tonic-gate Free (errbuf); 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* 1637c478bd9Sstevel@tonic-gate * If the request was canceled, call "notify()" 1647c478bd9Sstevel@tonic-gate * in case we're to notify the user. 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate } else if (canned) { 1677c478bd9Sstevel@tonic-gate if (SHOULD_NOTIFY(prs)) 1687c478bd9Sstevel@tonic-gate prs->request->outcome |= RS_NOTIFY; 1697c478bd9Sstevel@tonic-gate notify (prs, (char *)0, 0, 0, 0); 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * If the request finished successfully, call 1737c478bd9Sstevel@tonic-gate * "notify()" in case we're to notify the user. 1747c478bd9Sstevel@tonic-gate */ 1757c478bd9Sstevel@tonic-gate } else if (exited == 0) { 1767c478bd9Sstevel@tonic-gate prs->request->outcome |= RS_PRINTED; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate if (SHOULD_NOTIFY(prs)) 1797c478bd9Sstevel@tonic-gate prs->request->outcome |= RS_NOTIFY; 1807c478bd9Sstevel@tonic-gate notify (prs, (char *)0, 0, 0, 0); 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* 1847c478bd9Sstevel@tonic-gate * If the interface program exits with an 1857c478bd9Sstevel@tonic-gate * exit code higher than EXEC_EXIT_USER, it's 1867c478bd9Sstevel@tonic-gate * a special case. 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate switch (exited) { 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate case EXEC_EXIT_FAULT: 1927c478bd9Sstevel@tonic-gate printer_fault (pps, prs, 0, 0); 1937c478bd9Sstevel@tonic-gate break; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate case EXEC_EXIT_HUP: 1967c478bd9Sstevel@tonic-gate printer_fault (pps, prs, HANGUP_FAULT, 0); 1977c478bd9Sstevel@tonic-gate break; 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate case EXEC_EXIT_INTR: 2007c478bd9Sstevel@tonic-gate printer_fault (pps, prs, INTERRUPT_FAULT, 0); 2017c478bd9Sstevel@tonic-gate break; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate case EXEC_EXIT_PIPE: 2047c478bd9Sstevel@tonic-gate printer_fault (pps, prs, PIPE_FAULT, 0); 2057c478bd9Sstevel@tonic-gate break; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate case EXEC_EXIT_EXIT: 2087c478bd9Sstevel@tonic-gate note ( 2097c478bd9Sstevel@tonic-gate "Bad exit from interface program for printer %s: %d\n", 2107c478bd9Sstevel@tonic-gate pps->printer->name, 2117c478bd9Sstevel@tonic-gate ep->Errno 2127c478bd9Sstevel@tonic-gate ); 2137c478bd9Sstevel@tonic-gate printer_fault (pps, prs, EXIT_FAULT, 0); 2147c478bd9Sstevel@tonic-gate break; 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate case EXEC_EXIT_NPORT: 2177c478bd9Sstevel@tonic-gate printer_fault (pps, prs, OPEN_FAULT, ep->Errno); 2187c478bd9Sstevel@tonic-gate break; 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate case EXEC_EXIT_TMOUT: 2217c478bd9Sstevel@tonic-gate printer_fault (pps, prs, TIMEOUT_FAULT, 0); 2227c478bd9Sstevel@tonic-gate break; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate case EXEC_EXIT_NOPEN: 2257c478bd9Sstevel@tonic-gate errno = ep->Errno; 2267c478bd9Sstevel@tonic-gate note ( 2277c478bd9Sstevel@tonic-gate "Failed to open a print service file (%s).\n", 2287c478bd9Sstevel@tonic-gate PERROR 2297c478bd9Sstevel@tonic-gate ); 2307c478bd9Sstevel@tonic-gate break; 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate case EXEC_EXIT_NEXEC: 2337c478bd9Sstevel@tonic-gate errno = ep->Errno; 2347c478bd9Sstevel@tonic-gate note ( 2357c478bd9Sstevel@tonic-gate "Failed to exec child process (%s).\n", 2367c478bd9Sstevel@tonic-gate PERROR 2377c478bd9Sstevel@tonic-gate ); 2387c478bd9Sstevel@tonic-gate break; 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate case EXEC_EXIT_NOMEM: 2417c478bd9Sstevel@tonic-gate mallocfail (); 2427c478bd9Sstevel@tonic-gate break; 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate case EXEC_EXIT_NFORK: 2457c478bd9Sstevel@tonic-gate errno = ep->Errno; 2467c478bd9Sstevel@tonic-gate note ( 2477c478bd9Sstevel@tonic-gate "Failed to fork child process (%s).\n", 2487c478bd9Sstevel@tonic-gate PERROR 2497c478bd9Sstevel@tonic-gate ); 2507c478bd9Sstevel@tonic-gate break; 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate case EXEC_EXIT_NPUSH: 2537c478bd9Sstevel@tonic-gate printer_fault (pps, prs, PUSH_FAULT, ep->Errno); 2547c478bd9Sstevel@tonic-gate break; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate default: 2577c478bd9Sstevel@tonic-gate if ((exited & EXEC_EXIT_NMASK) == EXEC_EXIT_NDIAL) 2587c478bd9Sstevel@tonic-gate dial_problem ( 2597c478bd9Sstevel@tonic-gate pps, 2607c478bd9Sstevel@tonic-gate prs, 2617c478bd9Sstevel@tonic-gate exited & ~EXEC_EXIT_NMASK 2627c478bd9Sstevel@tonic-gate ); 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate else if ( 2657c478bd9Sstevel@tonic-gate exited < -1 2667c478bd9Sstevel@tonic-gate || exited > EXEC_EXIT_USER 2677c478bd9Sstevel@tonic-gate ) 2687c478bd9Sstevel@tonic-gate note ( 2697c478bd9Sstevel@tonic-gate "Bad exit from exec() for printer %s: %d\n", 2707c478bd9Sstevel@tonic-gate pps->printer->name, 2717c478bd9Sstevel@tonic-gate exited 2727c478bd9Sstevel@tonic-gate ); 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate } 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * Being in the "dowait()" routine means the 2797c478bd9Sstevel@tonic-gate * interface (and fast filter!) have stopped. 2807c478bd9Sstevel@tonic-gate * If we have a fault and we're expected to try 2817c478bd9Sstevel@tonic-gate * again later, make sure we try again later. 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate if ( 2847c478bd9Sstevel@tonic-gate (pps->status & PS_FAULTED) 2857c478bd9Sstevel@tonic-gate && !STREQU(pps->printer->fault_rec, NAME_WAIT) 2867c478bd9Sstevel@tonic-gate && !(pps->status & (PS_LATER|PS_DISABLED)) 2877c478bd9Sstevel@tonic-gate ) { 2887c478bd9Sstevel@tonic-gate load_str (&pps->dis_reason, CUZ_STOPPED); 2897c478bd9Sstevel@tonic-gate schedule (EV_LATER, WHEN_PRINTER, EV_ENABLE, pps); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate prs->request->outcome &= ~(RS_PRINTING|RS_STOPPED); 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* 2957c478bd9Sstevel@tonic-gate * If the printer to which this request was 2967c478bd9Sstevel@tonic-gate * assigned is not able to handle requests now, 2977c478bd9Sstevel@tonic-gate * push waiting requests off on to another 2987c478bd9Sstevel@tonic-gate * printer. 2997c478bd9Sstevel@tonic-gate */ 3007c478bd9Sstevel@tonic-gate if (prs->printer->status & (PS_FAULTED|PS_DISABLED|PS_LATER)) 3017c478bd9Sstevel@tonic-gate (void)queue_repel (prs->printer, 0, (qchk_fnc_type)0); 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate /* 3047c478bd9Sstevel@tonic-gate * If the request is now assigned to a different 3057c478bd9Sstevel@tonic-gate * printer, call "schedule()" to fire up an 3067c478bd9Sstevel@tonic-gate * interface. If this request also happens to 3077c478bd9Sstevel@tonic-gate * be dead, or in need of refiltering, it won't 3087c478bd9Sstevel@tonic-gate * get scheduled. 3097c478bd9Sstevel@tonic-gate */ 3107c478bd9Sstevel@tonic-gate if ( 3117c478bd9Sstevel@tonic-gate prs->printer != pps 3127c478bd9Sstevel@tonic-gate ) 3137c478bd9Sstevel@tonic-gate schedule (EV_INTERF, prs->printer); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate check_request (prs); 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* 3187c478bd9Sstevel@tonic-gate * Attract the FIRST request that is waiting to 3197c478bd9Sstevel@tonic-gate * print to this printer, unless the printer isn't 3207c478bd9Sstevel@tonic-gate * ready to print another request. We do this 3217c478bd9Sstevel@tonic-gate * even though requests may already be assigned 3227c478bd9Sstevel@tonic-gate * to this printer, because a request NOT assigned 3237c478bd9Sstevel@tonic-gate * might be ahead of them in the queue. 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate if (!(pps->status & (PS_FAULTED|PS_DISABLED|PS_LATER))) 3267c478bd9Sstevel@tonic-gate queue_attract (pps, qchk_waiting, 1); 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate break; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate case EX_SLOWF: 3317c478bd9Sstevel@tonic-gate prs = ep->ex.request; 3327c478bd9Sstevel@tonic-gate ep->ex.request = 0; 3337c478bd9Sstevel@tonic-gate prs->exec = 0; 3347c478bd9Sstevel@tonic-gate prs->request->outcome &= ~RS_FILTERING; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * If the slow filter was killed with SIGTERM, 3387c478bd9Sstevel@tonic-gate * it may have been because we canceled the 3397c478bd9Sstevel@tonic-gate * request, stopped the filtering, or put a 3407c478bd9Sstevel@tonic-gate * change hold on the request. If so, clear 3417c478bd9Sstevel@tonic-gate * the "killed" flag because that's not the 3427c478bd9Sstevel@tonic-gate * condition of importance. 3437c478bd9Sstevel@tonic-gate */ 3447c478bd9Sstevel@tonic-gate canned = 0; 3457c478bd9Sstevel@tonic-gate if (killed == SIGTERM){ 3467c478bd9Sstevel@tonic-gate if (prs->request->outcome & RS_CANCELLED) 3477c478bd9Sstevel@tonic-gate canned = 1; 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate if ( 3507c478bd9Sstevel@tonic-gate canned 3517c478bd9Sstevel@tonic-gate || prs->request->outcome & RS_STOPPED 3527c478bd9Sstevel@tonic-gate || Shutdown 3537c478bd9Sstevel@tonic-gate ) 3547c478bd9Sstevel@tonic-gate killed = 0; 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate /* 3587c478bd9Sstevel@tonic-gate * If there was standard error output from the 3597c478bd9Sstevel@tonic-gate * slow filter, or if the interface program exited 3607c478bd9Sstevel@tonic-gate * with a non-zero exit code, the user should 3617c478bd9Sstevel@tonic-gate * be notified. 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate errbuf = geterrbuf(prs); 3647c478bd9Sstevel@tonic-gate if (prs->request->outcome 3657c478bd9Sstevel@tonic-gate & (RS_REFILTER | RS_STOPPED)) { 3667c478bd9Sstevel@tonic-gate if (errbuf) { 3677c478bd9Sstevel@tonic-gate Free(errbuf); 3687c478bd9Sstevel@tonic-gate errbuf = NULL; 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate if ( 3727c478bd9Sstevel@tonic-gate errbuf 3737c478bd9Sstevel@tonic-gate || 0 < exited && exited <= EXEC_EXIT_USER 3747c478bd9Sstevel@tonic-gate || killed 3757c478bd9Sstevel@tonic-gate ) { 3767c478bd9Sstevel@tonic-gate prs->request->outcome |= RS_FAILED; 3777c478bd9Sstevel@tonic-gate prs->request->outcome |= RS_NOTIFY; 3787c478bd9Sstevel@tonic-gate notify (prs, errbuf, killed, exited, 1); 3797c478bd9Sstevel@tonic-gate if (errbuf) 3807c478bd9Sstevel@tonic-gate Free (errbuf); 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * If the request was canceled, call "notify()" 3857c478bd9Sstevel@tonic-gate * in case we're to notify the user. 3867c478bd9Sstevel@tonic-gate */ 3877c478bd9Sstevel@tonic-gate } else if (canned) { 3887c478bd9Sstevel@tonic-gate if (SHOULD_NOTIFY(prs)) 3897c478bd9Sstevel@tonic-gate prs->request->outcome |= RS_NOTIFY; 3907c478bd9Sstevel@tonic-gate notify (prs, (char *)0, 0, 0, 1); 3917c478bd9Sstevel@tonic-gate 3927c478bd9Sstevel@tonic-gate /* 3937c478bd9Sstevel@tonic-gate * If the slow filter exited normally, mark 3947c478bd9Sstevel@tonic-gate * the request as finished slow filtering. 3957c478bd9Sstevel@tonic-gate */ 3967c478bd9Sstevel@tonic-gate } else if (exited == 0) { 3977c478bd9Sstevel@tonic-gate prs->request->outcome |= RS_FILTERED; 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate } else if (exited == -1) { 4007c478bd9Sstevel@tonic-gate /*EMPTY*/; 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate } else if (exited == EXEC_EXIT_NOPEN) { 4037c478bd9Sstevel@tonic-gate errno = ep->Errno; 4047c478bd9Sstevel@tonic-gate note ( 4057c478bd9Sstevel@tonic-gate "Failed to open a print service file (%s).\n", 4067c478bd9Sstevel@tonic-gate PERROR 4077c478bd9Sstevel@tonic-gate ); 4087c478bd9Sstevel@tonic-gate 4097c478bd9Sstevel@tonic-gate } else if (exited == EXEC_EXIT_NEXEC) { 4107c478bd9Sstevel@tonic-gate errno = ep->Errno; 4117c478bd9Sstevel@tonic-gate note ( 4127c478bd9Sstevel@tonic-gate "Failed to exec child process (%s).\n", 4137c478bd9Sstevel@tonic-gate PERROR 4147c478bd9Sstevel@tonic-gate ); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate } else if (exited == EXEC_EXIT_NOMEM) { 4177c478bd9Sstevel@tonic-gate mallocfail (); 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate prs->request->outcome &= ~RS_STOPPED; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate schedule (EV_INTERF, prs->printer); 4247c478bd9Sstevel@tonic-gate if ( 4257c478bd9Sstevel@tonic-gate prs->request->outcome & RS_REFILTER 4267c478bd9Sstevel@tonic-gate ) 4277c478bd9Sstevel@tonic-gate schedule (EV_SLOWF, prs); 4287c478bd9Sstevel@tonic-gate else 4297c478bd9Sstevel@tonic-gate schedule (EV_SLOWF, (RSTATUS *)0); 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate check_request (prs); 4327c478bd9Sstevel@tonic-gate break; 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate case EX_NOTIFY: 4357c478bd9Sstevel@tonic-gate prs = ep->ex.request; 4367c478bd9Sstevel@tonic-gate ep->ex.request = 0; 4377c478bd9Sstevel@tonic-gate prs->exec = 0; 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate prs->request->outcome &= ~RS_NOTIFYING; 4407c478bd9Sstevel@tonic-gate if (!Shutdown || !killed) 4417c478bd9Sstevel@tonic-gate prs->request->outcome &= ~RS_NOTIFY; 4427c478bd9Sstevel@tonic-gate 4437c478bd9Sstevel@tonic-gate /* 4447c478bd9Sstevel@tonic-gate * Now that this notification process slot 4457c478bd9Sstevel@tonic-gate * has opened up, schedule the next notification 4467c478bd9Sstevel@tonic-gate * (if any). 4477c478bd9Sstevel@tonic-gate */ 4487c478bd9Sstevel@tonic-gate schedule (EV_NOTIFY, (RSTATUS *)0); 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate check_request (prs); 4517c478bd9Sstevel@tonic-gate break; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate case EX_ALERT: 4547c478bd9Sstevel@tonic-gate pas = ep->ex.printer->alert; 4557c478bd9Sstevel@tonic-gate goto CleanUpAlert; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate case EX_FALERT: 4587c478bd9Sstevel@tonic-gate pas = ep->ex.form->alert; 4597c478bd9Sstevel@tonic-gate goto CleanUpAlert; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate case EX_PALERT: 4627c478bd9Sstevel@tonic-gate pas = ep->ex.pwheel->alert; 4637c478bd9Sstevel@tonic-gate /* 4647c478bd9Sstevel@tonic-gate * CAUTION: It may well be that we've removed 4657c478bd9Sstevel@tonic-gate * the print wheel by the time we get here. 4667c478bd9Sstevel@tonic-gate * Only the alert structure (and exec structure) 4677c478bd9Sstevel@tonic-gate * can be considered okay. 4687c478bd9Sstevel@tonic-gate */ 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate CleanUpAlert: 4717c478bd9Sstevel@tonic-gate if (Shutdown) 4727c478bd9Sstevel@tonic-gate break; 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate if (ep->flags & EXF_RESTART) { 4757c478bd9Sstevel@tonic-gate ep->flags &= ~(EXF_RESTART); 4767c478bd9Sstevel@tonic-gate if (exec(ep->type, ep->ex.form) == 0) { 4777c478bd9Sstevel@tonic-gate pas->active = 1; 4787c478bd9Sstevel@tonic-gate break; 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate (void)Unlink (pas->msgfile); 4827c478bd9Sstevel@tonic-gate break; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate } 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate return; 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /** 4927c478bd9Sstevel@tonic-gate ** geterrbuf() - READ NON-BLANK STANDARD ERROR OUTPUT 4937c478bd9Sstevel@tonic-gate **/ 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate static char * 4967c478bd9Sstevel@tonic-gate geterrbuf(RSTATUS *prs) 4977c478bd9Sstevel@tonic-gate { 4987c478bd9Sstevel@tonic-gate register char *cp; 4997c478bd9Sstevel@tonic-gate int fd, 5007c478bd9Sstevel@tonic-gate n; 5017c478bd9Sstevel@tonic-gate char *buf = 0, 5027c478bd9Sstevel@tonic-gate *file; 5037c478bd9Sstevel@tonic-gate struct stat statbuf; 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate if (!prs) return(NULL); 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate file = makereqerr(prs); 5087c478bd9Sstevel@tonic-gate if ( 5097c478bd9Sstevel@tonic-gate Stat(file, &statbuf) == 0 5107c478bd9Sstevel@tonic-gate && statbuf.st_size 5117c478bd9Sstevel@tonic-gate && (fd = Open(file, O_RDONLY)) != -1 5127c478bd9Sstevel@tonic-gate ) { 5137c478bd9Sstevel@tonic-gate /* 5147c478bd9Sstevel@tonic-gate * Don't die if we can't allocate space for this 5157c478bd9Sstevel@tonic-gate * file--the file may be huge! 5167c478bd9Sstevel@tonic-gate */ 5177c478bd9Sstevel@tonic-gate lp_alloc_fail_handler = 0; 5187c478bd9Sstevel@tonic-gate if ((buf = Malloc(statbuf.st_size + 1))) 5197c478bd9Sstevel@tonic-gate if ((n = Read(fd, buf, statbuf.st_size)) > 0) { 5207c478bd9Sstevel@tonic-gate buf[n] = 0; 5217c478bd9Sstevel@tonic-gate 5227c478bd9Sstevel@tonic-gate /* 5237c478bd9Sstevel@tonic-gate * NOTE: Ignore error output with no 5247c478bd9Sstevel@tonic-gate * printable text. This hides problems we 5257c478bd9Sstevel@tonic-gate * have with some shell scripts that 5267c478bd9Sstevel@tonic-gate * occasionally cause spurious newlines 5277c478bd9Sstevel@tonic-gate * when stopped via SIGTERM. Without this 5287c478bd9Sstevel@tonic-gate * check for non-blank output, stopping 5297c478bd9Sstevel@tonic-gate * a request sometimes causes a request 5307c478bd9Sstevel@tonic-gate * failure. 5317c478bd9Sstevel@tonic-gate */ 5327c478bd9Sstevel@tonic-gate for (cp = buf; *cp && isspace(*cp); cp++) 5337c478bd9Sstevel@tonic-gate ; 5347c478bd9Sstevel@tonic-gate if (!*cp) { 5357c478bd9Sstevel@tonic-gate Free (buf); 5367c478bd9Sstevel@tonic-gate buf = 0; 5377c478bd9Sstevel@tonic-gate } 5387c478bd9Sstevel@tonic-gate } else { 5397c478bd9Sstevel@tonic-gate Free (buf); 5407c478bd9Sstevel@tonic-gate buf = 0; 5417c478bd9Sstevel@tonic-gate } 5427c478bd9Sstevel@tonic-gate lp_alloc_fail_handler = mallocfail; 5437c478bd9Sstevel@tonic-gate Close(fd); 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate if (file) 5467c478bd9Sstevel@tonic-gate Free (file); 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate return (buf); 5497c478bd9Sstevel@tonic-gate } 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate /** 5527c478bd9Sstevel@tonic-gate ** check_request() - CLEAN UP AFTER REQUEST 5537c478bd9Sstevel@tonic-gate **/ 5547c478bd9Sstevel@tonic-gate 5557c478bd9Sstevel@tonic-gate void 5567c478bd9Sstevel@tonic-gate check_request(RSTATUS *prs) 5577c478bd9Sstevel@tonic-gate { 5587c478bd9Sstevel@tonic-gate /* 5597c478bd9Sstevel@tonic-gate * If the request is done, decrement the count of requests 5607c478bd9Sstevel@tonic-gate * needing the form or print wheel. Update the disk copy of 5617c478bd9Sstevel@tonic-gate * the request. If we're finished with the request, get rid of it. 5627c478bd9Sstevel@tonic-gate */ 5637c478bd9Sstevel@tonic-gate if (prs->request->outcome & RS_DONE) { 5647c478bd9Sstevel@tonic-gate unqueue_form (prs); 5657c478bd9Sstevel@tonic-gate unqueue_pwheel (prs); 5667c478bd9Sstevel@tonic-gate putrequest (prs->req_file, prs->request); 567*0a44ef6dSjacobs if (!(prs->request->outcome & (RS_ACTIVE | RS_NOTIFY))) { 5687c478bd9Sstevel@tonic-gate rmfiles (prs, 1); 569*0a44ef6dSjacobs free_rstatus (prs); 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate return; 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /** 5767c478bd9Sstevel@tonic-gate ** check_children() 5777c478bd9Sstevel@tonic-gate **/ 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate void 5807c478bd9Sstevel@tonic-gate check_children(void) 5817c478bd9Sstevel@tonic-gate { 5827c478bd9Sstevel@tonic-gate register int i; 5837c478bd9Sstevel@tonic-gate 584*0a44ef6dSjacobs for (i = 0; Exec_Table[i] != NULL; i++) 585*0a44ef6dSjacobs if (Exec_Table[i]->pid > 0) 5867c478bd9Sstevel@tonic-gate break; 5877c478bd9Sstevel@tonic-gate 588*0a44ef6dSjacobs if (Exec_Table[i] == NULL) 5897c478bd9Sstevel@tonic-gate Shutdown = 2; 5907c478bd9Sstevel@tonic-gate } 591