/*
- * "$Id$"
+ * "$Id: subscriptions.c 7824 2008-08-01 21:11:55Z mike $"
*
* Subscription routines for the Common UNIX Printing System (CUPS) scheduler.
*
- * Copyright 1997-2006 by Easy Software Products, all rights reserved.
+ * Copyright 2007-2009 by Apple Inc.
+ * Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
- * property of Easy Software Products and are protected by Federal
- * copyright law. Distribution and use rights are outlined in the file
- * "LICENSE.txt" which should have been included with this file. If this
- * file is missing or damaged please contact Easy Software Products
- * at:
- *
- * Attn: CUPS Licensing Information
- * Easy Software Products
- * 44141 Airport View Drive, Suite 204
- * Hollywood, Maryland 20636 USA
- *
- * Voice: (301) 373-9600
- * EMail: cups-info@cups.org
- * WWW: http://www.cups.org
+ * property of Apple Inc. and are protected by Federal copyright
+ * law. Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file. If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
*
* Contents:
*
* cupsdLoadAllSubscriptions() - Load all subscriptions from the .conf file.
* cupsdSaveAllSubscriptions() - Save all subscriptions to the .conf file.
* cupsdStopAllNotifiers() - Stop all notifier processes.
- * cupsdUpdateNotifierStatus() - Read messages from notifiers.
* cupsd_compare_subscriptions() - Compare two subscriptions.
* cupsd_delete_event() - Delete a single event...
* cupsd_send_dbus() - Send a DBUS notification...
* cupsd_send_notification() - Send a notification for the specified
* event.
* cupsd_start_notifier() - Start a notifier subprocess...
+ * cupsd_update_notifier() - Read messages from notifiers.
*/
/*
#include "cupsd.h"
#ifdef HAVE_DBUS
# include <dbus/dbus.h>
+# ifdef HAVE_DBUS_MESSAGE_ITER_INIT_APPEND
+# define dbus_message_append_iter_init dbus_message_iter_init_append
+# define dbus_message_iter_append_string(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &(v))
+# define dbus_message_iter_append_uint32(i,v) dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &(v))
+# endif /* HAVE_DBUS_MESSAGE_ITER_INIT_APPEND */
#endif /* HAVE_DBUS */
static void cupsd_send_notification(cupsd_subscription_t *sub,
cupsd_event_t *event);
static void cupsd_start_notifier(cupsd_subscription_t *sub);
+static void cupsd_update_notifier(void);
/*
cupsd_subscription_t *sub; /* Current subscription */
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsdAddEvent(event=%s, dest=%p(%s), job=%p(%d), text=\"%s\", ...)",
+ cupsdEventName(event), dest, dest ? dest->name : "",
+ job, job ? job->id : 0, text);
+
/*
* Keep track of events with any OS-supplied notification mechanisms...
*/
"job-stopped");
break;
- case IPP_JOB_CANCELLED :
+ case IPP_JOB_CANCELED :
ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION,
IPP_TAG_KEYWORD, "job-state-reasons", NULL,
"job-canceled-by-user");
ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
"job-impressions-completed",
job->sheets ? job->sheets->values[0].integer : 0);
+ }
- /*
- * Send the notification for this subscription...
- */
+ /*
+ * Send the notification for this subscription...
+ */
- cupsd_send_notification(sub, temp);
- }
+ cupsd_send_notification(sub, temp);
}
}
if (temp)
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
else
cupsdLogMessage(CUPSD_LOG_DEBUG, "Discarding unused %s event...",
cupsdEventName(event));
"cupsdAddSubscription(mask=%x, dest=%p(%s), job=%p(%d), "
"uri=\"%s\")",
mask, dest, dest ? dest->name : "", job, job ? job->id : 0,
- uri);
+ uri ? uri : "(null)");
if (!Subscriptions)
Subscriptions = cupsArrayNew((cups_array_func_t)cupsd_compare_subscriptions,
* Limit the number of subscriptions...
*/
- if (cupsArrayCount(Subscriptions) >= MaxSubscriptions)
+ if (MaxSubscriptions > 0 && cupsArrayCount(Subscriptions) >= MaxSubscriptions)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "cupsdAddSubscription: Reached MaxSubscriptions %d "
+ "(count=%d)", MaxSubscriptions,
+ cupsArrayCount(Subscriptions));
return (NULL);
+ }
+
+ if (MaxSubscriptionsPerJob > 0 && job)
+ {
+ int count; /* Number of job subscriptions */
+
+ for (temp = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions),
+ count = 0;
+ temp;
+ temp = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ if (temp->job == job)
+ count ++;
+
+ if (count >= MaxSubscriptionsPerJob)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "cupsdAddSubscription: Reached MaxSubscriptionsPerJob %d "
+ "for job #%d (count=%d)", MaxSubscriptionsPerJob,
+ job->id, count);
+ return (NULL);
+ }
+ }
+
+ if (MaxSubscriptionsPerPrinter > 0 && dest)
+ {
+ int count; /* Number of printer subscriptions */
+
+ for (temp = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions),
+ count = 0;
+ temp;
+ temp = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ if (temp->dest == dest)
+ count ++;
+
+ if (count >= MaxSubscriptionsPerPrinter)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "cupsdAddSubscription: Reached "
+ "MaxSubscriptionsPerPrinter %d for %s (count=%d)",
+ MaxSubscriptionsPerPrinter, dest->name, count);
+ return (NULL);
+ }
+ }
/*
* Allocate memory for this subscription...
cupsArrayAdd(Subscriptions, temp);
+ /*
+ * For RSS subscriptions, run the notifier immediately...
+ */
+
+ if (uri && !strncmp(uri, "rss:", 4))
+ cupsd_start_notifier(temp);
+
return (temp);
}
*/
if (update)
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
}
case CUPSD_EVENT_PRINTER_MODIFIED :
return ("printer-modified");
+ case CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED :
+ return ("printer-queue-order-changed");
+
+ case CUPSD_EVENT_PRINTER_STATE :
case CUPSD_EVENT_PRINTER_STATE_CHANGED :
return ("printer-state-changed");
+ case CUPSD_EVENT_PRINTER_CONFIG :
case CUPSD_EVENT_PRINTER_CONFIG_CHANGED :
return ("printer-config-changed");
return ("job-progress");
case CUPSD_EVENT_JOB_STATE :
- return ("job-state");
-
case CUPSD_EVENT_JOB_STATE_CHANGED :
return ("job-state-changed");
return (CUPSD_EVENT_PRINTER_DELETED);
else if (!strcmp(name, "printer-modified"))
return (CUPSD_EVENT_PRINTER_MODIFIED);
+ else if (!strcmp(name, "printer-queue-order-changed"))
+ return (CUPSD_EVENT_PRINTER_QUEUE_ORDER_CHANGED);
else if (!strcmp(name, "printer-state-changed"))
return (CUPSD_EVENT_PRINTER_STATE_CHANGED);
else if (!strcmp(name, "printer-config-changed"))
return (CUPSD_EVENT_PRINTER_CONFIG_CHANGED);
else if (!strcmp(name, "printer-changed"))
return (CUPSD_EVENT_PRINTER_CHANGED);
- else if (!strcmp(name, "job-state"))
- return (CUPSD_EVENT_JOB_STATE);
else if (!strcmp(name, "job-created"))
return (CUPSD_EVENT_JOB_CREATED);
else if (!strcmp(name, "job-completed"))
}
if (update)
- cupsdSaveAllSubscriptions();
+ cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
}
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "</Subscription>"))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
if (delete_sub)
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
}
else if (!strcasecmp(line, "Events"))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
while (*value)
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unknown event name \'%s\' on line %d of subscriptions.conf.",
value, linenum);
- return;
+ break;
}
value = valueptr;
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "Recipient"))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "JobId"))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "PrinterName"))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "UserData"))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "LeaseDuration"))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "Interval"))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "ExpirationTime"))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else if (!strcasecmp(line, "NextEventId"))
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else
if (NotifierPipes[0] >= 0)
{
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdStopAllNotifiers: Removing fd %d from InputSet...",
- NotifierPipes[0]);
- FD_CLR(NotifierPipes[0], InputSet);
+ cupsdRemoveSelect(NotifierPipes[0]);
cupsdStatBufDelete(NotifierStatusBuffer);
}
-/*
- * 'cupsdUpdateNotifierStatus()' - Read messages from notifiers.
- */
-
-void
-cupsdUpdateNotifierStatus(void)
-{
- char *ptr, /* Pointer to end of line in buffer */
- message[1024]; /* Pointer to message text */
- int loglevel; /* Log level for message */
-
-
- while ((ptr = cupsdStatBufUpdate(NotifierStatusBuffer, &loglevel,
- message, sizeof(message))) != NULL)
- if (!strchr(NotifierStatusBuffer->buffer, '\n'))
- break;
-}
-
-
/*
* 'cupsd_compare_subscriptions()' - Compare two subscriptions.
*/
message = dbus_message_new_signal("/com/redhat/PrinterSpooler",
"com.redhat.PrinterSpooler", what);
- dbus_message_iter_init_append(message, &iter);
+ dbus_message_append_iter_init(message, &iter);
if (dest)
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &(dest->name));
+ dbus_message_iter_append_string(&iter, dest->name);
if (job)
{
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &(job->id));
- dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &(job->username));
+ dbus_message_iter_append_uint32(&iter, job->id);
+ dbus_message_iter_append_string(&iter, job->username);
}
dbus_connection_send(con, message, NULL);
ipp_state_t state; /* IPP event state */
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "cupsd_send_notification(sub=%p(%d), event=%p(%s))\n",
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "cupsd_send_notification(sub=%p(%d), event=%p(%s))",
sub, sub->id, event, cupsdEventName(event->event));
/*
if (sub->recipient)
{
- if (sub->pipe < 0)
- cupsd_start_notifier(sub);
+ for (;;)
+ {
+ if (sub->pipe < 0)
+ cupsd_start_notifier(sub);
- cupsdLogMessage(CUPSD_LOG_DEBUG, "sub->pipe=%d", sub->pipe);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "sub->pipe=%d", sub->pipe);
+
+ if (sub->pipe < 0)
+ break;
- if (sub->pipe >= 0)
- {
event->attrs->state = IPP_IDLE;
while ((state = ippWriteFile(sub->pipe, event->attrs)) != IPP_DATA)
break;
if (state == IPP_ERROR)
+ {
+ if (errno == EPIPE)
+ {
+ /*
+ * Notifier died, try restarting it...
+ */
+
+ cupsdLogMessage(CUPSD_LOG_WARN,
+ "Notifier for subscription %d (%s) went away, "
+ "retrying!",
+ sub->id, sub->recipient);
+ cupsdEndProcess(sub->pid, 0);
+
+ close(sub->pipe);
+ sub->pipe = -1;
+ continue;
+ }
+
cupsdLogMessage(CUPSD_LOG_ERROR,
"Unable to send event for subscription %d (%s)!",
sub->id, sub->recipient);
+ }
+
+ /*
+ * If we get this far, break out of the loop...
+ */
+
+ break;
}
}
{
int pid; /* Notifier process ID */
int fds[2]; /* Pipe file descriptors */
- int envc; /* Number of environment variables */
char *argv[4], /* Command-line arguments */
*envp[MAX_ENV], /* Environment variables */
user_data[128], /* Base-64 encoded user data */
* Setup the environment...
*/
- envc = cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
+ cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0])));
/*
* Create pipes as needed...
NotifierStatusBuffer = cupsdStatBufNew(NotifierPipes[0], "[Notifier]");
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "start_notifier: Adding fd %d to InputSet...",
- NotifierPipes[0]);
-
- FD_SET(NotifierPipes[0], InputSet);
+ cupsdAddSelect(NotifierPipes[0], (cupsd_selfunc_t)cupsd_update_notifier,
+ NULL, NULL);
}
if (cupsdOpenPipe(fds))
*/
if (cupsdStartProcess(command, argv, envp, fds[0], -1, NotifierPipes[1],
- -1, 0, &pid) < 0)
+ -1, -1, 0, DefaultProfile, 0, &pid) < 0)
{
/*
* Error - can't fork!
/*
- * End of "$Id$".
+ * 'cupsd_update_notifier()' - Read messages from notifiers.
+ */
+
+void
+cupsd_update_notifier(void)
+{
+ char message[1024]; /* Pointer to message text */
+ int loglevel; /* Log level for message */
+
+
+ while (cupsdStatBufUpdate(NotifierStatusBuffer, &loglevel,
+ message, sizeof(message)))
+ {
+ if (loglevel == CUPSD_LOG_INFO)
+ cupsdLogMessage(CUPSD_LOG_INFO, "%s", message);
+
+ if (!strchr(NotifierStatusBuffer->buffer, '\n'))
+ break;
+ }
+}
+
+
+/*
+ * End of "$Id: subscriptions.c 7824 2008-08-01 21:11:55Z mike $".
*/