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 */
21*0a44ef6dSjacobs
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
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate
31*0a44ef6dSjacobs #pragma ident "%Z%%M% %I% %E% SMI"
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate #include "stdarg.h"
347c478bd9Sstevel@tonic-gate #include "lpsched.h"
357c478bd9Sstevel@tonic-gate #include <syslog.h>
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate extern int isStartingForms;
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate typedef struct later {
407c478bd9Sstevel@tonic-gate struct later * next;
417c478bd9Sstevel@tonic-gate int event,
427c478bd9Sstevel@tonic-gate ticks;
437c478bd9Sstevel@tonic-gate union arg {
447c478bd9Sstevel@tonic-gate PSTATUS * printer;
457c478bd9Sstevel@tonic-gate RSTATUS * request;
467c478bd9Sstevel@tonic-gate FSTATUS * form;
477c478bd9Sstevel@tonic-gate } arg;
487c478bd9Sstevel@tonic-gate } LATER;
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate static LATER LaterHead = { 0 },
517c478bd9Sstevel@tonic-gate TempHead;
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate static void ev_interf(PSTATUS *);
547c478bd9Sstevel@tonic-gate static void ev_message(PSTATUS *);
557c478bd9Sstevel@tonic-gate static void ev_form_message(FSTATUS *);
567c478bd9Sstevel@tonic-gate static int ev_slowf(RSTATUS *);
577c478bd9Sstevel@tonic-gate static int ev_notify(RSTATUS *);
587c478bd9Sstevel@tonic-gate
59*0a44ef6dSjacobs static EXEC *find_exec_slot(EXEC **);
607c478bd9Sstevel@tonic-gate
_event_name(int event)617c478bd9Sstevel@tonic-gate static char *_event_name(int event)
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate static char *_names[] = {
647c478bd9Sstevel@tonic-gate "", "EV_SLOWF", "EV_INTERF", "EV_NOTIFY", "EV_LATER", "EV_ALARM",
65*0a44ef6dSjacobs "EV_MESSAGE", "EV_ENABLE", "EV_FORM_MESSAGE", NULL };
667c478bd9Sstevel@tonic-gate
67*0a44ef6dSjacobs if ((event < 0) || (event > EV_FORM_MESSAGE))
687c478bd9Sstevel@tonic-gate return ("BAD_EVENT");
697c478bd9Sstevel@tonic-gate else
707c478bd9Sstevel@tonic-gate return (_names[event]);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate /*
747c478bd9Sstevel@tonic-gate * schedule() - SCHEDULE BY EVENT
757c478bd9Sstevel@tonic-gate */
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate /*VARARGS1*/
787c478bd9Sstevel@tonic-gate void
schedule(int event,...)797c478bd9Sstevel@tonic-gate schedule(int event, ...)
807c478bd9Sstevel@tonic-gate {
817c478bd9Sstevel@tonic-gate va_list ap;
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate LATER * plprev;
847c478bd9Sstevel@tonic-gate LATER * pl;
857c478bd9Sstevel@tonic-gate LATER * plnext = 0;
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate register PSTATUS * pps;
887c478bd9Sstevel@tonic-gate register RSTATUS * prs;
897c478bd9Sstevel@tonic-gate register FSTATUS * pfs;
907c478bd9Sstevel@tonic-gate
91*0a44ef6dSjacobs int i;
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate * If we're in the process of shutting down, don't
947c478bd9Sstevel@tonic-gate * schedule anything.
957c478bd9Sstevel@tonic-gate */
967c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "schedule(%s)", _event_name(event));
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate if (Shutdown)
997c478bd9Sstevel@tonic-gate return;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate va_start (ap, event);
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate * If we're still in the process of starting up, don't start
1057c478bd9Sstevel@tonic-gate * anything! Schedule it for one tick later. While we're starting
1067c478bd9Sstevel@tonic-gate * ticks aren't counted, so the events won't be started.
1077c478bd9Sstevel@tonic-gate * HOWEVER, with a count of 1, a single EV_ALARM after we're
1087c478bd9Sstevel@tonic-gate * finished starting will be enough to clear all things scheduled
1097c478bd9Sstevel@tonic-gate * for later.
1107c478bd9Sstevel@tonic-gate */
1117c478bd9Sstevel@tonic-gate if (Starting) {
1127c478bd9Sstevel@tonic-gate switch (event) {
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate case EV_INTERF:
1157c478bd9Sstevel@tonic-gate case EV_ENABLE:
1167c478bd9Sstevel@tonic-gate pps = va_arg(ap, PSTATUS *);
1177c478bd9Sstevel@tonic-gate schedule (EV_LATER, 1, event, pps);
1187c478bd9Sstevel@tonic-gate goto Return;
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate case EV_SLOWF:
1217c478bd9Sstevel@tonic-gate case EV_NOTIFY:
1227c478bd9Sstevel@tonic-gate prs = va_arg(ap, RSTATUS *);
1237c478bd9Sstevel@tonic-gate schedule (EV_LATER, 1, event, prs);
1247c478bd9Sstevel@tonic-gate goto Return;
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate case EV_MESSAGE:
1277c478bd9Sstevel@tonic-gate pps = va_arg(ap, PSTATUS *);
1287c478bd9Sstevel@tonic-gate schedule (EV_LATER, 1, event, pps);
1297c478bd9Sstevel@tonic-gate goto Return;
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate case EV_FORM_MESSAGE:
1327c478bd9Sstevel@tonic-gate pfs = va_arg(ap, FSTATUS *);
1337c478bd9Sstevel@tonic-gate schedule (EV_LATER, 1, event, pfs);
1347c478bd9Sstevel@tonic-gate goto Return;
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate case EV_LATER:
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate * This is okay--in fact it may be us!
1397c478bd9Sstevel@tonic-gate */
1407c478bd9Sstevel@tonic-gate break;
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate case EV_ALARM:
1437c478bd9Sstevel@tonic-gate /*
1447c478bd9Sstevel@tonic-gate * The alarm will go off again, hold off for now.
1457c478bd9Sstevel@tonic-gate */
1467c478bd9Sstevel@tonic-gate goto Return;
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate * Schedule something:
1537c478bd9Sstevel@tonic-gate */
1547c478bd9Sstevel@tonic-gate switch (event) {
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate case EV_INTERF:
1577c478bd9Sstevel@tonic-gate if ((pps = va_arg(ap, PSTATUS *)) != NULL)
1587c478bd9Sstevel@tonic-gate ev_interf (pps);
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate else
161*0a44ef6dSjacobs for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
162*0a44ef6dSjacobs ev_interf (PStatus[i]);
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate break;
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate /*
1677c478bd9Sstevel@tonic-gate * The EV_ENABLE event is used to get a printer going again
1687c478bd9Sstevel@tonic-gate * after waiting for a fault to be cleared. We used to use
1697c478bd9Sstevel@tonic-gate * just the EV_INTERF event, but this wasn't enough: For
1707c478bd9Sstevel@tonic-gate * requests that can go on several different printers (e.g.
1717c478bd9Sstevel@tonic-gate * queued for class, queued for ``any''), a printer is
1727c478bd9Sstevel@tonic-gate * arbitrarily assigned. The EV_INTERF event just checks
1737c478bd9Sstevel@tonic-gate * assignments, not possibilities, so a printer with no
1747c478bd9Sstevel@tonic-gate * assigned requests but still eligible to handle one or
1757c478bd9Sstevel@tonic-gate * more requests would never automatically start up again after
1767c478bd9Sstevel@tonic-gate * a fault. The EV_ENABLE event calls "enable()" which eventually
1777c478bd9Sstevel@tonic-gate * gets around to invoking the EV_INTERF event. However, it first
1787c478bd9Sstevel@tonic-gate * calls "queue_attract()" to get an eligible request assigned
1797c478bd9Sstevel@tonic-gate * so that things proceed. This also makes sense from the
1807c478bd9Sstevel@tonic-gate * following standpoint: The documented method of getting a
1817c478bd9Sstevel@tonic-gate * printer going, while it is waiting for auto-retry, is to
1827c478bd9Sstevel@tonic-gate * manually issue the enable command!
1837c478bd9Sstevel@tonic-gate *
1847c478bd9Sstevel@tonic-gate * Note: "enable()" will destroy the current record of the fault,
1857c478bd9Sstevel@tonic-gate * so if the fault is still with us any new alert will not include
1867c478bd9Sstevel@tonic-gate * the history of each repeated fault. This is a plus and a minus,
1877c478bd9Sstevel@tonic-gate * usually a minus: While a repeated fault may occasionally show
1887c478bd9Sstevel@tonic-gate * a varied record, usually the same reason is given each time;
1897c478bd9Sstevel@tonic-gate * before switching to EV_ENABLE we typically saw a boring, long
1907c478bd9Sstevel@tonic-gate * list of identical reasons.
1917c478bd9Sstevel@tonic-gate */
1927c478bd9Sstevel@tonic-gate case EV_ENABLE:
1937c478bd9Sstevel@tonic-gate if ((pps = va_arg(ap, PSTATUS *)) != NULL)
1947c478bd9Sstevel@tonic-gate enable (pps);
1957c478bd9Sstevel@tonic-gate else
196*0a44ef6dSjacobs for (i = 0; PStatus != NULL && PStatus[i] != NULL; i++)
197*0a44ef6dSjacobs enable (PStatus[i]);
1987c478bd9Sstevel@tonic-gate break;
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate case EV_SLOWF:
2017c478bd9Sstevel@tonic-gate if ((prs = va_arg(ap, RSTATUS *)) != NULL)
2027c478bd9Sstevel@tonic-gate (void) ev_slowf (prs);
2037c478bd9Sstevel@tonic-gate else
2047c478bd9Sstevel@tonic-gate for (prs = Request_List; prs && ev_slowf(prs) != -1;
2057c478bd9Sstevel@tonic-gate prs = prs->next);
2067c478bd9Sstevel@tonic-gate break;
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate case EV_NOTIFY:
2097c478bd9Sstevel@tonic-gate if ((prs = va_arg(ap, RSTATUS *)) != NULL)
2107c478bd9Sstevel@tonic-gate (void) ev_notify (prs);
2117c478bd9Sstevel@tonic-gate else
2127c478bd9Sstevel@tonic-gate for (prs = Request_List; prs && ev_notify(prs) != -1;
2137c478bd9Sstevel@tonic-gate prs = prs->next);
2147c478bd9Sstevel@tonic-gate break;
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate case EV_MESSAGE:
2177c478bd9Sstevel@tonic-gate pps = va_arg(ap, PSTATUS *);
2187c478bd9Sstevel@tonic-gate ev_message(pps);
2197c478bd9Sstevel@tonic-gate break;
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate case EV_FORM_MESSAGE:
2227c478bd9Sstevel@tonic-gate pfs = va_arg(ap, FSTATUS *);
2237c478bd9Sstevel@tonic-gate ev_form_message(pfs);
2247c478bd9Sstevel@tonic-gate break;
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate case EV_LATER:
2277c478bd9Sstevel@tonic-gate pl = (LATER *)Malloc(sizeof (LATER));
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate if (!LaterHead.next)
2307c478bd9Sstevel@tonic-gate alarm (CLOCK_TICK);
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate pl->next = LaterHead.next;
2337c478bd9Sstevel@tonic-gate LaterHead.next = pl;
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate pl->ticks = va_arg(ap, int);
2367c478bd9Sstevel@tonic-gate pl->event = va_arg(ap, int);
2377c478bd9Sstevel@tonic-gate switch (pl->event) {
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate case EV_MESSAGE:
2407c478bd9Sstevel@tonic-gate case EV_INTERF:
2417c478bd9Sstevel@tonic-gate case EV_ENABLE:
2427c478bd9Sstevel@tonic-gate pl->arg.printer = va_arg(ap, PSTATUS *);
2437c478bd9Sstevel@tonic-gate if (pl->arg.printer)
2447c478bd9Sstevel@tonic-gate pl->arg.printer->status |= PS_LATER;
2457c478bd9Sstevel@tonic-gate break;
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate case EV_FORM_MESSAGE:
2487c478bd9Sstevel@tonic-gate pl->arg.form = va_arg(ap, FSTATUS *);
2497c478bd9Sstevel@tonic-gate break;
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate case EV_SLOWF:
2527c478bd9Sstevel@tonic-gate case EV_NOTIFY:
2537c478bd9Sstevel@tonic-gate pl->arg.request = va_arg(ap, RSTATUS *);
2547c478bd9Sstevel@tonic-gate break;
2557c478bd9Sstevel@tonic-gate
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate break;
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate case EV_ALARM:
2607c478bd9Sstevel@tonic-gate Sig_Alrm = 0;
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate /*
2637c478bd9Sstevel@tonic-gate * The act of scheduling some of the ``laters'' may
2647c478bd9Sstevel@tonic-gate * cause new ``laters'' to be added to the list.
2657c478bd9Sstevel@tonic-gate * To ease the handling of the linked list, we first
2667c478bd9Sstevel@tonic-gate * run through the list and move all events ready to
2677c478bd9Sstevel@tonic-gate * be scheduled to another list. Then we schedule the
2687c478bd9Sstevel@tonic-gate * events off the new list. This leaves the main ``later''
2697c478bd9Sstevel@tonic-gate * list ready for new events.
2707c478bd9Sstevel@tonic-gate */
2717c478bd9Sstevel@tonic-gate TempHead.next = 0;
2727c478bd9Sstevel@tonic-gate for (pl = (plprev = &LaterHead)->next; pl; pl = plnext) {
2737c478bd9Sstevel@tonic-gate plnext = pl->next;
2747c478bd9Sstevel@tonic-gate if (--pl->ticks)
2757c478bd9Sstevel@tonic-gate plprev = pl;
2767c478bd9Sstevel@tonic-gate else {
2777c478bd9Sstevel@tonic-gate plprev->next = plnext;
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate pl->next = TempHead.next;
2807c478bd9Sstevel@tonic-gate TempHead.next = pl;
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate for (pl = TempHead.next; pl; pl = plnext) {
2857c478bd9Sstevel@tonic-gate plnext = pl->next;
2867c478bd9Sstevel@tonic-gate switch (pl->event) {
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate case EV_MESSAGE:
2897c478bd9Sstevel@tonic-gate case EV_INTERF:
2907c478bd9Sstevel@tonic-gate case EV_ENABLE:
2917c478bd9Sstevel@tonic-gate pl->arg.printer->status &= ~PS_LATER;
2927c478bd9Sstevel@tonic-gate schedule (pl->event, pl->arg.printer);
2937c478bd9Sstevel@tonic-gate break;
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate case EV_FORM_MESSAGE:
2967c478bd9Sstevel@tonic-gate schedule (pl->event, pl->arg.form);
2977c478bd9Sstevel@tonic-gate break;
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate case EV_SLOWF:
3007c478bd9Sstevel@tonic-gate case EV_NOTIFY:
3017c478bd9Sstevel@tonic-gate schedule (pl->event, pl->arg.request);
3027c478bd9Sstevel@tonic-gate break;
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate Free ((char *)pl);
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate if (LaterHead.next)
3097c478bd9Sstevel@tonic-gate alarm (CLOCK_TICK);
3107c478bd9Sstevel@tonic-gate break;
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate Return: va_end (ap);
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate return;
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate
3197c478bd9Sstevel@tonic-gate /*
3207c478bd9Sstevel@tonic-gate * maybe_schedule() - MAYBE SCHEDULE SOMETHING FOR A REQUEST
3217c478bd9Sstevel@tonic-gate */
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate void
maybe_schedule(RSTATUS * prs)3247c478bd9Sstevel@tonic-gate maybe_schedule(RSTATUS *prs)
3257c478bd9Sstevel@tonic-gate {
3267c478bd9Sstevel@tonic-gate /*
3277c478bd9Sstevel@tonic-gate * Use this routine if a request has been changed by some
3287c478bd9Sstevel@tonic-gate * means so that it is ready for filtering or printing,
3297c478bd9Sstevel@tonic-gate * but a previous filtering or printing process for this
3307c478bd9Sstevel@tonic-gate * request MAY NOT have finished yet. If a process is still
3317c478bd9Sstevel@tonic-gate * running, then the cleanup of that process will cause
3327c478bd9Sstevel@tonic-gate * "schedule()" to be called. Calling "schedule()" regardless
3337c478bd9Sstevel@tonic-gate * might make another request slip ahead of this request.
3347c478bd9Sstevel@tonic-gate */
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate /*
3377c478bd9Sstevel@tonic-gate * "schedule()" will refuse if this request is filtering.
3387c478bd9Sstevel@tonic-gate * It will also refuse if the request ``was'' filtering
3397c478bd9Sstevel@tonic-gate * but the filter was terminated in "validate_request()",
3407c478bd9Sstevel@tonic-gate * because we can not have heard from the filter process
3417c478bd9Sstevel@tonic-gate * yet. Also, when called with a particular request,
3427c478bd9Sstevel@tonic-gate * "schedule()" won't slip another request ahead.
3437c478bd9Sstevel@tonic-gate */
3447c478bd9Sstevel@tonic-gate if (NEEDS_FILTERING(prs))
3457c478bd9Sstevel@tonic-gate schedule (EV_SLOWF, prs);
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate else if (!(prs->request->outcome & RS_STOPPED))
3487c478bd9Sstevel@tonic-gate schedule (EV_INTERF, prs->printer);
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate return;
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate static void
ev_message(PSTATUS * pps)3547c478bd9Sstevel@tonic-gate ev_message(PSTATUS *pps)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate register RSTATUS *prs;
3577c478bd9Sstevel@tonic-gate char toSelf;
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "ev_message(%s)",
3607c478bd9Sstevel@tonic-gate (pps && pps->request && pps->request->req_file ?
3617c478bd9Sstevel@tonic-gate pps->request->req_file : "NULL"));
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate toSelf = 0;
364*0a44ef6dSjacobs for (prs = Request_List; prs != NULL; prs = prs->next)
365*0a44ef6dSjacobs if (prs->printer == pps) {
3667c478bd9Sstevel@tonic-gate note("prs (%d) pps (%d)\n", prs, pps);
3677c478bd9Sstevel@tonic-gate if (!toSelf) {
3687c478bd9Sstevel@tonic-gate toSelf = 1;
3697c478bd9Sstevel@tonic-gate exec(EX_FAULT_MESSAGE, pps, prs);
3707c478bd9Sstevel@tonic-gate }
371*0a44ef6dSjacobs }
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate static void
ev_form_message_body(FSTATUS * pfs,RSTATUS * prs,char * toSelf,char *** sysList)3757c478bd9Sstevel@tonic-gate ev_form_message_body(FSTATUS *pfs, RSTATUS *prs, char *toSelf, char ***sysList)
3767c478bd9Sstevel@tonic-gate {
377*0a44ef6dSjacobs syslog(LOG_DEBUG, "ev_form_message_body(%s, %d, 0x%x)",
3787c478bd9Sstevel@tonic-gate (pfs && pfs->form && pfs->form->name ? pfs->form->name : "NULL"),
379*0a44ef6dSjacobs (toSelf ? *toSelf : 0),
3807c478bd9Sstevel@tonic-gate sysList);
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate if (!*toSelf) {
3837c478bd9Sstevel@tonic-gate *toSelf = 1;
3847c478bd9Sstevel@tonic-gate exec(EX_FORM_MESSAGE, pfs);
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate }
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate static void
ev_form_message(FSTATUS * pfs)3897c478bd9Sstevel@tonic-gate ev_form_message(FSTATUS *pfs)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate register RSTATUS *prs;
3927c478bd9Sstevel@tonic-gate char **sysList;
3937c478bd9Sstevel@tonic-gate char toSelf;
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "ev_form_message(%s)",
3967c478bd9Sstevel@tonic-gate (pfs && pfs->form && pfs->form->name ?
3977c478bd9Sstevel@tonic-gate pfs->form->name : "NULL"));
3987c478bd9Sstevel@tonic-gate
3997c478bd9Sstevel@tonic-gate toSelf = 0;
4007c478bd9Sstevel@tonic-gate sysList = NULL;
401*0a44ef6dSjacobs
402*0a44ef6dSjacobs for (prs = Request_List; prs != NULL; prs = prs->next)
403*0a44ef6dSjacobs if (prs->form == pfs)
4047c478bd9Sstevel@tonic-gate ev_form_message_body(pfs, prs, &toSelf, &sysList);
405*0a44ef6dSjacobs
4067c478bd9Sstevel@tonic-gate if (NewRequest && (NewRequest->form == pfs))
4077c478bd9Sstevel@tonic-gate ev_form_message_body(pfs, NewRequest, &toSelf, &sysList);
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate freelist(sysList);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate /*
4137c478bd9Sstevel@tonic-gate * ev_interf() - CHECK AND EXEC INTERFACE PROGRAM
4147c478bd9Sstevel@tonic-gate */
4157c478bd9Sstevel@tonic-gate
4167c478bd9Sstevel@tonic-gate /*
4177c478bd9Sstevel@tonic-gate * Macro to check if the request needs a print wheel or character set (S)
4187c478bd9Sstevel@tonic-gate * and the printer (P) has it mounted or can select it. Since the request
4197c478bd9Sstevel@tonic-gate * has already been approved for the printer, we don't have to check the
4207c478bd9Sstevel@tonic-gate * character set, just the mount. If the printer has selectable character
4217c478bd9Sstevel@tonic-gate * sets, there's nothing to check so the request is ready to print.
4227c478bd9Sstevel@tonic-gate */
4237c478bd9Sstevel@tonic-gate #define MATCH(PRS, PPS) (\
4247c478bd9Sstevel@tonic-gate !(PPS)->printer->daisy || \
4257c478bd9Sstevel@tonic-gate !(PRS)->pwheel_name || \
4267c478bd9Sstevel@tonic-gate !((PRS)->status & RSS_PWMAND) || \
4277c478bd9Sstevel@tonic-gate STREQU((PRS)->pwheel_name, NAME_ANY) || \
4287c478bd9Sstevel@tonic-gate ((PPS)->pwheel_name && \
4297c478bd9Sstevel@tonic-gate STREQU((PPS)->pwheel_name, (PRS)->pwheel_name)))
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate static void
ev_interf(PSTATUS * pps)4337c478bd9Sstevel@tonic-gate ev_interf(PSTATUS *pps)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate register RSTATUS *prs;
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "ev_interf(%s)",
4387c478bd9Sstevel@tonic-gate (pps && pps->request && pps->request->req_file ?
4397c478bd9Sstevel@tonic-gate pps->request->req_file : "NULL"));
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate /*
4437c478bd9Sstevel@tonic-gate * If the printer isn't tied up doing something
4447c478bd9Sstevel@tonic-gate * else, and isn't disabled, see if there is a request
4457c478bd9Sstevel@tonic-gate * waiting to print on it. Note: We don't include
4467c478bd9Sstevel@tonic-gate * PS_FAULTED here, because simply having a printer
4477c478bd9Sstevel@tonic-gate * fault (without also being disabled) isn't sufficient
4487c478bd9Sstevel@tonic-gate * to keep us from trying again. (In fact, we HAVE TO
4497c478bd9Sstevel@tonic-gate * try again, to see if the fault has gone away.)
4507c478bd9Sstevel@tonic-gate *
4517c478bd9Sstevel@tonic-gate * NOTE: If the printer is faulted but the filter controlling
4527c478bd9Sstevel@tonic-gate * the printer is waiting for the fault to clear, a
4537c478bd9Sstevel@tonic-gate * request will still be attached to the printer, as
4547c478bd9Sstevel@tonic-gate * evidenced by "pps->request", so we won't try to
4557c478bd9Sstevel@tonic-gate * schedule another request!
4567c478bd9Sstevel@tonic-gate */
4577c478bd9Sstevel@tonic-gate if (pps->request || pps->status & (PS_DISABLED|PS_LATER|PS_BUSY))
4587c478bd9Sstevel@tonic-gate return;
4597c478bd9Sstevel@tonic-gate
460*0a44ef6dSjacobs for (prs = Request_List; prs != NULL; prs = prs->next) {
461*0a44ef6dSjacobs if ((prs->printer == pps) && (qchk_waiting(prs)) &&
462*0a44ef6dSjacobs isFormUsableOnPrinter(pps, prs->form) && MATCH(prs, pps)) {
4637c478bd9Sstevel@tonic-gate /*
4647c478bd9Sstevel@tonic-gate * Just because the printer isn't busy and the
4657c478bd9Sstevel@tonic-gate * request is assigned to this printer, don't get the
4667c478bd9Sstevel@tonic-gate * idea that the request can't be printing (RS_ACTIVE),
4677c478bd9Sstevel@tonic-gate * because another printer may still have the request
4687c478bd9Sstevel@tonic-gate * attached but we've not yet heard from the child
4697c478bd9Sstevel@tonic-gate * process controlling that printer.
470*0a44ef6dSjacobs *
4717c478bd9Sstevel@tonic-gate * We have the waiting request, we have
4727c478bd9Sstevel@tonic-gate * the ready (local) printer. If the exec fails
4737c478bd9Sstevel@tonic-gate * because the fork failed, schedule a
4747c478bd9Sstevel@tonic-gate * try later and claim we succeeded. The
4757c478bd9Sstevel@tonic-gate * later attempt will sort things out,
4767c478bd9Sstevel@tonic-gate * e.g. will re-schedule if the fork fails
4777c478bd9Sstevel@tonic-gate * again.
4787c478bd9Sstevel@tonic-gate */
4797c478bd9Sstevel@tonic-gate pps->request = prs;
4807c478bd9Sstevel@tonic-gate if (exec(EX_INTERF, pps) == 0) {
4817c478bd9Sstevel@tonic-gate pps->status |= PS_BUSY;
4827c478bd9Sstevel@tonic-gate return;
4837c478bd9Sstevel@tonic-gate }
4847c478bd9Sstevel@tonic-gate pps->request = 0;
4857c478bd9Sstevel@tonic-gate if (errno == EAGAIN) {
4867c478bd9Sstevel@tonic-gate load_str (&pps->dis_reason, CUZ_NOFORK);
4877c478bd9Sstevel@tonic-gate schedule (EV_LATER, WHEN_FORK, EV_ENABLE, pps);
4887c478bd9Sstevel@tonic-gate return;
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate }
491*0a44ef6dSjacobs }
4927c478bd9Sstevel@tonic-gate
4937c478bd9Sstevel@tonic-gate return;
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate /*
4977c478bd9Sstevel@tonic-gate * ev_slowf() - CHECK AND EXEC SLOW FILTER
4987c478bd9Sstevel@tonic-gate */
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate static int
ev_slowf(RSTATUS * prs)5017c478bd9Sstevel@tonic-gate ev_slowf(RSTATUS *prs)
5027c478bd9Sstevel@tonic-gate {
5037c478bd9Sstevel@tonic-gate register EXEC *ep;
5047c478bd9Sstevel@tonic-gate
5057c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "ev_slowf(%s)",
5067c478bd9Sstevel@tonic-gate (prs && prs->req_file ? prs->req_file : "NULL"));
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate /*
5097c478bd9Sstevel@tonic-gate * Return -1 if no more can be executed (no more exec slots)
5107c478bd9Sstevel@tonic-gate * or if it's unwise to execute any more (fork failed).
5117c478bd9Sstevel@tonic-gate */
5127c478bd9Sstevel@tonic-gate
513*0a44ef6dSjacobs if (!(ep = find_exec_slot(Exec_Slow))) {
514*0a44ef6dSjacobs syslog(LOG_DEBUG, "ev_slowf(%s): no slot",
515*0a44ef6dSjacobs (prs && prs->req_file ? prs->req_file : "NULL"));
5167c478bd9Sstevel@tonic-gate return (-1);
517*0a44ef6dSjacobs }
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate if (!(prs->request->outcome & (RS_DONE|RS_HELD|RS_ACTIVE)) &&
5207c478bd9Sstevel@tonic-gate NEEDS_FILTERING(prs)) {
5217c478bd9Sstevel@tonic-gate (prs->exec = ep)->ex.request = prs;
5227c478bd9Sstevel@tonic-gate if (exec(EX_SLOWF, prs) != 0) {
5237c478bd9Sstevel@tonic-gate ep->ex.request = 0;
5247c478bd9Sstevel@tonic-gate prs->exec = 0;
5257c478bd9Sstevel@tonic-gate if (errno == EAGAIN) {
5267c478bd9Sstevel@tonic-gate schedule (EV_LATER, WHEN_FORK, EV_SLOWF, prs);
5277c478bd9Sstevel@tonic-gate return (-1);
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate }
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate return (0);
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate /*
5357c478bd9Sstevel@tonic-gate * ev_notify() - CHECK AND EXEC NOTIFICATION
5367c478bd9Sstevel@tonic-gate */
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate static int
ev_notify(RSTATUS * prs)5397c478bd9Sstevel@tonic-gate ev_notify(RSTATUS *prs)
5407c478bd9Sstevel@tonic-gate {
5417c478bd9Sstevel@tonic-gate register EXEC *ep;
5427c478bd9Sstevel@tonic-gate
5437c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "ev_notify(%s)",
5447c478bd9Sstevel@tonic-gate (prs && prs->req_file ? prs->req_file : "NULL"));
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate /*
5477c478bd9Sstevel@tonic-gate * Return -1 if no more can be executed (no more exec slots)
5487c478bd9Sstevel@tonic-gate * or if it's unwise to execute any more (fork failed, already
5497c478bd9Sstevel@tonic-gate * sent one to remote side).
5507c478bd9Sstevel@tonic-gate */
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate /*
5537c478bd9Sstevel@tonic-gate * If the job came from a remote machine, we forward the
5547c478bd9Sstevel@tonic-gate * outcome of the request to the network manager for sending
5557c478bd9Sstevel@tonic-gate * to the remote side.
5567c478bd9Sstevel@tonic-gate */
5577c478bd9Sstevel@tonic-gate if (prs->request->actions & ACT_NOTIFY) {
5587c478bd9Sstevel@tonic-gate if (prs->request->outcome & RS_NOTIFY) {
5597c478bd9Sstevel@tonic-gate prs->request->actions &= ~ACT_NOTIFY;
5607c478bd9Sstevel@tonic-gate return (0); /* but try another request */
5617c478bd9Sstevel@tonic-gate }
5627c478bd9Sstevel@tonic-gate /*
5637c478bd9Sstevel@tonic-gate * If the job didn't come from a remote system,
5647c478bd9Sstevel@tonic-gate * we'll try to start a process to send the notification
5657c478bd9Sstevel@tonic-gate * to the user. But we only allow so many notifications
5667c478bd9Sstevel@tonic-gate * to run at the same time, so we may not be able to
5677c478bd9Sstevel@tonic-gate * do it.
5687c478bd9Sstevel@tonic-gate */
569*0a44ef6dSjacobs } else if (!(ep = find_exec_slot(Exec_Notify)))
5707c478bd9Sstevel@tonic-gate return (-1);
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate else if (prs->request->outcome & RS_NOTIFY &&
5737c478bd9Sstevel@tonic-gate !(prs->request->outcome & RS_NOTIFYING)) {
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate (prs->exec = ep)->ex.request = prs;
5767c478bd9Sstevel@tonic-gate if (exec(EX_NOTIFY, prs) != 0) {
5777c478bd9Sstevel@tonic-gate ep->ex.request = 0;
5787c478bd9Sstevel@tonic-gate prs->exec = 0;
5797c478bd9Sstevel@tonic-gate if (errno == EAGAIN) {
5807c478bd9Sstevel@tonic-gate schedule (EV_LATER, WHEN_FORK, EV_NOTIFY, prs);
5817c478bd9Sstevel@tonic-gate return (-1);
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate return (0);
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate /*
5907c478bd9Sstevel@tonic-gate * find_exec_slot() - FIND AVAILABLE EXEC SLOT
5917c478bd9Sstevel@tonic-gate */
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate static EXEC *
find_exec_slot(EXEC ** exec_table)594*0a44ef6dSjacobs find_exec_slot(EXEC **exec_table)
5957c478bd9Sstevel@tonic-gate {
596*0a44ef6dSjacobs int i;
5977c478bd9Sstevel@tonic-gate
598*0a44ef6dSjacobs for (i = 0; exec_table[i] != NULL; i++)
599*0a44ef6dSjacobs if (exec_table[i]->pid == 0)
600*0a44ef6dSjacobs return (exec_table[i]);
6017c478bd9Sstevel@tonic-gate
602*0a44ef6dSjacobs syslog(LOG_DEBUG, "find_exec_slot(0x%8.8x): after %d, no slots",
603*0a44ef6dSjacobs exec_table, i);
6047c478bd9Sstevel@tonic-gate return (0);
6057c478bd9Sstevel@tonic-gate }
606