/*
- * "$Id: subscriptions.c 6376 2007-03-21 06:39:10Z mike $"
+ * "$Id$"
*
- * Subscription routines for the Common UNIX Printing System (CUPS) scheduler.
+ * Subscription routines for the CUPS scheduler.
*
+ * Copyright 2007-2011 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:
*
temp->time = time(NULL);
temp->attrs = ippNew();
temp->job = job;
- temp->dest = dest;
+
+ if (dest)
+ temp->dest = dest;
+ else if (job)
+ temp->dest = dest = cupsdFindPrinter(job->dest);
/*
* Add common event notification attributes...
"notify-charset", NULL, "utf-8");
ippAddString(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_LANGUAGE,
- "notify-natural-langugage", NULL, "en-US");
+ "notify-natural-language", NULL, "en-US");
ippAddInteger(temp->attrs, IPP_TAG_EVENT_NOTIFICATION, IPP_TAG_INTEGER,
"notify-subscription-id", sub->id);
}
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);
}
cupsd_subscription_t *sub, /* I - Subscription object */
int update) /* I - 1 = update subscriptions.conf */
{
- int i; /* Looping var */
-
-
/*
* Close the pipe to the notifier as needed...
*/
cupsdClearString(&(sub->owner));
cupsdClearString(&(sub->recipient));
- if (sub->events)
- {
- for (i = 0; i < sub->num_events; i ++)
- cupsd_delete_event(sub->events[i]);
-
- free(sub->events);
- }
+ cupsArrayDelete(sub->events);
free(sub);
*/
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);
}
*/
snprintf(line, sizeof(line), "%s/subscriptions.conf", ServerRoot);
- if ((fp = cupsFileOpen(line, "r")) == NULL)
- {
- if (errno != ENOENT)
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "LoadAllSubscriptions: Unable to open %s - %s", line,
- strerror(errno));
+ if ((fp = cupsdOpenConfFile(line)) == NULL)
return;
- }
/*
* Read all of the lines from the file...
while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
{
- if (!strcasecmp(line, "NextSubscriptionId") && value)
+ if (!_cups_strcasecmp(line, "NextSubscriptionId") && value)
{
/*
* NextSubscriptionId NNN
if (i >= NextSubscriptionId && i > 0)
NextSubscriptionId = i;
}
- else if (!strcasecmp(line, "<Subscription"))
+ else if (!_cups_strcasecmp(line, "<Subscription"))
{
/*
* <Subscription #>
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
- else if (!strcasecmp(line, "</Subscription>"))
+ else if (!_cups_strcasecmp(line, "</Subscription>"))
{
if (!sub)
{
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"))
+ else if (!_cups_strcasecmp(line, "Events"))
{
/*
* Events name
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;
}
}
- else if (!strcasecmp(line, "Owner"))
+ else if (!_cups_strcasecmp(line, "Owner"))
{
/*
* Owner
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
- else if (!strcasecmp(line, "Recipient"))
+ else if (!_cups_strcasecmp(line, "Recipient"))
{
/*
* Recipient uri
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
- else if (!strcasecmp(line, "JobId"))
+ else if (!_cups_strcasecmp(line, "JobId"))
{
/*
* JobId #
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
- else if (!strcasecmp(line, "PrinterName"))
+ else if (!_cups_strcasecmp(line, "PrinterName"))
{
/*
* PrinterName name
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
- else if (!strcasecmp(line, "UserData"))
+ else if (!_cups_strcasecmp(line, "UserData"))
{
/*
* UserData encoded-string
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
- else if (!strcasecmp(line, "LeaseDuration"))
+ else if (!_cups_strcasecmp(line, "LeaseDuration"))
{
/*
* LeaseDuration #
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
- else if (!strcasecmp(line, "Interval"))
+ else if (!_cups_strcasecmp(line, "Interval"))
{
/*
* Interval #
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
- else if (!strcasecmp(line, "ExpirationTime"))
+ else if (!_cups_strcasecmp(line, "ExpirationTime"))
{
/*
* ExpirationTime #
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
- else if (!strcasecmp(line, "NextEventId"))
+ else if (!_cups_strcasecmp(line, "NextEventId"))
{
/*
* NextEventId #
cupsdLogMessage(CUPSD_LOG_ERROR,
"Syntax error on line %d of subscriptions.conf.",
linenum);
- return;
+ break;
}
}
else
{
int i; /* Looping var */
cups_file_t *fp; /* subscriptions.conf file */
- char temp[1024]; /* Temporary string */
- char backup[1024]; /* subscriptions.conf.O file */
+ char filename[1024], /* subscriptions.conf filename */
+ temp[1024]; /* Temporary string */
cupsd_subscription_t *sub; /* Current subscription */
time_t curtime; /* Current time */
struct tm *curdate; /* Current date */
* Create the subscriptions.conf file...
*/
- snprintf(temp, sizeof(temp), "%s/subscriptions.conf", ServerRoot);
- snprintf(backup, sizeof(backup), "%s/subscriptions.conf.O", ServerRoot);
+ snprintf(filename, sizeof(filename), "%s/subscriptions.conf", ServerRoot);
- if (rename(temp, backup))
- {
- if (errno != ENOENT)
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to backup subscriptions.conf - %s",
- strerror(errno));
- }
-
- if ((fp = cupsFileOpen(temp, "w")) == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to save subscriptions.conf - %s",
- strerror(errno));
-
- if (rename(backup, temp))
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to restore subscriptions.conf - %s",
- strerror(errno));
+ if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm)) == NULL)
return;
- }
- else
- cupsdLogMessage(CUPSD_LOG_INFO, "Saving subscriptions.conf...");
- /*
- * Restrict access to the file...
- */
-
- fchown(cupsFileNumber(fp), getuid(), Group);
- fchmod(cupsFileNumber(fp), ConfigFilePerm);
+ cupsdLogMessage(CUPSD_LOG_INFO, "Saving subscriptions.conf...");
/*
* Write a small header to the file...
cupsFilePuts(fp, "</Subscription>\n");
}
- cupsFileClose(fp);
+ cupsdCloseCreatedConfFile(fp, filename);
}
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsd_send_notification(sub=%p(%d), event=%p(%s))\n",
+ "cupsd_send_notification(sub=%p(%d), event=%p(%s))",
sub, sub->id, event, cupsdEventName(event->event));
/*
if (!sub->events)
{
- sub->events = calloc(MaxEvents, sizeof(cupsd_event_t *));
+ sub->events = cupsArrayNew3((cups_array_func_t)NULL, NULL,
+ (cups_ahash_func_t)NULL, 0,
+ (cups_acopy_func_t)NULL,
+ (cups_afree_func_t)cupsd_delete_event);
if (!sub->events)
{
* Purge an old event as needed...
*/
- if (sub->num_events >= MaxEvents)
+ if (cupsArrayCount(sub->events) >= MaxEvents)
{
/*
* Purge the oldest event in the cache...
*/
- cupsd_delete_event(sub->events[0]);
+ cupsArrayRemove(sub->events, cupsArrayFirst(sub->events));
- sub->num_events --;
sub->first_event_id ++;
-
- memmove(sub->events, sub->events + 1,
- sub->num_events * sizeof(cupsd_event_t *));
}
/*
* event cache limit, we don't need to check for overflow here...
*/
- sub->events[sub->num_events] = event;
- sub->num_events ++;
+ cupsArrayAdd(sub->events, event);
/*
* Deliver the event...
*/
if (cupsdStartProcess(command, argv, envp, fds[0], -1, NotifierPipes[1],
- -1, -1, 0, &pid) < 0)
+ -1, -1, 0, DefaultProfile, NULL, &pid) < 0)
{
/*
* Error - can't fork!
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 6376 2007-03-21 06:39:10Z mike $".
+ * End of "$Id$".
*/