const char *name; /* Current event name */
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "copy_subscription_attrs(con=%p, sub=%p, ra=%p, exclude=%p)",
- (void *)con, (void *)sub, (void *)ra, (void *)exclude);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "copy_subscription_attrs(con=%p, sub=%p, ra=%p, exclude=%p)", (void *)con, (void *)sub, (void *)ra, (void *)exclude);
+
+ _cupsRWLockRead(&sub->lock);
/*
* Copy the subscription attributes to the response using the
if (!ra || cupsArrayFind(ra, "notify-subscription-id"))
ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
"notify-subscription-id", sub->id);
+
+ _cupsRWUnlock(&sub->lock);
}
goto finish_response;
}
- // TODO: Grab printer icon file...
httpClose(http);
/*
ipp_attribute_t *uri) /* I - Printer/job URI */
{
http_status_t status; /* Policy status */
- int count; /* Number of subscriptions */
+ int i, /* Looping var */
+ scount; /* Total number of subscriptions */
+ int count; /* Number of subscriptions returned */
int limit; /* Limit */
cupsd_subscription_t *sub; /* Subscription */
cups_array_t *ra; /* Requested attributes array */
else
username[0] = '\0';
- for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions), count = 0;
- sub;
- sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ _cupsRWLockRead(&SubscriptionsLock);
+
+ for (i = 0, count = 0, scount = cupsArrayCount(Subscriptions); i < scount; i ++)
+ {
+ sub = (cupsd_subscription_t *)cupsArrayIndex(Subscriptions, i);
+
if ((!printer || sub->dest == printer) && (!job || sub->job == job) &&
(!username[0] || !_cups_strcasecmp(username, sub->owner)))
{
if (limit && count >= limit)
break;
}
+ }
+
+ _cupsRWUnlock(&SubscriptionsLock);
cupsArrayDelete(ra);
* Renew the subscription...
*/
+ _cupsRWLockWrite(&sub->lock);
+
lease = ippFindAttribute(con->request, "notify-lease-duration",
IPP_TAG_INTEGER);
sub->expire = sub->lease ? time(NULL) + sub->lease : 0;
+ _cupsRWUnlock(&sub->lock);
+
cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
- con->response->request.status.status_code = IPP_OK;
+ con->response->request.status.status_code = IPP_STATUS_OK;
ippAddInteger(con->response, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
"notify-lease-duration", sub->lease);
/*
* Subscription routines for the CUPS scheduler.
*
- * Copyright © 2020-2024 by OpenPrinting.
+ * Copyright © 2020-2025 by OpenPrinting.
* Copyright © 2007-2019 by Apple Inc.
* Copyright © 1997-2007 by Easy Software Products, all rights reserved.
*
const char *text, /* I - Notification text */
...) /* I - Additional arguments as needed */
{
+ int i, /* Looping var */
+ scount; /* Number of subscriptions */
va_list ap; /* Pointer to additional arguments */
char ftext[1024]; /* Formatted text buffer */
ipp_attribute_t *attr; /* Printer/job attribute */
- cupsd_event_t *temp; /* New event pointer */
+ cupsd_event_t *temp = NULL; /* New event pointer */
cupsd_subscription_t *sub; /* Current subscription */
if (job && !dest)
dest = cupsdFindPrinter(job->dest);
- for (temp = NULL, sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
- sub;
- sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ _cupsRWLockRead(&SubscriptionsLock);
+
+ for (i = 0, scount = cupsArrayCount(Subscriptions); i < scount; i ++)
{
/*
* Check if this subscription requires this event...
*/
+ sub = (cupsd_subscription_t *)cupsArrayIndex(Subscriptions, i);
+
if ((sub->mask & event) != 0 && (sub->dest == dest || !sub->dest || sub->job == job))
{
/*
cupsdLogMessage(CUPSD_LOG_CRIT,
"Unable to allocate memory for event - %s",
strerror(errno));
+ _cupsRWUnlock(&SubscriptionsLock);
return;
}
}
}
+ _cupsRWUnlock(&SubscriptionsLock);
+
if (temp)
cupsdMarkDirty(CUPSD_DIRTY_SUBSCRIPTIONS);
else
cupsdLogMessage(CUPSD_LOG_DEBUG,
"cupsdAddSubscription(mask=%x, dest=%p(%s), job=%p(%d), "
"uri=\"%s\")",
- mask, dest, dest ? dest->name : "", job, job ? job->id : 0,
+ mask, (void *)dest, dest ? dest->name : "", (void *)job, job ? job->id : 0,
uri ? uri : "(null)");
+ _cupsRWLockWrite(&SubscriptionsLock);
+
if (!Subscriptions)
Subscriptions = cupsArrayNew((cups_array_func_t)cupsd_compare_subscriptions,
NULL);
cupsdLogMessage(CUPSD_LOG_CRIT,
"Unable to allocate memory for subscriptions - %s",
strerror(errno));
+ _cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
"cupsdAddSubscription: Reached MaxSubscriptions %d "
"(count=%d)", MaxSubscriptions,
cupsArrayCount(Subscriptions));
+ _cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
"cupsdAddSubscription: Reached MaxSubscriptionsPerJob %d "
"for job #%d (count=%d)", MaxSubscriptionsPerJob,
job->id, count);
+ _cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
}
"cupsdAddSubscription: Reached "
"MaxSubscriptionsPerPrinter %d for %s (count=%d)",
MaxSubscriptionsPerPrinter, dest->name, count);
+ _cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
}
cupsdLogMessage(CUPSD_LOG_CRIT,
"Unable to allocate memory for subscription object - %s",
strerror(errno));
+ _cupsRWUnlock(&SubscriptionsLock);
return (NULL);
}
+ _cupsRWInit(&temp->lock);
+
/*
* Fill in common data...
*/
cupsArrayAdd(Subscriptions, temp);
+ _cupsRWUnlock(&SubscriptionsLock);
+
/*
* For RSS subscriptions, run the notifier immediately...
*/
if (!Subscriptions)
return;
+ _cupsRWLockWrite(&SubscriptionsLock);
+
for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
sub;
sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
cupsArrayDelete(Subscriptions);
Subscriptions = NULL;
+
+ _cupsRWUnlock(&SubscriptionsLock);
}
* Remove subscription from array...
*/
+ _cupsRWLockWrite(&SubscriptionsLock);
+
cupsArrayRemove(Subscriptions, sub);
+ _cupsRWUnlock(&SubscriptionsLock);
+
/*
* Free memory...
*/
+ _cupsRWDestroy(&sub->lock);
+
cupsdClearString(&(sub->owner));
cupsdClearString(&(sub->recipient));
cupsd_subscription_t * /* O - Subscription object */
cupsdFindSubscription(int id) /* I - Subscription ID */
{
- cupsd_subscription_t sub; /* Subscription template */
+ cupsd_subscription_t key, /* Subscription key */
+ *sub; /* Matching subscription */
+
+ key.id = id;
+
+ _cupsRWLockRead(&SubscriptionsLock);
+ sub = (cupsd_subscription_t *)cupsArrayFind(Subscriptions, &sub);
- sub.id = id;
+ _cupsRWUnlock(&SubscriptionsLock);
- return ((cupsd_subscription_t *)cupsArrayFind(Subscriptions, &sub));
+ return (sub);
}
void
cupsdSaveAllSubscriptions(void)
{
- int i; /* Looping var */
+ int i, j, /* Looping vars */
+ scount; /* Number of subscriptions */
cups_file_t *fp; /* subscriptions.conf file */
char filename[1024]; /* subscriptions.conf filename */
cupsd_subscription_t *sub; /* Current subscription */
* Write every subscription known to the system...
*/
- for (sub = (cupsd_subscription_t *)cupsArrayFirst(Subscriptions);
- sub;
- sub = (cupsd_subscription_t *)cupsArrayNext(Subscriptions))
+ _cupsRWLockRead(&SubscriptionsLock);
+
+ for (i = 0, scount = cupsArrayCount(Subscriptions); i < scount; i ++)
{
+ sub = (cupsd_subscription_t *)cupsArrayIndex(Subscriptions, i);
+
cupsFilePrintf(fp, "<Subscription %d>\n", sub->id);
if ((name = cupsdEventName((cupsd_eventmask_t)sub->mask)) != NULL)
{
cupsFilePuts(fp, "UserData ");
- for (i = 0, hex = 0; i < sub->user_data_len; i ++)
+ for (j = 0, hex = 0; j < sub->user_data_len; j ++)
{
- if (sub->user_data[i] < ' ' ||
- sub->user_data[i] > 0x7f ||
- sub->user_data[i] == '<')
+ if (sub->user_data[j] < ' ' ||
+ sub->user_data[j] > 0x7f ||
+ sub->user_data[j] == '<')
{
if (!hex)
{
- cupsFilePrintf(fp, "<%02X", sub->user_data[i]);
+ cupsFilePrintf(fp, "<%02X", sub->user_data[j]);
hex = 1;
}
else
- cupsFilePrintf(fp, "%02X", sub->user_data[i]);
+ cupsFilePrintf(fp, "%02X", sub->user_data[j]);
}
else
{
if (hex)
{
- cupsFilePrintf(fp, ">%c", sub->user_data[i]);
+ cupsFilePrintf(fp, ">%c", sub->user_data[j]);
hex = 0;
}
else
- cupsFilePutChar(fp, sub->user_data[i]);
+ cupsFilePutChar(fp, sub->user_data[j]);
}
}
cupsFilePuts(fp, "</Subscription>\n");
}
+ _cupsRWUnlock(&SubscriptionsLock);
+
cupsdCloseCreatedConfFile(fp, filename);
}
* Allocate the events array as needed...
*/
+ _cupsRWLockWrite(&sub->lock);
+
if (!sub->events)
{
sub->events = cupsArrayNew3((cups_array_func_t)NULL, NULL,
*/
sub->next_event_id ++;
+
+ _cupsRWUnlock(&sub->lock);
}
/*
* Subscription definitions for the CUPS scheduler.
*
- * Copyright © 2020-2024 by OpenPrinting.
- * Copyright 2007-2010 by Apple Inc.
- * Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ * Copyright © 2020-2025 by OpenPrinting.
+ * Copyright © 2007-2010 by Apple Inc.
+ * Copyright © 1997-2007 by Easy Software Products, all rights reserved.
*
- * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
+ * Licensed under Apache License v2.0. See the file "LICENSE" for more
+ * information.
*/
/*
typedef struct cupsd_subscription_s /**** Subscription structure ****/
{
+ _cups_rwlock_t lock; /* Reader/writer lock */
int id; /* subscription-id */
unsigned mask; /* Event mask */
char *owner; /* notify-subscriber-user-name */
* Globals...
*/
-VAR int MaxSubscriptions VALUE(100),
+VAR int MaxSubscriptions VALUE(100),
/* Overall subscription limit */
- MaxSubscriptionsPerJob VALUE(0),
+ MaxSubscriptionsPerJob VALUE(0),
/* Per-job subscription limit */
MaxSubscriptionsPerPrinter VALUE(0),
/* Per-printer subscription limit */
- MaxSubscriptionsPerUser VALUE(0),
+ MaxSubscriptionsPerUser VALUE(0),
/* Per-user subscription limit */
- NextSubscriptionId VALUE(1),
+ NextSubscriptionId VALUE(1),
/* Next subscription ID */
- DefaultLeaseDuration VALUE(86400),
+ DefaultLeaseDuration VALUE(86400),
/* Default notify-lease-duration */
- MaxLeaseDuration VALUE(0);
+ MaxLeaseDuration VALUE(0);
/* Maximum notify-lease-duration */
-VAR cups_array_t *Subscriptions VALUE(NULL);
+VAR cups_array_t *Subscriptions VALUE(NULL);
/* Active subscriptions */
-
-VAR int MaxEvents VALUE(100); /* Maximum number of events */
-
-VAR unsigned LastEvent VALUE(0); /* Last event(s) processed */
-VAR int NotifierPipes[2] VALUE2(-1, -1);
+VAR _cups_rwlock_t SubscriptionsLock VALUE(_CUPS_RWLOCK_INITIALIZER);
+ /* Reader/writer lock for subscriptions */
+VAR int MaxEvents VALUE(100);
+ /* Maximum number of events */
+
+VAR unsigned LastEvent VALUE(0);
+ /* Last event(s) processed */
+VAR int NotifierPipes[2] VALUE2(-1, -1);
/* Pipes for notifier error/debug output */
VAR cupsd_statbuf_t *NotifierStatusBuffer VALUE(NULL);
/* Status buffer for pipes */